Skip to content

Commit

Permalink
Implement 'labels' attribute on 'labelable elements'
Browse files Browse the repository at this point in the history
  • Loading branch information
frewsxcv committed Oct 31, 2015
1 parent 37c03c7 commit 4de1169
Show file tree
Hide file tree
Showing 22 changed files with 183 additions and 63 deletions.
6 changes: 6 additions & 0 deletions components/script/dom/htmlbuttonelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use dom::htmlfieldsetelement::HTMLFieldSetElement;
use dom::htmlformelement::{FormControl, FormSubmitter};
use dom::htmlformelement::{SubmittedFrom, HTMLFormElement};
use dom::node::{Node, document_from_node, window_from_node};
use dom::nodelist::NodeList;
use dom::validitystate::ValidityState;
use dom::virtualmethods::VirtualMethods;
use selectors::states::*;
Expand Down Expand Up @@ -131,6 +132,11 @@ impl HTMLButtonElementMethods for HTMLButtonElement {

// https://html.spec.whatwg.org/multipage/#dom-button-value
make_setter!(SetValue, "value");

// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
fn Labels(&self) -> Root<NodeList> {
self.upcast::<HTMLElement>().labels()
}
}

impl VirtualMethods for HTMLButtonElement {
Expand Down
43 changes: 42 additions & 1 deletion components/script/dom/htmlelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use dom::attr::Attr;
use dom::attr::AttrValue;
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::HTMLElementBinding;
use dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
Expand All @@ -12,7 +13,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId, NodeTypeId};
use dom::bindings::conversions::Castable;
use dom::bindings::error::{Error, ErrorResult};
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference};
use dom::bindings::utils::Reflectable;
use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration};
use dom::document::Document;
Expand All @@ -23,8 +24,10 @@ use dom::htmlbodyelement::HTMLBodyElement;
use dom::htmlframesetelement::HTMLFrameSetElement;
use dom::htmlhtmlelement::HTMLHtmlElement;
use dom::htmlinputelement::HTMLInputElement;
use dom::htmllabelelement::HTMLLabelElement;
use dom::node::{Node, SEQUENTIALLY_FOCUSABLE};
use dom::node::{document_from_node, window_from_node};
use dom::nodelist::NodeList;
use dom::virtualmethods::VirtualMethods;
use msg::constellation_msg::FocusType;
use selectors::states::*;
Expand Down Expand Up @@ -364,6 +367,44 @@ impl HTMLElement {
let raw_name = attr.local_name();
to_camel_case(&raw_name)
}).collect()

// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
pub fn labels(&self) -> Root<NodeList> {
debug_assert!(self.is_labelable_element());

let element = self.upcast::<Element>();
let window = window_from_node(element);

// Traverse ancestors for implicitly associated <label> elements
// https://html.spec.whatwg.org/multipage/#the-label-element:attr-label-for-4
let ancestors =
self.upcast::<Node>()
.ancestors()
.filter_map(Root::downcast::<HTMLElement>)
// If we reach a labelable element, we have a guarantee no ancestors above it
// will be a label for this HTMLElement
.take_while(|elem| !elem.is_labelable_element())
.filter_map(Root::downcast::<HTMLLabelElement>)
.filter(|elem| !elem.upcast::<Element>().has_attribute(&atom!("for")))
.filter(|elem| elem.first_labelable_descendant().r() == Some(self))
.map(Root::upcast::<Node>);

let id = element.Id();
let id = match &id as &str {
"" => return NodeList::new_simple_list(window.r(), ancestors),
id => id,
};

// Traverse entire tree for <label> elements with `for` attribute matching `id`
let root_element = element.get_root_element();
let root_node = root_element.upcast::<Node>();
let children = root_node.traverse_preorder()
.filter_map(Root::downcast::<Element>)
.filter(|elem| elem.is::<HTMLLabelElement>())
.filter(|elem| elem.get_string_attribute(&atom!("for")) == id)
.map(Root::upcast::<Node>);

NodeList::new_simple_list(window.r(), children.chain(ancestors))
}
}

Expand Down
11 changes: 11 additions & 0 deletions components/script/dom/htmlinputelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use dom::htmlformelement::{ResetFrom, SubmittedFrom};
use dom::keyboardevent::KeyboardEvent;
use dom::node::{Node, NodeDamage};
use dom::node::{document_from_node, window_from_node};
use dom::nodelist::NodeList;
use dom::virtualmethods::VirtualMethods;
use msg::constellation_msg::ConstellationChan;
use selectors::states::*;
Expand Down Expand Up @@ -333,6 +334,16 @@ impl HTMLInputElementMethods for HTMLInputElement {
fn SetIndeterminate(&self, val: bool) {
self.upcast::<Element>().set_state(IN_INDETERMINATE_STATE, val)
}

// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
fn Labels(&self) -> Root<NodeList> {
if self.Type() == "hidden" {
let window = window_from_node(self.upcast::<Node>());
NodeList::empty(&window)
} else {
self.upcast::<HTMLElement>().labels()
}
}
}


Expand Down
2 changes: 1 addition & 1 deletion components/script/dom/htmllabelelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl VirtualMethods for HTMLLabelElement {
}

impl HTMLLabelElement {
fn first_labelable_descendant(&self) -> Option<Root<HTMLElement>> {
pub fn first_labelable_descendant(&self) -> Option<Root<HTMLElement>> {
self.upcast::<Node>()
.traverse_preorder()
.filter_map(Root::downcast::<HTMLElement>)
Expand Down
11 changes: 10 additions & 1 deletion components/script/dom/htmlmeterelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
* 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::bindings::codegen::Bindings::HTMLMeterElementBinding;
use dom::bindings::codegen::Bindings::HTMLMeterElementBinding::{self, HTMLMeterElementMethods};
use dom::bindings::conversions::Castable;
use dom::bindings::js::Root;
use dom::document::Document;
use dom::htmlelement::HTMLElement;
use dom::node::Node;
use dom::nodelist::NodeList;
use util::str::DOMString;

#[dom_struct]
Expand All @@ -31,3 +33,10 @@ impl HTMLMeterElement {
Node::reflect_node(box element, document, HTMLMeterElementBinding::Wrap)
}
}

impl HTMLMeterElementMethods for HTMLMeterElement {
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
fn Labels(&self) -> Root<NodeList> {
self.upcast::<HTMLElement>().labels()
}
}
7 changes: 7 additions & 0 deletions components/script/dom/htmloutputelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

use dom::bindings::codegen::Bindings::HTMLOutputElementBinding;
use dom::bindings::codegen::Bindings::HTMLOutputElementBinding::HTMLOutputElementMethods;
use dom::bindings::conversions::Castable;
use dom::bindings::js::Root;
use dom::document::Document;
use dom::htmlelement::HTMLElement;
use dom::htmlformelement::{FormControl, HTMLFormElement};
use dom::node::{Node, window_from_node};
use dom::nodelist::NodeList;
use dom::validitystate::ValidityState;
use util::str::DOMString;

Expand Down Expand Up @@ -47,6 +49,11 @@ impl HTMLOutputElementMethods for HTMLOutputElement {
fn GetForm(&self) -> Option<Root<HTMLFormElement>> {
self.form_owner()
}

// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
fn Labels(&self) -> Root<NodeList> {
self.upcast::<HTMLElement>().labels()
}
}

impl FormControl for HTMLOutputElement {}
11 changes: 10 additions & 1 deletion components/script/dom/htmlprogresselement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
* 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::bindings::codegen::Bindings::HTMLProgressElementBinding;
use dom::bindings::codegen::Bindings::HTMLProgressElementBinding::{self, HTMLProgressElementMethods};
use dom::bindings::conversions::Castable;
use dom::bindings::js::Root;
use dom::document::Document;
use dom::htmlelement::HTMLElement;
use dom::node::Node;
use dom::nodelist::NodeList;
use util::str::DOMString;

#[dom_struct]
Expand All @@ -32,3 +34,10 @@ impl HTMLProgressElement {
Node::reflect_node(box element, document, HTMLProgressElementBinding::Wrap)
}
}

impl HTMLProgressElementMethods for HTMLProgressElement {
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
fn Labels(&self) -> Root<NodeList> {
self.upcast::<HTMLElement>().labels()
}
}
6 changes: 6 additions & 0 deletions components/script/dom/htmlselectelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use dom::htmlfieldsetelement::HTMLFieldSetElement;
use dom::htmlformelement::{FormControl, HTMLFormElement};
use dom::htmloptionelement::HTMLOptionElement;
use dom::node::{Node, window_from_node};
use dom::nodelist::NodeList;
use dom::validitystate::ValidityState;
use dom::virtualmethods::VirtualMethods;
use selectors::states::*;
Expand Down Expand Up @@ -158,6 +159,11 @@ impl HTMLSelectElementMethods for HTMLSelectElement {
"select-one".to_owned()
}
}

// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
fn Labels(&self) -> Root<NodeList> {
self.upcast::<HTMLElement>().labels()
}
}

impl VirtualMethods for HTMLSelectElement {
Expand Down
6 changes: 6 additions & 0 deletions components/script/dom/htmltextareaelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use dom::htmlformelement::{FormControl, HTMLFormElement};
use dom::keyboardevent::KeyboardEvent;
use dom::node::{ChildrenMutation, Node, NodeDamage};
use dom::node::{document_from_node, window_from_node};
use dom::nodelist::NodeList;
use dom::virtualmethods::VirtualMethods;
use msg::constellation_msg::ConstellationChan;
use script_task::ScriptTaskEventCategory::InputEvent;
Expand Down Expand Up @@ -205,6 +206,11 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {

self.force_relayout();
}

// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
fn Labels(&self) -> Root<NodeList> {
self.upcast::<HTMLElement>().labels()
}
}


Expand Down
4 changes: 4 additions & 0 deletions components/script/dom/nodelist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ impl NodeList {
pub fn new_child_list(window: &Window, node: &Node) -> Root<NodeList> {
NodeList::new(window, NodeListType::Children(ChildrenList::new(node)))
}

pub fn empty(window: &Window) -> Root<NodeList> {
NodeList::new(window, NodeListType::Simple(vec![]))
}
}

impl NodeListMethods for NodeList {
Expand Down
2 changes: 1 addition & 1 deletion components/script/dom/webidls/HTMLButtonElement.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ interface HTMLButtonElement : HTMLElement {
//boolean reportValidity();
//void setCustomValidity(DOMString error);

//readonly attribute NodeList labels;
readonly attribute NodeList labels;
};
2 changes: 1 addition & 1 deletion components/script/dom/webidls/HTMLInputElement.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ interface HTMLInputElement : HTMLElement {
//boolean reportValidity();
//void setCustomValidity(DOMString error);

//readonly attribute NodeList labels;
readonly attribute NodeList labels;

//void select();
// attribute unsigned long selectionStart;
Expand Down
2 changes: 1 addition & 1 deletion components/script/dom/webidls/HTMLMeterElement.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ interface HTMLMeterElement : HTMLElement {
// attribute double low;
// attribute double high;
// attribute double optimum;
//readonly attribute NodeList labels;
readonly attribute NodeList labels;
};
2 changes: 1 addition & 1 deletion components/script/dom/webidls/HTMLOutputElement.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ interface HTMLOutputElement : HTMLElement {
//boolean reportValidity();
//void setCustomValidity(DOMString error);

//readonly attribute NodeList labels;
readonly attribute NodeList labels;
};
2 changes: 1 addition & 1 deletion components/script/dom/webidls/HTMLProgressElement.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ interface HTMLProgressElement : HTMLElement {
// attribute double value;
// attribute double max;
//readonly attribute double position;
//readonly attribute NodeList labels;
readonly attribute NodeList labels;
};
2 changes: 1 addition & 1 deletion components/script/dom/webidls/HTMLSelectElement.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ interface HTMLSelectElement : HTMLElement {
//boolean reportValidity();
//void setCustomValidity(DOMString error);

//readonly attribute NodeList labels;
readonly attribute NodeList labels;
};
2 changes: 1 addition & 1 deletion components/script/dom/webidls/HTMLTextAreaElement.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ interface HTMLTextAreaElement : HTMLElement {
//boolean reportValidity();
//void setCustomValidity(DOMString error);

//readonly attribute NodeList labels;
readonly attribute NodeList labels;

//void select();
// attribute unsigned long selectionStart;
Expand Down

0 comments on commit 4de1169

Please sign in to comment.