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