mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
auto merge of #2632 : brunoabinader/servo/document-queryselectorall, r=Ms2ger
Spec: http://dom.spec.whatwg.org/#dom-parentnode-queryselectorall Closes #851.
This commit is contained in:
commit
baa97fe6e5
6 changed files with 116 additions and 3 deletions
|
@ -330,6 +330,7 @@ pub trait DocumentMethods {
|
||||||
fn Location(&self) -> Temporary<Location>;
|
fn Location(&self) -> Temporary<Location>;
|
||||||
fn Children(&self) -> Temporary<HTMLCollection>;
|
fn Children(&self) -> Temporary<HTMLCollection>;
|
||||||
fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>;
|
fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>;
|
||||||
|
fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible<Temporary<NodeList>>;
|
||||||
fn GetOnclick(&self) -> Option<EventHandlerNonNull>;
|
fn GetOnclick(&self) -> Option<EventHandlerNonNull>;
|
||||||
fn SetOnclick(&self, listener: Option<EventHandlerNonNull>);
|
fn SetOnclick(&self, listener: Option<EventHandlerNonNull>);
|
||||||
fn GetOnload(&self) -> Option<EventHandlerNonNull>;
|
fn GetOnload(&self) -> Option<EventHandlerNonNull>;
|
||||||
|
@ -821,6 +822,12 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
root.query_selector(selectors)
|
root.query_selector(selectors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
|
||||||
|
fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible<Temporary<NodeList>> {
|
||||||
|
let root: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
|
root.query_selector_all(selectors)
|
||||||
|
}
|
||||||
|
|
||||||
fn GetOnclick(&self) -> Option<EventHandlerNonNull> {
|
fn GetOnclick(&self) -> Option<EventHandlerNonNull> {
|
||||||
let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
|
let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
|
||||||
eventtarget.get_event_handler_common("click")
|
eventtarget.get_event_handler_common("click")
|
||||||
|
|
|
@ -11,6 +11,7 @@ use dom::element::Element;
|
||||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||||
use dom::htmlcollection::HTMLCollection;
|
use dom::htmlcollection::HTMLCollection;
|
||||||
use dom::node::{DocumentFragmentNodeTypeId, Node, NodeHelpers, window_from_node};
|
use dom::node::{DocumentFragmentNodeTypeId, Node, NodeHelpers, window_from_node};
|
||||||
|
use dom::nodelist::NodeList;
|
||||||
use dom::window::{Window, WindowMethods};
|
use dom::window::{Window, WindowMethods};
|
||||||
use servo_util::str::DOMString;
|
use servo_util::str::DOMString;
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ impl DocumentFragment {
|
||||||
pub trait DocumentFragmentMethods {
|
pub trait DocumentFragmentMethods {
|
||||||
fn Children(&self) -> Temporary<HTMLCollection>;
|
fn Children(&self) -> Temporary<HTMLCollection>;
|
||||||
fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>;
|
fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>;
|
||||||
|
fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible<Temporary<NodeList>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DocumentFragmentMethods for JSRef<'a, DocumentFragment> {
|
impl<'a> DocumentFragmentMethods for JSRef<'a, DocumentFragment> {
|
||||||
|
@ -63,4 +65,11 @@ impl<'a> DocumentFragmentMethods for JSRef<'a, DocumentFragment> {
|
||||||
let root: &JSRef<Node> = NodeCast::from_ref(self);
|
let root: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
root.query_selector(selectors)
|
root.query_selector(selectors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
|
||||||
|
fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible<Temporary<NodeList>> {
|
||||||
|
let root: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
|
root.query_selector_all(selectors)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ use dom::htmlcollection::HTMLCollection;
|
||||||
use dom::htmlserializer::serialize;
|
use dom::htmlserializer::serialize;
|
||||||
use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node};
|
use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node};
|
||||||
use dom::node::{window_from_node, LayoutNodeHelpers};
|
use dom::node::{window_from_node, LayoutNodeHelpers};
|
||||||
|
use dom::nodelist::NodeList;
|
||||||
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
||||||
use layout_interface::ContentChangedDocumentDamage;
|
use layout_interface::ContentChangedDocumentDamage;
|
||||||
use layout_interface::MatchSelectorsDocumentDamage;
|
use layout_interface::MatchSelectorsDocumentDamage;
|
||||||
|
@ -430,6 +431,7 @@ pub trait ElementMethods {
|
||||||
fn GetOuterHTML(&self) -> Fallible<DOMString>;
|
fn GetOuterHTML(&self) -> Fallible<DOMString>;
|
||||||
fn Children(&self) -> Temporary<HTMLCollection>;
|
fn Children(&self) -> Temporary<HTMLCollection>;
|
||||||
fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>;
|
fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>;
|
||||||
|
fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible<Temporary<NodeList>>;
|
||||||
fn Remove(&self);
|
fn Remove(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,6 +714,12 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
root.query_selector(selectors)
|
root.query_selector(selectors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
|
||||||
|
fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible<Temporary<NodeList>> {
|
||||||
|
let root: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
|
root.query_selector_all(selectors)
|
||||||
|
}
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#dom-childnode-remove
|
// http://dom.spec.whatwg.org/#dom-childnode-remove
|
||||||
fn Remove(&self) {
|
fn Remove(&self) {
|
||||||
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
let node: &JSRef<Node> = NodeCast::from_ref(self);
|
||||||
|
|
|
@ -399,6 +399,7 @@ pub trait NodeHelpers {
|
||||||
fn get_content_boxes(&self) -> Vec<Rect<Au>>;
|
fn get_content_boxes(&self) -> Vec<Rect<Au>>;
|
||||||
|
|
||||||
fn query_selector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>;
|
fn query_selector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>;
|
||||||
|
fn query_selector_all(&self, selectors: DOMString) -> Fallible<Temporary<NodeList>>;
|
||||||
|
|
||||||
fn remove_self(&self);
|
fn remove_self(&self);
|
||||||
}
|
}
|
||||||
|
@ -569,9 +570,9 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
|
||||||
None => return Err(Syntax),
|
None => return Err(Syntax),
|
||||||
// Step 3.
|
// Step 3.
|
||||||
Some(ref selectors) => {
|
Some(ref selectors) => {
|
||||||
|
let root = self.ancestors().last().unwrap_or(self.clone());
|
||||||
for selector in selectors.iter() {
|
for selector in selectors.iter() {
|
||||||
assert!(selector.pseudo_element.is_none());
|
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()) {
|
for node in root.traverse_preorder().filter(|node| node.is_element()) {
|
||||||
let mut _shareable: bool = false;
|
let mut _shareable: bool = false;
|
||||||
if matches_compound_selector(selector.compound_selectors.deref(), &node, &mut _shareable) {
|
if matches_compound_selector(selector.compound_selectors.deref(), &node, &mut _shareable) {
|
||||||
|
@ -585,6 +586,32 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
|
||||||
|
fn query_selector_all(&self, selectors: DOMString) -> Fallible<Temporary<NodeList>> {
|
||||||
|
// 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 {
|
fn ancestors(&self) -> AncestorIterator {
|
||||||
AncestorIterator {
|
AncestorIterator {
|
||||||
current: self.parent_node.get().map(|node| (*node.root()).clone()),
|
current: self.parent_node.get().map(|node| (*node.root()).clone()),
|
||||||
|
|
|
@ -24,8 +24,11 @@ interface ParentNode {
|
||||||
// void append((Node or DOMString)... nodes);
|
// void append((Node or DOMString)... nodes);
|
||||||
|
|
||||||
//Element? query(DOMString relativeSelectors);
|
//Element? query(DOMString relativeSelectors);
|
||||||
//[NewObject] Elements queryAll(DOMString relativeSelectors);
|
//[NewObject]
|
||||||
|
//Elements queryAll(DOMString relativeSelectors);
|
||||||
[Throws]
|
[Throws]
|
||||||
Element? querySelector(DOMString selectors);
|
Element? querySelector(DOMString selectors);
|
||||||
//[NewObject] NodeList querySelectorAll(DOMString selectors);
|
//[NewObject]
|
||||||
|
[Throws]
|
||||||
|
NodeList querySelectorAll(DOMString selectors);
|
||||||
};
|
};
|
||||||
|
|
59
src/test/content/test_parentNode_querySelectorAll.html
Normal file
59
src/test/content/test_parentNode_querySelectorAll.html
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="harness.js"></script>
|
||||||
|
<script>
|
||||||
|
let foo = document.getElementById("foo");
|
||||||
|
let bar = document.getElementById("bar");
|
||||||
|
let baz = document.getElementById("baz");
|
||||||
|
|
||||||
|
{ // document.querySelector
|
||||||
|
let nodelist = document.querySelectorAll(".test");
|
||||||
|
is_a(nodelist, NodeList);
|
||||||
|
is(nodelist.length, 3);
|
||||||
|
is(nodelist.item(0), foo);
|
||||||
|
is(nodelist.item(1), bar);
|
||||||
|
is(nodelist.item(2), baz);
|
||||||
|
|
||||||
|
nodelist = document.querySelectorAll("div > .test");
|
||||||
|
is(nodelist.length, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // element.querySelector
|
||||||
|
let div = document.getElementById("parent");
|
||||||
|
let nodelist = div.querySelectorAll(".test");
|
||||||
|
is(nodelist.length, 3);
|
||||||
|
|
||||||
|
nodelist = div.querySelectorAll("div:nth-of-type(1)");
|
||||||
|
is(nodelist.item(0), div);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // docfrag.querySelector
|
||||||
|
let docfrag = document.createDocumentFragment();
|
||||||
|
|
||||||
|
let div = document.createElement("div");
|
||||||
|
div.id = "foo";
|
||||||
|
div.className = "myClass";
|
||||||
|
|
||||||
|
let child = document.createElement("div");
|
||||||
|
div.appendChild(child);
|
||||||
|
docfrag.appendChild(div);
|
||||||
|
|
||||||
|
let nodelist = docfrag.querySelectorAll("#foo");
|
||||||
|
is(nodelist.item(0), div);
|
||||||
|
|
||||||
|
nodelist = docfrag.querySelectorAll("#foo:nth-child(1)");
|
||||||
|
is(nodelist.item(0), div);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish();
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="parent">
|
||||||
|
<div id="foo" class="test"></div>
|
||||||
|
<div id="bar" class="test"></div>
|
||||||
|
<div id="baz" class="test"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue