Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 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/HTMLSummaryElement.h"
     23 
     24 #include "HTMLNames.h"
     25 #include "bindings/v8/ExceptionStatePlaceholder.h"
     26 #include "core/dom/KeyboardEvent.h"
     27 #include "core/dom/NodeRenderingContext.h"
     28 #include "core/dom/shadow/ShadowRoot.h"
     29 #include "core/html/HTMLDetailsElement.h"
     30 #include "core/html/shadow/DetailsMarkerControl.h"
     31 #include "core/html/shadow/HTMLContentElement.h"
     32 #include "core/rendering/RenderBlock.h"
     33 
     34 namespace WebCore {
     35 
     36 using namespace HTMLNames;
     37 
     38 PassRefPtr<HTMLSummaryElement> HTMLSummaryElement::create(const QualifiedName& tagName, Document* document)
     39 {
     40     RefPtr<HTMLSummaryElement> summary = adoptRef(new HTMLSummaryElement(tagName, document));
     41     summary->ensureUserAgentShadowRoot();
     42     return summary.release();
     43 }
     44 
     45 HTMLSummaryElement::HTMLSummaryElement(const QualifiedName& tagName, Document* document)
     46     : HTMLElement(tagName, document)
     47 {
     48     ASSERT(hasTagName(summaryTag));
     49 }
     50 
     51 RenderObject* HTMLSummaryElement::createRenderer(RenderStyle*)
     52 {
     53     return new RenderBlock(this);
     54 }
     55 
     56 void HTMLSummaryElement::didAddUserAgentShadowRoot(ShadowRoot* root)
     57 {
     58     root->appendChild(DetailsMarkerControl::create(document()), ASSERT_NO_EXCEPTION, AttachLazily);
     59     root->appendChild(HTMLContentElement::create(document()), ASSERT_NO_EXCEPTION, AttachLazily);
     60 }
     61 
     62 HTMLDetailsElement* HTMLSummaryElement::detailsElement() const
     63 {
     64     Node* parent = NodeRenderingTraversal::parent(this);
     65     if (parent && isHTMLDetailsElement(parent))
     66         return toHTMLDetailsElement(parent);
     67     return 0;
     68 }
     69 
     70 bool HTMLSummaryElement::isMainSummary() const
     71 {
     72     if (HTMLDetailsElement* details = detailsElement())
     73         return details->findMainSummary() == this;
     74 
     75     return false;
     76 }
     77 
     78 static bool isClickableControl(Node* node)
     79 {
     80     if (!node->isElementNode())
     81         return false;
     82     Element* element = toElement(node);
     83     if (element->isFormControlElement())
     84         return true;
     85     Element* host = element->shadowHost();
     86     return host && host->isFormControlElement();
     87 }
     88 
     89 bool HTMLSummaryElement::supportsFocus() const
     90 {
     91     return isMainSummary();
     92 }
     93 
     94 void HTMLSummaryElement::defaultEventHandler(Event* event)
     95 {
     96     if (isMainSummary() && renderer()) {
     97         if (event->type() == eventNames().DOMActivateEvent && !isClickableControl(event->target()->toNode())) {
     98             if (HTMLDetailsElement* details = detailsElement())
     99                 details->toggleOpen();
    100             event->setDefaultHandled();
    101             return;
    102         }
    103 
    104         if (event->isKeyboardEvent()) {
    105             if (event->type() == eventNames().keydownEvent && toKeyboardEvent(event)->keyIdentifier() == "U+0020") {
    106                 setActive(true, true);
    107                 // No setDefaultHandled() - IE dispatches a keypress in this case.
    108                 return;
    109             }
    110             if (event->type() == eventNames().keypressEvent) {
    111                 switch (toKeyboardEvent(event)->charCode()) {
    112                 case '\r':
    113                     dispatchSimulatedClick(event);
    114                     event->setDefaultHandled();
    115                     return;
    116                 case ' ':
    117                     // Prevent scrolling down the page.
    118                     event->setDefaultHandled();
    119                     return;
    120                 }
    121             }
    122             if (event->type() == eventNames().keyupEvent && toKeyboardEvent(event)->keyIdentifier() == "U+0020") {
    123                 if (active())
    124                     dispatchSimulatedClick(event);
    125                 event->setDefaultHandled();
    126                 return;
    127             }
    128         }
    129     }
    130 
    131     HTMLElement::defaultEventHandler(event);
    132 }
    133 
    134 bool HTMLSummaryElement::willRespondToMouseClickEvents()
    135 {
    136     if (isMainSummary() && renderer())
    137         return true;
    138 
    139     return HTMLElement::willRespondToMouseClickEvents();
    140 }
    141 
    142 }
    143