jquery-timepicker-rails 0.1.0 → 0.2.0
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.
@@ -1,675 +1,687 @@
|
|
1
|
-
/************************
|
2
|
-
jquery-timepicker
|
3
|
-
http://jonthornton.github.com/jquery-timepicker/
|
4
|
-
|
5
|
-
requires jQuery 1.7+
|
6
|
-
************************/
|
7
|
-
|
8
|
-
|
9
|
-
(function (factory) {
|
10
|
-
if (typeof define === 'function' && define.amd) {
|
11
|
-
// AMD. Register as an anonymous module.
|
12
|
-
define(['jquery'], factory);
|
13
|
-
} else {
|
14
|
-
// Browser globals
|
15
|
-
factory(jQuery);
|
16
|
-
}
|
17
|
-
}(function ($) {
|
18
|
-
var _baseDate = _generateBaseDate();
|
19
|
-
var _ONE_DAY = 86400;
|
20
|
-
var
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
var
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
var
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
self.
|
89
|
-
self.
|
90
|
-
self.
|
91
|
-
|
92
|
-
self.
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
}
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
var
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
}
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
self.
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
self.
|
271
|
-
}
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
function
|
360
|
-
{
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
var
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
case
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
case
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
if (
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
}
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
}
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
}
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
1
|
+
/************************
|
2
|
+
jquery-timepicker
|
3
|
+
http://jonthornton.github.com/jquery-timepicker/
|
4
|
+
|
5
|
+
requires jQuery 1.7+
|
6
|
+
************************/
|
7
|
+
|
8
|
+
|
9
|
+
(function (factory) {
|
10
|
+
if (typeof define === 'function' && define.amd) {
|
11
|
+
// AMD. Register as an anonymous module.
|
12
|
+
define(['jquery'], factory);
|
13
|
+
} else {
|
14
|
+
// Browser globals
|
15
|
+
factory(jQuery);
|
16
|
+
}
|
17
|
+
}(function ($) {
|
18
|
+
var _baseDate = _generateBaseDate();
|
19
|
+
var _ONE_DAY = 86400;
|
20
|
+
var _defaults = {
|
21
|
+
className: null,
|
22
|
+
minTime: null,
|
23
|
+
maxTime: null,
|
24
|
+
durationTime: null,
|
25
|
+
step: 30,
|
26
|
+
showDuration: false,
|
27
|
+
timeFormat: 'g:ia',
|
28
|
+
scrollDefaultNow: false,
|
29
|
+
scrollDefaultTime: false,
|
30
|
+
selectOnBlur: false,
|
31
|
+
forceRoundTime: false,
|
32
|
+
appendTo: 'body'
|
33
|
+
};
|
34
|
+
var _lang = {
|
35
|
+
decimal: '.',
|
36
|
+
mins: 'mins',
|
37
|
+
hr: 'hr',
|
38
|
+
hrs: 'hrs'
|
39
|
+
};
|
40
|
+
|
41
|
+
var methods =
|
42
|
+
{
|
43
|
+
init: function(options)
|
44
|
+
{
|
45
|
+
return this.each(function()
|
46
|
+
{
|
47
|
+
var self = $(this);
|
48
|
+
|
49
|
+
// convert dropdowns to text input
|
50
|
+
if (self[0].tagName == 'SELECT') {
|
51
|
+
var attrs = { 'type': 'text', 'value': self.val() };
|
52
|
+
var raw_attrs = self[0].attributes;
|
53
|
+
|
54
|
+
for (var i=0; i < raw_attrs.length; i++) {
|
55
|
+
attrs[raw_attrs[i].nodeName] = raw_attrs[i].nodeValue;
|
56
|
+
}
|
57
|
+
|
58
|
+
var input = $('<input />', attrs);
|
59
|
+
self.replaceWith(input);
|
60
|
+
self = input;
|
61
|
+
}
|
62
|
+
|
63
|
+
var settings = $.extend({}, _defaults);
|
64
|
+
|
65
|
+
if (options) {
|
66
|
+
settings = $.extend(settings, options);
|
67
|
+
}
|
68
|
+
|
69
|
+
if (settings.minTime) {
|
70
|
+
settings.minTime = _time2int(settings.minTime);
|
71
|
+
}
|
72
|
+
|
73
|
+
if (settings.maxTime) {
|
74
|
+
settings.maxTime = _time2int(settings.maxTime);
|
75
|
+
}
|
76
|
+
|
77
|
+
if (settings.durationTime) {
|
78
|
+
settings.durationTime = _time2int(settings.durationTime);
|
79
|
+
}
|
80
|
+
|
81
|
+
if (settings.lang) {
|
82
|
+
_lang = $.extend(_lang, settings.lang);
|
83
|
+
}
|
84
|
+
|
85
|
+
self.data('timepicker-settings', settings);
|
86
|
+
self.prop('autocomplete', 'off');
|
87
|
+
self.on('click.timepicker focus.timepicker', methods.show);
|
88
|
+
self.on('blur.timepicker', _formatValue);
|
89
|
+
self.on('keydown.timepicker', _keyhandler);
|
90
|
+
self.addClass('ui-timepicker-input');
|
91
|
+
|
92
|
+
_formatValue.call(self.get(0));
|
93
|
+
});
|
94
|
+
},
|
95
|
+
|
96
|
+
show: function(e)
|
97
|
+
{
|
98
|
+
var self = $(this);
|
99
|
+
|
100
|
+
if ('ontouchstart' in document) {
|
101
|
+
// block the keyboard on mobile devices
|
102
|
+
self.blur();
|
103
|
+
}
|
104
|
+
|
105
|
+
var list = self.data('timepicker-list');
|
106
|
+
|
107
|
+
// check if input is readonly
|
108
|
+
if (self.prop('readonly')) {
|
109
|
+
return;
|
110
|
+
}
|
111
|
+
|
112
|
+
// check if list needs to be rendered
|
113
|
+
if (!list || list.length === 0) {
|
114
|
+
_render(self);
|
115
|
+
list = self.data('timepicker-list');
|
116
|
+
}
|
117
|
+
|
118
|
+
// check if a flag was set to close this picker
|
119
|
+
if (self.hasClass('ui-timepicker-hideme')) {
|
120
|
+
self.removeClass('ui-timepicker-hideme');
|
121
|
+
list.hide();
|
122
|
+
return;
|
123
|
+
}
|
124
|
+
|
125
|
+
if (list.is(':visible')) {
|
126
|
+
return;
|
127
|
+
}
|
128
|
+
|
129
|
+
// make sure other pickers are hidden
|
130
|
+
methods.hide();
|
131
|
+
|
132
|
+
if ((self.offset().top + self.outerHeight(true) + list.outerHeight()) > $(window).height() + $(window).scrollTop()) {
|
133
|
+
// position the dropdown on top
|
134
|
+
list.css({ 'left':(self.offset().left), 'top': self.offset().top - list.outerHeight() });
|
135
|
+
} else {
|
136
|
+
// put it under the input
|
137
|
+
list.css({ 'left':(self.offset().left), 'top': self.offset().top + self.outerHeight() });
|
138
|
+
}
|
139
|
+
|
140
|
+
list.show();
|
141
|
+
|
142
|
+
var settings = self.data('timepicker-settings');
|
143
|
+
// position scrolling
|
144
|
+
var selected = list.find('.ui-timepicker-selected');
|
145
|
+
|
146
|
+
if (!selected.length) {
|
147
|
+
if (self.val()) {
|
148
|
+
selected = _findRow(self, list, _time2int(self.val()));
|
149
|
+
} else if (settings.scrollDefaultNow) {
|
150
|
+
selected = _findRow(self, list, _time2int(new Date()));
|
151
|
+
} else if (settings.scrollDefaultTime !== false) {
|
152
|
+
selected = _findRow(self, list, _time2int(settings.scrollDefaultTime));
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
if (selected && selected.length) {
|
157
|
+
var topOffset = list.scrollTop() + selected.position().top - selected.outerHeight();
|
158
|
+
list.scrollTop(topOffset);
|
159
|
+
} else {
|
160
|
+
list.scrollTop(0);
|
161
|
+
}
|
162
|
+
|
163
|
+
_attachCloseHandler();
|
164
|
+
|
165
|
+
self.trigger('showTimepicker');
|
166
|
+
},
|
167
|
+
|
168
|
+
hide: function(e)
|
169
|
+
{
|
170
|
+
$('.ui-timepicker-list:visible').each(function() {
|
171
|
+
var list = $(this);
|
172
|
+
var self = list.data('timepicker-input');
|
173
|
+
var settings = self.data('timepicker-settings');
|
174
|
+
|
175
|
+
if (settings && settings.selectOnBlur) {
|
176
|
+
_selectValue(self);
|
177
|
+
}
|
178
|
+
|
179
|
+
list.hide();
|
180
|
+
self.trigger('hideTimepicker');
|
181
|
+
});
|
182
|
+
},
|
183
|
+
|
184
|
+
option: function(key, value)
|
185
|
+
{
|
186
|
+
var self = $(this);
|
187
|
+
var settings = self.data('timepicker-settings');
|
188
|
+
var list = self.data('timepicker-list');
|
189
|
+
|
190
|
+
if (typeof key == 'object') {
|
191
|
+
settings = $.extend(settings, key);
|
192
|
+
|
193
|
+
} else if (typeof key == 'string' && typeof value != 'undefined') {
|
194
|
+
settings[key] = value;
|
195
|
+
|
196
|
+
} else if (typeof key == 'string') {
|
197
|
+
return settings[key];
|
198
|
+
}
|
199
|
+
|
200
|
+
if (settings.minTime) {
|
201
|
+
settings.minTime = _time2int(settings.minTime);
|
202
|
+
}
|
203
|
+
|
204
|
+
if (settings.maxTime) {
|
205
|
+
settings.maxTime = _time2int(settings.maxTime);
|
206
|
+
}
|
207
|
+
|
208
|
+
if (settings.durationTime) {
|
209
|
+
settings.durationTime = _time2int(settings.durationTime);
|
210
|
+
}
|
211
|
+
|
212
|
+
self.data('timepicker-settings', settings);
|
213
|
+
|
214
|
+
if (list) {
|
215
|
+
list.remove();
|
216
|
+
self.data('timepicker-list', false);
|
217
|
+
}
|
218
|
+
|
219
|
+
},
|
220
|
+
|
221
|
+
getSecondsFromMidnight: function()
|
222
|
+
{
|
223
|
+
return _time2int($(this).val());
|
224
|
+
},
|
225
|
+
|
226
|
+
getTime: function()
|
227
|
+
{
|
228
|
+
return new Date(_baseDate.valueOf() + (_time2int($(this).val())*1000));
|
229
|
+
},
|
230
|
+
|
231
|
+
setTime: function(value)
|
232
|
+
{
|
233
|
+
var self = $(this);
|
234
|
+
var prettyTime = _int2time(_time2int(value), self.data('timepicker-settings').timeFormat);
|
235
|
+
self.val(prettyTime);
|
236
|
+
},
|
237
|
+
|
238
|
+
remove: function()
|
239
|
+
{
|
240
|
+
var self = $(this);
|
241
|
+
|
242
|
+
// check if this element is a timepicker
|
243
|
+
if (!self.hasClass('ui-timepicker-input')) {
|
244
|
+
return;
|
245
|
+
}
|
246
|
+
|
247
|
+
self.removeAttr('autocomplete', 'off');
|
248
|
+
self.removeClass('ui-timepicker-input');
|
249
|
+
self.removeData('timepicker-settings');
|
250
|
+
self.off('.timepicker');
|
251
|
+
|
252
|
+
// timepicker-list won't be present unless the user has interacted with this timepicker
|
253
|
+
if (self.data('timepicker-list')) {
|
254
|
+
self.data('timepicker-list').remove();
|
255
|
+
}
|
256
|
+
|
257
|
+
self.removeData('timepicker-list');
|
258
|
+
}
|
259
|
+
};
|
260
|
+
|
261
|
+
// private methods
|
262
|
+
|
263
|
+
function _render(self)
|
264
|
+
{
|
265
|
+
var settings = self.data('timepicker-settings');
|
266
|
+
var list = self.data('timepicker-list');
|
267
|
+
|
268
|
+
if (list && list.length) {
|
269
|
+
list.remove();
|
270
|
+
self.data('timepicker-list', false);
|
271
|
+
}
|
272
|
+
|
273
|
+
list = $('<ul />', {
|
274
|
+
'tabindex': -1,
|
275
|
+
'class': 'ui-timepicker-list'
|
276
|
+
});
|
277
|
+
|
278
|
+
if (settings.className) {
|
279
|
+
list.addClass(settings.className);
|
280
|
+
}
|
281
|
+
|
282
|
+
list.css({'display':'none', 'position': 'absolute' });
|
283
|
+
|
284
|
+
if ((settings.minTime !== null || settings.durationTime !== null) && settings.showDuration) {
|
285
|
+
list.addClass('ui-timepicker-with-duration');
|
286
|
+
}
|
287
|
+
|
288
|
+
var durStart = (settings.durationTime !== null) ? settings.durationTime : settings.minTime;
|
289
|
+
var start = (settings.minTime !== null) ? settings.minTime : 0;
|
290
|
+
var end = (settings.maxTime !== null) ? settings.maxTime : (start + _ONE_DAY - 1);
|
291
|
+
|
292
|
+
if (end <= start) {
|
293
|
+
// make sure the end time is greater than start time, otherwise there will be no list to show
|
294
|
+
end += _ONE_DAY;
|
295
|
+
}
|
296
|
+
|
297
|
+
for (var i=start; i <= end; i += settings.step*60) {
|
298
|
+
var timeInt = i%_ONE_DAY;
|
299
|
+
var row = $('<li />');
|
300
|
+
row.data('time', timeInt);
|
301
|
+
row.text(_int2time(timeInt, settings.timeFormat));
|
302
|
+
|
303
|
+
if ((settings.minTime !== null || settings.durationTime !== null) && settings.showDuration) {
|
304
|
+
var duration = $('<span />');
|
305
|
+
duration.addClass('ui-timepicker-duration');
|
306
|
+
duration.text(' ('+_int2duration(i - durStart)+')');
|
307
|
+
row.append(duration);
|
308
|
+
}
|
309
|
+
|
310
|
+
list.append(row);
|
311
|
+
}
|
312
|
+
|
313
|
+
list.data('timepicker-input', self);
|
314
|
+
self.data('timepicker-list', list);
|
315
|
+
|
316
|
+
var appendTo = settings.appendTo;
|
317
|
+
if (typeof appendTo === 'string') {
|
318
|
+
appendTo = $(appendTo);
|
319
|
+
} else if (typeof appendTo === 'function') {
|
320
|
+
appendTo = appendTo(self);
|
321
|
+
}
|
322
|
+
appendTo.append(list);
|
323
|
+
_setSelected(self, list);
|
324
|
+
|
325
|
+
list.on('click', 'li', function(e) {
|
326
|
+
self.addClass('ui-timepicker-hideme');
|
327
|
+
self[0].focus();
|
328
|
+
|
329
|
+
// make sure only the clicked row is selected
|
330
|
+
list.find('li').removeClass('ui-timepicker-selected');
|
331
|
+
$(this).addClass('ui-timepicker-selected');
|
332
|
+
|
333
|
+
_selectValue(self);
|
334
|
+
list.hide();
|
335
|
+
});
|
336
|
+
}
|
337
|
+
|
338
|
+
function _generateBaseDate()
|
339
|
+
{
|
340
|
+
var _baseDate = new Date();
|
341
|
+
var _currentTimezoneOffset = _baseDate.getTimezoneOffset()*60000;
|
342
|
+
_baseDate.setHours(0); _baseDate.setMinutes(0); _baseDate.setSeconds(0);
|
343
|
+
var _baseDateTimezoneOffset = _baseDate.getTimezoneOffset()*60000;
|
344
|
+
|
345
|
+
return new Date(_baseDate.valueOf() - _baseDateTimezoneOffset + _currentTimezoneOffset);
|
346
|
+
}
|
347
|
+
|
348
|
+
function _attachCloseHandler()
|
349
|
+
{
|
350
|
+
if ('ontouchstart' in document) {
|
351
|
+
$('body').on('touchstart.ui-timepicker', _closeHandler);
|
352
|
+
} else {
|
353
|
+
$('body').on('mousedown.ui-timepicker', _closeHandler);
|
354
|
+
$(window).on('scroll.ui-timepicker', _closeHandler);
|
355
|
+
}
|
356
|
+
}
|
357
|
+
|
358
|
+
// event handler to decide whether to close timepicker
|
359
|
+
function _closeHandler(e)
|
360
|
+
{
|
361
|
+
var target = $(e.target);
|
362
|
+
var input = target.closest('.ui-timepicker-input');
|
363
|
+
if (input.length === 0 && target.closest('.ui-timepicker-list').length === 0) {
|
364
|
+
methods.hide();
|
365
|
+
}
|
366
|
+
|
367
|
+
$('body').unbind('.ui-timepicker');
|
368
|
+
$(window).unbind('.ui-timepicker');
|
369
|
+
}
|
370
|
+
|
371
|
+
function _findRow(self, list, value)
|
372
|
+
{
|
373
|
+
if (!value && value !== 0) {
|
374
|
+
return false;
|
375
|
+
}
|
376
|
+
|
377
|
+
var settings = self.data('timepicker-settings');
|
378
|
+
var out = false;
|
379
|
+
var halfStep = settings.step*30;
|
380
|
+
|
381
|
+
// loop through the menu items
|
382
|
+
list.find('li').each(function(i, obj) {
|
383
|
+
var jObj = $(obj);
|
384
|
+
|
385
|
+
var offset = jObj.data('time') - value;
|
386
|
+
|
387
|
+
// check if the value is less than half a step from each row
|
388
|
+
if (Math.abs(offset) < halfStep || offset == halfStep) {
|
389
|
+
out = jObj;
|
390
|
+
return false;
|
391
|
+
}
|
392
|
+
});
|
393
|
+
|
394
|
+
return out;
|
395
|
+
}
|
396
|
+
|
397
|
+
function _setSelected(self, list)
|
398
|
+
{
|
399
|
+
var timeValue = _time2int(self.val());
|
400
|
+
|
401
|
+
var selected = _findRow(self, list, timeValue);
|
402
|
+
if (selected) selected.addClass('ui-timepicker-selected');
|
403
|
+
}
|
404
|
+
|
405
|
+
|
406
|
+
function _formatValue()
|
407
|
+
{
|
408
|
+
if (this.value === '') {
|
409
|
+
return;
|
410
|
+
}
|
411
|
+
|
412
|
+
var self = $(this);
|
413
|
+
var seconds = _time2int(this.value);
|
414
|
+
|
415
|
+
if (seconds === null) {
|
416
|
+
self.trigger('timeFormatError');
|
417
|
+
return;
|
418
|
+
}
|
419
|
+
|
420
|
+
var settings = self.data('timepicker-settings');
|
421
|
+
|
422
|
+
if (settings.forceRoundTime) {
|
423
|
+
var offset = seconds % (settings.step*60); // step is in minutes
|
424
|
+
|
425
|
+
if (offset >= settings.step*30) {
|
426
|
+
// if offset is larger than a half step, round up
|
427
|
+
seconds += (settings.step*60) - offset;
|
428
|
+
} else {
|
429
|
+
// round down
|
430
|
+
seconds -= offset;
|
431
|
+
}
|
432
|
+
}
|
433
|
+
|
434
|
+
var prettyTime = _int2time(seconds, settings.timeFormat);
|
435
|
+
self.val(prettyTime);
|
436
|
+
}
|
437
|
+
|
438
|
+
function _keyhandler(e)
|
439
|
+
{
|
440
|
+
var self = $(this);
|
441
|
+
var list = self.data('timepicker-list');
|
442
|
+
|
443
|
+
if (!list.is(':visible')) {
|
444
|
+
if (e.keyCode == 40) {
|
445
|
+
self.focus();
|
446
|
+
} else {
|
447
|
+
return true;
|
448
|
+
}
|
449
|
+
}
|
450
|
+
|
451
|
+
switch (e.keyCode) {
|
452
|
+
|
453
|
+
case 13: // return
|
454
|
+
_selectValue(self);
|
455
|
+
methods.hide.apply(this);
|
456
|
+
e.preventDefault();
|
457
|
+
return false;
|
458
|
+
|
459
|
+
case 38: // up
|
460
|
+
var selected = list.find('.ui-timepicker-selected');
|
461
|
+
|
462
|
+
if (!selected.length) {
|
463
|
+
list.children().each(function(i, obj) {
|
464
|
+
if ($(obj).position().top > 0) {
|
465
|
+
selected = $(obj);
|
466
|
+
return false;
|
467
|
+
}
|
468
|
+
});
|
469
|
+
selected.addClass('ui-timepicker-selected');
|
470
|
+
|
471
|
+
} else if (!selected.is(':first-child')) {
|
472
|
+
selected.removeClass('ui-timepicker-selected');
|
473
|
+
selected.prev().addClass('ui-timepicker-selected');
|
474
|
+
|
475
|
+
if (selected.prev().position().top < selected.outerHeight()) {
|
476
|
+
list.scrollTop(list.scrollTop() - selected.outerHeight());
|
477
|
+
}
|
478
|
+
}
|
479
|
+
|
480
|
+
break;
|
481
|
+
|
482
|
+
case 40: // down
|
483
|
+
selected = list.find('.ui-timepicker-selected');
|
484
|
+
|
485
|
+
if (selected.length === 0) {
|
486
|
+
list.children().each(function(i, obj) {
|
487
|
+
if ($(obj).position().top > 0) {
|
488
|
+
selected = $(obj);
|
489
|
+
return false;
|
490
|
+
}
|
491
|
+
});
|
492
|
+
|
493
|
+
selected.addClass('ui-timepicker-selected');
|
494
|
+
} else if (!selected.is(':last-child')) {
|
495
|
+
selected.removeClass('ui-timepicker-selected');
|
496
|
+
selected.next().addClass('ui-timepicker-selected');
|
497
|
+
|
498
|
+
if (selected.next().position().top + 2*selected.outerHeight() > list.outerHeight()) {
|
499
|
+
list.scrollTop(list.scrollTop() + selected.outerHeight());
|
500
|
+
}
|
501
|
+
}
|
502
|
+
|
503
|
+
break;
|
504
|
+
|
505
|
+
case 27: // escape
|
506
|
+
list.find('li').removeClass('ui-timepicker-selected');
|
507
|
+
list.hide();
|
508
|
+
break;
|
509
|
+
|
510
|
+
case 9: //tab
|
511
|
+
methods.hide();
|
512
|
+
break;
|
513
|
+
|
514
|
+
case 16:
|
515
|
+
case 17:
|
516
|
+
case 18:
|
517
|
+
case 19:
|
518
|
+
case 20:
|
519
|
+
case 33:
|
520
|
+
case 34:
|
521
|
+
case 35:
|
522
|
+
case 36:
|
523
|
+
case 37:
|
524
|
+
case 39:
|
525
|
+
case 45:
|
526
|
+
return;
|
527
|
+
|
528
|
+
default:
|
529
|
+
list.find('li').removeClass('ui-timepicker-selected');
|
530
|
+
return;
|
531
|
+
}
|
532
|
+
}
|
533
|
+
|
534
|
+
function _selectValue(self)
|
535
|
+
{
|
536
|
+
var settings = self.data('timepicker-settings');
|
537
|
+
var list = self.data('timepicker-list');
|
538
|
+
var timeValue = null;
|
539
|
+
|
540
|
+
var cursor = list.find('.ui-timepicker-selected');
|
541
|
+
|
542
|
+
if (cursor.length) {
|
543
|
+
// selected value found
|
544
|
+
timeValue = cursor.data('time');
|
545
|
+
|
546
|
+
} else if (self.val()) {
|
547
|
+
|
548
|
+
// no selected value; fall back on input value
|
549
|
+
timeValue = _time2int(self.val());
|
550
|
+
|
551
|
+
_setSelected(self, list);
|
552
|
+
}
|
553
|
+
|
554
|
+
if (timeValue !== null) {
|
555
|
+
var timeString = _int2time(timeValue, settings.timeFormat);
|
556
|
+
self.val(timeString);
|
557
|
+
}
|
558
|
+
|
559
|
+
self.trigger('change').trigger('changeTime');
|
560
|
+
}
|
561
|
+
|
562
|
+
function _int2duration(seconds)
|
563
|
+
{
|
564
|
+
var minutes = Math.round(seconds/60);
|
565
|
+
var duration;
|
566
|
+
|
567
|
+
if (Math.abs(minutes) < 60) {
|
568
|
+
duration = [minutes, _lang.mins];
|
569
|
+
} else if (minutes == 60) {
|
570
|
+
duration = ['1', _lang.hr];
|
571
|
+
} else {
|
572
|
+
var hours = (minutes/60).toFixed(1);
|
573
|
+
if (_lang.decimal != '.') hours = hours.replace('.', _lang.decimal);
|
574
|
+
duration = [hours, _lang.hrs];
|
575
|
+
}
|
576
|
+
|
577
|
+
return duration.join(' ');
|
578
|
+
}
|
579
|
+
|
580
|
+
function _int2time(seconds, format)
|
581
|
+
{
|
582
|
+
if (seconds === null) {
|
583
|
+
return;
|
584
|
+
}
|
585
|
+
|
586
|
+
var time = new Date(_baseDate.valueOf() + (seconds*1000));
|
587
|
+
var output = '';
|
588
|
+
var hour, code;
|
589
|
+
|
590
|
+
for (var i=0; i<format.length; i++) {
|
591
|
+
|
592
|
+
code = format.charAt(i);
|
593
|
+
switch (code) {
|
594
|
+
|
595
|
+
case 'a':
|
596
|
+
output += (time.getHours() > 11) ? 'pm' : 'am';
|
597
|
+
break;
|
598
|
+
|
599
|
+
case 'A':
|
600
|
+
output += (time.getHours() > 11) ? 'PM' : 'AM';
|
601
|
+
break;
|
602
|
+
|
603
|
+
case 'g':
|
604
|
+
hour = time.getHours() % 12;
|
605
|
+
output += (hour === 0) ? '12' : hour;
|
606
|
+
break;
|
607
|
+
|
608
|
+
case 'G':
|
609
|
+
output += time.getHours();
|
610
|
+
break;
|
611
|
+
|
612
|
+
case 'h':
|
613
|
+
hour = time.getHours() % 12;
|
614
|
+
|
615
|
+
if (hour !== 0 && hour < 10) {
|
616
|
+
hour = '0'+hour;
|
617
|
+
}
|
618
|
+
|
619
|
+
output += (hour === 0) ? '12' : hour;
|
620
|
+
break;
|
621
|
+
|
622
|
+
case 'H':
|
623
|
+
hour = time.getHours();
|
624
|
+
output += (hour > 9) ? hour : '0'+hour;
|
625
|
+
break;
|
626
|
+
|
627
|
+
case 'i':
|
628
|
+
var minutes = time.getMinutes();
|
629
|
+
output += (minutes > 9) ? minutes : '0'+minutes;
|
630
|
+
break;
|
631
|
+
|
632
|
+
case 's':
|
633
|
+
seconds = time.getSeconds();
|
634
|
+
output += (seconds > 9) ? seconds : '0'+seconds;
|
635
|
+
break;
|
636
|
+
|
637
|
+
default:
|
638
|
+
output += code;
|
639
|
+
}
|
640
|
+
}
|
641
|
+
|
642
|
+
return output;
|
643
|
+
}
|
644
|
+
|
645
|
+
function _time2int(timeString)
|
646
|
+
{
|
647
|
+
if (timeString === '') return null;
|
648
|
+
if (timeString+0 == timeString) return timeString;
|
649
|
+
|
650
|
+
if (typeof(timeString) == 'object') {
|
651
|
+
timeString = timeString.getHours()+':'+timeString.getMinutes()+':'+timeString.getSeconds();
|
652
|
+
}
|
653
|
+
|
654
|
+
var d = new Date(0);
|
655
|
+
var time = timeString.toLowerCase().match(/(\d{1,2})(?::(\d{1,2}))?(?::(\d{2}))?\s*([pa]?)/);
|
656
|
+
|
657
|
+
if (!time) {
|
658
|
+
return null;
|
659
|
+
}
|
660
|
+
|
661
|
+
var hour = parseInt(time[1]*1, 10);
|
662
|
+
var hours;
|
663
|
+
|
664
|
+
if (time[4]) {
|
665
|
+
if (hour == 12) {
|
666
|
+
hours = (time[4] == 'p') ? 12 : 0;
|
667
|
+
} else {
|
668
|
+
hours = (hour + (time[4] == 'p' ? 12 : 0));
|
669
|
+
}
|
670
|
+
|
671
|
+
} else {
|
672
|
+
hours = hour;
|
673
|
+
}
|
674
|
+
|
675
|
+
var minutes = ( time[2]*1 || 0 );
|
676
|
+
var seconds = ( time[3]*1 || 0 );
|
677
|
+
return hours*3600 + minutes*60 + seconds;
|
678
|
+
}
|
679
|
+
|
680
|
+
// Plugin entry
|
681
|
+
$.fn.timepicker = function(method)
|
682
|
+
{
|
683
|
+
if(methods[method]) { return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); }
|
684
|
+
else if(typeof method === "object" || !method) { return methods.init.apply(this, arguments); }
|
685
|
+
else { $.error("Method "+ method + " does not exist on jQuery.timepicker"); }
|
686
|
+
};
|
687
|
+
}));
|