1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 6 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 7 * Copyright (C) 2014 Samsung Electronics. All rights reserved. 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Library General Public 11 * License as published by the Free Software Foundation; either 12 * version 2 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Library General Public License for more details. 18 * 19 * You should have received a copy of the GNU Library General Public License 20 * along with this library; see the file COPYING.LIB. If not, write to 21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 * Boston, MA 02110-1301, USA. 23 * 24 */ 25 26 #ifndef ElementTraversal_h 27 #define ElementTraversal_h 28 29 #include "core/dom/Element.h" 30 #include "core/dom/NodeTraversal.h" 31 32 namespace WebCore { 33 34 template <class ElementType> 35 class Traversal { 36 public: 37 // First or last ElementType child of the node. 38 static ElementType* firstChild(const ContainerNode& current) { return firstChildTemplate(current); } 39 static ElementType* firstChild(const Node& current) { return firstChildTemplate(current); } 40 static ElementType* lastChild(const ContainerNode& current) { return lastChildTemplate(current); } 41 static ElementType* lastChild(const Node& current) { return lastChildTemplate(current); } 42 43 // First ElementType ancestor of the node. 44 static ElementType* firstAncestor(const Node& current); 45 static ElementType* firstAncestorOrSelf(Node& current) { return firstAncestorOrSelfTemplate(current); } 46 static ElementType* firstAncestorOrSelf(Element& current) { return firstAncestorOrSelfTemplate(current); } 47 48 // First or last ElementType descendant of the node. 49 // For Elements firstWithin() is always the same as firstChild(). 50 static ElementType* firstWithin(const ContainerNode& current) { return firstWithinTemplate(current); } 51 static ElementType* firstWithin(const Node& current) { return firstWithinTemplate(current); } 52 static ElementType* lastWithin(const ContainerNode& current) { return lastWithinTemplate(current); } 53 static ElementType* lastWithin(const Node& current) { return lastWithinTemplate(current); } 54 55 // Pre-order traversal skipping non-element nodes. 56 static ElementType* next(const ContainerNode& current) { return nextTemplate(current); } 57 static ElementType* next(const Node& current) { return nextTemplate(current); } 58 static ElementType* next(const ContainerNode& current, const Node* stayWithin) { return nextTemplate(current, stayWithin); } 59 static ElementType* next(const Node& current, const Node* stayWithin) { return nextTemplate(current, stayWithin); } 60 static ElementType* previous(const ContainerNode& current) { return previousTemplate(current); } 61 static ElementType* previous(const Node& current) { return previousTemplate(current); } 62 static ElementType* previous(const ContainerNode& current, const Node* stayWithin) { return previousTemplate(current, stayWithin); } 63 static ElementType* previous(const Node& current, const Node* stayWithin) { return previousTemplate(current, stayWithin); } 64 65 // Like next, but skips children. 66 static ElementType* nextSkippingChildren(const ContainerNode& current) { return nextSkippingChildrenTemplate(current); } 67 static ElementType* nextSkippingChildren(const Node& current) { return nextSkippingChildrenTemplate(current); } 68 static ElementType* nextSkippingChildren(const ContainerNode& current, const Node* stayWithin) { return nextSkippingChildrenTemplate(current, stayWithin); } 69 static ElementType* nextSkippingChildren(const Node& current, const Node* stayWithin) { return nextSkippingChildrenTemplate(current, stayWithin); } 70 71 // Pre-order traversal including the pseudo-elements. 72 static ElementType* previousIncludingPseudo(const Node&, const Node* stayWithin = 0); 73 static ElementType* nextIncludingPseudo(const Node&, const Node* stayWithin = 0); 74 static ElementType* nextIncludingPseudoSkippingChildren(const Node&, const Node* stayWithin = 0); 75 76 // Utility function to traverse only the element and pseudo-element siblings of a node. 77 static ElementType* pseudoAwarePreviousSibling(const Node&); 78 79 // Previous / Next sibling. 80 static ElementType* previousSibling(const Node&); 81 static ElementType* nextSibling(const Node&); 82 83 private: 84 template <class NodeType> 85 static ElementType* firstChildTemplate(NodeType&); 86 template <class NodeType> 87 static ElementType* lastChildTemplate(NodeType&); 88 template <class NodeType> 89 static ElementType* firstAncestorOrSelfTemplate(NodeType&); 90 template <class NodeType> 91 static ElementType* firstWithinTemplate(NodeType&); 92 template <class NodeType> 93 static ElementType* lastWithinTemplate(NodeType&); 94 template <class NodeType> 95 static ElementType* nextTemplate(NodeType&); 96 template <class NodeType> 97 static ElementType* nextTemplate(NodeType&, const Node* stayWithin); 98 template <class NodeType> 99 static ElementType* previousTemplate(NodeType&); 100 template <class NodeType> 101 static ElementType* previousTemplate(NodeType&, const Node* stayWithin); 102 template <class NodeType> 103 static ElementType* nextSkippingChildrenTemplate(NodeType&); 104 template <class NodeType> 105 static ElementType* nextSkippingChildrenTemplate(NodeType&, const Node* stayWithin); 106 }; 107 108 typedef Traversal<Element> ElementTraversal; 109 110 // Specialized for pure Element to exploit the fact that Elements parent is always either another Element or the root. 111 template <> 112 template <class NodeType> 113 inline Element* Traversal<Element>::firstWithinTemplate(NodeType& current) 114 { 115 return firstChildTemplate(current); 116 } 117 118 template <> 119 template <class NodeType> 120 inline Element* Traversal<Element>::lastWithinTemplate(NodeType& current) 121 { 122 Node* node = NodeTraversal::lastWithin(current); 123 while (node && !node->isElementNode()) 124 node = NodeTraversal::previous(*node, ¤t); 125 return toElement(node); 126 } 127 128 template <> 129 template <class NodeType> 130 inline Element* Traversal<Element>::nextTemplate(NodeType& current) 131 { 132 Node* node = NodeTraversal::next(current); 133 while (node && !node->isElementNode()) 134 node = NodeTraversal::nextSkippingChildren(*node); 135 return toElement(node); 136 } 137 138 template <> 139 template <class NodeType> 140 inline Element* Traversal<Element>::nextTemplate(NodeType& current, const Node* stayWithin) 141 { 142 Node* node = NodeTraversal::next(current, stayWithin); 143 while (node && !node->isElementNode()) 144 node = NodeTraversal::nextSkippingChildren(*node, stayWithin); 145 return toElement(node); 146 } 147 148 template <> 149 template <class NodeType> 150 inline Element* Traversal<Element>::previousTemplate(NodeType& current) 151 { 152 Node* node = NodeTraversal::previous(current); 153 while (node && !node->isElementNode()) 154 node = NodeTraversal::previous(*node); 155 return toElement(node); 156 } 157 158 template <> 159 template <class NodeType> 160 inline Element* Traversal<Element>::previousTemplate(NodeType& current, const Node* stayWithin) 161 { 162 Node* node = NodeTraversal::previous(current, stayWithin); 163 while (node && !node->isElementNode()) 164 node = NodeTraversal::previous(*node, stayWithin); 165 return toElement(node); 166 } 167 168 // Generic versions. 169 template <class ElementType> 170 template <class NodeType> 171 inline ElementType* Traversal<ElementType>::firstChildTemplate(NodeType& current) 172 { 173 Node* node = current.firstChild(); 174 while (node && !isElementOfType<const ElementType>(*node)) 175 node = node->nextSibling(); 176 return toElement<ElementType>(node); 177 } 178 179 template <class ElementType> 180 inline ElementType* Traversal<ElementType>::firstAncestor(const Node& current) 181 { 182 ContainerNode* ancestor = current.parentNode(); 183 while (ancestor && !isElementOfType<const ElementType>(*ancestor)) 184 ancestor = ancestor->parentNode(); 185 return toElement<ElementType>(ancestor); 186 } 187 188 template <class ElementType> 189 template <class NodeType> 190 inline ElementType* Traversal<ElementType>::firstAncestorOrSelfTemplate(NodeType& current) 191 { 192 if (isElementOfType<const ElementType>(current)) 193 return &toElement<ElementType>(current); 194 return firstAncestor(current); 195 } 196 197 template <class ElementType> 198 template <class NodeType> 199 inline ElementType* Traversal<ElementType>::lastChildTemplate(NodeType& current) 200 { 201 Node* node = current.lastChild(); 202 while (node && !isElementOfType<const ElementType>(*node)) 203 node = node->previousSibling(); 204 return toElement<ElementType>(node); 205 } 206 207 template <class ElementType> 208 template <class NodeType> 209 inline ElementType* Traversal<ElementType>::firstWithinTemplate(NodeType& current) 210 { 211 Element* element = Traversal<Element>::firstWithin(current); 212 while (element && !isElementOfType<const ElementType>(*element)) 213 element = Traversal<Element>::next(*element, ¤t); 214 return toElement<ElementType>(element); 215 } 216 217 template <class ElementType> 218 template <class NodeType> 219 inline ElementType* Traversal<ElementType>::lastWithinTemplate(NodeType& current) 220 { 221 Element* element = Traversal<Element>::lastWithin(current); 222 while (element && !isElementOfType<const ElementType>(*element)) 223 element = Traversal<Element>::previous(element, ¤t); 224 return toElement<ElementType>(element); 225 } 226 227 template <class ElementType> 228 template <class NodeType> 229 inline ElementType* Traversal<ElementType>::nextTemplate(NodeType& current) 230 { 231 Element* element = Traversal<Element>::next(current); 232 while (element && !isElementOfType<const ElementType>(*element)) 233 element = Traversal<Element>::next(*element); 234 return toElement<ElementType>(element); 235 } 236 237 template <class ElementType> 238 template <class NodeType> 239 inline ElementType* Traversal<ElementType>::nextTemplate(NodeType& current, const Node* stayWithin) 240 { 241 Element* element = Traversal<Element>::next(current, stayWithin); 242 while (element && !isElementOfType<const ElementType>(*element)) 243 element = Traversal<Element>::next(*element, stayWithin); 244 return toElement<ElementType>(element); 245 } 246 247 template <class ElementType> 248 template <class NodeType> 249 inline ElementType* Traversal<ElementType>::previousTemplate(NodeType& current) 250 { 251 Element* element = Traversal<Element>::previous(current); 252 while (element && !isElementOfType<const ElementType>(*element)) 253 element = Traversal<Element>::previous(*element); 254 return toElement<ElementType>(element); 255 } 256 257 template <class ElementType> 258 template <class NodeType> 259 inline ElementType* Traversal<ElementType>::previousTemplate(NodeType& current, const Node* stayWithin) 260 { 261 Element* element = Traversal<Element>::previous(current, stayWithin); 262 while (element && !isElementOfType<const ElementType>(*element)) 263 element = Traversal<Element>::previous(*element, stayWithin); 264 return toElement<ElementType>(element); 265 } 266 267 template <class ElementType> 268 template <class NodeType> 269 inline ElementType* Traversal<ElementType>::nextSkippingChildrenTemplate(NodeType& current) 270 { 271 Node* node = NodeTraversal::nextSkippingChildren(current); 272 while (node && !isElementOfType<const ElementType>(*node)) 273 node = NodeTraversal::nextSkippingChildren(*node); 274 return toElement<ElementType>(node); 275 } 276 277 template <class ElementType> 278 template <class NodeType> 279 inline ElementType* Traversal<ElementType>::nextSkippingChildrenTemplate(NodeType& current, const Node* stayWithin) 280 { 281 Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin); 282 while (node && !isElementOfType<const ElementType>(*node)) 283 node = NodeTraversal::nextSkippingChildren(*node, stayWithin); 284 return toElement<ElementType>(node); 285 } 286 287 template <class ElementType> 288 inline ElementType* Traversal<ElementType>::previousIncludingPseudo(const Node& current, const Node* stayWithin) 289 { 290 Node* node = NodeTraversal::previousIncludingPseudo(current, stayWithin); 291 while (node && !isElementOfType<const ElementType>(*node)) 292 node = NodeTraversal::previousIncludingPseudo(*node, stayWithin); 293 return toElement<ElementType>(node); 294 } 295 296 template <class ElementType> 297 inline ElementType* Traversal<ElementType>::nextIncludingPseudo(const Node& current, const Node* stayWithin) 298 { 299 Node* node = NodeTraversal::nextIncludingPseudo(current, stayWithin); 300 while (node && !isElementOfType<const ElementType>(*node)) 301 node = NodeTraversal::nextIncludingPseudo(*node, stayWithin); 302 return toElement<ElementType>(node); 303 } 304 305 template <class ElementType> 306 inline ElementType* Traversal<ElementType>::nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin) 307 { 308 Node* node = NodeTraversal::nextIncludingPseudoSkippingChildren(current, stayWithin); 309 while (node && !isElementOfType<const ElementType>(*node)) 310 node = NodeTraversal::nextIncludingPseudoSkippingChildren(*node, stayWithin); 311 return toElement<ElementType>(node); 312 } 313 314 template <class ElementType> 315 inline ElementType* Traversal<ElementType>::pseudoAwarePreviousSibling(const Node& current) 316 { 317 Node* node = current.pseudoAwarePreviousSibling(); 318 while (node && !isElementOfType<const ElementType>(*node)) 319 node = node->pseudoAwarePreviousSibling(); 320 return toElement<ElementType>(node); 321 } 322 323 template <class ElementType> 324 inline ElementType* Traversal<ElementType>::previousSibling(const Node& current) 325 { 326 Node* node = current.previousSibling(); 327 while (node && !isElementOfType<const ElementType>(*node)) 328 node = node->previousSibling(); 329 return toElement<ElementType>(node); 330 } 331 332 template <class ElementType> 333 inline ElementType* Traversal<ElementType>::nextSibling(const Node& current) 334 { 335 Node* node = current.nextSibling(); 336 while (node && !isElementOfType<const ElementType>(*node)) 337 node = node->nextSibling(); 338 return toElement<ElementType>(node); 339 } 340 341 } // namespace WebCore 342 343 #endif 344