../WebCore: [Windows] Refactor RuntimeEnabledFeatures as a Singleton
[WebKit-https.git] / Source / WebCore / html / InputType.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, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved.
6  *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
7  * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
8  * Copyright (C) 2009, 2010, 2011, 2012 Google Inc. All rights reserved.
9  * Copyright (C) 2012 Samsung Electronics. All rights reserved.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this library; see the file COPYING.LIB.  If not, write to
23  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA 02110-1301, USA.
25  *
26  */
27
28 #include "config.h"
29 #include "InputType.h"
30
31 #include "AXObjectCache.h"
32 #include "BeforeTextInsertedEvent.h"
33 #include "ButtonInputType.h"
34 #include "CheckboxInputType.h"
35 #include "ColorInputType.h"
36 #include "DateComponents.h"
37 #include "DateInputType.h"
38 #include "DateTimeInputType.h"
39 #include "DateTimeLocalInputType.h"
40 #include "EmailInputType.h"
41 #include "ExceptionCode.h"
42 #include "ExceptionCodePlaceholder.h"
43 #include "FileInputType.h"
44 #include "FileList.h"
45 #include "FormController.h"
46 #include "FormDataList.h"
47 #include "HTMLFormElement.h"
48 #include "HTMLInputElement.h"
49 #include "HTMLNames.h"
50 #include "HTMLParserIdioms.h"
51 #include "HiddenInputType.h"
52 #include "ImageInputType.h"
53 #include "InputTypeNames.h"
54 #include "KeyboardEvent.h"
55 #include "LocalizedStrings.h"
56 #include "MonthInputType.h"
57 #include "NodeRenderStyle.h"
58 #include "NumberInputType.h"
59 #include "Page.h"
60 #include "PasswordInputType.h"
61 #include "RadioInputType.h"
62 #include "RangeInputType.h"
63 #include "RegularExpression.h"
64 #include "RenderElement.h"
65 #include "RenderTheme.h"
66 #include "ResetInputType.h"
67 #include "RuntimeEnabledFeatures.h"
68 #include "SearchInputType.h"
69 #include "ShadowRoot.h"
70 #include "SubmitInputType.h"
71 #include "TelephoneInputType.h"
72 #include "TextBreakIterator.h"
73 #include "TextInputType.h"
74 #include "TimeInputType.h"
75 #include "URLInputType.h"
76 #include "WeekInputType.h"
77 #include <limits>
78 #include <wtf/Assertions.h>
79 #include <wtf/HashMap.h>
80 #include <wtf/text/StringHash.h>
81
82 namespace WebCore {
83
84 using namespace HTMLNames;
85 using namespace std;
86
87 typedef OwnPtr<InputType> (*InputTypeFactoryFunction)(HTMLInputElement&);
88 typedef HashMap<AtomicString, InputTypeFactoryFunction, CaseFoldingHash> InputTypeFactoryMap;
89
90 static OwnPtr<InputTypeFactoryMap> createInputTypeFactoryMap()
91 {
92     OwnPtr<InputTypeFactoryMap> map = adoptPtr(new InputTypeFactoryMap);
93
94     // FIXME: Remove unnecessary '&'s from the following map.add operations
95     // once we switch to a non-broken Visual Studio compiler.  https://bugs.webkit.org/show_bug.cgi?id=121235
96     map->add(InputTypeNames::button(), &ButtonInputType::create);
97     map->add(InputTypeNames::checkbox(), &CheckboxInputType::create);
98 #if ENABLE(INPUT_TYPE_COLOR)
99     map->add(InputTypeNames::color(), &ColorInputType::create);
100 #endif
101 #if ENABLE(INPUT_TYPE_DATE)
102     if (RuntimeEnabledFeatures::sharedFeatures().inputTypeDateEnabled())
103         map->add(InputTypeNames::date(), &DateInputType::create);
104 #endif
105 #if ENABLE(INPUT_TYPE_DATETIME_INCOMPLETE)
106     if (RuntimeEnabledFeatures::sharedFeatures().inputTypeDateTimeEnabled())
107         map->add(InputTypeNames::datetime(), &DateTimeInputType::create);
108 #endif
109 #if ENABLE(INPUT_TYPE_DATETIMELOCAL)
110     if (RuntimeEnabledFeatures::sharedFeatures().inputTypeDateTimeLocalEnabled())
111         map->add(InputTypeNames::datetimelocal(), &DateTimeLocalInputType::create);
112 #endif
113     map->add(InputTypeNames::email(), &EmailInputType::create);
114     map->add(InputTypeNames::file(), &FileInputType::create);
115     map->add(InputTypeNames::hidden(), &HiddenInputType::create);
116     map->add(InputTypeNames::image(), &ImageInputType::create);
117 #if ENABLE(INPUT_TYPE_MONTH)
118     if (RuntimeEnabledFeatures::sharedFeatures().inputTypeMonthEnabled())
119         map->add(InputTypeNames::month(), &MonthInputType::create);
120 #endif
121     map->add(InputTypeNames::number(), &NumberInputType::create);
122     map->add(InputTypeNames::password(), &PasswordInputType::create);
123     map->add(InputTypeNames::radio(), &RadioInputType::create);
124     map->add(InputTypeNames::range(), &RangeInputType::create);
125     map->add(InputTypeNames::reset(), &ResetInputType::create);
126     map->add(InputTypeNames::search(), &SearchInputType::create);
127     map->add(InputTypeNames::submit(), &SubmitInputType::create);
128     map->add(InputTypeNames::telephone(), &TelephoneInputType::create);
129 #if ENABLE(INPUT_TYPE_TIME)
130     if (RuntimeEnabledFeatures::sharedFeatures().inputTypeTimeEnabled())
131         map->add(InputTypeNames::time(), &TimeInputType::create);
132 #endif
133     map->add(InputTypeNames::url(), &URLInputType::create);
134 #if ENABLE(INPUT_TYPE_WEEK)
135     if (RuntimeEnabledFeatures::sharedFeatures().inputTypeWeekEnabled())
136         map->add(InputTypeNames::week(), &WeekInputType::create);
137 #endif
138     // No need to register "text" because it is the default type.
139
140     return map;
141 }
142
143 OwnPtr<InputType> InputType::create(HTMLInputElement& element, const AtomicString& typeName)
144 {
145     static const InputTypeFactoryMap* factoryMap = createInputTypeFactoryMap().leakPtr();
146     OwnPtr<InputType> (*factory)(HTMLInputElement&) = typeName.isEmpty() ? 0 : factoryMap->get(typeName);
147     if (!factory)
148         factory = TextInputType::create;
149     return factory(element);
150 }
151
152 OwnPtr<InputType> InputType::createText(HTMLInputElement& element)
153 {
154     return TextInputType::create(element);
155 }
156
157 InputType::~InputType()
158 {
159 }
160
161 bool InputType::themeSupportsDataListUI(InputType* type)
162 {
163     Document& document = type->element().document();
164     RefPtr<RenderTheme> theme = document.page() ? document.page()->theme() : RenderTheme::defaultTheme();
165     return theme->supportsDataListUI(type->formControlType());
166 }
167
168 bool InputType::isTextField() const
169 {
170     return false;
171 }
172
173 bool InputType::isTextType() const
174 {
175     return false;
176 }
177
178 bool InputType::isRangeControl() const
179 {
180     return false;
181 }
182
183 bool InputType::shouldSaveAndRestoreFormControlState() const
184 {
185     return true;
186 }
187
188 FormControlState InputType::saveFormControlState() const
189 {
190     String currentValue = element().value();
191     if (currentValue == element().defaultValue())
192         return FormControlState();
193     return FormControlState(currentValue);
194 }
195
196 void InputType::restoreFormControlState(const FormControlState& state)
197 {
198     element().setValue(state[0]);
199 }
200
201 bool InputType::isFormDataAppendable() const
202 {
203     // There is no form data unless there's a name for non-image types.
204     return !element().name().isEmpty();
205 }
206
207 bool InputType::appendFormData(FormDataList& encoding, bool) const
208 {
209     // Always successful.
210     encoding.appendData(element().name(), element().value());
211     return true;
212 }
213
214 double InputType::valueAsDate() const
215 {
216     return DateComponents::invalidMilliseconds();
217 }
218
219 void InputType::setValueAsDate(double, ExceptionCode& ec) const
220 {
221     ec = INVALID_STATE_ERR;
222 }
223
224 double InputType::valueAsDouble() const
225 {
226     return numeric_limits<double>::quiet_NaN();
227 }
228
229 void InputType::setValueAsDouble(double doubleValue, TextFieldEventBehavior eventBehavior, ExceptionCode& ec) const
230 {
231     setValueAsDecimal(Decimal::fromDouble(doubleValue), eventBehavior, ec);
232 }
233
234 void InputType::setValueAsDecimal(const Decimal&, TextFieldEventBehavior, ExceptionCode& ec) const
235 {
236     ec = INVALID_STATE_ERR;
237 }
238
239 bool InputType::supportsValidation() const
240 {
241     return true;
242 }
243
244 bool InputType::typeMismatchFor(const String&) const
245 {
246     return false;
247 }
248
249 bool InputType::typeMismatch() const
250 {
251     return false;
252 }
253
254 bool InputType::supportsRequired() const
255 {
256     // Almost all validatable types support @required.
257     return supportsValidation();
258 }
259
260 bool InputType::valueMissing(const String&) const
261 {
262     return false;
263 }
264
265 bool InputType::hasBadInput() const
266 {
267     return false;
268 }
269
270 bool InputType::patternMismatch(const String&) const
271 {
272     return false;
273 }
274
275 bool InputType::rangeUnderflow(const String& value) const
276 {
277     if (!isSteppable())
278         return false;
279
280     const Decimal numericValue = parseToNumberOrNaN(value);
281     if (!numericValue.isFinite())
282         return false;
283
284     return numericValue < createStepRange(RejectAny).minimum();
285 }
286
287 bool InputType::rangeOverflow(const String& value) const
288 {
289     if (!isSteppable())
290         return false;
291
292     const Decimal numericValue = parseToNumberOrNaN(value);
293     if (!numericValue.isFinite())
294         return false;
295
296     return numericValue > createStepRange(RejectAny).maximum();
297 }
298
299 Decimal InputType::defaultValueForStepUp() const
300 {
301     return 0;
302 }
303
304 double InputType::minimum() const
305 {
306     return createStepRange(RejectAny).minimum().toDouble();
307 }
308
309 double InputType::maximum() const
310 {
311     return createStepRange(RejectAny).maximum().toDouble();
312 }
313
314 bool InputType::sizeShouldIncludeDecoration(int, int& preferredSize) const
315 {
316     preferredSize = element().size();
317     return false;
318 }
319
320 float InputType::decorationWidth() const
321 {
322     return 0;
323 }
324
325 bool InputType::isInRange(const String& value) const
326 {
327     if (!isSteppable())
328         return false;
329
330     const Decimal numericValue = parseToNumberOrNaN(value);
331     if (!numericValue.isFinite())
332         return true;
333
334     StepRange stepRange(createStepRange(RejectAny));
335     return numericValue >= stepRange.minimum() && numericValue <= stepRange.maximum();
336 }
337
338 bool InputType::isOutOfRange(const String& value) const
339 {
340     if (!isSteppable())
341         return false;
342
343     const Decimal numericValue = parseToNumberOrNaN(value);
344     if (!numericValue.isFinite())
345         return true;
346
347     StepRange stepRange(createStepRange(RejectAny));
348     return numericValue < stepRange.minimum() || numericValue > stepRange.maximum();
349 }
350
351 bool InputType::stepMismatch(const String& value) const
352 {
353     if (!isSteppable())
354         return false;
355
356     const Decimal numericValue = parseToNumberOrNaN(value);
357     if (!numericValue.isFinite())
358         return false;
359
360     return createStepRange(RejectAny).stepMismatch(numericValue);
361 }
362
363 String InputType::badInputText() const
364 {
365     ASSERT_NOT_REACHED();
366     return validationMessageTypeMismatchText();
367 }
368
369 String InputType::typeMismatchText() const
370 {
371     return validationMessageTypeMismatchText();
372 }
373
374 String InputType::valueMissingText() const
375 {
376     return validationMessageValueMissingText();
377 }
378
379 String InputType::validationMessage() const
380 {
381     String value = element().value();
382
383     // The order of the following checks is meaningful. e.g. We'd like to show the
384     // badInput message even if the control has other validation errors.
385     if (hasBadInput())
386         return badInputText();
387
388     if (valueMissing(value))
389         return valueMissingText();
390
391     if (typeMismatch())
392         return typeMismatchText();
393
394     if (patternMismatch(value))
395         return validationMessagePatternMismatchText();
396
397     if (element().tooLong())
398         return validationMessageTooLongText(numGraphemeClusters(value), element().maxLength());
399
400     if (!isSteppable())
401         return emptyString();
402
403     const Decimal numericValue = parseToNumberOrNaN(value);
404     if (!numericValue.isFinite())
405         return emptyString();
406
407     StepRange stepRange(createStepRange(RejectAny));
408
409     if (numericValue < stepRange.minimum())
410         return validationMessageRangeUnderflowText(serialize(stepRange.minimum()));
411
412     if (numericValue > stepRange.maximum())
413         return validationMessageRangeOverflowText(serialize(stepRange.maximum()));
414
415     if (stepRange.stepMismatch(numericValue)) {
416         const String stepString = stepRange.hasStep() ? serializeForNumberType(stepRange.step() / stepRange.stepScaleFactor()) : emptyString();
417         return validationMessageStepMismatchText(serialize(stepRange.stepBase()), stepString);
418     }
419
420     return emptyString();
421 }
422
423 void InputType::handleClickEvent(MouseEvent*)
424 {
425 }
426
427 void InputType::handleMouseDownEvent(MouseEvent*)
428 {
429 }
430
431 void InputType::handleDOMActivateEvent(Event*)
432 {
433 }
434
435 void InputType::handleKeydownEvent(KeyboardEvent*)
436 {
437 }
438
439 void InputType::handleKeypressEvent(KeyboardEvent*)
440 {
441 }
442
443 void InputType::handleKeyupEvent(KeyboardEvent*)
444 {
445 }
446
447 void InputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*)
448 {
449 }
450
451 #if ENABLE(TOUCH_EVENTS)
452 void InputType::handleTouchEvent(TouchEvent*)
453 {
454 }
455 #endif
456
457 void InputType::forwardEvent(Event*)
458 {
459 }
460
461 bool InputType::shouldSubmitImplicitly(Event* event)
462 {
463     return event->isKeyboardEvent() && event->type() == eventNames().keypressEvent && static_cast<KeyboardEvent*>(event)->charCode() == '\r';
464 }
465
466 PassRefPtr<HTMLFormElement> InputType::formForSubmission() const
467 {
468     return element().form();
469 }
470
471 RenderElement* InputType::createRenderer(RenderArena&, RenderStyle& style) const
472 {
473     return RenderElement::createFor(element(), style);
474 }
475
476 void InputType::blur()
477 {
478     element().defaultBlur();
479 }
480
481 void InputType::createShadowSubtree()
482 {
483 }
484
485 void InputType::destroyShadowSubtree()
486 {
487     ShadowRoot* root = element().userAgentShadowRoot();
488     if (!root)
489         return;
490
491     root->removeChildren();
492 }
493
494 Decimal InputType::parseToNumber(const String&, const Decimal& defaultValue) const
495 {
496     ASSERT_NOT_REACHED();
497     return defaultValue;
498 }
499
500 Decimal InputType::parseToNumberOrNaN(const String& string) const
501 {
502     return parseToNumber(string, Decimal::nan());
503 }
504
505 bool InputType::parseToDateComponents(const String&, DateComponents*) const
506 {
507     ASSERT_NOT_REACHED();
508     return false;
509 }
510
511 String InputType::serialize(const Decimal&) const
512 {
513     ASSERT_NOT_REACHED();
514     return String();
515 }
516
517 void InputType::dispatchSimulatedClickIfActive(KeyboardEvent* event) const
518 {
519     if (element().active())
520         element().dispatchSimulatedClick(event);
521     event->setDefaultHandled();
522 }
523
524 Chrome* InputType::chrome() const
525 {
526     if (Page* page = element().document().page())
527         return &page->chrome();
528     return 0;
529 }
530
531 bool InputType::canSetStringValue() const
532 {
533     return true;
534 }
535
536 bool InputType::hasCustomFocusLogic() const
537 {
538     return true;
539 }
540
541 bool InputType::isKeyboardFocusable(KeyboardEvent* event) const
542 {
543     return element().isTextFormControlKeyboardFocusable(event);
544 }
545
546 bool InputType::isMouseFocusable() const
547 {
548     return element().isTextFormControlMouseFocusable();
549 }
550
551 bool InputType::shouldUseInputMethod() const
552 {
553     return false;
554 }
555
556 void InputType::handleFocusEvent(Node*, FocusDirection)
557 {
558 }
559
560 void InputType::handleBlurEvent()
561 {
562 }
563
564 void InputType::accessKeyAction(bool)
565 {
566     element().focus(false);
567 }
568
569 void InputType::addSearchResult()
570 {
571 }
572
573 void InputType::attach()
574 {
575 }
576
577 void InputType::detach()
578 {
579 }
580
581 void InputType::altAttributeChanged()
582 {
583 }
584
585 void InputType::srcAttributeChanged()
586 {
587 }
588
589 bool InputType::shouldRespectAlignAttribute()
590 {
591     return false;
592 }
593
594 bool InputType::canChangeFromAnotherType() const
595 {
596     return true;
597 }
598
599 void InputType::minOrMaxAttributeChanged()
600 {
601 }
602
603 void InputType::stepAttributeChanged()
604 {
605 }
606
607 bool InputType::canBeSuccessfulSubmitButton()
608 {
609     return false;
610 }
611
612 HTMLElement* InputType::placeholderElement() const
613 {
614     return 0;
615 }
616
617 bool InputType::rendererIsNeeded()
618 {
619     return true;
620 }
621
622 FileList* InputType::files()
623 {
624     return 0;
625 }
626
627 void InputType::setFiles(PassRefPtr<FileList>)
628 {
629 }
630
631 bool InputType::getTypeSpecificValue(String&)
632 {
633     return false;
634 }
635
636 String InputType::fallbackValue() const
637 {
638     return String();
639 }
640
641 String InputType::defaultValue() const
642 {
643     return String();
644 }
645
646 bool InputType::canSetSuggestedValue()
647 {
648     return false;
649 }
650
651 bool InputType::shouldSendChangeEventAfterCheckedChanged()
652 {
653     return true;
654 }
655
656 bool InputType::storesValueSeparateFromAttribute()
657 {
658     return true;
659 }
660
661 void InputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
662 {
663     element().setValueInternal(sanitizedValue, eventBehavior);
664     element().setNeedsStyleRecalc();
665     if (!valueChanged)
666         return;
667     switch (eventBehavior) {
668     case DispatchChangeEvent:
669         element().dispatchFormControlChangeEvent();
670         break;
671     case DispatchInputAndChangeEvent:
672         element().dispatchFormControlInputEvent();
673         element().dispatchFormControlChangeEvent();
674         break;
675     case DispatchNoEvent:
676         break;
677     }
678 }
679
680 bool InputType::canSetValue(const String&)
681 {
682     return true;
683 }
684
685 OwnPtr<ClickHandlingState> InputType::willDispatchClick()
686 {
687     return nullptr;
688 }
689
690 void InputType::didDispatchClick(Event*, const ClickHandlingState&)
691 {
692 }
693
694 String InputType::localizeValue(const String& proposedValue) const
695 {
696     return proposedValue;
697 }
698
699 String InputType::visibleValue() const
700 {
701     return element().value();
702 }
703
704 String InputType::sanitizeValue(const String& proposedValue) const
705 {
706     return proposedValue;
707 }
708
709 bool InputType::receiveDroppedFiles(const DragData*)
710 {
711     ASSERT_NOT_REACHED();
712     return false;
713 }
714
715 #if ENABLE(FILE_SYSTEM)
716 String InputType::droppedFileSystemId()
717 {
718     ASSERT_NOT_REACHED();
719     return String();
720 }
721 #endif
722
723 Icon* InputType::icon() const
724 {
725     ASSERT_NOT_REACHED();
726     return 0;
727 }
728
729 bool InputType::shouldResetOnDocumentActivation()
730 {
731     return false;
732 }
733
734 bool InputType::shouldRespectListAttribute()
735 {
736     return false;
737 }
738
739 bool InputType::shouldRespectSpeechAttribute()
740 {
741     return false;
742 }
743
744 bool InputType::isTextButton() const
745 {
746     return false;
747 }
748
749 bool InputType::isRadioButton() const
750 {
751     return false;
752 }
753
754 bool InputType::isSearchField() const
755 {
756     return false;
757 }
758
759 bool InputType::isHiddenType() const
760 {
761     return false;
762 }
763
764 bool InputType::isPasswordField() const
765 {
766     return false;
767 }
768
769 bool InputType::isCheckbox() const
770 {
771     return false;
772 }
773
774 bool InputType::isEmailField() const
775 {
776     return false;
777 }
778
779 bool InputType::isFileUpload() const
780 {
781     return false;
782 }
783
784 bool InputType::isImageButton() const
785 {
786     return false;
787 }
788
789 bool InputType::supportLabels() const
790 {
791     return true;
792 }
793
794 bool InputType::isNumberField() const
795 {
796     return false;
797 }
798
799 bool InputType::isSubmitButton() const
800 {
801     return false;
802 }
803
804 bool InputType::isTelephoneField() const
805 {
806     return false;
807 }
808
809 bool InputType::isURLField() const
810 {
811     return false;
812 }
813
814 bool InputType::isDateField() const
815 {
816     return false;
817 }
818
819 bool InputType::isDateTimeField() const
820 {
821     return false;
822 }
823
824 bool InputType::isDateTimeLocalField() const
825 {
826     return false;
827 }
828
829 bool InputType::isMonthField() const
830 {
831     return false;
832 }
833
834 bool InputType::isTimeField() const
835 {
836     return false;
837 }
838
839 bool InputType::isWeekField() const
840 {
841     return false;
842 }
843
844 bool InputType::isEnumeratable()
845 {
846     return true;
847 }
848
849 bool InputType::isCheckable()
850 {
851     return false;
852 }
853
854 bool InputType::isSteppable() const
855 {
856     return false;
857 }
858
859 #if ENABLE(INPUT_TYPE_COLOR)
860 bool InputType::isColorControl() const
861 {
862     return false;
863 }
864 #endif
865
866 bool InputType::shouldRespectHeightAndWidthAttributes()
867 {
868     return false;
869 }
870
871 bool InputType::supportsPlaceholder() const
872 {
873     return false;
874 }
875
876 bool InputType::supportsReadOnly() const
877 {
878     return false;
879 }
880
881 void InputType::updateInnerTextValue()
882 {
883 }
884
885 void InputType::updatePlaceholderText()
886 {
887 }
888
889 void InputType::attributeChanged()
890 {
891 }
892
893 void InputType::multipleAttributeChanged()
894 {
895 }
896
897 void InputType::disabledAttributeChanged()
898 {
899 }
900
901 void InputType::readonlyAttributeChanged()
902 {
903 }
904
905 void InputType::requiredAttributeChanged()
906 {
907 }
908
909 void InputType::valueAttributeChanged()
910 {
911 }
912
913 void InputType::subtreeHasChanged()
914 {
915     ASSERT_NOT_REACHED();
916 }
917
918 #if ENABLE(TOUCH_EVENTS)
919 bool InputType::hasTouchEventHandler() const
920 {
921     return false;
922 }
923 #endif
924
925 String InputType::defaultToolTip() const
926 {
927     return String();
928 }
929
930 #if ENABLE(DATALIST_ELEMENT)
931 void InputType::listAttributeTargetChanged()
932 {
933 }
934
935 Decimal InputType::findClosestTickMarkValue(const Decimal&)
936 {
937     ASSERT_NOT_REACHED();
938     return Decimal::nan();
939 }
940 #endif
941
942 void InputType::updateClearButtonVisibility()
943 {
944 }
945
946 bool InputType::supportsIndeterminateAppearance() const
947 {
948     return false;
949 }
950
951 bool InputType::supportsSelectionAPI() const
952 {
953     return false;
954 }
955
956 unsigned InputType::height() const
957 {
958     return 0;
959 }
960
961 unsigned InputType::width() const
962 {
963     return 0;
964 }
965
966 void InputType::applyStep(int count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior, ExceptionCode& ec)
967 {
968     StepRange stepRange(createStepRange(anyStepHandling));
969     if (!stepRange.hasStep()) {
970         ec = INVALID_STATE_ERR;
971         return;
972     }
973
974     const Decimal current = parseToNumberOrNaN(element().value());
975     if (!current.isFinite()) {
976         ec = INVALID_STATE_ERR;
977         return;
978     }
979     Decimal newValue = current + stepRange.step() * count;
980     if (!newValue.isFinite()) {
981         ec = INVALID_STATE_ERR;
982         return;
983     }
984
985     const Decimal acceptableErrorValue = stepRange.acceptableError();
986     if (newValue - stepRange.minimum() < -acceptableErrorValue) {
987         ec = INVALID_STATE_ERR;
988         return;
989     }
990     if (newValue < stepRange.minimum())
991         newValue = stepRange.minimum();
992
993     const AtomicString& stepString = element().fastGetAttribute(stepAttr);
994     if (!equalIgnoringCase(stepString, "any"))
995         newValue = stepRange.alignValueForStep(current, newValue);
996
997     if (newValue - stepRange.maximum() > acceptableErrorValue) {
998         ec = INVALID_STATE_ERR;
999         return;
1000     }
1001     if (newValue > stepRange.maximum())
1002         newValue = stepRange.maximum();
1003
1004     setValueAsDecimal(newValue, eventBehavior, ec);
1005
1006     if (AXObjectCache* cache = element().document().existingAXObjectCache())
1007         cache->postNotification(&element(), AXObjectCache::AXValueChanged);
1008 }
1009
1010 bool InputType::getAllowedValueStep(Decimal* step) const
1011 {
1012     StepRange stepRange(createStepRange(RejectAny));
1013     *step = stepRange.step();
1014     return stepRange.hasStep();
1015 }
1016
1017 StepRange InputType::createStepRange(AnyStepHandling) const
1018 {
1019     ASSERT_NOT_REACHED();
1020     return StepRange();
1021 }
1022
1023 void InputType::stepUp(int n, ExceptionCode& ec)
1024 {
1025     if (!isSteppable()) {
1026         ec = INVALID_STATE_ERR;
1027         return;
1028     }
1029     applyStep(n, RejectAny, DispatchNoEvent, ec);
1030 }
1031
1032 void InputType::stepUpFromRenderer(int n)
1033 {
1034     // The differences from stepUp()/stepDown():
1035     //
1036     // Difference 1: the current value
1037     // If the current value is not a number, including empty, the current value is assumed as 0.
1038     //   * If 0 is in-range, and matches to step value
1039     //     - The value should be the +step if n > 0
1040     //     - The value should be the -step if n < 0
1041     //     If -step or +step is out of range, new value should be 0.
1042     //   * If 0 is smaller than the minimum value
1043     //     - The value should be the minimum value for any n
1044     //   * If 0 is larger than the maximum value
1045     //     - The value should be the maximum value for any n
1046     //   * If 0 is in-range, but not matched to step value
1047     //     - The value should be the larger matched value nearest to 0 if n > 0
1048     //       e.g. <input type=number min=-100 step=3> -> 2
1049     //     - The value should be the smaler matched value nearest to 0 if n < 0
1050     //       e.g. <input type=number min=-100 step=3> -> -1
1051     //   As for date/datetime-local/month/time/week types, the current value is assumed as "the current local date/time".
1052     //   As for datetime type, the current value is assumed as "the current date/time in UTC".
1053     // If the current value is smaller than the minimum value:
1054     //  - The value should be the minimum value if n > 0
1055     //  - Nothing should happen if n < 0
1056     // If the current value is larger than the maximum value:
1057     //  - The value should be the maximum value if n < 0
1058     //  - Nothing should happen if n > 0
1059     //
1060     // Difference 2: clamping steps
1061     // If the current value is not matched to step value:
1062     // - The value should be the larger matched value nearest to 0 if n > 0
1063     //   e.g. <input type=number value=3 min=-100 step=3> -> 5
1064     // - The value should be the smaler matched value nearest to 0 if n < 0
1065     //   e.g. <input type=number value=3 min=-100 step=3> -> 2
1066     //
1067     // n is assumed as -n if step < 0.
1068
1069     ASSERT(isSteppable());
1070     if (!isSteppable())
1071         return;
1072     ASSERT(n);
1073     if (!n)
1074         return;
1075
1076     StepRange stepRange(createStepRange(AnyIsDefaultStep));
1077
1078     // FIXME: Not any changes after stepping, even if it is an invalid value, may be better.
1079     // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "foo")
1080     if (!stepRange.hasStep())
1081       return;
1082
1083     const Decimal step = stepRange.step();
1084
1085     int sign;
1086     if (step > 0)
1087         sign = n;
1088     else if (step < 0)
1089         sign = -n;
1090     else
1091         sign = 0;
1092
1093     String currentStringValue = element().value();
1094     Decimal current = parseToNumberOrNaN(currentStringValue);
1095     if (!current.isFinite()) {
1096         current = defaultValueForStepUp();
1097         const Decimal nextDiff = step * n;
1098         if (current < stepRange.minimum() - nextDiff)
1099             current = stepRange.minimum() - nextDiff;
1100         if (current > stepRange.maximum() - nextDiff)
1101             current = stepRange.maximum() - nextDiff;
1102         setValueAsDecimal(current, DispatchInputAndChangeEvent, IGNORE_EXCEPTION);
1103     }
1104     if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > stepRange.maximum()))
1105         setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchInputAndChangeEvent, IGNORE_EXCEPTION);
1106     else {
1107         if (stepMismatch(element().value())) {
1108             ASSERT(!step.isZero());
1109             const Decimal base = stepRange.stepBase();
1110             Decimal newValue;
1111             if (sign < 0)
1112                 newValue = base + ((current - base) / step).floor() * step;
1113             else if (sign > 0)
1114                 newValue = base + ((current - base) / step).ceiling() * step;
1115             else
1116                 newValue = current;
1117
1118             if (newValue < stepRange.minimum())
1119                 newValue = stepRange.minimum();
1120             if (newValue > stepRange.maximum())
1121                 newValue = stepRange.maximum();
1122
1123             setValueAsDecimal(newValue, n == 1 || n == -1 ? DispatchInputAndChangeEvent : DispatchNoEvent, IGNORE_EXCEPTION);
1124             if (n > 1)
1125                 applyStep(n - 1, AnyIsDefaultStep, DispatchInputAndChangeEvent, IGNORE_EXCEPTION);
1126             else if (n < -1)
1127                 applyStep(n + 1, AnyIsDefaultStep, DispatchInputAndChangeEvent, IGNORE_EXCEPTION);
1128         } else
1129             applyStep(n, AnyIsDefaultStep, DispatchInputAndChangeEvent, IGNORE_EXCEPTION);
1130     }
1131 }
1132
1133 void InputType::observeFeatureIfVisible(FeatureObserver::Feature feature) const
1134 {
1135     if (RenderStyle* style = element().renderStyle()) {
1136         if (style->visibility() != HIDDEN)
1137             FeatureObserver::observe(&element().document(), feature);
1138     }
1139 }
1140
1141 } // namespace WebCore