Index: Source/core/html/HTMLCollection.cpp |
diff --git a/Source/core/html/HTMLCollection.cpp b/Source/core/html/HTMLCollection.cpp |
index 6402d501849435ac64123ad87c3b3f89c9e09bd0..e9852fd019d507cc420b8ce4e06ba05a9d88bc8d 100644 |
--- a/Source/core/html/HTMLCollection.cpp |
+++ b/Source/core/html/HTMLCollection.cpp |
@@ -255,43 +255,53 @@ static inline bool isMatchingHTMLElement(const HTMLCollection& htmlCollection, c |
return false; |
} |
-template <class NodeListType> |
-inline bool isMatchingElement(const NodeListType&, const Element&); |
- |
-template <> inline bool isMatchingElement(const HTMLCollection& htmlCollection, const Element& element) |
+inline bool HTMLCollection::elementMatches(const Element& element) const |
{ |
// These collections apply to any kind of Elements, not just HTMLElements. |
- switch (htmlCollection.type()) { |
+ switch (type()) { |
case DocAll: |
case NodeChildren: |
return true; |
case ClassCollectionType: |
- return toClassCollection(htmlCollection).elementMatches(element); |
+ return toClassCollection(*this).elementMatches(element); |
case TagCollectionType: |
- return toTagCollection(htmlCollection).elementMatches(element); |
+ return toTagCollection(*this).elementMatches(element); |
case HTMLTagCollectionType: |
- return toHTMLTagCollection(htmlCollection).elementMatches(element); |
+ return toHTMLTagCollection(*this).elementMatches(element); |
case DocumentNamedItems: |
- return toDocumentNameCollection(htmlCollection).elementMatches(element); |
+ return toDocumentNameCollection(*this).elementMatches(element); |
case WindowNamedItems: |
- return toWindowNameCollection(htmlCollection).elementMatches(element); |
+ return toWindowNameCollection(*this).elementMatches(element); |
default: |
break; |
} |
// The following only applies to HTMLElements. |
- return element.isHTMLElement() && isMatchingHTMLElement(htmlCollection, toHTMLElement(element)); |
+ return element.isHTMLElement() && isMatchingHTMLElement(*this, toHTMLElement(element)); |
} |
-template <> inline bool isMatchingElement(const ClassCollection& collection, const Element& element) |
-{ |
- return collection.elementMatches(element); |
-} |
+namespace { |
-template <> inline bool isMatchingElement(const HTMLTagCollection& collection, const Element& element) |
-{ |
- return collection.elementMatches(element); |
-} |
+template <class HTMLCollectionType> |
+class IsMatch { |
+public: |
+ IsMatch(const HTMLCollectionType& list) |
+ : m_list(list) |
+ { } |
+ |
+ bool operator() (const Element& element) const |
+ { |
+ return m_list.elementMatches(element); |
+ } |
+ |
+private: |
+ const HTMLCollectionType& m_list; |
+}; |
+ |
+} // namespace |
+ |
+template <class HTMLCollectionType> |
+static inline IsMatch<HTMLCollectionType> makeIsMatch(const HTMLCollectionType& list) { return IsMatch<HTMLCollectionType>(list); } |
Element* HTMLCollection::virtualItemAfter(Element*) const |
{ |
@@ -318,53 +328,19 @@ static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element) |
|| element.hasTagName(selectTag); |
} |
-inline Element* firstMatchingChildElement(const HTMLCollection& nodeList) |
-{ |
- Element* element = ElementTraversal::firstChild(nodeList.rootNode()); |
- while (element && !isMatchingElement(nodeList, *element)) |
- element = ElementTraversal::nextSibling(*element); |
- return element; |
-} |
- |
-inline Element* lastMatchingChildElement(const HTMLCollection& nodeList) |
-{ |
- Element* element = ElementTraversal::lastChild(nodeList.rootNode()); |
- while (element && !isMatchingElement(nodeList, *element)) |
- element = ElementTraversal::previousSibling(*element); |
- return element; |
-} |
- |
-inline Element* nextMatchingChildElement(const HTMLCollection& nodeList, Element& current) |
-{ |
- Element* next = ¤t; |
- do { |
- next = ElementTraversal::nextSibling(*next); |
- } while (next && !isMatchingElement(nodeList, *next)); |
- return next; |
-} |
- |
-inline Element* previousMatchingChildElement(const HTMLCollection& nodeList, Element& current) |
-{ |
- Element* previous = ¤t; |
- do { |
- previous = ElementTraversal::previousSibling(*previous); |
- } while (previous && !isMatchingElement(nodeList, *previous)); |
- return previous; |
-} |
- |
Element* HTMLCollection::traverseToFirstElement() const |
{ |
switch (type()) { |
case HTMLTagCollectionType: |
- return firstMatchingElement(toHTMLTagCollection(*this)); |
+ return ElementTraversal::firstWithin(rootNode(), makeIsMatch(toHTMLTagCollection(*this))); |
case ClassCollectionType: |
- return firstMatchingElement(toClassCollection(*this)); |
+ return ElementTraversal::firstWithin(rootNode(), makeIsMatch(toClassCollection(*this))); |
default: |
if (overridesItemAfter()) |
return virtualItemAfter(0); |
if (shouldOnlyIncludeDirectChildren()) |
- return firstMatchingChildElement(*this); |
- return firstMatchingElement(*this); |
+ return ElementTraversal::firstChild(rootNode(), makeIsMatch(*this)); |
+ return ElementTraversal::firstWithin(rootNode(), makeIsMatch(*this)); |
} |
} |
@@ -372,8 +348,8 @@ Element* HTMLCollection::traverseToLastElement() const |
{ |
ASSERT(canTraverseBackward()); |
if (shouldOnlyIncludeDirectChildren()) |
- return lastMatchingChildElement(*this); |
- return lastMatchingElement(*this); |
+ return ElementTraversal::lastChild(rootNode(), makeIsMatch(*this)); |
+ return ElementTraversal::lastWithin(rootNode(), makeIsMatch(*this)); |
} |
Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const |
@@ -381,9 +357,9 @@ Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre |
ASSERT(currentOffset < offset); |
switch (type()) { |
case HTMLTagCollectionType: |
- return traverseMatchingElementsForwardToOffset(toHTMLTagCollection(*this), offset, currentElement, currentOffset); |
+ return traverseMatchingElementsForwardToOffset(currentElement, &rootNode(), offset, currentOffset, makeIsMatch(toHTMLTagCollection(*this))); |
case ClassCollectionType: |
- return traverseMatchingElementsForwardToOffset(toClassCollection(*this), offset, currentElement, currentOffset); |
+ return traverseMatchingElementsForwardToOffset(currentElement, &rootNode(), offset, currentOffset, makeIsMatch(toClassCollection(*this))); |
default: |
if (overridesItemAfter()) { |
for (Element* next = virtualItemAfter(¤tElement); next; next = virtualItemAfter(next)) { |
@@ -393,13 +369,14 @@ Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre |
return 0; |
} |
if (shouldOnlyIncludeDirectChildren()) { |
- for (Element* next = nextMatchingChildElement(*this, currentElement); next; next = nextMatchingChildElement(*this, *next)) { |
+ IsMatch<HTMLCollection> isMatch(*this); |
+ for (Element* next = ElementTraversal::nextSibling(currentElement, isMatch); next; next = ElementTraversal::nextSibling(*next, isMatch)) { |
if (++currentOffset == offset) |
return next; |
} |
return 0; |
} |
- return traverseMatchingElementsForwardToOffset(*this, offset, currentElement, currentOffset); |
+ return traverseMatchingElementsForwardToOffset(currentElement, &rootNode(), offset, currentOffset, makeIsMatch(*this)); |
} |
} |
@@ -408,13 +385,14 @@ Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& curr |
ASSERT(currentOffset > offset); |
ASSERT(canTraverseBackward()); |
if (shouldOnlyIncludeDirectChildren()) { |
- for (Element* previous = previousMatchingChildElement(*this, currentElement); previous; previous = previousMatchingChildElement(*this, *previous)) { |
+ IsMatch<HTMLCollection> isMatch(*this); |
+ for (Element* previous = ElementTraversal::previousSibling(currentElement, isMatch); previous; previous = ElementTraversal::previousSibling(*previous, isMatch)) { |
if (--currentOffset == offset) |
return previous; |
} |
return 0; |
} |
- return traverseMatchingElementsBackwardToOffset(*this, offset, currentElement, currentOffset); |
+ return traverseMatchingElementsBackwardToOffset(currentElement, &rootNode(), offset, currentOffset, makeIsMatch(*this)); |
} |
Element* HTMLCollection::namedItem(const AtomicString& name) const |