1 /* 2 * Copyright (c) 2012 Motorola Mobility, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY MOTOROLA MOBILITY, INC. AND ITS CONTRIBUTORS 14 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY, INC. OR ITS 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "core/html/RadioNodeList.h" 28 29 #include "core/HTMLNames.h" 30 #include "core/InputTypeNames.h" 31 #include "core/dom/Element.h" 32 #include "core/dom/NodeRareData.h" 33 #include "core/html/HTMLFormElement.h" 34 #include "core/html/HTMLImageElement.h" 35 #include "core/html/HTMLInputElement.h" 36 #include "core/html/HTMLObjectElement.h" 37 38 namespace blink { 39 40 using namespace HTMLNames; 41 42 RadioNodeList::RadioNodeList(ContainerNode& rootNode, const AtomicString& name, CollectionType type) 43 : LiveNodeList(rootNode, type, InvalidateForFormControls, isHTMLFormElement(rootNode) ? NodeListIsRootedAtDocument : NodeListIsRootedAtNode) 44 , m_name(name) 45 { 46 } 47 48 RadioNodeList::~RadioNodeList() 49 { 50 #if !ENABLE(OILPAN) 51 ownerNode().nodeLists()->removeCache(this, type(), m_name); 52 #endif 53 } 54 55 static inline HTMLInputElement* toRadioButtonInputElement(Element& element) 56 { 57 if (!isHTMLInputElement(element)) 58 return 0; 59 HTMLInputElement& inputElement = toHTMLInputElement(element); 60 if (inputElement.type() != InputTypeNames::radio || inputElement.value().isEmpty()) 61 return 0; 62 return &inputElement; 63 } 64 65 String RadioNodeList::value() const 66 { 67 if (shouldOnlyMatchImgElements()) 68 return String(); 69 unsigned length = this->length(); 70 for (unsigned i = 0; i < length; ++i) { 71 const HTMLInputElement* inputElement = toRadioButtonInputElement(*item(i)); 72 if (!inputElement || !inputElement->checked()) 73 continue; 74 return inputElement->value(); 75 } 76 return String(); 77 } 78 79 void RadioNodeList::setValue(const String& value) 80 { 81 if (shouldOnlyMatchImgElements()) 82 return; 83 unsigned length = this->length(); 84 for (unsigned i = 0; i < length; ++i) { 85 HTMLInputElement* inputElement = toRadioButtonInputElement(*item(i)); 86 if (!inputElement || inputElement->value() != value) 87 continue; 88 inputElement->setChecked(true); 89 return; 90 } 91 } 92 93 bool RadioNodeList::matchesByIdOrName(const Element& testElement) const 94 { 95 return testElement.getIdAttribute() == m_name || testElement.getNameAttribute() == m_name; 96 } 97 98 bool RadioNodeList::checkElementMatchesRadioNodeListFilter(const Element& testElement) const 99 { 100 ASSERT(!shouldOnlyMatchImgElements()); 101 ASSERT(isHTMLObjectElement(testElement) || testElement.isFormControlElement()); 102 if (isHTMLFormElement(ownerNode())) { 103 HTMLFormElement* formElement = toHTMLElement(testElement).formOwner(); 104 if (!formElement || formElement != ownerNode()) 105 return false; 106 } 107 108 return matchesByIdOrName(testElement); 109 } 110 111 bool RadioNodeList::elementMatches(const Element& element) const 112 { 113 if (shouldOnlyMatchImgElements()) { 114 if (!isHTMLImageElement(element)) 115 return false; 116 117 if (toHTMLImageElement(element).formOwner() != ownerNode()) 118 return false; 119 120 return matchesByIdOrName(element); 121 } 122 123 if (!isHTMLObjectElement(element) && !element.isFormControlElement()) 124 return false; 125 126 if (isHTMLInputElement(element) && toHTMLInputElement(element).type() == InputTypeNames::image) 127 return false; 128 129 return checkElementMatchesRadioNodeListFilter(element); 130 } 131 132 } // namespace 133