@materializecss/materialize 2.0.3-alpha → 2.0.3
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.
- package/README.md +1 -1
- package/dist/css/materialize.css +345 -236
- package/dist/css/materialize.min.css +2 -2
- package/dist/js/materialize.js +518 -1979
- package/dist/js/materialize.min.js +2 -2
- package/dist/js/materialize.min.js.map +1 -1
- package/dist/src/buttons.d.ts.map +1 -1
- package/dist/src/cards.d.ts.map +1 -1
- package/dist/src/collapsible.d.ts +1 -0
- package/dist/src/collapsible.d.ts.map +1 -1
- package/dist/src/dropdown.d.ts.map +1 -1
- package/dist/src/global.d.ts.map +1 -1
- package/dist/src/materialbox.d.ts +14 -10
- package/dist/src/materialbox.d.ts.map +1 -1
- package/dist/src/modal.d.ts.map +1 -1
- package/dist/src/range.d.ts.map +1 -1
- package/dist/src/scrollspy.d.ts.map +1 -1
- package/dist/src/sidenav.d.ts +25 -25
- package/dist/src/sidenav.d.ts.map +1 -1
- package/dist/src/slider.d.ts +12 -12
- package/dist/src/slider.d.ts.map +1 -1
- package/dist/src/tabs.d.ts +1 -1
- package/dist/src/tabs.d.ts.map +1 -1
- package/dist/src/toasts.d.ts +7 -2
- package/dist/src/toasts.d.ts.map +1 -1
- package/dist/src/tooltip.d.ts +8 -2
- package/dist/src/tooltip.d.ts.map +1 -1
- package/package.json +14 -13
- package/sass/components/_buttons.scss +158 -73
- package/sass/components/_chips.scss +75 -28
- package/sass/components/_collapsible.scss +14 -2
- package/sass/components/_global.scss +6 -94
- package/sass/components/_materialbox.scss +2 -2
- package/sass/components/_modal.scss +0 -1
- package/sass/components/_preloader.scss +85 -0
- package/sass/components/_tooltip.scss +18 -8
- package/sass/components/_variables.scss +5 -4
- package/sass/components/forms/_range.scss +1 -1
- package/sass/components/forms/_switches.scss +44 -14
- package/Gruntfile.js +0 -480
- package/src/autocomplete.ts +0 -553
- package/src/bounding.ts +0 -6
- package/src/buttons.ts +0 -260
- package/src/cards.ts +0 -53
- package/src/carousel.ts +0 -676
- package/src/characterCounter.ts +0 -117
- package/src/chips.ts +0 -439
- package/src/collapsible.ts +0 -249
- package/src/component.ts +0 -120
- package/src/datepicker.ts +0 -1076
- package/src/dropdown.ts +0 -644
- package/src/edges.ts +0 -6
- package/src/forms.ts +0 -132
- package/src/global.ts +0 -114
- package/src/index.ts +0 -26
- package/src/materialbox.ts +0 -404
- package/src/modal.ts +0 -341
- package/src/parallax.ts +0 -149
- package/src/pushpin.ts +0 -165
- package/src/range.ts +0 -198
- package/src/scrollspy.ts +0 -263
- package/src/select.ts +0 -484
- package/src/sidenav.ts +0 -543
- package/src/slider.ts +0 -474
- package/src/tabs.ts +0 -347
- package/src/tapTarget.ts +0 -273
- package/src/timepicker.ts +0 -832
- package/src/toasts.ts +0 -290
- package/src/tooltip.ts +0 -346
- package/src/utils.ts +0 -271
- package/src/waves.ts +0 -70
package/src/timepicker.ts
DELETED
|
@@ -1,832 +0,0 @@
|
|
|
1
|
-
import { Modal } from "./modal";
|
|
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 = {
|
|
101
|
-
dialRadius: 135,
|
|
102
|
-
outerRadius: 105,
|
|
103
|
-
innerRadius: 70,
|
|
104
|
-
tickRadius: 20,
|
|
105
|
-
duration: 350,
|
|
106
|
-
container: null,
|
|
107
|
-
defaultTime: 'now', // default time, 'now' or '13:14' e.g.
|
|
108
|
-
fromNow: 0, // Millisecond offset from the defaultTime
|
|
109
|
-
showClearBtn: false,
|
|
110
|
-
// internationalization
|
|
111
|
-
i18n: {
|
|
112
|
-
cancel: 'Cancel',
|
|
113
|
-
clear: 'Clear',
|
|
114
|
-
done: 'Ok'
|
|
115
|
-
},
|
|
116
|
-
autoClose: false, // auto close when minute is selected
|
|
117
|
-
twelveHour: true, // change to 12 hour AM/PM clock from 24 hour
|
|
118
|
-
vibrate: true, // vibrate the device when dragging clock hand
|
|
119
|
-
// Callbacks
|
|
120
|
-
onOpenStart: null,
|
|
121
|
-
onOpenEnd: null,
|
|
122
|
-
onCloseStart: null,
|
|
123
|
-
onCloseEnd: null,
|
|
124
|
-
onSelect: null
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
type Point = {
|
|
128
|
-
x: number,
|
|
129
|
-
y: number
|
|
130
|
-
};
|
|
131
|
-
|
|
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
|
-
}
|
|
197
|
-
|
|
198
|
-
static get defaults(): TimepickerOptions {
|
|
199
|
-
return _defaults;
|
|
200
|
-
}
|
|
201
|
-
|
|
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
|
-
}
|
|
222
|
-
|
|
223
|
-
static _addLeadingZero(num: number) {
|
|
224
|
-
return (num < 10 ? '0' : '') + num;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
static _createSVGEl(name: string) {
|
|
228
|
-
let svgNS = 'http://www.w3.org/2000/svg';
|
|
229
|
-
return document.createElementNS(svgNS, name);
|
|
230
|
-
}
|
|
231
|
-
|
|
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 };
|
|
235
|
-
}
|
|
236
|
-
// mouse event
|
|
237
|
-
return { x: (e as MouseEvent).clientX, y: (e as MouseEvent).clientY };
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
static getInstance(el: HTMLElement): Timepicker {
|
|
241
|
-
return (el as any).M_Timepicker;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
destroy() {
|
|
245
|
-
this._removeEventHandlers();
|
|
246
|
-
this.modal.destroy();
|
|
247
|
-
this.modalEl.remove();
|
|
248
|
-
(this.el as any).M_Timepicker = undefined;
|
|
249
|
-
}
|
|
250
|
-
|
|
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)) {
|
|
272
|
-
e.preventDefault();
|
|
273
|
-
this.open();
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
_handleTimeInputEnterKey = (e: KeyboardEvent) => {
|
|
278
|
-
if (Utils.keys.ENTER.includes(e.key)) {
|
|
279
|
-
e.preventDefault();
|
|
280
|
-
this._inputFromTextField();
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
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);
|
|
368
|
-
}
|
|
369
|
-
this.isOpen = false;
|
|
370
|
-
}
|
|
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);
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
|
|
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 -
|
|
523
|
-
this.options.tickRadius +
|
|
524
|
-
'px';
|
|
525
|
-
tick.innerHTML = Timepicker._addLeadingZero(i);
|
|
526
|
-
this.minutesView.appendChild(tick);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
_handleAmPmClick = (e) => {
|
|
531
|
-
const btnClicked = <HTMLElement>e.target;
|
|
532
|
-
this.amOrPm = btnClicked.classList.contains('am-btn') ? 'AM' : 'PM';
|
|
533
|
-
this._updateAmPmView();
|
|
534
|
-
}
|
|
535
|
-
|
|
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');
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
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';
|
|
557
|
-
}
|
|
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';
|
|
565
|
-
}
|
|
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);
|
|
571
|
-
|
|
572
|
-
this._updateAmPmView();
|
|
573
|
-
}
|
|
574
|
-
|
|
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
|
-
}
|
|
611
|
-
|
|
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();
|
|
645
|
-
}
|
|
646
|
-
else {
|
|
647
|
-
const hour = new Date().getHours();
|
|
648
|
-
this.inputHours.value = (hour % 12).toString();
|
|
649
|
-
}
|
|
650
|
-
}
|
|
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();
|
|
658
|
-
}
|
|
659
|
-
else {
|
|
660
|
-
const minutes = new Date().getMinutes();
|
|
661
|
-
this.inputMinutes.value = Timepicker._addLeadingZero(minutes);
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
|
|
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
|
-
}
|
|
682
|
-
|
|
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;
|
|
690
|
-
|
|
691
|
-
if (this.options.twelveHour) {
|
|
692
|
-
radius = this.options.outerRadius;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
// Radian should in range [0, 2PI]
|
|
696
|
-
if (radian < 0) {
|
|
697
|
-
radian = Math.PI * 2 + radian;
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
// Get the round value
|
|
701
|
-
let value = Math.round(radian / unit);
|
|
702
|
-
|
|
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;
|
|
718
|
-
}
|
|
719
|
-
value = inner ? (value === 0 ? 12 : value) : value === 0 ? 0 : value + 12;
|
|
720
|
-
} else {
|
|
721
|
-
if (roundBy5) {
|
|
722
|
-
value *= 5;
|
|
723
|
-
}
|
|
724
|
-
if (value === 60) {
|
|
725
|
-
value = 0;
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
|
|
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);
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
|
|
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
|
-
}
|
|
750
|
-
|
|
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" />
|
|
815
|
-
</div>
|
|
816
|
-
<div class="timepicker-display-column timepicker-display-am-pm">
|
|
817
|
-
<div class="timepicker-span-am-pm"></div>
|
|
818
|
-
</div>
|
|
819
|
-
</div>
|
|
820
|
-
</div>
|
|
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`;
|
|
831
|
-
}
|
|
832
|
-
}
|