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 Apple Inc. All rights reserved.
      6  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Library General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Library General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Library General Public License
     19  * along with this library; see the file COPYING.LIB.  If not, write to
     20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     21  * Boston, MA 02110-1301, USA.
     22  *
     23  */
     24 
     25 #ifndef ElementTraversal_h
     26 #define ElementTraversal_h
     27 
     28 #include "core/dom/Element.h"
     29 #include "core/dom/NodeTraversal.h"
     30 
     31 namespace WebCore {
     32 
     33 namespace ElementTraversal {
     34 
     35 // First element child of the node.
     36 Element* firstWithin(const Node&);
     37 Element* firstWithin(const ContainerNode&);
     38 
     39 // Pre-order traversal skipping non-element nodes.
     40 Element* next(const Node&);
     41 Element* next(const Node&, const Node* stayWithin);
     42 Element* next(const ContainerNode&);
     43 Element* next(const ContainerNode&, const Node* stayWithin);
     44 
     45 // Like next, but skips children.
     46 Element* nextSkippingChildren(const Node&);
     47 Element* nextSkippingChildren(const Node&, const Node* stayWithin);
     48 Element* nextSkippingChildren(const ContainerNode&);
     49 Element* nextSkippingChildren(const ContainerNode&, const Node* stayWithin);
     50 
     51 // Pre-order traversal including the pseudo-elements.
     52 Element* previousIncludingPseudo(const Node&, const Node* stayWithin = 0);
     53 Element* nextIncludingPseudo(const Node&, const Node* stayWithin = 0);
     54 Element* nextIncludingPseudoSkippingChildren(const Node&, const Node* stayWithin = 0);
     55 
     56 // Utility function to traverse only the element and pseudo-element siblings of a node.
     57 Element* pseudoAwarePreviousSibling(const Node&);
     58 
     59 template <class NodeType>
     60 inline Element* firstElementWithinTemplate(NodeType& current)
     61 {
     62     // Except for the root containers, only elements can have element children.
     63     Node* node = current.firstChild();
     64     while (node && !node->isElementNode())
     65         node = node->nextSibling();
     66     return toElement(node);
     67 }
     68 inline Element* firstWithin(const ContainerNode& current) { return firstElementWithinTemplate(current); }
     69 inline Element* firstWithin(const Node& current) { return firstElementWithinTemplate(current); }
     70 
     71 template <class NodeType>
     72 inline Element* traverseNextElementTemplate(NodeType& current)
     73 {
     74     Node* node = NodeTraversal::next(current);
     75     while (node && !node->isElementNode())
     76         node = NodeTraversal::nextSkippingChildren(*node);
     77     return toElement(node);
     78 }
     79 inline Element* next(const ContainerNode& current) { return traverseNextElementTemplate(current); }
     80 inline Element* next(const Node& current) { return traverseNextElementTemplate(current); }
     81 
     82 template <class NodeType>
     83 inline Element* traverseNextElementTemplate(NodeType& current, const Node* stayWithin)
     84 {
     85     Node* node = NodeTraversal::next(current, stayWithin);
     86     while (node && !node->isElementNode())
     87         node = NodeTraversal::nextSkippingChildren(*node, stayWithin);
     88     return toElement(node);
     89 }
     90 inline Element* next(const ContainerNode& current, const Node* stayWithin) { return traverseNextElementTemplate(current, stayWithin); }
     91 inline Element* next(const Node& current, const Node* stayWithin) { return traverseNextElementTemplate(current, stayWithin); }
     92 
     93 template <class NodeType>
     94 inline Element* traverseNextElementSkippingChildrenTemplate(NodeType& current)
     95 {
     96     Node* node = NodeTraversal::nextSkippingChildren(current);
     97     while (node && !node->isElementNode())
     98         node = NodeTraversal::nextSkippingChildren(*node);
     99     return toElement(node);
    100 }
    101 inline Element* nextSkippingChildren(const ContainerNode& current) { return traverseNextElementSkippingChildrenTemplate(current); }
    102 inline Element* nextSkippingChildren(const Node& current) { return traverseNextElementSkippingChildrenTemplate(current); }
    103 
    104 template <class NodeType>
    105 inline Element* traverseNextElementSkippingChildrenTemplate(NodeType& current, const Node* stayWithin)
    106 {
    107     Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin);
    108     while (node && !node->isElementNode())
    109         node = NodeTraversal::nextSkippingChildren(*node, stayWithin);
    110     return toElement(node);
    111 }
    112 inline Element* nextSkippingChildren(const ContainerNode& current, const Node* stayWithin) { return traverseNextElementSkippingChildrenTemplate(current, stayWithin); }
    113 inline Element* nextSkippingChildren(const Node& current, const Node* stayWithin) { return traverseNextElementSkippingChildrenTemplate(current, stayWithin); }
    114 
    115 inline Element* previousIncludingPseudo(const Node& current, const Node* stayWithin)
    116 {
    117     Node* node = NodeTraversal::previousIncludingPseudo(current, stayWithin);
    118     while (node && !node->isElementNode())
    119         node = NodeTraversal::previousIncludingPseudo(*node, stayWithin);
    120     return toElement(node);
    121 }
    122 
    123 inline Element* nextIncludingPseudo(const Node& current, const Node* stayWithin)
    124 {
    125     Node* node = NodeTraversal::nextIncludingPseudo(current, stayWithin);
    126     while (node && !node->isElementNode())
    127         node = NodeTraversal::nextIncludingPseudo(*node, stayWithin);
    128     return toElement(node);
    129 }
    130 
    131 inline Element* nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin)
    132 {
    133     Node* node = NodeTraversal::nextIncludingPseudoSkippingChildren(current, stayWithin);
    134     while (node && !node->isElementNode())
    135         node = NodeTraversal::nextIncludingPseudoSkippingChildren(*node, stayWithin);
    136     return toElement(node);
    137 }
    138 
    139 inline Element* pseudoAwarePreviousSibling(const Node& current)
    140 {
    141     Node* node = current.pseudoAwarePreviousSibling();
    142     while (node && !node->isElementNode())
    143         node = node->pseudoAwarePreviousSibling();
    144     return toElement(node);
    145 }
    146 
    147 }
    148 
    149 }
    150 
    151 #endif
    152