Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: third_party/WebKit/Source/core/html/HTMLInputElement.cpp

Issue 2463693002: INPUT element: Updating 'step' attribute should adjust the last value. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
6 * rights reserved. 6 * rights reserved.
7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
8 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) 8 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
9 * Copyright (C) 2010 Google Inc. All rights reserved. 9 * Copyright (C) 2010 Google Inc. All rights reserved.
10 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. 10 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved.
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 380
381 void HTMLInputElement::initializeTypeInParsing() { 381 void HTMLInputElement::initializeTypeInParsing() {
382 DCHECK(m_parsingInProgress); 382 DCHECK(m_parsingInProgress);
383 DCHECK(!m_inputType); 383 DCHECK(!m_inputType);
384 DCHECK(!m_inputTypeView); 384 DCHECK(!m_inputTypeView);
385 385
386 const AtomicString& newTypeName = 386 const AtomicString& newTypeName =
387 InputType::normalizeTypeName(fastGetAttribute(typeAttr)); 387 InputType::normalizeTypeName(fastGetAttribute(typeAttr));
388 m_inputType = InputType::create(*this, newTypeName); 388 m_inputType = InputType::create(*this, newTypeName);
389 m_inputTypeView = m_inputType->createView(); 389 m_inputTypeView = m_inputType->createView();
390 String defaultValue = fastGetAttribute(valueAttr);
391 if (m_inputType->valueMode() == ValueMode::kValue)
392 m_valueIfDirty = sanitizeValue(defaultValue);
390 ensureUserAgentShadowRoot(); 393 ensureUserAgentShadowRoot();
391 394
392 setNeedsWillValidateCheck(); 395 setNeedsWillValidateCheck();
393 396
394 m_inputType->warnIfValueIsInvalid(fastGetAttribute(valueAttr).getString()); 397 if (!defaultValue.isNull())
398 m_inputType->warnIfValueIsInvalid(defaultValue);
395 399
396 m_inputTypeView->updateView(); 400 m_inputTypeView->updateView();
397 setTextAsOfLastFormControlChangeEvent(value()); 401 setTextAsOfLastFormControlChangeEvent(value());
398 setChangedSinceLastFormControlChangeEvent(false); 402 setChangedSinceLastFormControlChangeEvent(false);
399 } 403 }
400 404
401 void HTMLInputElement::updateType() { 405 void HTMLInputElement::updateType() {
402 DCHECK(m_inputType); 406 DCHECK(m_inputType);
403 DCHECK(m_inputTypeView); 407 DCHECK(m_inputTypeView);
404 408
(...skipping 23 matching lines...) Expand all
428 432
429 // https://html.spec.whatwg.org/multipage/forms.html#input-type-change 433 // https://html.spec.whatwg.org/multipage/forms.html#input-type-change
430 // 434 //
431 // 1. If the previous state of the element's type attribute put the value IDL 435 // 1. If the previous state of the element's type attribute put the value IDL
432 // attribute in the value mode, and the element's value is not the empty 436 // attribute in the value mode, and the element's value is not the empty
433 // string, and the new state of the element's type attribute puts the value 437 // string, and the new state of the element's type attribute puts the value
434 // IDL attribute in either the default mode or the default/on mode, then set 438 // IDL attribute in either the default mode or the default/on mode, then set
435 // the element's value content attribute to the element's value. 439 // the element's value content attribute to the element's value.
436 if (oldValueMode == ValueMode::kValue && 440 if (oldValueMode == ValueMode::kValue &&
437 (newValueMode == ValueMode::kDefault || 441 (newValueMode == ValueMode::kDefault ||
438 newValueMode == ValueMode::kDefaultOn) && 442 newValueMode == ValueMode::kDefaultOn)) {
439 hasDirtyValue()) { 443 if (hasDirtyValue())
440 setAttribute(valueAttr, AtomicString(m_valueIfDirty)); 444 setAttribute(valueAttr, AtomicString(m_valueIfDirty));
441 m_valueIfDirty = String(); 445 m_valueIfDirty = String();
442 m_hasDirtyValue = false; 446 m_hasDirtyValue = false;
443 } 447 }
444 // 2. Otherwise, if the previous state of the element's type attribute put the 448 // 2. Otherwise, if the previous state of the element's type attribute put the
445 // value IDL attribute in any mode other than the value mode, and the new 449 // value IDL attribute in any mode other than the value mode, and the new
446 // state of the element's type attribute puts the value IDL attribute in the 450 // state of the element's type attribute puts the value IDL attribute in the
447 // value mode, then set the value of the element to the value of the value 451 // value mode, then set the value of the element to the value of the value
448 // content attribute, if there is one, or the empty string otherwise, and then 452 // content attribute, if there is one, or the empty string otherwise, and then
449 // set the control's dirty value flag to false. 453 // set the control's dirty value flag to false.
450 else if (oldValueMode != ValueMode::kValue && 454 else if (oldValueMode != ValueMode::kValue &&
451 newValueMode == ValueMode::kValue) { 455 newValueMode == ValueMode::kValue) {
452 AtomicString valueString = fastGetAttribute(valueAttr); 456 AtomicString valueString = fastGetAttribute(valueAttr);
453 m_inputType->warnIfValueIsInvalid(valueString); 457 m_inputType->warnIfValueIsInvalid(valueString);
454 m_valueIfDirty = String(); 458 m_valueIfDirty = sanitizeValue(valueString);
455 m_hasDirtyValue = false; 459 m_hasDirtyValue = false;
456 } 460 }
457 // 3. Otherwise, if the previous state of the element's type attribute put the 461 // 3. Otherwise, if the previous state of the element's type attribute put the
458 // value IDL attribute in any mode other than the filename mode, and the new 462 // value IDL attribute in any mode other than the filename mode, and the new
459 // state of the element's type attribute puts the value IDL attribute in the 463 // state of the element's type attribute puts the value IDL attribute in the
460 // filename mode, then set the value of the element to the empty string. 464 // filename mode, then set the value of the element to the empty string.
461 else if (oldValueMode != ValueMode::kFilename && 465 else if (oldValueMode != ValueMode::kFilename &&
462 newValueMode == ValueMode::kFilename) { 466 newValueMode == ValueMode::kFilename) {
463 m_valueIfDirty = String(); 467 m_valueIfDirty = String();
464 m_hasDirtyValue = false; 468 m_hasDirtyValue = false;
465 469
466 } else { 470 } else {
467 if (!hasDirtyValue()) 471 // ValueMode wasn't changed, or kDefault <-> kDefaultOn.
468 m_inputType->warnIfValueIsInvalid( 472 if (!hasDirtyValue()) {
469 fastGetAttribute(valueAttr).getString()); 473 String defaultValue = fastGetAttribute(valueAttr);
470 String newValue = sanitizeValue(m_valueIfDirty); 474 if (!defaultValue.isNull())
471 DCHECK(!m_valueIfDirty.isNull() || newValue.isNull()); 475 m_inputType->warnIfValueIsInvalid(defaultValue);
472 if (newValue != m_valueIfDirty) 476 }
473 setValue(newValue); 477
478 if (newValueMode == ValueMode::kValue) {
479 String newValue = sanitizeValue(m_valueIfDirty);
480 if (!equalIgnoringNullity(newValue, m_valueIfDirty)) {
481 if (hasDirtyValue())
482 setValue(newValue);
483 else
484 setNonDirtyValue(newValue);
485 }
486 }
474 } 487 }
475 488
476 m_needsToUpdateViewValue = true; 489 m_needsToUpdateViewValue = true;
477 m_inputTypeView->updateView(); 490 m_inputTypeView->updateView();
478 491
479 if (didRespectHeightAndWidth != 492 if (didRespectHeightAndWidth !=
480 m_inputType->shouldRespectHeightAndWidthAttributes()) { 493 m_inputType->shouldRespectHeightAndWidthAttributes()) {
481 DCHECK(elementData()); 494 DCHECK(elementData());
482 AttributeCollection attributes = attributesWithoutUpdate(); 495 AttributeCollection attributes = attributesWithoutUpdate();
483 if (const Attribute* height = attributes.find(heightAttr)) 496 if (const Attribute* height = attributes.find(heightAttr))
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 m_autocomplete = Uninitialized; 720 m_autocomplete = Uninitialized;
708 else 721 else
709 m_autocomplete = On; 722 m_autocomplete = On;
710 } 723 }
711 } else if (name == typeAttr) { 724 } else if (name == typeAttr) {
712 updateType(); 725 updateType();
713 } else if (name == valueAttr) { 726 } else if (name == valueAttr) {
714 // We only need to setChanged if the form is looking at the default value 727 // We only need to setChanged if the form is looking at the default value
715 // right now. 728 // right now.
716 if (!hasDirtyValue()) { 729 if (!hasDirtyValue()) {
730 if (m_inputType->valueMode() == ValueMode::kValue) {
731 m_valueIfDirty = sanitizeValue(value);
732 setTextAsOfLastFormControlChangeEvent(m_valueIfDirty);
733 }
717 updatePlaceholderVisibility(); 734 updatePlaceholderVisibility();
718 setNeedsStyleRecalc( 735 setNeedsStyleRecalc(
719 SubtreeStyleChange, 736 SubtreeStyleChange,
720 StyleChangeReasonForTracing::fromAttribute(valueAttr)); 737 StyleChangeReasonForTracing::fromAttribute(valueAttr));
721 if (m_inputType->valueMode() == ValueMode::kValue)
722 setTextAsOfLastFormControlChangeEvent(sanitizeValue(value));
723 } 738 }
724 m_needsToUpdateViewValue = true; 739 m_needsToUpdateViewValue = true;
725 setNeedsValidityCheck(); 740 setNeedsValidityCheck();
726 m_valueAttributeWasUpdatedAfterParsing = !m_parsingInProgress; 741 m_valueAttributeWasUpdatedAfterParsing = !m_parsingInProgress;
727 m_inputType->warnIfValueIsInvalidAndElementIsVisible(value); 742 m_inputType->warnIfValueIsInvalidAndElementIsVisible(value);
728 m_inputTypeView->valueAttributeChanged(); 743 m_inputTypeView->valueAttributeChanged();
729 } else if (name == checkedAttr) { 744 } else if (name == checkedAttr) {
730 // Another radio button in the same group might be checked by state 745 // Another radio button in the same group might be checked by state
731 // restore. We shouldn't call setChecked() even if this has the checked 746 // restore. We shouldn't call setChecked() even if this has the checked
732 // attribute. So, delay the setChecked() call until 747 // attribute. So, delay the setChecked() call until
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 void HTMLInputElement::appendToFormData(FormData& formData) { 896 void HTMLInputElement::appendToFormData(FormData& formData) {
882 if (m_inputType->isFormDataAppendable()) 897 if (m_inputType->isFormDataAppendable())
883 m_inputType->appendToFormData(formData); 898 m_inputType->appendToFormData(formData);
884 } 899 }
885 900
886 String HTMLInputElement::resultForDialogSubmit() { 901 String HTMLInputElement::resultForDialogSubmit() {
887 return m_inputType->resultForDialogSubmit(); 902 return m_inputType->resultForDialogSubmit();
888 } 903 }
889 904
890 void HTMLInputElement::resetImpl() { 905 void HTMLInputElement::resetImpl() {
891 if (m_inputType->valueMode() == ValueMode::kValue || 906 if (m_inputType->valueMode() == ValueMode::kValue) {
892 m_inputType->valueMode() == ValueMode::kFilename) { 907 setNonDirtyValue(defaultValue());
893 setValue(String()); 908 setNeedsValidityCheck();
909 } else if (m_inputType->valueMode() == ValueMode::kFilename) {
910 setNonDirtyValue(String());
894 setNeedsValidityCheck(); 911 setNeedsValidityCheck();
895 } 912 }
896 913
897 setChecked(hasAttribute(checkedAttr)); 914 setChecked(hasAttribute(checkedAttr));
898 m_dirtyCheckedness = false; 915 m_dirtyCheckedness = false;
899 } 916 }
900 917
901 bool HTMLInputElement::isTextField() const { 918 bool HTMLInputElement::isTextField() const {
902 return m_inputType->isTextField(); 919 return m_inputType->isTextField();
903 } 920 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 m_isIndeterminate = sourceElement.m_isIndeterminate; 1003 m_isIndeterminate = sourceElement.m_isIndeterminate;
987 m_inputType->copyNonAttributeProperties(sourceElement); 1004 m_inputType->copyNonAttributeProperties(sourceElement);
988 1005
989 HTMLTextFormControlElement::copyNonAttributePropertiesFromElement(source); 1006 HTMLTextFormControlElement::copyNonAttributePropertiesFromElement(source);
990 1007
991 m_needsToUpdateViewValue = true; 1008 m_needsToUpdateViewValue = true;
992 m_inputTypeView->updateView(); 1009 m_inputTypeView->updateView();
993 } 1010 }
994 1011
995 String HTMLInputElement::value() const { 1012 String HTMLInputElement::value() const {
996 String value; 1013 switch (m_inputType->valueMode()) {
997 if (m_inputType->getTypeSpecificValue(value)) 1014 case ValueMode::kFilename: {
998 return value; 1015 String value;
999 1016 // TODO(tkent): The bool return value of getTypeSpecificValue() doesn't
1000 if (hasDirtyValue()) 1017 // make sense. FileInputType::getTypeSpecificValue() always returns true.
1001 return m_valueIfDirty; 1018 bool result = m_inputType->getTypeSpecificValue(value);
1002 1019 DCHECK(result);
1003 AtomicString valueString = fastGetAttribute(valueAttr); 1020 return value;
1004 value = sanitizeValue(valueString); 1021 }
1005 if (!value.isNull()) 1022 case ValueMode::kDefault:
1006 return value; 1023 return fastGetAttribute(valueAttr);
1007 1024 case ValueMode::kDefaultOn: {
1008 return m_inputType->fallbackValue(); 1025 AtomicString valueString = fastGetAttribute(valueAttr);
1026 return valueString.isNull() ? "on" : valueString;
1027 }
1028 case ValueMode::kValue:
1029 return m_valueIfDirty;
1030 }
1031 NOTREACHED();
1032 return emptyString();
1009 } 1033 }
1010 1034
1011 String HTMLInputElement::valueWithDefault() const { 1035 String HTMLInputElement::valueWithDefault() const {
1012 String value = this->value(); 1036 String value = this->value();
1013 if (!value.isNull()) 1037 if (!value.isNull())
1014 return value; 1038 return value;
1015 1039
1016 return m_inputType->defaultValue(); 1040 return m_inputType->defaultValue();
1017 } 1041 }
1018 1042
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 1101
1078 setLastChangeWasNotUserEdit(); 1102 setLastChangeWasNotUserEdit();
1079 m_needsToUpdateViewValue = true; 1103 m_needsToUpdateViewValue = true;
1080 // Prevent TextFieldInputType::setValue from using the suggested value. 1104 // Prevent TextFieldInputType::setValue from using the suggested value.
1081 m_suggestedValue = String(); 1105 m_suggestedValue = String();
1082 1106
1083 m_inputType->setValue(sanitizedValue, valueChanged, eventBehavior); 1107 m_inputType->setValue(sanitizedValue, valueChanged, eventBehavior);
1084 m_inputTypeView->didSetValue(sanitizedValue, valueChanged); 1108 m_inputTypeView->didSetValue(sanitizedValue, valueChanged);
1085 1109
1086 if (valueChanged && eventBehavior == DispatchNoEvent) 1110 if (valueChanged && eventBehavior == DispatchNoEvent)
1087 setTextAsOfLastFormControlChangeEvent( 1111 setTextAsOfLastFormControlChangeEvent(this->value());
1088 sanitizedValue.isNull() ? defaultValue() : sanitizedValue);
1089 1112
1090 if (!valueChanged) 1113 if (!valueChanged)
1091 return; 1114 return;
1092 1115
1093 notifyFormStateChanged(); 1116 notifyFormStateChanged();
1094 } 1117 }
1095 1118
1096 void HTMLInputElement::setNonAttributeValue(const String& sanitizedValue) { 1119 void HTMLInputElement::setNonAttributeValue(const String& sanitizedValue) {
1097 // This is a common code for ValueMode::kValue. 1120 // This is a common code for ValueMode::kValue.
1098 DCHECK_EQ(m_inputType->valueMode(), ValueMode::kValue); 1121 DCHECK_EQ(m_inputType->valueMode(), ValueMode::kValue);
1099 m_valueIfDirty = sanitizedValue; 1122 m_valueIfDirty = sanitizedValue;
1100 m_hasDirtyValue = !m_valueIfDirty.isNull(); 1123 m_hasDirtyValue = true;
1101 setNeedsValidityCheck(); 1124 setNeedsValidityCheck();
1102 if (m_inputType->isSteppable()) { 1125 if (m_inputType->isSteppable()) {
1103 pseudoStateChanged(CSSSelector::PseudoInRange); 1126 pseudoStateChanged(CSSSelector::PseudoInRange);
1104 pseudoStateChanged(CSSSelector::PseudoOutOfRange); 1127 pseudoStateChanged(CSSSelector::PseudoOutOfRange);
1105 } 1128 }
1106 if (document().focusedElement() == this) 1129 if (document().focusedElement() == this)
1107 document() 1130 document()
1108 .frameHost() 1131 .frameHost()
1109 ->chromeClient() 1132 ->chromeClient()
1110 .didUpdateTextOfFocusedElementByNonUserInput(*document().frame()); 1133 .didUpdateTextOfFocusedElementByNonUserInput(*document().frame());
1111 } 1134 }
1112 1135
1136 void HTMLInputElement::setNonDirtyValue(const String& newValue) {
1137 setValue(newValue);
1138 m_hasDirtyValue = false;
1139 }
1140
1113 bool HTMLInputElement::hasDirtyValue() const { 1141 bool HTMLInputElement::hasDirtyValue() const {
1114 DCHECK_EQ(!m_hasDirtyValue, m_valueIfDirty.isNull());
1115 return m_hasDirtyValue; 1142 return m_hasDirtyValue;
1116 } 1143 }
1117 1144
1118 void HTMLInputElement::updateView() { 1145 void HTMLInputElement::updateView() {
1119 m_inputTypeView->updateView(); 1146 m_inputTypeView->updateView();
1120 } 1147 }
1121 1148
1122 double HTMLInputElement::valueAsDate(bool& isNull) const { 1149 double HTMLInputElement::valueAsDate(bool& isNull) const {
1123 double date = m_inputType->valueAsDate(); 1150 double date = m_inputType->valueAsDate();
1124 isNull = !std::isfinite(date); 1151 isNull = !std::isfinite(date);
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 1480
1454 void HTMLInputElement::setCanReceiveDroppedFiles(bool canReceiveDroppedFiles) { 1481 void HTMLInputElement::setCanReceiveDroppedFiles(bool canReceiveDroppedFiles) {
1455 if (!!m_canReceiveDroppedFiles == canReceiveDroppedFiles) 1482 if (!!m_canReceiveDroppedFiles == canReceiveDroppedFiles)
1456 return; 1483 return;
1457 m_canReceiveDroppedFiles = canReceiveDroppedFiles; 1484 m_canReceiveDroppedFiles = canReceiveDroppedFiles;
1458 if (layoutObject()) 1485 if (layoutObject())
1459 layoutObject()->updateFromElement(); 1486 layoutObject()->updateFromElement();
1460 } 1487 }
1461 1488
1462 String HTMLInputElement::sanitizeValue(const String& proposedValue) const { 1489 String HTMLInputElement::sanitizeValue(const String& proposedValue) const {
1463 if (proposedValue.isNull())
1464 return proposedValue;
1465 return m_inputType->sanitizeValue(proposedValue); 1490 return m_inputType->sanitizeValue(proposedValue);
1466 } 1491 }
1467 1492
1468 String HTMLInputElement::localizeValue(const String& proposedValue) const { 1493 String HTMLInputElement::localizeValue(const String& proposedValue) const {
1469 if (proposedValue.isNull()) 1494 if (proposedValue.isNull())
1470 return proposedValue; 1495 return proposedValue;
1471 return m_inputType->localizeValue(proposedValue); 1496 return m_inputType->localizeValue(proposedValue);
1472 } 1497 }
1473 1498
1474 bool HTMLInputElement::isInRange() const { 1499 bool HTMLInputElement::isInRange() const {
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after
1933 1958
1934 bool HTMLInputElement::hasFallbackContent() const { 1959 bool HTMLInputElement::hasFallbackContent() const {
1935 return m_inputTypeView->hasFallbackContent(); 1960 return m_inputTypeView->hasFallbackContent();
1936 } 1961 }
1937 1962
1938 void HTMLInputElement::setFilesFromPaths(const Vector<String>& paths) { 1963 void HTMLInputElement::setFilesFromPaths(const Vector<String>& paths) {
1939 return m_inputType->setFilesFromPaths(paths); 1964 return m_inputType->setFilesFromPaths(paths);
1940 } 1965 }
1941 1966
1942 } // namespace blink 1967 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLInputElement.h ('k') | third_party/WebKit/Source/core/html/forms/InputType.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698