OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Appl
e Inc. All rights reserved. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Appl
e Inc. All rights reserved. |
6 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) | 6 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) |
7 * Copyright (C) 2014 Samsung Electronics. All rights reserved. | 7 * Copyright (C) 2014 Samsung Electronics. All rights reserved. |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "core/dom/NodeTraversal.h" | 30 #include "core/dom/NodeTraversal.h" |
31 | 31 |
32 namespace blink { | 32 namespace blink { |
33 | 33 |
34 template <class ElementType> | 34 template <class ElementType> |
35 class Traversal { | 35 class Traversal { |
36 public: | 36 public: |
37 // First or last ElementType child of the node. | 37 // First or last ElementType child of the node. |
38 static ElementType* firstChild(const ContainerNode& current) { return firstC
hildTemplate(current); } | 38 static ElementType* firstChild(const ContainerNode& current) { return firstC
hildTemplate(current); } |
39 static ElementType* firstChild(const Node& current) { return firstChildTempl
ate(current); } | 39 static ElementType* firstChild(const Node& current) { return firstChildTempl
ate(current); } |
| 40 template <class MatchFunc> |
| 41 static ElementType* firstChild(const ContainerNode&, MatchFunc); |
40 static ElementType* lastChild(const ContainerNode& current) { return lastChi
ldTemplate(current); } | 42 static ElementType* lastChild(const ContainerNode& current) { return lastChi
ldTemplate(current); } |
41 static ElementType* lastChild(const Node& current) { return lastChildTemplat
e(current); } | 43 static ElementType* lastChild(const Node& current) { return lastChildTemplat
e(current); } |
| 44 template <class MatchFunc> |
| 45 static ElementType* lastChild(const ContainerNode&, MatchFunc); |
42 | 46 |
43 // First ElementType ancestor of the node. | 47 // First ElementType ancestor of the node. |
44 static ElementType* firstAncestor(const Node& current); | 48 static ElementType* firstAncestor(const Node& current); |
45 static ElementType* firstAncestorOrSelf(Node& current) { return firstAncesto
rOrSelfTemplate(current); } | 49 static ElementType* firstAncestorOrSelf(Node& current) { return firstAncesto
rOrSelfTemplate(current); } |
46 static ElementType* firstAncestorOrSelf(Element& current) { return firstAnce
storOrSelfTemplate(current); } | 50 static ElementType* firstAncestorOrSelf(Element& current) { return firstAnce
storOrSelfTemplate(current); } |
47 static const ElementType* firstAncestorOrSelf(const Node& current) { return
firstAncestorOrSelfTemplate(const_cast<Node&>(current)); } | 51 static const ElementType* firstAncestorOrSelf(const Node& current) { return
firstAncestorOrSelfTemplate(const_cast<Node&>(current)); } |
48 static const ElementType* firstAncestorOrSelf(const Element& current) { retu
rn firstAncestorOrSelfTemplate(const_cast<Element&>(current)); } | 52 static const ElementType* firstAncestorOrSelf(const Element& current) { retu
rn firstAncestorOrSelfTemplate(const_cast<Element&>(current)); } |
49 | 53 |
50 // First or last ElementType descendant of the node. | 54 // First or last ElementType descendant of the node. |
51 // For Elements firstWithin() is always the same as firstChild(). | 55 // For Elements firstWithin() is always the same as firstChild(). |
52 static ElementType* firstWithin(const ContainerNode& current) { return first
WithinTemplate(current); } | 56 static ElementType* firstWithin(const ContainerNode& current) { return first
WithinTemplate(current); } |
53 static ElementType* firstWithin(const Node& current) { return firstWithinTem
plate(current); } | 57 static ElementType* firstWithin(const Node& current) { return firstWithinTem
plate(current); } |
| 58 template <typename MatchFunc> |
| 59 static ElementType* firstWithin(const ContainerNode&, MatchFunc); |
54 static ElementType* lastWithin(const ContainerNode& current) { return lastWi
thinTemplate(current); } | 60 static ElementType* lastWithin(const ContainerNode& current) { return lastWi
thinTemplate(current); } |
55 static ElementType* lastWithin(const Node& current) { return lastWithinTempl
ate(current); } | 61 static ElementType* lastWithin(const Node& current) { return lastWithinTempl
ate(current); } |
| 62 template <class MatchFunc> |
| 63 static ElementType* lastWithin(const ContainerNode&, MatchFunc); |
56 | 64 |
57 // Pre-order traversal skipping non-element nodes. | 65 // Pre-order traversal skipping non-element nodes. |
58 static ElementType* next(const ContainerNode& current) { return nextTemplate
(current); } | 66 static ElementType* next(const ContainerNode& current) { return nextTemplate
(current); } |
59 static ElementType* next(const Node& current) { return nextTemplate(current)
; } | 67 static ElementType* next(const Node& current) { return nextTemplate(current)
; } |
60 static ElementType* next(const ContainerNode& current, const Node* stayWithi
n) { return nextTemplate(current, stayWithin); } | 68 static ElementType* next(const ContainerNode& current, const Node* stayWithi
n) { return nextTemplate(current, stayWithin); } |
61 static ElementType* next(const Node& current, const Node* stayWithin) { retu
rn nextTemplate(current, stayWithin); } | 69 static ElementType* next(const Node& current, const Node* stayWithin) { retu
rn nextTemplate(current, stayWithin); } |
| 70 template <class MatchFunc> |
| 71 static ElementType* next(const ContainerNode& current, const Node* stayWithi
n, MatchFunc); |
62 static ElementType* previous(const Node&); | 72 static ElementType* previous(const Node&); |
63 static ElementType* previous(const Node&, const Node* stayWithin); | 73 static ElementType* previous(const Node&, const Node* stayWithin); |
| 74 template <class MatchFunc> |
| 75 static ElementType* previous(const ContainerNode& current, const Node* stayW
ithin, MatchFunc); |
64 | 76 |
65 // Like next, but skips children. | 77 // Like next, but skips children. |
66 static ElementType* nextSkippingChildren(const Node&); | 78 static ElementType* nextSkippingChildren(const Node&); |
67 static ElementType* nextSkippingChildren(const Node&, const Node* stayWithin
); | 79 static ElementType* nextSkippingChildren(const Node&, const Node* stayWithin
); |
68 | 80 |
69 // Pre-order traversal including the pseudo-elements. | 81 // Pre-order traversal including the pseudo-elements. |
70 static ElementType* previousIncludingPseudo(const Node&, const Node* stayWit
hin = 0); | 82 static ElementType* previousIncludingPseudo(const Node&, const Node* stayWit
hin = 0); |
71 static ElementType* nextIncludingPseudo(const Node&, const Node* stayWithin
= 0); | 83 static ElementType* nextIncludingPseudo(const Node&, const Node* stayWithin
= 0); |
72 static ElementType* nextIncludingPseudoSkippingChildren(const Node&, const N
ode* stayWithin = 0); | 84 static ElementType* nextIncludingPseudoSkippingChildren(const Node&, const N
ode* stayWithin = 0); |
73 | 85 |
74 // Utility function to traverse only the element and pseudo-element siblings
of a node. | 86 // Utility function to traverse only the element and pseudo-element siblings
of a node. |
75 static ElementType* pseudoAwarePreviousSibling(const Node&); | 87 static ElementType* pseudoAwarePreviousSibling(const Node&); |
76 | 88 |
77 // Previous / Next sibling. | 89 // Previous / Next sibling. |
78 static ElementType* previousSibling(const Node&); | 90 static ElementType* previousSibling(const Node&); |
| 91 template <class MatchFunc> |
| 92 static ElementType* previousSibling(const Node&, MatchFunc); |
79 static ElementType* nextSibling(const Node&); | 93 static ElementType* nextSibling(const Node&); |
| 94 template <class MatchFunc> |
| 95 static ElementType* nextSibling(const Node&, MatchFunc); |
80 | 96 |
81 private: | 97 private: |
82 template <class NodeType> | 98 template <class NodeType> |
83 static ElementType* firstChildTemplate(NodeType&); | 99 static ElementType* firstChildTemplate(NodeType&); |
84 template <class NodeType> | 100 template <class NodeType> |
85 static ElementType* lastChildTemplate(NodeType&); | 101 static ElementType* lastChildTemplate(NodeType&); |
86 template <class NodeType> | 102 template <class NodeType> |
87 static ElementType* firstAncestorOrSelfTemplate(NodeType&); | 103 static ElementType* firstAncestorOrSelfTemplate(NodeType&); |
88 template <class NodeType> | 104 template <class NodeType> |
89 static ElementType* firstWithinTemplate(NodeType&); | 105 static ElementType* firstWithinTemplate(NodeType&); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 template <class NodeType> | 146 template <class NodeType> |
131 inline ElementType* Traversal<ElementType>::firstChildTemplate(NodeType& current
) | 147 inline ElementType* Traversal<ElementType>::firstChildTemplate(NodeType& current
) |
132 { | 148 { |
133 Node* node = current.firstChild(); | 149 Node* node = current.firstChild(); |
134 while (node && !isElementOfType<const ElementType>(*node)) | 150 while (node && !isElementOfType<const ElementType>(*node)) |
135 node = node->nextSibling(); | 151 node = node->nextSibling(); |
136 return toElement<ElementType>(node); | 152 return toElement<ElementType>(node); |
137 } | 153 } |
138 | 154 |
139 template <class ElementType> | 155 template <class ElementType> |
| 156 template <class MatchFunc> |
| 157 inline ElementType* Traversal<ElementType>::firstChild(const ContainerNode& curr
ent, MatchFunc isMatch) |
| 158 { |
| 159 ElementType* element = Traversal<ElementType>::firstChild(current); |
| 160 while (element && !isMatch(*element)) |
| 161 element = Traversal<ElementType>::nextSibling(*element); |
| 162 return element; |
| 163 } |
| 164 |
| 165 template <class ElementType> |
140 inline ElementType* Traversal<ElementType>::firstAncestor(const Node& current) | 166 inline ElementType* Traversal<ElementType>::firstAncestor(const Node& current) |
141 { | 167 { |
142 ContainerNode* ancestor = current.parentNode(); | 168 ContainerNode* ancestor = current.parentNode(); |
143 while (ancestor && !isElementOfType<const ElementType>(*ancestor)) | 169 while (ancestor && !isElementOfType<const ElementType>(*ancestor)) |
144 ancestor = ancestor->parentNode(); | 170 ancestor = ancestor->parentNode(); |
145 return toElement<ElementType>(ancestor); | 171 return toElement<ElementType>(ancestor); |
146 } | 172 } |
147 | 173 |
148 template <class ElementType> | 174 template <class ElementType> |
149 template <class NodeType> | 175 template <class NodeType> |
150 inline ElementType* Traversal<ElementType>::firstAncestorOrSelfTemplate(NodeType
& current) | 176 inline ElementType* Traversal<ElementType>::firstAncestorOrSelfTemplate(NodeType
& current) |
151 { | 177 { |
152 if (isElementOfType<const ElementType>(current)) | 178 if (isElementOfType<const ElementType>(current)) |
153 return &toElement<ElementType>(current); | 179 return &toElement<ElementType>(current); |
154 return firstAncestor(current); | 180 return firstAncestor(current); |
155 } | 181 } |
156 | 182 |
157 template <class ElementType> | 183 template <class ElementType> |
158 template <class NodeType> | 184 template <class NodeType> |
159 inline ElementType* Traversal<ElementType>::lastChildTemplate(NodeType& current) | 185 inline ElementType* Traversal<ElementType>::lastChildTemplate(NodeType& current) |
160 { | 186 { |
161 Node* node = current.lastChild(); | 187 Node* node = current.lastChild(); |
162 while (node && !isElementOfType<const ElementType>(*node)) | 188 while (node && !isElementOfType<const ElementType>(*node)) |
163 node = node->previousSibling(); | 189 node = node->previousSibling(); |
164 return toElement<ElementType>(node); | 190 return toElement<ElementType>(node); |
165 } | 191 } |
166 | 192 |
167 template <class ElementType> | 193 template <class ElementType> |
| 194 template <class MatchFunc> |
| 195 inline ElementType* Traversal<ElementType>::lastChild(const ContainerNode& curre
nt, MatchFunc isMatch) |
| 196 { |
| 197 ElementType* element = Traversal<ElementType>::lastChild(current); |
| 198 while (element && !isMatch(*element)) |
| 199 element = Traversal<ElementType>::previousSibling(*element); |
| 200 return element; |
| 201 } |
| 202 |
| 203 template <class ElementType> |
168 template <class NodeType> | 204 template <class NodeType> |
169 inline ElementType* Traversal<ElementType>::firstWithinTemplate(NodeType& curren
t) | 205 inline ElementType* Traversal<ElementType>::firstWithinTemplate(NodeType& curren
t) |
170 { | 206 { |
171 Node* node = current.firstChild(); | 207 Node* node = current.firstChild(); |
172 while (node && !isElementOfType<const ElementType>(*node)) | 208 while (node && !isElementOfType<const ElementType>(*node)) |
173 node = NodeTraversal::next(*node, ¤t); | 209 node = NodeTraversal::next(*node, ¤t); |
174 return toElement<ElementType>(node); | 210 return toElement<ElementType>(node); |
175 } | 211 } |
176 | 212 |
177 template <class ElementType> | 213 template <class ElementType> |
| 214 template <typename MatchFunc> |
| 215 inline ElementType* Traversal<ElementType>::firstWithin(const ContainerNode& cur
rent, MatchFunc isMatch) |
| 216 { |
| 217 ElementType* element = Traversal<ElementType>::firstWithin(current); |
| 218 while (element && !isMatch(*element)) |
| 219 element = Traversal<ElementType>::next(*element, ¤t, isMatch); |
| 220 return element; |
| 221 } |
| 222 |
| 223 template <class ElementType> |
178 template <class NodeType> | 224 template <class NodeType> |
179 inline ElementType* Traversal<ElementType>::lastWithinTemplate(NodeType& current
) | 225 inline ElementType* Traversal<ElementType>::lastWithinTemplate(NodeType& current
) |
180 { | 226 { |
181 Node* node = NodeTraversal::lastWithin(current); | 227 Node* node = NodeTraversal::lastWithin(current); |
182 while (node && !isElementOfType<const ElementType>(*node)) | 228 while (node && !isElementOfType<const ElementType>(*node)) |
183 node = NodeTraversal::previous(*node, ¤t); | 229 node = NodeTraversal::previous(*node, ¤t); |
184 return toElement<ElementType>(node); | 230 return toElement<ElementType>(node); |
185 } | 231 } |
186 | 232 |
187 template <class ElementType> | 233 template <class ElementType> |
| 234 template <class MatchFunc> |
| 235 inline ElementType* Traversal<ElementType>::lastWithin(const ContainerNode& curr
ent, MatchFunc isMatch) |
| 236 { |
| 237 ElementType* element = Traversal<ElementType>::lastWithin(current); |
| 238 while (element && !isMatch(*element)) |
| 239 element = Traversal<ElementType>::previous(*element, ¤t, isMatch); |
| 240 return element; |
| 241 } |
| 242 |
| 243 template <class ElementType> |
188 template <class NodeType> | 244 template <class NodeType> |
189 inline ElementType* Traversal<ElementType>::nextTemplate(NodeType& current) | 245 inline ElementType* Traversal<ElementType>::nextTemplate(NodeType& current) |
190 { | 246 { |
191 Node* node = NodeTraversal::next(current); | 247 Node* node = NodeTraversal::next(current); |
192 while (node && !isElementOfType<const ElementType>(*node)) | 248 while (node && !isElementOfType<const ElementType>(*node)) |
193 node = NodeTraversal::next(*node); | 249 node = NodeTraversal::next(*node); |
194 return toElement<ElementType>(node); | 250 return toElement<ElementType>(node); |
195 } | 251 } |
196 | 252 |
197 template <class ElementType> | 253 template <class ElementType> |
198 template <class NodeType> | 254 template <class NodeType> |
199 inline ElementType* Traversal<ElementType>::nextTemplate(NodeType& current, cons
t Node* stayWithin) | 255 inline ElementType* Traversal<ElementType>::nextTemplate(NodeType& current, cons
t Node* stayWithin) |
200 { | 256 { |
201 Node* node = NodeTraversal::next(current, stayWithin); | 257 Node* node = NodeTraversal::next(current, stayWithin); |
202 while (node && !isElementOfType<const ElementType>(*node)) | 258 while (node && !isElementOfType<const ElementType>(*node)) |
203 node = NodeTraversal::next(*node, stayWithin); | 259 node = NodeTraversal::next(*node, stayWithin); |
204 return toElement<ElementType>(node); | 260 return toElement<ElementType>(node); |
205 } | 261 } |
206 | 262 |
207 template <class ElementType> | 263 template <class ElementType> |
| 264 template <class MatchFunc> |
| 265 inline ElementType* Traversal<ElementType>::next(const ContainerNode& current, c
onst Node* stayWithin, MatchFunc isMatch) |
| 266 { |
| 267 ElementType* element = Traversal<ElementType>::next(current, stayWithin); |
| 268 while (element && !isMatch(*element)) |
| 269 element = Traversal<ElementType>::next(*element, stayWithin); |
| 270 return element; |
| 271 } |
| 272 |
| 273 template <class ElementType> |
208 inline ElementType* Traversal<ElementType>::previous(const Node& current) | 274 inline ElementType* Traversal<ElementType>::previous(const Node& current) |
209 { | 275 { |
210 Node* node = NodeTraversal::previous(current); | 276 Node* node = NodeTraversal::previous(current); |
211 while (node && !isElementOfType<const ElementType>(*node)) | 277 while (node && !isElementOfType<const ElementType>(*node)) |
212 node = NodeTraversal::previous(*node); | 278 node = NodeTraversal::previous(*node); |
213 return toElement<ElementType>(node); | 279 return toElement<ElementType>(node); |
214 } | 280 } |
215 | 281 |
216 template <class ElementType> | 282 template <class ElementType> |
217 inline ElementType* Traversal<ElementType>::previous(const Node& current, const
Node* stayWithin) | 283 inline ElementType* Traversal<ElementType>::previous(const Node& current, const
Node* stayWithin) |
218 { | 284 { |
219 Node* node = NodeTraversal::previous(current, stayWithin); | 285 Node* node = NodeTraversal::previous(current, stayWithin); |
220 while (node && !isElementOfType<const ElementType>(*node)) | 286 while (node && !isElementOfType<const ElementType>(*node)) |
221 node = NodeTraversal::previous(*node, stayWithin); | 287 node = NodeTraversal::previous(*node, stayWithin); |
222 return toElement<ElementType>(node); | 288 return toElement<ElementType>(node); |
223 } | 289 } |
224 | 290 |
225 template <class ElementType> | 291 template <class ElementType> |
| 292 template <class MatchFunc> |
| 293 inline ElementType* Traversal<ElementType>::previous(const ContainerNode& curren
t, const Node* stayWithin, MatchFunc isMatch) |
| 294 { |
| 295 ElementType* element = Traversal<ElementType>::previous(current, stayWithin)
; |
| 296 while (element && !isMatch(*element)) |
| 297 element = Traversal<ElementType>::previous(*element, stayWithin); |
| 298 return element; |
| 299 } |
| 300 |
| 301 template <class ElementType> |
226 inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node& cur
rent) | 302 inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node& cur
rent) |
227 { | 303 { |
228 Node* node = NodeTraversal::nextSkippingChildren(current); | 304 Node* node = NodeTraversal::nextSkippingChildren(current); |
229 while (node && !isElementOfType<const ElementType>(*node)) | 305 while (node && !isElementOfType<const ElementType>(*node)) |
230 node = NodeTraversal::nextSkippingChildren(*node); | 306 node = NodeTraversal::nextSkippingChildren(*node); |
231 return toElement<ElementType>(node); | 307 return toElement<ElementType>(node); |
232 } | 308 } |
233 | 309 |
234 template <class ElementType> | 310 template <class ElementType> |
235 inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node& cur
rent, const Node* stayWithin) | 311 inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node& cur
rent, const Node* stayWithin) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 template <class ElementType> | 355 template <class ElementType> |
280 inline ElementType* Traversal<ElementType>::previousSibling(const Node& current) | 356 inline ElementType* Traversal<ElementType>::previousSibling(const Node& current) |
281 { | 357 { |
282 Node* node = current.previousSibling(); | 358 Node* node = current.previousSibling(); |
283 while (node && !isElementOfType<const ElementType>(*node)) | 359 while (node && !isElementOfType<const ElementType>(*node)) |
284 node = node->previousSibling(); | 360 node = node->previousSibling(); |
285 return toElement<ElementType>(node); | 361 return toElement<ElementType>(node); |
286 } | 362 } |
287 | 363 |
288 template <class ElementType> | 364 template <class ElementType> |
| 365 template <class MatchFunc> |
| 366 inline ElementType* Traversal<ElementType>::previousSibling(const Node& current,
MatchFunc isMatch) |
| 367 { |
| 368 ElementType* element = Traversal<ElementType>::previousSibling(current); |
| 369 while (element && !isMatch(*element)) |
| 370 element = Traversal<ElementType>::previousSibling(*element); |
| 371 return element; |
| 372 } |
| 373 |
| 374 template <class ElementType> |
289 inline ElementType* Traversal<ElementType>::nextSibling(const Node& current) | 375 inline ElementType* Traversal<ElementType>::nextSibling(const Node& current) |
290 { | 376 { |
291 Node* node = current.nextSibling(); | 377 Node* node = current.nextSibling(); |
292 while (node && !isElementOfType<const ElementType>(*node)) | 378 while (node && !isElementOfType<const ElementType>(*node)) |
293 node = node->nextSibling(); | 379 node = node->nextSibling(); |
294 return toElement<ElementType>(node); | 380 return toElement<ElementType>(node); |
295 } | 381 } |
296 | 382 |
| 383 template <class ElementType> |
| 384 template <class MatchFunc> |
| 385 inline ElementType* Traversal<ElementType>::nextSibling(const Node& current, Mat
chFunc isMatch) |
| 386 { |
| 387 ElementType* element = Traversal<ElementType>::nextSibling(current); |
| 388 while (element && !isMatch(*element)) |
| 389 element = Traversal<ElementType>::nextSibling(*element); |
| 390 return element; |
| 391 } |
| 392 |
297 } // namespace blink | 393 } // namespace blink |
298 | 394 |
299 #endif | 395 #endif |
OLD | NEW |