UNPKG

13.1 kBJavaScriptView Raw
1import { Component, Input, forwardRef } from '@angular/core';
2import { NG_VALUE_ACCESSOR } from '@angular/forms';
3import { TimepickerConfig } from './timepicker.config';
4export var TIMEPICKER_CONTROL_VALUE_ACCESSOR = {
5 provide: NG_VALUE_ACCESSOR,
6 useExisting: forwardRef(function () { return TimepickerComponent; }),
7 multi: true
8};
9// todo: refactor directive has to many functions! (extract to stateless helper)
10// todo: use moment js?
11// todo: implement `time` validator
12// todo: replace increment/decrement blockers with getters, or extract
13// todo: unify work with selected
14function isDefined(value) {
15 return typeof value !== 'undefined';
16}
17function addMinutes(date, minutes) {
18 var dt = new Date(date.getTime() + minutes * 60000);
19 var newDate = new Date(date);
20 newDate.setHours(dt.getHours(), dt.getMinutes());
21 return newDate;
22}
23export var TimepickerComponent = (function () {
24 function TimepickerComponent(_config) {
25 this.onChange = Function.prototype;
26 this.onTouched = Function.prototype;
27 // result value
28 this._selected = new Date();
29 this.config = _config;
30 Object.assign(this, _config);
31 }
32 Object.defineProperty(TimepickerComponent.prototype, "showMeridian", {
33 /** if true works in 12H mode and displays AM/PM. If false works in 24H mode and hides AM/PM */
34 get: function () {
35 return this._showMeridian;
36 },
37 set: function (value) {
38 this._showMeridian = value;
39 // || !this.$error.time
40 // if (true) {
41 this.updateTemplate();
42 return;
43 // }
44 // Evaluate from template
45 /*let hours = this.getHoursFromTemplate();
46 let minutes = this.getMinutesFromTemplate();
47 if (isDefined(hours) && isDefined(minutes)) {
48 this.selected.setHours(hours);
49 this.refresh();
50 }*/
51 },
52 enumerable: true,
53 configurable: true
54 });
55 Object.defineProperty(TimepickerComponent.prototype, "selected", {
56 get: function () {
57 return this._selected;
58 },
59 set: function (v) {
60 if (v) {
61 this._selected = v;
62 this.updateTemplate();
63 this.onChange(this.selected);
64 }
65 },
66 enumerable: true,
67 configurable: true
68 });
69 // todo: add formatter value to Date object
70 TimepickerComponent.prototype.ngOnInit = function () {
71 // todo: take in account $locale.DATETIME_FORMATS.AMPMS;
72 if (this.mousewheel) {
73 }
74 if (this.arrowkeys) {
75 }
76 // this.setupInputEvents();
77 };
78 TimepickerComponent.prototype.writeValue = function (v) {
79 if (v === this.selected) {
80 return;
81 }
82 if (v && v instanceof Date) {
83 this.selected = v;
84 return;
85 }
86 this.selected = v ? new Date(v) : void 0;
87 };
88 TimepickerComponent.prototype.registerOnChange = function (fn) {
89 this.onChange = fn;
90 };
91 TimepickerComponent.prototype.registerOnTouched = function (fn) {
92 this.onTouched = fn;
93 };
94 TimepickerComponent.prototype.setDisabledState = function (isDisabled) {
95 this.readonlyInput = isDisabled;
96 };
97 TimepickerComponent.prototype.updateHours = function () {
98 if (this.readonlyInput) {
99 return;
100 }
101 var hours = this.getHoursFromTemplate();
102 var minutes = this.getMinutesFromTemplate();
103 this.invalidHours = !isDefined(hours);
104 this.invalidMinutes = !isDefined(minutes);
105 if (this.invalidHours || this.invalidMinutes) {
106 // TODO: needed a validation functionality.
107 return;
108 }
109 this.selected.setHours(hours);
110 this.invalidHours = (this.selected < this.min || this.selected > this.max);
111 if (this.invalidHours) {
112 // todo: validation?
113 // invalidate(true);
114 return;
115 }
116 else {
117 this.refresh();
118 }
119 };
120 TimepickerComponent.prototype.hoursOnBlur = function () {
121 if (this.readonlyInput) {
122 return;
123 }
124 // todo: binded with validation
125 if (!this.invalidHours && parseInt(this.hours, 10) < 10) {
126 this.hours = this.pad(this.hours);
127 }
128 };
129 TimepickerComponent.prototype.updateMinutes = function () {
130 if (this.readonlyInput) {
131 return;
132 }
133 var minutes = this.getMinutesFromTemplate();
134 var hours = this.getHoursFromTemplate();
135 this.invalidMinutes = !isDefined(minutes);
136 this.invalidHours = !isDefined(hours);
137 if (this.invalidMinutes || this.invalidHours) {
138 // TODO: needed a validation functionality.
139 return;
140 }
141 this.selected.setMinutes(minutes);
142 this.invalidMinutes = (this.selected < this.min || this.selected > this.max);
143 if (this.invalidMinutes) {
144 // todo: validation
145 // invalidate(undefined, true);
146 return;
147 }
148 else {
149 this.refresh();
150 }
151 };
152 TimepickerComponent.prototype.minutesOnBlur = function () {
153 if (this.readonlyInput) {
154 return;
155 }
156 if (!this.invalidMinutes && parseInt(this.minutes, 10) < 10) {
157 this.minutes = this.pad(this.minutes);
158 }
159 };
160 TimepickerComponent.prototype.incrementHours = function () {
161 if (!this.noIncrementHours()) {
162 this.addMinutesToSelected(this.hourStep * 60);
163 }
164 };
165 TimepickerComponent.prototype.decrementHours = function () {
166 if (!this.noDecrementHours()) {
167 this.addMinutesToSelected(-this.hourStep * 60);
168 }
169 };
170 TimepickerComponent.prototype.incrementMinutes = function () {
171 if (!this.noIncrementMinutes()) {
172 this.addMinutesToSelected(this.minuteStep);
173 }
174 };
175 TimepickerComponent.prototype.decrementMinutes = function () {
176 if (!this.noDecrementMinutes()) {
177 this.addMinutesToSelected(-this.minuteStep);
178 }
179 };
180 TimepickerComponent.prototype.noIncrementHours = function () {
181 var incrementedSelected = addMinutes(this.selected, this.hourStep * 60);
182 return incrementedSelected > this.max ||
183 (incrementedSelected < this.selected && incrementedSelected < this.min);
184 };
185 TimepickerComponent.prototype.noDecrementHours = function () {
186 var decrementedSelected = addMinutes(this.selected, -this.hourStep * 60);
187 return decrementedSelected < this.min ||
188 (decrementedSelected > this.selected && decrementedSelected > this.max);
189 };
190 TimepickerComponent.prototype.noIncrementMinutes = function () {
191 var incrementedSelected = addMinutes(this.selected, this.minuteStep);
192 return incrementedSelected > this.max ||
193 (incrementedSelected < this.selected && incrementedSelected < this.min);
194 };
195 TimepickerComponent.prototype.noDecrementMinutes = function () {
196 var decrementedSelected = addMinutes(this.selected, -this.minuteStep);
197 return decrementedSelected < this.min ||
198 (decrementedSelected > this.selected && decrementedSelected > this.max);
199 };
200 TimepickerComponent.prototype.toggleMeridian = function () {
201 if (!this.noToggleMeridian()) {
202 var sign = this.selected.getHours() < 12 ? 1 : -1;
203 this.addMinutesToSelected(12 * 60 * sign);
204 }
205 };
206 TimepickerComponent.prototype.noToggleMeridian = function () {
207 if (this.readonlyInput) {
208 return true;
209 }
210 if (this.selected.getHours() < 13) {
211 return addMinutes(this.selected, 12 * 60) > this.max;
212 }
213 else {
214 return addMinutes(this.selected, -12 * 60) < this.min;
215 }
216 };
217 TimepickerComponent.prototype.refresh = function () {
218 // this.makeValid();
219 this.updateTemplate();
220 this.onChange(this.selected);
221 };
222 TimepickerComponent.prototype.updateTemplate = function () {
223 var hours = this.selected.getHours();
224 var minutes = this.selected.getMinutes();
225 if (this.showMeridian) {
226 // Convert 24 to 12 hour system
227 hours = (hours === 0 || hours === 12) ? 12 : hours % 12;
228 }
229 // this.hours = keyboardChange === 'h' ? hours : this.pad(hours);
230 // if (keyboardChange !== 'm') {
231 // this.minutes = this.pad(minutes);
232 // }
233 this.hours = this.pad(hours);
234 this.minutes = this.pad(minutes);
235 if (!this.meridians) {
236 this.meridians = this.config.meridians;
237 }
238 this.meridian = this.selected.getHours() < 12
239 ? this.meridians[0]
240 : this.meridians[1];
241 };
242 TimepickerComponent.prototype.getHoursFromTemplate = function () {
243 var hours = parseInt(this.hours, 10);
244 var valid = this.showMeridian
245 ? (hours > 0 && hours < 13)
246 : (hours >= 0 && hours < 24);
247 if (!valid) {
248 return void 0;
249 }
250 if (this.showMeridian) {
251 if (hours === 12) {
252 hours = 0;
253 }
254 if (this.meridian === this.meridians[1]) {
255 hours = hours + 12;
256 }
257 }
258 return hours;
259 };
260 TimepickerComponent.prototype.getMinutesFromTemplate = function () {
261 var minutes = parseInt(this.minutes, 10);
262 return (minutes >= 0 && minutes < 60) ? minutes : undefined;
263 };
264 TimepickerComponent.prototype.pad = function (value) {
265 return (isDefined(value) && value.toString().length < 2)
266 ? '0' + value
267 : value.toString();
268 };
269 TimepickerComponent.prototype.addMinutesToSelected = function (minutes) {
270 this.selected = addMinutes(this.selected, minutes);
271 this.refresh();
272 };
273 TimepickerComponent.decorators = [
274 { type: Component, args: [{
275 selector: 'timepicker',
276 template: "\n <table>\n <tbody>\n <tr class=\"text-center\" [ngClass]=\"{hidden: !showSpinners || readonlyInput}\">\n <td><a (click)=\"incrementHours()\" [ngClass]=\"{disabled: noIncrementHours()}\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n <td>&nbsp;</td>\n <td><a (click)=\"incrementMinutes()\" [ngClass]=\"{disabled: noIncrementMinutes()}\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n <td [ngClass]=\"{hidden: !showMeridian}\" *ngIf=\"showMeridian\"></td>\n </tr>\n <tr>\n <td class=\"form-group\" [ngClass]=\"{'has-error': invalidHours}\">\n <input style=\"width:50px;\" type=\"text\" [(ngModel)]=\"hours\" (change)=\"updateHours()\" class=\"form-control text-center\" [readonly]=\"readonlyInput\" (blur)=\"hoursOnBlur()\" maxlength=\"2\">\n </td>\n <td>:</td>\n <td class=\"form-group\" [ngClass]=\"{'has-error': invalidMinutes}\">\n <input style=\"width:50px;\" type=\"text\" [(ngModel)]=\"minutes\" (change)=\"updateMinutes()\" class=\"form-control text-center\" [readonly]=\"readonlyInput\" (blur)=\"minutesOnBlur()\" maxlength=\"2\">\n </td>\n <td [ngClass]=\"{hidden: !showMeridian}\" *ngIf=\"showMeridian\"><button type=\"button\" [ngClass]=\"{disabled: noToggleMeridian() || readonlyInput}\" class=\"btn btn-default text-center\" (click)=\"toggleMeridian()\">{{meridian}}</button></td>\n </tr>\n <tr class=\"text-center\" [ngClass]=\"{hidden: !showSpinners || readonlyInput}\">\n <td><a (click)=\"decrementHours()\" [ngClass]=\"{disabled: noDecrementHours()}\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n <td>&nbsp;</td>\n <td><a (click)=\"decrementMinutes()\" [ngClass]=\"{disabled: noDecrementMinutes()}\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n <td [ngClass]=\"{hidden: !showMeridian}\" *ngIf=\"showMeridian\"></td>\n </tr>\n </tbody>\n </table>\n ",
277 providers: [TIMEPICKER_CONTROL_VALUE_ACCESSOR]
278 },] },
279 ];
280 /** @nocollapse */
281 TimepickerComponent.ctorParameters = function () { return [
282 { type: TimepickerConfig, },
283 ]; };
284 TimepickerComponent.propDecorators = {
285 'hourStep': [{ type: Input },],
286 'minuteStep': [{ type: Input },],
287 'readonlyInput': [{ type: Input },],
288 'mousewheel': [{ type: Input },],
289 'arrowkeys': [{ type: Input },],
290 'showSpinners': [{ type: Input },],
291 'min': [{ type: Input },],
292 'max': [{ type: Input },],
293 'meridians': [{ type: Input },],
294 'showMeridian': [{ type: Input },],
295 };
296 return TimepickerComponent;
297}());
298//# sourceMappingURL=timepicker.component.js.map
\No newline at end of file