bootstrap-timepicker-rails-addon 0.2.5.1 → 0.2.6.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2694f17a4761a18db42b46d55b1e867026cb02a9
4
+ data.tar.gz: ea62c8d055d8687161a0bfcee2c06517f6ba7ecf
5
+ SHA512:
6
+ metadata.gz: 2d2e5e51de5a3d959da06b06a28ded6c35cc7cf135199b0b624b25e5bd81a44d139f13f9dd94595568230476ae481343d12699aba2d1ee44250daef3aea593f5
7
+ data.tar.gz: f7e42492cc187d4f02f1427c3ad1469d574b9b4caf78142ec8e1e925938ec3f18dafd3a1af51fa2dd8a95c6ca53b5bfda7f118cb59c9dd16ebb57461b2cf0438
data/README.md CHANGED
@@ -7,11 +7,13 @@ bootstrap-timepicker-rails-addon project integrates Timepicker for Twitter Boots
7
7
 
8
8
  Add this line to your application's Gemfile:
9
9
 
10
+ gem 'bootstrap-sass', '~> 2.3.2.0'
10
11
  gem 'bootstrap-timepicker-rails-addon'
11
12
 
12
13
  Or you can install from latest build:
13
14
 
14
15
  ```ruby
16
+ gem 'bootstrap-sass', '~> 2.3.2.0'
15
17
  gem 'bootstrap-timepicker-rails-addon', :require => 'bootstrap-timepicker-rails-addon',
16
18
  :git => 'git://github.com/ywjno/bootstrap-timepicker-rails-addon.git'
17
19
  ```
@@ -49,7 +51,7 @@ And here is the html code sample.
49
51
  </div>
50
52
  ```
51
53
 
52
- Please view the bootstrap-timepicker <a href="http://jdewit.github.com/bootstrap-timepicker">demos & documentation</a>.
54
+ Please view the bootstrap-timepicker <a href="http://jdewit.github.io/bootstrap-timepicker/">demos & documentation</a>.
53
55
 
54
56
  ## Contributing
55
57
 
@@ -2,7 +2,7 @@ module Bootstrap
2
2
  module Timepicker
3
3
  module Rails
4
4
  module Addon
5
- VERSION = "0.2.5.1"
5
+ VERSION = "0.2.6.1"
6
6
  end
7
7
  end
8
8
  end
@@ -1,1029 +1,1097 @@
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.disableMousewheel = options.disableMousewheel;
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
- _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
- 'mousewheel.timepicker DOMMouseScroll.timepicker': $.proxy(this.mousewheel, 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
- 'mousewheel.timepicker DOMMouseScroll.timepicker': $.proxy(this.mousewheel, this)
58
- });
59
- } else {
60
- this.$element.on({
61
- 'focus.timepicker': $.proxy(this.highlightUnit, this),
62
- 'click.timepicker': $.proxy(this.highlightUnit, this),
63
- 'keydown.timepicker': $.proxy(this.elementKeydown, this),
64
- 'blur.timepicker': $.proxy(this.blurElement, this),
65
- 'mousewheel.timepicker DOMMouseScroll.timepicker': $.proxy(this.mousewheel, this)
66
- });
67
- }
68
- }
69
-
70
- if (this.template !== false) {
71
- this.$widget = $(this.getTemplate()).prependTo(this.$element.parents(this.appendWidgetTo)).on('click', $.proxy(this.widgetClick, this));
72
- } else {
73
- this.$widget = false;
74
- }
75
-
76
- if (this.showInputs && this.$widget !== false) {
77
- this.$widget.find('input').each(function() {
78
- $(this).on({
79
- 'click.timepicker': function() { $(this).select(); },
80
- 'keydown.timepicker': $.proxy(self.widgetKeydown, self),
81
- 'keyup.timepicker': $.proxy(self.widgetKeyup, self)
82
- });
83
- });
84
- }
85
-
86
- this.setDefaultTime(this.defaultTime);
87
- },
88
-
89
- blurElement: function() {
90
- this.highlightedUnit = null;
91
- this.updateFromElementVal();
92
- },
93
-
94
- clear: function() {
95
- this.hour = '';
96
- this.minute = '';
97
- this.second = '';
98
- this.meridian = '';
99
-
100
- this.$element.val('');
101
- },
102
-
103
- decrementHour: function() {
104
- if (this.showMeridian) {
105
- if (this.hour === 1) {
106
- this.hour = 12;
107
- } else if (this.hour === 12) {
108
- this.hour--;
109
-
110
- return this.toggleMeridian();
111
- } else if (this.hour === 0) {
112
- this.hour = 11;
113
-
114
- return this.toggleMeridian();
115
- } else {
116
- this.hour--;
117
- }
118
- } else {
119
- if (this.hour <= 0) {
120
- this.hour = 23;
121
- } else {
122
- this.hour--;
123
- }
124
- }
125
- },
126
-
127
- decrementMinute: function(step) {
128
- var newVal;
129
-
130
- if (step) {
131
- newVal = this.minute - step;
132
- } else {
133
- newVal = this.minute - this.minuteStep;
134
- }
135
-
136
- if (newVal < 0) {
137
- this.decrementHour();
138
- this.minute = newVal + 60;
139
- } else {
140
- this.minute = newVal;
141
- }
142
- },
143
-
144
- decrementSecond: function() {
145
- var newVal = this.second - this.secondStep;
146
-
147
- if (newVal < 0) {
148
- this.decrementMinute(true);
149
- this.second = newVal + 60;
150
- } else {
151
- this.second = newVal;
152
- }
153
- },
154
-
155
- elementKeydown: function(e) {
156
- switch (e.keyCode) {
157
- case 9: //tab
158
- case 27: // escape
159
- this.updateFromElementVal();
160
- break;
161
- case 37: // left arrow
162
- e.preventDefault();
163
- this.highlightPrevUnit();
164
- break;
165
- case 38: // up arrow
166
- e.preventDefault();
167
- switch (this.highlightedUnit) {
168
- case 'hour':
169
- this.incrementHour();
170
- this.highlightHour();
171
- break;
172
- case 'minute':
173
- this.incrementMinute();
174
- this.highlightMinute();
175
- break;
176
- case 'second':
177
- this.incrementSecond();
178
- this.highlightSecond();
179
- break;
180
- case 'meridian':
181
- this.toggleMeridian();
182
- this.highlightMeridian();
183
- break;
184
- }
185
- this.update();
186
- break;
187
- case 39: // right arrow
188
- e.preventDefault();
189
- this.highlightNextUnit();
190
- break;
191
- case 40: // down arrow
192
- e.preventDefault();
193
- switch (this.highlightedUnit) {
194
- case 'hour':
195
- this.decrementHour();
196
- this.highlightHour();
197
- break;
198
- case 'minute':
199
- this.decrementMinute();
200
- this.highlightMinute();
201
- break;
202
- case 'second':
203
- this.decrementSecond();
204
- this.highlightSecond();
205
- break;
206
- case 'meridian':
207
- this.toggleMeridian();
208
- this.highlightMeridian();
209
- break;
210
- }
211
-
212
- this.update();
213
- break;
214
- }
215
- },
216
-
217
- getCursorPosition: function() {
218
- var input = this.$element.get(0);
219
-
220
- if ('selectionStart' in input) {// Standard-compliant browsers
221
-
222
- return input.selectionStart;
223
- } else if (document.selection) {// IE fix
224
- input.focus();
225
- var sel = document.selection.createRange(),
226
- selLen = document.selection.createRange().text.length;
227
-
228
- sel.moveStart('character', - input.value.length);
229
-
230
- return sel.text.length - selLen;
231
- }
232
- },
233
-
234
- getTemplate: function() {
235
- var template,
236
- hourTemplate,
237
- minuteTemplate,
238
- secondTemplate,
239
- meridianTemplate,
240
- templateContent;
241
-
242
- if (this.showInputs) {
243
- hourTemplate = '<input type="text" class="bootstrap-timepicker-hour" maxlength="2"/>';
244
- minuteTemplate = '<input type="text" class="bootstrap-timepicker-minute" maxlength="2"/>';
245
- secondTemplate = '<input type="text" class="bootstrap-timepicker-second" maxlength="2"/>';
246
- meridianTemplate = '<input type="text" class="bootstrap-timepicker-meridian" maxlength="2"/>';
247
- } else {
248
- hourTemplate = '<span class="bootstrap-timepicker-hour"></span>';
249
- minuteTemplate = '<span class="bootstrap-timepicker-minute"></span>';
250
- secondTemplate = '<span class="bootstrap-timepicker-second"></span>';
251
- meridianTemplate = '<span class="bootstrap-timepicker-meridian"></span>';
252
- }
253
-
254
- templateContent = '<table>'+
255
- '<tr>'+
256
- '<td><a href="#" data-action="incrementHour"><i class="icon-chevron-up"></i></a></td>'+
257
- '<td class="separator">&nbsp;</td>'+
258
- '<td><a href="#" data-action="incrementMinute"><i class="icon-chevron-up"></i></a></td>'+
259
- (this.showSeconds ?
260
- '<td class="separator">&nbsp;</td>'+
261
- '<td><a href="#" data-action="incrementSecond"><i class="icon-chevron-up"></i></a></td>'
262
- : '') +
263
- (this.showMeridian ?
264
- '<td class="separator">&nbsp;</td>'+
265
- '<td class="meridian-column"><a href="#" data-action="toggleMeridian"><i class="icon-chevron-up"></i></a></td>'
266
- : '') +
267
- '</tr>'+
268
- '<tr>'+
269
- '<td>'+ hourTemplate +'</td> '+
270
- '<td class="separator">:</td>'+
271
- '<td>'+ minuteTemplate +'</td> '+
272
- (this.showSeconds ?
273
- '<td class="separator">:</td>'+
274
- '<td>'+ secondTemplate +'</td>'
275
- : '') +
276
- (this.showMeridian ?
277
- '<td class="separator">&nbsp;</td>'+
278
- '<td>'+ meridianTemplate +'</td>'
279
- : '') +
280
- '</tr>'+
281
- '<tr>'+
282
- '<td><a href="#" data-action="decrementHour"><i class="icon-chevron-down"></i></a></td>'+
283
- '<td class="separator"></td>'+
284
- '<td><a href="#" data-action="decrementMinute"><i class="icon-chevron-down"></i></a></td>'+
285
- (this.showSeconds ?
286
- '<td class="separator">&nbsp;</td>'+
287
- '<td><a href="#" data-action="decrementSecond"><i class="icon-chevron-down"></i></a></td>'
288
- : '') +
289
- (this.showMeridian ?
290
- '<td class="separator">&nbsp;</td>'+
291
- '<td><a href="#" data-action="toggleMeridian"><i class="icon-chevron-down"></i></a></td>'
292
- : '') +
293
- '</tr>'+
294
- '</table>';
295
-
296
- switch(this.template) {
297
- case 'modal':
298
- template = '<div class="bootstrap-timepicker-widget modal hide fade in" data-backdrop="'+ (this.modalBackdrop ? 'true' : 'false') +'">'+
299
- '<div class="modal-header">'+
300
- '<a href="#" class="close" data-dismiss="modal">×</a>'+
301
- '<h3>Pick a Time</h3>'+
302
- '</div>'+
303
- '<div class="modal-content">'+
304
- templateContent +
305
- '</div>'+
306
- '<div class="modal-footer">'+
307
- '<a href="#" class="btn btn-primary" data-dismiss="modal">OK</a>'+
308
- '</div>'+
309
- '</div>';
310
- break;
311
- case 'dropdown':
312
- template = '<div class="bootstrap-timepicker-widget dropdown-menu">'+ templateContent +'</div>';
313
- break;
314
- }
315
-
316
- return template;
317
- },
318
-
319
- getTime: function() {
320
- if (!this.hour && !this.minute && !this.second) {
321
- return '';
322
- }
323
-
324
- return this.hour + ':' + (this.minute.toString().length === 1 ? '0' + this.minute : this.minute) + (this.showSeconds ? ':' + (this.second.toString().length === 1 ? '0' + this.second : this.second) : '') + (this.showMeridian ? ' ' + this.meridian : '');
325
- },
326
-
327
- hideWidget: function() {
328
- if (this.isOpen === false) {
329
- return;
330
- }
331
-
332
- this.$element.trigger({
333
- 'type': 'hide.timepicker',
334
- 'time': {
335
- 'value': this.getTime(),
336
- 'hours': this.hour,
337
- 'minutes': this.minute,
338
- 'seconds': this.second,
339
- 'meridian': this.meridian
340
- }
341
- });
342
-
343
- if (this.template === 'modal' && this.$widget.modal) {
344
- this.$widget.modal('hide');
345
- } else {
346
- this.$widget.removeClass('open');
347
- }
348
-
349
- $(document).off('mousedown.timepicker, touchend.timepicker');
350
-
351
- this.isOpen = false;
352
- },
353
-
354
- highlightUnit: function() {
355
- this.position = this.getCursorPosition();
356
- if (this.position >= 0 && this.position <= 2) {
357
- this.highlightHour();
358
- } else if (this.position >= 3 && this.position <= 5) {
359
- this.highlightMinute();
360
- } else if (this.position >= 6 && this.position <= 8) {
361
- if (this.showSeconds) {
362
- this.highlightSecond();
363
- } else {
364
- this.highlightMeridian();
365
- }
366
- } else if (this.position >= 9 && this.position <= 11) {
367
- this.highlightMeridian();
368
- }
369
- },
370
-
371
- highlightNextUnit: function() {
372
- switch (this.highlightedUnit) {
373
- case 'hour':
374
- this.highlightMinute();
375
- break;
376
- case 'minute':
377
- if (this.showSeconds) {
378
- this.highlightSecond();
379
- } else if (this.showMeridian){
380
- this.highlightMeridian();
381
- } else {
382
- this.highlightHour();
383
- }
384
- break;
385
- case 'second':
386
- if (this.showMeridian) {
387
- this.highlightMeridian();
388
- } else {
389
- this.highlightHour();
390
- }
391
- break;
392
- case 'meridian':
393
- this.highlightHour();
394
- break;
395
- }
396
- },
397
-
398
- highlightPrevUnit: function() {
399
- switch (this.highlightedUnit) {
400
- case 'hour':
401
- if(this.showMeridian){
402
- this.highlightMeridian();
403
- } else if (this.showSeconds) {
404
- this.highlightSecond();
405
- } else {
406
- this.highlightMinute();
407
- }
408
- break;
409
- case 'minute':
410
- this.highlightHour();
411
- break;
412
- case 'second':
413
- this.highlightMinute();
414
- break;
415
- case 'meridian':
416
- if (this.showSeconds) {
417
- this.highlightSecond();
418
- } else {
419
- this.highlightMinute();
420
- }
421
- break;
422
- }
423
- },
424
-
425
- highlightHour: function() {
426
- var $element = this.$element.get(0),
427
- self = this;
428
-
429
- this.highlightedUnit = 'hour';
430
-
431
- if ($element.setSelectionRange) {
432
- setTimeout(function() {
433
- if (self.hour < 10) {
434
- $element.setSelectionRange(0,1);
435
- } else {
436
- $element.setSelectionRange(0,2);
437
- }
438
- }, 0);
439
- }
440
- },
441
-
442
- highlightMinute: function() {
443
- var $element = this.$element.get(0),
444
- self = this;
445
-
446
- this.highlightedUnit = 'minute';
447
-
448
- if ($element.setSelectionRange) {
449
- setTimeout(function() {
450
- if (self.hour < 10) {
451
- $element.setSelectionRange(2,4);
452
- } else {
453
- $element.setSelectionRange(3,5);
454
- }
455
- }, 0);
456
- }
457
- },
458
-
459
- highlightSecond: function() {
460
- var $element = this.$element.get(0),
461
- self = this;
462
-
463
- this.highlightedUnit = 'second';
464
-
465
- if ($element.setSelectionRange) {
466
- setTimeout(function() {
467
- if (self.hour < 10) {
468
- $element.setSelectionRange(5,7);
469
- } else {
470
- $element.setSelectionRange(6,8);
471
- }
472
- }, 0);
473
- }
474
- },
475
-
476
- highlightMeridian: function() {
477
- var $element = this.$element.get(0),
478
- self = this;
479
-
480
- this.highlightedUnit = 'meridian';
481
-
482
- if ($element.setSelectionRange) {
483
- if (this.showSeconds) {
484
- setTimeout(function() {
485
- if (self.hour < 10) {
486
- $element.setSelectionRange(8,10);
487
- } else {
488
- $element.setSelectionRange(9,11);
489
- }
490
- }, 0);
491
- } else {
492
- setTimeout(function() {
493
- if (self.hour < 10) {
494
- $element.setSelectionRange(5,7);
495
- } else {
496
- $element.setSelectionRange(6,8);
497
- }
498
- }, 0);
499
- }
500
- }
501
- },
502
-
503
- incrementHour: function() {
504
- if (this.showMeridian) {
505
- if (this.hour === 11) {
506
- this.hour++;
507
- return this.toggleMeridian();
508
- } else if (this.hour === 12) {
509
- this.hour = 0;
510
- }
511
- }
512
- if (this.hour === 23) {
513
- this.hour = 0;
514
-
515
- return;
516
- }
517
- this.hour++;
518
- },
519
-
520
- incrementMinute: function(step) {
521
- var newVal;
522
-
523
- if (step) {
524
- newVal = this.minute + step;
525
- } else {
526
- newVal = this.minute + this.minuteStep - (this.minute % this.minuteStep);
527
- }
528
-
529
- if (newVal > 59) {
530
- this.incrementHour();
531
- this.minute = newVal - 60;
532
- } else {
533
- this.minute = newVal;
534
- }
535
- },
536
-
537
- incrementSecond: function() {
538
- var newVal = this.second + this.secondStep - (this.second % this.secondStep);
539
-
540
- if (newVal > 59) {
541
- this.incrementMinute(true);
542
- this.second = newVal - 60;
543
- } else {
544
- this.second = newVal;
545
- }
546
- },
547
-
548
- mousewheel: function(e) {
549
- if (this.disableMousewheel) {
550
- return;
551
- }
552
-
553
- e.preventDefault();
554
- e.stopPropagation();
555
-
556
- var delta = e.originalEvent.wheelDelta || -e.originalEvent.detail,
557
- scrollTo = null;
558
-
559
- if (e.type === 'mousewheel') {
560
- scrollTo = (e.originalEvent.wheelDelta * -1);
561
- }
562
- else if (e.type === 'DOMMouseScroll') {
563
- scrollTo = 40 * e.originalEvent.detail;
564
- }
565
-
566
- if (scrollTo) {
567
- e.preventDefault();
568
- $(this).scrollTop(scrollTo + $(this).scrollTop());
569
- }
570
-
571
- switch (this.highlightedUnit) {
572
- case 'minute':
573
- if (delta > 0) {
574
- this.incrementMinute();
575
- } else {
576
- this.decrementMinute();
577
- }
578
- this.highlightMinute();
579
- break;
580
- case 'second':
581
- if (delta > 0) {
582
- this.incrementSecond();
583
- } else {
584
- this.decrementSecond();
585
- }
586
- this.highlightSecond();
587
- break;
588
- case 'meridian':
589
- this.toggleMeridian();
590
- this.highlightMeridian();
591
- break;
592
- default:
593
- if (delta > 0) {
594
- this.incrementHour();
595
- } else {
596
- this.decrementHour();
597
- }
598
- this.highlightHour();
599
- break;
600
- }
601
-
602
- return false;
603
- },
604
-
605
- remove: function() {
606
- $('document').off('.timepicker');
607
- if (this.$widget) {
608
- this.$widget.remove();
609
- }
610
- delete this.$element.data().timepicker;
611
- },
612
-
613
- setDefaultTime: function(defaultTime) {
614
- if (!this.$element.val()) {
615
- if (defaultTime === 'current') {
616
- var dTime = new Date(),
617
- hours = dTime.getHours(),
618
- minutes = dTime.getMinutes(),
619
- seconds = dTime.getSeconds(),
620
- meridian = 'AM';
621
-
622
- if (seconds !== 0) {
623
- seconds = Math.ceil(dTime.getSeconds() / this.secondStep) * this.secondStep;
624
- if (seconds === 60) {
625
- minutes += 1;
626
- seconds = 0;
627
- }
628
- }
629
-
630
- if (minutes !== 0) {
631
- minutes = Math.ceil(dTime.getMinutes() / this.minuteStep) * this.minuteStep;
632
- if (minutes === 60) {
633
- hours += 1;
634
- minutes = 0;
635
- }
636
- }
637
-
638
- if (this.showMeridian) {
639
- if (hours === 0) {
640
- hours = 12;
641
- } else if (hours >= 12) {
642
- if (hours > 12) {
643
- hours = hours - 12;
644
- }
645
- meridian = 'PM';
646
- } else {
647
- meridian = 'AM';
648
- }
649
- }
650
-
651
- this.hour = hours;
652
- this.minute = minutes;
653
- this.second = seconds;
654
- this.meridian = meridian;
655
-
656
- this.update();
657
-
658
- } else if (defaultTime === false) {
659
- this.hour = 0;
660
- this.minute = 0;
661
- this.second = 0;
662
- this.meridian = 'AM';
663
- } else {
664
- this.setTime(defaultTime);
665
- }
666
- } else {
667
- this.updateFromElementVal();
668
- }
669
- },
670
-
671
- setTime: function(time, ignoreWidget) {
672
- if (!time) {
673
- this.clear();
674
- return;
675
- }
676
-
677
- var timeArray,
678
- hour,
679
- minute,
680
- second,
681
- meridian;
682
-
683
- if (typeof time === 'object' && time.getMonth){
684
- // this is a date object
685
- hour = time.getHours();
686
- minute = time.getMinutes();
687
- second = time.getSeconds();
688
-
689
- if (this.showMeridian){
690
- meridian = 'AM';
691
- if (hour > 12){
692
- meridian = 'PM';
693
- hour = hour % 12;
694
- }
695
-
696
- if (hour === 12){
697
- meridian = 'PM';
698
- }
699
- }
700
- } else {
701
- if (time.match(/p/i) !== null) {
702
- meridian = 'PM';
703
- } else {
704
- meridian = 'AM';
705
- }
706
-
707
- time = time.replace(/[^0-9\:]/g, '');
708
-
709
- timeArray = time.split(':');
710
-
711
- hour = timeArray[0] ? timeArray[0].toString() : timeArray.toString();
712
- minute = timeArray[1] ? timeArray[1].toString() : '';
713
- second = timeArray[2] ? timeArray[2].toString() : '';
714
-
715
- // idiot proofing
716
- if (hour.length > 4) {
717
- second = hour.substr(4, 2);
718
- }
719
- if (hour.length > 2) {
720
- minute = hour.substr(2, 2);
721
- hour = hour.substr(0, 2);
722
- }
723
- if (minute.length > 2) {
724
- second = minute.substr(2, 2);
725
- minute = minute.substr(0, 2);
726
- }
727
- if (second.length > 2) {
728
- second = second.substr(2, 2);
729
- }
730
-
731
- hour = parseInt(hour, 10);
732
- minute = parseInt(minute, 10);
733
- second = parseInt(second, 10);
734
-
735
- if (isNaN(hour)) {
736
- hour = 0;
737
- }
738
- if (isNaN(minute)) {
739
- minute = 0;
740
- }
741
- if (isNaN(second)) {
742
- second = 0;
743
- }
744
-
745
- if (this.showMeridian) {
746
- if (hour < 1) {
747
- hour = 1;
748
- } else if (hour > 12) {
749
- hour = 12;
750
- }
751
- } else {
752
- if (hour >= 24) {
753
- hour = 23;
754
- } else if (hour < 0) {
755
- hour = 0;
756
- }
757
- if (hour < 13 && meridian === 'PM') {
758
- hour = hour + 12;
759
- }
760
- }
761
-
762
- if (minute < 0) {
763
- minute = 0;
764
- } else if (minute >= 60) {
765
- minute = 59;
766
- }
767
-
768
- if (this.showSeconds) {
769
- if (isNaN(second)) {
770
- second = 0;
771
- } else if (second < 0) {
772
- second = 0;
773
- } else if (second >= 60) {
774
- second = 59;
775
- }
776
- }
777
- }
778
-
779
- this.hour = hour;
780
- this.minute = minute;
781
- this.second = second;
782
- this.meridian = meridian;
783
-
784
- this.update(ignoreWidget);
785
- },
786
-
787
- showWidget: function() {
788
- if (this.isOpen) {
789
- return;
790
- }
791
-
792
- if (this.$element.is(':disabled')) {
793
- return;
794
- }
795
-
796
- var self = this;
797
- $(document).on('mousedown.timepicker, touchend.timepicker', function (e) {
798
- // Clicked outside the timepicker, hide it
799
- if ($(e.target).closest('.bootstrap-timepicker-widget').length === 0) {
800
- self.hideWidget();
801
- }
802
- });
803
-
804
- this.$element.trigger({
805
- 'type': 'show.timepicker',
806
- 'time': {
807
- 'value': this.getTime(),
808
- 'hours': this.hour,
809
- 'minutes': this.minute,
810
- 'seconds': this.second,
811
- 'meridian': this.meridian
812
- }
813
- });
814
-
815
- if (this.disableFocus) {
816
- this.$element.blur();
817
- }
818
-
819
- // widget shouldn't be empty on open
820
- if (!this.hour) {
821
- if (this.defaultTime) {
822
- this.setDefaultTime(this.defaultTime);
823
- } else {
824
- this.setTime('0:0:0');
825
- }
826
- }
827
-
828
- if (this.template === 'modal' && this.$widget.modal) {
829
- this.$widget.modal('show').on('hidden', $.proxy(this.hideWidget, this));
830
- } else {
831
- if (this.isOpen === false) {
832
- this.$widget.addClass('open');
833
- }
834
- }
835
-
836
- this.isOpen = true;
837
- },
838
-
839
- toggleMeridian: function() {
840
- this.meridian = this.meridian === 'AM' ? 'PM' : 'AM';
841
- },
842
-
843
- update: function(ignoreWidget) {
844
- this.$element.trigger({
845
- 'type': 'changeTime.timepicker',
846
- 'time': {
847
- 'value': this.getTime(),
848
- 'hours': this.hour,
849
- 'minutes': this.minute,
850
- 'seconds': this.second,
851
- 'meridian': this.meridian
852
- }
853
- });
854
-
855
- this.updateElement();
856
- if (!ignoreWidget) {
857
- this.updateWidget();
858
- }
859
- },
860
-
861
- updateElement: function() {
862
- this.$element.val(this.getTime()).change();
863
- },
864
-
865
- updateFromElementVal: function() {
866
- this.setTime(this.$element.val());
867
- },
868
-
869
- updateWidget: function() {
870
- if (this.$widget === false) {
871
- return;
872
- }
873
-
874
- var hour = this.hour,
875
- minute = this.minute.toString().length === 1 ? '0' + this.minute : this.minute,
876
- second = this.second.toString().length === 1 ? '0' + this.second : this.second;
877
-
878
- if (this.showInputs) {
879
- this.$widget.find('input.bootstrap-timepicker-hour').val(hour);
880
- this.$widget.find('input.bootstrap-timepicker-minute').val(minute);
881
-
882
- if (this.showSeconds) {
883
- this.$widget.find('input.bootstrap-timepicker-second').val(second);
884
- }
885
- if (this.showMeridian) {
886
- this.$widget.find('input.bootstrap-timepicker-meridian').val(this.meridian);
887
- }
888
- } else {
889
- this.$widget.find('span.bootstrap-timepicker-hour').text(hour);
890
- this.$widget.find('span.bootstrap-timepicker-minute').text(minute);
891
-
892
- if (this.showSeconds) {
893
- this.$widget.find('span.bootstrap-timepicker-second').text(second);
894
- }
895
- if (this.showMeridian) {
896
- this.$widget.find('span.bootstrap-timepicker-meridian').text(this.meridian);
897
- }
898
- }
899
- },
900
-
901
- updateFromWidgetInputs: function() {
902
- if (this.$widget === false) {
903
- return;
904
- }
905
-
906
- var t = this.$widget.find('input.bootstrap-timepicker-hour').val() + ':' +
907
- this.$widget.find('input.bootstrap-timepicker-minute').val() +
908
- (this.showSeconds ? ':' + this.$widget.find('input.bootstrap-timepicker-second').val() : '') +
909
- (this.showMeridian ? this.$widget.find('input.bootstrap-timepicker-meridian').val() : '')
910
- ;
911
-
912
- this.setTime(t, true);
913
- },
914
-
915
- widgetClick: function(e) {
916
- e.stopPropagation();
917
- e.preventDefault();
918
-
919
- var $input = $(e.target),
920
- action = $input.closest('a').data('action');
921
-
922
- if (action) {
923
- this[action]();
924
- }
925
- this.update();
926
-
927
- if ($input.is('input')) {
928
- $input.get(0).setSelectionRange(0,2);
929
- }
930
- },
931
-
932
- widgetKeydown: function(e) {
933
- var $input = $(e.target),
934
- name = $input.attr('class').replace('bootstrap-timepicker-', '');
935
-
936
- switch (e.keyCode) {
937
- case 9: //tab
938
- if ((this.showMeridian && name === 'meridian') || (this.showSeconds && name === 'second') || (!this.showMeridian && !this.showSeconds && name === 'minute')) {
939
- return this.hideWidget();
940
- }
941
- break;
942
- case 27: // escape
943
- this.hideWidget();
944
- break;
945
- case 38: // up arrow
946
- e.preventDefault();
947
- switch (name) {
948
- case 'hour':
949
- this.incrementHour();
950
- break;
951
- case 'minute':
952
- this.incrementMinute();
953
- break;
954
- case 'second':
955
- this.incrementSecond();
956
- break;
957
- case 'meridian':
958
- this.toggleMeridian();
959
- break;
960
- }
961
- this.setTime(this.getTime());
962
- $input.get(0).setSelectionRange(0,2);
963
- break;
964
- case 40: // down arrow
965
- e.preventDefault();
966
- switch (name) {
967
- case 'hour':
968
- this.decrementHour();
969
- break;
970
- case 'minute':
971
- this.decrementMinute();
972
- break;
973
- case 'second':
974
- this.decrementSecond();
975
- break;
976
- case 'meridian':
977
- this.toggleMeridian();
978
- break;
979
- }
980
- this.setTime(this.getTime());
981
- $input.get(0).setSelectionRange(0,2);
982
- break;
983
- }
984
- },
985
-
986
- widgetKeyup: function(e) {
987
- if ((e.keyCode === 65) || (e.keyCode === 77) || (e.keyCode === 80) || (e.keyCode === 46) || (e.keyCode === 8) || (e.keyCode >= 46 && e.keyCode <= 57)) {
988
- this.updateFromWidgetInputs();
989
- }
990
- }
991
- };
992
-
993
- //TIMEPICKER PLUGIN DEFINITION
994
- $.fn.timepicker = function(option) {
995
- var args = Array.apply(null, arguments);
996
- args.shift();
997
- return this.each(function() {
998
- var $this = $(this),
999
- data = $this.data('timepicker'),
1000
- options = typeof option === 'object' && option;
1001
-
1002
- if (!data) {
1003
- $this.data('timepicker', (data = new Timepicker(this, $.extend({}, $.fn.timepicker.defaults, options, $(this).data()))));
1004
- }
1005
-
1006
- if (typeof option === 'string') {
1007
- data[option].apply(data, args);
1008
- }
1009
- });
1010
- };
1011
-
1012
- $.fn.timepicker.defaults = {
1013
- defaultTime: 'current',
1014
- disableFocus: false,
1015
- disableMousewheel: false,
1016
- isOpen: false,
1017
- minuteStep: 15,
1018
- modalBackdrop: false,
1019
- secondStep: 15,
1020
- showSeconds: false,
1021
- showInputs: true,
1022
- showMeridian: true,
1023
- template: 'dropdown',
1024
- appendWidgetTo: '.bootstrap-timepicker'
1025
- };
1026
-
1027
- $.fn.timepicker.Constructor = Timepicker;
1028
-
1029
- })(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.disableMousewheel = options.disableMousewheel;
21
+ this.isOpen = options.isOpen;
22
+ this.minuteStep = options.minuteStep;
23
+ this.modalBackdrop = options.modalBackdrop;
24
+ this.orientation = options.orientation;
25
+ this.secondStep = options.secondStep;
26
+ this.showInputs = options.showInputs;
27
+ this.showMeridian = options.showMeridian;
28
+ this.showSeconds = options.showSeconds;
29
+ this.template = options.template;
30
+ this.appendWidgetTo = options.appendWidgetTo;
31
+ this.showWidgetOnAddonClick = options.showWidgetOnAddonClick;
32
+
33
+ this._init();
34
+ };
35
+
36
+ Timepicker.prototype = {
37
+
38
+ constructor: Timepicker,
39
+ _init: function() {
40
+ var self = this;
41
+
42
+ if (this.showWidgetOnAddonClick && (this.$element.parent().hasClass('input-append') || this.$element.parent().hasClass('input-prepend'))) {
43
+ this.$element.parent('.input-append, .input-prepend').find('.add-on').on({
44
+ 'click.timepicker': $.proxy(this.showWidget, this)
45
+ });
46
+ this.$element.on({
47
+ 'focus.timepicker': $.proxy(this.highlightUnit, this),
48
+ 'click.timepicker': $.proxy(this.highlightUnit, this),
49
+ 'keydown.timepicker': $.proxy(this.elementKeydown, this),
50
+ 'blur.timepicker': $.proxy(this.blurElement, this),
51
+ 'mousewheel.timepicker DOMMouseScroll.timepicker': $.proxy(this.mousewheel, this)
52
+ });
53
+ } else {
54
+ if (this.template) {
55
+ this.$element.on({
56
+ 'focus.timepicker': $.proxy(this.showWidget, this),
57
+ 'click.timepicker': $.proxy(this.showWidget, this),
58
+ 'blur.timepicker': $.proxy(this.blurElement, this),
59
+ 'mousewheel.timepicker DOMMouseScroll.timepicker': $.proxy(this.mousewheel, this)
60
+ });
61
+ } else {
62
+ this.$element.on({
63
+ 'focus.timepicker': $.proxy(this.highlightUnit, this),
64
+ 'click.timepicker': $.proxy(this.highlightUnit, this),
65
+ 'keydown.timepicker': $.proxy(this.elementKeydown, this),
66
+ 'blur.timepicker': $.proxy(this.blurElement, this),
67
+ 'mousewheel.timepicker DOMMouseScroll.timepicker': $.proxy(this.mousewheel, this)
68
+ });
69
+ }
70
+ }
71
+
72
+ if (this.template !== false) {
73
+ this.$widget = $(this.getTemplate()).on('click', $.proxy(this.widgetClick, this));
74
+ } else {
75
+ this.$widget = false;
76
+ }
77
+
78
+ if (this.showInputs && this.$widget !== false) {
79
+ this.$widget.find('input').each(function() {
80
+ $(this).on({
81
+ 'click.timepicker': function() { $(this).select(); },
82
+ 'keydown.timepicker': $.proxy(self.widgetKeydown, self),
83
+ 'keyup.timepicker': $.proxy(self.widgetKeyup, self)
84
+ });
85
+ });
86
+ }
87
+
88
+ this.setDefaultTime(this.defaultTime);
89
+ },
90
+
91
+ blurElement: function() {
92
+ this.highlightedUnit = null;
93
+ this.updateFromElementVal();
94
+ },
95
+
96
+ clear: function() {
97
+ this.hour = '';
98
+ this.minute = '';
99
+ this.second = '';
100
+ this.meridian = '';
101
+
102
+ this.$element.val('');
103
+ },
104
+
105
+ decrementHour: function() {
106
+ if (this.showMeridian) {
107
+ if (this.hour === 1) {
108
+ this.hour = 12;
109
+ } else if (this.hour === 12) {
110
+ this.hour--;
111
+
112
+ return this.toggleMeridian();
113
+ } else if (this.hour === 0) {
114
+ this.hour = 11;
115
+
116
+ return this.toggleMeridian();
117
+ } else {
118
+ this.hour--;
119
+ }
120
+ } else {
121
+ if (this.hour <= 0) {
122
+ this.hour = 23;
123
+ } else {
124
+ this.hour--;
125
+ }
126
+ }
127
+ },
128
+
129
+ decrementMinute: function(step) {
130
+ var newVal;
131
+
132
+ if (step) {
133
+ newVal = this.minute - step;
134
+ } else {
135
+ newVal = this.minute - this.minuteStep;
136
+ }
137
+
138
+ if (newVal < 0) {
139
+ this.decrementHour();
140
+ this.minute = newVal + 60;
141
+ } else {
142
+ this.minute = newVal;
143
+ }
144
+ },
145
+
146
+ decrementSecond: function() {
147
+ var newVal = this.second - this.secondStep;
148
+
149
+ if (newVal < 0) {
150
+ this.decrementMinute(true);
151
+ this.second = newVal + 60;
152
+ } else {
153
+ this.second = newVal;
154
+ }
155
+ },
156
+
157
+ elementKeydown: function(e) {
158
+ switch (e.keyCode) {
159
+ case 9: //tab
160
+ case 27: // escape
161
+ this.updateFromElementVal();
162
+ break;
163
+ case 37: // left arrow
164
+ e.preventDefault();
165
+ this.highlightPrevUnit();
166
+ break;
167
+ case 38: // up arrow
168
+ e.preventDefault();
169
+ switch (this.highlightedUnit) {
170
+ case 'hour':
171
+ this.incrementHour();
172
+ this.highlightHour();
173
+ break;
174
+ case 'minute':
175
+ this.incrementMinute();
176
+ this.highlightMinute();
177
+ break;
178
+ case 'second':
179
+ this.incrementSecond();
180
+ this.highlightSecond();
181
+ break;
182
+ case 'meridian':
183
+ this.toggleMeridian();
184
+ this.highlightMeridian();
185
+ break;
186
+ }
187
+ this.update();
188
+ break;
189
+ case 39: // right arrow
190
+ e.preventDefault();
191
+ this.highlightNextUnit();
192
+ break;
193
+ case 40: // down arrow
194
+ e.preventDefault();
195
+ switch (this.highlightedUnit) {
196
+ case 'hour':
197
+ this.decrementHour();
198
+ this.highlightHour();
199
+ break;
200
+ case 'minute':
201
+ this.decrementMinute();
202
+ this.highlightMinute();
203
+ break;
204
+ case 'second':
205
+ this.decrementSecond();
206
+ this.highlightSecond();
207
+ break;
208
+ case 'meridian':
209
+ this.toggleMeridian();
210
+ this.highlightMeridian();
211
+ break;
212
+ }
213
+
214
+ this.update();
215
+ break;
216
+ }
217
+ },
218
+
219
+ getCursorPosition: function() {
220
+ var input = this.$element.get(0);
221
+
222
+ if ('selectionStart' in input) {// Standard-compliant browsers
223
+
224
+ return input.selectionStart;
225
+ } else if (document.selection) {// IE fix
226
+ input.focus();
227
+ var sel = document.selection.createRange(),
228
+ selLen = document.selection.createRange().text.length;
229
+
230
+ sel.moveStart('character', - input.value.length);
231
+
232
+ return sel.text.length - selLen;
233
+ }
234
+ },
235
+
236
+ getTemplate: function() {
237
+ var template,
238
+ hourTemplate,
239
+ minuteTemplate,
240
+ secondTemplate,
241
+ meridianTemplate,
242
+ templateContent;
243
+
244
+ if (this.showInputs) {
245
+ hourTemplate = '<input type="text" class="bootstrap-timepicker-hour" maxlength="2"/>';
246
+ minuteTemplate = '<input type="text" class="bootstrap-timepicker-minute" maxlength="2"/>';
247
+ secondTemplate = '<input type="text" class="bootstrap-timepicker-second" maxlength="2"/>';
248
+ meridianTemplate = '<input type="text" class="bootstrap-timepicker-meridian" maxlength="2"/>';
249
+ } else {
250
+ hourTemplate = '<span class="bootstrap-timepicker-hour"></span>';
251
+ minuteTemplate = '<span class="bootstrap-timepicker-minute"></span>';
252
+ secondTemplate = '<span class="bootstrap-timepicker-second"></span>';
253
+ meridianTemplate = '<span class="bootstrap-timepicker-meridian"></span>';
254
+ }
255
+
256
+ templateContent = '<table>'+
257
+ '<tr>'+
258
+ '<td><a href="#" data-action="incrementHour"><i class="icon-chevron-up"></i></a></td>'+
259
+ '<td class="separator">&nbsp;</td>'+
260
+ '<td><a href="#" data-action="incrementMinute"><i class="icon-chevron-up"></i></a></td>'+
261
+ (this.showSeconds ?
262
+ '<td class="separator">&nbsp;</td>'+
263
+ '<td><a href="#" data-action="incrementSecond"><i class="icon-chevron-up"></i></a></td>'
264
+ : '') +
265
+ (this.showMeridian ?
266
+ '<td class="separator">&nbsp;</td>'+
267
+ '<td class="meridian-column"><a href="#" data-action="toggleMeridian"><i class="icon-chevron-up"></i></a></td>'
268
+ : '') +
269
+ '</tr>'+
270
+ '<tr>'+
271
+ '<td>'+ hourTemplate +'</td> '+
272
+ '<td class="separator">:</td>'+
273
+ '<td>'+ minuteTemplate +'</td> '+
274
+ (this.showSeconds ?
275
+ '<td class="separator">:</td>'+
276
+ '<td>'+ secondTemplate +'</td>'
277
+ : '') +
278
+ (this.showMeridian ?
279
+ '<td class="separator">&nbsp;</td>'+
280
+ '<td>'+ meridianTemplate +'</td>'
281
+ : '') +
282
+ '</tr>'+
283
+ '<tr>'+
284
+ '<td><a href="#" data-action="decrementHour"><i class="icon-chevron-down"></i></a></td>'+
285
+ '<td class="separator"></td>'+
286
+ '<td><a href="#" data-action="decrementMinute"><i class="icon-chevron-down"></i></a></td>'+
287
+ (this.showSeconds ?
288
+ '<td class="separator">&nbsp;</td>'+
289
+ '<td><a href="#" data-action="decrementSecond"><i class="icon-chevron-down"></i></a></td>'
290
+ : '') +
291
+ (this.showMeridian ?
292
+ '<td class="separator">&nbsp;</td>'+
293
+ '<td><a href="#" data-action="toggleMeridian"><i class="icon-chevron-down"></i></a></td>'
294
+ : '') +
295
+ '</tr>'+
296
+ '</table>';
297
+
298
+ switch(this.template) {
299
+ case 'modal':
300
+ template = '<div class="bootstrap-timepicker-widget modal hide fade in" data-backdrop="'+ (this.modalBackdrop ? 'true' : 'false') +'">'+
301
+ '<div class="modal-header">'+
302
+ '<a href="#" class="close" data-dismiss="modal">×</a>'+
303
+ '<h3>Pick a Time</h3>'+
304
+ '</div>'+
305
+ '<div class="modal-content">'+
306
+ templateContent +
307
+ '</div>'+
308
+ '<div class="modal-footer">'+
309
+ '<a href="#" class="btn btn-primary" data-dismiss="modal">OK</a>'+
310
+ '</div>'+
311
+ '</div>';
312
+ break;
313
+ case 'dropdown':
314
+ template = '<div class="bootstrap-timepicker-widget dropdown-menu">'+ templateContent +'</div>';
315
+ break;
316
+ }
317
+
318
+ return template;
319
+ },
320
+
321
+ getTime: function() {
322
+ if (this.hour === '') {
323
+ return '';
324
+ }
325
+
326
+ return this.hour + ':' + (this.minute.toString().length === 1 ? '0' + this.minute : this.minute) + (this.showSeconds ? ':' + (this.second.toString().length === 1 ? '0' + this.second : this.second) : '') + (this.showMeridian ? ' ' + this.meridian : '');
327
+ },
328
+
329
+ hideWidget: function() {
330
+ if (this.isOpen === false) {
331
+ return;
332
+ }
333
+
334
+ this.$element.trigger({
335
+ 'type': 'hide.timepicker',
336
+ 'time': {
337
+ 'value': this.getTime(),
338
+ 'hours': this.hour,
339
+ 'minutes': this.minute,
340
+ 'seconds': this.second,
341
+ 'meridian': this.meridian
342
+ }
343
+ });
344
+
345
+ if (this.template === 'modal' && this.$widget.modal) {
346
+ this.$widget.modal('hide');
347
+ } else {
348
+ this.$widget.removeClass('open');
349
+ }
350
+
351
+ $(document).off('mousedown.timepicker, touchend.timepicker');
352
+
353
+ this.isOpen = false;
354
+ // show/hide approach taken by datepicker
355
+ this.$widget.detach();
356
+ },
357
+
358
+ highlightUnit: function() {
359
+ this.position = this.getCursorPosition();
360
+ if (this.position >= 0 && this.position <= 2) {
361
+ this.highlightHour();
362
+ } else if (this.position >= 3 && this.position <= 5) {
363
+ this.highlightMinute();
364
+ } else if (this.position >= 6 && this.position <= 8) {
365
+ if (this.showSeconds) {
366
+ this.highlightSecond();
367
+ } else {
368
+ this.highlightMeridian();
369
+ }
370
+ } else if (this.position >= 9 && this.position <= 11) {
371
+ this.highlightMeridian();
372
+ }
373
+ },
374
+
375
+ highlightNextUnit: function() {
376
+ switch (this.highlightedUnit) {
377
+ case 'hour':
378
+ this.highlightMinute();
379
+ break;
380
+ case 'minute':
381
+ if (this.showSeconds) {
382
+ this.highlightSecond();
383
+ } else if (this.showMeridian){
384
+ this.highlightMeridian();
385
+ } else {
386
+ this.highlightHour();
387
+ }
388
+ break;
389
+ case 'second':
390
+ if (this.showMeridian) {
391
+ this.highlightMeridian();
392
+ } else {
393
+ this.highlightHour();
394
+ }
395
+ break;
396
+ case 'meridian':
397
+ this.highlightHour();
398
+ break;
399
+ }
400
+ },
401
+
402
+ highlightPrevUnit: function() {
403
+ switch (this.highlightedUnit) {
404
+ case 'hour':
405
+ if(this.showMeridian){
406
+ this.highlightMeridian();
407
+ } else if (this.showSeconds) {
408
+ this.highlightSecond();
409
+ } else {
410
+ this.highlightMinute();
411
+ }
412
+ break;
413
+ case 'minute':
414
+ this.highlightHour();
415
+ break;
416
+ case 'second':
417
+ this.highlightMinute();
418
+ break;
419
+ case 'meridian':
420
+ if (this.showSeconds) {
421
+ this.highlightSecond();
422
+ } else {
423
+ this.highlightMinute();
424
+ }
425
+ break;
426
+ }
427
+ },
428
+
429
+ highlightHour: function() {
430
+ var $element = this.$element.get(0),
431
+ self = this;
432
+
433
+ this.highlightedUnit = 'hour';
434
+
435
+ if ($element.setSelectionRange) {
436
+ setTimeout(function() {
437
+ if (self.hour < 10) {
438
+ $element.setSelectionRange(0,1);
439
+ } else {
440
+ $element.setSelectionRange(0,2);
441
+ }
442
+ }, 0);
443
+ }
444
+ },
445
+
446
+ highlightMinute: function() {
447
+ var $element = this.$element.get(0),
448
+ self = this;
449
+
450
+ this.highlightedUnit = 'minute';
451
+
452
+ if ($element.setSelectionRange) {
453
+ setTimeout(function() {
454
+ if (self.hour < 10) {
455
+ $element.setSelectionRange(2,4);
456
+ } else {
457
+ $element.setSelectionRange(3,5);
458
+ }
459
+ }, 0);
460
+ }
461
+ },
462
+
463
+ highlightSecond: function() {
464
+ var $element = this.$element.get(0),
465
+ self = this;
466
+
467
+ this.highlightedUnit = 'second';
468
+
469
+ if ($element.setSelectionRange) {
470
+ setTimeout(function() {
471
+ if (self.hour < 10) {
472
+ $element.setSelectionRange(5,7);
473
+ } else {
474
+ $element.setSelectionRange(6,8);
475
+ }
476
+ }, 0);
477
+ }
478
+ },
479
+
480
+ highlightMeridian: function() {
481
+ var $element = this.$element.get(0),
482
+ self = this;
483
+
484
+ this.highlightedUnit = 'meridian';
485
+
486
+ if ($element.setSelectionRange) {
487
+ if (this.showSeconds) {
488
+ setTimeout(function() {
489
+ if (self.hour < 10) {
490
+ $element.setSelectionRange(8,10);
491
+ } else {
492
+ $element.setSelectionRange(9,11);
493
+ }
494
+ }, 0);
495
+ } else {
496
+ setTimeout(function() {
497
+ if (self.hour < 10) {
498
+ $element.setSelectionRange(5,7);
499
+ } else {
500
+ $element.setSelectionRange(6,8);
501
+ }
502
+ }, 0);
503
+ }
504
+ }
505
+ },
506
+
507
+ incrementHour: function() {
508
+ if (this.showMeridian) {
509
+ if (this.hour === 11) {
510
+ this.hour++;
511
+ return this.toggleMeridian();
512
+ } else if (this.hour === 12) {
513
+ this.hour = 0;
514
+ }
515
+ }
516
+ if (this.hour === 23) {
517
+ this.hour = 0;
518
+
519
+ return;
520
+ }
521
+ this.hour++;
522
+ },
523
+
524
+ incrementMinute: function(step) {
525
+ var newVal;
526
+
527
+ if (step) {
528
+ newVal = this.minute + step;
529
+ } else {
530
+ newVal = this.minute + this.minuteStep - (this.minute % this.minuteStep);
531
+ }
532
+
533
+ if (newVal > 59) {
534
+ this.incrementHour();
535
+ this.minute = newVal - 60;
536
+ } else {
537
+ this.minute = newVal;
538
+ }
539
+ },
540
+
541
+ incrementSecond: function() {
542
+ var newVal = this.second + this.secondStep - (this.second % this.secondStep);
543
+
544
+ if (newVal > 59) {
545
+ this.incrementMinute(true);
546
+ this.second = newVal - 60;
547
+ } else {
548
+ this.second = newVal;
549
+ }
550
+ },
551
+
552
+ mousewheel: function(e) {
553
+ if (this.disableMousewheel) {
554
+ return;
555
+ }
556
+
557
+ e.preventDefault();
558
+ e.stopPropagation();
559
+
560
+ var delta = e.originalEvent.wheelDelta || -e.originalEvent.detail,
561
+ scrollTo = null;
562
+
563
+ if (e.type === 'mousewheel') {
564
+ scrollTo = (e.originalEvent.wheelDelta * -1);
565
+ }
566
+ else if (e.type === 'DOMMouseScroll') {
567
+ scrollTo = 40 * e.originalEvent.detail;
568
+ }
569
+
570
+ if (scrollTo) {
571
+ e.preventDefault();
572
+ $(this).scrollTop(scrollTo + $(this).scrollTop());
573
+ }
574
+
575
+ switch (this.highlightedUnit) {
576
+ case 'minute':
577
+ if (delta > 0) {
578
+ this.incrementMinute();
579
+ } else {
580
+ this.decrementMinute();
581
+ }
582
+ this.highlightMinute();
583
+ break;
584
+ case 'second':
585
+ if (delta > 0) {
586
+ this.incrementSecond();
587
+ } else {
588
+ this.decrementSecond();
589
+ }
590
+ this.highlightSecond();
591
+ break;
592
+ case 'meridian':
593
+ this.toggleMeridian();
594
+ this.highlightMeridian();
595
+ break;
596
+ default:
597
+ if (delta > 0) {
598
+ this.incrementHour();
599
+ } else {
600
+ this.decrementHour();
601
+ }
602
+ this.highlightHour();
603
+ break;
604
+ }
605
+
606
+ return false;
607
+ },
608
+
609
+ // This method was adapted from bootstrap-datepicker.
610
+ place : function() {
611
+ if (this.isInline) {
612
+ return;
613
+ }
614
+ var widgetWidth = this.$widget.outerWidth(), widgetHeight = this.$widget.outerHeight(), visualPadding = 10, windowWidth =
615
+ $(window).width(), windowHeight = $(window).height(), scrollTop = $(window).scrollTop();
616
+
617
+ var zIndex = parseInt(this.$element.parents().filter(function() {}).first().css('z-index'), 10) + 10;
618
+ var offset = this.component ? this.component.parent().offset() : this.$element.offset();
619
+ var height = this.component ? this.component.outerHeight(true) : this.$element.outerHeight(false);
620
+ var width = this.component ? this.component.outerWidth(true) : this.$element.outerWidth(false);
621
+ var left = offset.left, top = offset.top;
622
+
623
+ this.$widget.removeClass('timepicker-orient-top timepicker-orient-bottom timepicker-orient-right timepicker-orient-left');
624
+
625
+ if (this.orientation.x !== 'auto') {
626
+ this.picker.addClass('datepicker-orient-' + this.orientation.x);
627
+ if (this.orientation.x === 'right') {
628
+ left -= widgetWidth - width;
629
+ }
630
+ } else{
631
+ // auto x orientation is best-placement: if it crosses a window edge, fudge it sideways
632
+ // Default to left
633
+ this.$widget.addClass('timepicker-orient-left');
634
+ if (offset.left < 0) {
635
+ left -= offset.left - visualPadding;
636
+ } else if (offset.left + widgetWidth > windowWidth) {
637
+ left = windowWidth - widgetWidth - visualPadding;
638
+ }
639
+ }
640
+ // auto y orientation is best-situation: top or bottom, no fudging, decision based on which shows more of the widget
641
+ var yorient = this.orientation.y, topOverflow, bottomOverflow;
642
+ if (yorient === 'auto') {
643
+ topOverflow = -scrollTop + offset.top - widgetHeight;
644
+ bottomOverflow = scrollTop + windowHeight - (offset.top + height + widgetHeight);
645
+ if (Math.max(topOverflow, bottomOverflow) === bottomOverflow) {
646
+ yorient = 'top';
647
+ } else {
648
+ yorient = 'bottom';
649
+ }
650
+ }
651
+ this.$widget.addClass('timepicker-orient-' + yorient);
652
+ if (yorient === 'top'){
653
+ top += height;
654
+ } else{
655
+ top -= widgetHeight + parseInt(this.$widget.css('padding-top'), 10);
656
+ }
657
+
658
+ this.$widget.css({
659
+ top : top,
660
+ left : left,
661
+ zIndex : zIndex
662
+ });
663
+ },
664
+
665
+ remove: function() {
666
+ $('document').off('.timepicker');
667
+ if (this.$widget) {
668
+ this.$widget.remove();
669
+ }
670
+ delete this.$element.data().timepicker;
671
+ },
672
+
673
+ setDefaultTime: function(defaultTime) {
674
+ if (!this.$element.val()) {
675
+ if (defaultTime === 'current') {
676
+ var dTime = new Date(),
677
+ hours = dTime.getHours(),
678
+ minutes = dTime.getMinutes(),
679
+ seconds = dTime.getSeconds(),
680
+ meridian = 'AM';
681
+
682
+ if (seconds !== 0) {
683
+ seconds = Math.ceil(dTime.getSeconds() / this.secondStep) * this.secondStep;
684
+ if (seconds === 60) {
685
+ minutes += 1;
686
+ seconds = 0;
687
+ }
688
+ }
689
+
690
+ if (minutes !== 0) {
691
+ minutes = Math.ceil(dTime.getMinutes() / this.minuteStep) * this.minuteStep;
692
+ if (minutes === 60) {
693
+ hours += 1;
694
+ minutes = 0;
695
+ }
696
+ }
697
+
698
+ if (this.showMeridian) {
699
+ if (hours === 0) {
700
+ hours = 12;
701
+ } else if (hours >= 12) {
702
+ if (hours > 12) {
703
+ hours = hours - 12;
704
+ }
705
+ meridian = 'PM';
706
+ } else {
707
+ meridian = 'AM';
708
+ }
709
+ }
710
+
711
+ this.hour = hours;
712
+ this.minute = minutes;
713
+ this.second = seconds;
714
+ this.meridian = meridian;
715
+
716
+ this.update();
717
+
718
+ } else if (defaultTime === false) {
719
+ this.hour = 0;
720
+ this.minute = 0;
721
+ this.second = 0;
722
+ this.meridian = 'AM';
723
+ } else {
724
+ this.setTime(defaultTime);
725
+ }
726
+ } else {
727
+ this.updateFromElementVal();
728
+ }
729
+ },
730
+
731
+ setTime: function(time, ignoreWidget) {
732
+ if (!time) {
733
+ this.clear();
734
+ return;
735
+ }
736
+
737
+ var timeArray,
738
+ hour,
739
+ minute,
740
+ second,
741
+ meridian;
742
+
743
+ if (typeof time === 'object' && time.getMonth){
744
+ // this is a date object
745
+ hour = time.getHours();
746
+ minute = time.getMinutes();
747
+ second = time.getSeconds();
748
+
749
+ if (this.showMeridian){
750
+ meridian = 'AM';
751
+ if (hour > 12){
752
+ meridian = 'PM';
753
+ hour = hour % 12;
754
+ }
755
+
756
+ if (hour === 12){
757
+ meridian = 'PM';
758
+ }
759
+ }
760
+ } else {
761
+ if (time.match(/p/i) !== null) {
762
+ meridian = 'PM';
763
+ } else {
764
+ meridian = 'AM';
765
+ }
766
+
767
+ time = time.replace(/[^0-9\:]/g, '');
768
+
769
+ timeArray = time.split(':');
770
+
771
+ hour = timeArray[0] ? timeArray[0].toString() : timeArray.toString();
772
+ minute = timeArray[1] ? timeArray[1].toString() : '';
773
+ second = timeArray[2] ? timeArray[2].toString() : '';
774
+
775
+ // idiot proofing
776
+ if (hour.length > 4) {
777
+ second = hour.substr(4, 2);
778
+ }
779
+ if (hour.length > 2) {
780
+ minute = hour.substr(2, 2);
781
+ hour = hour.substr(0, 2);
782
+ }
783
+ if (minute.length > 2) {
784
+ second = minute.substr(2, 2);
785
+ minute = minute.substr(0, 2);
786
+ }
787
+ if (second.length > 2) {
788
+ second = second.substr(2, 2);
789
+ }
790
+
791
+ hour = parseInt(hour, 10);
792
+ minute = parseInt(minute, 10);
793
+ second = parseInt(second, 10);
794
+
795
+ if (isNaN(hour)) {
796
+ hour = 0;
797
+ }
798
+ if (isNaN(minute)) {
799
+ minute = 0;
800
+ }
801
+ if (isNaN(second)) {
802
+ second = 0;
803
+ }
804
+
805
+ if (this.showMeridian) {
806
+ if (hour < 1) {
807
+ hour = 1;
808
+ } else if (hour > 12) {
809
+ hour = 12;
810
+ }
811
+ } else {
812
+ if (hour >= 24) {
813
+ hour = 23;
814
+ } else if (hour < 0) {
815
+ hour = 0;
816
+ }
817
+ if (hour < 13 && meridian === 'PM') {
818
+ hour = hour + 12;
819
+ }
820
+ }
821
+
822
+ if (minute < 0) {
823
+ minute = 0;
824
+ } else if (minute >= 60) {
825
+ minute = 59;
826
+ }
827
+
828
+ if (this.showSeconds) {
829
+ if (isNaN(second)) {
830
+ second = 0;
831
+ } else if (second < 0) {
832
+ second = 0;
833
+ } else if (second >= 60) {
834
+ second = 59;
835
+ }
836
+ }
837
+ }
838
+
839
+ this.hour = hour;
840
+ this.minute = minute;
841
+ this.second = second;
842
+ this.meridian = meridian;
843
+
844
+ this.update(ignoreWidget);
845
+ },
846
+
847
+ showWidget: function() {
848
+ if (this.isOpen) {
849
+ return;
850
+ }
851
+
852
+ if (this.$element.is(':disabled')) {
853
+ return;
854
+ }
855
+
856
+ // show/hide approach taken by datepicker
857
+ this.$widget.appendTo(this.appendWidgetTo);
858
+ var self = this;
859
+ $(document).on('mousedown.timepicker, touchend.timepicker', function (e) {
860
+ // This condition was inspired by bootstrap-datepicker.
861
+ // The element the timepicker is invoked on is the input but it has a sibling for addon/button.
862
+ if (!(self.$element.parent().find(e.target).length ||
863
+ self.$widget.is(e.target) ||
864
+ self.$widget.find(e.target).length)) {
865
+ self.hideWidget();
866
+ }
867
+ });
868
+
869
+ this.$element.trigger({
870
+ 'type': 'show.timepicker',
871
+ 'time': {
872
+ 'value': this.getTime(),
873
+ 'hours': this.hour,
874
+ 'minutes': this.minute,
875
+ 'seconds': this.second,
876
+ 'meridian': this.meridian
877
+ }
878
+ });
879
+
880
+ this.place();
881
+ if (this.disableFocus) {
882
+ this.$element.blur();
883
+ }
884
+
885
+ // widget shouldn't be empty on open
886
+ if (this.hour === '') {
887
+ if (this.defaultTime) {
888
+ this.setDefaultTime(this.defaultTime);
889
+ } else {
890
+ this.setTime('0:0:0');
891
+ }
892
+ }
893
+
894
+ if (this.template === 'modal' && this.$widget.modal) {
895
+ this.$widget.modal('show').on('hidden', $.proxy(this.hideWidget, this));
896
+ } else {
897
+ if (this.isOpen === false) {
898
+ this.$widget.addClass('open');
899
+ }
900
+ }
901
+
902
+ this.isOpen = true;
903
+ },
904
+
905
+ toggleMeridian: function() {
906
+ this.meridian = this.meridian === 'AM' ? 'PM' : 'AM';
907
+ },
908
+
909
+ update: function(ignoreWidget) {
910
+ this.updateElement();
911
+ if (!ignoreWidget) {
912
+ this.updateWidget();
913
+ }
914
+
915
+ this.$element.trigger({
916
+ 'type': 'changeTime.timepicker',
917
+ 'time': {
918
+ 'value': this.getTime(),
919
+ 'hours': this.hour,
920
+ 'minutes': this.minute,
921
+ 'seconds': this.second,
922
+ 'meridian': this.meridian
923
+ }
924
+ });
925
+ },
926
+
927
+ updateElement: function() {
928
+ this.$element.val(this.getTime()).change();
929
+ },
930
+
931
+ updateFromElementVal: function() {
932
+ this.setTime(this.$element.val());
933
+ },
934
+
935
+ updateWidget: function() {
936
+ if (this.$widget === false) {
937
+ return;
938
+ }
939
+
940
+ var hour = this.hour,
941
+ minute = this.minute.toString().length === 1 ? '0' + this.minute : this.minute,
942
+ second = this.second.toString().length === 1 ? '0' + this.second : this.second;
943
+
944
+ if (this.showInputs) {
945
+ this.$widget.find('input.bootstrap-timepicker-hour').val(hour);
946
+ this.$widget.find('input.bootstrap-timepicker-minute').val(minute);
947
+
948
+ if (this.showSeconds) {
949
+ this.$widget.find('input.bootstrap-timepicker-second').val(second);
950
+ }
951
+ if (this.showMeridian) {
952
+ this.$widget.find('input.bootstrap-timepicker-meridian').val(this.meridian);
953
+ }
954
+ } else {
955
+ this.$widget.find('span.bootstrap-timepicker-hour').text(hour);
956
+ this.$widget.find('span.bootstrap-timepicker-minute').text(minute);
957
+
958
+ if (this.showSeconds) {
959
+ this.$widget.find('span.bootstrap-timepicker-second').text(second);
960
+ }
961
+ if (this.showMeridian) {
962
+ this.$widget.find('span.bootstrap-timepicker-meridian').text(this.meridian);
963
+ }
964
+ }
965
+ },
966
+
967
+ updateFromWidgetInputs: function() {
968
+ if (this.$widget === false) {
969
+ return;
970
+ }
971
+
972
+ var t = this.$widget.find('input.bootstrap-timepicker-hour').val() + ':' +
973
+ this.$widget.find('input.bootstrap-timepicker-minute').val() +
974
+ (this.showSeconds ? ':' + this.$widget.find('input.bootstrap-timepicker-second').val() : '') +
975
+ (this.showMeridian ? this.$widget.find('input.bootstrap-timepicker-meridian').val() : '')
976
+ ;
977
+
978
+ this.setTime(t, true);
979
+ },
980
+
981
+ widgetClick: function(e) {
982
+ e.stopPropagation();
983
+ e.preventDefault();
984
+
985
+ var $input = $(e.target),
986
+ action = $input.closest('a').data('action');
987
+
988
+ if (action) {
989
+ this[action]();
990
+ }
991
+ this.update();
992
+
993
+ if ($input.is('input')) {
994
+ $input.get(0).setSelectionRange(0,2);
995
+ }
996
+ },
997
+
998
+ widgetKeydown: function(e) {
999
+ var $input = $(e.target),
1000
+ name = $input.attr('class').replace('bootstrap-timepicker-', '');
1001
+
1002
+ switch (e.keyCode) {
1003
+ case 9: //tab
1004
+ if ((this.showMeridian && name === 'meridian') || (this.showSeconds && name === 'second') || (!this.showMeridian && !this.showSeconds && name === 'minute')) {
1005
+ return this.hideWidget();
1006
+ }
1007
+ break;
1008
+ case 27: // escape
1009
+ this.hideWidget();
1010
+ break;
1011
+ case 38: // up arrow
1012
+ e.preventDefault();
1013
+ switch (name) {
1014
+ case 'hour':
1015
+ this.incrementHour();
1016
+ break;
1017
+ case 'minute':
1018
+ this.incrementMinute();
1019
+ break;
1020
+ case 'second':
1021
+ this.incrementSecond();
1022
+ break;
1023
+ case 'meridian':
1024
+ this.toggleMeridian();
1025
+ break;
1026
+ }
1027
+ this.setTime(this.getTime());
1028
+ $input.get(0).setSelectionRange(0,2);
1029
+ break;
1030
+ case 40: // down arrow
1031
+ e.preventDefault();
1032
+ switch (name) {
1033
+ case 'hour':
1034
+ this.decrementHour();
1035
+ break;
1036
+ case 'minute':
1037
+ this.decrementMinute();
1038
+ break;
1039
+ case 'second':
1040
+ this.decrementSecond();
1041
+ break;
1042
+ case 'meridian':
1043
+ this.toggleMeridian();
1044
+ break;
1045
+ }
1046
+ this.setTime(this.getTime());
1047
+ $input.get(0).setSelectionRange(0,2);
1048
+ break;
1049
+ }
1050
+ },
1051
+
1052
+ widgetKeyup: function(e) {
1053
+ if ((e.keyCode === 65) || (e.keyCode === 77) || (e.keyCode === 80) || (e.keyCode === 46) || (e.keyCode === 8) || (e.keyCode >= 46 && e.keyCode <= 57)) {
1054
+ this.updateFromWidgetInputs();
1055
+ }
1056
+ }
1057
+ };
1058
+
1059
+ //TIMEPICKER PLUGIN DEFINITION
1060
+ $.fn.timepicker = function(option) {
1061
+ var args = Array.apply(null, arguments);
1062
+ args.shift();
1063
+ return this.each(function() {
1064
+ var $this = $(this),
1065
+ data = $this.data('timepicker'),
1066
+ options = typeof option === 'object' && option;
1067
+
1068
+ if (!data) {
1069
+ $this.data('timepicker', (data = new Timepicker(this, $.extend({}, $.fn.timepicker.defaults, options, $(this).data()))));
1070
+ }
1071
+
1072
+ if (typeof option === 'string') {
1073
+ data[option].apply(data, args);
1074
+ }
1075
+ });
1076
+ };
1077
+
1078
+ $.fn.timepicker.defaults = {
1079
+ defaultTime: 'current',
1080
+ disableFocus: false,
1081
+ disableMousewheel: false,
1082
+ isOpen: false,
1083
+ minuteStep: 15,
1084
+ modalBackdrop: false,
1085
+ orientation: { x: 'auto', y: 'auto'},
1086
+ secondStep: 15,
1087
+ showSeconds: false,
1088
+ showInputs: true,
1089
+ showMeridian: true,
1090
+ template: 'dropdown',
1091
+ appendWidgetTo: 'body',
1092
+ showWidgetOnAddonClick: true
1093
+ };
1094
+
1095
+ $.fn.timepicker.Constructor = Timepicker;
1096
+
1097
+ })(jQuery, window, document);