mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
parent
8ecbed9e42
commit
7ce40080bf
7 changed files with 85 additions and 159 deletions
|
@ -30,9 +30,6 @@ pub trait Activatable {
|
||||||
// https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
|
// https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
|
||||||
fn activation_behavior(&self, event: &Event, target: &EventTarget);
|
fn activation_behavior(&self, event: &Event, target: &EventTarget);
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#implicit-submission
|
|
||||||
fn implicit_submission(&self, ctrl_key: bool, shift_key: bool, alt_key: bool, meta_key: bool);
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#concept-selector-active
|
// https://html.spec.whatwg.org/multipage/#concept-selector-active
|
||||||
fn enter_formal_activation_state(&self) {
|
fn enter_formal_activation_state(&self) {
|
||||||
self.as_element().set_active_state(true);
|
self.as_element().set_active_state(true);
|
||||||
|
|
|
@ -121,7 +121,7 @@ use html5ever::{LocalName, Namespace, QualName};
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use js::jsapi::{JSObject, JSRuntime};
|
use js::jsapi::{JSObject, JSRuntime};
|
||||||
use keyboard_types::{Key, KeyState, Modifiers};
|
use keyboard_types::{Code, Key, KeyState};
|
||||||
use metrics::{
|
use metrics::{
|
||||||
InteractiveFlag, InteractiveMetrics, InteractiveWindow, ProfilerMetadataFactory,
|
InteractiveFlag, InteractiveMetrics, InteractiveWindow, ProfilerMetadataFactory,
|
||||||
ProgressiveWebMetric,
|
ProgressiveWebMetric,
|
||||||
|
@ -1469,9 +1469,8 @@ impl Document {
|
||||||
// however *when* we do it is up to us.
|
// however *when* we do it is up to us.
|
||||||
// Here, we're dispatching it after the key event so the script has a chance to cancel it
|
// Here, we're dispatching it after the key event so the script has a chance to cancel it
|
||||||
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=27337
|
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=27337
|
||||||
match keyboard_event.key {
|
if (keyboard_event.key == Key::Enter && keyboard_event.state == KeyState::Up) ||
|
||||||
Key::Character(ref letter)
|
(keyboard_event.code == Code::Space && keyboard_event.state == KeyState::Down)
|
||||||
if letter == " " && keyboard_event.state == KeyState::Up =>
|
|
||||||
{
|
{
|
||||||
let maybe_elem = target.downcast::<Element>();
|
let maybe_elem = target.downcast::<Element>();
|
||||||
if let Some(el) = maybe_elem {
|
if let Some(el) = maybe_elem {
|
||||||
|
@ -1485,20 +1484,6 @@ impl Document {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Key::Enter if keyboard_event.state == KeyState::Up => {
|
|
||||||
let maybe_elem = target.downcast::<Element>();
|
|
||||||
if let Some(el) = maybe_elem {
|
|
||||||
if let Some(a) = el.as_maybe_activatable() {
|
|
||||||
let ctrl = keyboard_event.modifiers.contains(Modifiers::CONTROL);
|
|
||||||
let alt = keyboard_event.modifiers.contains(Modifiers::ALT);
|
|
||||||
let shift = keyboard_event.modifiers.contains(Modifiers::SHIFT);
|
|
||||||
let meta = keyboard_event.modifiers.contains(Modifiers::META);
|
|
||||||
a.implicit_submission(ctrl, alt, shift, meta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.window.reflow(ReflowGoal::Full, ReflowReason::KeyEvent);
|
self.window.reflow(ReflowGoal::Full, ReflowReason::KeyEvent);
|
||||||
|
|
|
@ -578,16 +578,6 @@ impl Activatable for HTMLAnchorElement {
|
||||||
//TODO: Download the link is `download` attribute is set.
|
//TODO: Download the link is `download` attribute is set.
|
||||||
follow_hyperlink(element, ismap_suffix);
|
follow_hyperlink(element, ismap_suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO:https://html.spec.whatwg.org/multipage/#the-a-element
|
|
||||||
fn implicit_submission(
|
|
||||||
&self,
|
|
||||||
_ctrl_key: bool,
|
|
||||||
_shift_key: bool,
|
|
||||||
_alt_key: bool,
|
|
||||||
_meta_key: bool,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#following-hyperlinks-2>
|
/// <https://html.spec.whatwg.org/multipage/#following-hyperlinks-2>
|
||||||
|
|
|
@ -326,15 +326,6 @@ impl Activatable for HTMLAreaElement {
|
||||||
|
|
||||||
fn canceled_activation(&self) {}
|
fn canceled_activation(&self) {}
|
||||||
|
|
||||||
fn implicit_submission(
|
|
||||||
&self,
|
|
||||||
_ctrl_key: bool,
|
|
||||||
_shift_key: bool,
|
|
||||||
_alt_key: bool,
|
|
||||||
_meta_key: bool,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn activation_behavior(&self, _event: &Event, _target: &EventTarget) {
|
fn activation_behavior(&self, _event: &Event, _target: &EventTarget) {
|
||||||
follow_hyperlink(self.as_element(), None);
|
follow_hyperlink(self.as_element(), None);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use crate::dom::activation::{synthetic_click_activation, Activatable, ActivationSource};
|
use crate::dom::activation::Activatable;
|
||||||
use crate::dom::attr::Attr;
|
use crate::dom::attr::Attr;
|
||||||
use crate::dom::bindings::codegen::Bindings::HTMLButtonElementBinding;
|
use crate::dom::bindings::codegen::Bindings::HTMLButtonElementBinding;
|
||||||
use crate::dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
|
use crate::dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
|
||||||
|
@ -18,7 +18,7 @@ use crate::dom::htmlfieldsetelement::HTMLFieldSetElement;
|
||||||
use crate::dom::htmlformelement::HTMLFormElement;
|
use crate::dom::htmlformelement::HTMLFormElement;
|
||||||
use crate::dom::htmlformelement::{FormControl, FormDatum, FormDatumValue};
|
use crate::dom::htmlformelement::{FormControl, FormDatum, FormDatumValue};
|
||||||
use crate::dom::htmlformelement::{FormSubmitter, ResetFrom, SubmittedFrom};
|
use crate::dom::htmlformelement::{FormSubmitter, ResetFrom, SubmittedFrom};
|
||||||
use crate::dom::node::{document_from_node, window_from_node, BindContext, Node, UnbindContext};
|
use crate::dom::node::{window_from_node, BindContext, Node, UnbindContext};
|
||||||
use crate::dom::nodelist::NodeList;
|
use crate::dom::nodelist::NodeList;
|
||||||
use crate::dom::validation::Validatable;
|
use crate::dom::validation::Validatable;
|
||||||
use crate::dom::validitystate::{ValidationFlags, ValidityState};
|
use crate::dom::validitystate::{ValidationFlags, ValidityState};
|
||||||
|
@ -322,29 +322,4 @@ impl Activatable for HTMLButtonElement {
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#implicit-submission
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
fn implicit_submission(&self, ctrl_key: bool, shift_key: bool, alt_key: bool, meta_key: bool) {
|
|
||||||
let doc = document_from_node(self);
|
|
||||||
let node = doc.upcast::<Node>();
|
|
||||||
let owner = self.form_owner();
|
|
||||||
if owner.is_none() || self.upcast::<Element>().click_in_progress() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
node.query_selector_iter(DOMString::from("button[type=submit]"))
|
|
||||||
.unwrap()
|
|
||||||
.filter_map(DomRoot::downcast::<HTMLButtonElement>)
|
|
||||||
.find(|r| r.form_owner() == owner)
|
|
||||||
.map(|s| {
|
|
||||||
synthetic_click_activation(
|
|
||||||
s.as_element(),
|
|
||||||
ctrl_key,
|
|
||||||
shift_key,
|
|
||||||
alt_key,
|
|
||||||
meta_key,
|
|
||||||
ActivationSource::NotFromClick,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1221,6 +1221,75 @@ impl HTMLInputElement {
|
||||||
fn selection(&self) -> TextControlSelection<Self> {
|
fn selection(&self) -> TextControlSelection<Self> {
|
||||||
TextControlSelection::new(&self, &self.textinput)
|
TextControlSelection::new(&self, &self.textinput)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#implicit-submission
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
fn implicit_submission(&self, ctrl_key: bool, shift_key: bool, alt_key: bool, meta_key: bool) {
|
||||||
|
let doc = document_from_node(self);
|
||||||
|
let node = doc.upcast::<Node>();
|
||||||
|
let owner = self.form_owner();
|
||||||
|
let form = match owner {
|
||||||
|
None => return,
|
||||||
|
Some(ref f) => f,
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.upcast::<Element>().click_in_progress() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let submit_button;
|
||||||
|
submit_button = node
|
||||||
|
.query_selector_iter(DOMString::from("input[type=submit]"))
|
||||||
|
.unwrap()
|
||||||
|
.filter_map(DomRoot::downcast::<HTMLInputElement>)
|
||||||
|
.find(|r| r.form_owner() == owner);
|
||||||
|
match submit_button {
|
||||||
|
Some(ref button) => {
|
||||||
|
if button.is_instance_activatable() {
|
||||||
|
synthetic_click_activation(
|
||||||
|
button.as_element(),
|
||||||
|
ctrl_key,
|
||||||
|
shift_key,
|
||||||
|
alt_key,
|
||||||
|
meta_key,
|
||||||
|
ActivationSource::NotFromClick,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let inputs = node
|
||||||
|
.query_selector_iter(DOMString::from("input"))
|
||||||
|
.unwrap()
|
||||||
|
.filter_map(DomRoot::downcast::<HTMLInputElement>)
|
||||||
|
.filter(|input| {
|
||||||
|
input.form_owner() == owner &&
|
||||||
|
match input.input_type() {
|
||||||
|
InputType::Text |
|
||||||
|
InputType::Search |
|
||||||
|
InputType::Url |
|
||||||
|
InputType::Tel |
|
||||||
|
InputType::Email |
|
||||||
|
InputType::Password |
|
||||||
|
InputType::Date |
|
||||||
|
InputType::Month |
|
||||||
|
InputType::Week |
|
||||||
|
InputType::Time |
|
||||||
|
InputType::DatetimeLocal |
|
||||||
|
InputType::Number => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if inputs.skip(1).next().is_some() {
|
||||||
|
// lazily test for > 1 submission-blocking inputs
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
form.submit(
|
||||||
|
SubmittedFrom::NotFromForm,
|
||||||
|
FormSubmitter::FormElement(&form),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualMethods for HTMLInputElement {
|
impl VirtualMethods for HTMLInputElement {
|
||||||
|
@ -1746,75 +1815,6 @@ impl Activatable for HTMLInputElement {
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#implicit-submission
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
fn implicit_submission(&self, ctrl_key: bool, shift_key: bool, alt_key: bool, meta_key: bool) {
|
|
||||||
let doc = document_from_node(self);
|
|
||||||
let node = doc.upcast::<Node>();
|
|
||||||
let owner = self.form_owner();
|
|
||||||
let form = match owner {
|
|
||||||
None => return,
|
|
||||||
Some(ref f) => f,
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.upcast::<Element>().click_in_progress() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let submit_button;
|
|
||||||
submit_button = node
|
|
||||||
.query_selector_iter(DOMString::from("input[type=submit]"))
|
|
||||||
.unwrap()
|
|
||||||
.filter_map(DomRoot::downcast::<HTMLInputElement>)
|
|
||||||
.find(|r| r.form_owner() == owner);
|
|
||||||
match submit_button {
|
|
||||||
Some(ref button) => {
|
|
||||||
if button.is_instance_activatable() {
|
|
||||||
synthetic_click_activation(
|
|
||||||
button.as_element(),
|
|
||||||
ctrl_key,
|
|
||||||
shift_key,
|
|
||||||
alt_key,
|
|
||||||
meta_key,
|
|
||||||
ActivationSource::NotFromClick,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
let inputs = node
|
|
||||||
.query_selector_iter(DOMString::from("input"))
|
|
||||||
.unwrap()
|
|
||||||
.filter_map(DomRoot::downcast::<HTMLInputElement>)
|
|
||||||
.filter(|input| {
|
|
||||||
input.form_owner() == owner &&
|
|
||||||
match input.input_type() {
|
|
||||||
InputType::Text |
|
|
||||||
InputType::Search |
|
|
||||||
InputType::Url |
|
|
||||||
InputType::Tel |
|
|
||||||
InputType::Email |
|
|
||||||
InputType::Password |
|
|
||||||
InputType::Date |
|
|
||||||
InputType::Month |
|
|
||||||
InputType::Week |
|
|
||||||
InputType::Time |
|
|
||||||
InputType::DatetimeLocal |
|
|
||||||
InputType::Number => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if inputs.skip(1).next().is_some() {
|
|
||||||
// lazily test for > 1 submission-blocking inputs
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
form.submit(
|
|
||||||
SubmittedFrom::NotFromForm,
|
|
||||||
FormSubmitter::FormElement(&form),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#attr-input-accept
|
// https://html.spec.whatwg.org/multipage/#attr-input-accept
|
||||||
|
|
|
@ -83,18 +83,6 @@ impl Activatable for HTMLLabelElement {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#implicit-submission
|
|
||||||
fn implicit_submission(
|
|
||||||
&self,
|
|
||||||
_ctrl_key: bool,
|
|
||||||
_shift_key: bool,
|
|
||||||
_alt_key: bool,
|
|
||||||
_meta_key: bool,
|
|
||||||
) {
|
|
||||||
//FIXME: Investigate and implement implicit submission for label elements
|
|
||||||
// Issue filed at https://github.com/servo/servo/issues/8263
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HTMLLabelElementMethods for HTMLLabelElement {
|
impl HTMLLabelElementMethods for HTMLLabelElement {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue