2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
5 * Copyright (C) 2014 Samsung Electronics. All rights reserved.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 #ifndef HTMLCollection_h
25 #define HTMLCollection_h
27 #include "core/dom/LiveNodeListBase.h"
28 #include "core/html/CollectionIndexCache.h"
29 #include "core/html/CollectionType.h"
30 #include "wtf/Forward.h"
31 #include "wtf/HashMap.h"
32 #include "wtf/Vector.h"
36 class HTMLCollection : public ScriptWrappable, public RefCounted<HTMLCollection>, public LiveNodeListBase {
38 enum ItemAfterOverrideType {
40 DoesNotOverrideItemAfter,
43 static PassRefPtr<HTMLCollection> create(ContainerNode& base, CollectionType);
44 virtual ~HTMLCollection();
45 virtual void invalidateCache(Document* oldDocument = 0) const OVERRIDE;
46 void invalidateCacheForAttribute(const QualifiedName*) const;
49 unsigned length() const { return m_collectionIndexCache.nodeCount(*this); }
50 Element* item(unsigned offset) const { return m_collectionIndexCache.nodeAt(*this, offset); }
51 virtual Element* namedItem(const AtomicString& name) const;
52 bool namedPropertyQuery(const AtomicString&, ExceptionState&);
53 void namedPropertyEnumerator(Vector<String>& names, ExceptionState&);
56 void namedItems(const AtomicString& name, Vector<RefPtr<Element> >&) const;
57 bool isEmpty() const { return m_collectionIndexCache.isEmpty(*this); }
58 bool hasExactlyOneItem() const { return m_collectionIndexCache.hasExactlyOneNode(*this); }
60 // CollectionIndexCache API.
61 bool canTraverseBackward() const { return !overridesItemAfter(); }
62 Element* traverseToFirstElement() const;
63 Element* traverseToLastElement() const;
64 Element* traverseForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const;
65 Element* traverseBackwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const;
68 HTMLCollection(ContainerNode& base, CollectionType, ItemAfterOverrideType);
70 class NamedItemCache {
72 static PassOwnPtr<NamedItemCache> create()
74 return adoptPtr(new NamedItemCache);
77 Vector<Element*>* getElementsById(const AtomicString& id) const { return m_idCache.get(id.impl()); }
78 Vector<Element*>* getElementsByName(const AtomicString& name) const { return m_nameCache.get(name.impl()); }
79 void addElementWithId(const AtomicString& id, Element* element) { addElementToMap(m_idCache, id, element); }
80 void addElementWithName(const AtomicString& name, Element* element) { addElementToMap(m_nameCache, name, element); }
84 typedef HashMap<StringImpl*, OwnPtr<Vector<Element*> > > StringToElementsMap;
85 static void addElementToMap(StringToElementsMap& map, const AtomicString& key, Element* element)
87 OwnPtr<Vector<Element*> >& vector = map.add(key.impl(), nullptr).storedValue->value;
89 vector = adoptPtr(new Vector<Element*>);
90 vector->append(element);
93 StringToElementsMap m_idCache;
94 StringToElementsMap m_nameCache;
97 bool overridesItemAfter() const { return m_overridesItemAfter; }
98 virtual Element* virtualItemAfter(Element*) const;
99 bool shouldOnlyIncludeDirectChildren() const { return m_shouldOnlyIncludeDirectChildren; }
100 virtual void supportedPropertyNames(Vector<String>& names);
102 virtual void updateIdNameCache() const;
103 bool hasValidIdNameCache() const { return m_namedItemCache; }
105 void setNamedItemCache(PassOwnPtr<NamedItemCache> cache) const
107 ASSERT(!m_namedItemCache);
108 document().incrementNodeListWithIdNameCacheCount();
109 m_namedItemCache = cache;
112 NamedItemCache& namedItemCache() const
114 ASSERT(m_namedItemCache);
115 return *m_namedItemCache;
119 Element* traverseNextElement(Element& previous) const;
121 void invalidateIdNameCacheMaps(Document* oldDocument = 0) const
123 if (!hasValidIdNameCache())
126 // Make sure we decrement the NodeListWithIdNameCache count from
127 // the old document instead of the new one in the case the collection
128 // is moved to a new document.
129 unregisterIdNameCacheFromDocument(oldDocument ? *oldDocument : document());
131 m_namedItemCache.clear();
134 void unregisterIdNameCacheFromDocument(Document& document) const
136 ASSERT(hasValidIdNameCache());
137 document.decrementNodeListWithIdNameCacheCount();
140 const unsigned m_overridesItemAfter : 1;
141 const unsigned m_shouldOnlyIncludeDirectChildren : 1;
142 mutable OwnPtr<NamedItemCache> m_namedItemCache;
143 mutable CollectionIndexCache<HTMLCollection, Element> m_collectionIndexCache;
146 DEFINE_TYPE_CASTS(HTMLCollection, LiveNodeListBase, collection, isHTMLCollectionType(collection->type()), isHTMLCollectionType(collection.type()));
148 inline void HTMLCollection::invalidateCacheForAttribute(const QualifiedName* attrName) const
150 if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName))
152 else if (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr)
153 invalidateIdNameCacheMaps();