bootstrap-timepicker-rails-addon 0.1.1.2 → 0.2.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -26,14 +26,14 @@ Or install it yourself as:
26
26
 
27
27
  ## Usage
28
28
 
29
- Add this line to app/assets/stylesheets/application.css
30
-
31
- *= require bootstrap-timepicker
32
-
33
29
  Add this line to app/assets/javascripts/application.js
34
30
 
35
31
  //= require bootstrap-timepicker
36
32
 
33
+ Add this line to app/assets/stylesheets/application.css
34
+
35
+ *= require bootstrap-timepicker
36
+
37
37
  Just call timepicker() with any selector in view.
38
38
 
39
39
  ```javascript
@@ -2,7 +2,7 @@ module Bootstrap
2
2
  module Timepicker
3
3
  module Rails
4
4
  module Addon
5
- VERSION = "0.1.1.2"
5
+ VERSION = "0.2.3.1"
6
6
  end
7
7
  end
8
8
  end
@@ -1,883 +1,888 @@
1
- /*!
2
- * Timepicker Component for Twitter Bootstrap
3
- *
4
- * Copyright 2013 Joris de Wit
5
- *
6
- * Contributors https://github.com/jdewit/bootstrap-timepicker/graphs/contributors
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- ;(function($, window, document, undefined) {
12
-
13
- 'use strict'; // jshint ;_;
14
-
15
- // TIMEPICKER PUBLIC CLASS DEFINITION
16
- var Timepicker = function(element, options) {
17
- this.widget = '';
18
- this.$element = $(element);
19
- this.defaultTime = options.defaultTime;
20
- this.disableFocus = options.disableFocus;
21
- this.isOpen = options.isOpen;
22
- this.minuteStep = options.minuteStep;
23
- this.modalBackdrop = options.modalBackdrop;
24
- this.secondStep = options.secondStep;
25
- this.showInputs = options.showInputs;
26
- this.showMeridian = options.showMeridian;
27
- this.showSeconds = options.showSeconds;
28
- this.template = options.template;
29
- this.appendWidgetTo = options.appendWidgetTo;
30
-
31
- this._init();
32
- };
33
-
34
- Timepicker.prototype = {
35
-
36
- constructor: Timepicker,
37
-
38
- _init: function() {
39
- var self = this;
40
-
41
- if (this.$element.parent().hasClass('input-append') || this.$element.parent().hasClass('input-prepend')) {
42
- this.$element.parent('.input-append, .input-prepend').find('.add-on').on({
43
- 'click.timepicker': $.proxy(this.showWidget, this)
44
- });
45
- this.$element.on({
46
- 'focus.timepicker': $.proxy(this.highlightUnit, this),
47
- 'click.timepicker': $.proxy(this.highlightUnit, this),
48
- 'keydown.timepicker': $.proxy(this.elementKeydown, this),
49
- 'blur.timepicker': $.proxy(this.blurElement, this)
50
- });
51
- } else {
52
- if (this.template) {
53
- this.$element.on({
54
- 'focus.timepicker': $.proxy(this.showWidget, this),
55
- 'click.timepicker': $.proxy(this.showWidget, this),
56
- 'blur.timepicker': $.proxy(this.blurElement, this)
57
- });
58
- } else {
59
- this.$element.on({
60
- 'focus.timepicker': $.proxy(this.highlightUnit, this),
61
- 'click.timepicker': $.proxy(this.highlightUnit, this),
62
- 'keydown.timepicker': $.proxy(this.elementKeydown, this),
63
- 'blur.timepicker': $.proxy(this.blurElement, this)
64
- });
65
- }
66
- }
67
-
68
- if (this.template !== false) {
69
- this.$widget = $(this.getTemplate()).prependTo(this.$element.parents(this.appendWidgetTo)).on('click', $.proxy(this.widgetClick, this));
70
- } else {
71
- this.$widget = false;
72
- }
73
-
74
- if (this.showInputs && this.$widget !== false) {
75
- this.$widget.find('input').each(function() {
76
- $(this).on({
77
- 'click.timepicker': function() { $(this).select(); },
78
- 'keydown.timepicker': $.proxy(self.widgetKeydown, self)
79
- });
80
- });
81
- }
82
-
83
- this.setDefaultTime(this.defaultTime);
84
- },
85
-
86
- blurElement: function() {
87
- this.highlightedUnit = undefined;
88
- this.updateFromElementVal();
89
- },
90
-
91
- decrementHour: function() {
92
- if (this.showMeridian) {
93
- if (this.hour === 1) {
94
- this.hour = 12;
95
- } else if (this.hour === 12) {
96
- this.hour--;
97
-
98
- return this.toggleMeridian();
99
- } else if (this.hour === 0) {
100
- this.hour = 11;
101
-
102
- return this.toggleMeridian();
103
- } else {
104
- this.hour--;
105
- }
106
- } else {
107
- if (this.hour === 0) {
108
- this.hour = 23;
109
- } else {
110
- this.hour--;
111
- }
112
- }
113
- this.update();
114
- },
115
-
116
- decrementMinute: function(step) {
117
- var newVal;
118
-
119
- if (step) {
120
- newVal = this.minute - step;
121
- } else {
122
- newVal = this.minute - this.minuteStep;
123
- }
124
-
125
- if (newVal < 0) {
126
- this.decrementHour();
127
- this.minute = newVal + 60;
128
- } else {
129
- this.minute = newVal;
130
- }
131
- this.update();
132
- },
133
-
134
- decrementSecond: function() {
135
- var newVal = this.second - this.secondStep;
136
-
137
- if (newVal < 0) {
138
- this.decrementMinute(true);
139
- this.second = newVal + 60;
140
- } else {
141
- this.second = newVal;
142
- }
143
- this.update();
144
- },
145
-
146
- elementKeydown: function(e) {
147
- switch (e.keyCode) {
148
- case 9: //tab
149
- this.updateFromElementVal();
150
-
151
- switch (this.highlightedUnit) {
152
- case 'hour':
153
- e.preventDefault();
154
- this.highlightNextUnit();
155
- break;
156
- case 'minute':
157
- if (this.showMeridian || this.showSeconds) {
158
- e.preventDefault();
159
- this.highlightNextUnit();
160
- }
161
- break;
162
- case 'second':
163
- if (this.showMeridian) {
164
- e.preventDefault();
165
- this.highlightNextUnit();
166
- }
167
- break;
168
- }
169
- break;
170
- case 27: // escape
171
- this.updateFromElementVal();
172
- break;
173
- case 37: // left arrow
174
- e.preventDefault();
175
- this.highlightPrevUnit();
176
- this.updateFromElementVal();
177
- break;
178
- case 38: // up arrow
179
- e.preventDefault();
180
- switch (this.highlightedUnit) {
181
- case 'hour':
182
- this.incrementHour();
183
- this.highlightHour();
184
- break;
185
- case 'minute':
186
- this.incrementMinute();
187
- this.highlightMinute();
188
- break;
189
- case 'second':
190
- this.incrementSecond();
191
- this.highlightSecond();
192
- break;
193
- case 'meridian':
194
- this.toggleMeridian();
195
- this.highlightMeridian();
196
- break;
197
- }
198
- break;
199
- case 39: // right arrow
200
- e.preventDefault();
201
- this.updateFromElementVal();
202
- this.highlightNextUnit();
203
- break;
204
- case 40: // down arrow
205
- e.preventDefault();
206
- switch (this.highlightedUnit) {
207
- case 'hour':
208
- this.decrementHour();
209
- this.highlightHour();
210
- break;
211
- case 'minute':
212
- this.decrementMinute();
213
- this.highlightMinute();
214
- break;
215
- case 'second':
216
- this.decrementSecond();
217
- this.highlightSecond();
218
- break;
219
- case 'meridian':
220
- this.toggleMeridian();
221
- this.highlightMeridian();
222
- break;
223
- }
224
- break;
225
- }
226
- },
227
-
228
- formatTime: function(hour, minute, second, meridian) {
229
- hour = hour < 10 ? '0' + hour : hour;
230
- minute = minute < 10 ? '0' + minute : minute;
231
- second = second < 10 ? '0' + second : second;
232
-
233
- return hour + ':' + minute + (this.showSeconds ? ':' + second : '') + (this.showMeridian ? ' ' + meridian : '');
234
- },
235
-
236
- getCursorPosition: function() {
237
- var input = this.$element.get(0);
238
-
239
- if ('selectionStart' in input) {// Standard-compliant browsers
240
-
241
- return input.selectionStart;
242
- } else if (document.selection) {// IE fix
243
- input.focus();
244
- var sel = document.selection.createRange(),
245
- selLen = document.selection.createRange().text.length;
246
-
247
- sel.moveStart('character', - input.value.length);
248
-
249
- return sel.text.length - selLen;
250
- }
251
- },
252
-
253
- getTemplate: function() {
254
- var template,
255
- hourTemplate,
256
- minuteTemplate,
257
- secondTemplate,
258
- meridianTemplate,
259
- templateContent;
260
-
261
- if (this.showInputs) {
262
- hourTemplate = '<input type="text" name="hour" class="bootstrap-timepicker-hour" maxlength="2"/>';
263
- minuteTemplate = '<input type="text" name="minute" class="bootstrap-timepicker-minute" maxlength="2"/>';
264
- secondTemplate = '<input type="text" name="second" class="bootstrap-timepicker-second" maxlength="2"/>';
265
- meridianTemplate = '<input type="text" name="meridian" class="bootstrap-timepicker-meridian" maxlength="2"/>';
266
- } else {
267
- hourTemplate = '<span class="bootstrap-timepicker-hour"></span>';
268
- minuteTemplate = '<span class="bootstrap-timepicker-minute"></span>';
269
- secondTemplate = '<span class="bootstrap-timepicker-second"></span>';
270
- meridianTemplate = '<span class="bootstrap-timepicker-meridian"></span>';
271
- }
272
-
273
- templateContent = '<table>'+
274
- '<tr>'+
275
- '<td><a href="#" data-action="incrementHour"><i class="icon-chevron-up"></i></a></td>'+
276
- '<td class="separator">&nbsp;</td>'+
277
- '<td><a href="#" data-action="incrementMinute"><i class="icon-chevron-up"></i></a></td>'+
278
- (this.showSeconds ?
279
- '<td class="separator">&nbsp;</td>'+
280
- '<td><a href="#" data-action="incrementSecond"><i class="icon-chevron-up"></i></a></td>'
281
- : '') +
282
- (this.showMeridian ?
283
- '<td class="separator">&nbsp;</td>'+
284
- '<td class="meridian-column"><a href="#" data-action="toggleMeridian"><i class="icon-chevron-up"></i></a></td>'
285
- : '') +
286
- '</tr>'+
287
- '<tr>'+
288
- '<td>'+ hourTemplate +'</td> '+
289
- '<td class="separator">:</td>'+
290
- '<td>'+ minuteTemplate +'</td> '+
291
- (this.showSeconds ?
292
- '<td class="separator">:</td>'+
293
- '<td>'+ secondTemplate +'</td>'
294
- : '') +
295
- (this.showMeridian ?
296
- '<td class="separator">&nbsp;</td>'+
297
- '<td>'+ meridianTemplate +'</td>'
298
- : '') +
299
- '</tr>'+
300
- '<tr>'+
301
- '<td><a href="#" data-action="decrementHour"><i class="icon-chevron-down"></i></a></td>'+
302
- '<td class="separator"></td>'+
303
- '<td><a href="#" data-action="decrementMinute"><i class="icon-chevron-down"></i></a></td>'+
304
- (this.showSeconds ?
305
- '<td class="separator">&nbsp;</td>'+
306
- '<td><a href="#" data-action="decrementSecond"><i class="icon-chevron-down"></i></a></td>'
307
- : '') +
308
- (this.showMeridian ?
309
- '<td class="separator">&nbsp;</td>'+
310
- '<td><a href="#" data-action="toggleMeridian"><i class="icon-chevron-down"></i></a></td>'
311
- : '') +
312
- '</tr>'+
313
- '</table>';
314
-
315
- switch(this.template) {
316
- case 'modal':
317
- template = '<div class="bootstrap-timepicker-widget modal hide fade in" data-backdrop="'+ (this.modalBackdrop ? 'true' : 'false') +'">'+
318
- '<div class="modal-header">'+
319
- '<a href="#" class="close" data-dismiss="modal">×</a>'+
320
- '<h3>Pick a Time</h3>'+
321
- '</div>'+
322
- '<div class="modal-content">'+
323
- templateContent +
324
- '</div>'+
325
- '<div class="modal-footer">'+
326
- '<a href="#" class="btn btn-primary" data-dismiss="modal">OK</a>'+
327
- '</div>'+
328
- '</div>';
329
- break;
330
- case 'dropdown':
331
- template = '<div class="bootstrap-timepicker-widget dropdown-menu">'+ templateContent +'</div>';
332
- break;
333
- }
334
-
335
- return template;
336
- },
337
-
338
- getTime: function() {
339
- return this.formatTime(this.hour, this.minute, this.second, this.meridian);
340
- },
341
-
342
- hideWidget: function() {
343
- if (this.isOpen === false) {
344
- return;
345
- }
346
-
347
- if (this.showInputs) {
348
- this.updateFromWidgetInputs();
349
- }
350
-
351
- this.$element.trigger({
352
- 'type': 'hide.timepicker',
353
- 'time': {
354
- 'value': this.getTime(),
355
- 'hours': this.hour,
356
- 'minutes': this.minute,
357
- 'seconds': this.second,
358
- 'meridian': this.meridian
359
- }
360
- });
361
-
362
- if (this.template === 'modal') {
363
- this.$widget.modal('hide');
364
- } else {
365
- this.$widget.removeClass('open');
366
- }
367
-
368
- $(document).off('mousedown.timepicker');
369
-
370
- this.isOpen = false;
371
- },
372
-
373
- highlightUnit: function() {
374
- this.position = this.getCursorPosition();
375
- if (this.position >= 0 && this.position <= 2) {
376
- this.highlightHour();
377
- } else if (this.position >= 3 && this.position <= 5) {
378
- this.highlightMinute();
379
- } else if (this.position >= 6 && this.position <= 8) {
380
- if (this.showSeconds) {
381
- this.highlightSecond();
382
- } else {
383
- this.highlightMeridian();
384
- }
385
- } else if (this.position >= 9 && this.position <= 11) {
386
- this.highlightMeridian();
387
- }
388
- },
389
-
390
- highlightNextUnit: function() {
391
- switch (this.highlightedUnit) {
392
- case 'hour':
393
- this.highlightMinute();
394
- break;
395
- case 'minute':
396
- if (this.showSeconds) {
397
- this.highlightSecond();
398
- } else if (this.showMeridian){
399
- this.highlightMeridian();
400
- } else {
401
- this.highlightHour();
402
- }
403
- break;
404
- case 'second':
405
- if (this.showMeridian) {
406
- this.highlightMeridian();
407
- } else {
408
- this.highlightHour();
409
- }
410
- break;
411
- case 'meridian':
412
- this.highlightHour();
413
- break;
414
- }
415
- },
416
-
417
- highlightPrevUnit: function() {
418
- switch (this.highlightedUnit) {
419
- case 'hour':
420
- this.highlightMeridian();
421
- break;
422
- case 'minute':
423
- this.highlightHour();
424
- break;
425
- case 'second':
426
- this.highlightMinute();
427
- break;
428
- case 'meridian':
429
- if (this.showSeconds) {
430
- this.highlightSecond();
431
- } else {
432
- this.highlightMinute();
433
- }
434
- break;
435
- }
436
- },
437
-
438
- highlightHour: function() {
439
- var $element = this.$element.get(0);
440
-
441
- this.highlightedUnit = 'hour';
442
-
443
- if ($element.setSelectionRange) {
444
- setTimeout(function() {
445
- $element.setSelectionRange(0,2);
446
- }, 0);
447
- }
448
- },
449
-
450
- highlightMinute: function() {
451
- var $element = this.$element.get(0);
452
-
453
- this.highlightedUnit = 'minute';
454
-
455
- if ($element.setSelectionRange) {
456
- setTimeout(function() {
457
- $element.setSelectionRange(3,5);
458
- }, 0);
459
- }
460
- },
461
-
462
- highlightSecond: function() {
463
- var $element = this.$element.get(0);
464
-
465
- this.highlightedUnit = 'second';
466
-
467
- if ($element.setSelectionRange) {
468
- setTimeout(function() {
469
- $element.setSelectionRange(6,8);
470
- }, 0);
471
- }
472
- },
473
-
474
- highlightMeridian: function() {
475
- var $element = this.$element.get(0);
476
-
477
- this.highlightedUnit = 'meridian';
478
-
479
- if ($element.setSelectionRange) {
480
- if (this.showSeconds) {
481
- setTimeout(function() {
482
- $element.setSelectionRange(9,11);
483
- }, 0);
484
- } else {
485
- setTimeout(function() {
486
- $element.setSelectionRange(6,8);
487
- }, 0);
488
- }
489
- }
490
- },
491
-
492
- incrementHour: function() {
493
- if (this.showMeridian) {
494
- if (this.hour === 11) {
495
- this.hour++;
496
- return this.toggleMeridian();
497
- } else if (this.hour === 12) {
498
- this.hour = 0;
499
- }
500
- }
501
- if (this.hour === 23) {
502
- return this.hour = 0;
503
- }
504
- this.hour++;
505
- this.update();
506
- },
507
-
508
- incrementMinute: function(step) {
509
- var newVal;
510
-
511
- if (step) {
512
- newVal = this.minute + step;
513
- } else {
514
- newVal = this.minute + this.minuteStep - (this.minute % this.minuteStep);
515
- }
516
-
517
- if (newVal > 59) {
518
- this.incrementHour();
519
- this.minute = newVal - 60;
520
- } else {
521
- this.minute = newVal;
522
- }
523
- this.update();
524
- },
525
-
526
- incrementSecond: function() {
527
- var newVal = this.second + this.secondStep - (this.second % this.secondStep);
528
-
529
- if (newVal > 59) {
530
- this.incrementMinute(true);
531
- this.second = newVal - 60;
532
- } else {
533
- this.second = newVal;
534
- }
535
- this.update();
536
- },
537
-
538
- remove: function() {
539
- $('document').off('.timepicker');
540
- if (this.$widget) {
541
- this.$widget.remove();
542
- }
543
- delete this.$element.data().timepicker;
544
- },
545
-
546
- setDefaultTime: function(defaultTime){
547
- if (!this.$element.val()) {
548
- if (defaultTime === 'current') {
549
- var dTime = new Date(),
550
- hours = dTime.getHours(),
551
- minutes = Math.floor(dTime.getMinutes() / this.minuteStep) * this.minuteStep,
552
- seconds = Math.floor(dTime.getSeconds() / this.secondStep) * this.secondStep,
553
- meridian = 'AM';
554
-
555
- if (this.showMeridian) {
556
- if (hours === 0) {
557
- hours = 12;
558
- } else if (hours >= 12) {
559
- if (hours > 12) {
560
- hours = hours - 12;
561
- }
562
- meridian = 'PM';
563
- } else {
564
- meridian = 'AM';
565
- }
566
- }
567
-
568
- this.hour = hours;
569
- this.minute = minutes;
570
- this.second = seconds;
571
- this.meridian = meridian;
572
-
573
- this.update();
574
-
575
- } else if (defaultTime === false) {
576
- this.hour = 0;
577
- this.minute = 0;
578
- this.second = 0;
579
- this.meridian = 'AM';
580
- } else {
581
- this.setTime(defaultTime);
582
- }
583
- } else {
584
- this.updateFromElementVal();
585
- }
586
- },
587
-
588
- setTime: function(time) {
589
- var arr,
590
- timeArray;
591
-
592
- if (this.showMeridian) {
593
- arr = time.split(' ');
594
- timeArray = arr[0].split(':');
595
- this.meridian = arr[1];
596
- } else {
597
- timeArray = time.split(':');
598
- }
599
-
600
- this.hour = parseInt(timeArray[0], 10);
601
- this.minute = parseInt(timeArray[1], 10);
602
- this.second = parseInt(timeArray[2], 10);
603
-
604
- if (isNaN(this.hour)) {
605
- this.hour = 0;
606
- }
607
- if (isNaN(this.minute)) {
608
- this.minute = 0;
609
- }
610
-
611
- if (this.showMeridian) {
612
- if (this.hour > 12) {
613
- this.hour = 12;
614
- } else if (this.hour < 1) {
615
- this.hour = 12;
616
- }
617
-
618
- if (this.meridian === 'am' || this.meridian === 'a') {
619
- this.meridian = 'AM';
620
- } else if (this.meridian === 'pm' || this.meridian === 'p') {
621
- this.meridian = 'PM';
622
- }
623
-
624
- if (this.meridian !== 'AM' && this.meridian !== 'PM') {
625
- this.meridian = 'AM';
626
- }
627
- } else {
628
- if (this.hour >= 24) {
629
- this.hour = 23;
630
- } else if (this.hour < 0) {
631
- this.hour = 0;
632
- }
633
- }
634
-
635
- if (this.minute < 0) {
636
- this.minute = 0;
637
- } else if (this.minute >= 60) {
638
- this.minute = 59;
639
- }
640
-
641
- if (this.showSeconds) {
642
- if (isNaN(this.second)) {
643
- this.second = 0;
644
- } else if (this.second < 0) {
645
- this.second = 0;
646
- } else if (this.second >= 60) {
647
- this.second = 59;
648
- }
649
- }
650
-
651
- this.update();
652
- },
653
-
654
- showWidget: function() {
655
- if (this.isOpen) {
656
- return;
657
- }
658
-
659
- var self = this;
660
- $(document).on('mousedown.timepicker', function (e) {
661
- // Clicked outside the timepicker, hide it
662
- if ($(e.target).closest('.bootstrap-timepicker-widget').length === 0) {
663
- self.hideWidget();
664
- }
665
- });
666
-
667
- this.$element.trigger({
668
- 'type': 'show.timepicker',
669
- 'time': {
670
- 'value': this.getTime(),
671
- 'hours': this.hour,
672
- 'minutes': this.minute,
673
- 'seconds': this.second,
674
- 'meridian': this.meridian
675
- }
676
- });
677
-
678
- if (this.disableFocus) {
679
- this.$element.blur();
680
- }
681
-
682
- this.updateFromElementVal();
683
-
684
- if (this.template === 'modal') {
685
- this.$widget.modal('show').on('hidden', $.proxy(this.hideWidget, this));
686
- } else {
687
- if (this.isOpen === false) {
688
- this.$widget.addClass('open');
689
- }
690
- }
691
-
692
- this.isOpen = true;
693
- },
694
-
695
- toggleMeridian: function() {
696
- this.meridian = this.meridian === 'AM' ? 'PM' : 'AM';
697
- this.update();
698
- },
699
-
700
- update: function() {
701
- this.$element.trigger({
702
- 'type': 'changeTime.timepicker',
703
- 'time': {
704
- 'value': this.getTime(),
705
- 'hours': this.hour,
706
- 'minutes': this.minute,
707
- 'seconds': this.second,
708
- 'meridian': this.meridian
709
- }
710
- });
711
-
712
- this.updateElement();
713
- this.updateWidget();
714
- },
715
-
716
- updateElement: function() {
717
- this.$element.val(this.getTime()).change();
718
- },
719
-
720
- updateFromElementVal: function() {
721
- var val = this.$element.val();
722
-
723
- if (val) {
724
- this.setTime(val);
725
- }
726
- },
727
-
728
- updateWidget: function() {
729
- if (this.$widget === false) {
730
- return;
731
- }
732
-
733
- var hour = this.hour < 10 ? '0' + this.hour : this.hour,
734
- minute = this.minute < 10 ? '0' + this.minute : this.minute,
735
- second = this.second < 10 ? '0' + this.second : this.second;
736
-
737
- if (this.showInputs) {
738
- this.$widget.find('input.bootstrap-timepicker-hour').val(hour);
739
- this.$widget.find('input.bootstrap-timepicker-minute').val(minute);
740
-
741
- if (this.showSeconds) {
742
- this.$widget.find('input.bootstrap-timepicker-second').val(second);
743
- }
744
- if (this.showMeridian) {
745
- this.$widget.find('input.bootstrap-timepicker-meridian').val(this.meridian);
746
- }
747
- } else {
748
- this.$widget.find('span.bootstrap-timepicker-hour').text(hour);
749
- this.$widget.find('span.bootstrap-timepicker-minute').text(minute);
750
-
751
- if (this.showSeconds) {
752
- this.$widget.find('span.bootstrap-timepicker-second').text(second);
753
- }
754
- if (this.showMeridian) {
755
- this.$widget.find('span.bootstrap-timepicker-meridian').text(this.meridian);
756
- }
757
- }
758
- },
759
-
760
- updateFromWidgetInputs: function() {
761
- if (this.$widget === false) {
762
- return;
763
- }
764
- var time = $('input.bootstrap-timepicker-hour', this.$widget).val() + ':' +
765
- $('input.bootstrap-timepicker-minute', this.$widget).val() +
766
- (this.showSeconds ? ':' + $('input.bootstrap-timepicker-second', this.$widget).val() : '') +
767
- (this.showMeridian ? ' ' + $('input.bootstrap-timepicker-meridian', this.$widget).val() : '');
768
-
769
- this.setTime(time);
770
- },
771
-
772
- widgetClick: function(e) {
773
- e.stopPropagation();
774
- e.preventDefault();
775
-
776
- var action = $(e.target).closest('a').data('action');
777
- if (action) {
778
- this[action]();
779
- }
780
- },
781
-
782
- widgetKeydown: function(e) {
783
- var $input = $(e.target).closest('input'),
784
- name = $input.attr('name');
785
-
786
- switch (e.keyCode) {
787
- case 9: //tab
788
- if (this.showMeridian) {
789
- if (name === 'meridian') {
790
- return this.hideWidget();
791
- }
792
- } else {
793
- if (this.showSeconds) {
794
- if (name === 'second') {
795
- return this.hideWidget();
796
- }
797
- } else {
798
- if (name === 'minute') {
799
- return this.hideWidget();
800
- }
801
- }
802
- }
803
-
804
- this.updateFromWidgetInputs();
805
- break;
806
- case 27: // escape
807
- this.hideWidget();
808
- break;
809
- case 38: // up arrow
810
- e.preventDefault();
811
- switch (name) {
812
- case 'hour':
813
- this.incrementHour();
814
- break;
815
- case 'minute':
816
- this.incrementMinute();
817
- break;
818
- case 'second':
819
- this.incrementSecond();
820
- break;
821
- case 'meridian':
822
- this.toggleMeridian();
823
- break;
824
- }
825
- break;
826
- case 40: // down arrow
827
- e.preventDefault();
828
- switch (name) {
829
- case 'hour':
830
- this.decrementHour();
831
- break;
832
- case 'minute':
833
- this.decrementMinute();
834
- break;
835
- case 'second':
836
- this.decrementSecond();
837
- break;
838
- case 'meridian':
839
- this.toggleMeridian();
840
- break;
841
- }
842
- break;
843
- }
844
- }
845
- };
846
-
847
-
848
- //TIMEPICKER PLUGIN DEFINITION
849
- $.fn.timepicker = function(option) {
850
- var args = Array.apply(null, arguments);
851
- args.shift();
852
- return this.each(function() {
853
- var $this = $(this),
854
- data = $this.data('timepicker'),
855
- options = typeof option === 'object' && option;
856
-
857
- if (!data) {
858
- $this.data('timepicker', (data = new Timepicker(this, $.extend({}, $.fn.timepicker.defaults, options, $(this).data()))));
859
- }
860
-
861
- if (typeof option === 'string') {
862
- data[option].apply(data, args);
863
- }
864
- });
865
- };
866
-
867
- $.fn.timepicker.defaults = {
868
- defaultTime: 'current',
869
- disableFocus: false,
870
- isOpen: false,
871
- minuteStep: 15,
872
- modalBackdrop: false,
873
- secondStep: 15,
874
- showSeconds: false,
875
- showInputs: true,
876
- showMeridian: true,
877
- template: 'dropdown',
878
- appendWidgetTo: '.bootstrap-timepicker'
879
- };
880
-
881
- $.fn.timepicker.Constructor = Timepicker;
882
-
883
- })(jQuery, window, document);
1
+ /*!
2
+ * Timepicker Component for Twitter Bootstrap
3
+ *
4
+ * Copyright 2013 Joris de Wit
5
+ *
6
+ * Contributors https://github.com/jdewit/bootstrap-timepicker/graphs/contributors
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+ (function($, window, document, undefined) {
12
+ 'use strict';
13
+
14
+ // TIMEPICKER PUBLIC CLASS DEFINITION
15
+ var Timepicker = function(element, options) {
16
+ this.widget = '';
17
+ this.$element = $(element);
18
+ this.defaultTime = options.defaultTime;
19
+ this.disableFocus = options.disableFocus;
20
+ this.isOpen = options.isOpen;
21
+ this.minuteStep = options.minuteStep;
22
+ this.modalBackdrop = options.modalBackdrop;
23
+ this.secondStep = options.secondStep;
24
+ this.showInputs = options.showInputs;
25
+ this.showMeridian = options.showMeridian;
26
+ this.showSeconds = options.showSeconds;
27
+ this.template = options.template;
28
+ this.appendWidgetTo = options.appendWidgetTo;
29
+
30
+ this._init();
31
+ };
32
+
33
+ Timepicker.prototype = {
34
+
35
+ constructor: Timepicker,
36
+
37
+ _init: function() {
38
+ var self = this;
39
+
40
+ if (this.$element.parent().hasClass('input-append') || this.$element.parent().hasClass('input-prepend')) {
41
+ this.$element.parent('.input-append, .input-prepend').find('.add-on').on({
42
+ 'click.timepicker': $.proxy(this.showWidget, this)
43
+ });
44
+ this.$element.on({
45
+ 'focus.timepicker': $.proxy(this.highlightUnit, this),
46
+ 'click.timepicker': $.proxy(this.highlightUnit, this),
47
+ 'keydown.timepicker': $.proxy(this.elementKeydown, this),
48
+ 'blur.timepicker': $.proxy(this.blurElement, this)
49
+ });
50
+ } else {
51
+ if (this.template) {
52
+ this.$element.on({
53
+ 'focus.timepicker': $.proxy(this.showWidget, this),
54
+ 'click.timepicker': $.proxy(this.showWidget, this),
55
+ 'blur.timepicker': $.proxy(this.blurElement, this)
56
+ });
57
+ } else {
58
+ this.$element.on({
59
+ 'focus.timepicker': $.proxy(this.highlightUnit, this),
60
+ 'click.timepicker': $.proxy(this.highlightUnit, this),
61
+ 'keydown.timepicker': $.proxy(this.elementKeydown, this),
62
+ 'blur.timepicker': $.proxy(this.blurElement, this)
63
+ });
64
+ }
65
+ }
66
+
67
+ if (this.template !== false) {
68
+ this.$widget = $(this.getTemplate()).prependTo(this.$element.parents(this.appendWidgetTo)).on('click', $.proxy(this.widgetClick, this));
69
+ } else {
70
+ this.$widget = false;
71
+ }
72
+
73
+ if (this.showInputs && this.$widget !== false) {
74
+ this.$widget.find('input').each(function() {
75
+ $(this).on({
76
+ 'click.timepicker': function() { $(this).select(); },
77
+ 'keydown.timepicker': $.proxy(self.widgetKeydown, self)
78
+ });
79
+ });
80
+ }
81
+
82
+ this.setDefaultTime(this.defaultTime);
83
+ },
84
+
85
+ blurElement: function() {
86
+ this.highlightedUnit = undefined;
87
+ this.updateFromElementVal();
88
+ },
89
+
90
+ decrementHour: function() {
91
+ if (this.showMeridian) {
92
+ if (this.hour === 1) {
93
+ this.hour = 12;
94
+ } else if (this.hour === 12) {
95
+ this.hour--;
96
+
97
+ return this.toggleMeridian();
98
+ } else if (this.hour === 0) {
99
+ this.hour = 11;
100
+
101
+ return this.toggleMeridian();
102
+ } else {
103
+ this.hour--;
104
+ }
105
+ } else {
106
+ if (this.hour === 0) {
107
+ this.hour = 23;
108
+ } else {
109
+ this.hour--;
110
+ }
111
+ }
112
+ this.update();
113
+ },
114
+
115
+ decrementMinute: function(step) {
116
+ var newVal;
117
+
118
+ if (step) {
119
+ newVal = this.minute - step;
120
+ } else {
121
+ newVal = this.minute - this.minuteStep;
122
+ }
123
+
124
+ if (newVal < 0) {
125
+ this.decrementHour();
126
+ this.minute = newVal + 60;
127
+ } else {
128
+ this.minute = newVal;
129
+ }
130
+ this.update();
131
+ },
132
+
133
+ decrementSecond: function() {
134
+ var newVal = this.second - this.secondStep;
135
+
136
+ if (newVal < 0) {
137
+ this.decrementMinute(true);
138
+ this.second = newVal + 60;
139
+ } else {
140
+ this.second = newVal;
141
+ }
142
+ this.update();
143
+ },
144
+
145
+ elementKeydown: function(e) {
146
+ switch (e.keyCode) {
147
+ case 9: //tab
148
+ this.updateFromElementVal();
149
+
150
+ switch (this.highlightedUnit) {
151
+ case 'hour':
152
+ e.preventDefault();
153
+ this.highlightNextUnit();
154
+ break;
155
+ case 'minute':
156
+ if (this.showMeridian || this.showSeconds) {
157
+ e.preventDefault();
158
+ this.highlightNextUnit();
159
+ }
160
+ break;
161
+ case 'second':
162
+ if (this.showMeridian) {
163
+ e.preventDefault();
164
+ this.highlightNextUnit();
165
+ }
166
+ break;
167
+ }
168
+ break;
169
+ case 27: // escape
170
+ this.updateFromElementVal();
171
+ break;
172
+ case 37: // left arrow
173
+ e.preventDefault();
174
+ this.highlightPrevUnit();
175
+ this.updateFromElementVal();
176
+ break;
177
+ case 38: // up arrow
178
+ e.preventDefault();
179
+ switch (this.highlightedUnit) {
180
+ case 'hour':
181
+ this.incrementHour();
182
+ this.highlightHour();
183
+ break;
184
+ case 'minute':
185
+ this.incrementMinute();
186
+ this.highlightMinute();
187
+ break;
188
+ case 'second':
189
+ this.incrementSecond();
190
+ this.highlightSecond();
191
+ break;
192
+ case 'meridian':
193
+ this.toggleMeridian();
194
+ this.highlightMeridian();
195
+ break;
196
+ }
197
+ break;
198
+ case 39: // right arrow
199
+ e.preventDefault();
200
+ this.updateFromElementVal();
201
+ this.highlightNextUnit();
202
+ break;
203
+ case 40: // down arrow
204
+ e.preventDefault();
205
+ switch (this.highlightedUnit) {
206
+ case 'hour':
207
+ this.decrementHour();
208
+ this.highlightHour();
209
+ break;
210
+ case 'minute':
211
+ this.decrementMinute();
212
+ this.highlightMinute();
213
+ break;
214
+ case 'second':
215
+ this.decrementSecond();
216
+ this.highlightSecond();
217
+ break;
218
+ case 'meridian':
219
+ this.toggleMeridian();
220
+ this.highlightMeridian();
221
+ break;
222
+ }
223
+ break;
224
+ }
225
+ },
226
+
227
+ formatTime: function(hour, minute, second, meridian) {
228
+ hour = hour < 10 ? '0' + hour : hour;
229
+ minute = minute < 10 ? '0' + minute : minute;
230
+ second = second < 10 ? '0' + second : second;
231
+
232
+ return hour + ':' + minute + (this.showSeconds ? ':' + second : '') + (this.showMeridian ? ' ' + meridian : '');
233
+ },
234
+
235
+ getCursorPosition: function() {
236
+ var input = this.$element.get(0);
237
+
238
+ if ('selectionStart' in input) {// Standard-compliant browsers
239
+
240
+ return input.selectionStart;
241
+ } else if (document.selection) {// IE fix
242
+ input.focus();
243
+ var sel = document.selection.createRange(),
244
+ selLen = document.selection.createRange().text.length;
245
+
246
+ sel.moveStart('character', - input.value.length);
247
+
248
+ return sel.text.length - selLen;
249
+ }
250
+ },
251
+
252
+ getTemplate: function() {
253
+ var template,
254
+ hourTemplate,
255
+ minuteTemplate,
256
+ secondTemplate,
257
+ meridianTemplate,
258
+ templateContent;
259
+
260
+ if (this.showInputs) {
261
+ hourTemplate = '<input type="text" name="hour" class="bootstrap-timepicker-hour" maxlength="2"/>';
262
+ minuteTemplate = '<input type="text" name="minute" class="bootstrap-timepicker-minute" maxlength="2"/>';
263
+ secondTemplate = '<input type="text" name="second" class="bootstrap-timepicker-second" maxlength="2"/>';
264
+ meridianTemplate = '<input type="text" name="meridian" class="bootstrap-timepicker-meridian" maxlength="2"/>';
265
+ } else {
266
+ hourTemplate = '<span class="bootstrap-timepicker-hour"></span>';
267
+ minuteTemplate = '<span class="bootstrap-timepicker-minute"></span>';
268
+ secondTemplate = '<span class="bootstrap-timepicker-second"></span>';
269
+ meridianTemplate = '<span class="bootstrap-timepicker-meridian"></span>';
270
+ }
271
+
272
+ templateContent = '<table>'+
273
+ '<tr>'+
274
+ '<td><a href="#" data-action="incrementHour"><i class="icon-chevron-up"></i></a></td>'+
275
+ '<td class="separator">&nbsp;</td>'+
276
+ '<td><a href="#" data-action="incrementMinute"><i class="icon-chevron-up"></i></a></td>'+
277
+ (this.showSeconds ?
278
+ '<td class="separator">&nbsp;</td>'+
279
+ '<td><a href="#" data-action="incrementSecond"><i class="icon-chevron-up"></i></a></td>'
280
+ : '') +
281
+ (this.showMeridian ?
282
+ '<td class="separator">&nbsp;</td>'+
283
+ '<td class="meridian-column"><a href="#" data-action="toggleMeridian"><i class="icon-chevron-up"></i></a></td>'
284
+ : '') +
285
+ '</tr>'+
286
+ '<tr>'+
287
+ '<td>'+ hourTemplate +'</td> '+
288
+ '<td class="separator">:</td>'+
289
+ '<td>'+ minuteTemplate +'</td> '+
290
+ (this.showSeconds ?
291
+ '<td class="separator">:</td>'+
292
+ '<td>'+ secondTemplate +'</td>'
293
+ : '') +
294
+ (this.showMeridian ?
295
+ '<td class="separator">&nbsp;</td>'+
296
+ '<td>'+ meridianTemplate +'</td>'
297
+ : '') +
298
+ '</tr>'+
299
+ '<tr>'+
300
+ '<td><a href="#" data-action="decrementHour"><i class="icon-chevron-down"></i></a></td>'+
301
+ '<td class="separator"></td>'+
302
+ '<td><a href="#" data-action="decrementMinute"><i class="icon-chevron-down"></i></a></td>'+
303
+ (this.showSeconds ?
304
+ '<td class="separator">&nbsp;</td>'+
305
+ '<td><a href="#" data-action="decrementSecond"><i class="icon-chevron-down"></i></a></td>'
306
+ : '') +
307
+ (this.showMeridian ?
308
+ '<td class="separator">&nbsp;</td>'+
309
+ '<td><a href="#" data-action="toggleMeridian"><i class="icon-chevron-down"></i></a></td>'
310
+ : '') +
311
+ '</tr>'+
312
+ '</table>';
313
+
314
+ switch(this.template) {
315
+ case 'modal':
316
+ template = '<div class="bootstrap-timepicker-widget modal hide fade in" data-backdrop="'+ (this.modalBackdrop ? 'true' : 'false') +'">'+
317
+ '<div class="modal-header">'+
318
+ '<a href="#" class="close" data-dismiss="modal">×</a>'+
319
+ '<h3>Pick a Time</h3>'+
320
+ '</div>'+
321
+ '<div class="modal-content">'+
322
+ templateContent +
323
+ '</div>'+
324
+ '<div class="modal-footer">'+
325
+ '<a href="#" class="btn btn-primary" data-dismiss="modal">OK</a>'+
326
+ '</div>'+
327
+ '</div>';
328
+ break;
329
+ case 'dropdown':
330
+ template = '<div class="bootstrap-timepicker-widget dropdown-menu">'+ templateContent +'</div>';
331
+ break;
332
+ }
333
+
334
+ return template;
335
+ },
336
+
337
+ getTime: function() {
338
+ return this.formatTime(this.hour, this.minute, this.second, this.meridian);
339
+ },
340
+
341
+ hideWidget: function() {
342
+ if (this.isOpen === false) {
343
+ return;
344
+ }
345
+
346
+ if (this.showInputs) {
347
+ this.updateFromWidgetInputs();
348
+ }
349
+
350
+ this.$element.trigger({
351
+ 'type': 'hide.timepicker',
352
+ 'time': {
353
+ 'value': this.getTime(),
354
+ 'hours': this.hour,
355
+ 'minutes': this.minute,
356
+ 'seconds': this.second,
357
+ 'meridian': this.meridian
358
+ }
359
+ });
360
+
361
+ if (this.template === 'modal' && this.$widget.modal) {
362
+ this.$widget.modal('hide');
363
+ } else {
364
+ this.$widget.removeClass('open');
365
+ }
366
+
367
+ $(document).off('mousedown.timepicker');
368
+
369
+ this.isOpen = false;
370
+ },
371
+
372
+ highlightUnit: function() {
373
+ this.position = this.getCursorPosition();
374
+ if (this.position >= 0 && this.position <= 2) {
375
+ this.highlightHour();
376
+ } else if (this.position >= 3 && this.position <= 5) {
377
+ this.highlightMinute();
378
+ } else if (this.position >= 6 && this.position <= 8) {
379
+ if (this.showSeconds) {
380
+ this.highlightSecond();
381
+ } else {
382
+ this.highlightMeridian();
383
+ }
384
+ } else if (this.position >= 9 && this.position <= 11) {
385
+ this.highlightMeridian();
386
+ }
387
+ },
388
+
389
+ highlightNextUnit: function() {
390
+ switch (this.highlightedUnit) {
391
+ case 'hour':
392
+ this.highlightMinute();
393
+ break;
394
+ case 'minute':
395
+ if (this.showSeconds) {
396
+ this.highlightSecond();
397
+ } else if (this.showMeridian){
398
+ this.highlightMeridian();
399
+ } else {
400
+ this.highlightHour();
401
+ }
402
+ break;
403
+ case 'second':
404
+ if (this.showMeridian) {
405
+ this.highlightMeridian();
406
+ } else {
407
+ this.highlightHour();
408
+ }
409
+ break;
410
+ case 'meridian':
411
+ this.highlightHour();
412
+ break;
413
+ }
414
+ },
415
+
416
+ highlightPrevUnit: function() {
417
+ switch (this.highlightedUnit) {
418
+ case 'hour':
419
+ this.highlightMeridian();
420
+ break;
421
+ case 'minute':
422
+ this.highlightHour();
423
+ break;
424
+ case 'second':
425
+ this.highlightMinute();
426
+ break;
427
+ case 'meridian':
428
+ if (this.showSeconds) {
429
+ this.highlightSecond();
430
+ } else {
431
+ this.highlightMinute();
432
+ }
433
+ break;
434
+ }
435
+ },
436
+
437
+ highlightHour: function() {
438
+ var $element = this.$element.get(0);
439
+
440
+ this.highlightedUnit = 'hour';
441
+
442
+ if ($element.setSelectionRange) {
443
+ setTimeout(function() {
444
+ $element.setSelectionRange(0,2);
445
+ }, 0);
446
+ }
447
+ },
448
+
449
+ highlightMinute: function() {
450
+ var $element = this.$element.get(0);
451
+
452
+ this.highlightedUnit = 'minute';
453
+
454
+ if ($element.setSelectionRange) {
455
+ setTimeout(function() {
456
+ $element.setSelectionRange(3,5);
457
+ }, 0);
458
+ }
459
+ },
460
+
461
+ highlightSecond: function() {
462
+ var $element = this.$element.get(0);
463
+
464
+ this.highlightedUnit = 'second';
465
+
466
+ if ($element.setSelectionRange) {
467
+ setTimeout(function() {
468
+ $element.setSelectionRange(6,8);
469
+ }, 0);
470
+ }
471
+ },
472
+
473
+ highlightMeridian: function() {
474
+ var $element = this.$element.get(0);
475
+
476
+ this.highlightedUnit = 'meridian';
477
+
478
+ if ($element.setSelectionRange) {
479
+ if (this.showSeconds) {
480
+ setTimeout(function() {
481
+ $element.setSelectionRange(9,11);
482
+ }, 0);
483
+ } else {
484
+ setTimeout(function() {
485
+ $element.setSelectionRange(6,8);
486
+ }, 0);
487
+ }
488
+ }
489
+ },
490
+
491
+ incrementHour: function() {
492
+ if (this.showMeridian) {
493
+ if (this.hour === 11) {
494
+ this.hour++;
495
+ return this.toggleMeridian();
496
+ } else if (this.hour === 12) {
497
+ this.hour = 0;
498
+ }
499
+ }
500
+ if (this.hour === 23) {
501
+ this.hour = 0;
502
+
503
+ return;
504
+ }
505
+ this.hour++;
506
+ this.update();
507
+ },
508
+
509
+ incrementMinute: function(step) {
510
+ var newVal;
511
+
512
+ if (step) {
513
+ newVal = this.minute + step;
514
+ } else {
515
+ newVal = this.minute + this.minuteStep - (this.minute % this.minuteStep);
516
+ }
517
+
518
+ if (newVal > 59) {
519
+ this.incrementHour();
520
+ this.minute = newVal - 60;
521
+ } else {
522
+ this.minute = newVal;
523
+ }
524
+ this.update();
525
+ },
526
+
527
+ incrementSecond: function() {
528
+ var newVal = this.second + this.secondStep - (this.second % this.secondStep);
529
+
530
+ if (newVal > 59) {
531
+ this.incrementMinute(true);
532
+ this.second = newVal - 60;
533
+ } else {
534
+ this.second = newVal;
535
+ }
536
+ this.update();
537
+ },
538
+
539
+ remove: function() {
540
+ $('document').off('.timepicker');
541
+ if (this.$widget) {
542
+ this.$widget.remove();
543
+ }
544
+ delete this.$element.data().timepicker;
545
+ },
546
+
547
+ setDefaultTime: function(defaultTime){
548
+ if (!this.$element.val()) {
549
+ if (defaultTime === 'current') {
550
+ var dTime = new Date(),
551
+ hours = dTime.getHours(),
552
+ minutes = Math.floor(dTime.getMinutes() / this.minuteStep) * this.minuteStep,
553
+ seconds = Math.floor(dTime.getSeconds() / this.secondStep) * this.secondStep,
554
+ meridian = 'AM';
555
+
556
+ if (this.showMeridian) {
557
+ if (hours === 0) {
558
+ hours = 12;
559
+ } else if (hours >= 12) {
560
+ if (hours > 12) {
561
+ hours = hours - 12;
562
+ }
563
+ meridian = 'PM';
564
+ } else {
565
+ meridian = 'AM';
566
+ }
567
+ }
568
+
569
+ this.hour = hours;
570
+ this.minute = minutes;
571
+ this.second = seconds;
572
+ this.meridian = meridian;
573
+
574
+ this.update();
575
+
576
+ } else if (defaultTime === false) {
577
+ this.hour = 0;
578
+ this.minute = 0;
579
+ this.second = 0;
580
+ this.meridian = 'AM';
581
+ } else {
582
+ this.setTime(defaultTime);
583
+ }
584
+ } else {
585
+ this.updateFromElementVal();
586
+ }
587
+ },
588
+
589
+ setTime: function(time) {
590
+ var arr,
591
+ timeArray;
592
+
593
+ if (this.showMeridian) {
594
+ arr = time.split(' ');
595
+ timeArray = arr[0].split(':');
596
+ this.meridian = arr[1];
597
+ } else {
598
+ timeArray = time.split(':');
599
+ }
600
+
601
+ this.hour = parseInt(timeArray[0], 10);
602
+ this.minute = parseInt(timeArray[1], 10);
603
+ this.second = parseInt(timeArray[2], 10);
604
+
605
+ if (isNaN(this.hour)) {
606
+ this.hour = 0;
607
+ }
608
+ if (isNaN(this.minute)) {
609
+ this.minute = 0;
610
+ }
611
+
612
+ if (this.showMeridian) {
613
+ if (this.hour > 12) {
614
+ this.hour = 12;
615
+ } else if (this.hour < 1) {
616
+ this.hour = 12;
617
+ }
618
+
619
+ if (this.meridian === 'am' || this.meridian === 'a') {
620
+ this.meridian = 'AM';
621
+ } else if (this.meridian === 'pm' || this.meridian === 'p') {
622
+ this.meridian = 'PM';
623
+ }
624
+
625
+ if (this.meridian !== 'AM' && this.meridian !== 'PM') {
626
+ this.meridian = 'AM';
627
+ }
628
+ } else {
629
+ if (this.hour >= 24) {
630
+ this.hour = 23;
631
+ } else if (this.hour < 0) {
632
+ this.hour = 0;
633
+ }
634
+ }
635
+
636
+ if (this.minute < 0) {
637
+ this.minute = 0;
638
+ } else if (this.minute >= 60) {
639
+ this.minute = 59;
640
+ }
641
+
642
+ if (this.showSeconds) {
643
+ if (isNaN(this.second)) {
644
+ this.second = 0;
645
+ } else if (this.second < 0) {
646
+ this.second = 0;
647
+ } else if (this.second >= 60) {
648
+ this.second = 59;
649
+ }
650
+ }
651
+
652
+ this.update();
653
+ },
654
+
655
+ showWidget: function() {
656
+ if (this.isOpen) {
657
+ return;
658
+ }
659
+
660
+ if (this.$element.is(':disabled')) {
661
+ return;
662
+ }
663
+
664
+ var self = this;
665
+ $(document).on('mousedown.timepicker', function (e) {
666
+ // Clicked outside the timepicker, hide it
667
+ if ($(e.target).closest('.bootstrap-timepicker-widget').length === 0) {
668
+ self.hideWidget();
669
+ }
670
+ });
671
+
672
+ this.$element.trigger({
673
+ 'type': 'show.timepicker',
674
+ 'time': {
675
+ 'value': this.getTime(),
676
+ 'hours': this.hour,
677
+ 'minutes': this.minute,
678
+ 'seconds': this.second,
679
+ 'meridian': this.meridian
680
+ }
681
+ });
682
+
683
+ if (this.disableFocus) {
684
+ this.$element.blur();
685
+ }
686
+
687
+ this.updateFromElementVal();
688
+
689
+ if (this.template === 'modal' && this.$widget.modal) {
690
+ this.$widget.modal('show').on('hidden', $.proxy(this.hideWidget, this));
691
+ } else {
692
+ if (this.isOpen === false) {
693
+ this.$widget.addClass('open');
694
+ }
695
+ }
696
+
697
+ this.isOpen = true;
698
+ },
699
+
700
+ toggleMeridian: function() {
701
+ this.meridian = this.meridian === 'AM' ? 'PM' : 'AM';
702
+ this.update();
703
+ },
704
+
705
+ update: function() {
706
+ this.$element.trigger({
707
+ 'type': 'changeTime.timepicker',
708
+ 'time': {
709
+ 'value': this.getTime(),
710
+ 'hours': this.hour,
711
+ 'minutes': this.minute,
712
+ 'seconds': this.second,
713
+ 'meridian': this.meridian
714
+ }
715
+ });
716
+
717
+ this.updateElement();
718
+ this.updateWidget();
719
+ },
720
+
721
+ updateElement: function() {
722
+ this.$element.val(this.getTime()).change();
723
+ },
724
+
725
+ updateFromElementVal: function() {
726
+ var val = this.$element.val();
727
+
728
+ if (val) {
729
+ this.setTime(val);
730
+ }
731
+ },
732
+
733
+ updateWidget: function() {
734
+ if (this.$widget === false) {
735
+ return;
736
+ }
737
+
738
+ var hour = this.hour < 10 ? '0' + this.hour : this.hour,
739
+ minute = this.minute < 10 ? '0' + this.minute : this.minute,
740
+ second = this.second < 10 ? '0' + this.second : this.second;
741
+
742
+ if (this.showInputs) {
743
+ this.$widget.find('input.bootstrap-timepicker-hour').val(hour);
744
+ this.$widget.find('input.bootstrap-timepicker-minute').val(minute);
745
+
746
+ if (this.showSeconds) {
747
+ this.$widget.find('input.bootstrap-timepicker-second').val(second);
748
+ }
749
+ if (this.showMeridian) {
750
+ this.$widget.find('input.bootstrap-timepicker-meridian').val(this.meridian);
751
+ }
752
+ } else {
753
+ this.$widget.find('span.bootstrap-timepicker-hour').text(hour);
754
+ this.$widget.find('span.bootstrap-timepicker-minute').text(minute);
755
+
756
+ if (this.showSeconds) {
757
+ this.$widget.find('span.bootstrap-timepicker-second').text(second);
758
+ }
759
+ if (this.showMeridian) {
760
+ this.$widget.find('span.bootstrap-timepicker-meridian').text(this.meridian);
761
+ }
762
+ }
763
+ },
764
+
765
+ updateFromWidgetInputs: function() {
766
+ if (this.$widget === false) {
767
+ return;
768
+ }
769
+ var time = $('input.bootstrap-timepicker-hour', this.$widget).val() + ':' +
770
+ $('input.bootstrap-timepicker-minute', this.$widget).val() +
771
+ (this.showSeconds ? ':' + $('input.bootstrap-timepicker-second', this.$widget).val() : '') +
772
+ (this.showMeridian ? ' ' + $('input.bootstrap-timepicker-meridian', this.$widget).val() : '');
773
+
774
+ this.setTime(time);
775
+ },
776
+
777
+ widgetClick: function(e) {
778
+ e.stopPropagation();
779
+ e.preventDefault();
780
+
781
+ var action = $(e.target).closest('a').data('action');
782
+ if (action) {
783
+ this[action]();
784
+ }
785
+ },
786
+
787
+ widgetKeydown: function(e) {
788
+ var $input = $(e.target).closest('input'),
789
+ name = $input.attr('name');
790
+
791
+ switch (e.keyCode) {
792
+ case 9: //tab
793
+ if (this.showMeridian) {
794
+ if (name === 'meridian') {
795
+ return this.hideWidget();
796
+ }
797
+ } else {
798
+ if (this.showSeconds) {
799
+ if (name === 'second') {
800
+ return this.hideWidget();
801
+ }
802
+ } else {
803
+ if (name === 'minute') {
804
+ return this.hideWidget();
805
+ }
806
+ }
807
+ }
808
+
809
+ this.updateFromWidgetInputs();
810
+ break;
811
+ case 27: // escape
812
+ this.hideWidget();
813
+ break;
814
+ case 38: // up arrow
815
+ e.preventDefault();
816
+ switch (name) {
817
+ case 'hour':
818
+ this.incrementHour();
819
+ break;
820
+ case 'minute':
821
+ this.incrementMinute();
822
+ break;
823
+ case 'second':
824
+ this.incrementSecond();
825
+ break;
826
+ case 'meridian':
827
+ this.toggleMeridian();
828
+ break;
829
+ }
830
+ break;
831
+ case 40: // down arrow
832
+ e.preventDefault();
833
+ switch (name) {
834
+ case 'hour':
835
+ this.decrementHour();
836
+ break;
837
+ case 'minute':
838
+ this.decrementMinute();
839
+ break;
840
+ case 'second':
841
+ this.decrementSecond();
842
+ break;
843
+ case 'meridian':
844
+ this.toggleMeridian();
845
+ break;
846
+ }
847
+ break;
848
+ }
849
+ }
850
+ };
851
+
852
+
853
+ //TIMEPICKER PLUGIN DEFINITION
854
+ $.fn.timepicker = function(option) {
855
+ var args = Array.apply(null, arguments);
856
+ args.shift();
857
+ return this.each(function() {
858
+ var $this = $(this),
859
+ data = $this.data('timepicker'),
860
+ options = typeof option === 'object' && option;
861
+
862
+ if (!data) {
863
+ $this.data('timepicker', (data = new Timepicker(this, $.extend({}, $.fn.timepicker.defaults, options, $(this).data()))));
864
+ }
865
+
866
+ if (typeof option === 'string') {
867
+ data[option].apply(data, args);
868
+ }
869
+ });
870
+ };
871
+
872
+ $.fn.timepicker.defaults = {
873
+ defaultTime: 'current',
874
+ disableFocus: false,
875
+ isOpen: false,
876
+ minuteStep: 15,
877
+ modalBackdrop: false,
878
+ secondStep: 15,
879
+ showSeconds: false,
880
+ showInputs: true,
881
+ showMeridian: true,
882
+ template: 'dropdown',
883
+ appendWidgetTo: '.bootstrap-timepicker'
884
+ };
885
+
886
+ $.fn.timepicker.Constructor = Timepicker;
887
+
888
+ })(jQuery, window, document);