1 use webcore::value::{Value, Reference};
2 use webcore::try_from::TryInto;
3 use webcore::reference_type::ReferenceType;
4 use webapi::node::Node;
5 
6 /// `NodeList` objects are collections of nodes such as those returned by properties
7 /// such as [INode::child_nodes](trait.INode.html#method.child_nodes) and the
8 /// [Document::query_selector_all](struct.Document.html#method.query_selector_all) method.
9 ///
10 /// In some cases, the `NodeList` is a live collection, which means that changes in the DOM
11 /// are reflected in the collection - for example [INode::child_nodes](trait.INode.html#method.child_nodes) is live.
12 ///
13 /// In other cases, the `NodeList` is a static collection, meaning any subsequent change
14 /// in the DOM does not affect the content of the collection - for example
15 /// [Document::query_selector_all](struct.Document.html#method.query_selector_all) returns
16 /// a static `NodeList`.
17 ///
18 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/NodeList)
19 // https://dom.spec.whatwg.org/#nodelist
20 #[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
21 #[reference(instance_of = "NodeList")]
22 pub struct NodeList( Reference );
23 
24 impl NodeList {
25     /// Returns the number of [Node](struct.Node.html)s contained in this list.
26     ///
27     /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/NodeList/length)
28     // https://dom.spec.whatwg.org/#ref-for-dom-nodelist-length
len( &self ) -> u3229     pub fn len( &self ) -> u32 {
30         js!( return @{self}.length; ).try_into().unwrap()
31     }
32 
33     /// Returns a node from a NodeList by index.
34     ///
35     /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/NodeList/item)
36     // https://dom.spec.whatwg.org/#ref-for-dom-nodelist-item
item( &self, index: u32 ) -> Option< Node >37     pub fn item( &self, index: u32 ) -> Option< Node > {
38         js!(
39             return @{self}[ @{index} ];
40         ).try_into().unwrap()
41     }
42 
43     /// Returns an iterator over the list.
iter( &self ) -> NodeIter44     pub fn iter( &self ) -> NodeIter {
45         NodeIter {
46             list: self.clone(),
47             index: 0
48         }
49     }
50 }
51 
52 impl IntoIterator for NodeList {
53     type Item = Node;
54     type IntoIter = NodeIter;
55 
56     #[inline]
into_iter( self ) -> Self::IntoIter57     fn into_iter( self ) -> Self::IntoIter {
58         NodeIter {
59             list: self,
60             index: 0
61         }
62     }
63 }
64 
65 impl< 'a > IntoIterator for &'a NodeList {
66     type Item = Node;
67     type IntoIter = NodeIter;
68 
69     #[inline]
into_iter( self ) -> Self::IntoIter70     fn into_iter( self ) -> Self::IntoIter {
71         NodeIter {
72             list: self.clone(),
73             index: 0
74         }
75     }
76 }
77 
78 #[derive(Debug)]
79 pub struct NodeIter {
80     list: NodeList,
81     index: i32
82 }
83 
84 impl Iterator for NodeIter {
85     type Item = Node;
next( &mut self ) -> Option< Self::Item >86     fn next( &mut self ) -> Option< Self::Item > {
87         let value = js!(
88             return @{&self.list}[ @{self.index} ];
89         );
90 
91         let node = match value {
92             Value::Undefined => return None,
93             Value::Reference( reference ) => unsafe { Node::from_reference_unchecked( reference ) },
94             _ => unreachable!()
95         };
96 
97         self.index += 1;
98         Some( node )
99     }
100 }
101