@materializecss/materialize 2.0.1-alpha → 2.0.3-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/Gruntfile.js +5 -2
  2. package/dist/css/materialize.css +1510 -288
  3. package/dist/css/materialize.min.css +2 -2
  4. package/dist/js/materialize.js +2782 -2688
  5. package/dist/js/materialize.min.js +2 -8967
  6. package/dist/js/materialize.min.js.map +1 -1
  7. package/dist/src/autocomplete.d.ts +143 -0
  8. package/dist/src/autocomplete.d.ts.map +1 -0
  9. package/dist/src/bounding.d.ts +7 -0
  10. package/dist/src/bounding.d.ts.map +1 -0
  11. package/dist/src/buttons.d.ts +65 -0
  12. package/dist/src/buttons.d.ts.map +1 -0
  13. package/dist/src/cards.d.ts +4 -0
  14. package/dist/src/cards.d.ts.map +1 -0
  15. package/dist/src/carousel.d.ts +131 -0
  16. package/dist/src/carousel.d.ts.map +1 -0
  17. package/dist/src/characterCounter.d.ts +37 -0
  18. package/dist/src/characterCounter.d.ts.map +1 -0
  19. package/dist/src/chips.d.ts +131 -0
  20. package/dist/src/chips.d.ts.map +1 -0
  21. package/dist/src/collapsible.d.ts +74 -0
  22. package/dist/src/collapsible.d.ts.map +1 -0
  23. package/dist/src/component.d.ts +74 -0
  24. package/dist/src/component.d.ts.map +1 -0
  25. package/dist/src/datepicker.d.ts +248 -0
  26. package/dist/src/datepicker.d.ts.map +1 -0
  27. package/dist/src/dropdown.d.ts +148 -0
  28. package/dist/src/dropdown.d.ts.map +1 -0
  29. package/dist/src/edges.d.ts +7 -0
  30. package/dist/src/edges.d.ts.map +1 -0
  31. package/dist/src/forms.d.ts +12 -0
  32. package/dist/src/forms.d.ts.map +1 -0
  33. package/dist/src/global.d.ts +60 -0
  34. package/dist/src/global.d.ts.map +1 -0
  35. package/dist/src/index.d.ts +27 -0
  36. package/dist/src/index.d.ts.map +1 -0
  37. package/dist/src/materialbox.d.ts +92 -0
  38. package/dist/src/materialbox.d.ts.map +1 -0
  39. package/dist/src/modal.d.ts +119 -0
  40. package/dist/src/modal.d.ts.map +1 -0
  41. package/dist/src/parallax.d.ts +40 -0
  42. package/dist/src/parallax.d.ts.map +1 -0
  43. package/dist/src/pushpin.d.ts +52 -0
  44. package/dist/src/pushpin.d.ts.map +1 -0
  45. package/dist/src/range.d.ts +41 -0
  46. package/dist/src/range.d.ts.map +1 -0
  47. package/dist/src/scrollspy.d.ts +62 -0
  48. package/dist/src/scrollspy.d.ts.map +1 -0
  49. package/dist/src/select.d.ts +77 -0
  50. package/dist/src/select.d.ts.map +1 -0
  51. package/dist/src/sidenav.d.ts +122 -0
  52. package/dist/src/sidenav.d.ts.map +1 -0
  53. package/dist/src/slider.d.ts +103 -0
  54. package/dist/src/slider.d.ts.map +1 -0
  55. package/dist/src/tabs.d.ts +80 -0
  56. package/dist/src/tabs.d.ts.map +1 -0
  57. package/dist/src/tapTarget.d.ts +59 -0
  58. package/dist/src/tapTarget.d.ts.map +1 -0
  59. package/dist/src/timepicker.d.ts +208 -0
  60. package/dist/src/timepicker.d.ts.map +1 -0
  61. package/dist/src/toasts.d.ts +90 -0
  62. package/dist/src/toasts.d.ts.map +1 -0
  63. package/dist/src/tooltip.d.ts +112 -0
  64. package/dist/src/tooltip.d.ts.map +1 -0
  65. package/dist/src/utils.d.ts +97 -0
  66. package/dist/src/utils.d.ts.map +1 -0
  67. package/dist/src/waves.d.ts +16 -0
  68. package/dist/src/waves.d.ts.map +1 -0
  69. package/package.json +4 -1
  70. package/sass/components/_cards.scss +1 -1
  71. package/sass/components/_collapsible.scss +0 -41
  72. package/sass/components/_global.scss +53 -2
  73. package/sass/components/_grid.scss +28 -47
  74. package/sass/components/_icons-material-design.scss +2 -1
  75. package/sass/components/_navbar.scss +30 -27
  76. package/sass/components/_pulse.scss +1 -0
  77. package/sass/components/_sidenav.scss +63 -45
  78. package/sass/components/_theme_variables.scss +29 -49
  79. package/sass/components/_typography.scss +2 -2
  80. package/sass/components/_variables.scss +2 -0
  81. package/sass/components/colors.module.scss +180 -0
  82. package/sass/components/forms/_input-fields.scss +4 -10
  83. package/sass/components/theme.dark.module.scss +32 -0
  84. package/sass/components/theme.light.module.scss +32 -0
  85. package/sass/components/tokens.module.scss +272 -0
  86. package/sass/components/typography.module.scss +150 -0
  87. package/sass/materialize.scss +6 -4
  88. package/src/autocomplete.ts +188 -94
  89. package/src/buttons.ts +225 -260
  90. package/src/cards.ts +5 -6
  91. package/src/carousel.ts +611 -542
  92. package/src/characterCounter.ts +50 -21
  93. package/src/chips.ts +152 -63
  94. package/src/collapsible.ts +97 -32
  95. package/src/component.ts +99 -10
  96. package/src/datepicker.ts +905 -726
  97. package/src/dropdown.ts +573 -484
  98. package/src/edges.ts +4 -4
  99. package/src/forms.ts +36 -24
  100. package/src/global.ts +57 -328
  101. package/src/index.ts +26 -0
  102. package/src/materialbox.ts +354 -298
  103. package/src/modal.ts +296 -211
  104. package/src/parallax.ts +129 -105
  105. package/src/pushpin.ts +148 -103
  106. package/src/range.ts +166 -150
  107. package/src/scrollspy.ts +214 -174
  108. package/src/select.ts +434 -398
  109. package/src/sidenav.ts +447 -381
  110. package/src/slider.ts +421 -362
  111. package/src/tabs.ts +276 -222
  112. package/src/tapTarget.ts +246 -213
  113. package/src/timepicker.ts +738 -614
  114. package/src/toasts.ts +254 -230
  115. package/src/tooltip.ts +315 -252
  116. package/src/utils.ts +271 -0
  117. package/src/waves.ts +10 -10
package/src/timepicker.ts CHANGED
@@ -1,8 +1,103 @@
1
- import { Component } from "./component";
2
- import { M } from "./global";
3
1
  import { Modal } from "./modal";
4
-
5
- let _defaults = {
2
+ import { Utils } from "./utils";
3
+ import { Component, BaseOptions, InitElements, MElement, I18nOptions } from "./component";
4
+
5
+ export type Views = "hours" | "minutes";
6
+
7
+ export interface TimepickerOptions extends BaseOptions {
8
+ /**
9
+ * Dial radius.
10
+ * @default 135
11
+ */
12
+ dialRadius: number;
13
+ /**
14
+ * Outer radius.
15
+ * @default 105
16
+ */
17
+ outerRadius: number;
18
+ /**
19
+ * Inner radius.
20
+ * @default 70
21
+ */
22
+ innerRadius: number;
23
+ /**
24
+ * Tick radius.
25
+ * @default 20
26
+ */
27
+ tickRadius: number;
28
+ /**
29
+ * Duration of the transition from/to the hours/minutes view.
30
+ * @default 350
31
+ */
32
+ duration: number;
33
+ /**
34
+ * Specify a DOM element OR selector for a DOM element to render
35
+ * the time picker in, by default it will be placed before the input.
36
+ * @default null
37
+ */
38
+ container: HTMLElement | string | null;
39
+ /**
40
+ * Show the clear button in the Timepicker.
41
+ * @default false
42
+ */
43
+ showClearBtn: boolean;
44
+ /**
45
+ * Default time to set on the timepicker 'now' or '13:14'.
46
+ * @default 'now';
47
+ */
48
+ defaultTime: string;
49
+ /**
50
+ * Millisecond offset from the defaultTime.
51
+ * @default 0
52
+ */
53
+ fromNow: number;
54
+ /**
55
+ * Internationalization options.
56
+ */
57
+ i18n: Partial<I18nOptions>;
58
+ /**
59
+ * Automatically close picker when minute is selected.
60
+ * @default false;
61
+ */
62
+ autoClose: boolean;
63
+ /**
64
+ * Use 12 hour AM/PM clock instead of 24 hour clock.
65
+ * @default true
66
+ */
67
+ twelveHour: boolean;
68
+ /**
69
+ * Vibrate device when dragging clock hand.
70
+ * @default true
71
+ */
72
+ vibrate: boolean;
73
+ /**
74
+ * Callback function called before modal is opened.
75
+ * @default null
76
+ */
77
+ onOpenStart: (el: HTMLElement) => void;
78
+ /**
79
+ * Callback function called after modal is opened.
80
+ * @default null
81
+ */
82
+ onOpenEnd: (el: HTMLElement) => void;
83
+ /**
84
+ * Callback function called before modal is closed.
85
+ * @default null
86
+ */
87
+ onCloseStart: (el: HTMLElement) => void;
88
+ /**
89
+ * Callback function called after modal is closed.
90
+ * @default null
91
+ */
92
+ onCloseEnd: (el: HTMLElement) => void;
93
+ /**
94
+ * Callback function when a time is selected.
95
+ * @default null
96
+ */
97
+ onSelect: (hour: number, minute: number) => void;
98
+ }
99
+
100
+ let _defaults: TimepickerOptions = {
6
101
  dialRadius: 135,
7
102
  outerRadius: 105,
8
103
  innerRadius: 70,
@@ -34,675 +129,704 @@ type Point = {
34
129
  y: number
35
130
  };
36
131
 
37
- export class Timepicker extends Component {
38
- el: HTMLInputElement;
39
- id: string;
40
- modal: Modal;
41
- modalEl: HTMLElement;
42
- private _handleInputKeydownBound: any;
43
- private _handleInputClickBound: any;
44
- private _handleClockClickStartBound: any;
45
- private _handleDocumentClickMoveBound: any;
46
- private _handleDocumentClickEndBound: any;
47
- private _inputFromTextFieldBound: any;
48
- plate: any;
49
- digitalClock: any;
50
- inputHours: HTMLInputElement;
51
- inputMinutes: HTMLInputElement;
52
- x0: number;
53
- y0: number;
54
- moved: boolean;
55
- dx: number;
56
- dy: number;
57
- currentView: string;
58
- hand: any;
59
- minutesView: HTMLElement;
60
- hours: any;
61
- minutes: any;
62
- time: string;
63
- amOrPm: any;
64
- static _template: any;
65
- isOpen: boolean;
66
- vibrate: string;
67
- _canvas: HTMLElement;
68
- hoursView: any;
69
- spanAmPm: HTMLSpanElement;
70
- footer: HTMLElement;
71
- private _amBtn: HTMLElement;
72
- private _pmBtn: HTMLElement;
73
- bg: Element;
74
- bearing: Element;
75
- g: Element;
76
- toggleViewTimer: string | number | NodeJS.Timeout;
77
- canvas: any;
78
- vibrateTimer: any;
79
-
80
- constructor(el, options) {
81
- super(Timepicker, el, options);
82
- (this.el as any).M_Timepicker = this;
83
- this.options = {...Timepicker.defaults, ...options};
84
- this.id = M.guid();
85
- this._insertHTMLIntoDOM();
86
- this._setupModal();
87
- this._setupVariables();
88
- this._setupEventHandlers();
89
- this._clockSetup();
90
- this._pickerSetup();
91
- }
92
-
93
- static get defaults() {
94
- return _defaults;
95
- }
96
-
97
- static init(els, options) {
98
- return super.init(this, els, options);
99
- }
100
-
101
- static _addLeadingZero(num) {
102
- return (num < 10 ? '0' : '') + num;
103
- }
104
-
105
- static _createSVGEl(name) {
106
- let svgNS = 'http://www.w3.org/2000/svg';
107
- return document.createElementNS(svgNS, name);
108
- }
109
-
110
- static _Pos(e): Point {
111
- if (e.targetTouches && e.targetTouches.length >= 1) {
112
- return { x: e.targetTouches[0].clientX, y: e.targetTouches[0].clientY };
113
- }
114
- // mouse event
115
- return { x: e.clientX, y: e.clientY };
116
- }
132
+ export class Timepicker extends Component<TimepickerOptions> {
133
+ declare el: HTMLInputElement;
134
+ id: string;
135
+ modal: Modal;
136
+ modalEl: HTMLElement;
137
+ plate: any;
138
+ digitalClock: any;
139
+ inputHours: HTMLInputElement;
140
+ inputMinutes: HTMLInputElement;
141
+ x0: number;
142
+ y0: number;
143
+ moved: boolean;
144
+ dx: number;
145
+ dy: number;
146
+ /**
147
+ * Current view on the timepicker.
148
+ * @default 'hours'
149
+ */
150
+ currentView: Views;
151
+ hand: any;
152
+ minutesView: HTMLElement;
153
+ hours: any;
154
+ minutes: any;
155
+ /** The selected time. */
156
+ time: string;
157
+ /**
158
+ * If the time is AM or PM on twelve-hour clock.
159
+ * @default 'PM'
160
+ */
161
+ amOrPm: "AM" | "PM";
162
+ static _template: any;
163
+ /** If the picker is open. */
164
+ isOpen: boolean;
165
+ /** Vibrate device when dragging clock hand. */
166
+ vibrate: "vibrate" | "webkitVibrate" | null;
167
+ _canvas: HTMLElement;
168
+ hoursView: any;
169
+ spanAmPm: HTMLSpanElement;
170
+ footer: HTMLElement;
171
+ private _amBtn: HTMLElement;
172
+ private _pmBtn: HTMLElement;
173
+ bg: Element;
174
+ bearing: Element;
175
+ g: Element;
176
+ toggleViewTimer: string | number | NodeJS.Timeout;
177
+ canvas: any;
178
+ vibrateTimer: any;
179
+
180
+ constructor(el: HTMLInputElement, options: Partial<TimepickerOptions>) {
181
+ super(el, options, Timepicker);
182
+ (this.el as any).M_Timepicker = this;
183
+
184
+ this.options = {
185
+ ...Timepicker.defaults,
186
+ ...options
187
+ };
188
+
189
+ this.id = Utils.guid();
190
+ this._insertHTMLIntoDOM();
191
+ this._setupModal();
192
+ this._setupVariables();
193
+ this._setupEventHandlers();
194
+ this._clockSetup();
195
+ this._pickerSetup();
196
+ }
117
197
 
118
- static getInstance(el) {
119
- const domElem = !!el.jquery ? el[0] : el;
120
- return domElem.M_Timepicker;
121
- }
198
+ static get defaults(): TimepickerOptions {
199
+ return _defaults;
200
+ }
122
201
 
123
- destroy() {
124
- this._removeEventHandlers();
125
- this.modal.destroy();
126
- this.modalEl.remove();
127
- (this.el as any).M_Timepicker = undefined;
128
- }
202
+ /**
203
+ * Initializes instance of Timepicker.
204
+ * @param el HTML element.
205
+ * @param options Component options.
206
+ */
207
+ static init(el: HTMLInputElement, options?: Partial<TimepickerOptions>): Timepicker;
208
+ /**
209
+ * Initializes instances of Timepicker.
210
+ * @param els HTML elements.
211
+ * @param options Component options.
212
+ */
213
+ static init(els: InitElements<HTMLInputElement | MElement>, options?: Partial<TimepickerOptions>): Timepicker[];
214
+ /**
215
+ * Initializes instances of Timepicker.
216
+ * @param els HTML elements.
217
+ * @param options Component options.
218
+ */
219
+ static init(els: HTMLInputElement | InitElements<HTMLInputElement | MElement>, options: Partial<TimepickerOptions> = {}): Timepicker | Timepicker[] {
220
+ return super.init(els, options, Timepicker);
221
+ }
129
222
 
130
- _setupEventHandlers() {
131
- this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
132
- this._handleInputClickBound = this._handleInputClick.bind(this);
133
- this._handleClockClickStartBound = this._handleClockClickStart.bind(this);
134
- this._handleDocumentClickMoveBound = this._handleDocumentClickMove.bind(this);
135
- this._handleDocumentClickEndBound = this._handleDocumentClickEnd.bind(this);
136
- this._inputFromTextFieldBound = this._handleTimeInputEnterKey.bind(this);
137
- this.el.addEventListener('click', this._handleInputClickBound);
138
- this.el.addEventListener('keydown', this._handleInputKeydownBound);
139
- this.plate.addEventListener('mousedown', this._handleClockClickStartBound);
140
- this.plate.addEventListener('touchstart', this._handleClockClickStartBound);
141
- this.digitalClock.addEventListener('keyup', this._inputFromTextFieldBound);
142
- this.inputHours.addEventListener('click', this.showView.bind(this, 'hours'));
143
- this.inputMinutes.addEventListener('click', this.showView.bind(this, 'minutes'));
144
- }
223
+ static _addLeadingZero(num: number) {
224
+ return (num < 10 ? '0' : '') + num;
225
+ }
145
226
 
146
- _removeEventHandlers() {
147
- this.el.removeEventListener('click', this._handleInputClickBound);
148
- this.el.removeEventListener('keydown', this._handleInputKeydownBound);
149
- }
227
+ static _createSVGEl(name: string) {
228
+ let svgNS = 'http://www.w3.org/2000/svg';
229
+ return document.createElementNS(svgNS, name);
230
+ }
150
231
 
151
- _handleInputClick() {
152
- this.open();
232
+ static _Pos(e: TouchEvent | MouseEvent): Point {
233
+ if (e.type.startsWith("touch") && (e as TouchEvent).targetTouches.length >= 1) {
234
+ return { x: (e as TouchEvent).targetTouches[0].clientX, y: (e as TouchEvent).targetTouches[0].clientY };
153
235
  }
236
+ // mouse event
237
+ return { x: (e as MouseEvent).clientX, y: (e as MouseEvent).clientY };
238
+ }
154
239
 
155
- _handleInputKeydown(e) {
156
- if (e.which === M.keys.ENTER) {
157
- e.preventDefault();
158
- this.open();
159
- }
160
- }
240
+ static getInstance(el: HTMLElement): Timepicker {
241
+ return (el as any).M_Timepicker;
242
+ }
161
243
 
162
- _handleTimeInputEnterKey(e) {
163
- if (e.which === M.keys.ENTER) {
164
- e.preventDefault();
165
- this._inputFromTextField();
166
- }
167
- }
244
+ destroy() {
245
+ this._removeEventHandlers();
246
+ this.modal.destroy();
247
+ this.modalEl.remove();
248
+ (this.el as any).M_Timepicker = undefined;
249
+ }
168
250
 
169
- _handleClockClickStart(e) {
170
- e.preventDefault();
171
- let clockPlateBR = this.plate.getBoundingClientRect();
172
- let offset = { x: clockPlateBR.left, y: clockPlateBR.top };
173
-
174
- this.x0 = offset.x + this.options.dialRadius;
175
- this.y0 = offset.y + this.options.dialRadius;
176
- this.moved = false;
177
- let clickPos = Timepicker._Pos(e);
178
- this.dx = clickPos.x - this.x0;
179
- this.dy = clickPos.y - this.y0;
180
-
181
- // Set clock hands
182
- this.setHand(this.dx, this.dy, false);
183
- // Mousemove on document
184
- document.addEventListener('mousemove', this._handleDocumentClickMoveBound);
185
- document.addEventListener('touchmove', this._handleDocumentClickMoveBound);
186
- // Mouseup on document
187
- document.addEventListener('mouseup', this._handleDocumentClickEndBound);
188
- document.addEventListener('touchend', this._handleDocumentClickEndBound);
189
- }
190
-
191
- _handleDocumentClickMove(e) {
251
+ _setupEventHandlers() {
252
+ this.el.addEventListener('click', this._handleInputClick);
253
+ this.el.addEventListener('keydown', this._handleInputKeydown);
254
+ this.plate.addEventListener('mousedown', this._handleClockClickStart);
255
+ this.plate.addEventListener('touchstart', this._handleClockClickStart);
256
+ this.digitalClock.addEventListener('keyup', this._inputFromTextField);
257
+ this.inputHours.addEventListener('click', () => this.showView('hours'));
258
+ this.inputMinutes.addEventListener('click', () => this.showView('minutes'));
259
+ }
260
+
261
+ _removeEventHandlers() {
262
+ this.el.removeEventListener('click', this._handleInputClick);
263
+ this.el.removeEventListener('keydown', this._handleInputKeydown);
264
+ }
265
+
266
+ _handleInputClick = () => {
267
+ this.open();
268
+ }
269
+
270
+ _handleInputKeydown = (e: KeyboardEvent) => {
271
+ if (Utils.keys.ENTER.includes(e.key)) {
192
272
  e.preventDefault();
193
- let clickPos = Timepicker._Pos(e);
194
- let x = clickPos.x - this.x0;
195
- let y = clickPos.y - this.y0;
196
- this.moved = true;
197
- this.setHand(x, y, false);
273
+ this.open();
198
274
  }
275
+ }
199
276
 
200
- _handleDocumentClickEnd(e) {
277
+ _handleTimeInputEnterKey = (e: KeyboardEvent) => {
278
+ if (Utils.keys.ENTER.includes(e.key)) {
201
279
  e.preventDefault();
202
- document.removeEventListener('mouseup', this._handleDocumentClickEndBound);
203
- document.removeEventListener('touchend', this._handleDocumentClickEndBound);
204
- let clickPos = Timepicker._Pos(e);
205
- let x = clickPos.x - this.x0;
206
- let y = clickPos.y - this.y0;
207
- if (this.moved && x === this.dx && y === this.dy) {
208
- this.setHand(x, y);
209
- }
210
- if (this.currentView === 'hours') {
211
- this.showView('minutes', this.options.duration / 2);
212
- }
213
- else if (this.options.autoClose) {
214
- this.minutesView.classList.add('timepicker-dial-out');
215
- setTimeout(() => {
216
- this.done();
217
- }, this.options.duration / 2);
218
- }
219
- if (typeof this.options.onSelect === 'function') {
220
- this.options.onSelect.call(this, this.hours, this.minutes);
221
- }
222
- // Unbind mousemove event
223
- document.removeEventListener('mousemove', this._handleDocumentClickMoveBound);
224
- document.removeEventListener('touchmove', this._handleDocumentClickMoveBound);
225
- }
226
-
227
- _insertHTMLIntoDOM() {
228
- const template = document.createElement('template');
229
- template.innerHTML = Timepicker._template.trim();
230
- this.modalEl = <HTMLElement>template.content.firstChild;
231
- this.modalEl.id = 'modal-' + this.id;
232
-
233
- // Append popover to input by default
234
- const optEl = this.options.container;
235
- const containerEl = optEl instanceof HTMLElement ? optEl : document.querySelector(optEl);
236
-
237
- if (this.options.container && !!containerEl) {
238
- containerEl.append(this.modalEl);
239
- }
240
- else {
241
- this.el.parentElement.appendChild(this.modalEl);
242
- }
280
+ this._inputFromTextField();
243
281
  }
282
+ }
244
283
 
245
- _setupModal() {
246
- this.modal = M.Modal.init(this.modalEl, {
247
- onOpenStart: this.options.onOpenStart,
248
- onOpenEnd: this.options.onOpenEnd,
249
- onCloseStart: this.options.onCloseStart,
250
- onCloseEnd: () => {
251
- if (typeof this.options.onCloseEnd === 'function') {
252
- this.options.onCloseEnd.call(this);
253
- }
254
- this.isOpen = false;
255
- }
256
- });
257
- }
258
-
259
- _setupVariables() {
260
- this.currentView = 'hours';
261
- this.vibrate = navigator.vibrate
262
- ? 'vibrate'
263
- : (navigator as any).webkitVibrate
264
- ? 'webkitVibrate'
265
- : null;
266
- this._canvas = this.modalEl.querySelector('.timepicker-canvas');
267
- this.plate = this.modalEl.querySelector('.timepicker-plate');
268
- this.digitalClock = this.modalEl.querySelector('.timepicker-display-column');
269
- this.hoursView = this.modalEl.querySelector('.timepicker-hours');
270
- this.minutesView = this.modalEl.querySelector('.timepicker-minutes');
271
- this.inputHours = this.modalEl.querySelector('.timepicker-input-hours');
272
- this.inputMinutes = this.modalEl.querySelector('.timepicker-input-minutes');
273
- this.spanAmPm = this.modalEl.querySelector('.timepicker-span-am-pm');
274
- this.footer = this.modalEl.querySelector('.timepicker-footer');
275
- this.amOrPm = 'PM';
276
- }
277
-
278
- private _createButton(text: string, visibility: string): HTMLButtonElement {
279
- const button = document.createElement('button');
280
- button.classList.add('btn-flat', 'waves-effect');
281
- button.style.visibility = visibility;
282
- button.type = 'button';
283
- button.tabIndex = this.options.twelveHour ? 3 : 1;
284
- button.innerText = text;
285
- return button;
286
- }
287
-
288
- _pickerSetup() {
289
- const clearButton = this._createButton(this.options.i18n.clear, this.options.showClearBtn ? '' : 'hidden');
290
- clearButton.classList.add('timepicker-clear');
291
- clearButton.addEventListener('click', this.clear.bind(this));
292
- this.footer.appendChild(clearButton);
293
-
294
- const confirmationBtnsContainer = document.createElement('div');
295
- confirmationBtnsContainer.classList.add('confirmation-btns');
296
- this.footer.append(confirmationBtnsContainer);
297
-
298
- const cancelButton = this._createButton(this.options.i18n.cancel, '');
299
- cancelButton.classList.add('timepicker-close');
300
- cancelButton.addEventListener('click', this.close.bind(this));
301
- confirmationBtnsContainer.appendChild(cancelButton);
302
-
303
- const doneButton = this._createButton(this.options.i18n.done, '');
304
- doneButton.classList.add('timepicker-close');
305
- doneButton.addEventListener('click', this.done.bind(this));
306
- confirmationBtnsContainer.appendChild(doneButton);
307
- }
308
-
309
- _clockSetup() {
310
- if (this.options.twelveHour) {
311
- // AM Button
312
- this._amBtn = document.createElement('div');
313
- this._amBtn.classList.add('am-btn');
314
- this._amBtn.innerText = 'AM';
315
- this._amBtn.addEventListener('click', this._handleAmPmClick.bind(this));
316
- this.spanAmPm.appendChild(this._amBtn);
317
- // PM Button
318
- this._pmBtn = document.createElement('div');
319
- this._pmBtn.classList.add('pm-btn');
320
- this._pmBtn.innerText = 'PM';
321
- this._pmBtn.addEventListener('click', this._handleAmPmClick.bind(this));
322
- this.spanAmPm.appendChild(this._pmBtn);
323
- }
324
- this._buildHoursView();
325
- this._buildMinutesView();
326
- this._buildSVGClock();
327
- }
328
-
329
- _buildSVGClock() {
330
- // Draw clock hands and others
331
- let dialRadius = this.options.dialRadius;
332
- let tickRadius = this.options.tickRadius;
333
- let diameter = dialRadius * 2;
334
- let svg = Timepicker._createSVGEl('svg');
335
- svg.setAttribute('class', 'timepicker-svg');
336
- svg.setAttribute('width', diameter.toString());
337
- svg.setAttribute('height', diameter.toString());
338
- let g = Timepicker._createSVGEl('g');
339
- g.setAttribute('transform', 'translate(' + dialRadius + ',' + dialRadius + ')');
340
- let bearing = Timepicker._createSVGEl('circle');
341
- bearing.setAttribute('class', 'timepicker-canvas-bearing');
342
- bearing.setAttribute('cx', '0');
343
- bearing.setAttribute('cy', '0');
344
- bearing.setAttribute('r', '4');
345
- let hand = Timepicker._createSVGEl('line');
346
- hand.setAttribute('x1', '0');
347
- hand.setAttribute('y1', '0');
348
- let bg = Timepicker._createSVGEl('circle');
349
- bg.setAttribute('class', 'timepicker-canvas-bg');
350
- bg.setAttribute('r', tickRadius);
351
- g.appendChild(hand);
352
- g.appendChild(bg);
353
- g.appendChild(bearing);
354
- svg.appendChild(g);
355
- this._canvas.appendChild(svg);
356
- this.hand = hand;
357
- this.bg = bg;
358
- this.bearing = bearing;
359
- this.g = g;
360
- }
361
-
362
- _buildHoursView() {
363
- const $tick = document.createElement('div');
364
- $tick.classList.add('timepicker-tick');
365
- // Hours view
366
- if (this.options.twelveHour) {
367
- for (let i = 1; i < 13; i += 1) {
368
- const tick = <HTMLElement>$tick.cloneNode(true);
369
- const radian = (i / 6) * Math.PI;
370
- const radius = this.options.outerRadius;
371
- tick.style.left = this.options.dialRadius + Math.sin(radian) * radius - this.options.tickRadius + 'px';
372
- tick.style.top = this.options.dialRadius - Math.cos(radian) * radius - this.options.tickRadius + 'px';
373
- tick.innerHTML = i === 0 ? '00' : i.toString();
374
- this.hoursView.appendChild(tick);
375
- // tick.on(mousedownEvent, mousedown);
284
+ _handleClockClickStart = (e) => {
285
+ e.preventDefault();
286
+ let clockPlateBR = this.plate.getBoundingClientRect();
287
+ let offset = { x: clockPlateBR.left, y: clockPlateBR.top };
288
+
289
+ this.x0 = offset.x + this.options.dialRadius;
290
+ this.y0 = offset.y + this.options.dialRadius;
291
+ this.moved = false;
292
+ let clickPos = Timepicker._Pos(e);
293
+ this.dx = clickPos.x - this.x0;
294
+ this.dy = clickPos.y - this.y0;
295
+
296
+ // Set clock hands
297
+ this.setHand(this.dx, this.dy, false);
298
+ // Mousemove on document
299
+ document.addEventListener('mousemove', this._handleDocumentClickMove);
300
+ document.addEventListener('touchmove', this._handleDocumentClickMove);
301
+ // Mouseup on document
302
+ document.addEventListener('mouseup', this._handleDocumentClickEnd);
303
+ document.addEventListener('touchend', this._handleDocumentClickEnd);
304
+ }
305
+
306
+ _handleDocumentClickMove = (e) => {
307
+ e.preventDefault();
308
+ let clickPos = Timepicker._Pos(e);
309
+ let x = clickPos.x - this.x0;
310
+ let y = clickPos.y - this.y0;
311
+ this.moved = true;
312
+ this.setHand(x, y, false);
313
+ }
314
+
315
+ _handleDocumentClickEnd = (e) => {
316
+ e.preventDefault();
317
+ document.removeEventListener('mouseup', this._handleDocumentClickEnd);
318
+ document.removeEventListener('touchend', this._handleDocumentClickEnd);
319
+ let clickPos = Timepicker._Pos(e);
320
+ let x = clickPos.x - this.x0;
321
+ let y = clickPos.y - this.y0;
322
+ if (this.moved && x === this.dx && y === this.dy) {
323
+ this.setHand(x, y);
324
+ }
325
+ if (this.currentView === 'hours') {
326
+ this.showView('minutes', this.options.duration / 2);
327
+ }
328
+ else if (this.options.autoClose) {
329
+ this.minutesView.classList.add('timepicker-dial-out');
330
+ setTimeout(() => {
331
+ this.done();
332
+ }, this.options.duration / 2);
333
+ }
334
+ if (typeof this.options.onSelect === 'function') {
335
+ this.options.onSelect.call(this, this.hours, this.minutes);
336
+ }
337
+ // Unbind mousemove event
338
+ document.removeEventListener('mousemove', this._handleDocumentClickMove);
339
+ document.removeEventListener('touchmove', this._handleDocumentClickMove);
340
+ }
341
+
342
+ _insertHTMLIntoDOM() {
343
+ const template = document.createElement('template');
344
+ template.innerHTML = Timepicker._template.trim();
345
+ this.modalEl = <HTMLElement>template.content.firstChild;
346
+ this.modalEl.id = 'modal-' + this.id;
347
+
348
+ // Append popover to input by default
349
+ const optEl = this.options.container;
350
+ const containerEl = optEl instanceof HTMLElement ? optEl : document.querySelector(optEl);
351
+
352
+ if (this.options.container && !!containerEl) {
353
+ containerEl.append(this.modalEl);
354
+ }
355
+ else {
356
+ this.el.parentElement.appendChild(this.modalEl);
357
+ }
358
+ }
359
+
360
+ _setupModal() {
361
+ this.modal = Modal.init(this.modalEl, {
362
+ onOpenStart: this.options.onOpenStart,
363
+ onOpenEnd: this.options.onOpenEnd,
364
+ onCloseStart: this.options.onCloseStart,
365
+ onCloseEnd: () => {
366
+ if (typeof this.options.onCloseEnd === 'function') {
367
+ this.options.onCloseEnd.call(this);
376
368
  }
369
+ this.isOpen = false;
377
370
  }
378
- else {
379
- for (let i = 0; i < 24; i += 1) {
380
- const tick = <HTMLElement>$tick.cloneNode(true);
381
- const radian = (i / 6) * Math.PI;
382
- const inner = i > 0 && i < 13;
383
- const radius = inner ? this.options.innerRadius : this.options.outerRadius;
384
- tick.style.left = this.options.dialRadius + Math.sin(radian) * radius - this.options.tickRadius + 'px';
385
- tick.style.top = this.options.dialRadius - Math.cos(radian) * radius - this.options.tickRadius + 'px';
386
- tick.innerHTML = i === 0 ? '00' : i.toString();
387
- this.hoursView.appendChild(tick);
388
- // tick.on(mousedownEvent, mousedown);
389
- }
371
+ });
372
+ }
373
+
374
+ _setupVariables() {
375
+ this.currentView = 'hours';
376
+ this.vibrate = navigator.vibrate
377
+ ? 'vibrate'
378
+ : (navigator as any).webkitVibrate
379
+ ? 'webkitVibrate'
380
+ : null;
381
+ this._canvas = this.modalEl.querySelector('.timepicker-canvas');
382
+ this.plate = this.modalEl.querySelector('.timepicker-plate');
383
+ this.digitalClock = this.modalEl.querySelector('.timepicker-display-column');
384
+ this.hoursView = this.modalEl.querySelector('.timepicker-hours');
385
+ this.minutesView = this.modalEl.querySelector('.timepicker-minutes');
386
+ this.inputHours = this.modalEl.querySelector('.timepicker-input-hours');
387
+ this.inputMinutes = this.modalEl.querySelector('.timepicker-input-minutes');
388
+ this.spanAmPm = this.modalEl.querySelector('.timepicker-span-am-pm');
389
+ this.footer = this.modalEl.querySelector('.timepicker-footer');
390
+ this.amOrPm = 'PM';
391
+ }
392
+
393
+ private _createButton(text: string, visibility: string): HTMLButtonElement {
394
+ const button = document.createElement('button');
395
+ button.classList.add('btn-flat', 'waves-effect');
396
+ button.style.visibility = visibility;
397
+ button.type = 'button';
398
+ button.tabIndex = this.options.twelveHour ? 3 : 1;
399
+ button.innerText = text;
400
+ return button;
401
+ }
402
+
403
+ _pickerSetup() {
404
+ const clearButton = this._createButton(this.options.i18n.clear, this.options.showClearBtn ? '' : 'hidden');
405
+ clearButton.classList.add('timepicker-clear');
406
+ clearButton.addEventListener('click', this.clear);
407
+ this.footer.appendChild(clearButton);
408
+
409
+ const confirmationBtnsContainer = document.createElement('div');
410
+ confirmationBtnsContainer.classList.add('confirmation-btns');
411
+ this.footer.append(confirmationBtnsContainer);
412
+
413
+ const cancelButton = this._createButton(this.options.i18n.cancel, '');
414
+ cancelButton.classList.add('timepicker-close');
415
+ cancelButton.addEventListener('click', this.close);
416
+ confirmationBtnsContainer.appendChild(cancelButton);
417
+
418
+ const doneButton = this._createButton(this.options.i18n.done, '');
419
+ doneButton.classList.add('timepicker-close');
420
+ doneButton.addEventListener('click', this.done);
421
+ confirmationBtnsContainer.appendChild(doneButton);
422
+ }
423
+
424
+ _clockSetup() {
425
+ if (this.options.twelveHour) {
426
+ // AM Button
427
+ this._amBtn = document.createElement('div');
428
+ this._amBtn.classList.add('am-btn');
429
+ this._amBtn.innerText = 'AM';
430
+ this._amBtn.addEventListener('click', this._handleAmPmClick);
431
+ this.spanAmPm.appendChild(this._amBtn);
432
+ // PM Button
433
+ this._pmBtn = document.createElement('div');
434
+ this._pmBtn.classList.add('pm-btn');
435
+ this._pmBtn.innerText = 'PM';
436
+ this._pmBtn.addEventListener('click', this._handleAmPmClick);
437
+ this.spanAmPm.appendChild(this._pmBtn);
438
+ }
439
+ this._buildHoursView();
440
+ this._buildMinutesView();
441
+ this._buildSVGClock();
442
+ }
443
+
444
+ _buildSVGClock() {
445
+ // Draw clock hands and others
446
+ let dialRadius = this.options.dialRadius;
447
+ let tickRadius = this.options.tickRadius;
448
+ let diameter = dialRadius * 2;
449
+ let svg = Timepicker._createSVGEl('svg');
450
+ svg.setAttribute('class', 'timepicker-svg');
451
+ svg.setAttribute('width', diameter.toString());
452
+ svg.setAttribute('height', diameter.toString());
453
+ let g = Timepicker._createSVGEl('g');
454
+ g.setAttribute('transform', 'translate(' + dialRadius + ',' + dialRadius + ')');
455
+ let bearing = Timepicker._createSVGEl('circle');
456
+ bearing.setAttribute('class', 'timepicker-canvas-bearing');
457
+ bearing.setAttribute('cx', '0');
458
+ bearing.setAttribute('cy', '0');
459
+ bearing.setAttribute('r', '4');
460
+ let hand = Timepicker._createSVGEl('line');
461
+ hand.setAttribute('x1', '0');
462
+ hand.setAttribute('y1', '0');
463
+ let bg = Timepicker._createSVGEl('circle');
464
+ bg.setAttribute('class', 'timepicker-canvas-bg');
465
+ bg.setAttribute('r', tickRadius.toString());
466
+ g.appendChild(hand);
467
+ g.appendChild(bg);
468
+ g.appendChild(bearing);
469
+ svg.appendChild(g);
470
+ this._canvas.appendChild(svg);
471
+ this.hand = hand;
472
+ this.bg = bg;
473
+ this.bearing = bearing;
474
+ this.g = g;
475
+ }
476
+
477
+ _buildHoursView() {
478
+ const $tick = document.createElement('div');
479
+ $tick.classList.add('timepicker-tick');
480
+ // Hours view
481
+ if (this.options.twelveHour) {
482
+ for (let i = 1; i < 13; i += 1) {
483
+ const tick = <HTMLElement>$tick.cloneNode(true);
484
+ const radian = (i / 6) * Math.PI;
485
+ const radius = this.options.outerRadius;
486
+ tick.style.left = this.options.dialRadius + Math.sin(radian) * radius - this.options.tickRadius + 'px';
487
+ tick.style.top = this.options.dialRadius - Math.cos(radian) * radius - this.options.tickRadius + 'px';
488
+ tick.innerHTML = i === 0 ? '00' : i.toString();
489
+ this.hoursView.appendChild(tick);
490
+ // tick.on(mousedownEvent, mousedown);
491
+ }
492
+ }
493
+ else {
494
+ for (let i = 0; i < 24; i += 1) {
495
+ const tick = <HTMLElement>$tick.cloneNode(true);
496
+ const radian = (i / 6) * Math.PI;
497
+ const inner = i > 0 && i < 13;
498
+ const radius = inner ? this.options.innerRadius : this.options.outerRadius;
499
+ tick.style.left = this.options.dialRadius + Math.sin(radian) * radius - this.options.tickRadius + 'px';
500
+ tick.style.top = this.options.dialRadius - Math.cos(radian) * radius - this.options.tickRadius + 'px';
501
+ tick.innerHTML = i === 0 ? '00' : i.toString();
502
+ this.hoursView.appendChild(tick);
503
+ // tick.on(mousedownEvent, mousedown);
390
504
  }
391
505
  }
506
+ }
392
507
 
393
- _buildMinutesView() {
394
- const _tick = document.createElement('div');
395
- _tick.classList.add('timepicker-tick');
396
- // Minutes view
397
- for (let i = 0; i < 60; i += 5) {
398
- const tick = <HTMLElement>_tick.cloneNode(true);
399
- const radian = (i / 30) * Math.PI;
400
- tick.style.left =
401
- this.options.dialRadius +
402
- Math.sin(radian) * this.options.outerRadius -
508
+ _buildMinutesView() {
509
+ const _tick = document.createElement('div');
510
+ _tick.classList.add('timepicker-tick');
511
+ // Minutes view
512
+ for (let i = 0; i < 60; i += 5) {
513
+ const tick = <HTMLElement>_tick.cloneNode(true);
514
+ const radian = (i / 30) * Math.PI;
515
+ tick.style.left =
516
+ this.options.dialRadius +
517
+ Math.sin(radian) * this.options.outerRadius -
518
+ this.options.tickRadius +
519
+ 'px';
520
+ tick.style.top =
521
+ this.options.dialRadius -
522
+ Math.cos(radian) * this.options.outerRadius -
403
523
  this.options.tickRadius +
404
524
  'px';
405
- tick.style.top =
406
- this.options.dialRadius -
407
- Math.cos(radian) * this.options.outerRadius -
408
- this.options.tickRadius +
409
- 'px';
410
- tick.innerHTML = Timepicker._addLeadingZero(i);
411
- this.minutesView.appendChild(tick);
412
- }
525
+ tick.innerHTML = Timepicker._addLeadingZero(i);
526
+ this.minutesView.appendChild(tick);
413
527
  }
528
+ }
414
529
 
415
- _handleAmPmClick(e) {
416
- const btnClicked = <HTMLElement>e.target;
417
- this.amOrPm = btnClicked.classList.contains('am-btn') ? 'AM' : 'PM';
418
- this._updateAmPmView();
419
- }
530
+ _handleAmPmClick = (e) => {
531
+ const btnClicked = <HTMLElement>e.target;
532
+ this.amOrPm = btnClicked.classList.contains('am-btn') ? 'AM' : 'PM';
533
+ this._updateAmPmView();
534
+ }
420
535
 
421
- _updateAmPmView() {
422
- if (this.options.twelveHour) {
423
- if (this.amOrPm === 'PM') {
424
- this._amBtn.classList.remove('text-primary');
425
- this._pmBtn.classList.add('text-primary');
426
- }
427
- else if (this.amOrPm === 'AM') {
428
- this._amBtn.classList.add('text-primary');
429
- this._pmBtn.classList.remove('text-primary');
430
- }
536
+ _updateAmPmView() {
537
+ if (this.options.twelveHour) {
538
+ if (this.amOrPm === 'PM') {
539
+ this._amBtn.classList.remove('text-primary');
540
+ this._pmBtn.classList.add('text-primary');
541
+ }
542
+ else if (this.amOrPm === 'AM') {
543
+ this._amBtn.classList.add('text-primary');
544
+ this._pmBtn.classList.remove('text-primary');
431
545
  }
432
546
  }
547
+ }
433
548
 
434
- _updateTimeFromInput() {
435
- // Get the time
436
- let value = ((this.el.value || this.options.defaultTime || '') + '').split(':');
437
- if (this.options.twelveHour && !(typeof value[1] === 'undefined')) {
438
- if (value[1].toUpperCase().indexOf('AM') > 0) {
439
- this.amOrPm = 'AM';
440
- } else {
441
- this.amOrPm = 'PM';
442
- }
443
- value[1] = value[1].replace('AM', '').replace('PM', '');
549
+ _updateTimeFromInput() {
550
+ // Get the time
551
+ let value = ((this.el.value || this.options.defaultTime || '') + '').split(':');
552
+ if (this.options.twelveHour && !(typeof value[1] === 'undefined')) {
553
+ if (value[1].toUpperCase().indexOf('AM') > 0) {
554
+ this.amOrPm = 'AM';
555
+ } else {
556
+ this.amOrPm = 'PM';
444
557
  }
445
- if (value[0] === 'now') {
446
- let now = new Date(+new Date() + this.options.fromNow);
447
- value = [now.getHours().toString(), now.getMinutes().toString()];
448
- if (this.options.twelveHour) {
449
- this.amOrPm = parseInt(value[0]) >= 12 && parseInt(value[0]) < 24 ? 'PM' : 'AM';
450
- }
558
+ value[1] = value[1].replace('AM', '').replace('PM', '');
559
+ }
560
+ if (value[0] === 'now') {
561
+ let now = new Date(+new Date() + this.options.fromNow);
562
+ value = [now.getHours().toString(), now.getMinutes().toString()];
563
+ if (this.options.twelveHour) {
564
+ this.amOrPm = parseInt(value[0]) >= 12 && parseInt(value[0]) < 24 ? 'PM' : 'AM';
451
565
  }
452
- this.hours = +value[0] || 0;
453
- this.minutes = +value[1] || 0;
454
- this.inputHours.value = this.hours;
455
- this.inputMinutes.value = Timepicker._addLeadingZero(this.minutes);
456
-
457
- this._updateAmPmView();
458
566
  }
567
+ this.hours = +value[0] || 0;
568
+ this.minutes = +value[1] || 0;
569
+ this.inputHours.value = this.hours;
570
+ this.inputMinutes.value = Timepicker._addLeadingZero(this.minutes);
459
571
 
460
- showView(view, delay: number = null) {
461
- if (view === 'minutes' && getComputedStyle(this.hoursView).visibility === 'visible') {
462
- // raiseCallback(this.options.beforeHourSelect);
463
- }
464
- let isHours = view === 'hours',
465
- nextView = isHours ? this.hoursView : this.minutesView,
466
- hideView = isHours ? this.minutesView : this.hoursView;
467
- this.currentView = view;
572
+ this._updateAmPmView();
573
+ }
468
574
 
469
- if (isHours) {
470
- this.inputHours.classList.add('text-primary');
471
- this.inputMinutes.classList.remove('text-primary');
472
- }
473
- else {
474
- this.inputHours.classList.remove('text-primary');
475
- this.inputMinutes.classList.add('text-primary');
476
- }
575
+ /**
576
+ * Show hours or minutes view on timepicker.
577
+ * @param view The name of the view you want to switch to, 'hours' or 'minutes'.
578
+ */
579
+ showView = (view: Views, delay: number = null) => {
580
+ if (view === 'minutes' && getComputedStyle(this.hoursView).visibility === 'visible') {
581
+ // raiseCallback(this.options.beforeHourSelect);
582
+ }
583
+ let isHours = view === 'hours',
584
+ nextView = isHours ? this.hoursView : this.minutesView,
585
+ hideView = isHours ? this.minutesView : this.hoursView;
586
+ this.currentView = view;
587
+
588
+ if (isHours) {
589
+ this.inputHours.classList.add('text-primary');
590
+ this.inputMinutes.classList.remove('text-primary');
591
+ }
592
+ else {
593
+ this.inputHours.classList.remove('text-primary');
594
+ this.inputMinutes.classList.add('text-primary');
595
+ }
596
+
597
+ // Transition view
598
+ hideView.classList.add('timepicker-dial-out');
599
+
600
+ nextView.style.visibility = 'visible';
601
+ nextView.classList.remove('timepicker-dial-out');
602
+
603
+ // Reset clock hand
604
+ this.resetClock(delay);
605
+ // After transitions ended
606
+ clearTimeout(this.toggleViewTimer);
607
+ this.toggleViewTimer = setTimeout(() => {
608
+ hideView.style.visibility = 'hidden';
609
+ }, this.options.duration);
610
+ }
477
611
 
478
- // Transition view
479
- hideView.classList.add('timepicker-dial-out');
480
-
481
- nextView.style.visibility = 'visible';
482
- nextView.classList.remove('timepicker-dial-out');
483
-
484
- // Reset clock hand
485
- this.resetClock(delay);
486
- // After transitions ended
487
- clearTimeout(this.toggleViewTimer);
488
- this.toggleViewTimer = setTimeout(() => {
489
- hideView.style.visibility = 'hidden';
490
- }, this.options.duration);
491
- }
492
-
493
- resetClock(delay) {
494
- let view = this.currentView,
495
- value = this[view],
496
- isHours = view === 'hours',
497
- unit = Math.PI / (isHours ? 6 : 30),
498
- radian = value * unit,
499
- radius =
500
- isHours && value > 0 && value < 13 ? this.options.innerRadius : this.options.outerRadius,
501
- x = Math.sin(radian) * radius,
502
- y = -Math.cos(radian) * radius,
503
- self = this;
504
-
505
- if (delay) {
506
- this.canvas?.classList.add('timepicker-canvas-out');
507
- setTimeout(() => {
508
- self.canvas?.classList.remove('timepicker-canvas-out');
509
- self.setHand(x, y);
510
- }, delay);
612
+ resetClock(delay) {
613
+ let view = this.currentView,
614
+ value = this[view],
615
+ isHours = view === 'hours',
616
+ unit = Math.PI / (isHours ? 6 : 30),
617
+ radian = value * unit,
618
+ radius =
619
+ isHours && value > 0 && value < 13 ? this.options.innerRadius : this.options.outerRadius,
620
+ x = Math.sin(radian) * radius,
621
+ y = -Math.cos(radian) * radius,
622
+ self = this;
623
+
624
+ if (delay) {
625
+ this.canvas?.classList.add('timepicker-canvas-out');
626
+ setTimeout(() => {
627
+ self.canvas?.classList.remove('timepicker-canvas-out');
628
+ self.setHand(x, y);
629
+ }, delay);
630
+ }
631
+ else {
632
+ this.setHand(x, y);
633
+ }
634
+ }
635
+
636
+ _inputFromTextField = () => {
637
+ const isHours = this.currentView === 'hours';
638
+ if (isHours) {
639
+ const value = parseInt(this.inputHours.value);
640
+ if (value > 0 && value < 13) {
641
+ this.drawClockFromTimeInput(value, isHours);
642
+ this.showView('minutes', this.options.duration / 2);
643
+ this.hours = value;
644
+ this.inputMinutes.focus();
511
645
  }
512
646
  else {
513
- this.setHand(x, y);
647
+ const hour = new Date().getHours();
648
+ this.inputHours.value = (hour % 12).toString();
514
649
  }
515
650
  }
516
-
517
- _inputFromTextField() {
518
- const isHours = this.currentView === 'hours';
519
- if (isHours) {
520
- const value = parseInt(this.inputHours.value);
521
- if (value > 0 && value < 13) {
522
- this.drawClockFromTimeInput(value, isHours);
523
- this.showView('minutes', this.options.duration / 2);
524
- this.hours = value;
525
- this.inputMinutes.focus();
526
- }
527
- else {
528
- const hour = new Date().getHours();
529
- this.inputHours.value = (hour % 12).toString();
530
- }
651
+ else {
652
+ const value = parseInt(this.inputMinutes.value);
653
+ if (value >= 0 && value < 60) {
654
+ this.inputMinutes.value = Timepicker._addLeadingZero(value);
655
+ this.drawClockFromTimeInput(value, isHours);
656
+ this.minutes = value;
657
+ (<HTMLElement>this.modalEl.querySelector('.confirmation-btns :nth-child(2)')).focus();
531
658
  }
532
659
  else {
533
- const value = parseInt(this.inputMinutes.value);
534
- if (value >= 0 && value < 60) {
535
- this.inputMinutes.value = Timepicker._addLeadingZero(value);
536
- this.drawClockFromTimeInput(value, isHours);
537
- this.minutes = value;
538
- (<HTMLElement>this.modalEl.querySelector('.confirmation-btns :nth-child(2)')).focus();
539
- }
540
- else {
541
- const minutes = new Date().getMinutes();
542
- this.inputMinutes.value = Timepicker._addLeadingZero(minutes);
543
- }
660
+ const minutes = new Date().getMinutes();
661
+ this.inputMinutes.value = Timepicker._addLeadingZero(minutes);
544
662
  }
545
663
  }
664
+ }
546
665
 
547
- drawClockFromTimeInput(value, isHours) {
548
- const unit = Math.PI / (isHours ? 6 : 30);
549
- const radian = value * unit;
550
- let radius;
551
- if (this.options.twelveHour) {
552
- radius = this.options.outerRadius;
553
- }
554
- let cx1 = Math.sin(radian) * (radius - this.options.tickRadius),
555
- cy1 = -Math.cos(radian) * (radius - this.options.tickRadius),
556
- cx2 = Math.sin(radian) * radius,
557
- cy2 = -Math.cos(radian) * radius;
558
- this.hand.setAttribute('x2', cx1.toString());
559
- this.hand.setAttribute('y2', cy1.toString());
560
- this.bg.setAttribute('cx', cx2.toString());
561
- this.bg.setAttribute('cy', cy2.toString());
562
- }
563
-
564
- setHand(x, y, roundBy5: boolean = false) {
565
- let radian = Math.atan2(x, -y),
566
- isHours = this.currentView === 'hours',
567
- unit = Math.PI / (isHours || roundBy5 ? 6 : 30),
568
- z = Math.sqrt(x * x + y * y),
569
- inner = isHours && z < (this.options.outerRadius + this.options.innerRadius) / 2,
570
- radius = inner ? this.options.innerRadius : this.options.outerRadius;
666
+ drawClockFromTimeInput(value, isHours) {
667
+ const unit = Math.PI / (isHours ? 6 : 30);
668
+ const radian = value * unit;
669
+ let radius;
670
+ if (this.options.twelveHour) {
671
+ radius = this.options.outerRadius;
672
+ }
673
+ let cx1 = Math.sin(radian) * (radius - this.options.tickRadius),
674
+ cy1 = -Math.cos(radian) * (radius - this.options.tickRadius),
675
+ cx2 = Math.sin(radian) * radius,
676
+ cy2 = -Math.cos(radian) * radius;
677
+ this.hand.setAttribute('x2', cx1.toString());
678
+ this.hand.setAttribute('y2', cy1.toString());
679
+ this.bg.setAttribute('cx', cx2.toString());
680
+ this.bg.setAttribute('cy', cy2.toString());
681
+ }
571
682
 
572
- if (this.options.twelveHour) {
573
- radius = this.options.outerRadius;
574
- }
683
+ setHand(x, y, roundBy5: boolean = false) {
684
+ let radian = Math.atan2(x, -y),
685
+ isHours = this.currentView === 'hours',
686
+ unit = Math.PI / (isHours || roundBy5 ? 6 : 30),
687
+ z = Math.sqrt(x * x + y * y),
688
+ inner = isHours && z < (this.options.outerRadius + this.options.innerRadius) / 2,
689
+ radius = inner ? this.options.innerRadius : this.options.outerRadius;
575
690
 
576
- // Radian should in range [0, 2PI]
577
- if (radian < 0) {
578
- radian = Math.PI * 2 + radian;
579
- }
691
+ if (this.options.twelveHour) {
692
+ radius = this.options.outerRadius;
693
+ }
580
694
 
581
- // Get the round value
582
- let value = Math.round(radian / unit);
695
+ // Radian should in range [0, 2PI]
696
+ if (radian < 0) {
697
+ radian = Math.PI * 2 + radian;
698
+ }
583
699
 
584
- // Get the round radian
585
- radian = value * unit;
700
+ // Get the round value
701
+ let value = Math.round(radian / unit);
586
702
 
587
- // Correct the hours or minutes
588
- if (this.options.twelveHour) {
589
- if (isHours) {
590
- if (value === 0) value = 12;
591
- } else {
592
- if (roundBy5) value *= 5;
593
- if (value === 60) value = 0;
703
+ // Get the round radian
704
+ radian = value * unit;
705
+
706
+ // Correct the hours or minutes
707
+ if (this.options.twelveHour) {
708
+ if (isHours) {
709
+ if (value === 0) value = 12;
710
+ } else {
711
+ if (roundBy5) value *= 5;
712
+ if (value === 60) value = 0;
713
+ }
714
+ } else {
715
+ if (isHours) {
716
+ if (value === 12) {
717
+ value = 0;
594
718
  }
719
+ value = inner ? (value === 0 ? 12 : value) : value === 0 ? 0 : value + 12;
595
720
  } else {
596
- if (isHours) {
597
- if (value === 12) {
598
- value = 0;
599
- }
600
- value = inner ? (value === 0 ? 12 : value) : value === 0 ? 0 : value + 12;
601
- } else {
602
- if (roundBy5) {
603
- value *= 5;
604
- }
605
- if (value === 60) {
606
- value = 0;
607
- }
721
+ if (roundBy5) {
722
+ value *= 5;
723
+ }
724
+ if (value === 60) {
725
+ value = 0;
608
726
  }
609
727
  }
728
+ }
610
729
 
611
- // Once hours or minutes changed, vibrate the device
612
- if (this[this.currentView] !== value) {
613
- if (this.vibrate && this.options.vibrate) {
614
- // Do not vibrate too frequently
615
- if (!this.vibrateTimer) {
616
- navigator[this.vibrate](10);
617
- this.vibrateTimer = setTimeout(() => {
618
- this.vibrateTimer = null;
619
- }, 100);
620
- }
730
+ // Once hours or minutes changed, vibrate the device
731
+ if (this[this.currentView] !== value) {
732
+ if (this.vibrate && this.options.vibrate) {
733
+ // Do not vibrate too frequently
734
+ if (!this.vibrateTimer) {
735
+ navigator[this.vibrate](10);
736
+ this.vibrateTimer = setTimeout(() => {
737
+ this.vibrateTimer = null;
738
+ }, 100);
621
739
  }
622
740
  }
741
+ }
623
742
 
624
- this[this.currentView] = value;
625
- if (isHours) {
626
- this.inputHours.value = value.toString();
627
- }
628
- else {
629
- this.inputMinutes.value = Timepicker._addLeadingZero(value);
630
- }
743
+ this[this.currentView] = value;
744
+ if (isHours) {
745
+ this.inputHours.value = value.toString();
746
+ }
747
+ else {
748
+ this.inputMinutes.value = Timepicker._addLeadingZero(value);
749
+ }
631
750
 
632
- // Set clock hand and others' position
633
- let cx1 = Math.sin(radian) * (radius - this.options.tickRadius),
634
- cy1 = -Math.cos(radian) * (radius - this.options.tickRadius),
635
- cx2 = Math.sin(radian) * radius,
636
- cy2 = -Math.cos(radian) * radius;
637
- this.hand.setAttribute('x2', cx1.toString());
638
- this.hand.setAttribute('y2', cy1.toString());
639
- this.bg.setAttribute('cx', cx2.toString());
640
- this.bg.setAttribute('cy', cy2.toString());
641
- }
642
-
643
- open() {
644
- if (this.isOpen) return;
645
- this.isOpen = true;
646
- this._updateTimeFromInput();
647
- this.showView('hours');
648
- this.modal.open(undefined);
649
- }
650
-
651
- close() {
652
- if (!this.isOpen) return;
653
- this.isOpen = false;
654
- this.modal.close();
655
- }
656
-
657
- done(e = null, clearValue = null) {
658
- // Set input value
659
- let last = this.el.value;
660
- let value = clearValue
661
- ? ''
662
- : Timepicker._addLeadingZero(this.hours) + ':' + Timepicker._addLeadingZero(this.minutes);
663
- this.time = value;
664
- if (!clearValue && this.options.twelveHour) {
665
- value = `${value} ${this.amOrPm}`;
666
- }
667
- this.el.value = value;
668
- // Trigger change event
669
- if (value !== last) {
670
- this.el.dispatchEvent(new Event('change'));
671
- }
672
- this.close();
673
- this.el.focus();
674
- }
675
-
676
- clear() {
677
- this.done(null, true);
678
- }
679
-
680
- static {
681
- Timepicker._template = `
682
- <div class="modal timepicker-modal">
683
- <div class="modal-content timepicker-container">
684
- <div class="timepicker-digital-display">
685
- <div class="timepicker-text-container">
686
- <div class="timepicker-display-column">
687
- <input type="text" maxlength="2" autofocus class="timepicker-input-hours text-primary" />
688
- :
689
- <input type="text" maxlength="2" class="timepicker-input-minutes" />
690
- </div>
691
- <div class="timepicker-display-column timepicker-display-am-pm">
692
- <div class="timepicker-span-am-pm"></div>
693
- </div>
751
+ // Set clock hand and others' position
752
+ let cx1 = Math.sin(radian) * (radius - this.options.tickRadius),
753
+ cy1 = -Math.cos(radian) * (radius - this.options.tickRadius),
754
+ cx2 = Math.sin(radian) * radius,
755
+ cy2 = -Math.cos(radian) * radius;
756
+ this.hand.setAttribute('x2', cx1.toString());
757
+ this.hand.setAttribute('y2', cy1.toString());
758
+ this.bg.setAttribute('cx', cx2.toString());
759
+ this.bg.setAttribute('cy', cy2.toString());
760
+ }
761
+
762
+ /**
763
+ * Open timepicker.
764
+ */
765
+ open = () => {
766
+ if (this.isOpen) return;
767
+ this.isOpen = true;
768
+ this._updateTimeFromInput();
769
+ this.showView('hours');
770
+ this.modal.open(undefined);
771
+ }
772
+
773
+ /**
774
+ * Close timepicker.
775
+ */
776
+ close = () => {
777
+ if (!this.isOpen) return;
778
+ this.isOpen = false;
779
+ this.modal.close();
780
+ }
781
+
782
+ done = (e = null, clearValue = null) => {
783
+ // Set input value
784
+ let last = this.el.value;
785
+ let value = clearValue
786
+ ? ''
787
+ : Timepicker._addLeadingZero(this.hours) + ':' + Timepicker._addLeadingZero(this.minutes);
788
+ this.time = value;
789
+ if (!clearValue && this.options.twelveHour) {
790
+ value = `${value} ${this.amOrPm}`;
791
+ }
792
+ this.el.value = value;
793
+ // Trigger change event
794
+ if (value !== last) {
795
+ this.el.dispatchEvent(new Event('change',{bubbles:true, cancelable:true, composed:true}));
796
+ }
797
+ this.close();
798
+ this.el.focus();
799
+ }
800
+
801
+ clear = () => {
802
+ this.done(null, true);
803
+ }
804
+
805
+ static {
806
+ Timepicker._template = `
807
+ <div class="modal timepicker-modal">
808
+ <div class="modal-content timepicker-container">
809
+ <div class="timepicker-digital-display">
810
+ <div class="timepicker-text-container">
811
+ <div class="timepicker-display-column">
812
+ <input type="text" maxlength="2" autofocus class="timepicker-input-hours text-primary" />
813
+ :
814
+ <input type="text" maxlength="2" class="timepicker-input-minutes" />
694
815
  </div>
695
- </div>
696
- <div class="timepicker-analog-display">
697
- <div class="timepicker-plate">
698
- <div class="timepicker-canvas"></div>
699
- <div class="timepicker-dial timepicker-hours"></div>
700
- <div class="timepicker-dial timepicker-minutes timepicker-dial-out"></div>
816
+ <div class="timepicker-display-column timepicker-display-am-pm">
817
+ <div class="timepicker-span-am-pm"></div>
701
818
  </div>
702
- <div class="timepicker-footer"></div>
703
819
  </div>
704
820
  </div>
705
- </div`;
706
- }
821
+ <div class="timepicker-analog-display">
822
+ <div class="timepicker-plate">
823
+ <div class="timepicker-canvas"></div>
824
+ <div class="timepicker-dial timepicker-hours"></div>
825
+ <div class="timepicker-dial timepicker-minutes timepicker-dial-out"></div>
826
+ </div>
827
+ <div class="timepicker-footer"></div>
828
+ </div>
829
+ </div>
830
+ </div`;
707
831
  }
708
-
832
+ }