2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reserved.
6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
26 #include "core/html/HTMLLabelElement.h"
28 #include "HTMLNames.h"
29 #include "core/dom/ElementTraversal.h"
30 #include "core/events/Event.h"
31 #include "core/html/FormAssociatedElement.h"
35 using namespace HTMLNames;
37 static bool supportsLabels(const Element& element)
39 if (!element.isHTMLElement())
41 if (!toHTMLElement(element).isLabelable())
43 return toLabelableElement(element).supportLabels();
46 inline HTMLLabelElement::HTMLLabelElement(Document& document)
47 : HTMLElement(labelTag, document)
49 ScriptWrappable::init(this);
52 PassRefPtrWillBeRawPtr<HTMLLabelElement> HTMLLabelElement::create(Document& document)
54 return adoptRefWillBeRefCountedGarbageCollected(new HTMLLabelElement(document));
57 bool HTMLLabelElement::rendererIsFocusable() const
59 HTMLLabelElement* that = const_cast<HTMLLabelElement*>(this);
60 return that->isContentEditable();
63 LabelableElement* HTMLLabelElement::control() const
65 const AtomicString& controlId = getAttribute(forAttr);
66 if (controlId.isNull()) {
67 // Search the children and descendants of the label element for a form element.
68 // per http://dev.w3.org/html5/spec/Overview.html#the-label-element
69 // the form element must be "labelable form-associated element".
70 for (Element* element = ElementTraversal::next(*this, this); element; element = ElementTraversal::next(*element, this)) {
71 if (!supportsLabels(*element))
73 return toLabelableElement(element);
78 if (Element* element = treeScope().getElementById(controlId)) {
79 if (supportsLabels(*element))
80 return toLabelableElement(element);
86 HTMLFormElement* HTMLLabelElement::formOwner() const
88 return FormAssociatedElement::findAssociatedForm(this);
91 void HTMLLabelElement::setActive(bool down)
96 // Update our status first.
97 HTMLElement::setActive(down);
99 // Also update our corresponding control.
100 if (HTMLElement* element = control())
101 element->setActive(down);
104 void HTMLLabelElement::setHovered(bool over)
106 if (over == hovered())
109 // Update our status first.
110 HTMLElement::setHovered(over);
112 // Also update our corresponding control.
113 if (HTMLElement* element = control())
114 element->setHovered(over);
117 bool HTMLLabelElement::isInteractiveContent() const
122 bool HTMLLabelElement::isInInteractiveContent(Node* node) const
124 if (!containsIncludingShadowDOM(node))
126 while (node && this != node) {
127 if (node->isHTMLElement() && toHTMLElement(node)->isInteractiveContent())
129 node = node->parentOrShadowHostNode();
134 void HTMLLabelElement::defaultEventHandler(Event* evt)
136 static bool processingClick = false;
138 if (evt->type() == EventTypeNames::click && !processingClick) {
139 RefPtr<HTMLElement> element = control();
141 // If we can't find a control or if the control received the click
142 // event, then there's no need for us to do anything.
143 if (!element || (evt->target() && element->containsIncludingShadowDOM(evt->target()->toNode())))
146 if (evt->target() && isInInteractiveContent(evt->target()->toNode()))
149 processingClick = true;
151 document().updateLayoutIgnorePendingStylesheets();
152 if (element->isMouseFocusable())
153 element->focus(true, FocusTypeMouse);
155 // Click the corresponding control.
156 element->dispatchSimulatedClick(evt);
158 processingClick = false;
160 evt->setDefaultHandled();
163 HTMLElement::defaultEventHandler(evt);
166 bool HTMLLabelElement::willRespondToMouseClickEvents()
168 if (control() && control()->willRespondToMouseClickEvents())
171 return HTMLElement::willRespondToMouseClickEvents();
174 void HTMLLabelElement::focus(bool, FocusType type)
176 // to match other browsers, always restore previous selection
177 if (HTMLElement* element = control())
178 element->focus(true, type);
180 HTMLElement::focus(true, type);
183 void HTMLLabelElement::accessKeyAction(bool sendMouseEvents)
185 if (HTMLElement* element = control())
186 element->accessKeyAction(sendMouseEvents);
188 HTMLElement::accessKeyAction(sendMouseEvents);