diff options
author | rohan.prinja <rohan.prinja@samsung.com> | 2015-11-03 19:01:23 +0900 |
---|---|---|
committer | rohan.prinja <rohan.prinja@samsung.com> | 2015-11-03 19:01:23 +0900 |
commit | 6e774ea6eb6d719b98f924ab5bd0629d92fb27d0 (patch) | |
tree | fa48b89bb313a2e9514124b556bbcff5ed526a0f /components/script/dom/htmlelement.rs | |
parent | 7032a5d1dee9bb2ba0bee45f1fda984dadfa0609 (diff) | |
parent | 4f51710ed387baa1ad0a6e4cdb0fc5eee44093d5 (diff) | |
download | servo-6e774ea6eb6d719b98f924ab5bd0629d92fb27d0.tar.gz servo-6e774ea6eb6d719b98f924ab5bd0629d92fb27d0.zip |
merge from master
Diffstat (limited to 'components/script/dom/htmlelement.rs')
-rw-r--r-- | components/script/dom/htmlelement.rs | 99 |
1 files changed, 95 insertions, 4 deletions
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index 8836d3aae69..43c319678c9 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -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; @@ -12,21 +13,25 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::inheritance::Castable; use dom::bindings::inheritance::{ElementTypeId, HTMLElementTypeId, NodeTypeId}; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; use dom::bindings::reflector::Reflectable; use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration}; use dom::document::Document; use dom::domstringmap::DOMStringMap; -use dom::element::{AttributeMutation, Element, EventState}; +use dom::element::{AttributeMutation, Element}; use dom::eventtarget::EventTarget; 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::*; +use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::default::Default; use std::intrinsics; @@ -50,10 +55,10 @@ impl PartialEq for HTMLElement { impl HTMLElement { pub fn new_inherited(tag_name: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLElement { - HTMLElement::new_inherited_with_state(EventState::empty(), tag_name, prefix, document) + HTMLElement::new_inherited_with_state(ElementState::empty(), tag_name, prefix, document) } - pub fn new_inherited_with_state(state: EventState, tag_name: DOMString, + pub fn new_inherited_with_state(state: ElementState, tag_name: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLElement { HTMLElement { @@ -275,6 +280,45 @@ fn to_snake_case(name: DOMString) -> DOMString { attr_name } + +// https://html.spec.whatwg.org/multipage/#attr-data-* +// if this attribute is in snake case with a data- prefix, +// this function returns a name converted to camel case +// without the data prefix. + +fn to_camel_case(name: &str) -> Option<DOMString> { + if !name.starts_with("data-") { + return None; + } + let name = &name[5..]; + let has_uppercase = name.chars().any(|curr_char| { + curr_char.is_ascii() && curr_char.is_uppercase() + }); + if has_uppercase { + return None; + } + let mut result = "".to_owned(); + let mut name_chars = name.chars(); + while let Some(curr_char) = name_chars.next() { + //check for hyphen followed by character + if curr_char == '\x2d' { + if let Some(next_char) = name_chars.next() { + if next_char.is_ascii() && next_char.is_lowercase() { + result.push(next_char.to_ascii_uppercase()); + } else { + result.push(curr_char); + result.push(next_char); + } + } else { + result.push(curr_char); + } + } else { + result.push(curr_char); + } + } + Some(result) +} + impl HTMLElement { pub fn set_custom_attr(&self, name: DOMString, value: DOMString) -> ErrorResult { if name.chars() @@ -316,6 +360,53 @@ impl HTMLElement { _ => false, } } + + pub fn supported_prop_names_custom_attr(&self) -> Vec<DOMString> { + let element = self.upcast::<Element>(); + element.attrs().iter().filter_map(|attr| { + 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)) + } } impl VirtualMethods for HTMLElement { |