Home | History | Annotate | Download | only in html
      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