diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index 13e891ee5cc..ed20cdeaffb 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -330,6 +330,7 @@ pub trait DocumentMethods { fn Location(&self) -> Temporary; fn Children(&self) -> Temporary; fn QuerySelector(&self, selectors: DOMString) -> Fallible>>; + fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible>; fn GetOnclick(&self) -> Option; fn SetOnclick(&self, listener: Option); fn GetOnload(&self) -> Option; @@ -821,6 +822,12 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { root.query_selector(selectors) } + // http://dom.spec.whatwg.org/#dom-parentnode-queryselectorall + fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible> { + let root: &JSRef = NodeCast::from_ref(self); + root.query_selector_all(selectors) + } + fn GetOnclick(&self) -> Option { let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.get_event_handler_common("click") diff --git a/src/components/script/dom/documentfragment.rs b/src/components/script/dom/documentfragment.rs index bcf9c28e7c1..823b97601a9 100644 --- a/src/components/script/dom/documentfragment.rs +++ b/src/components/script/dom/documentfragment.rs @@ -11,6 +11,7 @@ use dom::element::Element; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlcollection::HTMLCollection; use dom::node::{DocumentFragmentNodeTypeId, Node, NodeHelpers, window_from_node}; +use dom::nodelist::NodeList; use dom::window::{Window, WindowMethods}; use servo_util::str::DOMString; @@ -49,6 +50,7 @@ impl DocumentFragment { pub trait DocumentFragmentMethods { fn Children(&self) -> Temporary; fn QuerySelector(&self, selectors: DOMString) -> Fallible>>; + fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible>; } impl<'a> DocumentFragmentMethods for JSRef<'a, DocumentFragment> { @@ -63,4 +65,11 @@ impl<'a> DocumentFragmentMethods for JSRef<'a, DocumentFragment> { let root: &JSRef = NodeCast::from_ref(self); root.query_selector(selectors) } + + // http://dom.spec.whatwg.org/#dom-parentnode-queryselectorall + fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible> { + let root: &JSRef = NodeCast::from_ref(self); + root.query_selector_all(selectors) + } + } diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 742463b597e..976ed02c739 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -22,6 +22,7 @@ use dom::htmlcollection::HTMLCollection; use dom::htmlserializer::serialize; use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node}; use dom::node::{window_from_node, LayoutNodeHelpers}; +use dom::nodelist::NodeList; use dom::virtualmethods::{VirtualMethods, vtable_for}; use layout_interface::ContentChangedDocumentDamage; use layout_interface::MatchSelectorsDocumentDamage; @@ -430,6 +431,7 @@ pub trait ElementMethods { fn GetOuterHTML(&self) -> Fallible; fn Children(&self) -> Temporary; fn QuerySelector(&self, selectors: DOMString) -> Fallible>>; + fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible>; fn Remove(&self); } @@ -712,6 +714,12 @@ impl<'a> ElementMethods for JSRef<'a, Element> { root.query_selector(selectors) } + // http://dom.spec.whatwg.org/#dom-parentnode-queryselectorall + fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible> { + let root: &JSRef = NodeCast::from_ref(self); + root.query_selector_all(selectors) + } + // http://dom.spec.whatwg.org/#dom-childnode-remove fn Remove(&self) { let node: &JSRef = NodeCast::from_ref(self); diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index a3d2132f601..d83d48b047f 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -399,6 +399,7 @@ pub trait NodeHelpers { fn get_content_boxes(&self) -> Vec>; fn query_selector(&self, selectors: DOMString) -> Fallible>>; + fn query_selector_all(&self, selectors: DOMString) -> Fallible>; fn remove_self(&self); } @@ -569,9 +570,9 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { None => return Err(Syntax), // Step 3. Some(ref selectors) => { + let root = self.ancestors().last().unwrap_or(self.clone()); for selector in selectors.iter() { assert!(selector.pseudo_element.is_none()); - let root = self.ancestors().last().unwrap_or(self.clone()); for node in root.traverse_preorder().filter(|node| node.is_element()) { let mut _shareable: bool = false; if matches_compound_selector(selector.compound_selectors.deref(), &node, &mut _shareable) { @@ -585,6 +586,32 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { Ok(None) } + // http://dom.spec.whatwg.org/#dom-parentnode-queryselectorall + fn query_selector_all(&self, selectors: DOMString) -> Fallible> { + // Step 1. + let mut nodes = vec!(); + let root = self.ancestors().last().unwrap_or(self.clone()); + let namespace = NamespaceMap::new(); + match parse_selector_list(tokenize(selectors.as_slice()).map(|(token, _)| token).collect(), &namespace) { + // Step 2. + None => return Err(Syntax), + // Step 3. + Some(ref selectors) => { + for selector in selectors.iter() { + assert!(selector.pseudo_element.is_none()); + for node in root.traverse_preorder().filter(|node| node.is_element()) { + let mut _shareable: bool = false; + if matches_compound_selector(selector.compound_selectors.deref(), &node, &mut _shareable) { + nodes.push(node.clone()) + } + } + } + } + } + let window = window_from_node(self).root(); + Ok(NodeList::new_simple_list(&window.root_ref(), nodes)) + } + fn ancestors(&self) -> AncestorIterator { AncestorIterator { current: self.parent_node.get().map(|node| (*node.root()).clone()), diff --git a/src/components/script/dom/webidls/ParentNode.webidl b/src/components/script/dom/webidls/ParentNode.webidl index 70ab892fea8..daa4339611f 100644 --- a/src/components/script/dom/webidls/ParentNode.webidl +++ b/src/components/script/dom/webidls/ParentNode.webidl @@ -24,8 +24,11 @@ interface ParentNode { // void append((Node or DOMString)... nodes); //Element? query(DOMString relativeSelectors); - //[NewObject] Elements queryAll(DOMString relativeSelectors); + //[NewObject] + //Elements queryAll(DOMString relativeSelectors); [Throws] Element? querySelector(DOMString selectors); - //[NewObject] NodeList querySelectorAll(DOMString selectors); + //[NewObject] + [Throws] + NodeList querySelectorAll(DOMString selectors); }; diff --git a/src/test/content/test_parentNode_querySelectorAll.html b/src/test/content/test_parentNode_querySelectorAll.html new file mode 100644 index 00000000000..599e017e61f --- /dev/null +++ b/src/test/content/test_parentNode_querySelectorAll.html @@ -0,0 +1,59 @@ + + + + + + + +
+
+
+
+
+ +