Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 2011 Google Inc. All Rights Reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "TreeScope.h"
     28 
     29 #include "Element.h"
     30 #include "HTMLAnchorElement.h"
     31 #include "HTMLMapElement.h"
     32 #include "HTMLNames.h"
     33 #include "NodeRareData.h"
     34 
     35 namespace WebCore {
     36 
     37 using namespace HTMLNames;
     38 
     39 TreeScope::TreeScope(Document* document, ConstructionType constructionType)
     40     : ContainerNode(0, constructionType)
     41     , m_parentTreeScope(0)
     42     , m_accessKeyMapValid(false)
     43     , m_numNodeListCaches(0)
     44 {
     45     m_document = document;
     46     if (document != this) {
     47         // Assume document as parent scope
     48         m_parentTreeScope = document;
     49         // FIXME: This branch should be inert until shadow scopes are landed.
     50         ASSERT_NOT_REACHED();
     51     }
     52 }
     53 
     54 TreeScope::~TreeScope()
     55 {
     56     if (hasRareData())
     57         rareData()->setTreeScope(0);
     58 }
     59 
     60 void TreeScope::destroyTreeScopeData()
     61 {
     62     m_elementsById.clear();
     63     m_imageMapsByName.clear();
     64     m_elementsByAccessKey.clear();
     65 }
     66 
     67 void TreeScope::setParentTreeScope(TreeScope* newParentScope)
     68 {
     69     // A document node cannot be re-parented.
     70     ASSERT(!isDocumentNode());
     71     // Every scope other than document needs a parent scope.
     72     ASSERT(m_parentTreeScope);
     73     ASSERT(newParentScope);
     74 
     75     m_parentTreeScope = newParentScope;
     76 }
     77 
     78 Element* TreeScope::getElementById(const AtomicString& elementId) const
     79 {
     80     if (elementId.isEmpty())
     81         return 0;
     82     return m_elementsById.getElementById(elementId.impl(), this);
     83 }
     84 
     85 void TreeScope::addElementById(const AtomicString& elementId, Element* element)
     86 {
     87     m_elementsById.add(elementId.impl(), element);
     88 }
     89 
     90 void TreeScope::removeElementById(const AtomicString& elementId, Element* element)
     91 {
     92     m_elementsById.remove(elementId.impl(), element);
     93 }
     94 
     95 Element* TreeScope::getElementByAccessKey(const String& key) const
     96 {
     97     if (key.isEmpty())
     98         return 0;
     99     if (!m_accessKeyMapValid) {
    100         for (Node* n = firstChild(); n; n = n->traverseNextNode()) {
    101             if (!n->isElementNode())
    102                 continue;
    103             Element* element = static_cast<Element*>(n);
    104             const AtomicString& accessKey = element->getAttribute(accesskeyAttr);
    105             if (!accessKey.isEmpty())
    106                 m_elementsByAccessKey.set(accessKey.impl(), element);
    107         }
    108         m_accessKeyMapValid = true;
    109     }
    110     return m_elementsByAccessKey.get(key.impl());
    111 }
    112 
    113 void TreeScope::invalidateAccessKeyMap()
    114 {
    115     m_accessKeyMapValid = false;
    116     m_elementsByAccessKey.clear();
    117 }
    118 
    119 void TreeScope::addImageMap(HTMLMapElement* imageMap)
    120 {
    121     AtomicStringImpl* name = imageMap->getName().impl();
    122     if (!name)
    123         return;
    124     m_imageMapsByName.add(name, imageMap);
    125 }
    126 
    127 void TreeScope::removeImageMap(HTMLMapElement* imageMap)
    128 {
    129     AtomicStringImpl* name = imageMap->getName().impl();
    130     if (!name)
    131         return;
    132     m_imageMapsByName.remove(name, imageMap);
    133 }
    134 
    135 HTMLMapElement* TreeScope::getImageMap(const String& url) const
    136 {
    137     if (url.isNull())
    138         return 0;
    139     size_t hashPos = url.find('#');
    140     String name = (hashPos == notFound ? url : url.substring(hashPos + 1)).impl();
    141     if (document()->isHTMLDocument())
    142         return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByLowercasedMapName(AtomicString(name.lower()).impl(), this));
    143     return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByMapName(AtomicString(name).impl(), this));
    144 }
    145 
    146 Element* TreeScope::findAnchor(const String& name)
    147 {
    148     if (name.isEmpty())
    149         return 0;
    150     if (Element* element = getElementById(name))
    151         return element;
    152     for (Node* node = this; node; node = node->traverseNextNode()) {
    153         if (node->hasTagName(aTag)) {
    154             HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(node);
    155             if (document()->inQuirksMode()) {
    156                 // Quirks mode, case insensitive comparison of names.
    157                 if (equalIgnoringCase(anchor->name(), name))
    158                     return anchor;
    159             } else {
    160                 // Strict mode, names need to match exactly.
    161                 if (anchor->name() == name)
    162                     return anchor;
    163             }
    164         }
    165     }
    166     return 0;
    167 }
    168 
    169 } // namespace WebCore
    170 
    171