InputType.h (8444B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_InputType_h__ 8 #define mozilla_dom_InputType_h__ 9 10 #include <stdint.h> 11 12 #include "mozilla/Decimal.h" 13 #include "mozilla/Maybe.h" 14 #include "mozilla/TextControlState.h" 15 #include "mozilla/UniquePtr.h" 16 #include "nsError.h" 17 #include "nsIConstraintValidation.h" 18 #include "nsString.h" 19 20 // This must come outside of any namespace, or else it won't overload with the 21 // double based version in nsMathUtils.h 22 inline mozilla::Decimal NS_floorModulo(mozilla::Decimal x, mozilla::Decimal y) { 23 return (x - y * (x / y).floor()); 24 } 25 26 class nsIFrame; 27 28 namespace mozilla::dom { 29 class HTMLInputElement; 30 31 /** 32 * A common superclass for different types of a HTMLInputElement. 33 */ 34 class InputType { 35 public: 36 using ValueSetterOption = TextControlState::ValueSetterOption; 37 using ValueSetterOptions = TextControlState::ValueSetterOptions; 38 39 // Custom deleter for UniquePtr<InputType> to avoid freeing memory 40 // pre-allocated for InputType, but we still need to call the destructor 41 // explicitly. 42 struct DoNotDelete { 43 void operator()(InputType* p) { p->~InputType(); } 44 }; 45 46 static UniquePtr<InputType, DoNotDelete> Create( 47 HTMLInputElement* aInputElement, FormControlType, void* aMemory); 48 49 virtual ~InputType() = default; 50 51 // Float value returned by GetStep() when the step attribute is set to 'any'. 52 static constexpr Decimal kStepAny = Decimal(0_d); 53 54 /** 55 * Drop the reference to the input element. 56 */ 57 void DropReference(); 58 59 virtual bool MinAndMaxLengthApply() const { return false; } 60 virtual bool IsTooLong() const; 61 virtual bool IsTooShort() const; 62 virtual bool IsValueMissing() const; 63 virtual bool HasTypeMismatch() const; 64 // May return Nothing() if the JS engine failed to evaluate the regex. 65 virtual Maybe<bool> HasPatternMismatch() const; 66 virtual bool IsRangeOverflow() const; 67 virtual bool IsRangeUnderflow() const; 68 virtual bool HasStepMismatch() const; 69 virtual bool HasBadInput() const; 70 71 nsresult GetValidationMessage( 72 nsAString& aValidationMessage, 73 nsIConstraintValidation::ValidityStateType aType); 74 virtual nsresult GetValueMissingMessage(nsAString& aMessage); 75 virtual nsresult GetTypeMismatchMessage(nsAString& aMessage); 76 virtual nsresult GetRangeOverflowMessage(nsAString& aMessage); 77 virtual nsresult GetRangeUnderflowMessage(nsAString& aMessage); 78 virtual nsresult GetBadInputMessage(nsAString& aMessage); 79 80 MOZ_CAN_RUN_SCRIPT virtual void MinMaxStepAttrChanged() {} 81 82 /** 83 * Convert a string to a Decimal number in a type specific way, 84 * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#concept-input-value-string-number 85 * ie parse a date string to a timestamp if type=date, 86 * or parse a number string to its value if type=number. 87 * @param aValue the string to be parsed. 88 */ 89 struct StringToNumberResult { 90 // The result decimal. Successfully parsed if it's finite. 91 Decimal mResult = Decimal::nan(); 92 // Whether the result required reading locale-dependent data (for input 93 // type=number), or the value parses using the regular HTML rules. 94 bool mLocalized = false; 95 }; 96 virtual StringToNumberResult ConvertStringToNumber( 97 const nsAString& aValue) const; 98 99 enum class Localized : bool { No = false, Yes }; 100 /** 101 * Convert a Decimal to a string in a type specific way, ie convert a 102 * timestamp to a date string if type=date or append the number string 103 * representing the value if type=number. 104 * 105 * @param aValue the Decimal to be converted 106 * @param Localized whether the value should be localized. 107 * @param aResultString [out] the string representing the Decimal 108 * @return whether the function succeeded, it will fail if the current input's 109 * type is not supported or the number can't be converted to a string 110 * as expected by the type. 111 */ 112 virtual bool ConvertNumberToString(Decimal aValue, Localized, 113 nsAString& aResultString) const; 114 115 protected: 116 explicit InputType(HTMLInputElement* aInputElement) 117 : mInputElement(aInputElement) {} 118 119 /** 120 * Get the mutable state of the element. 121 * When the element isn't mutable (immutable), the value or checkedness 122 * should not be changed by the user. 123 * 124 * See: 125 * https://html.spec.whatwg.org/multipage/forms.html#the-input-element:concept-fe-mutable 126 */ 127 virtual bool IsMutable() const; 128 129 /** 130 * Returns whether the input element's current value is the empty string. 131 * This only makes sense for some input types; does NOT make sense for file 132 * inputs. 133 * 134 * @return whether the input element's current value is the empty string. 135 */ 136 bool IsValueEmpty() const; 137 138 // A getter for callers that know we're not dealing with a file input, so they 139 // don't have to think about the caller type. 140 void GetNonFileValueInternal(nsAString& aValue) const; 141 142 /** 143 * Setting the input element's value. 144 * 145 * @param aValue String to set. 146 * @param aOptions See TextControlState::ValueSetterOption. 147 */ 148 MOZ_CAN_RUN_SCRIPT nsresult 149 SetValueInternal(const nsAString& aValue, const ValueSetterOptions& aOptions); 150 151 /** 152 * Get the primary frame for the input element. 153 */ 154 nsIFrame* GetPrimaryFrame() const; 155 156 /** 157 * Parse a date string of the form yyyy-mm-dd 158 * 159 * @param aValue the string to be parsed. 160 * @return the date in aYear, aMonth, aDay. 161 * @return whether the parsing was successful. 162 */ 163 bool ParseDate(const nsAString& aValue, uint32_t* aYear, uint32_t* aMonth, 164 uint32_t* aDay) const; 165 166 /** 167 * Returns the time expressed in milliseconds of |aValue| being parsed as a 168 * time following the HTML specifications: 169 * https://html.spec.whatwg.org/multipage/infrastructure.html#parse-a-time-string 170 * 171 * Note: |aResult| can be null. 172 * 173 * @param aValue the string to be parsed. 174 * @param aResult the time expressed in milliseconds representing the time 175 * [out] 176 * @return whether the parsing was successful. 177 */ 178 bool ParseTime(const nsAString& aValue, uint32_t* aResult) const; 179 180 /** 181 * Parse a month string of the form yyyy-mm 182 * 183 * @param the string to be parsed. 184 * @return the year and month in aYear and aMonth. 185 * @return whether the parsing was successful. 186 */ 187 bool ParseMonth(const nsAString& aValue, uint32_t* aYear, 188 uint32_t* aMonth) const; 189 190 /** 191 * Parse a week string of the form yyyy-Www 192 * 193 * @param the string to be parsed. 194 * @return the year and week in aYear and aWeek. 195 * @return whether the parsing was successful. 196 */ 197 bool ParseWeek(const nsAString& aValue, uint32_t* aYear, 198 uint32_t* aWeek) const; 199 200 /** 201 * Parse a datetime-local string of the form yyyy-mm-ddThh:mm[:ss.s] or 202 * yyyy-mm-dd hh:mm[:ss.s], where fractions of seconds can be 1 to 3 digits. 203 * 204 * @param the string to be parsed. 205 * @return the date in aYear, aMonth, aDay and time expressed in milliseconds 206 * in aTime. 207 * @return whether the parsing was successful. 208 */ 209 bool ParseDateTimeLocal(const nsAString& aValue, uint32_t* aYear, 210 uint32_t* aMonth, uint32_t* aDay, 211 uint32_t* aTime) const; 212 213 /** 214 * This methods returns the number of months between January 1970 and the 215 * given year and month. 216 */ 217 int32_t MonthsSinceJan1970(uint32_t aYear, uint32_t aMonth) const; 218 219 /** 220 * This methods returns the number of days since epoch for a given year and 221 * week. 222 */ 223 double DaysSinceEpochFromWeek(uint32_t aYear, uint32_t aWeek) const; 224 225 /** 226 * This methods returns the day of the week given a date. If @isoWeek is true, 227 * 7=Sunday, otherwise, 0=Sunday. 228 */ 229 uint32_t DayOfWeek(uint32_t aYear, uint32_t aMonth, uint32_t aDay, 230 bool isoWeek) const; 231 232 /** 233 * This methods returns the maximum number of week in a given year, the 234 * result is either 52 or 53. 235 */ 236 uint32_t MaximumWeekInYear(uint32_t aYear) const; 237 238 HTMLInputElement* mInputElement; 239 }; 240 241 } // namespace mozilla::dom 242 243 #endif /* mozilla_dom_InputType_h__ */