Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23  */
     24 
     25 #include "config.h"
     26 #include "ClassList.h"
     27 
     28 #include "Element.h"
     29 #include "HTMLNames.h"
     30 #include "HTMLParserIdioms.h"
     31 #include "SpaceSplitString.h"
     32 #include <wtf/text/StringBuilder.h>
     33 
     34 namespace WebCore {
     35 
     36 using namespace HTMLNames;
     37 
     38 ClassList::ClassList(Element* element)
     39     : m_element(element)
     40 {
     41     if (m_element->document()->inQuirksMode())
     42         m_classNamesForQuirksMode.set(m_element->fastGetAttribute(classAttr), false);
     43 }
     44 
     45 void ClassList::ref()
     46 {
     47     m_element->ref();
     48 }
     49 
     50 void ClassList::deref()
     51 {
     52     m_element->deref();
     53 }
     54 
     55 unsigned ClassList::length() const
     56 {
     57     return m_element->hasClass() ? classNames().size() : 0;
     58 }
     59 
     60 const AtomicString ClassList::item(unsigned index) const
     61 {
     62     if (index >= length())
     63         return AtomicString();
     64     return classNames()[index];
     65 }
     66 
     67 bool ClassList::contains(const AtomicString& token, ExceptionCode& ec) const
     68 {
     69     if (!validateToken(token, ec))
     70         return false;
     71     return containsInternal(token);
     72 }
     73 
     74 bool ClassList::containsInternal(const AtomicString& token) const
     75 {
     76     return m_element->hasClass() && classNames().contains(token);
     77 }
     78 
     79 void ClassList::add(const AtomicString& token, ExceptionCode& ec)
     80 {
     81     if (!validateToken(token, ec))
     82         return;
     83     addInternal(token);
     84 }
     85 
     86 void ClassList::addInternal(const AtomicString& token)
     87 {
     88     const AtomicString& oldClassName(m_element->fastGetAttribute(classAttr));
     89     if (oldClassName.isEmpty())
     90         m_element->setAttribute(classAttr, token);
     91     else if (!containsInternal(token)) {
     92         const AtomicString& newClassName(addToken(oldClassName, token));
     93         m_element->setAttribute(classAttr, newClassName);
     94     }
     95 }
     96 
     97 void ClassList::remove(const AtomicString& token, ExceptionCode& ec)
     98 {
     99     if (!validateToken(token, ec))
    100         return;
    101     removeInternal(token);
    102 }
    103 
    104 void ClassList::removeInternal(const AtomicString& token)
    105 {
    106     // Check using contains first since it uses AtomicString comparisons instead
    107     // of character by character testing.
    108     if (!containsInternal(token))
    109         return;
    110     const AtomicString& newClassName(removeToken(m_element->fastGetAttribute(classAttr), token));
    111     m_element->setAttribute(classAttr, newClassName);
    112 }
    113 
    114 bool ClassList::toggle(const AtomicString& token, ExceptionCode& ec)
    115 {
    116     if (!validateToken(token, ec))
    117         return false;
    118 
    119     if (containsInternal(token)) {
    120         removeInternal(token);
    121         return false;
    122     }
    123     addInternal(token);
    124     return true;
    125 }
    126 
    127 String ClassList::toString() const
    128 {
    129     return m_element->fastGetAttribute(classAttr);
    130 }
    131 
    132 void ClassList::reset(const String& newClassName)
    133 {
    134     if (!m_classNamesForQuirksMode.isNull())
    135         m_classNamesForQuirksMode.set(newClassName, false);
    136 }
    137 
    138 const SpaceSplitString& ClassList::classNames() const
    139 {
    140     ASSERT(m_element->hasClass());
    141     if (!m_classNamesForQuirksMode.isNull())
    142         return m_classNamesForQuirksMode;
    143     return m_element->attributeMap()->classNames();
    144 }
    145 
    146 } // namespace WebCore
    147