WebCore/html/HTMLInputElement.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     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, 2008, 2009, 2010 Apple Inc. All rights reserved.
       
     6  *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
       
     7  * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
       
     8  * Copyright (C) 2010 Google Inc. All rights reserved.
       
     9  *
       
    10  * This library is free software; you can redistribute it and/or
       
    11  * modify it under the terms of the GNU Library General Public
       
    12  * License as published by the Free Software Foundation; either
       
    13  * version 2 of the License, or (at your option) any later version.
       
    14  *
       
    15  * This library is distributed in the hope that it will be useful,
       
    16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    18  * Library General Public License for more details.
       
    19  *
       
    20  * You should have received a copy of the GNU Library General Public License
       
    21  * along with this library; see the file COPYING.LIB.  If not, write to
       
    22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    23  * Boston, MA 02110-1301, USA.
       
    24  *
       
    25  */
       
    26 
       
    27 #include "config.h"
       
    28 #include "HTMLInputElement.h"
       
    29 
       
    30 #include "AXObjectCache.h"
       
    31 #include "Attribute.h"
       
    32 #include "BeforeTextInsertedEvent.h"
       
    33 #include "CSSPropertyNames.h"
       
    34 #include "ChromeClient.h"
       
    35 #include "DateComponents.h"
       
    36 #include "Document.h"
       
    37 #include "Editor.h"
       
    38 #include "Event.h"
       
    39 #include "EventHandler.h"
       
    40 #include "EventNames.h"
       
    41 #include "ExceptionCode.h"
       
    42 #include "File.h"
       
    43 #include "FileList.h"
       
    44 #include "FileSystem.h"
       
    45 #include "FocusController.h"
       
    46 #include "FormDataList.h"
       
    47 #include "Frame.h"
       
    48 #include "HTMLDataListElement.h"
       
    49 #include "HTMLFormElement.h"
       
    50 #include "HTMLImageLoader.h"
       
    51 #include "HTMLNames.h"
       
    52 #include "HTMLOptionElement.h"
       
    53 #include "LegacyHTMLTreeBuilder.h"
       
    54 #include "KeyboardEvent.h"
       
    55 #include "LocalizedStrings.h"
       
    56 #include "MouseEvent.h"
       
    57 #include "Page.h"
       
    58 #include "RegularExpression.h"
       
    59 #include "RenderButton.h"
       
    60 #include "RenderFileUploadControl.h"
       
    61 #include "RenderImage.h"
       
    62 #include "RenderSlider.h"
       
    63 #include "RenderText.h"
       
    64 #include "RenderTextControlSingleLine.h"
       
    65 #include "RenderTheme.h"
       
    66 #include "ScriptEventListener.h"
       
    67 #include "StepRange.h"
       
    68 #include "StringHash.h"
       
    69 #include "TextEvent.h"
       
    70 #include <wtf/HashMap.h>
       
    71 #include <wtf/MathExtras.h>
       
    72 #include <wtf/StdLibExtras.h>
       
    73 
       
    74 using namespace std;
       
    75 
       
    76 namespace WebCore {
       
    77 
       
    78 using namespace HTMLNames;
       
    79 
       
    80 const int maxSavedResults = 256;
       
    81 
       
    82 // Constant values for getAllowedValueStep().
       
    83 static const double dateDefaultStep = 1.0;
       
    84 static const double dateStepScaleFactor = 86400000.0;
       
    85 static const double dateTimeDefaultStep = 60.0;
       
    86 static const double dateTimeStepScaleFactor = 1000.0;
       
    87 static const double monthDefaultStep = 1.0;
       
    88 static const double monthStepScaleFactor = 1.0;
       
    89 static const double numberDefaultStep = 1.0;
       
    90 static const double numberStepScaleFactor = 1.0;
       
    91 static const double timeDefaultStep = 60.0;
       
    92 static const double timeStepScaleFactor = 1000.0;
       
    93 static const double weekDefaultStep = 1.0;
       
    94 static const double weekStepScaleFactor = 604800000.0;
       
    95 
       
    96 // Constant values for minimum().
       
    97 static const double numberDefaultMinimum = -DBL_MAX;
       
    98 static const double rangeDefaultMinimum = 0.0;
       
    99 
       
   100 // Constant values for maximum().
       
   101 static const double numberDefaultMaximum = DBL_MAX;
       
   102 static const double rangeDefaultMaximum = 100.0;
       
   103 
       
   104 static const double defaultStepBase = 0.0;
       
   105 static const double weekDefaultStepBase = -259200000.0; // The first day of 1970-W01.
       
   106 
       
   107 static const double msecPerMinute = 60 * 1000;
       
   108 static const double msecPerSecond = 1000;
       
   109 
       
   110 static bool isNumberCharacter(UChar ch)
       
   111 {
       
   112     return ch == '+' || ch == '-' || ch == '.' || ch == 'e' || ch == 'E'
       
   113         || ch >= '0' && ch <= '9';
       
   114 }
       
   115 
       
   116 HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
       
   117     : HTMLTextFormControlElement(tagName, document, form)
       
   118     , m_xPos(0)
       
   119     , m_yPos(0)
       
   120     , m_maxResults(-1)
       
   121     , m_type(TEXT)
       
   122     , m_checked(false)
       
   123     , m_defaultChecked(false)
       
   124     , m_useDefaultChecked(true)
       
   125     , m_indeterminate(false)
       
   126     , m_haveType(false)
       
   127     , m_activeSubmit(false)
       
   128     , m_autocomplete(Uninitialized)
       
   129     , m_autofilled(false)
       
   130     , m_inited(false)
       
   131 {
       
   132     ASSERT(hasTagName(inputTag) || hasTagName(isindexTag));
       
   133 }
       
   134 
       
   135 PassRefPtr<HTMLInputElement> HTMLInputElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
       
   136 {
       
   137     return adoptRef(new HTMLInputElement(tagName, document, form));
       
   138 }
       
   139 
       
   140 HTMLInputElement::~HTMLInputElement()
       
   141 {
       
   142     if (needsActivationCallback())
       
   143         document()->unregisterForDocumentActivationCallbacks(this);
       
   144 
       
   145     document()->checkedRadioButtons().removeButton(this);
       
   146 
       
   147     // Need to remove this from the form while it is still an HTMLInputElement,
       
   148     // so can't wait for the base class's destructor to do it.
       
   149     removeFromForm();
       
   150 }
       
   151 
       
   152 const AtomicString& HTMLInputElement::formControlName() const
       
   153 {
       
   154     return m_data.name();
       
   155 }
       
   156 
       
   157 bool HTMLInputElement::autoComplete() const
       
   158 {
       
   159     if (m_autocomplete != Uninitialized)
       
   160         return m_autocomplete == On;
       
   161     return HTMLTextFormControlElement::autoComplete();
       
   162 }
       
   163 
       
   164 static inline CheckedRadioButtons& checkedRadioButtons(const HTMLInputElement* element)
       
   165 {
       
   166     if (HTMLFormElement* form = element->form())
       
   167         return form->checkedRadioButtons();
       
   168     return element->document()->checkedRadioButtons();
       
   169 }
       
   170 
       
   171 void HTMLInputElement::updateCheckedRadioButtons()
       
   172 {
       
   173     if (attached() && checked())
       
   174         checkedRadioButtons(this).addButton(this);
       
   175 
       
   176     if (form()) {
       
   177         const Vector<HTMLFormControlElement*>& controls = form()->associatedElements();
       
   178         for (unsigned i = 0; i < controls.size(); ++i) {
       
   179             HTMLFormControlElement* control = controls[i];
       
   180             if (control->name() != name())
       
   181                 continue;
       
   182             if (control->type() != type())
       
   183                 continue;
       
   184             control->setNeedsValidityCheck();
       
   185         }
       
   186     } else {
       
   187         // FIXME: Traversing the document is inefficient.
       
   188         for (Node* node = document()->body(); node; node = node->traverseNextNode()) {
       
   189             if (!node->isElementNode())
       
   190                 continue;
       
   191             Element* element = static_cast<Element*>(node);
       
   192             if (element->formControlName() != name())
       
   193                 continue;
       
   194             if (element->formControlType() != type())
       
   195                 continue;
       
   196             HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(element);
       
   197             if (control->form())
       
   198                 continue;
       
   199             control->setNeedsValidityCheck();
       
   200         }
       
   201     }
       
   202    
       
   203     if (renderer() && renderer()->style()->hasAppearance())
       
   204         renderer()->theme()->stateChanged(renderer(), CheckedState);
       
   205 }
       
   206 
       
   207 bool HTMLInputElement::valueMissing() const
       
   208 {
       
   209     if (!isRequiredFormControl() || readOnly() || disabled())
       
   210         return false;
       
   211 
       
   212     switch (inputType()) {
       
   213     case DATE:
       
   214     case DATETIME:
       
   215     case DATETIMELOCAL:
       
   216     case EMAIL:
       
   217     case FILE:
       
   218     case MONTH:
       
   219     case NUMBER:
       
   220     case PASSWORD:
       
   221     case SEARCH:
       
   222     case TELEPHONE:
       
   223     case TEXT:
       
   224     case TIME:
       
   225     case URL:
       
   226     case WEEK:
       
   227         return value().isEmpty();
       
   228     case CHECKBOX:
       
   229         return !checked();
       
   230     case RADIO:
       
   231         return !checkedRadioButtons(this).checkedButtonForGroup(name());
       
   232     case COLOR:
       
   233         return false;
       
   234     case BUTTON:
       
   235     case HIDDEN:
       
   236     case IMAGE:
       
   237     case ISINDEX:
       
   238     case RANGE:
       
   239     case RESET:
       
   240     case SUBMIT:
       
   241         break;
       
   242     }
       
   243 
       
   244     ASSERT_NOT_REACHED();
       
   245     return false;
       
   246 }
       
   247 
       
   248 bool HTMLInputElement::patternMismatch() const
       
   249 {
       
   250     switch (inputType()) {
       
   251     case BUTTON:
       
   252     case CHECKBOX:
       
   253     case COLOR:
       
   254     case DATE:
       
   255     case DATETIME:
       
   256     case DATETIMELOCAL:
       
   257     case FILE:
       
   258     case HIDDEN:
       
   259     case IMAGE:
       
   260     case ISINDEX:
       
   261     case MONTH:
       
   262     case NUMBER:
       
   263     case RADIO:
       
   264     case RANGE:
       
   265     case RESET:
       
   266     case SUBMIT:
       
   267     case TIME:
       
   268     case WEEK:
       
   269         return false;
       
   270     case EMAIL:
       
   271     case PASSWORD:
       
   272     case SEARCH:
       
   273     case TELEPHONE:
       
   274     case TEXT:
       
   275     case URL:
       
   276         const AtomicString& pattern = getAttribute(patternAttr);
       
   277         String value = this->value();
       
   278          // Empty values can't be mismatched
       
   279         if (pattern.isEmpty() || value.isEmpty())
       
   280             return false;
       
   281         RegularExpression patternRegExp(pattern, TextCaseSensitive);
       
   282         int matchLength = 0;
       
   283         int valueLength = value.length();
       
   284         int matchOffset = patternRegExp.match(value, 0, &matchLength);
       
   285         return matchOffset || matchLength != valueLength;
       
   286     }
       
   287     ASSERT_NOT_REACHED();
       
   288     return false;
       
   289 }
       
   290 
       
   291 bool HTMLInputElement::tooLong() const
       
   292 {
       
   293     switch (inputType()) {
       
   294     case EMAIL:
       
   295     case PASSWORD:
       
   296     case SEARCH:
       
   297     case TELEPHONE:
       
   298     case TEXT:
       
   299     case URL: {
       
   300         int max = maxLength();
       
   301         if (max < 0)
       
   302             return false;
       
   303         // Return false for the default value even if it is longer than maxLength.
       
   304         bool userEdited = !m_data.value().isNull();
       
   305         if (!userEdited)
       
   306             return false;
       
   307         return numGraphemeClusters(value()) > static_cast<unsigned>(max);
       
   308     }
       
   309     case BUTTON:
       
   310     case CHECKBOX:
       
   311     case COLOR:
       
   312     case DATE:
       
   313     case DATETIME:
       
   314     case DATETIMELOCAL:
       
   315     case FILE:
       
   316     case HIDDEN:
       
   317     case IMAGE:
       
   318     case ISINDEX:
       
   319     case MONTH:
       
   320     case NUMBER:
       
   321     case RADIO:
       
   322     case RANGE:
       
   323     case RESET:
       
   324     case SUBMIT:
       
   325     case TIME:
       
   326     case WEEK:
       
   327         return false;
       
   328     }
       
   329     ASSERT_NOT_REACHED();
       
   330     return false;
       
   331 }
       
   332 
       
   333 bool HTMLInputElement::rangeUnderflow() const
       
   334 {
       
   335     const double nan = numeric_limits<double>::quiet_NaN();
       
   336     switch (inputType()) {
       
   337     case DATE:
       
   338     case DATETIME:
       
   339     case DATETIMELOCAL:
       
   340     case MONTH:
       
   341     case NUMBER:
       
   342     case TIME:
       
   343     case WEEK: {
       
   344         double doubleValue = parseToDouble(value(), nan);
       
   345         return isfinite(doubleValue) && doubleValue < minimum();
       
   346     }
       
   347     case RANGE: // Guaranteed by sanitization.
       
   348         ASSERT(parseToDouble(value(), nan) >= minimum());
       
   349     case BUTTON:
       
   350     case CHECKBOX:
       
   351     case COLOR:
       
   352     case EMAIL:
       
   353     case FILE:
       
   354     case HIDDEN:
       
   355     case IMAGE:
       
   356     case ISINDEX:
       
   357     case PASSWORD:
       
   358     case RADIO:
       
   359     case RESET:
       
   360     case SEARCH:
       
   361     case SUBMIT:
       
   362     case TELEPHONE:
       
   363     case TEXT:
       
   364     case URL:
       
   365         break;
       
   366     }
       
   367     return false;
       
   368 }
       
   369 
       
   370 bool HTMLInputElement::rangeOverflow() const
       
   371 {
       
   372     const double nan = numeric_limits<double>::quiet_NaN();
       
   373     switch (inputType()) {
       
   374     case DATE:
       
   375     case DATETIME:
       
   376     case DATETIMELOCAL:
       
   377     case MONTH:
       
   378     case NUMBER:
       
   379     case TIME:
       
   380     case WEEK: {
       
   381         double doubleValue = parseToDouble(value(), nan);
       
   382         return isfinite(doubleValue) && doubleValue > maximum();
       
   383     }
       
   384     case RANGE: // Guaranteed by sanitization.
       
   385         ASSERT(parseToDouble(value(), nan) <= maximum());
       
   386     case BUTTON:
       
   387     case CHECKBOX:
       
   388     case COLOR:
       
   389     case EMAIL:
       
   390     case FILE:
       
   391     case HIDDEN:
       
   392     case IMAGE:
       
   393     case ISINDEX:
       
   394     case PASSWORD:
       
   395     case RADIO:
       
   396     case RESET:
       
   397     case SEARCH:
       
   398     case SUBMIT:
       
   399     case TELEPHONE:
       
   400     case TEXT:
       
   401     case URL:
       
   402         break;
       
   403     }
       
   404     return false;
       
   405 }
       
   406 
       
   407 double HTMLInputElement::minimum() const
       
   408 {
       
   409     switch (inputType()) {
       
   410     case DATE:
       
   411         return parseToDouble(getAttribute(minAttr), DateComponents::minimumDate());
       
   412     case DATETIME:
       
   413     case DATETIMELOCAL:
       
   414         return parseToDouble(getAttribute(minAttr), DateComponents::minimumDateTime());
       
   415     case MONTH:
       
   416         return parseToDouble(getAttribute(minAttr), DateComponents::minimumMonth());
       
   417     case NUMBER:
       
   418         return parseToDouble(getAttribute(minAttr), numberDefaultMinimum);
       
   419     case RANGE:
       
   420         return parseToDouble(getAttribute(minAttr), rangeDefaultMinimum);
       
   421     case TIME:
       
   422         return parseToDouble(getAttribute(minAttr), DateComponents::minimumTime());
       
   423     case WEEK:
       
   424         return parseToDouble(getAttribute(minAttr), DateComponents::minimumWeek());
       
   425     case BUTTON:
       
   426     case CHECKBOX:
       
   427     case COLOR:
       
   428     case EMAIL:
       
   429     case FILE:
       
   430     case HIDDEN:
       
   431     case IMAGE:
       
   432     case ISINDEX:
       
   433     case PASSWORD:
       
   434     case RADIO:
       
   435     case RESET:
       
   436     case SEARCH:
       
   437     case SUBMIT:
       
   438     case TELEPHONE:
       
   439     case TEXT:
       
   440     case URL:
       
   441         break;
       
   442     }
       
   443     ASSERT_NOT_REACHED();
       
   444     return 0;
       
   445 }
       
   446 
       
   447 double HTMLInputElement::maximum() const
       
   448 {
       
   449     switch (inputType()) {
       
   450     case DATE:
       
   451         return parseToDouble(getAttribute(maxAttr), DateComponents::maximumDate());
       
   452     case DATETIME:
       
   453     case DATETIMELOCAL:
       
   454         return parseToDouble(getAttribute(maxAttr), DateComponents::maximumDateTime());
       
   455     case MONTH:
       
   456         return parseToDouble(getAttribute(maxAttr), DateComponents::maximumMonth());
       
   457     case NUMBER:
       
   458         return parseToDouble(getAttribute(maxAttr), numberDefaultMaximum);
       
   459     case RANGE: {
       
   460         double max = parseToDouble(getAttribute(maxAttr), rangeDefaultMaximum);
       
   461         // A remedy for the inconsistent min/max values for RANGE.
       
   462         // Sets the maximum to the default or the minimum value.
       
   463         double min = minimum();
       
   464         if (max < min)
       
   465             max = std::max(min, rangeDefaultMaximum);
       
   466         return max;
       
   467     }
       
   468     case TIME:
       
   469         return parseToDouble(getAttribute(maxAttr), DateComponents::maximumTime());
       
   470     case WEEK:
       
   471         return parseToDouble(getAttribute(maxAttr), DateComponents::maximumWeek());
       
   472     case BUTTON:
       
   473     case CHECKBOX:
       
   474     case COLOR:
       
   475     case EMAIL:
       
   476     case FILE:
       
   477     case HIDDEN:
       
   478     case IMAGE:
       
   479     case ISINDEX:
       
   480     case PASSWORD:
       
   481     case RADIO:
       
   482     case RESET:
       
   483     case SEARCH:
       
   484     case SUBMIT:
       
   485     case TELEPHONE:
       
   486     case TEXT:
       
   487     case URL:
       
   488         break;
       
   489     }
       
   490     ASSERT_NOT_REACHED();
       
   491     return 0;
       
   492 }
       
   493 
       
   494 double HTMLInputElement::stepBase() const
       
   495 {
       
   496     switch (inputType()) {
       
   497     case RANGE:
       
   498         return minimum();
       
   499     case DATE:
       
   500     case DATETIME:
       
   501     case DATETIMELOCAL:
       
   502     case MONTH:
       
   503     case NUMBER:
       
   504     case TIME:
       
   505         return parseToDouble(getAttribute(minAttr), defaultStepBase);
       
   506     case WEEK:
       
   507         return parseToDouble(getAttribute(minAttr), weekDefaultStepBase);
       
   508     case BUTTON:
       
   509     case CHECKBOX:
       
   510     case COLOR:
       
   511     case EMAIL:
       
   512     case FILE:
       
   513     case HIDDEN:
       
   514     case IMAGE:
       
   515     case ISINDEX:
       
   516     case PASSWORD:
       
   517     case RADIO:
       
   518     case RESET:
       
   519     case SEARCH:
       
   520     case SUBMIT:
       
   521     case TELEPHONE:
       
   522     case TEXT:
       
   523     case URL:
       
   524         break;
       
   525     }
       
   526     ASSERT_NOT_REACHED();
       
   527     return 0.0;
       
   528 }
       
   529 
       
   530 bool HTMLInputElement::stepMismatch() const
       
   531 {
       
   532     double step;
       
   533     if (!getAllowedValueStep(&step))
       
   534         return false;
       
   535     switch (inputType()) {
       
   536     case RANGE:
       
   537         // stepMismatch doesn't occur for RANGE. RenderSlider guarantees the
       
   538         // value matches to step on user input, and sanitation takes care
       
   539         // of the general case.
       
   540         return false;
       
   541     case NUMBER: {
       
   542         double doubleValue;
       
   543         if (!parseToDoubleForNumberType(value(), &doubleValue))
       
   544             return false;
       
   545         doubleValue = fabs(doubleValue - stepBase());
       
   546         if (isinf(doubleValue))
       
   547             return false;
       
   548         // double's fractional part size is DBL_MAN_DIG-bit.  If the current
       
   549         // value is greater than step*2^DBL_MANT_DIG, the following fmod() makes
       
   550         // no sense.
       
   551         if (doubleValue / pow(2.0, DBL_MANT_DIG) > step)
       
   552             return false;
       
   553         double remainder = fmod(doubleValue, step);
       
   554         // Accepts errors in lower 7-bit.
       
   555         double acceptableError = step / pow(2.0, DBL_MANT_DIG - 7);
       
   556         return acceptableError < remainder && remainder < (step - acceptableError);
       
   557     }
       
   558     case DATE:
       
   559     case DATETIME:
       
   560     case DATETIMELOCAL:
       
   561     case MONTH:
       
   562     case TIME:
       
   563     case WEEK: {
       
   564         const double nan = numeric_limits<double>::quiet_NaN();
       
   565         double doubleValue = parseToDouble(value(), nan);
       
   566         doubleValue = fabs(doubleValue - stepBase());
       
   567         if (!isfinite(doubleValue))
       
   568             return false;
       
   569         ASSERT(round(doubleValue) == doubleValue);
       
   570         ASSERT(round(step) == step);
       
   571         return fmod(doubleValue, step);
       
   572     }
       
   573     case BUTTON:
       
   574     case CHECKBOX:
       
   575     case COLOR:
       
   576     case EMAIL:
       
   577     case FILE:
       
   578     case HIDDEN:
       
   579     case IMAGE:
       
   580     case ISINDEX:
       
   581     case PASSWORD:
       
   582     case RADIO:
       
   583     case RESET:
       
   584     case SEARCH:
       
   585     case SUBMIT:
       
   586     case TELEPHONE:
       
   587     case TEXT:
       
   588     case URL:
       
   589         break;
       
   590     }
       
   591     // Non-supported types should be rejected by getAllowedValueStep().
       
   592     ASSERT_NOT_REACHED();
       
   593     return false;
       
   594 }
       
   595 
       
   596 bool HTMLInputElement::getStepParameters(double* defaultStep, double* stepScaleFactor) const
       
   597 {
       
   598     ASSERT(defaultStep);
       
   599     ASSERT(stepScaleFactor);
       
   600     switch (inputType()) {
       
   601     case NUMBER:
       
   602     case RANGE:
       
   603         *defaultStep = numberDefaultStep;
       
   604         *stepScaleFactor = numberStepScaleFactor;
       
   605         return true;
       
   606     case DATE:
       
   607         *defaultStep = dateDefaultStep;
       
   608         *stepScaleFactor = dateStepScaleFactor;
       
   609         return true;
       
   610     case DATETIME:
       
   611     case DATETIMELOCAL:
       
   612         *defaultStep = dateTimeDefaultStep;
       
   613         *stepScaleFactor = dateTimeStepScaleFactor;
       
   614         return true;
       
   615     case MONTH:
       
   616         *defaultStep = monthDefaultStep;
       
   617         *stepScaleFactor = monthStepScaleFactor;
       
   618         return true;
       
   619     case TIME:
       
   620         *defaultStep = timeDefaultStep;
       
   621         *stepScaleFactor = timeStepScaleFactor;
       
   622         return true;
       
   623     case WEEK:
       
   624         *defaultStep = weekDefaultStep;
       
   625         *stepScaleFactor = weekStepScaleFactor;
       
   626         return true;
       
   627     case BUTTON:
       
   628     case CHECKBOX:
       
   629     case COLOR:
       
   630     case EMAIL:
       
   631     case FILE:
       
   632     case HIDDEN:
       
   633     case IMAGE:
       
   634     case ISINDEX:
       
   635     case PASSWORD:
       
   636     case RADIO:
       
   637     case RESET:
       
   638     case SEARCH:
       
   639     case SUBMIT:
       
   640     case TELEPHONE:
       
   641     case TEXT:
       
   642     case URL:
       
   643         return false;
       
   644     }
       
   645     ASSERT_NOT_REACHED();
       
   646     return false;
       
   647 }
       
   648 
       
   649 bool HTMLInputElement::getAllowedValueStep(double* step) const
       
   650 {
       
   651     ASSERT(step);
       
   652     double defaultStep;
       
   653     double stepScaleFactor;
       
   654     if (!getStepParameters(&defaultStep, &stepScaleFactor))
       
   655         return false;
       
   656     const AtomicString& stepString = getAttribute(stepAttr);
       
   657     if (stepString.isEmpty()) {
       
   658         *step = defaultStep * stepScaleFactor;
       
   659         return true;
       
   660     }
       
   661     if (equalIgnoringCase(stepString, "any"))
       
   662         return false;
       
   663     double parsed;
       
   664     if (!parseToDoubleForNumberType(stepString, &parsed) || parsed <= 0.0) {
       
   665         *step = defaultStep * stepScaleFactor;
       
   666         return true;
       
   667     }
       
   668     // For DATE, MONTH, WEEK, the parsed value should be an integer.
       
   669     if (inputType() == DATE || inputType() == MONTH || inputType() == WEEK)
       
   670         parsed = max(round(parsed), 1.0);
       
   671     double result = parsed * stepScaleFactor;
       
   672     // For DATETIME, DATETIMELOCAL, TIME, the result should be an integer.
       
   673     if (inputType() == DATETIME || inputType() == DATETIMELOCAL || inputType() == TIME)
       
   674         result = max(round(result), 1.0);
       
   675     ASSERT(result > 0);
       
   676     *step = result;
       
   677     return true;
       
   678 }
       
   679 
       
   680 void HTMLInputElement::applyStep(double count, ExceptionCode& ec)
       
   681 {
       
   682     double step;
       
   683     if (!getAllowedValueStep(&step)) {
       
   684         ec = INVALID_STATE_ERR;
       
   685         return;
       
   686     }
       
   687     const double nan = numeric_limits<double>::quiet_NaN();
       
   688     double current = parseToDouble(value(), nan);
       
   689     if (!isfinite(current)) {
       
   690         ec = INVALID_STATE_ERR;
       
   691         return;
       
   692     }
       
   693     double newValue = current + step * count;
       
   694     if (isinf(newValue)) {
       
   695         ec = INVALID_STATE_ERR;
       
   696         return;
       
   697     }
       
   698     if (newValue < minimum()) {
       
   699         ec = INVALID_STATE_ERR;
       
   700         return;
       
   701     }
       
   702     double base = stepBase();
       
   703     newValue = base + round((newValue - base) / step) * step;
       
   704     if (newValue > maximum()) {
       
   705         ec = INVALID_STATE_ERR;
       
   706         return;
       
   707     }
       
   708     setValueAsNumber(newValue, ec);
       
   709 }
       
   710 
       
   711 void HTMLInputElement::stepUp(int n, ExceptionCode& ec)
       
   712 {
       
   713     applyStep(n, ec);
       
   714 }
       
   715 
       
   716 void HTMLInputElement::stepDown(int n, ExceptionCode& ec)
       
   717 {
       
   718     applyStep(-n, ec);
       
   719 }
       
   720 
       
   721 bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const
       
   722 {
       
   723     // If text fields can be focused, then they should always be keyboard focusable
       
   724     if (isTextField())
       
   725         return HTMLFormControlElementWithState::isFocusable();
       
   726         
       
   727     // If the base class says we can't be focused, then we can stop now.
       
   728     if (!HTMLFormControlElementWithState::isKeyboardFocusable(event))
       
   729         return false;
       
   730 
       
   731     if (inputType() == RADIO) {
       
   732 
       
   733         // Never allow keyboard tabbing to leave you in the same radio group.  Always
       
   734         // skip any other elements in the group.
       
   735         Node* currentFocusedNode = document()->focusedNode();
       
   736         if (currentFocusedNode && currentFocusedNode->hasTagName(inputTag)) {
       
   737             HTMLInputElement* focusedInput = static_cast<HTMLInputElement*>(currentFocusedNode);
       
   738             if (focusedInput->inputType() == RADIO && focusedInput->form() == form() && focusedInput->name() == name())
       
   739                 return false;
       
   740         }
       
   741         
       
   742         // Allow keyboard focus if we're checked or if nothing in the group is checked.
       
   743         return checked() || !checkedRadioButtons(this).checkedButtonForGroup(name());
       
   744     }
       
   745     
       
   746     return true;
       
   747 }
       
   748 
       
   749 bool HTMLInputElement::isMouseFocusable() const
       
   750 {
       
   751     if (isTextField())
       
   752         return HTMLFormControlElementWithState::isFocusable();
       
   753     return HTMLFormControlElementWithState::isMouseFocusable();
       
   754 }
       
   755 
       
   756 void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection)
       
   757 {        
       
   758     if (isTextField())
       
   759         InputElement::updateFocusAppearance(m_data, this, this, restorePreviousSelection);
       
   760     else
       
   761         HTMLFormControlElementWithState::updateFocusAppearance(restorePreviousSelection);
       
   762 }
       
   763 
       
   764 void HTMLInputElement::aboutToUnload()
       
   765 {
       
   766     InputElement::aboutToUnload(this, this);
       
   767 }
       
   768 
       
   769 bool HTMLInputElement::shouldUseInputMethod() const
       
   770 {
       
   771     // The reason IME's are disabled for the password field is because IMEs 
       
   772     // can access the underlying password and display it in clear text --
       
   773     // e.g. you can use it to access the stored password for any site 
       
   774     // with only trivial effort.
       
   775     return isTextField() && inputType() != PASSWORD;
       
   776 }
       
   777 
       
   778 void HTMLInputElement::handleFocusEvent()
       
   779 {
       
   780     InputElement::dispatchFocusEvent(this, this);
       
   781 }
       
   782 
       
   783 void HTMLInputElement::handleBlurEvent()
       
   784 {
       
   785     InputElement::dispatchBlurEvent(this, this);
       
   786 }
       
   787 
       
   788 void HTMLInputElement::setType(const String& t)
       
   789 {
       
   790     if (t.isEmpty()) {
       
   791         int exccode;
       
   792         removeAttribute(typeAttr, exccode);
       
   793     } else
       
   794         setAttribute(typeAttr, t);
       
   795 }
       
   796 
       
   797 typedef HashMap<String, HTMLInputElement::InputType, CaseFoldingHash> InputTypeMap;
       
   798 static const InputTypeMap* createTypeMap()
       
   799 {
       
   800     InputTypeMap* map = new InputTypeMap;
       
   801     map->add("button", HTMLInputElement::BUTTON);
       
   802     map->add("checkbox", HTMLInputElement::CHECKBOX);
       
   803     map->add("color", HTMLInputElement::COLOR);
       
   804     map->add("date", HTMLInputElement::DATE);
       
   805     map->add("datetime", HTMLInputElement::DATETIME);
       
   806     map->add("datetime-local", HTMLInputElement::DATETIMELOCAL);
       
   807     map->add("email", HTMLInputElement::EMAIL);
       
   808     map->add("file", HTMLInputElement::FILE);
       
   809     map->add("hidden", HTMLInputElement::HIDDEN);
       
   810     map->add("image", HTMLInputElement::IMAGE);
       
   811     map->add("khtml_isindex", HTMLInputElement::ISINDEX);
       
   812     map->add("month", HTMLInputElement::MONTH);
       
   813     map->add("number", HTMLInputElement::NUMBER);
       
   814     map->add("password", HTMLInputElement::PASSWORD);
       
   815     map->add("radio", HTMLInputElement::RADIO);
       
   816     map->add("range", HTMLInputElement::RANGE);
       
   817     map->add("reset", HTMLInputElement::RESET);
       
   818     map->add("search", HTMLInputElement::SEARCH);
       
   819     map->add("submit", HTMLInputElement::SUBMIT);
       
   820     map->add("tel", HTMLInputElement::TELEPHONE);
       
   821     map->add("time", HTMLInputElement::TIME);
       
   822     map->add("url", HTMLInputElement::URL);
       
   823     map->add("week", HTMLInputElement::WEEK);
       
   824     // No need to register "text" because it is the default type.
       
   825     return map;
       
   826 }
       
   827 
       
   828 void HTMLInputElement::setInputType(const String& t)
       
   829 {
       
   830     static const InputTypeMap* typeMap = createTypeMap();
       
   831     InputType newType = t.isNull() ? TEXT : typeMap->get(t);
       
   832 
       
   833     // IMPORTANT: Don't allow the type to be changed to FILE after the first
       
   834     // type change, otherwise a JavaScript programmer would be able to set a text
       
   835     // field's value to something like /etc/passwd and then change it to a file field.
       
   836     if (inputType() != newType) {
       
   837         if (newType == FILE && m_haveType)
       
   838             // Set the attribute back to the old value.
       
   839             // Useful in case we were called from inside parseMappedAttribute.
       
   840             setAttribute(typeAttr, type());
       
   841         else {
       
   842             checkedRadioButtons(this).removeButton(this);
       
   843 
       
   844             if (newType == FILE && !m_fileList)
       
   845                 m_fileList = FileList::create();
       
   846 
       
   847             bool wasAttached = attached();
       
   848             if (wasAttached)
       
   849                 detach();
       
   850 
       
   851             bool didStoreValue = storesValueSeparateFromAttribute();
       
   852             bool wasPasswordField = inputType() == PASSWORD;
       
   853             bool didRespectHeightAndWidth = respectHeightAndWidthAttrs();
       
   854             m_type = newType;
       
   855             setNeedsWillValidateCheck();
       
   856             bool willStoreValue = storesValueSeparateFromAttribute();
       
   857             bool isPasswordField = inputType() == PASSWORD;
       
   858             bool willRespectHeightAndWidth = respectHeightAndWidthAttrs();
       
   859 
       
   860             if (didStoreValue && !willStoreValue && !m_data.value().isNull()) {
       
   861                 setAttribute(valueAttr, m_data.value());
       
   862                 m_data.setValue(String());
       
   863             }
       
   864             if (!didStoreValue && willStoreValue)
       
   865                 m_data.setValue(sanitizeValue(getAttribute(valueAttr)));
       
   866             else
       
   867                 InputElement::updateValueIfNeeded(m_data, this);
       
   868 
       
   869             if (wasPasswordField && !isPasswordField)
       
   870                 unregisterForActivationCallbackIfNeeded();
       
   871             else if (!wasPasswordField && isPasswordField)
       
   872                 registerForActivationCallbackIfNeeded();
       
   873 
       
   874             if (didRespectHeightAndWidth != willRespectHeightAndWidth) {
       
   875                 NamedNodeMap* map = attributeMap();
       
   876                 ASSERT(map);
       
   877                 if (Attribute* height = map->getAttributeItem(heightAttr))
       
   878                     attributeChanged(height, false);
       
   879                 if (Attribute* width = map->getAttributeItem(widthAttr))
       
   880                     attributeChanged(width, false);
       
   881                 if (Attribute* align = map->getAttributeItem(alignAttr))
       
   882                     attributeChanged(align, false);
       
   883             }
       
   884 
       
   885             if (wasAttached) {
       
   886                 attach();
       
   887                 if (document()->focusedNode() == this)
       
   888                     updateFocusAppearance(true);
       
   889             }
       
   890 
       
   891             checkedRadioButtons(this).addButton(this);
       
   892         }
       
   893 
       
   894         setNeedsValidityCheck();
       
   895         InputElement::notifyFormStateChanged(this);
       
   896     }
       
   897     m_haveType = true;
       
   898 
       
   899     if (inputType() != IMAGE && m_imageLoader)
       
   900         m_imageLoader.clear();
       
   901 }
       
   902 
       
   903 static const AtomicString* createFormControlTypes()
       
   904 {
       
   905     AtomicString* types = new AtomicString[HTMLInputElement::numberOfTypes];
       
   906     // The values must be lowercased because they will be the return values of
       
   907     //  input.type and it must be lowercase according to DOM Level 2.
       
   908     types[HTMLInputElement::BUTTON] = "button";
       
   909     types[HTMLInputElement::CHECKBOX] = "checkbox";
       
   910     types[HTMLInputElement::COLOR] = "color";
       
   911     types[HTMLInputElement::DATE] = "date";
       
   912     types[HTMLInputElement::DATETIME] = "datetime";
       
   913     types[HTMLInputElement::DATETIMELOCAL] = "datetime-local";
       
   914     types[HTMLInputElement::EMAIL] = "email";
       
   915     types[HTMLInputElement::FILE] = "file";
       
   916     types[HTMLInputElement::HIDDEN] = "hidden";
       
   917     types[HTMLInputElement::IMAGE] = "image";
       
   918     types[HTMLInputElement::ISINDEX] = emptyAtom;
       
   919     types[HTMLInputElement::MONTH] = "month";
       
   920     types[HTMLInputElement::NUMBER] = "number";
       
   921     types[HTMLInputElement::PASSWORD] = "password";
       
   922     types[HTMLInputElement::RADIO] = "radio";
       
   923     types[HTMLInputElement::RANGE] = "range";
       
   924     types[HTMLInputElement::RESET] = "reset";
       
   925     types[HTMLInputElement::SEARCH] = "search";
       
   926     types[HTMLInputElement::SUBMIT] = "submit";
       
   927     types[HTMLInputElement::TELEPHONE] = "tel";
       
   928     types[HTMLInputElement::TEXT] = "text";
       
   929     types[HTMLInputElement::TIME] = "time";
       
   930     types[HTMLInputElement::URL] = "url";
       
   931     types[HTMLInputElement::WEEK] = "week";
       
   932     return types;
       
   933 }
       
   934 
       
   935 const AtomicString& HTMLInputElement::formControlType() const
       
   936 {
       
   937     static const AtomicString* formControlTypes = createFormControlTypes();
       
   938     return formControlTypes[inputType()];
       
   939 }
       
   940 
       
   941 bool HTMLInputElement::saveFormControlState(String& result) const
       
   942 {
       
   943     switch (inputType()) {
       
   944     case BUTTON:
       
   945     case COLOR:
       
   946     case DATE:
       
   947     case DATETIME:
       
   948     case DATETIMELOCAL:
       
   949     case EMAIL:
       
   950     case FILE:
       
   951     case HIDDEN:
       
   952     case IMAGE:
       
   953     case ISINDEX:
       
   954     case MONTH:
       
   955     case NUMBER:
       
   956     case RANGE:
       
   957     case RESET:
       
   958     case SEARCH:
       
   959     case SUBMIT:
       
   960     case TELEPHONE:
       
   961     case TEXT:
       
   962     case TIME:
       
   963     case URL:
       
   964     case WEEK: {
       
   965         String currentValue = value();
       
   966         if (currentValue == defaultValue())
       
   967             return false;
       
   968         result = currentValue;
       
   969         return true;
       
   970     }
       
   971     case CHECKBOX:
       
   972     case RADIO:
       
   973         result = checked() ? "on" : "off";
       
   974         return true;
       
   975     case PASSWORD:
       
   976         return false;
       
   977     }
       
   978     ASSERT_NOT_REACHED();
       
   979     return false;
       
   980 }
       
   981 
       
   982 void HTMLInputElement::restoreFormControlState(const String& state)
       
   983 {
       
   984     ASSERT(inputType() != PASSWORD); // should never save/restore password fields
       
   985     switch (inputType()) {
       
   986     case BUTTON:
       
   987     case COLOR:
       
   988     case DATE:
       
   989     case DATETIME:
       
   990     case DATETIMELOCAL:
       
   991     case EMAIL:
       
   992     case FILE:
       
   993     case HIDDEN:
       
   994     case IMAGE:
       
   995     case ISINDEX:
       
   996     case MONTH:
       
   997     case NUMBER:
       
   998     case RANGE:
       
   999     case RESET:
       
  1000     case SEARCH:
       
  1001     case SUBMIT:
       
  1002     case TELEPHONE:
       
  1003     case TEXT:
       
  1004     case TIME:
       
  1005     case URL:
       
  1006     case WEEK:
       
  1007         setValue(state);
       
  1008         break;
       
  1009     case CHECKBOX:
       
  1010     case RADIO:
       
  1011         setChecked(state == "on");
       
  1012         break;
       
  1013     case PASSWORD:
       
  1014         break;
       
  1015     }
       
  1016 }
       
  1017 
       
  1018 bool HTMLInputElement::canStartSelection() const
       
  1019 {
       
  1020     if (!isTextField())
       
  1021         return false;
       
  1022     return HTMLFormControlElementWithState::canStartSelection();
       
  1023 }
       
  1024 
       
  1025 bool HTMLInputElement::canHaveSelection() const
       
  1026 {
       
  1027     return isTextField();
       
  1028 }
       
  1029 
       
  1030 void HTMLInputElement::accessKeyAction(bool sendToAnyElement)
       
  1031 {
       
  1032     switch (inputType()) {
       
  1033     case BUTTON:
       
  1034     case CHECKBOX:
       
  1035     case FILE:
       
  1036     case IMAGE:
       
  1037     case RADIO:
       
  1038     case RANGE:
       
  1039     case RESET:
       
  1040     case SUBMIT:
       
  1041         focus(false);
       
  1042         // send the mouse button events iff the caller specified sendToAnyElement
       
  1043         dispatchSimulatedClick(0, sendToAnyElement);
       
  1044         break;
       
  1045     case HIDDEN:
       
  1046         // a no-op for this type
       
  1047         break;
       
  1048     case COLOR:
       
  1049     case DATE:
       
  1050     case DATETIME:
       
  1051     case DATETIMELOCAL:
       
  1052     case EMAIL:
       
  1053     case ISINDEX:
       
  1054     case MONTH:
       
  1055     case NUMBER:
       
  1056     case PASSWORD:
       
  1057     case SEARCH:
       
  1058     case TELEPHONE:
       
  1059     case TEXT:
       
  1060     case TIME:
       
  1061     case URL:
       
  1062     case WEEK:
       
  1063         // should never restore previous selection here
       
  1064         focus(false);
       
  1065          break;
       
  1066     }
       
  1067 }
       
  1068 
       
  1069 bool HTMLInputElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
       
  1070 {
       
  1071     if (((attrName == heightAttr || attrName == widthAttr) && respectHeightAndWidthAttrs())
       
  1072         || attrName == vspaceAttr 
       
  1073         || attrName == hspaceAttr) {
       
  1074         result = eUniversal;
       
  1075         return false;
       
  1076     } 
       
  1077 
       
  1078     if (attrName == alignAttr) {
       
  1079         if (inputType() == IMAGE) {
       
  1080             // Share with <img> since the alignment behavior is the same.
       
  1081             result = eReplaced;
       
  1082             return false;
       
  1083         }
       
  1084     }
       
  1085 
       
  1086     return HTMLElement::mapToEntry(attrName, result);
       
  1087 }
       
  1088 
       
  1089 void HTMLInputElement::parseMappedAttribute(Attribute* attr)
       
  1090 {
       
  1091     if (attr->name() == nameAttr) {
       
  1092         checkedRadioButtons(this).removeButton(this);
       
  1093         m_data.setName(attr->value());
       
  1094         checkedRadioButtons(this).addButton(this);
       
  1095         HTMLFormControlElementWithState::parseMappedAttribute(attr);
       
  1096     } else if (attr->name() == autocompleteAttr) {
       
  1097         if (equalIgnoringCase(attr->value(), "off")) {
       
  1098             m_autocomplete = Off;
       
  1099             registerForActivationCallbackIfNeeded();
       
  1100         } else {
       
  1101             bool needsToUnregister = m_autocomplete == Off;
       
  1102 
       
  1103             if (attr->isEmpty())
       
  1104                 m_autocomplete = Uninitialized;
       
  1105             else
       
  1106                 m_autocomplete = On;
       
  1107 
       
  1108             if (needsToUnregister)
       
  1109                 unregisterForActivationCallbackIfNeeded();
       
  1110         }
       
  1111     } else if (attr->name() == typeAttr) {
       
  1112         setInputType(attr->value());
       
  1113     } else if (attr->name() == valueAttr) {
       
  1114         // We only need to setChanged if the form is looking at the default value right now.
       
  1115         if (m_data.value().isNull())
       
  1116             setNeedsStyleRecalc();
       
  1117         setFormControlValueMatchesRenderer(false);
       
  1118         setNeedsValidityCheck();
       
  1119     } else if (attr->name() == checkedAttr) {
       
  1120         m_defaultChecked = !attr->isNull();
       
  1121         if (m_useDefaultChecked) {
       
  1122             setChecked(m_defaultChecked);
       
  1123             m_useDefaultChecked = true;
       
  1124         }
       
  1125         setNeedsValidityCheck();
       
  1126     } else if (attr->name() == maxlengthAttr) {
       
  1127         InputElement::parseMaxLengthAttribute(m_data, this, this, attr);
       
  1128         setNeedsValidityCheck();
       
  1129     } else if (attr->name() == sizeAttr)
       
  1130         InputElement::parseSizeAttribute(m_data, this, attr);
       
  1131     else if (attr->name() == altAttr) {
       
  1132         if (renderer() && inputType() == IMAGE)
       
  1133             toRenderImage(renderer())->updateAltText();
       
  1134     } else if (attr->name() == srcAttr) {
       
  1135         if (renderer() && inputType() == IMAGE) {
       
  1136             if (!m_imageLoader)
       
  1137                 m_imageLoader.set(new HTMLImageLoader(this));
       
  1138             m_imageLoader->updateFromElementIgnoringPreviousError();
       
  1139         }
       
  1140     } else if (attr->name() == usemapAttr || attr->name() == accesskeyAttr) {
       
  1141         // FIXME: ignore for the moment
       
  1142     } else if (attr->name() == vspaceAttr) {
       
  1143         addCSSLength(attr, CSSPropertyMarginTop, attr->value());
       
  1144         addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
       
  1145     } else if (attr->name() == hspaceAttr) {
       
  1146         addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
       
  1147         addCSSLength(attr, CSSPropertyMarginRight, attr->value());
       
  1148     } else if (attr->name() == alignAttr) {
       
  1149         if (inputType() == IMAGE)
       
  1150             addHTMLAlignment(attr);
       
  1151     } else if (attr->name() == widthAttr) {
       
  1152         if (respectHeightAndWidthAttrs())
       
  1153             addCSSLength(attr, CSSPropertyWidth, attr->value());
       
  1154     } else if (attr->name() == heightAttr) {
       
  1155         if (respectHeightAndWidthAttrs())
       
  1156             addCSSLength(attr, CSSPropertyHeight, attr->value());
       
  1157     } else if (attr->name() == onsearchAttr) {
       
  1158         // Search field and slider attributes all just cause updateFromElement to be called through style recalcing.
       
  1159         setAttributeEventListener(eventNames().searchEvent, createAttributeEventListener(this, attr));
       
  1160     } else if (attr->name() == resultsAttr) {
       
  1161         int oldResults = m_maxResults;
       
  1162         m_maxResults = !attr->isNull() ? std::min(attr->value().toInt(), maxSavedResults) : -1;
       
  1163         // FIXME: Detaching just for maxResults change is not ideal.  We should figure out the right
       
  1164         // time to relayout for this change.
       
  1165         if (m_maxResults != oldResults && (m_maxResults <= 0 || oldResults <= 0) && attached()) {
       
  1166             detach();
       
  1167             attach();
       
  1168         }
       
  1169         setNeedsStyleRecalc();
       
  1170     } else if (attr->name() == autosaveAttr
       
  1171                || attr->name() == incrementalAttr)
       
  1172         setNeedsStyleRecalc();
       
  1173     else if (attr->name() == minAttr
       
  1174              || attr->name() == maxAttr) {
       
  1175         if (inputType() == RANGE) {
       
  1176             // Sanitize the value.
       
  1177             setValue(value());
       
  1178             setNeedsStyleRecalc();
       
  1179         }
       
  1180         setNeedsValidityCheck();
       
  1181     } else if (attr->name() == multipleAttr
       
  1182              || attr->name() == patternAttr
       
  1183              || attr->name() == precisionAttr
       
  1184              || attr->name() == stepAttr)
       
  1185         setNeedsValidityCheck();
       
  1186 #if ENABLE(DATALIST)
       
  1187     else if (attr->name() == listAttr)
       
  1188         m_hasNonEmptyList = !attr->isEmpty();
       
  1189         // FIXME: we need to tell this change to a renderer if the attribute affects the appearance.
       
  1190 #endif
       
  1191 #if ENABLE(INPUT_SPEECH)
       
  1192     else if (attr->name() == speechAttr) {
       
  1193       if (renderer())
       
  1194           renderer()->updateFromElement();
       
  1195       setNeedsStyleRecalc();
       
  1196     }
       
  1197 #endif
       
  1198     else
       
  1199         HTMLTextFormControlElement::parseMappedAttribute(attr);
       
  1200 }
       
  1201 
       
  1202 bool HTMLInputElement::rendererIsNeeded(RenderStyle *style)
       
  1203 {
       
  1204     if (inputType() == HIDDEN)
       
  1205         return false;
       
  1206     return HTMLFormControlElementWithState::rendererIsNeeded(style);
       
  1207 }
       
  1208 
       
  1209 RenderObject* HTMLInputElement::createRenderer(RenderArena *arena, RenderStyle *style)
       
  1210 {
       
  1211     switch (inputType()) {
       
  1212     case BUTTON:
       
  1213     case RESET:
       
  1214     case SUBMIT:
       
  1215         return new (arena) RenderButton(this);
       
  1216     case CHECKBOX:
       
  1217     case RADIO:
       
  1218         return RenderObject::createObject(this, style);
       
  1219     case FILE:
       
  1220         return new (arena) RenderFileUploadControl(this);
       
  1221     case HIDDEN:
       
  1222         break;
       
  1223     case IMAGE:
       
  1224         return new (arena) RenderImage(this);
       
  1225     case RANGE:
       
  1226         return new (arena) RenderSlider(this);
       
  1227     case COLOR:
       
  1228     case DATE:
       
  1229     case DATETIME:
       
  1230     case DATETIMELOCAL:
       
  1231     case EMAIL:
       
  1232     case ISINDEX:
       
  1233     case MONTH:
       
  1234     case NUMBER:
       
  1235     case PASSWORD:
       
  1236     case SEARCH:
       
  1237     case TELEPHONE:
       
  1238     case TEXT:
       
  1239     case TIME:
       
  1240     case URL:
       
  1241     case WEEK:
       
  1242         return new (arena) RenderTextControlSingleLine(this, placeholderShouldBeVisible());
       
  1243     }
       
  1244     ASSERT(false);
       
  1245     return 0;
       
  1246 }
       
  1247 
       
  1248 void HTMLInputElement::attach()
       
  1249 {
       
  1250     if (!m_inited) {
       
  1251         if (!m_haveType)
       
  1252             setInputType(getAttribute(typeAttr));
       
  1253         m_inited = true;
       
  1254     }
       
  1255 
       
  1256     HTMLFormControlElementWithState::attach();
       
  1257 
       
  1258     if (inputType() == IMAGE) {
       
  1259         if (!m_imageLoader)
       
  1260             m_imageLoader.set(new HTMLImageLoader(this));
       
  1261         m_imageLoader->updateFromElement();
       
  1262         if (renderer() && m_imageLoader->haveFiredBeforeLoadEvent()) {
       
  1263             RenderImage* imageObj = toRenderImage(renderer());
       
  1264             imageObj->setCachedImage(m_imageLoader->image()); 
       
  1265             
       
  1266             // If we have no image at all because we have no src attribute, set
       
  1267             // image height and width for the alt text instead.
       
  1268             if (!m_imageLoader->image() && !imageObj->cachedImage())
       
  1269                 imageObj->setImageSizeForAltText();
       
  1270         }
       
  1271     }
       
  1272 
       
  1273     if (inputType() == RADIO)
       
  1274         updateCheckedRadioButtons();
       
  1275 
       
  1276     if (document()->focusedNode() == this)
       
  1277         document()->updateFocusAppearanceSoon(true /* restore selection */);
       
  1278 }
       
  1279 
       
  1280 void HTMLInputElement::detach()
       
  1281 {
       
  1282     HTMLFormControlElementWithState::detach();
       
  1283     setFormControlValueMatchesRenderer(false);
       
  1284 }
       
  1285 
       
  1286 String HTMLInputElement::altText() const
       
  1287 {
       
  1288     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
       
  1289     // also heavily discussed by Hixie on bugzilla
       
  1290     // note this is intentionally different to HTMLImageElement::altText()
       
  1291     String alt = getAttribute(altAttr);
       
  1292     // fall back to title attribute
       
  1293     if (alt.isNull())
       
  1294         alt = getAttribute(titleAttr);
       
  1295     if (alt.isNull())
       
  1296         alt = getAttribute(valueAttr);
       
  1297     if (alt.isEmpty())
       
  1298         alt = inputElementAltText();
       
  1299     return alt;
       
  1300 }
       
  1301 
       
  1302 bool HTMLInputElement::isSuccessfulSubmitButton() const
       
  1303 {
       
  1304     // HTML spec says that buttons must have names to be considered successful.
       
  1305     // However, other browsers do not impose this constraint. So we do likewise.
       
  1306     return !disabled() && (inputType() == IMAGE || inputType() == SUBMIT);
       
  1307 }
       
  1308 
       
  1309 bool HTMLInputElement::isActivatedSubmit() const
       
  1310 {
       
  1311     return m_activeSubmit;
       
  1312 }
       
  1313 
       
  1314 void HTMLInputElement::setActivatedSubmit(bool flag)
       
  1315 {
       
  1316     m_activeSubmit = flag;
       
  1317 }
       
  1318 
       
  1319 bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart)
       
  1320 {
       
  1321     // image generates its own names, but for other types there is no form data unless there's a name
       
  1322     if (name().isEmpty() && inputType() != IMAGE)
       
  1323         return false;
       
  1324 
       
  1325     switch (inputType()) {
       
  1326     case COLOR:
       
  1327     case DATE:
       
  1328     case DATETIME:
       
  1329     case DATETIMELOCAL:
       
  1330     case EMAIL:
       
  1331     case HIDDEN:
       
  1332     case ISINDEX:
       
  1333     case MONTH:
       
  1334     case NUMBER:
       
  1335     case PASSWORD:
       
  1336     case RANGE:
       
  1337     case SEARCH:
       
  1338     case TELEPHONE:
       
  1339     case TEXT:
       
  1340     case TIME:
       
  1341     case URL:
       
  1342     case WEEK:
       
  1343         // always successful
       
  1344         encoding.appendData(name(), value());
       
  1345         return true;
       
  1346 
       
  1347     case CHECKBOX:
       
  1348     case RADIO:
       
  1349         if (checked()) {
       
  1350             encoding.appendData(name(), value());
       
  1351             return true;
       
  1352         }
       
  1353         break;
       
  1354 
       
  1355     case BUTTON:
       
  1356     case RESET:
       
  1357         // these types of buttons are never successful
       
  1358         return false;
       
  1359 
       
  1360     case IMAGE:
       
  1361         if (m_activeSubmit) {
       
  1362             encoding.appendData(name().isEmpty() ? "x" : (name() + ".x"), m_xPos);
       
  1363             encoding.appendData(name().isEmpty() ? "y" : (name() + ".y"), m_yPos);
       
  1364             if (!name().isEmpty() && !value().isEmpty())
       
  1365                 encoding.appendData(name(), value());
       
  1366             return true;
       
  1367         }
       
  1368         break;
       
  1369 
       
  1370     case SUBMIT:
       
  1371         if (m_activeSubmit) {
       
  1372             String encstr = valueWithDefault();
       
  1373             encoding.appendData(name(), encstr);
       
  1374             return true;
       
  1375         }
       
  1376         break;
       
  1377 
       
  1378     case FILE: {
       
  1379         unsigned numFiles = m_fileList->length();
       
  1380         if (!multipart) {
       
  1381             // Send only the basenames.
       
  1382             // 4.10.16.4 and 4.10.16.6 sections in HTML5.
       
  1383     
       
  1384             // Unlike the multipart case, we have no special
       
  1385             // handling for the empty fileList because Netscape
       
  1386             // doesn't support for non-multipart submission of
       
  1387             // file inputs, and Firefox doesn't add "name=" query
       
  1388             // parameter.
       
  1389 
       
  1390             for (unsigned i = 0; i < numFiles; ++i) 
       
  1391                 encoding.appendData(name(), m_fileList->item(i)->fileName());
       
  1392             return true;
       
  1393         }
       
  1394 
       
  1395         // If no filename at all is entered, return successful but empty.
       
  1396         // Null would be more logical, but Netscape posts an empty file. Argh.
       
  1397         if (!numFiles) {
       
  1398             encoding.appendBlob(name(), File::create(""));
       
  1399             return true;
       
  1400         }
       
  1401 
       
  1402         for (unsigned i = 0; i < numFiles; ++i)
       
  1403             encoding.appendBlob(name(), m_fileList->item(i));
       
  1404         return true;
       
  1405         }
       
  1406     }
       
  1407     return false;
       
  1408 }
       
  1409 
       
  1410 void HTMLInputElement::reset()
       
  1411 {
       
  1412     if (storesValueSeparateFromAttribute())
       
  1413         setValue(String());
       
  1414 
       
  1415     setChecked(m_defaultChecked);
       
  1416     m_useDefaultChecked = true;
       
  1417 }
       
  1418 
       
  1419 bool HTMLInputElement::isTextField() const
       
  1420 {
       
  1421     switch (inputType()) {
       
  1422     case COLOR:
       
  1423     case DATE:
       
  1424     case DATETIME:
       
  1425     case DATETIMELOCAL:
       
  1426     case EMAIL:
       
  1427     case ISINDEX:
       
  1428     case MONTH:
       
  1429     case NUMBER:
       
  1430     case PASSWORD:
       
  1431     case SEARCH:
       
  1432     case TELEPHONE:
       
  1433     case TEXT:
       
  1434     case TIME:
       
  1435     case URL:
       
  1436     case WEEK:
       
  1437         return true;
       
  1438     case BUTTON:
       
  1439     case CHECKBOX:
       
  1440     case FILE:
       
  1441     case HIDDEN:
       
  1442     case IMAGE:
       
  1443     case RADIO:
       
  1444     case RANGE:
       
  1445     case RESET:
       
  1446     case SUBMIT:
       
  1447         return false;
       
  1448     }
       
  1449     ASSERT_NOT_REACHED();
       
  1450     return false;
       
  1451 }
       
  1452 
       
  1453 void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent)
       
  1454 {
       
  1455     if (checked() == nowChecked)
       
  1456         return;
       
  1457 
       
  1458     checkedRadioButtons(this).removeButton(this);
       
  1459 
       
  1460     m_useDefaultChecked = false;
       
  1461     m_checked = nowChecked;
       
  1462     setNeedsStyleRecalc();
       
  1463 
       
  1464     updateCheckedRadioButtons();
       
  1465 
       
  1466     // Ideally we'd do this from the render tree (matching
       
  1467     // RenderTextView), but it's not possible to do it at the moment
       
  1468     // because of the way the code is structured.
       
  1469     if (renderer() && AXObjectCache::accessibilityEnabled())
       
  1470         renderer()->document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXCheckedStateChanged, true);
       
  1471 
       
  1472     // Only send a change event for items in the document (avoid firing during
       
  1473     // parsing) and don't send a change event for a radio button that's getting
       
  1474     // unchecked to match other browsers. DOM is not a useful standard for this
       
  1475     // because it says only to fire change events at "lose focus" time, which is
       
  1476     // definitely wrong in practice for these types of elements.
       
  1477     if (sendChangeEvent && inDocument() && (inputType() != RADIO || nowChecked))
       
  1478         dispatchFormControlChangeEvent();
       
  1479 }
       
  1480 
       
  1481 void HTMLInputElement::setIndeterminate(bool newValue)
       
  1482 {
       
  1483     // Only checkboxes and radio buttons honor indeterminate.
       
  1484     if (!allowsIndeterminate() || indeterminate() == newValue)
       
  1485         return;
       
  1486 
       
  1487     m_indeterminate = newValue;
       
  1488 
       
  1489     setNeedsStyleRecalc();
       
  1490 
       
  1491     if (renderer() && renderer()->style()->hasAppearance())
       
  1492         renderer()->theme()->stateChanged(renderer(), CheckedState);
       
  1493 }
       
  1494 
       
  1495 int HTMLInputElement::size() const
       
  1496 {
       
  1497     return m_data.size();
       
  1498 }
       
  1499 
       
  1500 void HTMLInputElement::copyNonAttributeProperties(const Element* source)
       
  1501 {
       
  1502     const HTMLInputElement* sourceElement = static_cast<const HTMLInputElement*>(source);
       
  1503 
       
  1504     m_data.setValue(sourceElement->m_data.value());
       
  1505     setChecked(sourceElement->m_checked);
       
  1506     m_defaultChecked = sourceElement->m_defaultChecked;
       
  1507     m_useDefaultChecked = sourceElement->m_useDefaultChecked;
       
  1508     m_indeterminate = sourceElement->m_indeterminate;
       
  1509 
       
  1510     HTMLFormControlElementWithState::copyNonAttributeProperties(source);
       
  1511 }
       
  1512 
       
  1513 String HTMLInputElement::value() const
       
  1514 {
       
  1515     // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't applicable to the file upload control
       
  1516     // but we don't want to break existing websites, who may be relying on being able to get the file name as a value.
       
  1517     if (inputType() == FILE) {
       
  1518         if (!m_fileList->isEmpty())
       
  1519             return m_fileList->item(0)->fileName();
       
  1520         return String();
       
  1521     }
       
  1522 
       
  1523     String value = m_data.value();
       
  1524     if (value.isNull()) {
       
  1525         value = sanitizeValue(fastGetAttribute(valueAttr));
       
  1526         
       
  1527         // If no attribute exists, extra handling may be necessary.
       
  1528         // For Checkbox Types just use "on" or "" based off the checked() state of the control.
       
  1529         // For a Range Input use the calculated default value.
       
  1530         if (value.isNull()) {
       
  1531             if (inputType() == CHECKBOX || inputType() == RADIO)
       
  1532                 return checked() ? "on" : "";
       
  1533             if (inputType() == RANGE)
       
  1534                 return serializeForNumberType(StepRange(this).defaultValue());
       
  1535         }
       
  1536     }
       
  1537 
       
  1538     return value;
       
  1539 }
       
  1540 
       
  1541 String HTMLInputElement::valueWithDefault() const
       
  1542 {
       
  1543     String v = value();
       
  1544     if (v.isNull()) {
       
  1545         switch (inputType()) {
       
  1546         case BUTTON:
       
  1547         case CHECKBOX:
       
  1548         case COLOR:
       
  1549         case DATE:
       
  1550         case DATETIME:
       
  1551         case DATETIMELOCAL:
       
  1552         case EMAIL:
       
  1553         case FILE:
       
  1554         case HIDDEN:
       
  1555         case IMAGE:
       
  1556         case ISINDEX:
       
  1557         case MONTH:
       
  1558         case NUMBER:
       
  1559         case PASSWORD:
       
  1560         case RADIO:
       
  1561         case RANGE:
       
  1562         case SEARCH:
       
  1563         case TELEPHONE:
       
  1564         case TEXT:
       
  1565         case TIME:
       
  1566         case URL:
       
  1567         case WEEK:
       
  1568             break;
       
  1569         case RESET:
       
  1570             v = resetButtonDefaultLabel();
       
  1571             break;
       
  1572         case SUBMIT:
       
  1573             v = submitButtonDefaultLabel();
       
  1574             break;
       
  1575         }
       
  1576     }
       
  1577     return v;
       
  1578 }
       
  1579 
       
  1580 void HTMLInputElement::setValueForUser(const String& value)
       
  1581 {
       
  1582     // Call setValue and make it send a change event.
       
  1583     setValue(value, true);
       
  1584 }
       
  1585 
       
  1586 const String& HTMLInputElement::suggestedValue() const
       
  1587 {
       
  1588     return m_data.suggestedValue();
       
  1589 }
       
  1590 
       
  1591 void HTMLInputElement::setSuggestedValue(const String& value)
       
  1592 {
       
  1593     if (inputType() != TEXT)
       
  1594         return;
       
  1595     setFormControlValueMatchesRenderer(false);
       
  1596     m_data.setSuggestedValue(sanitizeValue(value));
       
  1597     updatePlaceholderVisibility(false);
       
  1598     if (renderer())
       
  1599         renderer()->updateFromElement();
       
  1600     setNeedsStyleRecalc();
       
  1601 }
       
  1602 
       
  1603 void HTMLInputElement::setValue(const String& value, bool sendChangeEvent)
       
  1604 {
       
  1605     // For security reasons, we don't allow setting the filename, but we do allow clearing it.
       
  1606     // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't applicable to the file upload control
       
  1607     // but we don't want to break existing websites, who may be relying on this method to clear things.
       
  1608     if (inputType() == FILE && !value.isEmpty())
       
  1609         return;
       
  1610 
       
  1611     setFormControlValueMatchesRenderer(false);
       
  1612     if (storesValueSeparateFromAttribute()) {
       
  1613         if (inputType() == FILE)
       
  1614             m_fileList->clear();
       
  1615         else {
       
  1616             m_data.setValue(sanitizeValue(value));
       
  1617             if (isTextField())
       
  1618                 updatePlaceholderVisibility(false);
       
  1619         }
       
  1620         setNeedsStyleRecalc();
       
  1621     } else
       
  1622         setAttribute(valueAttr, sanitizeValue(value));
       
  1623 
       
  1624     setNeedsValidityCheck();
       
  1625 
       
  1626     if (isTextField()) {
       
  1627         unsigned max = m_data.value().length();
       
  1628         if (document()->focusedNode() == this)
       
  1629             InputElement::updateSelectionRange(this, this, max, max);
       
  1630         else
       
  1631             cacheSelection(max, max);
       
  1632         m_data.setSuggestedValue(String());
       
  1633     }
       
  1634 
       
  1635     // Don't dispatch the change event when focused, it will be dispatched
       
  1636     // when the control loses focus.
       
  1637     if (sendChangeEvent && document()->focusedNode() != this)
       
  1638         dispatchFormControlChangeEvent();
       
  1639 
       
  1640     InputElement::notifyFormStateChanged(this);
       
  1641 }
       
  1642 
       
  1643 double HTMLInputElement::parseToDouble(const String& src, double defaultValue) const
       
  1644 {
       
  1645     switch (inputType()) {
       
  1646     case DATE:
       
  1647     case DATETIME:
       
  1648     case DATETIMELOCAL:
       
  1649     case TIME:
       
  1650     case WEEK: {
       
  1651         DateComponents date;
       
  1652         if (!parseToDateComponents(inputType(), src, &date))
       
  1653             return defaultValue;
       
  1654         double msec = date.millisecondsSinceEpoch();
       
  1655         ASSERT(isfinite(msec));
       
  1656         return msec;
       
  1657     }
       
  1658     case MONTH: {
       
  1659         DateComponents date;
       
  1660         if (!parseToDateComponents(inputType(), src, &date))
       
  1661             return defaultValue;
       
  1662         double months = date.monthsSinceEpoch();
       
  1663         ASSERT(isfinite(months));
       
  1664         return months;
       
  1665     }
       
  1666     case NUMBER:
       
  1667     case RANGE: {
       
  1668         double numberValue;
       
  1669         if (!parseToDoubleForNumberType(src, &numberValue))
       
  1670             return defaultValue;
       
  1671         ASSERT(isfinite(numberValue));
       
  1672         return numberValue;
       
  1673     }
       
  1674 
       
  1675     case BUTTON:
       
  1676     case CHECKBOX:
       
  1677     case COLOR:
       
  1678     case EMAIL:
       
  1679     case FILE:
       
  1680     case HIDDEN:
       
  1681     case IMAGE:
       
  1682     case ISINDEX:
       
  1683     case PASSWORD:
       
  1684     case RADIO:
       
  1685     case RESET:
       
  1686     case SEARCH:
       
  1687     case SUBMIT:
       
  1688     case TELEPHONE:
       
  1689     case TEXT:
       
  1690     case URL:
       
  1691         return defaultValue;
       
  1692     }
       
  1693     ASSERT_NOT_REACHED();
       
  1694     return defaultValue;
       
  1695 }
       
  1696 
       
  1697 double HTMLInputElement::valueAsDate() const
       
  1698 {
       
  1699     switch (inputType()) {
       
  1700     case DATE:
       
  1701     case DATETIME:
       
  1702     case TIME:
       
  1703     case WEEK:
       
  1704         return parseToDouble(value(), DateComponents::invalidMilliseconds());
       
  1705     case MONTH: {
       
  1706         DateComponents date;
       
  1707         if (!parseToDateComponents(inputType(), value(), &date))
       
  1708             return DateComponents::invalidMilliseconds();
       
  1709         double msec = date.millisecondsSinceEpoch();
       
  1710         ASSERT(isfinite(msec));
       
  1711         return msec;
       
  1712     }
       
  1713 
       
  1714     case BUTTON:
       
  1715     case CHECKBOX:
       
  1716     case COLOR:
       
  1717     case DATETIMELOCAL: // valueAsDate doesn't work for the DATETIMELOCAL type according to the standard.
       
  1718     case EMAIL:
       
  1719     case FILE:
       
  1720     case HIDDEN:
       
  1721     case IMAGE:
       
  1722     case ISINDEX:
       
  1723     case NUMBER:
       
  1724     case PASSWORD:
       
  1725     case RADIO:
       
  1726     case RANGE:
       
  1727     case RESET:
       
  1728     case SEARCH:
       
  1729     case SUBMIT:
       
  1730     case TELEPHONE:
       
  1731     case TEXT:
       
  1732     case URL:
       
  1733         return DateComponents::invalidMilliseconds();
       
  1734     }
       
  1735     ASSERT_NOT_REACHED();
       
  1736     return DateComponents::invalidMilliseconds();
       
  1737 }
       
  1738 
       
  1739 void HTMLInputElement::setValueAsDate(double value, ExceptionCode& ec)
       
  1740 {
       
  1741     switch (inputType()) {
       
  1742     case DATE:
       
  1743     case DATETIME:
       
  1744     case TIME:
       
  1745     case WEEK:
       
  1746         setValue(serializeForDateTimeTypes(value));
       
  1747         return;
       
  1748     case MONTH: {
       
  1749         DateComponents date;
       
  1750         if (!date.setMillisecondsSinceEpochForMonth(value)) {
       
  1751             setValue(String());
       
  1752             return;
       
  1753         }
       
  1754         setValue(date.toString());
       
  1755         return;
       
  1756     }
       
  1757     case BUTTON:
       
  1758     case CHECKBOX:
       
  1759     case COLOR:
       
  1760     case DATETIMELOCAL: // valueAsDate doesn't work for the DATETIMELOCAL type according to the standard.
       
  1761     case EMAIL:
       
  1762     case FILE:
       
  1763     case HIDDEN:
       
  1764     case IMAGE:
       
  1765     case ISINDEX:
       
  1766     case NUMBER:
       
  1767     case PASSWORD:
       
  1768     case RADIO:
       
  1769     case RANGE:
       
  1770     case RESET:
       
  1771     case SEARCH:
       
  1772     case SUBMIT:
       
  1773     case TELEPHONE:
       
  1774     case TEXT:
       
  1775     case URL:
       
  1776         ec = INVALID_STATE_ERR;
       
  1777         return;
       
  1778     }
       
  1779     ASSERT_NOT_REACHED();
       
  1780 }
       
  1781 
       
  1782 double HTMLInputElement::valueAsNumber() const
       
  1783 {
       
  1784     const double nan = numeric_limits<double>::quiet_NaN();
       
  1785     switch (inputType()) {
       
  1786     case DATE:
       
  1787     case DATETIME:
       
  1788     case DATETIMELOCAL:
       
  1789     case MONTH:
       
  1790     case NUMBER:
       
  1791     case RANGE:
       
  1792     case TIME:
       
  1793     case WEEK:
       
  1794         return parseToDouble(value(), nan);
       
  1795 
       
  1796     case BUTTON:
       
  1797     case CHECKBOX:
       
  1798     case COLOR:
       
  1799     case EMAIL:
       
  1800     case FILE:
       
  1801     case HIDDEN:
       
  1802     case IMAGE:
       
  1803     case ISINDEX:
       
  1804     case PASSWORD:
       
  1805     case RADIO:
       
  1806     case RESET:
       
  1807     case SEARCH:
       
  1808     case SUBMIT:
       
  1809     case TELEPHONE:
       
  1810     case TEXT:
       
  1811     case URL:
       
  1812         return nan;
       
  1813     }
       
  1814     ASSERT_NOT_REACHED();
       
  1815     return nan;
       
  1816 }
       
  1817 
       
  1818 void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec)
       
  1819 {
       
  1820     if (!isfinite(newValue)) {
       
  1821         ec = NOT_SUPPORTED_ERR;
       
  1822         return;
       
  1823     }
       
  1824     switch (inputType()) {
       
  1825     case DATE:
       
  1826     case DATETIME:
       
  1827     case DATETIMELOCAL:
       
  1828     case MONTH:
       
  1829     case NUMBER:
       
  1830     case RANGE:
       
  1831     case TIME:
       
  1832     case WEEK:
       
  1833         setValue(serialize(newValue));
       
  1834         return;
       
  1835 
       
  1836     case BUTTON:
       
  1837     case CHECKBOX:
       
  1838     case COLOR:
       
  1839     case EMAIL:
       
  1840     case FILE:
       
  1841     case HIDDEN:
       
  1842     case IMAGE:
       
  1843     case ISINDEX:
       
  1844     case PASSWORD:
       
  1845     case RADIO:
       
  1846     case RESET:
       
  1847     case SEARCH:
       
  1848     case SUBMIT:
       
  1849     case TELEPHONE:
       
  1850     case TEXT:
       
  1851     case URL:
       
  1852         ec = INVALID_STATE_ERR;
       
  1853         return;
       
  1854     }
       
  1855     ASSERT_NOT_REACHED();
       
  1856 }
       
  1857 
       
  1858 String HTMLInputElement::serializeForDateTimeTypes(double value) const
       
  1859 {
       
  1860     bool success = false;
       
  1861     DateComponents date;
       
  1862     switch (inputType()) {
       
  1863     case DATE:
       
  1864         success = date.setMillisecondsSinceEpochForDate(value);
       
  1865         break;
       
  1866     case DATETIME:
       
  1867         success = date.setMillisecondsSinceEpochForDateTime(value);
       
  1868         break;
       
  1869     case DATETIMELOCAL:
       
  1870         success = date.setMillisecondsSinceEpochForDateTimeLocal(value);
       
  1871         break;
       
  1872     case MONTH:
       
  1873         success = date.setMonthsSinceEpoch(value);
       
  1874         break;
       
  1875     case TIME:
       
  1876         success = date.setMillisecondsSinceMidnight(value);
       
  1877         break;
       
  1878     case WEEK:
       
  1879         success = date.setMillisecondsSinceEpochForWeek(value);
       
  1880         break;
       
  1881     case NUMBER:
       
  1882     case RANGE:
       
  1883     case BUTTON:
       
  1884     case CHECKBOX:
       
  1885     case COLOR:
       
  1886     case EMAIL:
       
  1887     case FILE:
       
  1888     case HIDDEN:
       
  1889     case IMAGE:
       
  1890     case ISINDEX:
       
  1891     case PASSWORD:
       
  1892     case RADIO:
       
  1893     case RESET:
       
  1894     case SEARCH:
       
  1895     case SUBMIT:
       
  1896     case TELEPHONE:
       
  1897     case TEXT:
       
  1898     case URL:
       
  1899         ASSERT_NOT_REACHED();
       
  1900         return String();
       
  1901     }
       
  1902     if (!success)
       
  1903         return String();
       
  1904 
       
  1905     double step;
       
  1906     if (!getAllowedValueStep(&step))
       
  1907         return date.toString();
       
  1908     if (!fmod(step, msecPerMinute))
       
  1909         return date.toString(DateComponents::None);
       
  1910     if (!fmod(step, msecPerSecond))
       
  1911         return date.toString(DateComponents::Second);
       
  1912     return date.toString(DateComponents::Millisecond);
       
  1913 }
       
  1914 
       
  1915 String HTMLInputElement::serialize(double value) const
       
  1916 {
       
  1917     if (!isfinite(value))
       
  1918         return String();
       
  1919     switch (inputType()) {
       
  1920     case DATE:
       
  1921     case DATETIME:
       
  1922     case DATETIMELOCAL:
       
  1923     case MONTH:
       
  1924     case TIME:
       
  1925     case WEEK:
       
  1926         return serializeForDateTimeTypes(value);
       
  1927     case NUMBER:
       
  1928     case RANGE:
       
  1929         return serializeForNumberType(value);
       
  1930 
       
  1931     case BUTTON:
       
  1932     case CHECKBOX:
       
  1933     case COLOR:
       
  1934     case EMAIL:
       
  1935     case FILE:
       
  1936     case HIDDEN:
       
  1937     case IMAGE:
       
  1938     case ISINDEX:
       
  1939     case PASSWORD:
       
  1940     case RADIO:
       
  1941     case RESET:
       
  1942     case SEARCH:
       
  1943     case SUBMIT:
       
  1944     case TELEPHONE:
       
  1945     case TEXT:
       
  1946     case URL:
       
  1947         break;
       
  1948     }
       
  1949     ASSERT_NOT_REACHED();
       
  1950     return String();
       
  1951 }
       
  1952 
       
  1953 String HTMLInputElement::placeholder() const
       
  1954 {
       
  1955     return getAttribute(placeholderAttr).string();
       
  1956 }
       
  1957 
       
  1958 void HTMLInputElement::setPlaceholder(const String& value)
       
  1959 {
       
  1960     setAttribute(placeholderAttr, value);
       
  1961 }
       
  1962 
       
  1963 bool HTMLInputElement::searchEventsShouldBeDispatched() const
       
  1964 {
       
  1965     return hasAttribute(incrementalAttr);
       
  1966 }
       
  1967 
       
  1968 void HTMLInputElement::setValueFromRenderer(const String& value)
       
  1969 {
       
  1970     // File upload controls will always use setFileListFromRenderer.
       
  1971     ASSERT(inputType() != FILE);
       
  1972     m_data.setSuggestedValue(String());
       
  1973     updatePlaceholderVisibility(false);
       
  1974     InputElement::setValueFromRenderer(m_data, this, this, value);
       
  1975     setNeedsValidityCheck();
       
  1976 
       
  1977     // Clear autofill flag (and yellow background) on user edit.
       
  1978     setAutofilled(false);
       
  1979 }
       
  1980 
       
  1981 void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths)
       
  1982 {
       
  1983     m_fileList->clear();
       
  1984     int size = paths.size();
       
  1985 
       
  1986 #if ENABLE(DIRECTORY_UPLOAD)
       
  1987     // If a directory is being selected, the UI allows a directory to be chosen
       
  1988     // and the paths provided here share a root directory somewhere up the tree;
       
  1989     // we want to store only the relative paths from that point.
       
  1990     if (webkitdirectory() && size > 0) {
       
  1991         String rootPath = directoryName(paths[0]);
       
  1992         // Find the common root path.
       
  1993         for (int i = 1; i < size; i++) {
       
  1994             while (!paths[i].startsWith(rootPath))
       
  1995                 rootPath = directoryName(rootPath);
       
  1996         }
       
  1997         rootPath = directoryName(rootPath);
       
  1998         ASSERT(rootPath.length());
       
  1999         for (int i = 0; i < size; i++)
       
  2000             m_fileList->append(File::create(paths[i].substring(1 + rootPath.length()), paths[i]));
       
  2001     } else {
       
  2002         for (int i = 0; i < size; i++)
       
  2003             m_fileList->append(File::create(paths[i]));
       
  2004     }
       
  2005 #else
       
  2006     for (int i = 0; i < size; i++)
       
  2007         m_fileList->append(File::create(paths[i]));
       
  2008 #endif
       
  2009 
       
  2010     setFormControlValueMatchesRenderer(true);
       
  2011     InputElement::notifyFormStateChanged(this);
       
  2012     setNeedsValidityCheck();
       
  2013 }
       
  2014 
       
  2015 bool HTMLInputElement::storesValueSeparateFromAttribute() const
       
  2016 {
       
  2017     switch (inputType()) {
       
  2018     case BUTTON:
       
  2019     case CHECKBOX:
       
  2020     case HIDDEN:
       
  2021     case IMAGE:
       
  2022     case RADIO:
       
  2023     case RESET:
       
  2024     case SUBMIT:
       
  2025         return false;
       
  2026     case COLOR:
       
  2027     case DATE:
       
  2028     case DATETIME:
       
  2029     case DATETIMELOCAL:
       
  2030     case EMAIL:
       
  2031     case FILE:
       
  2032     case ISINDEX:
       
  2033     case MONTH:
       
  2034     case NUMBER:
       
  2035     case PASSWORD:
       
  2036     case RANGE:
       
  2037     case SEARCH:
       
  2038     case TELEPHONE:
       
  2039     case TEXT:
       
  2040     case TIME:
       
  2041     case URL:
       
  2042     case WEEK:
       
  2043         return true;
       
  2044     }
       
  2045     return false;
       
  2046 }
       
  2047 
       
  2048 struct EventHandlingState {
       
  2049     RefPtr<HTMLInputElement> m_currRadio;
       
  2050     bool m_indeterminate;
       
  2051     bool m_checked;
       
  2052     
       
  2053     EventHandlingState(bool indeterminate, bool checked)
       
  2054         : m_indeterminate(indeterminate)
       
  2055         , m_checked(checked) { }
       
  2056 };
       
  2057 
       
  2058 void* HTMLInputElement::preDispatchEventHandler(Event *evt)
       
  2059 {
       
  2060     // preventDefault or "return false" are used to reverse the automatic checking/selection we do here.
       
  2061     // This result gives us enough info to perform the "undo" in postDispatch of the action we take here.
       
  2062     void* result = 0; 
       
  2063     if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent()
       
  2064             && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
       
  2065         
       
  2066         EventHandlingState* state = new EventHandlingState(indeterminate(), checked());
       
  2067 
       
  2068         if (inputType() == CHECKBOX) {
       
  2069             if (indeterminate())
       
  2070                 setIndeterminate(false);
       
  2071             else
       
  2072                 setChecked(!checked(), true);
       
  2073         } else {
       
  2074             // For radio buttons, store the current selected radio object.
       
  2075             // We really want radio groups to end up in sane states, i.e., to have something checked.
       
  2076             // Therefore if nothing is currently selected, we won't allow this action to be "undone", since
       
  2077             // we want some object in the radio group to actually get selected.
       
  2078             HTMLInputElement* currRadio = checkedRadioButtons(this).checkedButtonForGroup(name());
       
  2079             if (currRadio) {
       
  2080                 // We have a radio button selected that is not us.  Cache it in our result field and ref it so
       
  2081                 // that it can't be destroyed.
       
  2082                 state->m_currRadio = currRadio;
       
  2083             }
       
  2084             if (indeterminate())
       
  2085                 setIndeterminate(false);
       
  2086             setChecked(true, true);
       
  2087         }
       
  2088         result = state;
       
  2089     }
       
  2090     return result;
       
  2091 }
       
  2092 
       
  2093 void HTMLInputElement::postDispatchEventHandler(Event *evt, void* data)
       
  2094 {
       
  2095     if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent()
       
  2096             && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
       
  2097         
       
  2098         if (EventHandlingState* state = reinterpret_cast<EventHandlingState*>(data)) {
       
  2099             if (inputType() == CHECKBOX) {
       
  2100                 // Reverse the checking we did in preDispatch.
       
  2101                 if (evt->defaultPrevented() || evt->defaultHandled()) {
       
  2102                     setIndeterminate(state->m_indeterminate);
       
  2103                     setChecked(state->m_checked);
       
  2104                 }
       
  2105             } else {
       
  2106                 HTMLInputElement* input = state->m_currRadio.get();
       
  2107                 if (evt->defaultPrevented() || evt->defaultHandled()) {
       
  2108                     // Restore the original selected radio button if possible.
       
  2109                     // Make sure it is still a radio button and only do the restoration if it still
       
  2110                     // belongs to our group.
       
  2111 
       
  2112                     if (input && input->form() == form() && input->inputType() == RADIO && input->name() == name()) {
       
  2113                         // Ok, the old radio button is still in our form and in our group and is still a 
       
  2114                         // radio button, so it's safe to restore selection to it.
       
  2115                         input->setChecked(true);
       
  2116                     }
       
  2117                     setIndeterminate(state->m_indeterminate);
       
  2118                 }
       
  2119             }
       
  2120             delete state;
       
  2121         }
       
  2122 
       
  2123         // Left clicks on radio buttons and check boxes already performed default actions in preDispatchEventHandler(). 
       
  2124         evt->setDefaultHandled();
       
  2125     }
       
  2126 }
       
  2127 
       
  2128 void HTMLInputElement::defaultEventHandler(Event* evt)
       
  2129 {
       
  2130     // FIXME: It would be better to refactor this for the different types of input element.
       
  2131     // Having them all in one giant function makes this hard to read, and almost all the handling is type-specific.
       
  2132 
       
  2133     bool implicitSubmission = false;
       
  2134 
       
  2135     if (isTextField() && evt->type() == eventNames().textInputEvent && evt->isTextEvent() && static_cast<TextEvent*>(evt)->data() == "\n")
       
  2136         implicitSubmission = true;
       
  2137 
       
  2138     if (inputType() == IMAGE && evt->isMouseEvent() && evt->type() == eventNames().clickEvent) {
       
  2139         // record the mouse position for when we get the DOMActivate event
       
  2140         MouseEvent* me = static_cast<MouseEvent*>(evt);
       
  2141         // FIXME: We could just call offsetX() and offsetY() on the event,
       
  2142         // but that's currently broken, so for now do the computation here.
       
  2143         if (me->isSimulated() || !renderer()) {
       
  2144             m_xPos = 0;
       
  2145             m_yPos = 0;
       
  2146         } else {
       
  2147             // FIXME: This doesn't work correctly with transforms.
       
  2148             // FIXME: pageX/pageY need adjusting for pageZoomFactor(). Use actualPageLocation()?
       
  2149             IntPoint absOffset = roundedIntPoint(renderer()->localToAbsolute());
       
  2150             m_xPos = me->pageX() - absOffset.x();
       
  2151             m_yPos = me->pageY() - absOffset.y();
       
  2152         }
       
  2153     }
       
  2154 
       
  2155     if (hasSpinButton() && evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent()) {
       
  2156         String key = static_cast<KeyboardEvent*>(evt)->keyIdentifier();
       
  2157         int step = 0;
       
  2158         if (key == "Up")
       
  2159             step = 1;
       
  2160         else if (key == "Down")
       
  2161             step = -1;
       
  2162         if (step) {
       
  2163             stepUpFromRenderer(step);
       
  2164             evt->setDefaultHandled();
       
  2165             return;
       
  2166         }
       
  2167     }
       
  2168  
       
  2169    if (isTextField()
       
  2170             && evt->type() == eventNames().keydownEvent
       
  2171             && evt->isKeyboardEvent()
       
  2172             && focused()
       
  2173             && document()->frame()
       
  2174             && document()->frame()->doTextFieldCommandFromEvent(this, static_cast<KeyboardEvent*>(evt))) {
       
  2175         evt->setDefaultHandled();
       
  2176         return;
       
  2177     }
       
  2178 
       
  2179     if (inputType() == RADIO
       
  2180             && evt->isMouseEvent()
       
  2181             && evt->type() == eventNames().clickEvent
       
  2182             && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
       
  2183         evt->setDefaultHandled();
       
  2184         return;
       
  2185     }
       
  2186     
       
  2187     // Call the base event handler before any of our own event handling for almost all events in text fields.
       
  2188     // Makes editing keyboard handling take precedence over the keydown and keypress handling in this function.
       
  2189     bool callBaseClassEarly = isTextField() && !implicitSubmission
       
  2190         && (evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
       
  2191     if (callBaseClassEarly) {
       
  2192         HTMLFormControlElementWithState::defaultEventHandler(evt);
       
  2193         if (evt->defaultHandled())
       
  2194             return;
       
  2195     }
       
  2196 
       
  2197     // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
       
  2198     // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
       
  2199     // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
       
  2200     // must dispatch a DOMActivate event - a click event will not do the job.
       
  2201     if (evt->type() == eventNames().DOMActivateEvent && !disabled()) {
       
  2202         if (inputType() == IMAGE || inputType() == SUBMIT || inputType() == RESET) {
       
  2203             if (!form())
       
  2204                 return;
       
  2205             if (inputType() == RESET)
       
  2206                 form()->reset();
       
  2207             else {
       
  2208                 m_activeSubmit = true;
       
  2209                 // FIXME: Would be cleaner to get m_xPos and m_yPos out of the underlying mouse
       
  2210                 // event (if any) here instead of relying on the variables set above when
       
  2211                 // processing the click event. Even better, appendFormData could pass the
       
  2212                 // event in, and then we could get rid of m_xPos and m_yPos altogether!
       
  2213                 if (!form()->prepareSubmit(evt)) {
       
  2214                     m_xPos = 0;
       
  2215                     m_yPos = 0;
       
  2216                 }
       
  2217                 m_activeSubmit = false;
       
  2218             }
       
  2219         } else if (inputType() == FILE && renderer())
       
  2220             toRenderFileUploadControl(renderer())->click();
       
  2221     }
       
  2222 
       
  2223     // Use key press event here since sending simulated mouse events
       
  2224     // on key down blocks the proper sending of the key press event.
       
  2225     if (evt->type() == eventNames().keypressEvent && evt->isKeyboardEvent()) {
       
  2226         bool clickElement = false;
       
  2227 
       
  2228         int charCode = static_cast<KeyboardEvent*>(evt)->charCode();
       
  2229 
       
  2230         if (charCode == '\r') {
       
  2231             switch (inputType()) {
       
  2232             case CHECKBOX:
       
  2233             case COLOR:
       
  2234             case DATE:
       
  2235             case DATETIME:
       
  2236             case DATETIMELOCAL:
       
  2237             case EMAIL:
       
  2238             case HIDDEN:
       
  2239             case ISINDEX:
       
  2240             case MONTH:
       
  2241             case NUMBER:
       
  2242             case PASSWORD:
       
  2243             case RADIO:
       
  2244             case RANGE:
       
  2245             case SEARCH:
       
  2246             case TELEPHONE:
       
  2247             case TEXT:
       
  2248             case TIME:
       
  2249             case URL:
       
  2250             case WEEK:
       
  2251                 // Simulate mouse click on the default form button for enter for these types of elements.
       
  2252                 implicitSubmission = true;
       
  2253                 break;
       
  2254             case BUTTON:
       
  2255             case FILE:
       
  2256             case IMAGE:
       
  2257             case RESET:
       
  2258             case SUBMIT:
       
  2259                 // Simulate mouse click for enter for these types of elements.
       
  2260                 clickElement = true;
       
  2261                 break;
       
  2262             }
       
  2263         } else if (charCode == ' ') {
       
  2264             switch (inputType()) {
       
  2265             case BUTTON:
       
  2266             case CHECKBOX:
       
  2267             case FILE:
       
  2268             case IMAGE:
       
  2269             case RESET:
       
  2270             case SUBMIT:
       
  2271             case RADIO:
       
  2272                 // Prevent scrolling down the page.
       
  2273                 evt->setDefaultHandled();
       
  2274                 return;
       
  2275             default:
       
  2276                 break;
       
  2277             }
       
  2278         }
       
  2279 
       
  2280         if (clickElement) {
       
  2281             dispatchSimulatedClick(evt);
       
  2282             evt->setDefaultHandled();
       
  2283             return;
       
  2284         }
       
  2285     }
       
  2286 
       
  2287     if (evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent()) {
       
  2288         String key = static_cast<KeyboardEvent*>(evt)->keyIdentifier();
       
  2289 
       
  2290         if (key == "U+0020") {
       
  2291             switch (inputType()) {
       
  2292             case BUTTON:
       
  2293             case CHECKBOX:
       
  2294             case FILE:
       
  2295             case IMAGE:
       
  2296             case RESET:
       
  2297             case SUBMIT:
       
  2298             case RADIO:
       
  2299                 setActive(true, true);
       
  2300                 // No setDefaultHandled(), because IE dispatches a keypress in this case
       
  2301                 // and the caller will only dispatch a keypress if we don't call setDefaultHandled.
       
  2302                 return;
       
  2303             default:
       
  2304                 break;
       
  2305             }
       
  2306         }
       
  2307 
       
  2308         if (inputType() == RADIO && (key == "Up" || key == "Down" || key == "Left" || key == "Right")) {
       
  2309             // Left and up mean "previous radio button".
       
  2310             // Right and down mean "next radio button".
       
  2311             // Tested in WinIE, and even for RTL, left still means previous radio button (and so moves
       
  2312             // to the right).  Seems strange, but we'll match it.
       
  2313             bool forward = (key == "Down" || key == "Right");
       
  2314             
       
  2315             // We can only stay within the form's children if the form hasn't been demoted to a leaf because
       
  2316             // of malformed HTML.
       
  2317             Node* n = this;
       
  2318             while ((n = (forward ? n->traverseNextNode() : n->traversePreviousNode()))) {
       
  2319                 // Once we encounter a form element, we know we're through.
       
  2320                 if (n->hasTagName(formTag))
       
  2321                     break;
       
  2322                     
       
  2323                 // Look for more radio buttons.
       
  2324                 if (n->hasTagName(inputTag)) {
       
  2325                     HTMLInputElement* elt = static_cast<HTMLInputElement*>(n);
       
  2326                     if (elt->form() != form())
       
  2327                         break;
       
  2328                     if (n->hasTagName(inputTag)) {
       
  2329                         HTMLInputElement* inputElt = static_cast<HTMLInputElement*>(n);
       
  2330                         if (inputElt->inputType() == RADIO && inputElt->name() == name() && inputElt->isFocusable()) {
       
  2331                             inputElt->setChecked(true);
       
  2332                             document()->setFocusedNode(inputElt);
       
  2333                             inputElt->dispatchSimulatedClick(evt, false, false);
       
  2334                             evt->setDefaultHandled();
       
  2335                             break;
       
  2336                         }
       
  2337                     }
       
  2338                 }
       
  2339             }
       
  2340         }
       
  2341     }
       
  2342 
       
  2343     if (evt->type() == eventNames().keyupEvent && evt->isKeyboardEvent()) {
       
  2344         bool clickElement = false;
       
  2345 
       
  2346         String key = static_cast<KeyboardEvent*>(evt)->keyIdentifier();
       
  2347 
       
  2348         if (key == "U+0020") {
       
  2349             switch (inputType()) {
       
  2350             case BUTTON:
       
  2351             case CHECKBOX:
       
  2352             case FILE:
       
  2353             case IMAGE:
       
  2354             case RESET:
       
  2355             case SUBMIT:
       
  2356                 // Simulate mouse click for spacebar for these types of elements.
       
  2357                 // The AppKit already does this for some, but not all, of them.
       
  2358                 clickElement = true;
       
  2359                 break;
       
  2360             case RADIO:
       
  2361                 // If an unselected radio is tabbed into (because the entire group has nothing
       
  2362                 // checked, or because of some explicit .focus() call), then allow space to check it.
       
  2363                 if (!checked())
       
  2364                     clickElement = true;
       
  2365                 break;
       
  2366             case COLOR:
       
  2367             case DATE:
       
  2368             case DATETIME:
       
  2369             case DATETIMELOCAL:
       
  2370             case EMAIL:
       
  2371             case HIDDEN:
       
  2372             case ISINDEX:
       
  2373             case MONTH:
       
  2374             case NUMBER:
       
  2375             case PASSWORD:
       
  2376             case RANGE:
       
  2377             case SEARCH:
       
  2378             case TELEPHONE:
       
  2379             case TEXT:
       
  2380             case TIME:
       
  2381             case URL:
       
  2382             case WEEK:
       
  2383                 break;
       
  2384             }
       
  2385         }
       
  2386 
       
  2387         if (clickElement) {
       
  2388             if (active())
       
  2389                 dispatchSimulatedClick(evt);
       
  2390             evt->setDefaultHandled();
       
  2391             return;
       
  2392         }        
       
  2393     }
       
  2394 
       
  2395     if (implicitSubmission) {
       
  2396         if (isSearchField()) {
       
  2397             addSearchResult();
       
  2398             onSearch();
       
  2399         }
       
  2400         // Fire onChange for text fields.
       
  2401         RenderObject* r = renderer();
       
  2402         if (r && r->isTextField() && toRenderTextControl(r)->wasChangedSinceLastChangeEvent()) {
       
  2403             dispatchFormControlChangeEvent();
       
  2404             // Refetch the renderer since arbitrary JS code run during onchange can do anything, including destroying it.
       
  2405             r = renderer();
       
  2406             if (r && r->isTextField())
       
  2407                 toRenderTextControl(r)->setChangedSinceLastChangeEvent(false);
       
  2408         }
       
  2409 
       
  2410         RefPtr<HTMLFormElement> formForSubmission = form();
       
  2411         // If there is no form and the element is an <isindex>, then create a temporary form just to be used for submission.
       
  2412         if (!formForSubmission && inputType() == ISINDEX)
       
  2413             formForSubmission = createTemporaryFormForIsIndex();
       
  2414 
       
  2415         // Form may never have been present, or may have been destroyed by code responding to the change event.
       
  2416         if (formForSubmission)
       
  2417             formForSubmission->submitImplicitly(evt, canTriggerImplicitSubmission());
       
  2418 
       
  2419         evt->setDefaultHandled();
       
  2420         return;
       
  2421     }
       
  2422 
       
  2423     if (evt->isBeforeTextInsertedEvent())
       
  2424         handleBeforeTextInsertedEvent(evt);
       
  2425 
       
  2426     if (isTextField() && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == eventNames().blurEvent || evt->type() == eventNames().focusEvent))
       
  2427         toRenderTextControlSingleLine(renderer())->forwardEvent(evt);
       
  2428 
       
  2429     if (inputType() == RANGE && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent()))
       
  2430         toRenderSlider(renderer())->forwardEvent(evt);
       
  2431 
       
  2432     if (!callBaseClassEarly && !evt->defaultHandled())
       
  2433         HTMLFormControlElementWithState::defaultEventHandler(evt);
       
  2434 }
       
  2435 
       
  2436 void HTMLInputElement::handleBeforeTextInsertedEvent(Event* event)
       
  2437 {
       
  2438     if (inputType() == NUMBER) {
       
  2439         BeforeTextInsertedEvent* textEvent = static_cast<BeforeTextInsertedEvent*>(event);
       
  2440         unsigned length = textEvent->text().length();
       
  2441         bool hasInvalidChar = false;
       
  2442         for (unsigned i = 0; i < length; ++i) {
       
  2443             if (!isNumberCharacter(textEvent->text()[i])) {
       
  2444                 hasInvalidChar = true;
       
  2445                 break;
       
  2446             }
       
  2447         }
       
  2448         if (hasInvalidChar) {
       
  2449             Vector<UChar> stripped;
       
  2450             stripped.reserveCapacity(length);
       
  2451             for (unsigned i = 0; i < length; ++i) {
       
  2452                 UChar ch = textEvent->text()[i];
       
  2453                 if (!isNumberCharacter(ch))
       
  2454                     continue;
       
  2455                 stripped.append(ch);
       
  2456             }
       
  2457             textEvent->setText(String::adopt(stripped));
       
  2458         }
       
  2459     }
       
  2460     InputElement::handleBeforeTextInsertedEvent(m_data, this, this, event);
       
  2461 }
       
  2462 
       
  2463 PassRefPtr<HTMLFormElement> HTMLInputElement::createTemporaryFormForIsIndex()
       
  2464 {
       
  2465     RefPtr<HTMLFormElement> form = HTMLFormElement::create(document());
       
  2466     form->registerFormElement(this);
       
  2467     form->setMethod("GET");
       
  2468     if (!document()->baseURL().isEmpty()) {
       
  2469         // We treat the href property of the <base> element as the form action, as per section 7.5 
       
  2470         // "Queries and Indexes" of the HTML 2.0 spec. <http://www.w3.org/MarkUp/html-spec/html-spec_7.html#SEC7.5>.
       
  2471         form->setAction(document()->baseURL().string());
       
  2472     }
       
  2473     return form.release();
       
  2474 }
       
  2475 
       
  2476 bool HTMLInputElement::isURLAttribute(Attribute *attr) const
       
  2477 {
       
  2478     return (attr->name() == srcAttr);
       
  2479 }
       
  2480 
       
  2481 String HTMLInputElement::defaultValue() const
       
  2482 {
       
  2483     return getAttribute(valueAttr);
       
  2484 }
       
  2485 
       
  2486 void HTMLInputElement::setDefaultValue(const String &value)
       
  2487 {
       
  2488     setAttribute(valueAttr, value);
       
  2489 }
       
  2490 
       
  2491 bool HTMLInputElement::defaultChecked() const
       
  2492 {
       
  2493     return !getAttribute(checkedAttr).isNull();
       
  2494 }
       
  2495 
       
  2496 void HTMLInputElement::setDefaultName(const AtomicString& name)
       
  2497 {
       
  2498     m_data.setName(name);
       
  2499 }
       
  2500 
       
  2501 String HTMLInputElement::accept() const
       
  2502 {
       
  2503     return getAttribute(acceptAttr);
       
  2504 }
       
  2505 
       
  2506 String HTMLInputElement::alt() const
       
  2507 {
       
  2508     return getAttribute(altAttr);
       
  2509 }
       
  2510 
       
  2511 int HTMLInputElement::maxLength() const
       
  2512 {
       
  2513     return m_data.maxLength();
       
  2514 }
       
  2515 
       
  2516 void HTMLInputElement::setMaxLength(int maxLength, ExceptionCode& ec)
       
  2517 {
       
  2518     if (maxLength < 0)
       
  2519         ec = INDEX_SIZE_ERR;
       
  2520     else
       
  2521         setAttribute(maxlengthAttr, String::number(maxLength));
       
  2522 }
       
  2523 
       
  2524 bool HTMLInputElement::multiple() const
       
  2525 {
       
  2526     return !getAttribute(multipleAttr).isNull();
       
  2527 }
       
  2528 
       
  2529 #if ENABLE(DIRECTORY_UPLOAD)
       
  2530 bool HTMLInputElement::webkitdirectory() const
       
  2531 {
       
  2532     return !getAttribute(webkitdirectoryAttr).isNull();
       
  2533 }
       
  2534 #endif
       
  2535 
       
  2536 void HTMLInputElement::setSize(unsigned size)
       
  2537 {
       
  2538     setAttribute(sizeAttr, String::number(size));
       
  2539 }
       
  2540 
       
  2541 KURL HTMLInputElement::src() const
       
  2542 {
       
  2543     return document()->completeURL(getAttribute(srcAttr));
       
  2544 }
       
  2545 
       
  2546 void HTMLInputElement::setAutofilled(bool b)
       
  2547 {
       
  2548     if (b == m_autofilled)
       
  2549         return;
       
  2550         
       
  2551     m_autofilled = b;
       
  2552     setNeedsStyleRecalc();
       
  2553 }
       
  2554 
       
  2555 FileList* HTMLInputElement::files()
       
  2556 {
       
  2557     if (inputType() != FILE)
       
  2558         return 0;
       
  2559     return m_fileList.get();
       
  2560 }
       
  2561 
       
  2562 String HTMLInputElement::sanitizeValue(const String& proposedValue) const
       
  2563 {
       
  2564     if (isTextField())
       
  2565         return InputElement::sanitizeValueForTextField(this, proposedValue);
       
  2566 
       
  2567     // If the proposedValue is null than this is a reset scenario and we
       
  2568     // want the range input's value attribute to take priority over the
       
  2569     // calculated default (middle) value.
       
  2570     if (inputType() == RANGE && !proposedValue.isNull())
       
  2571         return serializeForNumberType(StepRange(this).clampValue(proposedValue));
       
  2572 
       
  2573     return proposedValue;
       
  2574 }
       
  2575 
       
  2576 bool HTMLInputElement::needsActivationCallback()
       
  2577 {
       
  2578     return inputType() == PASSWORD || m_autocomplete == Off;
       
  2579 }
       
  2580 
       
  2581 void HTMLInputElement::registerForActivationCallbackIfNeeded()
       
  2582 {
       
  2583     if (needsActivationCallback())
       
  2584         document()->registerForDocumentActivationCallbacks(this);
       
  2585 }
       
  2586 
       
  2587 void HTMLInputElement::unregisterForActivationCallbackIfNeeded()
       
  2588 {
       
  2589     if (!needsActivationCallback())
       
  2590         document()->unregisterForDocumentActivationCallbacks(this);
       
  2591 }
       
  2592 
       
  2593 bool HTMLInputElement::isRequiredFormControl() const
       
  2594 {
       
  2595     if (!required())
       
  2596         return false;
       
  2597 
       
  2598     switch (inputType()) {
       
  2599     case CHECKBOX:
       
  2600     case DATE:
       
  2601     case DATETIME:
       
  2602     case DATETIMELOCAL:
       
  2603     case EMAIL:
       
  2604     case FILE:
       
  2605     case MONTH:
       
  2606     case NUMBER:
       
  2607     case PASSWORD:
       
  2608     case RADIO:
       
  2609     case SEARCH:
       
  2610     case TELEPHONE:
       
  2611     case TEXT:
       
  2612     case TIME:
       
  2613     case URL:
       
  2614     case WEEK:
       
  2615         return true;
       
  2616     case BUTTON:
       
  2617     case COLOR:
       
  2618     case HIDDEN:
       
  2619     case IMAGE:
       
  2620     case ISINDEX:
       
  2621     case RANGE:
       
  2622     case RESET:
       
  2623     case SUBMIT:
       
  2624         return false;
       
  2625     }
       
  2626 
       
  2627     ASSERT_NOT_REACHED();
       
  2628     return false;
       
  2629 }
       
  2630 
       
  2631 void HTMLInputElement::cacheSelection(int start, int end)
       
  2632 {
       
  2633     m_data.setCachedSelectionStart(start);
       
  2634     m_data.setCachedSelectionEnd(end);
       
  2635 }
       
  2636 
       
  2637 void HTMLInputElement::addSearchResult()
       
  2638 {
       
  2639     ASSERT(isSearchField());
       
  2640     if (renderer())
       
  2641         toRenderTextControlSingleLine(renderer())->addSearchResult();
       
  2642 }
       
  2643 
       
  2644 void HTMLInputElement::onSearch()
       
  2645 {
       
  2646     ASSERT(isSearchField());
       
  2647     if (renderer())
       
  2648         toRenderTextControlSingleLine(renderer())->stopSearchEventTimer();
       
  2649     dispatchEvent(Event::create(eventNames().searchEvent, true, false));
       
  2650 }
       
  2651 
       
  2652 void HTMLInputElement::documentDidBecomeActive()
       
  2653 {
       
  2654     ASSERT(needsActivationCallback());
       
  2655     reset();
       
  2656 }
       
  2657 
       
  2658 void HTMLInputElement::willMoveToNewOwnerDocument()
       
  2659 {
       
  2660     if (m_imageLoader)
       
  2661         m_imageLoader->elementWillMoveToNewOwnerDocument();
       
  2662 
       
  2663     // Always unregister for cache callbacks when leaving a document, even if we would otherwise like to be registered
       
  2664     if (needsActivationCallback())
       
  2665         document()->unregisterForDocumentActivationCallbacks(this);
       
  2666         
       
  2667     document()->checkedRadioButtons().removeButton(this);
       
  2668     
       
  2669     HTMLFormControlElementWithState::willMoveToNewOwnerDocument();
       
  2670 }
       
  2671 
       
  2672 void HTMLInputElement::didMoveToNewOwnerDocument()
       
  2673 {
       
  2674     registerForActivationCallbackIfNeeded();
       
  2675         
       
  2676     HTMLFormControlElementWithState::didMoveToNewOwnerDocument();
       
  2677 }
       
  2678     
       
  2679 void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
       
  2680 {
       
  2681     HTMLFormControlElementWithState::addSubresourceAttributeURLs(urls);
       
  2682 
       
  2683     addSubresourceURL(urls, src());
       
  2684 }
       
  2685 
       
  2686 bool HTMLInputElement::recalcWillValidate() const
       
  2687 {
       
  2688     switch (inputType()) {
       
  2689     case CHECKBOX:
       
  2690     case COLOR:
       
  2691     case DATE:
       
  2692     case DATETIME:
       
  2693     case DATETIMELOCAL:
       
  2694     case EMAIL:
       
  2695     case FILE:
       
  2696     case ISINDEX:
       
  2697     case MONTH:
       
  2698     case NUMBER:
       
  2699     case PASSWORD:
       
  2700     case RADIO:
       
  2701     case RANGE:
       
  2702     case SEARCH:
       
  2703     case TELEPHONE:
       
  2704     case TEXT:
       
  2705     case TIME:
       
  2706     case URL:
       
  2707     case WEEK:
       
  2708         return HTMLFormControlElementWithState::recalcWillValidate();
       
  2709     case BUTTON:
       
  2710     case HIDDEN:
       
  2711     case IMAGE:
       
  2712     case RESET:
       
  2713     case SUBMIT:
       
  2714         return false;
       
  2715     }
       
  2716     ASSERT_NOT_REACHED();
       
  2717     return false;
       
  2718 }
       
  2719 
       
  2720 bool HTMLInputElement::parseToDateComponents(InputType type, const String& formString, DateComponents* out)
       
  2721 {
       
  2722     if (formString.isEmpty())
       
  2723         return false;
       
  2724     DateComponents ignoredResult;
       
  2725     if (!out)
       
  2726         out = &ignoredResult;
       
  2727     const UChar* characters = formString.characters();
       
  2728     unsigned length = formString.length();
       
  2729     unsigned end;
       
  2730 
       
  2731     switch (type) {
       
  2732     case DATE:
       
  2733         return out->parseDate(characters, length, 0, end) && end == length;
       
  2734     case DATETIME:
       
  2735         return out->parseDateTime(characters, length, 0, end) && end == length;
       
  2736     case DATETIMELOCAL:
       
  2737         return out->parseDateTimeLocal(characters, length, 0, end) && end == length;
       
  2738     case MONTH:
       
  2739         return out->parseMonth(characters, length, 0, end) && end == length;
       
  2740     case WEEK:
       
  2741         return out->parseWeek(characters, length, 0, end) && end == length;
       
  2742     case TIME:
       
  2743         return out->parseTime(characters, length, 0, end) && end == length;
       
  2744     default:
       
  2745         ASSERT_NOT_REACHED();
       
  2746         return false;
       
  2747     }
       
  2748 }
       
  2749 
       
  2750 #if ENABLE(DATALIST)
       
  2751 
       
  2752 HTMLElement* HTMLInputElement::list() const
       
  2753 {
       
  2754     return dataList();
       
  2755 }
       
  2756 
       
  2757 HTMLDataListElement* HTMLInputElement::dataList() const
       
  2758 {
       
  2759     if (!m_hasNonEmptyList)
       
  2760         return 0;
       
  2761 
       
  2762     switch (inputType()) {
       
  2763     case COLOR:
       
  2764     case DATE:
       
  2765     case DATETIME:
       
  2766     case DATETIMELOCAL:
       
  2767     case EMAIL:
       
  2768     case MONTH:
       
  2769     case NUMBER:
       
  2770     case RANGE:
       
  2771     case SEARCH:
       
  2772     case TELEPHONE:
       
  2773     case TEXT:
       
  2774     case TIME:
       
  2775     case URL:
       
  2776     case WEEK: {
       
  2777         Element* element = document()->getElementById(getAttribute(listAttr));
       
  2778         if (element && element->hasTagName(datalistTag))
       
  2779             return static_cast<HTMLDataListElement*>(element);
       
  2780         break;
       
  2781     }
       
  2782     case BUTTON:
       
  2783     case CHECKBOX:
       
  2784     case FILE:
       
  2785     case HIDDEN:
       
  2786     case IMAGE:
       
  2787     case ISINDEX:
       
  2788     case PASSWORD:
       
  2789     case RADIO:
       
  2790     case RESET:
       
  2791     case SUBMIT:
       
  2792         break;
       
  2793     }
       
  2794     return 0;
       
  2795 }
       
  2796 
       
  2797 HTMLOptionElement* HTMLInputElement::selectedOption() const
       
  2798 {
       
  2799     String currentValue = value();
       
  2800     // The empty value never matches to a datalist option because it
       
  2801     // doesn't represent a suggestion according to the standard.
       
  2802     if (currentValue.isEmpty())
       
  2803         return 0;
       
  2804 
       
  2805     HTMLDataListElement* sourceElement = dataList();
       
  2806     if (!sourceElement)
       
  2807         return 0;
       
  2808     RefPtr<HTMLCollection> options = sourceElement->options();
       
  2809     for (unsigned i = 0; options && i < options->length(); ++i) {
       
  2810         HTMLOptionElement* option = static_cast<HTMLOptionElement*>(options->item(i));
       
  2811         if (!option->disabled() && currentValue == option->value())
       
  2812             return option;
       
  2813     }
       
  2814     return 0;
       
  2815 }
       
  2816 
       
  2817 #endif // ENABLE(DATALIST)
       
  2818 
       
  2819 void HTMLInputElement::stepUpFromRenderer(int n)
       
  2820 {
       
  2821     // The difference from stepUp()/stepDown() is:
       
  2822     // If the current value is invalid, the value will be
       
  2823     //  - the minimum value if n > 0
       
  2824     //  - the maximum value if n < 0
       
  2825 
       
  2826     ASSERT(hasSpinButton());
       
  2827     if (!hasSpinButton())
       
  2828         return;
       
  2829     ASSERT(n);
       
  2830     if (!n)
       
  2831         return;
       
  2832 
       
  2833     const double nan = numeric_limits<double>::quiet_NaN();
       
  2834     double current = parseToDouble(value(), nan);
       
  2835     if (!isfinite(current)) {
       
  2836         setValue(serialize(n > 0 ? minimum() : maximum()));
       
  2837         return;
       
  2838     }
       
  2839     ExceptionCode ec;
       
  2840     stepUp(n, ec);
       
  2841 }
       
  2842 
       
  2843 #if ENABLE(WCSS)
       
  2844 void HTMLInputElement::setWapInputFormat(String& mask)
       
  2845 {
       
  2846     String validateMask = validateInputMask(m_data, mask);
       
  2847     if (!validateMask.isEmpty())
       
  2848         m_data.setInputFormatMask(validateMask);
       
  2849 }
       
  2850 #endif
       
  2851 
       
  2852 #if ENABLE(INPUT_SPEECH)
       
  2853 bool HTMLInputElement::isSpeechEnabled() const
       
  2854 {
       
  2855     switch (inputType()) {
       
  2856     // FIXME: Add support for RANGE, EMAIL, URL, COLOR and DATE/TIME input types.
       
  2857     case NUMBER:
       
  2858     case PASSWORD:
       
  2859     case SEARCH:
       
  2860     case TELEPHONE:
       
  2861     case TEXT:
       
  2862         return hasAttribute(speechAttr);
       
  2863     case BUTTON:
       
  2864     case CHECKBOX:
       
  2865     case COLOR:
       
  2866     case DATE:
       
  2867     case DATETIME:
       
  2868     case DATETIMELOCAL:
       
  2869     case EMAIL:
       
  2870     case FILE:
       
  2871     case HIDDEN:
       
  2872     case IMAGE:
       
  2873     case ISINDEX:
       
  2874     case MONTH:
       
  2875     case RADIO:
       
  2876     case RANGE:
       
  2877     case RESET:
       
  2878     case SUBMIT:
       
  2879     case TIME:
       
  2880     case URL:
       
  2881     case WEEK:
       
  2882         return false;
       
  2883     }
       
  2884     return false;
       
  2885 }
       
  2886 #endif
       
  2887 
       
  2888 } // namespace