web_sys_query/query/
traversing.rs

1//! Traversing
2
3use crate::{
4    error::Error,
5    query::{Collection, Document, Element},
6};
7
8/// Traversing methods
9impl Element {
10    // TODO: .add()
11    // TODO: .addBack()
12
13    pub fn children(&self, selectors: Option<&str>) -> Result<Collection, Error> {
14        let children = Collection::from(self.0.children());
15        if let Some(selectors) = selectors {
16            children
17                .iter()
18                .filter_map(|elem| match elem.is(selectors) {
19                    Err(err) => Some(Err(err)),
20                    Ok(true) => Some(Ok(elem.clone())),
21                    Ok(false) => None,
22                })
23                .collect::<Result<Vec<Element>, Error>>()
24                .map(Into::into)
25        } else {
26            Ok(children)
27        }
28    }
29
30    /// Find the closets element that matches the selector.
31    pub fn closest(&self, selectors: &str) -> Result<Option<Self>, Error> {
32        self.0
33            .closest(selectors)
34            .map(|elem| elem.map(Into::into))
35            .map_err(Into::into)
36    }
37
38    // TODO: .contents()
39    // TODO: .each()
40    // TODO: .end()
41    // TODO: .eq()
42    // TODO: .even()
43
44    /// Filter if the element matches the selector.
45    pub fn filter(&self, selectors: &str) -> Result<Option<Self>, Error> {
46        self.is(selectors)
47            .map(|result| if result { Some(self.clone()) } else { None })
48    }
49
50    /// Find elements by selectors.
51    pub fn find(&self, selectors: &str) -> Result<Collection, Error> {
52        self.0
53            .query_selector_all(selectors)
54            .map(Into::into)
55            .map_err(Into::into)
56    }
57
58    pub fn first(&self) -> Element {
59        self.clone()
60    }
61
62    /// Filter if a decendant matches the selector.
63    pub fn has(&self, selectors: &str) -> Result<Option<Self>, Error> {
64        self.0
65            .query_selector(selectors)
66            .map(|elem| elem.map(|_| self.clone()))
67            .map_err(Into::into)
68    }
69
70    /// Check if the element matches the selectors.
71    pub fn is(&self, selectors: &str) -> Result<bool, Error> {
72        self.0.matches(selectors).map_err(Into::into)
73    }
74
75    pub fn last(&self) -> Element {
76        self.clone()
77    }
78
79    // TODO: .map()
80
81    pub fn next(&self, selectors: Option<&str>) -> Result<Option<Self>, Error> {
82        if let Some(element) = self.next_element_sibling().map(Self::from) {
83            match selectors {
84                Some(selectors) => element.filter(selectors),
85                None => Ok(Some(element)),
86            }
87        } else {
88            Ok(None)
89        }
90    }
91
92    // TODO: .nextAll()
93    // TODO: .nextUntil()
94
95    /// Filter if the element does not matche the selector.
96    pub fn not(&self, selectors: &str) -> Result<Option<Self>, Error> {
97        self.is(selectors)
98            .map(|result| if !result { Some(self.clone()) } else { None })
99    }
100
101    // TODO: .odd()
102    // TODO: .offsetParent()
103
104    pub fn parent(&self) -> Option<Self> {
105        self.parent_element().map(Into::into)
106    }
107
108    // TODO: .parents()
109    // TODO: .parentsUntil()
110
111    pub fn prev(&self, selectors: Option<&str>) -> Result<Option<Self>, Error> {
112        if let Some(element) = self.previous_element_sibling().map(Self::from) {
113            match selectors {
114                Some(selectors) => element.filter(selectors),
115                None => Ok(Some(element)),
116            }
117        } else {
118            Ok(None)
119        }
120    }
121
122    // TODO: .prevAll()
123    // TODO: .prevUntil()
124    // TODO: .siblings()
125    // TODO: .slice()
126}
127
128/// Traversing methods
129impl Collection {
130    pub fn children(&self, selectors: Option<&str>) -> Result<Collection, Error> {
131        self.iter().map(|elem| elem.children(selectors)).collect()
132    }
133
134    pub fn filter(&self, selectors: &str) -> Result<Collection, Error> {
135        self.iter()
136            .filter_map(|elem| elem.filter(selectors).transpose())
137            .collect()
138    }
139
140    pub fn find(&self, selectors: &str) -> Result<Collection, Error> {
141        self.iter().map(|elem| elem.find(selectors)).collect()
142    }
143
144    pub fn first(&self) -> Option<Element> {
145        self.0.front().map(Clone::clone)
146    }
147
148    pub fn has(&self, selectors: &str) -> Result<Collection, Error> {
149        self.iter()
150            .filter_map(|elem| elem.has(selectors).transpose())
151            .collect()
152    }
153
154    pub fn is(&self, selectors: &str) -> Result<bool, Error> {
155        let is = self
156            .iter()
157            .map(|elem| elem.is(selectors))
158            .collect::<Result<Vec<_>, Error>>()?;
159        Ok(is.contains(&true))
160    }
161
162    pub fn last(&self) -> Option<Element> {
163        self.0.back().map(Clone::clone)
164    }
165
166    pub fn next(&self, selectors: Option<&str>) -> Result<Collection, Error> {
167        self.iter()
168            .filter_map(|elem| elem.next(selectors).transpose())
169            .collect()
170    }
171
172    pub fn parent(&self) -> Collection {
173        self.iter().filter_map(|elem| elem.parent()).collect()
174    }
175
176    pub fn prev(&self, selectors: Option<&str>) -> Result<Collection, Error> {
177        self.iter()
178            .filter_map(|elem| elem.prev(selectors).transpose())
179            .collect()
180    }
181}
182
183/// Traversing methods.
184impl Document {
185    pub fn children(&self, selectors: Option<&str>) -> Result<Collection, Error> {
186        let children = Collection::from(self.0.children());
187        if let Some(selectors) = selectors {
188            children
189                .iter()
190                .filter_map(|elem| match elem.is(selectors) {
191                    Err(err) => Some(Err(err)),
192                    Ok(true) => Some(Ok(elem.clone())),
193                    Ok(false) => None,
194                })
195                .collect::<Result<Vec<Element>, Error>>()
196                .map(Into::into)
197        } else {
198            Ok(children)
199        }
200    }
201
202    pub fn find(&self, selectors: &str) -> Result<Collection, Error> {
203        self.0
204            .query_selector_all(selectors)
205            .map(Into::into)
206            .map_err(Into::into)
207    }
208}