e6b8228c3d10072b8eb6f6eb9131285f29019e14
[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 "Document.h"
33 #include "Editor.h"
34 #include "Event.h"
35 #include "EventHandler.h"
36 #include "EventNames.h"
37 #include "ExceptionCode.h"
38 #include "File.h"
39 #include "FileList.h"
40 #include "FocusController.h"
41 #include "FormDataList.h"
42 #include "Frame.h"
43 #include "HTMLDataListElement.h"
44 #include "HTMLFormElement.h"
45 #include "HTMLImageLoader.h"
46 #include "HTMLNames.h"
47 #include "HTMLOptionElement.h"
48 #include "ScriptEventListener.h"
49 #include "KeyboardEvent.h"
50 #include "LocalizedStrings.h"
51 #include "MappedAttribute.h"
52 #include "MouseEvent.h"
53 #include "Page.h"
54 #include "RegularExpression.h"
55 #include "RenderButton.h"
56 #include "RenderFileUploadControl.h"
57 #include "RenderImage.h"
58 #include "RenderSlider.h"
59 #include "RenderText.h"
60 #include "RenderTextControlSingleLine.h"
61 #include "RenderTheme.h"
62 #include "TextEvent.h"
63 #include <wtf/MathExtras.h>
64 #include <wtf/StdLibExtras.h>
65
66 using namespace std;
67
68 namespace WebCore {
69
70 using namespace HTMLNames;
71
72 const int maxSavedResults = 256;
73
74 HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
75     : HTMLTextFormControlElement(tagName, doc, f)
76     , m_xPos(0)
77     , m_yPos(0)
78     , m_maxResults(-1)
79     , m_type(TEXT)
80     , m_checked(false)
81     , m_defaultChecked(false)
82     , m_useDefaultChecked(true)
83     , m_indeterminate(false)
84     , m_haveType(false)
85     , m_activeSubmit(false)
86     , m_autocomplete(Uninitialized)
87     , m_autofilled(false)
88     , m_inited(false)
89 {
90     ASSERT(hasTagName(inputTag) || hasTagName(isindexTag));
91 }
92
93 HTMLInputElement::~HTMLInputElement()
94 {
95     if (needsActivationCallback())
96         document()->unregisterForDocumentActivationCallbacks(this);
97
98     document()->checkedRadioButtons().removeButton(this);
99
100     // Need to remove this from the form while it is still an HTMLInputElement,
101     // so can't wait for the base class's destructor to do it.
102     removeFromForm();
103 }
104
105 const AtomicString& HTMLInputElement::formControlName() const
106 {
107     return m_data.name();
108 }
109
110 bool HTMLInputElement::autoComplete() const
111 {
112     if (m_autocomplete != Uninitialized)
113         return m_autocomplete == On;
114     
115     // Assuming we're still in a Form, respect the Form's setting
116     if (HTMLFormElement* form = this->form())
117         return form->autoComplete();
118     
119     // The default is true
120     return true;
121 }
122
123 bool HTMLInputElement::valueMissing() const
124 {
125     if (!isRequiredFormControl() || readOnly() || disabled())
126         return false;
127
128     switch (inputType()) {
129         case TEXT:
130         case SEARCH:
131         case URL:
132         case TELEPHONE:
133         case EMAIL:
134         case PASSWORD:
135         case NUMBER:
136         case FILE:
137             return value().isEmpty();
138         case CHECKBOX:
139             return !checked();
140         case RADIO:
141             return !document()->checkedRadioButtons().checkedButtonForGroup(name());
142         case COLOR:
143             return false;
144         case HIDDEN:
145         case RANGE:
146         case SUBMIT:
147         case IMAGE:
148         case RESET:
149         case BUTTON:
150         case ISINDEX:
151             break;
152     }
153
154     ASSERT_NOT_REACHED();
155     return false;
156 }
157
158 bool HTMLInputElement::patternMismatch() const
159 {
160     switch (inputType()) {
161         case ISINDEX:
162         case CHECKBOX:
163         case RADIO:
164         case SUBMIT:
165         case RESET:
166         case FILE:
167         case HIDDEN:
168         case IMAGE:
169         case BUTTON:
170         case RANGE:
171         case NUMBER:
172         case COLOR:
173             return false;
174         case TEXT:
175         case SEARCH:
176         case URL:
177         case TELEPHONE:
178         case EMAIL:
179         case PASSWORD:
180             const AtomicString& pattern = getAttribute(patternAttr);
181             String value = this->value();
182
183             // Empty values can't be mismatched
184             if (pattern.isEmpty() || value.isEmpty())
185                 return false;
186
187             RegularExpression patternRegExp(pattern, TextCaseSensitive);
188             int matchLength = 0;
189             int valueLength = value.length();
190             int matchOffset = patternRegExp.match(value, 0, &matchLength);
191
192             return matchOffset != 0 || matchLength != valueLength;
193     }
194
195     ASSERT_NOT_REACHED();
196     return false;
197 }
198
199 static inline CheckedRadioButtons& checkedRadioButtons(const HTMLInputElement *element)
200 {
201     if (HTMLFormElement* form = element->form())
202         return form->checkedRadioButtons();
203     
204     return element->document()->checkedRadioButtons();
205 }
206
207 bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const
208 {
209     // If text fields can be focused, then they should always be keyboard focusable
210     if (isTextField())
211         return HTMLFormControlElementWithState::isFocusable();
212         
213     // If the base class says we can't be focused, then we can stop now.
214     if (!HTMLFormControlElementWithState::isKeyboardFocusable(event))
215         return false;
216
217     if (inputType() == RADIO) {
218
219         // Never allow keyboard tabbing to leave you in the same radio group.  Always
220         // skip any other elements in the group.
221         Node* currentFocusedNode = document()->focusedNode();
222         if (currentFocusedNode && currentFocusedNode->hasTagName(inputTag)) {
223             HTMLInputElement* focusedInput = static_cast<HTMLInputElement*>(currentFocusedNode);
224             if (focusedInput->inputType() == RADIO && focusedInput->form() == form() &&
225                 focusedInput->name() == name())
226                 return false;
227         }
228         
229         // Allow keyboard focus if we're checked or if nothing in the group is checked.
230         return checked() || !checkedRadioButtons(this).checkedButtonForGroup(name());
231     }
232     
233     return true;
234 }
235
236 bool HTMLInputElement::isMouseFocusable() const
237 {
238     if (isTextField())
239         return HTMLFormControlElementWithState::isFocusable();
240     return HTMLFormControlElementWithState::isMouseFocusable();
241 }
242
243 void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection)
244 {        
245     if (isTextField())
246         InputElement::updateFocusAppearance(m_data, this, this, restorePreviousSelection);
247     else
248         HTMLFormControlElementWithState::updateFocusAppearance(restorePreviousSelection);
249 }
250
251 void HTMLInputElement::aboutToUnload()
252 {
253     InputElement::aboutToUnload(this, this);
254 }
255
256 bool HTMLInputElement::shouldUseInputMethod() const
257 {
258     return m_type == TEXT || m_type == SEARCH || m_type == ISINDEX;
259 }
260
261 void HTMLInputElement::handleFocusEvent()
262 {
263     InputElement::dispatchFocusEvent(this, this);
264
265     if (isTextField())
266         m_autofilled = false;
267 }
268
269 void HTMLInputElement::handleBlurEvent()
270 {
271     InputElement::dispatchBlurEvent(this, this);
272 }
273
274 void HTMLInputElement::setType(const String& t)
275 {
276     if (t.isEmpty()) {
277         int exccode;
278         removeAttribute(typeAttr, exccode);
279     } else
280         setAttribute(typeAttr, t);
281 }
282
283 void HTMLInputElement::setInputType(const String& t)
284 {
285     InputType newType;
286     
287     if (equalIgnoringCase(t, "password"))
288         newType = PASSWORD;
289     else if (equalIgnoringCase(t, "checkbox"))
290         newType = CHECKBOX;
291     else if (equalIgnoringCase(t, "radio"))
292         newType = RADIO;
293     else if (equalIgnoringCase(t, "submit"))
294         newType = SUBMIT;
295     else if (equalIgnoringCase(t, "reset"))
296         newType = RESET;
297     else if (equalIgnoringCase(t, "file"))
298         newType = FILE;
299     else if (equalIgnoringCase(t, "hidden"))
300         newType = HIDDEN;
301     else if (equalIgnoringCase(t, "image"))
302         newType = IMAGE;
303     else if (equalIgnoringCase(t, "button"))
304         newType = BUTTON;
305     else if (equalIgnoringCase(t, "khtml_isindex"))
306         newType = ISINDEX;
307     else if (equalIgnoringCase(t, "search"))
308         newType = SEARCH;
309     else if (equalIgnoringCase(t, "range"))
310         newType = RANGE;
311     else if (equalIgnoringCase(t, "email"))
312         newType = EMAIL;
313     else if (equalIgnoringCase(t, "number"))
314         newType = NUMBER;
315     else if (equalIgnoringCase(t, "tel"))
316         newType = TELEPHONE;
317     else if (equalIgnoringCase(t, "url"))
318         newType = URL;
319     else if (equalIgnoringCase(t, "color"))
320         newType = COLOR;
321     else
322         newType = TEXT;
323
324     // IMPORTANT: Don't allow the type to be changed to FILE after the first
325     // type change, otherwise a JavaScript programmer would be able to set a text
326     // field's value to something like /etc/passwd and then change it to a file field.
327     if (inputType() != newType) {
328         if (newType == FILE && m_haveType)
329             // Set the attribute back to the old value.
330             // Useful in case we were called from inside parseMappedAttribute.
331             setAttribute(typeAttr, type());
332         else {
333             checkedRadioButtons(this).removeButton(this);
334
335             if (newType == FILE && !m_fileList)
336                 m_fileList = FileList::create();
337
338             bool wasAttached = attached();
339             if (wasAttached)
340                 detach();
341
342             bool didStoreValue = storesValueSeparateFromAttribute();
343             bool wasPasswordField = inputType() == PASSWORD;
344             bool didRespectHeightAndWidth = respectHeightAndWidthAttrs();
345             m_type = newType;
346             bool willStoreValue = storesValueSeparateFromAttribute();
347             bool isPasswordField = inputType() == PASSWORD;
348             bool willRespectHeightAndWidth = respectHeightAndWidthAttrs();
349
350             if (didStoreValue && !willStoreValue && !m_data.value().isNull()) {
351                 setAttribute(valueAttr, m_data.value());
352                 m_data.setValue(String());
353             }
354             if (!didStoreValue && willStoreValue)
355                 m_data.setValue(sanitizeValue(getAttribute(valueAttr)));
356             else
357                 InputElement::updateValueIfNeeded(m_data, this);
358
359             if (wasPasswordField && !isPasswordField)
360                 unregisterForActivationCallbackIfNeeded();
361             else if (!wasPasswordField && isPasswordField)
362                 registerForActivationCallbackIfNeeded();
363
364             if (didRespectHeightAndWidth != willRespectHeightAndWidth) {
365                 NamedMappedAttrMap* map = mappedAttributes();
366                 ASSERT(map);
367                 if (Attribute* height = map->getAttributeItem(heightAttr))
368                     attributeChanged(height, false);
369                 if (Attribute* width = map->getAttributeItem(widthAttr))
370                     attributeChanged(width, false);
371                 if (Attribute* align = map->getAttributeItem(alignAttr))
372                     attributeChanged(align, false);
373             }
374
375             if (wasAttached) {
376                 attach();
377                 if (document()->focusedNode() == this)
378                     updateFocusAppearance(true);
379             }
380
381             checkedRadioButtons(this).addButton(this);
382         }
383
384         InputElement::notifyFormStateChanged(this);
385     }
386     m_haveType = true;
387
388     if (inputType() != IMAGE && m_imageLoader)
389         m_imageLoader.clear();
390 }
391
392 const AtomicString& HTMLInputElement::formControlType() const
393 {
394     // needs to be lowercase according to DOM spec
395     switch (inputType()) {
396         case BUTTON: {
397             DEFINE_STATIC_LOCAL(const AtomicString, button, ("button"));
398             return button;
399         }
400         case CHECKBOX: {
401             DEFINE_STATIC_LOCAL(const AtomicString, checkbox, ("checkbox"));
402             return checkbox;
403         }
404         case COLOR: {
405             DEFINE_STATIC_LOCAL(const AtomicString, color, ("color"));
406             return color;
407         }
408         case EMAIL: {
409             DEFINE_STATIC_LOCAL(const AtomicString, email, ("email"));
410             return email;
411         }
412         case FILE: {
413             DEFINE_STATIC_LOCAL(const AtomicString, file, ("file"));
414             return file;
415         }
416         case HIDDEN: {
417             DEFINE_STATIC_LOCAL(const AtomicString, hidden, ("hidden"));
418             return hidden;
419         }
420         case IMAGE: {
421             DEFINE_STATIC_LOCAL(const AtomicString, image, ("image"));
422             return image;
423         }
424         case ISINDEX:
425             return emptyAtom;
426         case NUMBER: {
427             DEFINE_STATIC_LOCAL(const AtomicString, number, ("number"));
428             return number;
429         }
430         case PASSWORD: {
431             DEFINE_STATIC_LOCAL(const AtomicString, password, ("password"));
432             return password;
433         }
434         case RADIO: {
435             DEFINE_STATIC_LOCAL(const AtomicString, radio, ("radio"));
436             return radio;
437         }
438         case RANGE: {
439             DEFINE_STATIC_LOCAL(const AtomicString, range, ("range"));
440             return range;
441         }
442         case RESET: {
443             DEFINE_STATIC_LOCAL(const AtomicString, reset, ("reset"));
444             return reset;
445         }
446         case SEARCH: {
447             DEFINE_STATIC_LOCAL(const AtomicString, search, ("search"));
448             return search;
449         }
450         case SUBMIT: {
451             DEFINE_STATIC_LOCAL(const AtomicString, submit, ("submit"));
452             return submit;
453         }
454         case TELEPHONE: {
455             DEFINE_STATIC_LOCAL(const AtomicString, telephone, ("tel"));
456             return telephone;
457         }
458         case TEXT: {
459             DEFINE_STATIC_LOCAL(const AtomicString, text, ("text"));
460             return text;
461         }
462         case URL: {
463             DEFINE_STATIC_LOCAL(const AtomicString, url, ("url"));
464             return url;
465         }
466     }
467     return emptyAtom;
468 }
469
470 bool HTMLInputElement::saveFormControlState(String& result) const
471 {
472     if (!autoComplete())
473         return false;
474
475     switch (inputType()) {
476         case BUTTON:
477         case COLOR:
478         case EMAIL:
479         case FILE:
480         case HIDDEN:
481         case IMAGE:
482         case ISINDEX:
483         case NUMBER:
484         case RANGE:
485         case RESET:
486         case SEARCH:
487         case SUBMIT:
488         case TELEPHONE:
489         case TEXT:
490         case URL:
491             result = value();
492             return true;
493         case CHECKBOX:
494         case RADIO:
495             result = checked() ? "on" : "off";
496             return true;
497         case PASSWORD:
498             return false;
499     }
500     ASSERT_NOT_REACHED();
501     return false;
502 }
503
504 void HTMLInputElement::restoreFormControlState(const String& state)
505 {
506     ASSERT(inputType() != PASSWORD); // should never save/restore password fields
507     switch (inputType()) {
508         case BUTTON:
509         case COLOR:
510         case EMAIL:
511         case FILE:
512         case HIDDEN:
513         case IMAGE:
514         case ISINDEX:
515         case NUMBER:
516         case RANGE:
517         case RESET:
518         case SEARCH:
519         case SUBMIT:
520         case TELEPHONE:
521         case TEXT:
522         case URL:
523             setValue(state);
524             break;
525         case CHECKBOX:
526         case RADIO:
527             setChecked(state == "on");
528             break;
529         case PASSWORD:
530             break;
531     }
532 }
533
534 bool HTMLInputElement::canStartSelection() const
535 {
536     if (!isTextField())
537         return false;
538     return HTMLFormControlElementWithState::canStartSelection();
539 }
540
541 bool HTMLInputElement::canHaveSelection() const
542 {
543     return isTextField();
544 }
545
546 int HTMLInputElement::selectionStart() const
547 {
548     if (!isTextField())
549         return 0;
550     if (document()->focusedNode() != this && m_data.cachedSelectionStart() != -1)
551         return m_data.cachedSelectionStart();
552     if (!renderer())
553         return 0;
554     return toRenderTextControl(renderer())->selectionStart();
555 }
556
557 int HTMLInputElement::selectionEnd() const
558 {
559     if (!isTextField())
560         return 0;
561     if (document()->focusedNode() != this && m_data.cachedSelectionEnd() != -1)
562         return m_data.cachedSelectionEnd();
563     if (!renderer())
564         return 0;
565     return toRenderTextControl(renderer())->selectionEnd();
566 }
567
568 static bool isTextFieldWithRenderer(HTMLInputElement* element)
569 {
570     if (!element->isTextField())
571         return false;
572
573     element->document()->updateLayoutIgnorePendingStylesheets();
574     if (!element->renderer())
575         return false;
576
577     return true;
578 }
579
580 void HTMLInputElement::setSelectionStart(int start)
581 {
582     if (isTextFieldWithRenderer(this))
583         toRenderTextControl(renderer())->setSelectionStart(start);
584 }
585
586 void HTMLInputElement::setSelectionEnd(int end)
587 {
588     if (isTextFieldWithRenderer(this))
589         toRenderTextControl(renderer())->setSelectionEnd(end);
590 }
591
592 void HTMLInputElement::select()
593 {
594     if (isTextFieldWithRenderer(this))
595         toRenderTextControl(renderer())->select();
596 }
597
598 void HTMLInputElement::setSelectionRange(int start, int end)
599 {
600     InputElement::updateSelectionRange(this, this, start, end);
601 }
602
603 void HTMLInputElement::accessKeyAction(bool sendToAnyElement)
604 {
605     switch (inputType()) {
606         case BUTTON:
607         case CHECKBOX:
608         case FILE:
609         case IMAGE:
610         case RADIO:
611         case RANGE:
612         case RESET:
613         case SUBMIT:
614             focus(false);
615             // send the mouse button events iff the caller specified sendToAnyElement
616             dispatchSimulatedClick(0, sendToAnyElement);
617             break;
618         case HIDDEN:
619             // a no-op for this type
620             break;
621         case COLOR:
622         case EMAIL:
623         case ISINDEX:
624         case NUMBER:
625         case PASSWORD:
626         case SEARCH:
627         case TELEPHONE:
628         case TEXT:
629         case URL:
630             // should never restore previous selection here
631             focus(false);
632             break;
633     }
634 }
635
636 bool HTMLInputElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
637 {
638     if (((attrName == heightAttr || attrName == widthAttr) && respectHeightAndWidthAttrs()) ||
639         attrName == vspaceAttr ||
640         attrName == hspaceAttr) {
641         result = eUniversal;
642         return false;
643     } 
644
645     if (attrName == alignAttr) {
646         if (inputType() == IMAGE) {
647             // Share with <img> since the alignment behavior is the same.
648             result = eReplaced;
649             return false;
650         }
651     }
652
653     return HTMLElement::mapToEntry(attrName, result);
654 }
655
656 void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr)
657 {
658     if (attr->name() == nameAttr) {
659         checkedRadioButtons(this).removeButton(this);
660         m_data.setName(attr->value());
661         checkedRadioButtons(this).addButton(this);
662     } else if (attr->name() == autocompleteAttr) {
663         if (equalIgnoringCase(attr->value(), "off")) {
664             m_autocomplete = Off;
665             registerForActivationCallbackIfNeeded();
666         } else {
667             if (m_autocomplete == Off)
668                 unregisterForActivationCallbackIfNeeded();
669             if (attr->isEmpty())
670                 m_autocomplete = Uninitialized;
671             else
672                 m_autocomplete = On;
673         }
674     } else if (attr->name() == typeAttr) {
675         setInputType(attr->value());
676     } else if (attr->name() == valueAttr) {
677         // We only need to setChanged if the form is looking at the default value right now.
678         if (m_data.value().isNull())
679             setNeedsStyleRecalc();
680         setFormControlValueMatchesRenderer(false);
681     } else if (attr->name() == checkedAttr) {
682         m_defaultChecked = !attr->isNull();
683         if (m_useDefaultChecked) {
684             setChecked(m_defaultChecked);
685             m_useDefaultChecked = true;
686         }
687     } else if (attr->name() == maxlengthAttr)
688         InputElement::parseMaxLengthAttribute(m_data, this, this, attr);
689     else if (attr->name() == sizeAttr)
690         InputElement::parseSizeAttribute(m_data, this, attr);
691     else if (attr->name() == altAttr) {
692         if (renderer() && inputType() == IMAGE)
693             toRenderImage(renderer())->updateAltText();
694     } else if (attr->name() == srcAttr) {
695         if (renderer() && inputType() == IMAGE) {
696             if (!m_imageLoader)
697                 m_imageLoader.set(new HTMLImageLoader(this));
698             m_imageLoader->updateFromElementIgnoringPreviousError();
699         }
700     } else if (attr->name() == usemapAttr ||
701                attr->name() == accesskeyAttr) {
702         // FIXME: ignore for the moment
703     } else if (attr->name() == vspaceAttr) {
704         addCSSLength(attr, CSSPropertyMarginTop, attr->value());
705         addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
706     } else if (attr->name() == hspaceAttr) {
707         addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
708         addCSSLength(attr, CSSPropertyMarginRight, attr->value());
709     } else if (attr->name() == alignAttr) {
710         if (inputType() == IMAGE)
711             addHTMLAlignment(attr);
712     } else if (attr->name() == widthAttr) {
713         if (respectHeightAndWidthAttrs())
714             addCSSLength(attr, CSSPropertyWidth, attr->value());
715     } else if (attr->name() == heightAttr) {
716         if (respectHeightAndWidthAttrs())
717             addCSSLength(attr, CSSPropertyHeight, attr->value());
718     } else if (attr->name() == onfocusAttr) {
719         setAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(this, attr));
720     } else if (attr->name() == onblurAttr) {
721         setAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(this, attr));
722     } else if (attr->name() == onselectAttr) {
723         setAttributeEventListener(eventNames().selectEvent, createAttributeEventListener(this, attr));
724     } else if (attr->name() == onchangeAttr) {
725         setAttributeEventListener(eventNames().changeEvent, createAttributeEventListener(this, attr));
726     }
727     // Search field and slider attributes all just cause updateFromElement to be called through style
728     // recalcing.
729     else if (attr->name() == onsearchAttr) {
730         setAttributeEventListener(eventNames().searchEvent, createAttributeEventListener(this, attr));
731     } else if (attr->name() == resultsAttr) {
732         int oldResults = m_maxResults;
733         m_maxResults = !attr->isNull() ? min(attr->value().toInt(), maxSavedResults) : -1;
734         // FIXME: Detaching just for maxResults change is not ideal.  We should figure out the right
735         // time to relayout for this change.
736         if (m_maxResults != oldResults && (m_maxResults <= 0 || oldResults <= 0) && attached()) {
737             detach();
738             attach();
739         }
740         setNeedsStyleRecalc();
741     } else if (attr->name() == placeholderAttr) {
742         updatePlaceholderVisibility(true);
743     } else if (attr->name() == autosaveAttr ||
744              attr->name() == incrementalAttr ||
745              attr->name() == minAttr ||
746              attr->name() == maxAttr ||
747              attr->name() == multipleAttr ||
748              attr->name() == precisionAttr)
749         setNeedsStyleRecalc();
750 #if ENABLE(DATALIST)
751     else if (attr->name() == listAttr)
752         m_hasNonEmptyList = !attr->isEmpty();
753         // FIXME: we need to tell this change to a renderer if the attribute affects the appearance.
754 #endif
755     else
756         HTMLFormControlElementWithState::parseMappedAttribute(attr);
757 }
758
759 bool HTMLInputElement::rendererIsNeeded(RenderStyle *style)
760 {
761     switch (inputType()) {
762         case BUTTON:
763         case CHECKBOX:
764         case COLOR:
765         case EMAIL:
766         case FILE:
767         case IMAGE:
768         case ISINDEX:
769         case NUMBER:
770         case PASSWORD:
771         case RADIO:
772         case RANGE:
773         case RESET:
774         case SEARCH:
775         case SUBMIT:
776         case TELEPHONE:
777         case TEXT:
778         case URL:
779             return HTMLFormControlElementWithState::rendererIsNeeded(style);
780         case HIDDEN:
781             return false;
782     }
783     ASSERT(false);
784     return false;
785 }
786
787 RenderObject *HTMLInputElement::createRenderer(RenderArena *arena, RenderStyle *style)
788 {
789     switch (inputType()) {
790         case BUTTON:
791         case RESET:
792         case SUBMIT:
793             return new (arena) RenderButton(this);
794         case CHECKBOX:
795         case RADIO:
796             return RenderObject::createObject(this, style);
797         case FILE:
798             return new (arena) RenderFileUploadControl(this);
799         case HIDDEN:
800             break;
801         case IMAGE:
802             return new (arena) RenderImage(this);
803         case RANGE:
804             return new (arena) RenderSlider(this);
805         case COLOR:
806         case EMAIL:
807         case ISINDEX:
808         case NUMBER:
809         case PASSWORD:
810         case SEARCH:
811         case TELEPHONE:
812         case TEXT:
813         case URL:
814             return new (arena) RenderTextControlSingleLine(this, placeholderShouldBeVisible());
815     }
816     ASSERT(false);
817     return 0;
818 }
819
820 void HTMLInputElement::attach()
821 {
822     if (!m_inited) {
823         if (!m_haveType)
824             setInputType(getAttribute(typeAttr));
825         m_inited = true;
826     }
827
828     HTMLFormControlElementWithState::attach();
829
830     if (inputType() == IMAGE) {
831         if (!m_imageLoader)
832             m_imageLoader.set(new HTMLImageLoader(this));
833         m_imageLoader->updateFromElement();
834         if (renderer()) {
835             RenderImage* imageObj = toRenderImage(renderer());
836             imageObj->setCachedImage(m_imageLoader->image()); 
837             
838             // If we have no image at all because we have no src attribute, set
839             // image height and width for the alt text instead.
840             if (!m_imageLoader->image() && !imageObj->cachedImage())
841                 imageObj->setImageSizeForAltText();
842         }
843     }
844 }
845
846 void HTMLInputElement::detach()
847 {
848     HTMLFormControlElementWithState::detach();
849     setFormControlValueMatchesRenderer(false);
850 }
851
852 String HTMLInputElement::altText() const
853 {
854     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
855     // also heavily discussed by Hixie on bugzilla
856     // note this is intentionally different to HTMLImageElement::altText()
857     String alt = getAttribute(altAttr);
858     // fall back to title attribute
859     if (alt.isNull())
860         alt = getAttribute(titleAttr);
861     if (alt.isNull())
862         alt = getAttribute(valueAttr);
863     if (alt.isEmpty())
864         alt = inputElementAltText();
865     return alt;
866 }
867
868 bool HTMLInputElement::isSuccessfulSubmitButton() const
869 {
870     // HTML spec says that buttons must have names to be considered successful.
871     // However, other browsers do not impose this constraint. So we do likewise.
872     return !disabled() && (inputType() == IMAGE || inputType() == SUBMIT);
873 }
874
875 bool HTMLInputElement::isActivatedSubmit() const
876 {
877     return m_activeSubmit;
878 }
879
880 void HTMLInputElement::setActivatedSubmit(bool flag)
881 {
882     m_activeSubmit = flag;
883 }
884
885 bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart)
886 {
887     // image generates its own names, but for other types there is no form data unless there's a name
888     if (name().isEmpty() && inputType() != IMAGE)
889         return false;
890
891     switch (inputType()) {
892         case COLOR:
893         case EMAIL:
894         case HIDDEN:
895         case ISINDEX:
896         case NUMBER:
897         case PASSWORD:
898         case RANGE:
899         case SEARCH:
900         case TELEPHONE:
901         case TEXT:
902         case URL:
903             // always successful
904             encoding.appendData(name(), value());
905             return true;
906
907         case CHECKBOX:
908         case RADIO:
909             if (checked()) {
910                 encoding.appendData(name(), value());
911                 return true;
912             }
913             break;
914
915         case BUTTON:
916         case RESET:
917             // these types of buttons are never successful
918             return false;
919
920         case IMAGE:
921             if (m_activeSubmit) {
922                 encoding.appendData(name().isEmpty() ? "x" : (name() + ".x"), m_xPos);
923                 encoding.appendData(name().isEmpty() ? "y" : (name() + ".y"), m_yPos);
924                 if (!name().isEmpty() && !value().isEmpty())
925                     encoding.appendData(name(), value());
926                 return true;
927             }
928             break;
929
930         case SUBMIT:
931             if (m_activeSubmit) {
932                 String enc_str = valueWithDefault();
933                 encoding.appendData(name(), enc_str);
934                 return true;
935             }
936             break;
937
938         case FILE: {
939             unsigned numFiles = m_fileList->length();
940             if (!multipart) {
941                 // Send only the basenames.
942                 // 4.10.16.4 and 4.10.16.6 sections in HTML5.
943
944                 // Unlike the multipart case, we have no special
945                 // handling for the empty fileList because Netscape
946                 // doesn't support for non-multipart submission of
947                 // file inputs, and Firefox doesn't add "name=" query
948                 // parameter.
949
950                 for (unsigned i = 0; i < numFiles; ++i) {
951                     encoding.appendData(name(), m_fileList->item(i)->fileName());
952                 }
953                 return true;
954             }
955
956             // If no filename at all is entered, return successful but empty.
957             // Null would be more logical, but Netscape posts an empty file. Argh.
958             if (!numFiles) {
959                 encoding.appendFile(name(), File::create(""));
960                 return true;
961             }
962
963             for (unsigned i = 0; i < numFiles; ++i)
964                 encoding.appendFile(name(), m_fileList->item(i));
965             return true;
966         }
967     }
968     return false;
969 }
970
971 void HTMLInputElement::reset()
972 {
973     if (storesValueSeparateFromAttribute())
974         setValue(String());
975
976     setChecked(m_defaultChecked);
977     m_useDefaultChecked = true;
978 }
979
980 void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent)
981 {
982     if (checked() == nowChecked)
983         return;
984
985     checkedRadioButtons(this).removeButton(this);
986
987     m_useDefaultChecked = false;
988     m_checked = nowChecked;
989     setNeedsStyleRecalc();
990
991     checkedRadioButtons(this).addButton(this);
992
993     if (renderer() && renderer()->style()->hasAppearance())
994         renderer()->theme()->stateChanged(renderer(), CheckedState);
995
996     // Ideally we'd do this from the render tree (matching
997     // RenderTextView), but it's not possible to do it at the moment
998     // because of the way the code is structured.
999     if (renderer() && AXObjectCache::accessibilityEnabled())
1000         renderer()->document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXCheckedStateChanged, true);
1001
1002     // Only send a change event for items in the document (avoid firing during
1003     // parsing) and don't send a change event for a radio button that's getting
1004     // unchecked to match other browsers. DOM is not a useful standard for this
1005     // because it says only to fire change events at "lose focus" time, which is
1006     // definitely wrong in practice for these types of elements.
1007     if (sendChangeEvent && inDocument() && (inputType() != RADIO || nowChecked))
1008         dispatchFormControlChangeEvent();
1009 }
1010
1011 void HTMLInputElement::setIndeterminate(bool _indeterminate)
1012 {
1013     // Only checkboxes honor indeterminate.
1014     if (inputType() != CHECKBOX || indeterminate() == _indeterminate)
1015         return;
1016
1017     m_indeterminate = _indeterminate;
1018
1019     setNeedsStyleRecalc();
1020
1021     if (renderer() && renderer()->style()->hasAppearance())
1022         renderer()->theme()->stateChanged(renderer(), CheckedState);
1023 }
1024
1025 int HTMLInputElement::size() const
1026 {
1027     return m_data.size();
1028 }
1029
1030 void HTMLInputElement::copyNonAttributeProperties(const Element* source)
1031 {
1032     const HTMLInputElement* sourceElement = static_cast<const HTMLInputElement*>(source);
1033
1034     m_data.setValue(sourceElement->m_data.value());
1035     m_checked = sourceElement->m_checked;
1036     m_indeterminate = sourceElement->m_indeterminate;
1037
1038     HTMLFormControlElementWithState::copyNonAttributeProperties(source);
1039 }
1040
1041 String HTMLInputElement::value() const
1042 {
1043     // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't applicable to the file upload control
1044     // but we don't want to break existing websites, who may be relying on being able to get the file name as a value.
1045     if (inputType() == FILE) {
1046         if (!m_fileList->isEmpty())
1047             return m_fileList->item(0)->fileName();
1048         return String();
1049     }
1050
1051     String value = m_data.value();
1052     if (value.isNull()) {
1053         value = sanitizeValue(getAttribute(valueAttr));
1054
1055         // If no attribute exists, then just use "on" or "" based off the checked() state of the control.
1056         if (value.isNull() && (inputType() == CHECKBOX || inputType() == RADIO))
1057             return checked() ? "on" : "";
1058     }
1059
1060     return value;
1061 }
1062
1063 String HTMLInputElement::valueWithDefault() const
1064 {
1065     String v = value();
1066     if (v.isNull()) {
1067         switch (inputType()) {
1068             case BUTTON:
1069             case CHECKBOX:
1070             case COLOR:
1071             case EMAIL:
1072             case FILE:
1073             case HIDDEN:
1074             case IMAGE:
1075             case ISINDEX:
1076             case NUMBER:
1077             case PASSWORD:
1078             case RADIO:
1079             case RANGE:
1080             case SEARCH:
1081             case TELEPHONE:
1082             case TEXT:
1083             case URL:
1084                 break;
1085             case RESET:
1086                 v = resetButtonDefaultLabel();
1087                 break;
1088             case SUBMIT:
1089                 v = submitButtonDefaultLabel();
1090                 break;
1091         }
1092     }
1093     return v;
1094 }
1095
1096 void HTMLInputElement::setValue(const String& value)
1097 {
1098     // For security reasons, we don't allow setting the filename, but we do allow clearing it.
1099     // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't applicable to the file upload control
1100     // but we don't want to break existing websites, who may be relying on this method to clear things.
1101     if (inputType() == FILE && !value.isEmpty())
1102         return;
1103
1104     setFormControlValueMatchesRenderer(false);
1105     if (storesValueSeparateFromAttribute()) {
1106         if (inputType() == FILE)
1107             m_fileList->clear();
1108         else {
1109             m_data.setValue(sanitizeValue(value));
1110             if (isTextField()) {
1111                 updatePlaceholderVisibility(false);
1112                 if (inDocument())
1113                     document()->updateStyleIfNeeded();
1114             }
1115         }
1116         if (renderer())
1117             renderer()->updateFromElement();
1118         setNeedsStyleRecalc();
1119     } else
1120         setAttribute(valueAttr, sanitizeValue(value));
1121     
1122     if (isTextField()) {
1123         unsigned max = m_data.value().length();
1124         if (document()->focusedNode() == this)
1125             InputElement::updateSelectionRange(this, this, max, max);
1126         else
1127             cacheSelection(max, max);
1128     }
1129     InputElement::notifyFormStateChanged(this);
1130 }
1131
1132 String HTMLInputElement::placeholder() const
1133 {
1134     return getAttribute(placeholderAttr).string();
1135 }
1136
1137 void HTMLInputElement::setPlaceholder(const String& value)
1138 {
1139     setAttribute(placeholderAttr, value);
1140 }
1141
1142 bool HTMLInputElement::searchEventsShouldBeDispatched() const
1143 {
1144     return hasAttribute(incrementalAttr);
1145 }
1146
1147 void HTMLInputElement::setValueFromRenderer(const String& value)
1148 {
1149     // File upload controls will always use setFileListFromRenderer.
1150     ASSERT(inputType() != FILE);
1151     updatePlaceholderVisibility(false);
1152     InputElement::setValueFromRenderer(m_data, this, this, value);
1153 }
1154
1155 void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths)
1156 {
1157     m_fileList->clear();
1158     int size = paths.size();
1159     for (int i = 0; i < size; i++)
1160         m_fileList->append(File::create(paths[i]));
1161
1162     setFormControlValueMatchesRenderer(true);
1163     InputElement::notifyFormStateChanged(this);
1164 }
1165
1166 bool HTMLInputElement::storesValueSeparateFromAttribute() const
1167 {
1168     switch (inputType()) {
1169         case BUTTON:
1170         case CHECKBOX:
1171         case HIDDEN:
1172         case IMAGE:
1173         case RADIO:
1174         case RESET:
1175         case SUBMIT:
1176             return false;
1177         case COLOR:
1178         case EMAIL:
1179         case FILE:
1180         case ISINDEX:
1181         case NUMBER:
1182         case PASSWORD:
1183         case RANGE:
1184         case SEARCH:
1185         case TELEPHONE:
1186         case TEXT:
1187         case URL:
1188             return true;
1189     }
1190     return false;
1191 }
1192
1193 void* HTMLInputElement::preDispatchEventHandler(Event *evt)
1194 {
1195     // preventDefault or "return false" are used to reverse the automatic checking/selection we do here.
1196     // This result gives us enough info to perform the "undo" in postDispatch of the action we take here.
1197     void* result = 0; 
1198     if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent()
1199             && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
1200         if (inputType() == CHECKBOX) {
1201             // As a way to store the state, we return 0 if we were unchecked, 1 if we were checked, and 2 for
1202             // indeterminate.
1203             if (indeterminate()) {
1204                 result = (void*)0x2;
1205                 setIndeterminate(false);
1206             } else {
1207                 if (checked())
1208                     result = (void*)0x1;
1209                 setChecked(!checked(), true);
1210             }
1211         } else {
1212             // For radio buttons, store the current selected radio object.
1213             // We really want radio groups to end up in sane states, i.e., to have something checked.
1214             // Therefore if nothing is currently selected, we won't allow this action to be "undone", since
1215             // we want some object in the radio group to actually get selected.
1216             HTMLInputElement* currRadio = checkedRadioButtons(this).checkedButtonForGroup(name());
1217             if (currRadio) {
1218                 // We have a radio button selected that is not us.  Cache it in our result field and ref it so
1219                 // that it can't be destroyed.
1220                 currRadio->ref();
1221                 result = currRadio;
1222             }
1223             setChecked(true, true);
1224         }
1225     }
1226     return result;
1227 }
1228
1229 void HTMLInputElement::postDispatchEventHandler(Event *evt, void* data)
1230 {
1231     if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent()
1232             && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
1233         if (inputType() == CHECKBOX) {
1234             // Reverse the checking we did in preDispatch.
1235             if (evt->defaultPrevented() || evt->defaultHandled()) {
1236                 if (data == (void*)0x2)
1237                     setIndeterminate(true);
1238                 else
1239                     setChecked(data);
1240             }
1241         } else if (data) {
1242             HTMLInputElement* input = static_cast<HTMLInputElement*>(data);
1243             if (evt->defaultPrevented() || evt->defaultHandled()) {
1244                 // Restore the original selected radio button if possible.
1245                 // Make sure it is still a radio button and only do the restoration if it still
1246                 // belongs to our group.
1247
1248                 if (input->form() == form() && input->inputType() == RADIO && input->name() == name()) {
1249                     // Ok, the old radio button is still in our form and in our group and is still a 
1250                     // radio button, so it's safe to restore selection to it.
1251                     input->setChecked(true);
1252                 }
1253             }
1254             input->deref();
1255         }
1256
1257         // Left clicks on radio buttons and check boxes already performed default actions in preDispatchEventHandler(). 
1258         evt->setDefaultHandled();
1259     }
1260 }
1261
1262 void HTMLInputElement::defaultEventHandler(Event* evt)
1263 {
1264     // FIXME: It would be better to refactor this for the different types of input element.
1265     // Having them all in one giant function makes this hard to read, and almost all the handling is type-specific.
1266
1267     bool clickDefaultFormButton = false;
1268
1269     if (isTextField() && evt->type() == eventNames().textInputEvent && evt->isTextEvent() && static_cast<TextEvent*>(evt)->data() == "\n")
1270         clickDefaultFormButton = true;
1271
1272     if (inputType() == IMAGE && evt->isMouseEvent() && evt->type() == eventNames().clickEvent) {
1273         // record the mouse position for when we get the DOMActivate event
1274         MouseEvent* me = static_cast<MouseEvent*>(evt);
1275         // FIXME: We could just call offsetX() and offsetY() on the event,
1276         // but that's currently broken, so for now do the computation here.
1277         if (me->isSimulated() || !renderer()) {
1278             m_xPos = 0;
1279             m_yPos = 0;
1280         } else {
1281             // FIXME: This doesn't work correctly with transforms.
1282             // FIXME: pageX/pageY need adjusting for pageZoomFactor(). Use actualPageLocation()?
1283             IntPoint absOffset = roundedIntPoint(renderer()->localToAbsolute());
1284             m_xPos = me->pageX() - absOffset.x();
1285             m_yPos = me->pageY() - absOffset.y();
1286         }
1287     }
1288
1289     if (isTextField()
1290             && evt->type() == eventNames().keydownEvent
1291             && evt->isKeyboardEvent()
1292             && focused()
1293             && document()->frame()
1294             && document()->frame()->doTextFieldCommandFromEvent(this, static_cast<KeyboardEvent*>(evt))) {
1295         evt->setDefaultHandled();
1296         return;
1297     }
1298
1299     if (inputType() == RADIO
1300             && evt->isMouseEvent()
1301             && evt->type() == eventNames().clickEvent
1302             && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
1303         evt->setDefaultHandled();
1304         return;
1305     }
1306     
1307     // Call the base event handler before any of our own event handling for almost all events in text fields.
1308     // Makes editing keyboard handling take precedence over the keydown and keypress handling in this function.
1309     bool callBaseClassEarly = isTextField() && !clickDefaultFormButton
1310         && (evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
1311     if (callBaseClassEarly) {
1312         HTMLFormControlElementWithState::defaultEventHandler(evt);
1313         if (evt->defaultHandled())
1314             return;
1315     }
1316
1317     // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
1318     // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
1319     // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
1320     // must dispatch a DOMActivate event - a click event will not do the job.
1321     if (evt->type() == eventNames().DOMActivateEvent && !disabled()) {
1322         if (inputType() == IMAGE || inputType() == SUBMIT || inputType() == RESET) {
1323             if (!form())
1324                 return;
1325             if (inputType() == RESET)
1326                 form()->reset();
1327             else {
1328                 m_activeSubmit = true;
1329                 // FIXME: Would be cleaner to get m_xPos and m_yPos out of the underlying mouse
1330                 // event (if any) here instead of relying on the variables set above when
1331                 // processing the click event. Even better, appendFormData could pass the
1332                 // event in, and then we could get rid of m_xPos and m_yPos altogether!
1333                 if (!form()->prepareSubmit(evt)) {
1334                     m_xPos = 0;
1335                     m_yPos = 0;
1336                 }
1337                 m_activeSubmit = false;
1338             }
1339         } else if (inputType() == FILE && renderer())
1340             toRenderFileUploadControl(renderer())->click();
1341     }
1342
1343     // Use key press event here since sending simulated mouse events
1344     // on key down blocks the proper sending of the key press event.
1345     if (evt->type() == eventNames().keypressEvent && evt->isKeyboardEvent()) {
1346         bool clickElement = false;
1347
1348         int charCode = static_cast<KeyboardEvent*>(evt)->charCode();
1349
1350         if (charCode == '\r') {
1351             switch (inputType()) {
1352                 case CHECKBOX:
1353                 case COLOR:
1354                 case EMAIL:
1355                 case HIDDEN:
1356                 case ISINDEX:
1357                 case NUMBER:
1358                 case PASSWORD:
1359                 case RANGE:
1360                 case SEARCH:
1361                 case TELEPHONE:
1362                 case TEXT:
1363                 case URL:
1364                     // Simulate mouse click on the default form button for enter for these types of elements.
1365                     clickDefaultFormButton = true;
1366                     break;
1367                 case BUTTON:
1368                 case FILE:
1369                 case IMAGE:
1370                 case RESET:
1371                 case SUBMIT:
1372                     // Simulate mouse click for enter for these types of elements.
1373                     clickElement = true;
1374                     break;
1375                 case RADIO:
1376                     break; // Don't do anything for enter on a radio button.
1377             }
1378         } else if (charCode == ' ') {
1379             switch (inputType()) {
1380                 case BUTTON:
1381                 case CHECKBOX:
1382                 case FILE:
1383                 case IMAGE:
1384                 case RESET:
1385                 case SUBMIT:
1386                 case RADIO:
1387                     // Prevent scrolling down the page.
1388                     evt->setDefaultHandled();
1389                     return;
1390                 default:
1391                     break;
1392             }
1393         }
1394
1395         if (clickElement) {
1396             dispatchSimulatedClick(evt);
1397             evt->setDefaultHandled();
1398             return;
1399         }
1400     }
1401
1402     if (evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent()) {
1403         String key = static_cast<KeyboardEvent*>(evt)->keyIdentifier();
1404
1405         if (key == "U+0020") {
1406             switch (inputType()) {
1407                 case BUTTON:
1408                 case CHECKBOX:
1409                 case FILE:
1410                 case IMAGE:
1411                 case RESET:
1412                 case SUBMIT:
1413                 case RADIO:
1414                     setActive(true, true);
1415                     // No setDefaultHandled(), because IE dispatches a keypress in this case
1416                     // and the caller will only dispatch a keypress if we don't call setDefaultHandled.
1417                     return;
1418                 default:
1419                     break;
1420             }
1421         }
1422
1423         if (inputType() == RADIO && (key == "Up" || key == "Down" || key == "Left" || key == "Right")) {
1424             // Left and up mean "previous radio button".
1425             // Right and down mean "next radio button".
1426             // Tested in WinIE, and even for RTL, left still means previous radio button (and so moves
1427             // to the right).  Seems strange, but we'll match it.
1428             bool forward = (key == "Down" || key == "Right");
1429             
1430             // We can only stay within the form's children if the form hasn't been demoted to a leaf because
1431             // of malformed HTML.
1432             Node* n = this;
1433             while ((n = (forward ? n->traverseNextNode() : n->traversePreviousNode()))) {
1434                 // Once we encounter a form element, we know we're through.
1435                 if (n->hasTagName(formTag))
1436                     break;
1437                     
1438                 // Look for more radio buttons.
1439                 if (n->hasTagName(inputTag)) {
1440                     HTMLInputElement* elt = static_cast<HTMLInputElement*>(n);
1441                     if (elt->form() != form())
1442                         break;
1443                     if (n->hasTagName(inputTag)) {
1444                         HTMLInputElement* inputElt = static_cast<HTMLInputElement*>(n);
1445                         if (inputElt->inputType() == RADIO && inputElt->name() == name() && inputElt->isFocusable()) {
1446                             inputElt->setChecked(true);
1447                             document()->setFocusedNode(inputElt);
1448                             inputElt->dispatchSimulatedClick(evt, false, false);
1449                             evt->setDefaultHandled();
1450                             break;
1451                         }
1452                     }
1453                 }
1454             }
1455         }
1456     }
1457
1458     if (evt->type() == eventNames().keyupEvent && evt->isKeyboardEvent()) {
1459         bool clickElement = false;
1460
1461         String key = static_cast<KeyboardEvent*>(evt)->keyIdentifier();
1462
1463         if (key == "U+0020") {
1464             switch (inputType()) {
1465                 case BUTTON:
1466                 case CHECKBOX:
1467                 case FILE:
1468                 case IMAGE:
1469                 case RESET:
1470                 case SUBMIT:
1471                     // Simulate mouse click for spacebar for these types of elements.
1472                     // The AppKit already does this for some, but not all, of them.
1473                     clickElement = true;
1474                     break;
1475                 case RADIO:
1476                     // If an unselected radio is tabbed into (because the entire group has nothing
1477                     // checked, or because of some explicit .focus() call), then allow space to check it.
1478                     if (!checked())
1479                         clickElement = true;
1480                     break;
1481                 case COLOR:
1482                 case EMAIL:
1483                 case HIDDEN:
1484                 case ISINDEX:
1485                 case NUMBER:
1486                 case PASSWORD:
1487                 case RANGE:
1488                 case SEARCH:
1489                 case TELEPHONE:
1490                 case TEXT:
1491                 case URL:
1492                     break;
1493             }
1494         }
1495
1496         if (clickElement) {
1497             if (active())
1498                 dispatchSimulatedClick(evt);
1499             evt->setDefaultHandled();
1500             return;
1501         }        
1502     }
1503
1504     if (clickDefaultFormButton) {
1505         if (isSearchField()) {
1506             addSearchResult();
1507             onSearch();
1508         }
1509         // Fire onChange for text fields.
1510         RenderObject* r = renderer();
1511         if (r && r->isTextField() && toRenderTextControl(r)->isEdited()) {
1512             dispatchFormControlChangeEvent();
1513             // Refetch the renderer since arbitrary JS code run during onchange can do anything, including destroying it.
1514             r = renderer();
1515             if (r && r->isTextField())
1516                 toRenderTextControl(r)->setEdited(false);
1517         }
1518         // Form may never have been present, or may have been destroyed by the change event.
1519         if (form())
1520             form()->submitClick(evt);
1521         evt->setDefaultHandled();
1522         return;
1523     }
1524
1525     if (evt->isBeforeTextInsertedEvent())
1526         InputElement::handleBeforeTextInsertedEvent(m_data, this, this, evt);
1527
1528     if (isTextField() && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == eventNames().blurEvent || evt->type() == eventNames().focusEvent))
1529         toRenderTextControlSingleLine(renderer())->forwardEvent(evt);
1530
1531     if (inputType() == RANGE && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent()))
1532         toRenderSlider(renderer())->forwardEvent(evt);
1533
1534     if (!callBaseClassEarly && !evt->defaultHandled())
1535         HTMLFormControlElementWithState::defaultEventHandler(evt);
1536 }
1537
1538 bool HTMLInputElement::isURLAttribute(Attribute *attr) const
1539 {
1540     return (attr->name() == srcAttr);
1541 }
1542
1543 String HTMLInputElement::defaultValue() const
1544 {
1545     return getAttribute(valueAttr);
1546 }
1547
1548 void HTMLInputElement::setDefaultValue(const String &value)
1549 {
1550     setAttribute(valueAttr, value);
1551 }
1552
1553 bool HTMLInputElement::defaultChecked() const
1554 {
1555     return !getAttribute(checkedAttr).isNull();
1556 }
1557
1558 void HTMLInputElement::setDefaultChecked(bool defaultChecked)
1559 {
1560     setAttribute(checkedAttr, defaultChecked ? "" : 0);
1561 }
1562
1563 void HTMLInputElement::setDefaultName(const AtomicString& name)
1564 {
1565     m_data.setName(name);
1566 }
1567
1568 String HTMLInputElement::accept() const
1569 {
1570     return getAttribute(acceptAttr);
1571 }
1572
1573 void HTMLInputElement::setAccept(const String &value)
1574 {
1575     setAttribute(acceptAttr, value);
1576 }
1577
1578 String HTMLInputElement::accessKey() const
1579 {
1580     return getAttribute(accesskeyAttr);
1581 }
1582
1583 void HTMLInputElement::setAccessKey(const String &value)
1584 {
1585     setAttribute(accesskeyAttr, value);
1586 }
1587
1588 String HTMLInputElement::align() const
1589 {
1590     return getAttribute(alignAttr);
1591 }
1592
1593 void HTMLInputElement::setAlign(const String &value)
1594 {
1595     setAttribute(alignAttr, value);
1596 }
1597
1598 String HTMLInputElement::alt() const
1599 {
1600     return getAttribute(altAttr);
1601 }
1602
1603 void HTMLInputElement::setAlt(const String &value)
1604 {
1605     setAttribute(altAttr, value);
1606 }
1607
1608 int HTMLInputElement::maxLength() const
1609 {
1610     return m_data.maxLength();
1611 }
1612
1613 void HTMLInputElement::setMaxLength(int _maxLength, ExceptionCode& exceptionCode)
1614 {
1615     if (_maxLength < 0)
1616         exceptionCode = INDEX_SIZE_ERR;
1617     else
1618         setAttribute(maxlengthAttr, String::number(_maxLength));
1619 }
1620
1621 bool HTMLInputElement::multiple() const
1622 {
1623     return !getAttribute(multipleAttr).isNull();
1624 }
1625
1626 void HTMLInputElement::setMultiple(bool multiple)
1627 {
1628     setAttribute(multipleAttr, multiple ? "" : 0);
1629 }
1630     
1631 void HTMLInputElement::setSize(unsigned _size)
1632 {
1633     setAttribute(sizeAttr, String::number(_size));
1634 }
1635
1636 KURL HTMLInputElement::src() const
1637 {
1638     return document()->completeURL(getAttribute(srcAttr));
1639 }
1640
1641 void HTMLInputElement::setSrc(const String &value)
1642 {
1643     setAttribute(srcAttr, value);
1644 }
1645
1646 String HTMLInputElement::useMap() const
1647 {
1648     return getAttribute(usemapAttr);
1649 }
1650
1651 void HTMLInputElement::setUseMap(const String &value)
1652 {
1653     setAttribute(usemapAttr, value);
1654 }
1655
1656 void HTMLInputElement::setAutofilled(bool b)
1657 {
1658     if (b == m_autofilled)
1659         return;
1660         
1661     m_autofilled = b;
1662     setNeedsStyleRecalc();
1663 }
1664
1665 FileList* HTMLInputElement::files()
1666 {
1667     if (inputType() != FILE)
1668         return 0;
1669     return m_fileList.get();
1670 }
1671
1672 String HTMLInputElement::sanitizeValue(const String& proposedValue) const
1673 {
1674     if (isTextField())
1675         return InputElement::sanitizeValue(this, proposedValue);
1676     return proposedValue;
1677 }
1678
1679 bool HTMLInputElement::needsActivationCallback()
1680 {
1681     return inputType() == PASSWORD || m_autocomplete == Off;
1682 }
1683
1684 void HTMLInputElement::registerForActivationCallbackIfNeeded()
1685 {
1686     if (needsActivationCallback())
1687         document()->registerForDocumentActivationCallbacks(this);
1688 }
1689
1690 void HTMLInputElement::unregisterForActivationCallbackIfNeeded()
1691 {
1692     if (!needsActivationCallback())
1693         document()->unregisterForDocumentActivationCallbacks(this);
1694 }
1695
1696 bool HTMLInputElement::isRequiredFormControl() const
1697 {
1698     if (!required())
1699         return false;
1700
1701     switch (inputType()) {
1702         case TEXT:
1703         case SEARCH:
1704         case URL:
1705         case TELEPHONE:
1706         case EMAIL:
1707         case PASSWORD:
1708         case NUMBER:
1709         case CHECKBOX:
1710         case RADIO:
1711         case FILE:
1712             return true;
1713         case HIDDEN:
1714         case RANGE:
1715         case SUBMIT:
1716         case IMAGE:
1717         case RESET:
1718         case BUTTON:
1719         case COLOR:
1720         case ISINDEX:
1721             return false;
1722     }
1723
1724     ASSERT_NOT_REACHED();
1725     return false;
1726 }
1727
1728 void HTMLInputElement::cacheSelection(int start, int end)
1729 {
1730     m_data.setCachedSelectionStart(start);
1731     m_data.setCachedSelectionEnd(end);
1732 }
1733
1734 void HTMLInputElement::addSearchResult()
1735 {
1736     ASSERT(isSearchField());
1737     if (renderer())
1738         toRenderTextControlSingleLine(renderer())->addSearchResult();
1739 }
1740
1741 void HTMLInputElement::onSearch()
1742 {
1743     ASSERT(isSearchField());
1744     if (renderer())
1745         toRenderTextControlSingleLine(renderer())->stopSearchEventTimer();
1746     dispatchEvent(Event::create(eventNames().searchEvent, true, false));
1747 }
1748
1749 VisibleSelection HTMLInputElement::selection() const
1750 {
1751     if (!renderer() || !isTextField() || m_data.cachedSelectionStart() == -1 || m_data.cachedSelectionEnd() == -1)
1752         return VisibleSelection();
1753     return toRenderTextControl(renderer())->selection(m_data.cachedSelectionStart(), m_data.cachedSelectionEnd());
1754 }
1755
1756 void HTMLInputElement::documentDidBecomeActive()
1757 {
1758     ASSERT(needsActivationCallback());
1759     reset();
1760 }
1761
1762 void HTMLInputElement::willMoveToNewOwnerDocument()
1763 {
1764     // Always unregister for cache callbacks when leaving a document, even if we would otherwise like to be registered
1765     if (needsActivationCallback())
1766         document()->unregisterForDocumentActivationCallbacks(this);
1767         
1768     document()->checkedRadioButtons().removeButton(this);
1769     
1770     HTMLFormControlElementWithState::willMoveToNewOwnerDocument();
1771 }
1772
1773 void HTMLInputElement::didMoveToNewOwnerDocument()
1774 {
1775     registerForActivationCallbackIfNeeded();
1776         
1777     HTMLFormControlElementWithState::didMoveToNewOwnerDocument();
1778 }
1779     
1780 void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
1781 {
1782     HTMLFormControlElementWithState::addSubresourceAttributeURLs(urls);
1783
1784     addSubresourceURL(urls, src());
1785 }
1786
1787 bool HTMLInputElement::willValidate() const
1788 {
1789     // FIXME: This shall check for new WF2 input types too
1790     return HTMLFormControlElementWithState::willValidate() && inputType() != HIDDEN &&
1791            inputType() != BUTTON && inputType() != RESET;
1792 }
1793
1794 bool HTMLInputElement::formStringToDouble(const String& src, double* out)
1795 {
1796     // See HTML5 2.4.4.3 `Real numbers.'
1797
1798     if (src.isEmpty())
1799         return false;
1800     // String::toDouble() accepts leading + \t \n \v \f \r and SPACE, which are invalid in HTML5.
1801     // So, check the first character.
1802     if (src[0] != '-' && (src[0] < '0' || src[0] > '9'))
1803         return false;
1804
1805     bool valid = false;
1806     double value = src.toDouble(&valid);
1807     if (!valid)
1808         return false;
1809     // NaN and Infinity are not valid numbers according to the standard.
1810     if (isnan(value) || isinf(value))
1811         return false;
1812     if (out)
1813         *out = value;
1814     return true;
1815 }
1816
1817 #if ENABLE(DATALIST)
1818 HTMLElement* HTMLInputElement::list() const
1819 {
1820     return dataList();
1821 }
1822
1823 HTMLDataListElement* HTMLInputElement::dataList() const
1824 {
1825     if (!m_hasNonEmptyList)
1826         return 0;
1827
1828     switch (inputType()) {
1829     case TEXT:
1830     case SEARCH:
1831     case URL:
1832     case TELEPHONE:
1833     case EMAIL:
1834     case NUMBER:
1835     case RANGE:
1836     case COLOR: {
1837         Element* element = document()->getElementById(getAttribute(listAttr));
1838         if (element && element->hasTagName(datalistTag))
1839             return static_cast<HTMLDataListElement*>(element);
1840         break;
1841     }
1842     case HIDDEN:
1843     case PASSWORD:
1844     case CHECKBOX:
1845     case RADIO:
1846     case FILE:
1847     case SUBMIT:
1848     case IMAGE:
1849     case RESET:
1850     case BUTTON:
1851     case ISINDEX:
1852         break;
1853     }
1854     return 0;
1855 }
1856
1857 HTMLOptionElement* HTMLInputElement::selectedOption() const
1858 {
1859     String currentValue = value();
1860     // The empty value never matches to a datalist option because it
1861     // doesn't represent a suggestion according to the standard.
1862     if (currentValue.isEmpty())
1863         return 0;
1864
1865     HTMLDataListElement* sourceElement = dataList();
1866     if (!sourceElement)
1867         return 0;
1868     RefPtr<HTMLCollection> options = sourceElement->options();
1869     for (unsigned i = 0; options && i < options->length(); ++i) {
1870         HTMLOptionElement* option = static_cast<HTMLOptionElement*>(options->item(i));
1871         if (!option->disabled() && currentValue == option->value())
1872             return option;
1873     }
1874     return 0;
1875 }
1876 #endif  // ENABLE(DATALIST)
1877
1878 } // namespace