Home | History | Annotate | Download | only in dom
      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, &current);
    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, &current);
    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, &current);
    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