15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2005, 2011 Apple Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010 Google Inc. All rights reserved. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 2306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/html/forms/RadioInputType.h" 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 255d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/HTMLNames.h" 265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/InputTypeNames.h" 2776c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)#include "core/dom/Document.h" 28d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/dom/ElementTraversal.h" 2906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/KeyboardEvent.h" 3006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/MouseEvent.h" 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLInputElement.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/SpatialNavigation.h" 331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/text/PlatformLocale.h" 34e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/PassOwnPtr.h" 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 36c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 38197021e6b966cfb06891637935ef33fff06433d1Ben Murdochnamespace { 39197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 40197021e6b966cfb06891637935ef33fff06433d1Ben MurdochHTMLElement* nextElement(const HTMLElement& element, bool forward) 41197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{ 42197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch return forward ? Traversal<HTMLElement>::next(element) : Traversal<HTMLElement>::previous(element); 43197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} 44197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 45197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch} // namespace 46197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames; 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 49323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)PassRefPtrWillBeRawPtr<InputType> RadioInputType::create(HTMLInputElement& element) 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 51323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) return adoptRefWillBeNoop(new RadioInputType(element)); 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const AtomicString& RadioInputType::formControlType() const 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 5651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return InputTypeNames::radio; 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RadioInputType::valueMissing(const String&) const 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 61bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) return element().isInRequiredRadioButtonGroup() && !element().checkedRadioButtonForGroup(); 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String RadioInputType::valueMissingText() const 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 6651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return locale().queryString(blink::WebLocalizedString::ValidationValueMissingForRadio); 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RadioInputType::handleClickEvent(MouseEvent* event) 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) event->setDefaultHandled(); 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RadioInputType::handleKeydownEvent(KeyboardEvent* event) 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) BaseCheckableInputType::handleKeydownEvent(event); 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (event->defaultHandled()) 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const String& key = event->keyIdentifier(); 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (key != "Up" && key != "Down" && key != "Left" && key != "Right") 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Left and up mean "previous radio button". 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Right and down mean "next radio button". 8506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) // Tested in WinIE, and even for RTL, left still means previous radio button 8606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) // (and so moves to the right). Seems strange, but we'll match it. However, 8706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) // when using Spatial Navigation, we need to be able to navigate without 8806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) // changing the selection. 89bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) Document& document = element().document(); 908abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) if (isSpatialNavigationEnabled(document.frame())) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool forward = (key == "Down" || key == "Right"); 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We can only stay within the form's children if the form hasn't been demoted to a leaf because 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // of malformed HTML. 96197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch for (HTMLElement* htmlElement = nextElement(element(), forward); htmlElement; htmlElement = nextElement(*htmlElement, forward)) { 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Once we encounter a form element, we know we're through. 98d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (isHTMLFormElement(*htmlElement)) 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Look for more radio buttons. 101d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!isHTMLInputElement(*htmlElement)) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 103d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) HTMLInputElement* inputElement = toHTMLInputElement(htmlElement); 104bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) if (inputElement->form() != element().form()) 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 1067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (inputElement->type() == InputTypeNames::radio && inputElement->name() == element().name() && inputElement->isFocusable()) { 107d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) RefPtrWillBeRawPtr<HTMLInputElement> protector(inputElement); 1088abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) document.setFocusedElement(inputElement); 10951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) inputElement->dispatchSimulatedClick(event, SendNoEvents); 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) event->setDefaultHandled(); 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RadioInputType::handleKeyupEvent(KeyboardEvent* event) 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const String& key = event->keyIdentifier(); 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (key != "U+0020") 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If an unselected radio is tabbed into (because the entire group has nothing 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // checked, or because of some explicit .focus() call), then allow space to check it. 123bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) if (element().checked()) 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) dispatchSimulatedClickIfActive(event); 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 128f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)bool RadioInputType::isKeyboardFocusable() const 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 130f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) if (!InputType::isKeyboardFocusable()) 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // When using Spatial Navigation, every radio button should be focusable. 134bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) if (isSpatialNavigationEnabled(element().document().frame())) 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) // Never allow keyboard tabbing to leave you in the same radio group. Always 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // skip any other elements in the group. 139bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) Element* currentFocusedElement = element().document().focusedElement(); 140d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (isHTMLInputElement(currentFocusedElement)) { 141d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) HTMLInputElement& focusedInput = toHTMLInputElement(*currentFocusedElement); 1427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (focusedInput.type() == InputTypeNames::radio && focusedInput.form() == element().form() && focusedInput.name() == element().name()) 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Allow keyboard focus if we're checked or if nothing in the group is checked. 147bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) return element().checked() || !element().checkedRadioButtonForGroup(); 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RadioInputType::shouldSendChangeEventAfterCheckedChanged() 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Don't send a change event for a radio button that's getting unchecked. 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This was done to match the behavior of other browsers. 154bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) return element().checked(); 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 157f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)PassOwnPtrWillBeRawPtr<ClickHandlingState> RadioInputType::willDispatchClick() 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // An event handler can use preventDefault or "return false" to reverse the selection we do here. 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The ClickHandlingState object contains what we need to undo what we did here in didDispatchClick. 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We want radio groups to end up in sane states, i.e., to have something checked. 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Therefore if nothing is currently selected, we won't allow the upcoming action to be "undone", since 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // we want some object in the radio group to actually get selected. 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 166f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) OwnPtrWillBeRawPtr<ClickHandlingState> state = adoptPtrWillBeNoop(new ClickHandlingState); 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 168bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) state->checked = element().checked(); 169bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) state->checkedRadioButton = element().checkedRadioButtonForGroup(); 170bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) element().setChecked(true, DispatchChangeEvent); 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return state.release(); 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RadioInputType::didDispatchClick(Event* event, const ClickHandlingState& state) 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (event->defaultPrevented() || event->defaultHandled()) { 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Restore the original selected radio button if possible. 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Make sure it is still a radio button and only do the restoration if it still belongs to our group. 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) HTMLInputElement* checkedRadioButton = state.checkedRadioButton.get(); 1817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (!checkedRadioButton) 1827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci element().setChecked(false); 1837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci else if (checkedRadioButton->type() == InputTypeNames::radio 184bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) && checkedRadioButton->form() == element().form() 1857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci && checkedRadioButton->name() == element().name()) 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) checkedRadioButton->setChecked(true); 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The work we did in willDispatchClick was default handling. 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) event->setDefaultHandled(); 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccibool RadioInputType::shouldAppearIndeterminate() const 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return !element().checkedRadioButtonForGroup(); 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 198c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 199