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