aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/htmllabelelement.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/htmllabelelement.rs')
-rw-r--r--components/script/dom/htmllabelelement.rs179
1 files changed, 101 insertions, 78 deletions
diff --git a/components/script/dom/htmllabelelement.rs b/components/script/dom/htmllabelelement.rs
index 73a62af5570..970f4a97b7a 100644
--- a/components/script/dom/htmllabelelement.rs
+++ b/components/script/dom/htmllabelelement.rs
@@ -1,48 +1,57 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-use dom::activation::{Activatable, ActivationSource, synthetic_click_activation};
-use dom::attr::Attr;
-use dom::bindings::codegen::Bindings::HTMLLabelElementBinding;
-use dom::bindings::codegen::Bindings::HTMLLabelElementBinding::HTMLLabelElementMethods;
-use dom::bindings::inheritance::Castable;
-use dom::bindings::js::Root;
-use dom::bindings::str::DOMString;
-use dom::document::Document;
-use dom::element::{AttributeMutation, Element};
-use dom::event::Event;
-use dom::eventtarget::EventTarget;
-use dom::htmlelement::HTMLElement;
-use dom::htmlformelement::{FormControl, FormControlElementHelpers, HTMLFormElement};
-use dom::node::{document_from_node, Node};
-use dom::virtualmethods::VirtualMethods;
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use crate::dom::activation::Activatable;
+use crate::dom::attr::Attr;
+use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
+use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
+use crate::dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
+use crate::dom::bindings::codegen::Bindings::HTMLLabelElementBinding::HTMLLabelElementMethods;
+use crate::dom::bindings::codegen::Bindings::NodeBinding::{GetRootNodeOptions, NodeMethods};
+use crate::dom::bindings::inheritance::Castable;
+use crate::dom::bindings::root::DomRoot;
+use crate::dom::bindings::str::DOMString;
+use crate::dom::document::Document;
+use crate::dom::element::{AttributeMutation, Element};
+use crate::dom::event::Event;
+use crate::dom::eventtarget::EventTarget;
+use crate::dom::htmlelement::HTMLElement;
+use crate::dom::htmlformelement::{FormControl, FormControlElementHelpers, HTMLFormElement};
+use crate::dom::node::{Node, ShadowIncluding};
+use crate::dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
-use html5ever_atoms::LocalName;
+use html5ever::{LocalName, Prefix};
use style::attr::AttrValue;
#[dom_struct]
pub struct HTMLLabelElement {
- htmlelement: HTMLElement
+ htmlelement: HTMLElement,
}
impl HTMLLabelElement {
- fn new_inherited(local_name: LocalName,
- prefix: Option<DOMString>,
- document: &Document) -> HTMLLabelElement {
+ fn new_inherited(
+ local_name: LocalName,
+ prefix: Option<Prefix>,
+ document: &Document,
+ ) -> HTMLLabelElement {
HTMLLabelElement {
- htmlelement:
- HTMLElement::new_inherited(local_name, prefix, document),
+ htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
}
}
#[allow(unrooted_must_root)]
- pub fn new(local_name: LocalName,
- prefix: Option<DOMString>,
- document: &Document) -> Root<HTMLLabelElement> {
- Node::reflect_node(box HTMLLabelElement::new_inherited(local_name, prefix, document),
- document,
- HTMLLabelElementBinding::Wrap)
+ pub fn new(
+ local_name: LocalName,
+ prefix: Option<Prefix>,
+ document: &Document,
+ ) -> DomRoot<HTMLLabelElement> {
+ Node::reflect_node(
+ Box::new(HTMLLabelElement::new_inherited(
+ local_name, prefix, document,
+ )),
+ document,
+ )
}
}
@@ -55,40 +64,21 @@ impl Activatable for HTMLLabelElement {
true
}
- // https://html.spec.whatwg.org/multipage/#run-pre-click-activation-steps
- // https://html.spec.whatwg.org/multipage/#the-button-element:activation-behavior
- fn pre_click_activation(&self) {
- }
-
- // https://html.spec.whatwg.org/multipage/#run-canceled-activation-steps
- fn canceled_activation(&self) {
- }
-
- // https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
+ // https://html.spec.whatwg.org/multipage/#the-label-element:activation_behaviour
+ // Basically this is telling us that if activation bubbles up to the label
+ // at all, we are free to do an implementation-dependent thing;
+ // firing a click event is an example, and the precise details of that
+ // click event (e.g. isTrusted) are not specified.
fn activation_behavior(&self, _event: &Event, _target: &EventTarget) {
if let Some(e) = self.GetControl() {
- let elem = e.upcast::<Element>();
- synthetic_click_activation(elem,
- false,
- false,
- false,
- false,
- ActivationSource::NotFromClick);
+ e.Click();
}
}
-
- // 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 {
// https://html.spec.whatwg.org/multipage/#dom-fae-form
- fn GetForm(&self) -> Option<Root<HTMLFormElement>> {
+ fn GetForm(&self) -> Option<DomRoot<HTMLFormElement>> {
self.form_owner()
}
@@ -99,34 +89,64 @@ impl HTMLLabelElementMethods for HTMLLabelElement {
make_atomic_setter!(SetHtmlFor, "for");
// https://html.spec.whatwg.org/multipage/#dom-label-control
- fn GetControl(&self) -> Option<Root<HTMLElement>> {
- if !self.upcast::<Node>().is_in_doc() {
- return None;
- }
-
- let for_attr = match self.upcast::<Element>().get_attribute(&ns!(), &local_name!("for")) {
+ fn GetControl(&self) -> Option<DomRoot<HTMLElement>> {
+ let for_attr = match self
+ .upcast::<Element>()
+ .get_attribute(&ns!(), &local_name!("for"))
+ {
Some(for_attr) => for_attr,
None => return self.first_labelable_descendant(),
};
- let for_value = for_attr.value();
- document_from_node(self).get_element_by_id(for_value.as_atom())
- .and_then(Root::downcast::<HTMLElement>)
- .into_iter()
- .filter(|e| e.is_labelable_element())
- .next()
+ let for_value = for_attr.Value();
+
+ // "If the attribute is specified and there is an element in the tree
+ // whose ID is equal to the value of the for attribute, and the first
+ // such element in tree order is a labelable element, then that
+ // element is the label element's labeled control."
+ // Two subtle points here: we need to search the _tree_, which is
+ // not necessarily the document if we're detached from the document,
+ // and we only consider one element even if a later element with
+ // the same ID is labelable.
+
+ let maybe_found = self
+ .upcast::<Node>()
+ .GetRootNode(&GetRootNodeOptions::empty())
+ .traverse_preorder(ShadowIncluding::No)
+ .find_map(|e| {
+ if let Some(htmle) = e.downcast::<HTMLElement>() {
+ if htmle.upcast::<Element>().Id() == for_value {
+ Some(DomRoot::from_ref(htmle))
+ } else {
+ None
+ }
+ } else {
+ None
+ }
+ });
+ // We now have the element that we would return, but only return it
+ // if it's labelable.
+ if let Some(ref maybe_labelable) = maybe_found {
+ if maybe_labelable.is_labelable_element() {
+ return maybe_found;
+ }
+ }
+ None
}
}
impl VirtualMethods for HTMLLabelElement {
- fn super_type(&self) -> Option<&VirtualMethods> {
- Some(self.upcast::<HTMLElement>() as &VirtualMethods)
+ fn super_type(&self) -> Option<&dyn VirtualMethods> {
+ Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
}
fn parse_plain_attribute(&self, name: &LocalName, value: DOMString) -> AttrValue {
match name {
&local_name!("for") => AttrValue::from_atomic(value.into()),
- _ => self.super_type().unwrap().parse_plain_attribute(name, value),
+ _ => self
+ .super_type()
+ .unwrap()
+ .parse_plain_attribute(name, value),
}
}
@@ -142,20 +162,23 @@ impl VirtualMethods for HTMLLabelElement {
}
impl HTMLLabelElement {
- pub fn first_labelable_descendant(&self) -> Option<Root<HTMLElement>> {
+ pub fn first_labelable_descendant(&self) -> Option<DomRoot<HTMLElement>> {
self.upcast::<Node>()
- .traverse_preorder()
- .filter_map(Root::downcast::<HTMLElement>)
+ .traverse_preorder(ShadowIncluding::No)
+ .filter_map(DomRoot::downcast::<HTMLElement>)
.filter(|elem| elem.is_labelable_element())
.next()
}
}
impl FormControl for HTMLLabelElement {
- fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
- self.GetControl().map(Root::upcast::<Element>).and_then(|elem| {
- elem.as_maybe_form_control().and_then(|control| control.form_owner())
- })
+ fn form_owner(&self) -> Option<DomRoot<HTMLFormElement>> {
+ self.GetControl()
+ .map(DomRoot::upcast::<Element>)
+ .and_then(|elem| {
+ elem.as_maybe_form_control()
+ .and_then(|control| control.form_owner())
+ })
}
fn set_form_owner(&self, _: Option<&HTMLFormElement>) {