1/* 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) 7 * 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. 12 * 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. 17 * 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. 22 * 23 */ 24 25#include "config.h" 26#include "HTMLLabelElement.h" 27 28#include "Document.h" 29#include "ElementIterator.h" 30#include "Event.h" 31#include "EventNames.h" 32#include "FormAssociatedElement.h" 33#include "HTMLNames.h" 34 35namespace WebCore { 36 37using namespace HTMLNames; 38 39static LabelableElement* nodeAsSupportedLabelableElement(Node* node) 40{ 41 if (!node || !isLabelableElement(*node)) 42 return nullptr; 43 LabelableElement& element = toLabelableElement(*node); 44 return element.supportLabels() ? &element : nullptr; 45} 46 47inline HTMLLabelElement::HTMLLabelElement(const QualifiedName& tagName, Document& document) 48 : HTMLElement(tagName, document) 49{ 50 ASSERT(hasTagName(labelTag)); 51} 52 53PassRefPtr<HTMLLabelElement> HTMLLabelElement::create(const QualifiedName& tagName, Document& document) 54{ 55 return adoptRef(new HTMLLabelElement(tagName, document)); 56} 57 58bool HTMLLabelElement::isFocusable() const 59{ 60 return false; 61} 62 63LabelableElement* HTMLLabelElement::control() 64{ 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 (auto& labelableElement : descendantsOfType<LabelableElement>(*this)) { 71 if (labelableElement.supportLabels()) 72 return &labelableElement; 73 } 74 return nullptr; 75 } 76 77 // Find the first element whose id is controlId. If it is found and it is a labelable form control, 78 // return it, otherwise return 0. 79 return nodeAsSupportedLabelableElement(treeScope().getElementById(controlId)); 80} 81 82HTMLFormElement* HTMLLabelElement::form() const 83{ 84 return FormAssociatedElement::findAssociatedForm(this, 0); 85} 86 87void HTMLLabelElement::setActive(bool down, bool pause) 88{ 89 if (down == active()) 90 return; 91 92 // Update our status first. 93 HTMLElement::setActive(down, pause); 94 95 // Also update our corresponding control. 96 if (HTMLElement* element = control()) 97 element->setActive(down, pause); 98} 99 100void HTMLLabelElement::setHovered(bool over) 101{ 102 if (over == hovered()) 103 return; 104 105 // Update our status first. 106 HTMLElement::setHovered(over); 107 108 // Also update our corresponding control. 109 if (HTMLElement* element = control()) 110 element->setHovered(over); 111} 112 113void HTMLLabelElement::defaultEventHandler(Event* evt) 114{ 115 static bool processingClick = false; 116 117 if (evt->type() == eventNames().clickEvent && !processingClick) { 118 RefPtr<HTMLElement> element = control(); 119 120 // If we can't find a control or if the control received the click 121 // event, then there's no need for us to do anything. 122 if (!element || (evt->target() && element->containsIncludingShadowDOM(evt->target()->toNode()))) 123 return; 124 125 processingClick = true; 126 127 // Click the corresponding control. 128 element->dispatchSimulatedClick(evt); 129 130 document().updateLayoutIgnorePendingStylesheets(); 131 if (element->isMouseFocusable()) 132 element->focus(); 133 134 processingClick = false; 135 136 evt->setDefaultHandled(); 137 } 138 139 HTMLElement::defaultEventHandler(evt); 140} 141 142bool HTMLLabelElement::willRespondToMouseClickEvents() 143{ 144 return (control() && control()->willRespondToMouseClickEvents()) || HTMLElement::willRespondToMouseClickEvents(); 145} 146 147void HTMLLabelElement::focus(bool, FocusDirection direction) 148{ 149 // to match other browsers, always restore previous selection 150 if (HTMLElement* element = control()) 151 element->focus(true, direction); 152} 153 154void HTMLLabelElement::accessKeyAction(bool sendMouseEvents) 155{ 156 if (HTMLElement* element = control()) 157 element->accessKeyAction(sendMouseEvents); 158 else 159 HTMLElement::accessKeyAction(sendMouseEvents); 160} 161 162} // namespace 163