diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index cb0143d1645..8f1c918e256 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -4,6 +4,7 @@ //! Element nodes. +use cssparser::tokenize; use dom::attr::{Attr, ReplacedAttr, FirstSetAttr, AttrMethods, AttrHelpersForLayout}; use dom::attr::{AttrValue, StringAttrValue, UIntAttrValue}; use dom::attrlist::AttrList; @@ -13,7 +14,7 @@ use dom::bindings::js::{JS, JSRef, Temporary, TemporaryPushable}; use dom::bindings::js::{OptionalSettable, OptionalRootable, Root}; use dom::bindings::trace::Traceable; use dom::bindings::utils::{Reflectable, Reflector}; -use dom::bindings::error::{ErrorResult, Fallible, NamespaceError, InvalidCharacter}; +use dom::bindings::error::{ErrorResult, Fallible, NamespaceError, InvalidCharacter, Syntax}; use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type}; use dom::clientrect::ClientRect; use dom::clientrectlist::ClientRectList; @@ -28,6 +29,7 @@ use dom::nodelist::NodeList; use dom::virtualmethods::{VirtualMethods, vtable_for}; use layout_interface::ContentChangedDocumentDamage; use layout_interface::MatchSelectorsDocumentDamage; +use style::{matches_compound_selector, NamespaceMap, parse_selector_list}; use style; use servo_util::namespace; use servo_util::namespace::{Namespace, Null}; @@ -452,6 +454,7 @@ pub trait ElementMethods { fn QuerySelector(&self, selectors: DOMString) -> Fallible>>; fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible>; fn Remove(&self); + fn Matches(&self, selectors: DOMString) -> Fallible; } impl<'a> ElementMethods for JSRef<'a, Element> { @@ -760,6 +763,25 @@ impl<'a> ElementMethods for JSRef<'a, Element> { let node: &JSRef = NodeCast::from_ref(self); node.remove_self(); } + + // http://dom.spec.whatwg.org/#dom-element-matches + fn Matches(&self, selectors: DOMString) -> Fallible { + let namespace = NamespaceMap::new(); + match parse_selector_list(tokenize(selectors.as_slice()).map(|(token, _)| token).collect(), + &namespace) { + None => return Err(Syntax), + Some(ref selectors) => { + let root: &JSRef = NodeCast::from_ref(self); + for selector in selectors.iter() { + let mut shareable = false; + if matches_compound_selector(&*selector.compound_selectors, root, &mut shareable) { + return Ok(true); + } + } + } + } + Ok(false) + } } pub fn get_attribute_parts<'a>(name: &'a str) -> (Option<&'a str>, &'a str) { diff --git a/src/components/script/dom/webidls/Element.webidl b/src/components/script/dom/webidls/Element.webidl index e088a2263dd..d7d3ad6da25 100644 --- a/src/components/script/dom/webidls/Element.webidl +++ b/src/components/script/dom/webidls/Element.webidl @@ -46,6 +46,9 @@ interface Element : Node { boolean hasAttribute(DOMString name); boolean hasAttributeNS(DOMString? namespace, DOMString localName); + [Throws] + boolean matches(DOMString selectors); + HTMLCollection getElementsByTagName(DOMString localName); HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); HTMLCollection getElementsByClassName(DOMString classNames); diff --git a/src/test/content/test_element_matches.html b/src/test/content/test_element_matches.html new file mode 100644 index 00000000000..55f89d4a3fc --- /dev/null +++ b/src/test/content/test_element_matches.html @@ -0,0 +1,18 @@ + + + + + + +
+ + + +