1 /* 2 * This file is part of the WebKit project. 3 * 4 * Copyright (C) 2009 Michelangelo De Simone <micdesim (at) gmail.com> 5 * Copyright (C) 2010 Apple Inc. All rights reserved. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public License 18 * along with this library; see the file COPYING.LIB. If not, write to 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 * 22 */ 23 24 #include "config.h" 25 #include "ValidityState.h" 26 27 #include "HTMLInputElement.h" 28 #include "HTMLNames.h" 29 #include "HTMLSelectElement.h" 30 #include "HTMLTextAreaElement.h" 31 #include "HTMLTreeBuilder.h" 32 #include "LocalizedStrings.h" 33 #include <wtf/StdLibExtras.h> 34 35 namespace WebCore { 36 37 using namespace HTMLNames; 38 39 String ValidityState::validationMessage() const 40 { 41 if (!toHTMLElement(m_control)->willValidate()) 42 return String(); 43 44 if (customError()) 45 return m_customErrorMessage; 46 HTMLElement* element = toHTMLElement(m_control); 47 bool isInputElement = element->isFormControlElement() && element->hasTagName(inputTag); 48 bool isTextAreaElement = element->isFormControlElement() && element->hasTagName(textareaTag); 49 // The order of the following checks is meaningful. e.g. We'd like to show the 50 // valueMissing message even if the control has other validation errors. 51 if (valueMissing()) { 52 if (element->hasTagName(selectTag)) 53 return validationMessageValueMissingForSelectText(); 54 if (isInputElement) 55 return static_cast<HTMLInputElement*>(element)->valueMissingText(); 56 return validationMessageValueMissingText(); 57 } 58 if (typeMismatch()) { 59 if (isInputElement) 60 return static_cast<HTMLInputElement*>(element)->typeMismatchText(); 61 return validationMessageTypeMismatchText(); 62 } 63 if (patternMismatch()) 64 return validationMessagePatternMismatchText(); 65 if (tooLong()) { 66 if (!isInputElement && !isTextAreaElement) { 67 ASSERT_NOT_REACHED(); 68 return String(); 69 } 70 HTMLTextFormControlElement* text = static_cast<HTMLTextFormControlElement*>(element); 71 return validationMessageTooLongText(numGraphemeClusters(text->value()), text->maxLength()); 72 } 73 if (rangeUnderflow()) { 74 if (!isInputElement) { 75 ASSERT_NOT_REACHED(); 76 return String(); 77 } 78 return validationMessageRangeUnderflowText(static_cast<HTMLInputElement*>(element)->minimumString()); 79 } 80 if (rangeOverflow()) { 81 if (!isInputElement) { 82 ASSERT_NOT_REACHED(); 83 return String(); 84 } 85 return validationMessageRangeOverflowText(static_cast<HTMLInputElement*>(element)->maximumString()); 86 } 87 if (stepMismatch()) { 88 if (!isInputElement) { 89 ASSERT_NOT_REACHED(); 90 return String(); 91 } 92 HTMLInputElement* input = static_cast<HTMLInputElement*>(element); 93 return validationMessageStepMismatchText(input->stepBaseString(), input->stepString()); 94 } 95 96 return String(); 97 } 98 99 void ValidityState::setCustomErrorMessage(const String& message) 100 { 101 m_customErrorMessage = message; 102 if (m_control->isFormControlElement()) 103 static_cast<HTMLFormControlElement*>(m_control)->setNeedsValidityCheck(); 104 } 105 106 bool ValidityState::valueMissing() const 107 { 108 HTMLElement* element = toHTMLElement(m_control); 109 if (!element->willValidate()) 110 return false; 111 112 if (element->hasTagName(inputTag)) { 113 HTMLInputElement* input = static_cast<HTMLInputElement*>(element); 114 return input->valueMissing(input->value()); 115 } 116 if (element->hasTagName(textareaTag)) { 117 HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(element); 118 return textArea->valueMissing(textArea->value()); 119 } 120 if (element->hasTagName(selectTag)) { 121 HTMLSelectElement* select = static_cast<HTMLSelectElement*>(element); 122 return select->valueMissing(); 123 } 124 return false; 125 } 126 127 bool ValidityState::typeMismatch() const 128 { 129 HTMLElement* element = toHTMLElement(m_control); 130 if (!element->willValidate()) 131 return false; 132 133 if (!element->hasTagName(inputTag)) 134 return false; 135 return static_cast<HTMLInputElement*>(element)->typeMismatch(); 136 } 137 138 bool ValidityState::patternMismatch() const 139 { 140 HTMLElement* element = toHTMLElement(m_control); 141 if (!element->willValidate()) 142 return false; 143 144 if (!element->hasTagName(inputTag)) 145 return false; 146 HTMLInputElement* input = static_cast<HTMLInputElement*>(element); 147 return input->patternMismatch(input->value()); 148 } 149 150 bool ValidityState::tooLong() const 151 { 152 HTMLElement* element = toHTMLElement(m_control); 153 if (!element->willValidate()) 154 return false; 155 156 if (element->hasTagName(inputTag)) { 157 HTMLInputElement* input = static_cast<HTMLInputElement*>(element); 158 return input->tooLong(input->value(), HTMLTextFormControlElement::CheckDirtyFlag); 159 } 160 if (element->hasTagName(textareaTag)) { 161 HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(element); 162 return textArea->tooLong(textArea->value(), HTMLTextFormControlElement::CheckDirtyFlag); 163 } 164 return false; 165 } 166 167 bool ValidityState::rangeUnderflow() const 168 { 169 HTMLElement* element = toHTMLElement(m_control); 170 if (!element->willValidate()) 171 return false; 172 173 if (!element->hasTagName(inputTag)) 174 return false; 175 HTMLInputElement* input = static_cast<HTMLInputElement*>(element); 176 return input->rangeUnderflow(input->value()); 177 } 178 179 bool ValidityState::rangeOverflow() const 180 { 181 HTMLElement* element = toHTMLElement(m_control); 182 if (!element->willValidate()) 183 return false; 184 185 if (!element->hasTagName(inputTag)) 186 return false; 187 HTMLInputElement* input = static_cast<HTMLInputElement*>(element); 188 return input->rangeOverflow(input->value()); 189 } 190 191 bool ValidityState::stepMismatch() const 192 { 193 HTMLElement* element = toHTMLElement(m_control); 194 if (!element->willValidate()) 195 return false; 196 197 if (!element->hasTagName(inputTag)) 198 return false; 199 HTMLInputElement* input = static_cast<HTMLInputElement*>(element); 200 return input->stepMismatch(input->value()); 201 } 202 203 bool ValidityState::customError() const 204 { 205 HTMLElement* element = toHTMLElement(m_control); 206 return element->willValidate() && !m_customErrorMessage.isEmpty(); 207 } 208 209 bool ValidityState::valid() const 210 { 211 bool someError = typeMismatch() || stepMismatch() || rangeUnderflow() || rangeOverflow() 212 || tooLong() || patternMismatch() || valueMissing() || customError(); 213 return !someError; 214 } 215 216 } // namespace 217