| Index: Source/core/dom/ElementTraversal.h
|
| diff --git a/Source/core/dom/ElementTraversal.h b/Source/core/dom/ElementTraversal.h
|
| index 2f8ede5aaf8257376e092345d5ad6e83423c571a..6705f04efcd20b8bf281258b366a92797c59998a 100644
|
| --- a/Source/core/dom/ElementTraversal.h
|
| +++ b/Source/core/dom/ElementTraversal.h
|
| @@ -2,7 +2,7 @@
|
| * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
|
| * (C) 1999 Antti Koivisto (koivisto@kde.org)
|
| * (C) 2001 Dirk Mueller (mueller@kde.org)
|
| - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
|
| + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
|
| * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
|
| * Copyright (C) 2014 Samsung Electronics. All rights reserved.
|
| *
|
| @@ -31,74 +31,93 @@
|
|
|
| namespace WebCore {
|
|
|
| -class ElementTraversal {
|
| +template <class ElementType>
|
| +class Traversal {
|
| public:
|
| - // First / Last element child of the node.
|
| - static Element* firstWithin(const ContainerNode& current) { return firstElementWithinTemplate(current); }
|
| - static Element* firstWithin(const Node& current) { return firstElementWithinTemplate(current); }
|
| - static Element* lastWithin(const ContainerNode& current) { return lastWithinTemplate(current); }
|
| - static Element* lastWithin(const Node& current) { return lastWithinTemplate(current); }
|
| + // First or last ElementType child of the node.
|
| + static ElementType* firstChild(const ContainerNode& current) { return firstChildTemplate(current); }
|
| + static ElementType* firstChild(const Node& current) { return firstChildTemplate(current); }
|
| + static ElementType* lastChild(const ContainerNode& current) { return lastChildTemplate(current); }
|
| + static ElementType* lastChild(const Node& current) { return lastChildTemplate(current); }
|
| +
|
| + // First or last ElementType descendant of the node.
|
| + // For Elements firstWithin() is always the same as firstChild().
|
| + static ElementType* firstWithin(const ContainerNode& current) { return firstWithinTemplate(current); }
|
| + static ElementType* firstWithin(const Node& current) { return firstWithinTemplate(current); }
|
| + static ElementType* lastWithin(const ContainerNode& current) { return lastWithinTemplate(current); }
|
| + static ElementType* lastWithin(const Node& current) { return lastWithinTemplate(current); }
|
|
|
| // Pre-order traversal skipping non-element nodes.
|
| - static Element* next(const ContainerNode& current) { return traverseNextElementTemplate(current); }
|
| - static Element* next(const Node& current) { return traverseNextElementTemplate(current); }
|
| - static Element* next(const ContainerNode& current, const Node* stayWithin) { return traverseNextElementTemplate(current, stayWithin); }
|
| - static Element* next(const Node& current, const Node* stayWithin) { return traverseNextElementTemplate(current, stayWithin); }
|
| + static ElementType* next(const ContainerNode& current) { return nextTemplate(current); }
|
| + static ElementType* next(const Node& current) { return nextTemplate(current); }
|
| + static ElementType* next(const ContainerNode& current, const Node* stayWithin) { return nextTemplate(current, stayWithin); }
|
| + static ElementType* next(const Node& current, const Node* stayWithin) { return nextTemplate(current, stayWithin); }
|
| + static ElementType* previous(const ContainerNode& current) { return previousTemplate(current); }
|
| + static ElementType* previous(const Node& current) { return previousTemplate(current); }
|
| + static ElementType* previous(const ContainerNode& current, const Node* stayWithin) { return previousTemplate(current, stayWithin); }
|
| + static ElementType* previous(const Node& current, const Node* stayWithin) { return previousTemplate(current, stayWithin); }
|
|
|
| // Like next, but skips children.
|
| - static Element* nextSkippingChildren(const ContainerNode& current) { return traverseNextElementSkippingChildrenTemplate(current); }
|
| - static Element* nextSkippingChildren(const Node& current) { return traverseNextElementSkippingChildrenTemplate(current); }
|
| - static Element* nextSkippingChildren(const ContainerNode& current, const Node* stayWithin) { return traverseNextElementSkippingChildrenTemplate(current, stayWithin); }
|
| - static Element* nextSkippingChildren(const Node& current, const Node* stayWithin) { return traverseNextElementSkippingChildrenTemplate(current, stayWithin); }
|
| + static ElementType* nextSkippingChildren(const ContainerNode& current) { return nextSkippingChildrenTemplate(current); }
|
| + static ElementType* nextSkippingChildren(const Node& current) { return nextSkippingChildrenTemplate(current); }
|
| + static ElementType* nextSkippingChildren(const ContainerNode& current, const Node* stayWithin) { return nextSkippingChildrenTemplate(current, stayWithin); }
|
| + static ElementType* nextSkippingChildren(const Node& current, const Node* stayWithin) { return nextSkippingChildrenTemplate(current, stayWithin); }
|
|
|
| // Pre-order traversal including the pseudo-elements.
|
| - static Element* previousIncludingPseudo(const Node&, const Node* stayWithin = 0);
|
| - static Element* nextIncludingPseudo(const Node&, const Node* stayWithin = 0);
|
| - static Element* nextIncludingPseudoSkippingChildren(const Node&, const Node* stayWithin = 0);
|
| + static ElementType* previousIncludingPseudo(const Node&, const Node* stayWithin = 0);
|
| + static ElementType* nextIncludingPseudo(const Node&, const Node* stayWithin = 0);
|
| + static ElementType* nextIncludingPseudoSkippingChildren(const Node&, const Node* stayWithin = 0);
|
|
|
| // Utility function to traverse only the element and pseudo-element siblings of a node.
|
| - static Element* pseudoAwarePreviousSibling(const Node&);
|
| + static ElementType* pseudoAwarePreviousSibling(const Node&);
|
|
|
| // Previous / Next sibling.
|
| - static Element* previousSibling(const Node&);
|
| - static Element* nextSibling(const Node&);
|
| + static ElementType* previousSibling(const Node&);
|
| + static ElementType* nextSibling(const Node&);
|
|
|
| private:
|
| template <class NodeType>
|
| - static Element* firstElementWithinTemplate(NodeType&);
|
| + static ElementType* firstChildTemplate(NodeType&);
|
| + template <class NodeType>
|
| + static ElementType* lastChildTemplate(NodeType&);
|
| + template <class NodeType>
|
| + static ElementType* firstWithinTemplate(NodeType&);
|
| + template <class NodeType>
|
| + static ElementType* lastWithinTemplate(NodeType&);
|
| + template <class NodeType>
|
| + static ElementType* nextTemplate(NodeType&);
|
| template <class NodeType>
|
| - static Element* lastWithinTemplate(NodeType&);
|
| + static ElementType* nextTemplate(NodeType&, const Node* stayWithin);
|
| template <class NodeType>
|
| - static Element* traverseNextElementTemplate(NodeType&);
|
| + static ElementType* previousTemplate(NodeType&);
|
| template <class NodeType>
|
| - static Element* traverseNextElementTemplate(NodeType&, const Node* stayWithin);
|
| + static ElementType* previousTemplate(NodeType&, const Node* stayWithin);
|
| template <class NodeType>
|
| - static Element* traverseNextElementSkippingChildrenTemplate(NodeType&);
|
| + static ElementType* nextSkippingChildrenTemplate(NodeType&);
|
| template <class NodeType>
|
| - static Element* traverseNextElementSkippingChildrenTemplate(NodeType&, const Node* stayWithin);
|
| + static ElementType* nextSkippingChildrenTemplate(NodeType&, const Node* stayWithin);
|
| };
|
|
|
| +typedef Traversal<Element> ElementTraversal;
|
| +
|
| +// Specialized for pure Element to exploit the fact that Elements parent is always either another Element or the root.
|
| +template <>
|
| template <class NodeType>
|
| -inline Element* ElementTraversal::firstElementWithinTemplate(NodeType& current)
|
| +inline Element* Traversal<Element>::firstWithinTemplate(NodeType& current)
|
| {
|
| - // Except for the root containers, only elements can have element children.
|
| - Node* node = current.firstChild();
|
| - while (node && !node->isElementNode())
|
| - node = node->nextSibling();
|
| - return toElement(node);
|
| + return firstChildTemplate(current);
|
| }
|
|
|
| +template <>
|
| template <class NodeType>
|
| -inline Element* ElementTraversal::lastWithinTemplate(NodeType& current)
|
| +inline Element* Traversal<Element>::lastWithinTemplate(NodeType& current)
|
| {
|
| - Node* node = current.lastChild();
|
| - while (node && !node->isElementNode())
|
| - node = node->previousSibling();
|
| - return toElement(node);
|
| + return lastChildTemplate(current);
|
| }
|
|
|
| +template <>
|
| template <class NodeType>
|
| -inline Element* ElementTraversal::traverseNextElementTemplate(NodeType& current)
|
| +inline Element* Traversal<Element>::nextTemplate(NodeType& current)
|
| {
|
| Node* node = NodeTraversal::next(current);
|
| while (node && !node->isElementNode())
|
| @@ -106,8 +125,9 @@ inline Element* ElementTraversal::traverseNextElementTemplate(NodeType& current)
|
| return toElement(node);
|
| }
|
|
|
| +template <>
|
| template <class NodeType>
|
| -inline Element* ElementTraversal::traverseNextElementTemplate(NodeType& current, const Node* stayWithin)
|
| +inline Element* Traversal<Element>::nextTemplate(NodeType& current, const Node* stayWithin)
|
| {
|
| Node* node = NodeTraversal::next(current, stayWithin);
|
| while (node && !node->isElementNode())
|
| @@ -115,70 +135,179 @@ inline Element* ElementTraversal::traverseNextElementTemplate(NodeType& current,
|
| return toElement(node);
|
| }
|
|
|
| +template <>
|
| template <class NodeType>
|
| -inline Element* ElementTraversal::traverseNextElementSkippingChildrenTemplate(NodeType& current)
|
| +inline Element* Traversal<Element>::previousTemplate(NodeType& current)
|
| {
|
| - Node* node = NodeTraversal::nextSkippingChildren(current);
|
| + Node* node = NodeTraversal::previous(current);
|
| while (node && !node->isElementNode())
|
| - node = NodeTraversal::nextSkippingChildren(*node);
|
| + node = NodeTraversal::previous(*node);
|
| return toElement(node);
|
| }
|
|
|
| +template <>
|
| template <class NodeType>
|
| -inline Element* ElementTraversal::traverseNextElementSkippingChildrenTemplate(NodeType& current, const Node* stayWithin)
|
| +inline Element* Traversal<Element>::previousTemplate(NodeType& current, const Node* stayWithin)
|
| {
|
| - Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin);
|
| + Node* node = NodeTraversal::previous(current, stayWithin);
|
| while (node && !node->isElementNode())
|
| - node = NodeTraversal::nextSkippingChildren(*node, stayWithin);
|
| + node = NodeTraversal::previous(*node, stayWithin);
|
| return toElement(node);
|
| }
|
|
|
| -inline Element* ElementTraversal::previousIncludingPseudo(const Node& current, const Node* stayWithin)
|
| +// Generic versions.
|
| +template <class ElementType>
|
| +template <class NodeType>
|
| +inline ElementType* Traversal<ElementType>::firstChildTemplate(NodeType& current)
|
| +{
|
| + Node* node = current.firstChild();
|
| + while (node && !isElementOfType<const ElementType>(*node))
|
| + node = node->nextSibling();
|
| + return toElement<ElementType>(node);
|
| +}
|
| +
|
| +template <class ElementType>
|
| +template <class NodeType>
|
| +inline ElementType* Traversal<ElementType>::lastChildTemplate(NodeType& current)
|
| +{
|
| + Node* node = current.lastChild();
|
| + while (node && !isElementOfType<const ElementType>(*node))
|
| + node = node->previousSibling();
|
| + return toElement<ElementType>(node);
|
| +}
|
| +
|
| +template <class ElementType>
|
| +template <class NodeType>
|
| +inline ElementType* Traversal<ElementType>::firstWithinTemplate(NodeType& current)
|
| +{
|
| + Element* element = Traversal<Element>::firstWithin(current);
|
| + while (element && !isElementOfType<const ElementType>(*element))
|
| + element = Traversal<Element>::next(*element, ¤t);
|
| + return toElement<ElementType>(element);
|
| +}
|
| +
|
| +template <class ElementType>
|
| +template <class NodeType>
|
| +inline ElementType* Traversal<ElementType>::lastWithinTemplate(NodeType& current)
|
| +{
|
| + Element* element = Traversal<Element>::lastWithin(current);
|
| + while (element && !isElementOfType<const ElementType>(*element))
|
| + element = Traversal<Element>::previous(element, ¤t);
|
| + return toElement<ElementType>(element);
|
| +}
|
| +
|
| +template <class ElementType>
|
| +template <class NodeType>
|
| +inline ElementType* Traversal<ElementType>::nextTemplate(NodeType& current)
|
| +{
|
| + Element* element = Traversal<Element>::next(current);
|
| + while (element && !isElementOfType<const ElementType>(*element))
|
| + element = Traversal<Element>::next(*element);
|
| + return toElement<ElementType>(element);
|
| +}
|
| +
|
| +template <class ElementType>
|
| +template <class NodeType>
|
| +inline ElementType* Traversal<ElementType>::nextTemplate(NodeType& current, const Node* stayWithin)
|
| +{
|
| + Element* element = Traversal<Element>::next(current, stayWithin);
|
| + while (element && !isElementOfType<const ElementType>(*element))
|
| + element = Traversal<Element>::next(*element, stayWithin);
|
| + return toElement<ElementType>(element);
|
| +}
|
| +
|
| +template <class ElementType>
|
| +template <class NodeType>
|
| +inline ElementType* Traversal<ElementType>::previousTemplate(NodeType& current)
|
| +{
|
| + Element* element = Traversal<Element>::previous(current);
|
| + while (element && !isElementOfType<const ElementType>(*element))
|
| + element = Traversal<Element>::previous(*element);
|
| + return toElement<ElementType>(element);
|
| +}
|
| +
|
| +template <class ElementType>
|
| +template <class NodeType>
|
| +inline ElementType* Traversal<ElementType>::previousTemplate(NodeType& current, const Node* stayWithin)
|
| +{
|
| + Element* element = Traversal<Element>::previous(current, stayWithin);
|
| + while (element && !isElementOfType<const ElementType>(*element))
|
| + element = Traversal<Element>::previous(*element, stayWithin);
|
| + return toElement<ElementType>(element);
|
| +}
|
| +
|
| +template <class ElementType>
|
| +template <class NodeType>
|
| +inline ElementType* Traversal<ElementType>::nextSkippingChildrenTemplate(NodeType& current)
|
| +{
|
| + Node* node = NodeTraversal::nextSkippingChildren(current);
|
| + while (node && !isElementOfType<const ElementType>(*node))
|
| + node = NodeTraversal::nextSkippingChildren(*node);
|
| + return toElement<ElementType>(node);
|
| +}
|
| +
|
| +template <class ElementType>
|
| +template <class NodeType>
|
| +inline ElementType* Traversal<ElementType>::nextSkippingChildrenTemplate(NodeType& current, const Node* stayWithin)
|
| +{
|
| + Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin);
|
| + while (node && !isElementOfType<const ElementType>(*node))
|
| + node = NodeTraversal::nextSkippingChildren(*node, stayWithin);
|
| + return toElement<ElementType>(node);
|
| +}
|
| +
|
| +template <class ElementType>
|
| +inline ElementType* Traversal<ElementType>::previousIncludingPseudo(const Node& current, const Node* stayWithin)
|
| {
|
| Node* node = NodeTraversal::previousIncludingPseudo(current, stayWithin);
|
| - while (node && !node->isElementNode())
|
| + while (node && !isElementOfType<const ElementType>(*node))
|
| node = NodeTraversal::previousIncludingPseudo(*node, stayWithin);
|
| - return toElement(node);
|
| + return toElement<ElementType>(node);
|
| }
|
|
|
| -inline Element* ElementTraversal::nextIncludingPseudo(const Node& current, const Node* stayWithin)
|
| +template <class ElementType>
|
| +inline ElementType* Traversal<ElementType>::nextIncludingPseudo(const Node& current, const Node* stayWithin)
|
| {
|
| Node* node = NodeTraversal::nextIncludingPseudo(current, stayWithin);
|
| - while (node && !node->isElementNode())
|
| + while (node && !isElementOfType<const ElementType>(*node))
|
| node = NodeTraversal::nextIncludingPseudo(*node, stayWithin);
|
| - return toElement(node);
|
| + return toElement<ElementType>(node);
|
| }
|
|
|
| -inline Element* ElementTraversal::nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin)
|
| +template <class ElementType>
|
| +inline ElementType* Traversal<ElementType>::nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin)
|
| {
|
| Node* node = NodeTraversal::nextIncludingPseudoSkippingChildren(current, stayWithin);
|
| - while (node && !node->isElementNode())
|
| + while (node && !isElementOfType<const ElementType>(*node))
|
| node = NodeTraversal::nextIncludingPseudoSkippingChildren(*node, stayWithin);
|
| - return toElement(node);
|
| + return toElement<ElementType>(node);
|
| }
|
|
|
| -inline Element* ElementTraversal::pseudoAwarePreviousSibling(const Node& current)
|
| +template <class ElementType>
|
| +inline ElementType* Traversal<ElementType>::pseudoAwarePreviousSibling(const Node& current)
|
| {
|
| Node* node = current.pseudoAwarePreviousSibling();
|
| - while (node && !node->isElementNode())
|
| + while (node && !isElementOfType<const ElementType>(*node))
|
| node = node->pseudoAwarePreviousSibling();
|
| - return toElement(node);
|
| + return toElement<ElementType>(node);
|
| }
|
|
|
| -inline Element* ElementTraversal::previousSibling(const Node& current)
|
| +template <class ElementType>
|
| +inline ElementType* Traversal<ElementType>::previousSibling(const Node& current)
|
| {
|
| Node* node = current.previousSibling();
|
| - while (node && !node->isElementNode())
|
| + while (node && !isElementOfType<const ElementType>(*node))
|
| node = node->previousSibling();
|
| - return toElement(node);
|
| + return toElement<ElementType>(node);
|
| }
|
|
|
| -inline Element* ElementTraversal::nextSibling(const Node& current)
|
| +template <class ElementType>
|
| +inline ElementType* Traversal<ElementType>::nextSibling(const Node& current)
|
| {
|
| Node* node = current.nextSibling();
|
| - while (node && !node->isElementNode())
|
| + while (node && !isElementOfType<const ElementType>(*node))
|
| node = node->nextSibling();
|
| - return toElement(node);
|
| + return toElement<ElementType>(node);
|
| }
|
|
|
| } // namespace WebCore
|
|
|