Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / ElementTraversal.h
index e824182..c5a3906 100644 (file)
@@ -29,7 +29,7 @@
 #include "core/dom/Element.h"
 #include "core/dom/NodeTraversal.h"
 
-namespace WebCore {
+namespace blink {
 
 template <class ElementType>
 class Traversal {
@@ -37,36 +37,46 @@ public:
     // 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); }
+    template <class MatchFunc>
+    static ElementType* firstChild(const ContainerNode&, MatchFunc);
     static ElementType* lastChild(const ContainerNode& current) { return lastChildTemplate(current); }
     static ElementType* lastChild(const Node& current) { return lastChildTemplate(current); }
+    template <class MatchFunc>
+    static ElementType* lastChild(const ContainerNode&, MatchFunc);
 
     // First ElementType ancestor of the node.
     static ElementType* firstAncestor(const Node& current);
     static ElementType* firstAncestorOrSelf(Node& current) { return firstAncestorOrSelfTemplate(current); }
     static ElementType* firstAncestorOrSelf(Element& current) { return firstAncestorOrSelfTemplate(current); }
+    static const ElementType* firstAncestorOrSelf(const Node& current) { return firstAncestorOrSelfTemplate(const_cast<Node&>(current)); }
+    static const ElementType* firstAncestorOrSelf(const Element& current) { return firstAncestorOrSelfTemplate(const_cast<Element&>(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); }
+    template <typename MatchFunc>
+    static ElementType* firstWithin(const ContainerNode&, MatchFunc);
     static ElementType* lastWithin(const ContainerNode& current) { return lastWithinTemplate(current); }
     static ElementType* lastWithin(const Node& current) { return lastWithinTemplate(current); }
+    template <class MatchFunc>
+    static ElementType* lastWithin(const ContainerNode&, MatchFunc);
 
     // Pre-order traversal skipping non-element nodes.
     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); }
+    template <class MatchFunc>
+    static ElementType* next(const ContainerNode& current, const Node* stayWithin, MatchFunc);
+    static ElementType* previous(const Node&);
+    static ElementType* previous(const Node&, const Node* stayWithin);
+    template <class MatchFunc>
+    static ElementType* previous(const ContainerNode& current, const Node* stayWithin, MatchFunc);
 
     // Like next, but skips children.
-    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); }
+    static ElementType* nextSkippingChildren(const Node&);
+    static ElementType* nextSkippingChildren(const Node&, const Node* stayWithin);
 
     // Pre-order traversal including the pseudo-elements.
     static ElementType* previousIncludingPseudo(const Node&, const Node* stayWithin = 0);
@@ -78,7 +88,11 @@ public:
 
     // Previous / Next sibling.
     static ElementType* previousSibling(const Node&);
+    template <class MatchFunc>
+    static ElementType* previousSibling(const Node&, MatchFunc);
     static ElementType* nextSibling(const Node&);
+    template <class MatchFunc>
+    static ElementType* nextSibling(const Node&, MatchFunc);
 
 private:
     template <class NodeType>
@@ -95,14 +109,6 @@ private:
     static ElementType* nextTemplate(NodeType&);
     template <class NodeType>
     static ElementType* nextTemplate(NodeType&, const Node* stayWithin);
-    template <class NodeType>
-    static ElementType* previousTemplate(NodeType&);
-    template <class NodeType>
-    static ElementType* previousTemplate(NodeType&, const Node* stayWithin);
-    template <class NodeType>
-    static ElementType* nextSkippingChildrenTemplate(NodeType&);
-    template <class NodeType>
-    static ElementType* nextSkippingChildrenTemplate(NodeType&, const Node* stayWithin);
 };
 
 typedef Traversal<Element> ElementTraversal;
@@ -117,16 +123,6 @@ inline Element* Traversal<Element>::firstWithinTemplate(NodeType& current)
 
 template <>
 template <class NodeType>
-inline Element* Traversal<Element>::lastWithinTemplate(NodeType& current)
-{
-    Node* node = NodeTraversal::lastWithin(current);
-    while (node && !node->isElementNode())
-        node = NodeTraversal::previous(*node, &current);
-    return toElement(node);
-}
-
-template <>
-template <class NodeType>
 inline Element* Traversal<Element>::nextTemplate(NodeType& current)
 {
     Node* node = NodeTraversal::next(current);
@@ -145,26 +141,6 @@ inline Element* Traversal<Element>::nextTemplate(NodeType& current, const Node*
     return toElement(node);
 }
 
-template <>
-template <class NodeType>
-inline Element* Traversal<Element>::previousTemplate(NodeType& current)
-{
-    Node* node = NodeTraversal::previous(current);
-    while (node && !node->isElementNode())
-        node = NodeTraversal::previous(*node);
-    return toElement(node);
-}
-
-template <>
-template <class NodeType>
-inline Element* Traversal<Element>::previousTemplate(NodeType& current, const Node* stayWithin)
-{
-    Node* node = NodeTraversal::previous(current, stayWithin);
-    while (node && !node->isElementNode())
-        node = NodeTraversal::previous(*node, stayWithin);
-    return toElement(node);
-}
-
 // Generic versions.
 template <class ElementType>
 template <class NodeType>
@@ -177,6 +153,16 @@ inline ElementType* Traversal<ElementType>::firstChildTemplate(NodeType& current
 }
 
 template <class ElementType>
+template <class MatchFunc>
+inline ElementType* Traversal<ElementType>::firstChild(const ContainerNode& current, MatchFunc isMatch)
+{
+    ElementType* element = Traversal<ElementType>::firstChild(current);
+    while (element && !isMatch(*element))
+        element = Traversal<ElementType>::nextSibling(*element);
+    return element;
+}
+
+template <class ElementType>
 inline ElementType* Traversal<ElementType>::firstAncestor(const Node& current)
 {
     ContainerNode* ancestor = current.parentNode();
@@ -205,68 +191,115 @@ inline ElementType* Traversal<ElementType>::lastChildTemplate(NodeType& current)
 }
 
 template <class ElementType>
+template <class MatchFunc>
+inline ElementType* Traversal<ElementType>::lastChild(const ContainerNode& current, MatchFunc isMatch)
+{
+    ElementType* element = Traversal<ElementType>::lastChild(current);
+    while (element && !isMatch(*element))
+        element = Traversal<ElementType>::previousSibling(*element);
+    return element;
+}
+
+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, &current);
-    return toElement<ElementType>(element);
+    Node* node = current.firstChild();
+    while (node && !isElementOfType<const ElementType>(*node))
+        node = NodeTraversal::next(*node, &current);
+    return toElement<ElementType>(node);
+}
+
+template <class ElementType>
+template <typename MatchFunc>
+inline ElementType* Traversal<ElementType>::firstWithin(const ContainerNode& current, MatchFunc isMatch)
+{
+    ElementType* element = Traversal<ElementType>::firstWithin(current);
+    while (element && !isMatch(*element))
+        element = Traversal<ElementType>::next(*element, &current, isMatch);
+    return 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, &current);
-    return toElement<ElementType>(element);
+    Node* node = NodeTraversal::lastWithin(current);
+    while (node && !isElementOfType<const ElementType>(*node))
+        node = NodeTraversal::previous(*node, &current);
+    return toElement<ElementType>(node);
+}
+
+template <class ElementType>
+template <class MatchFunc>
+inline ElementType* Traversal<ElementType>::lastWithin(const ContainerNode& current, MatchFunc isMatch)
+{
+    ElementType* element = Traversal<ElementType>::lastWithin(current);
+    while (element && !isMatch(*element))
+        element = Traversal<ElementType>::previous(*element, &current, isMatch);
+    return 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);
+    Node* node = NodeTraversal::next(current);
+    while (node && !isElementOfType<const ElementType>(*node))
+        node = NodeTraversal::next(*node);
+    return toElement<ElementType>(node);
 }
 
 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);
+    Node* node = NodeTraversal::next(current, stayWithin);
+    while (node && !isElementOfType<const ElementType>(*node))
+        node = NodeTraversal::next(*node, stayWithin);
+    return toElement<ElementType>(node);
 }
 
 template <class ElementType>
-template <class NodeType>
-inline ElementType* Traversal<ElementType>::previousTemplate(NodeType& current)
+template <class MatchFunc>
+inline ElementType* Traversal<ElementType>::next(const ContainerNode& current, const Node* stayWithin, MatchFunc isMatch)
 {
-    Element* element = Traversal<Element>::previous(current);
-    while (element && !isElementOfType<const ElementType>(*element))
-        element = Traversal<Element>::previous(*element);
-    return toElement<ElementType>(element);
+    ElementType* element = Traversal<ElementType>::next(current, stayWithin);
+    while (element && !isMatch(*element))
+        element = Traversal<ElementType>::next(*element, stayWithin);
+    return element;
 }
 
 template <class ElementType>
-template <class NodeType>
-inline ElementType* Traversal<ElementType>::previousTemplate(NodeType& current, const Node* stayWithin)
+inline ElementType* Traversal<ElementType>::previous(const Node& current)
+{
+    Node* node = NodeTraversal::previous(current);
+    while (node && !isElementOfType<const ElementType>(*node))
+        node = NodeTraversal::previous(*node);
+    return toElement<ElementType>(node);
+}
+
+template <class ElementType>
+inline ElementType* Traversal<ElementType>::previous(const Node& 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);
+    Node* node = NodeTraversal::previous(current, stayWithin);
+    while (node && !isElementOfType<const ElementType>(*node))
+        node = NodeTraversal::previous(*node, stayWithin);
+    return toElement<ElementType>(node);
 }
 
 template <class ElementType>
-template <class NodeType>
-inline ElementType* Traversal<ElementType>::nextSkippingChildrenTemplate(NodeType& current)
+template <class MatchFunc>
+inline ElementType* Traversal<ElementType>::previous(const ContainerNode& current, const Node* stayWithin, MatchFunc isMatch)
+{
+    ElementType* element = Traversal<ElementType>::previous(current, stayWithin);
+    while (element && !isMatch(*element))
+        element = Traversal<ElementType>::previous(*element, stayWithin);
+    return element;
+}
+
+template <class ElementType>
+inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node& current)
 {
     Node* node = NodeTraversal::nextSkippingChildren(current);
     while (node && !isElementOfType<const ElementType>(*node))
@@ -275,8 +308,7 @@ inline ElementType* Traversal<ElementType>::nextSkippingChildrenTemplate(NodeTyp
 }
 
 template <class ElementType>
-template <class NodeType>
-inline ElementType* Traversal<ElementType>::nextSkippingChildrenTemplate(NodeType& current, const Node* stayWithin)
+inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node& current, const Node* stayWithin)
 {
     Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin);
     while (node && !isElementOfType<const ElementType>(*node))
@@ -330,6 +362,16 @@ inline ElementType* Traversal<ElementType>::previousSibling(const Node& current)
 }
 
 template <class ElementType>
+template <class MatchFunc>
+inline ElementType* Traversal<ElementType>::previousSibling(const Node& current, MatchFunc isMatch)
+{
+    ElementType* element = Traversal<ElementType>::previousSibling(current);
+    while (element && !isMatch(*element))
+        element = Traversal<ElementType>::previousSibling(*element);
+    return element;
+}
+
+template <class ElementType>
 inline ElementType* Traversal<ElementType>::nextSibling(const Node& current)
 {
     Node* node = current.nextSibling();
@@ -338,6 +380,16 @@ inline ElementType* Traversal<ElementType>::nextSibling(const Node& current)
     return toElement<ElementType>(node);
 }
 
-} // namespace WebCore
+template <class ElementType>
+template <class MatchFunc>
+inline ElementType* Traversal<ElementType>::nextSibling(const Node& current, MatchFunc isMatch)
+{
+    ElementType* element = Traversal<ElementType>::nextSibling(current);
+    while (element && !isMatch(*element))
+        element = Traversal<ElementType>::nextSibling(*element);
+    return element;
+}
+
+} // namespace blink
 
 #endif