Added CollectionFilter, CollectionTypeId

This commit is contained in:
Bruno de Oliveira Abinader 2014-03-20 18:27:30 -04:00
parent f34a64049a
commit 904e464824
3 changed files with 56 additions and 18 deletions

View file

@ -12,24 +12,40 @@ use dom::window::Window;
use servo_util::namespace::Namespace; use servo_util::namespace::Namespace;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use serialize::{Encoder, Encodable};
pub trait CollectionFilter {
fn filter(&self, elem: &JS<Element>, root: &JS<Node>) -> bool;
}
impl<S: Encoder> Encodable<S> for ~CollectionFilter {
fn encode(&self, _s: &mut S) {}
}
#[deriving(Encodable)]
pub enum CollectionTypeId {
Static(~[JS<Element>]),
Live(JS<Node>, ~CollectionFilter)
}
#[deriving(Encodable)] #[deriving(Encodable)]
pub struct HTMLCollection { pub struct HTMLCollection {
elements: ~[JS<Element>], collection: CollectionTypeId,
reflector_: Reflector, reflector_: Reflector,
window: JS<Window>, window: JS<Window>,
} }
impl HTMLCollection { impl HTMLCollection {
pub fn new_inherited(window: JS<Window>, elements: ~[JS<Element>]) -> HTMLCollection { pub fn new_inherited(window: JS<Window>, collection: CollectionTypeId) -> HTMLCollection {
HTMLCollection { HTMLCollection {
elements: elements, collection: collection,
reflector_: Reflector::new(), reflector_: Reflector::new(),
window: window, window: window,
} }
} }
pub fn new(window: &JS<Window>, elements: ~[JS<Element>]) -> JS<HTMLCollection> { pub fn new(window: &JS<Window>, collection: CollectionTypeId) -> JS<HTMLCollection> {
reflect_dom_object(~HTMLCollection::new_inherited(window.clone(), elements), reflect_dom_object(~HTMLCollection::new_inherited(window.clone(), collection),
window, HTMLCollectionBinding::Wrap) 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<Window>, root: &JS<Node>, tag_name: DOMString) -> JS<HTMLCollection> { pub fn by_tag_name(window: &JS<Window>, root: &JS<Node>, tag_name: DOMString) -> JS<HTMLCollection> {
@ -66,15 +82,26 @@ impl HTMLCollection {
impl HTMLCollection { impl HTMLCollection {
// http://dom.spec.whatwg.org/#dom-htmlcollection-length // http://dom.spec.whatwg.org/#dom-htmlcollection-length
pub fn Length(&self) -> u32 { 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<JS<Element>> = ElementCast::to(&child);
elem.map_or(false, |elem| filter.filter(&elem, root))
}) as u32
}
} }
// http://dom.spec.whatwg.org/#dom-htmlcollection-item // http://dom.spec.whatwg.org/#dom-htmlcollection-item
pub fn Item(&self, index: u32) -> Option<JS<Element>> { pub fn Item(&self, index: u32) -> Option<JS<Element>> {
if index < self.Length() { match self.collection {
Some(self.elements[index].clone()) Static(ref elems) => elems
} else { .get(index as uint)
None .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. // Step 2.
self.elements.iter().find(|elem| { match self.collection {
elem.get_string_attribute("name") == key || elem.get_string_attribute("id") == key Static(ref elems) => elems.iter()
}).map(|maybe_elem| maybe_elem.clone()) .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())
}
} }
} }

View file

@ -9,7 +9,7 @@ use dom::bindings::error::ErrorResult;
use dom::document::Document; use dom::document::Document;
use dom::element::{Element, HTMLFormElementTypeId}; use dom::element::{Element, HTMLFormElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlcollection::HTMLCollection; use dom::htmlcollection::{HTMLCollection, Static};
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId}; use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString; use servo_util::str::DOMString;
@ -118,7 +118,7 @@ impl HTMLFormElement {
// FIXME: https://github.com/mozilla/servo/issues/1844 // FIXME: https://github.com/mozilla/servo/issues/1844
let doc = self.htmlelement.element.node.owner_doc(); let doc = self.htmlelement.element.node.owner_doc();
let doc = doc.get(); let doc = doc.get();
HTMLCollection::new(&doc.window, ~[]) HTMLCollection::new(&doc.window, Static(~[]))
} }
pub fn Length(&self) -> i32 { pub fn Length(&self) -> i32 {

View file

@ -9,7 +9,7 @@ use dom::bindings::error::ErrorResult;
use dom::document::Document; use dom::document::Document;
use dom::element::HTMLMapElementTypeId; use dom::element::HTMLMapElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlcollection::HTMLCollection; use dom::htmlcollection::{HTMLCollection, Static};
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId}; use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString; use servo_util::str::DOMString;
@ -54,6 +54,6 @@ impl HTMLMapElement {
// FIXME: https://github.com/mozilla/servo/issues/1845 // FIXME: https://github.com/mozilla/servo/issues/1845
let doc = self.htmlelement.element.node.owner_doc(); let doc = self.htmlelement.element.node.owner_doc();
let doc = doc.get(); let doc = doc.get();
HTMLCollection::new(&doc.window, ~[]) HTMLCollection::new(&doc.window, Static(~[]))
} }
} }