Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies)
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  *
     19  */
     20 
     21 #include "config.h"
     22 #include "core/html/HTMLDetailsElement.h"
     23 
     24 #include "HTMLNames.h"
     25 #include "bindings/v8/ExceptionStatePlaceholder.h"
     26 #include "core/dom/NodeRenderingContext.h"
     27 #include "core/dom/Text.h"
     28 #include "core/dom/shadow/ShadowRoot.h"
     29 #include "core/html/HTMLSummaryElement.h"
     30 #include "core/html/shadow/HTMLContentElement.h"
     31 #include "core/platform/LocalizedStrings.h"
     32 #include "core/rendering/RenderBlock.h"
     33 
     34 namespace WebCore {
     35 
     36 using namespace HTMLNames;
     37 
     38 PassRefPtr<HTMLDetailsElement> HTMLDetailsElement::create(const QualifiedName& tagName, Document* document)
     39 {
     40     RefPtr<HTMLDetailsElement> details = adoptRef(new HTMLDetailsElement(tagName, document));
     41     details->ensureUserAgentShadowRoot();
     42     return details.release();
     43 }
     44 
     45 HTMLDetailsElement::HTMLDetailsElement(const QualifiedName& tagName, Document* document)
     46     : HTMLElement(tagName, document)
     47     , m_isOpen(false)
     48 {
     49     ASSERT(hasTagName(detailsTag));
     50     ScriptWrappable::init(this);
     51 }
     52 
     53 RenderObject* HTMLDetailsElement::createRenderer(RenderStyle*)
     54 {
     55     return new RenderBlock(this);
     56 }
     57 
     58 void HTMLDetailsElement::didAddUserAgentShadowRoot(ShadowRoot* root)
     59 {
     60     DEFINE_STATIC_LOCAL(AtomicString, summarySelector, ("summary:first-of-type", AtomicString::ConstructFromLiteral));
     61 
     62     RefPtr<HTMLSummaryElement> defaultSummary = HTMLSummaryElement::create(summaryTag, document());
     63     defaultSummary->appendChild(Text::create(document(), defaultDetailsSummaryText()), ASSERT_NO_EXCEPTION);
     64 
     65     RefPtr<HTMLContentElement> content = HTMLContentElement::create(document());
     66     content->setAttribute(selectAttr, summarySelector);
     67     content->appendChild(defaultSummary);
     68 
     69     root->appendChild(content, ASSERT_NO_EXCEPTION, AttachLazily);
     70     root->appendChild(HTMLContentElement::create(document()), ASSERT_NO_EXCEPTION, AttachLazily);
     71 }
     72 
     73 Element* HTMLDetailsElement::findMainSummary() const
     74 {
     75     for (Node* child = firstChild(); child; child = child->nextSibling()) {
     76         if (child->hasTagName(summaryTag))
     77             return toElement(child);
     78     }
     79 
     80     HTMLContentElement* content = toHTMLContentElement(userAgentShadowRoot()->firstChild());
     81     ASSERT(content->firstChild() && content->firstChild()->hasTagName(summaryTag));
     82     return toElement(content->firstChild());
     83 }
     84 
     85 void HTMLDetailsElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
     86 {
     87     if (name == openAttr) {
     88         bool oldValue = m_isOpen;
     89         m_isOpen = !value.isNull();
     90         if (oldValue != m_isOpen)
     91             lazyReattachIfAttached();
     92     } else
     93         HTMLElement::parseAttribute(name, value);
     94 }
     95 
     96 bool HTMLDetailsElement::childShouldCreateRenderer(const NodeRenderingContext& childContext) const
     97 {
     98     if (m_isOpen)
     99         return HTMLElement::childShouldCreateRenderer(childContext);
    100     if (!childContext.node()->hasTagName(summaryTag))
    101         return false;
    102     return childContext.node() == findMainSummary() && HTMLElement::childShouldCreateRenderer(childContext);
    103 }
    104 
    105 void HTMLDetailsElement::toggleOpen()
    106 {
    107     setAttribute(openAttr, m_isOpen ? nullAtom : emptyAtom);
    108 }
    109 
    110 }
    111