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_DateTimeInputTypes_h__
8 #define mozilla_dom_DateTimeInputTypes_h__
9 
10 #include "mozilla/dom/InputType.h"
11 
12 namespace mozilla {
13 namespace dom {
14 
15 class DateTimeInputTypeBase : public InputType {
16  public:
17   ~DateTimeInputTypeBase() override = default;
18 
19   bool IsValueMissing() const override;
20   bool IsRangeOverflow() const override;
21   bool IsRangeUnderflow() const override;
22   bool HasStepMismatch(bool aUseZeroIfValueNaN) const override;
23   bool HasBadInput() const override;
24 
25   nsresult GetRangeOverflowMessage(nsAString& aMessage) override;
26   nsresult GetRangeUnderflowMessage(nsAString& aMessage) override;
27 
28   nsresult MinMaxStepAttrChanged() override;
29 
30  protected:
DateTimeInputTypeBase(HTMLInputElement * aInputElement)31   explicit DateTimeInputTypeBase(HTMLInputElement* aInputElement)
32       : InputType(aInputElement) {}
33 
34   bool IsMutable() const override;
35 
36   /**
37    * This method converts aValue (milliseconds within a day) to hours, minutes,
38    * seconds and milliseconds.
39    */
40   bool GetTimeFromMs(double aValue, uint16_t* aHours, uint16_t* aMinutes,
41                      uint16_t* aSeconds, uint16_t* aMilliseconds) const;
42 
43   // Minimum year limited by HTML standard, year >= 1.
44   static const double kMinimumYear;
45   // Maximum year limited by ECMAScript date object range, year <= 275760.
46   static const double kMaximumYear;
47   // Maximum valid month is 275760-09.
48   static const double kMaximumMonthInMaximumYear;
49   // Maximum valid week is 275760-W37.
50   static const double kMaximumWeekInMaximumYear;
51   // Milliseconds in a day.
52   static const double kMsPerDay;
53 };
54 
55 // input type=date
56 class DateInputType : public DateTimeInputTypeBase {
57  public:
Create(HTMLInputElement * aInputElement,void * aMemory)58   static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) {
59     return new (aMemory) DateInputType(aInputElement);
60   }
61 
62   // Currently, for input date and time, only date can have an invalid value, as
63   // we forbid or autocorrect values that are not in the valid range for time.
64   // For example, in 12hr format, if user enters '2' in the hour field, it will
65   // be treated as '02' and automatically advance to the next field.
66   nsresult GetBadInputMessage(nsAString& aMessage) override;
67 
68   bool ConvertStringToNumber(nsAString& aValue,
69                              Decimal& aResultValue) const override;
70   bool ConvertNumberToString(Decimal aValue,
71                              nsAString& aResultString) const override;
72 
73  private:
DateInputType(HTMLInputElement * aInputElement)74   explicit DateInputType(HTMLInputElement* aInputElement)
75       : DateTimeInputTypeBase(aInputElement) {}
76 };
77 
78 // input type=time
79 class TimeInputType : public DateTimeInputTypeBase {
80  public:
Create(HTMLInputElement * aInputElement,void * aMemory)81   static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) {
82     return new (aMemory) TimeInputType(aInputElement);
83   }
84 
85   bool ConvertStringToNumber(nsAString& aValue,
86                              Decimal& aResultValue) const override;
87   bool ConvertNumberToString(Decimal aValue,
88                              nsAString& aResultString) const override;
89   bool IsRangeOverflow() const override;
90   bool IsRangeUnderflow() const override;
91   nsresult GetRangeOverflowMessage(nsAString& aMessage) override;
92   nsresult GetRangeUnderflowMessage(nsAString& aMessage) override;
93 
94  private:
TimeInputType(HTMLInputElement * aInputElement)95   explicit TimeInputType(HTMLInputElement* aInputElement)
96       : DateTimeInputTypeBase(aInputElement) {}
97 
98   // https://html.spec.whatwg.org/multipage/input.html#has-a-reversed-range
99   bool HasReversedRange() const;
100   bool IsReversedRangeUnderflowAndOverflow() const;
101   nsresult GetReversedRangeUnderflowAndOverflowMessage(nsAString& aMessage);
102 };
103 
104 // input type=week
105 class WeekInputType : public DateTimeInputTypeBase {
106  public:
Create(HTMLInputElement * aInputElement,void * aMemory)107   static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) {
108     return new (aMemory) WeekInputType(aInputElement);
109   }
110 
111   bool ConvertStringToNumber(nsAString& aValue,
112                              Decimal& aResultValue) const override;
113   bool ConvertNumberToString(Decimal aValue,
114                              nsAString& aResultString) const override;
115 
116  private:
WeekInputType(HTMLInputElement * aInputElement)117   explicit WeekInputType(HTMLInputElement* aInputElement)
118       : DateTimeInputTypeBase(aInputElement) {}
119 };
120 
121 // input type=month
122 class MonthInputType : public DateTimeInputTypeBase {
123  public:
Create(HTMLInputElement * aInputElement,void * aMemory)124   static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) {
125     return new (aMemory) MonthInputType(aInputElement);
126   }
127 
128   bool ConvertStringToNumber(nsAString& aValue,
129                              Decimal& aResultValue) const override;
130   bool ConvertNumberToString(Decimal aValue,
131                              nsAString& aResultString) const override;
132 
133  private:
MonthInputType(HTMLInputElement * aInputElement)134   explicit MonthInputType(HTMLInputElement* aInputElement)
135       : DateTimeInputTypeBase(aInputElement) {}
136 };
137 
138 // input type=datetime-local
139 class DateTimeLocalInputType : public DateTimeInputTypeBase {
140  public:
Create(HTMLInputElement * aInputElement,void * aMemory)141   static InputType* Create(HTMLInputElement* aInputElement, void* aMemory) {
142     return new (aMemory) DateTimeLocalInputType(aInputElement);
143   }
144 
145   bool ConvertStringToNumber(nsAString& aValue,
146                              Decimal& aResultValue) const override;
147   bool ConvertNumberToString(Decimal aValue,
148                              nsAString& aResultString) const override;
149 
150  private:
DateTimeLocalInputType(HTMLInputElement * aInputElement)151   explicit DateTimeLocalInputType(HTMLInputElement* aInputElement)
152       : DateTimeInputTypeBase(aInputElement) {}
153 };
154 
155 }  // namespace dom
156 }  // namespace mozilla
157 
158 #endif /* mozilla_dom_DateTimeInputTypes_h__ */
159