Remove HTMLContentElement
[WebKit-https.git] / Source / WebCore / html / HTMLSummaryElement.cpp
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 "HTMLSummaryElement.h"
23
24 #if ENABLE(DETAILS_ELEMENT)
25 #include "DetailsMarkerControl.h"
26 #include "HTMLDetailsElement.h"
27 #include "HTMLNames.h"
28 #include "InsertionPoint.h"
29 #include "KeyboardEvent.h"
30 #include "MouseEvent.h"
31 #include "NodeRenderingTraversal.h"
32 #include "PlatformMouseEvent.h"
33 #include "RenderBlockFlow.h"
34 #include "ShadowRoot.h"
35
36 namespace WebCore {
37
38 using namespace HTMLNames;
39
40 class SummaryContentElement : public InsertionPoint {
41 public:
42     static PassRefPtr<SummaryContentElement> create(Document&);
43
44 private:
45     SummaryContentElement(Document& document)
46         : InsertionPoint(webkitShadowContentTag, document)
47     {
48     }
49 };
50
51 PassRefPtr<SummaryContentElement> SummaryContentElement::create(Document& document)
52 {
53     return adoptRef(new SummaryContentElement(document));
54 }
55
56 PassRefPtr<HTMLSummaryElement> HTMLSummaryElement::create(const QualifiedName& tagName, Document& document)
57 {
58     RefPtr<HTMLSummaryElement> summary = adoptRef(new HTMLSummaryElement(tagName, document));
59     summary->ensureUserAgentShadowRoot();
60     return summary.release();
61 }
62
63 HTMLSummaryElement::HTMLSummaryElement(const QualifiedName& tagName, Document& document)
64     : HTMLElement(tagName, document)
65 {
66     ASSERT(hasTagName(summaryTag));
67 }
68
69 RenderElement* HTMLSummaryElement::createRenderer(RenderArena& arena, RenderStyle&)
70 {
71     return new (arena) RenderBlockFlow(this);
72 }
73
74 bool HTMLSummaryElement::childShouldCreateRenderer(const Node* child) const
75 {
76     if (child->isPseudoElement())
77         return HTMLElement::childShouldCreateRenderer(child);
78
79     return hasShadowRootOrActiveInsertionPointParent(child) && HTMLElement::childShouldCreateRenderer(child);
80 }
81
82 void HTMLSummaryElement::didAddUserAgentShadowRoot(ShadowRoot* root)
83 {
84     root->appendChild(DetailsMarkerControl::create(document()), ASSERT_NO_EXCEPTION, AttachLazily);
85     root->appendChild(SummaryContentElement::create(document()), ASSERT_NO_EXCEPTION, AttachLazily);
86 }
87
88 HTMLDetailsElement* HTMLSummaryElement::detailsElement() const
89 {
90     Node* mayDetails = NodeRenderingTraversal::parent(this);
91     if (!mayDetails || !mayDetails->hasTagName(detailsTag))
92         return 0;
93     return static_cast<HTMLDetailsElement*>(mayDetails);
94 }
95
96 bool HTMLSummaryElement::isMainSummary() const
97 {
98     if (HTMLDetailsElement* details = detailsElement())
99         return details->findMainSummary() == this;
100
101     return false;
102 }
103
104 static bool isClickableControl(Node* node)
105 {
106     if (!node->isElementNode())
107         return false;
108     Element* element = toElement(node);
109     if (element->isFormControlElement())
110         return true;
111     Element* host = element->shadowHost();
112     return host && host->isFormControlElement();
113 }
114
115 bool HTMLSummaryElement::supportsFocus() const
116 {
117     return isMainSummary();
118 }
119
120 void HTMLSummaryElement::defaultEventHandler(Event* event)
121 {
122     if (isMainSummary() && renderer()) {
123         if (event->type() == eventNames().DOMActivateEvent && !isClickableControl(event->target()->toNode())) {
124             if (HTMLDetailsElement* details = detailsElement())
125                 details->toggleOpen();
126             event->setDefaultHandled();
127             return;
128         }
129
130         if (event->isKeyboardEvent()) {
131             if (event->type() == eventNames().keydownEvent && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "U+0020") {
132                 setActive(true, true);
133                 // No setDefaultHandled() - IE dispatches a keypress in this case.
134                 return;
135             }
136             if (event->type() == eventNames().keypressEvent) {
137                 switch (static_cast<KeyboardEvent*>(event)->charCode()) {
138                 case '\r':
139                     dispatchSimulatedClick(event);
140                     event->setDefaultHandled();
141                     return;
142                 case ' ':
143                     // Prevent scrolling down the page.
144                     event->setDefaultHandled();
145                     return;
146                 }
147             }
148             if (event->type() == eventNames().keyupEvent && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "U+0020") {
149                 if (active())
150                     dispatchSimulatedClick(event);
151                 event->setDefaultHandled();
152                 return;
153             }
154         }
155     }
156
157     HTMLElement::defaultEventHandler(event);
158 }
159
160 bool HTMLSummaryElement::willRespondToMouseClickEvents()
161 {
162     if (isMainSummary() && renderer())
163         return true;
164
165     return HTMLElement::willRespondToMouseClickEvents();
166 }
167
168 }
169
170 #endif