diff --git a/src/components/script/dom/htmlcollection.rs b/src/components/script/dom/htmlcollection.rs
index 77d36e07005..71f4f90a568 100644
--- a/src/components/script/dom/htmlcollection.rs
+++ b/src/components/script/dom/htmlcollection.rs
@@ -12,24 +12,40 @@ use dom::window::Window;
use servo_util::namespace::Namespace;
use servo_util::str::DOMString;
+use serialize::{Encoder, Encodable};
+
+pub trait CollectionFilter {
+ fn filter(&self, elem: &JS, root: &JS) -> bool;
+}
+
+impl Encodable for ~CollectionFilter {
+ fn encode(&self, _s: &mut S) {}
+}
+
+#[deriving(Encodable)]
+pub enum CollectionTypeId {
+ Static(~[JS]),
+ Live(JS, ~CollectionFilter)
+}
+
#[deriving(Encodable)]
pub struct HTMLCollection {
- elements: ~[JS],
+ collection: CollectionTypeId,
reflector_: Reflector,
window: JS,
}
impl HTMLCollection {
- pub fn new_inherited(window: JS, elements: ~[JS]) -> HTMLCollection {
+ pub fn new_inherited(window: JS, collection: CollectionTypeId) -> HTMLCollection {
HTMLCollection {
- elements: elements,
+ collection: collection,
reflector_: Reflector::new(),
window: window,
}
}
- pub fn new(window: &JS, elements: ~[JS]) -> JS {
- reflect_dom_object(~HTMLCollection::new_inherited(window.clone(), elements),
+ pub fn new(window: &JS, collection: CollectionTypeId) -> JS {
+ reflect_dom_object(~HTMLCollection::new_inherited(window.clone(), collection),
window, HTMLCollectionBinding::Wrap)
}
}
@@ -45,7 +61,7 @@ impl HTMLCollection {
}
}
}
- HTMLCollection::new(window, elements)
+ HTMLCollection::new(window, Static(elements))
}
pub fn by_tag_name(window: &JS, root: &JS, tag_name: DOMString) -> JS {
@@ -66,15 +82,26 @@ impl HTMLCollection {
impl HTMLCollection {
// http://dom.spec.whatwg.org/#dom-htmlcollection-length
pub fn Length(&self) -> u32 {
- self.elements.len() as u32
+ match self.collection {
+ Static(ref elems) => elems.len() as u32,
+ Live(ref root, ref filter) => root.traverse_preorder()
+ .count(|child| {
+ let elem: Option> = ElementCast::to(&child);
+ elem.map_or(false, |elem| filter.filter(&elem, root))
+ }) as u32
+ }
}
// http://dom.spec.whatwg.org/#dom-htmlcollection-item
pub fn Item(&self, index: u32) -> Option> {
- if index < self.Length() {
- Some(self.elements[index].clone())
- } else {
- None
+ match self.collection {
+ Static(ref elems) => elems
+ .get(index as uint)
+ .map(|elem| elem.clone()),
+ Live(ref root, ref filter) => root.traverse_preorder()
+ .filter_map(|node| ElementCast::to(&node))
+ .filter(|elem| filter.filter(elem, root))
+ .nth(index as uint).clone()
}
}
@@ -86,9 +113,20 @@ impl HTMLCollection {
}
// Step 2.
- self.elements.iter().find(|elem| {
- elem.get_string_attribute("name") == key || elem.get_string_attribute("id") == key
- }).map(|maybe_elem| maybe_elem.clone())
+ match self.collection {
+ Static(ref elems) => elems.iter()
+ .find(|elem| {
+ elem.get_string_attribute("name") == key ||
+ elem.get_string_attribute("id") == key })
+ .map(|maybe_elem| maybe_elem.clone()),
+ Live(ref root, ref filter) => root.traverse_preorder()
+ .filter_map(|node| ElementCast::to(&node))
+ .filter(|elem| filter.filter(elem, root))
+ .find(|elem| {
+ elem.get_string_attribute("name") == key ||
+ elem.get_string_attribute("id") == key })
+ .map(|maybe_elem| maybe_elem.clone())
+ }
}
}
diff --git a/src/components/script/dom/htmlformelement.rs b/src/components/script/dom/htmlformelement.rs
index a1ca7d5dc2f..cabb71cc1ea 100644
--- a/src/components/script/dom/htmlformelement.rs
+++ b/src/components/script/dom/htmlformelement.rs
@@ -9,7 +9,7 @@ use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::{Element, HTMLFormElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
-use dom::htmlcollection::HTMLCollection;
+use dom::htmlcollection::{HTMLCollection, Static};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;
@@ -118,7 +118,7 @@ impl HTMLFormElement {
// FIXME: https://github.com/mozilla/servo/issues/1844
let doc = self.htmlelement.element.node.owner_doc();
let doc = doc.get();
- HTMLCollection::new(&doc.window, ~[])
+ HTMLCollection::new(&doc.window, Static(~[]))
}
pub fn Length(&self) -> i32 {
diff --git a/src/components/script/dom/htmlmapelement.rs b/src/components/script/dom/htmlmapelement.rs
index d343073a278..c439225362c 100644
--- a/src/components/script/dom/htmlmapelement.rs
+++ b/src/components/script/dom/htmlmapelement.rs
@@ -9,7 +9,7 @@ use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLMapElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
-use dom::htmlcollection::HTMLCollection;
+use dom::htmlcollection::{HTMLCollection, Static};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;
@@ -54,6 +54,6 @@ impl HTMLMapElement {
// FIXME: https://github.com/mozilla/servo/issues/1845
let doc = self.htmlelement.element.node.owner_doc();
let doc = doc.get();
- HTMLCollection::new(&doc.window, ~[])
+ HTMLCollection::new(&doc.window, Static(~[]))
}
}