bootstrap-timepicker-rails-addon 0.2.6.1 → 0.2.6.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2694f17a4761a18db42b46d55b1e867026cb02a9
4
- data.tar.gz: ea62c8d055d8687161a0bfcee2c06517f6ba7ecf
3
+ metadata.gz: 73ef986c743ddd07b6efa2abc64c65c3f9888b49
4
+ data.tar.gz: e7303c0b0db59c96dd3c51fa9e426b00b321d52d
5
5
  SHA512:
6
- metadata.gz: 2d2e5e51de5a3d959da06b06a28ded6c35cc7cf135199b0b624b25e5bd81a44d139f13f9dd94595568230476ae481343d12699aba2d1ee44250daef3aea593f5
7
- data.tar.gz: f7e42492cc187d4f02f1427c3ad1469d574b9b4caf78142ec8e1e925938ec3f18dafd3a1af51fa2dd8a95c6ca53b5bfda7f118cb59c9dd16ebb57461b2cf0438
6
+ metadata.gz: c71615436357e27de40230de0cc7ddf2a8d6cf8ae3dae38aad63159aaac6a489494f6c51db06e8228c4e94dcc6c6d15373f234f2e824d160da3555a2d47364c6
7
+ data.tar.gz: 0ffdef80c3570637f38f65cbe6e370c9c8bfbf4a84f7f0ebf30df64515c5b0fbde1b0938bb371a93a716481db6ce14f4af704ebb2a6d9af9a5f3e23959f35ac6
data/LICENSE CHANGED
@@ -1,22 +1,22 @@
1
- Copyright (c) 2013
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2013
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,62 +1,62 @@
1
- # Bootstrap::Timepicker::Rails::Addon
2
- This is the GEMified version of [bootstrap-timepicker](https://github.com/jdewit/bootstrap-timepicker)
3
-
4
- bootstrap-timepicker-rails-addon project integrates Timepicker for Twitter Bootstrap 2.x with Rails 3 and 4 assets pipeline.
5
-
6
- ## Installation
7
-
8
- Add this line to your application's Gemfile:
9
-
10
- gem 'bootstrap-sass', '~> 2.3.2.0'
11
- gem 'bootstrap-timepicker-rails-addon'
12
-
13
- Or you can install from latest build:
14
-
15
- ```ruby
16
- gem 'bootstrap-sass', '~> 2.3.2.0'
17
- gem 'bootstrap-timepicker-rails-addon', :require => 'bootstrap-timepicker-rails-addon',
18
- :git => 'git://github.com/ywjno/bootstrap-timepicker-rails-addon.git'
19
- ```
20
-
21
- And then execute:
22
-
23
- $ bundle
24
-
25
- Or install it yourself as:
26
-
27
- $ gem install bootstrap-timepicker-rails-addon
28
-
29
- ## Usage
30
-
31
- Add this line to app/assets/javascripts/application.js
32
-
33
- //= require bootstrap-timepicker
34
-
35
- Add this line to app/assets/stylesheets/application.css
36
-
37
- *= require bootstrap-timepicker
38
-
39
- Just call timepicker() with any selector in view.
40
-
41
- ```javascript
42
- $('#timepicker').timepicker();
43
- ```
44
-
45
- And here is the html code sample.
46
-
47
- ```html
48
- <div class="input-append bootstrap-timepicker">
49
- <input id="timepicker" type="text" class="input-small">
50
- <span class="add-on"><i class="icon-time"></i></span>
51
- </div>
52
- ```
53
-
54
- Please view the bootstrap-timepicker <a href="http://jdewit.github.io/bootstrap-timepicker/">demos & documentation</a>.
55
-
56
- ## Contributing
57
-
58
- 1. Fork it
59
- 2. Create your feature branch (`git checkout -b my-new-feature`)
60
- 3. Commit your changes (`git commit -am 'Add some feature'`)
61
- 4. Push to the branch (`git push origin my-new-feature`)
62
- 5. Create new Pull Request
1
+ # Bootstrap::Timepicker::Rails::Addon
2
+ This is the GEMified version of [bootstrap-timepicker](https://github.com/jdewit/bootstrap-timepicker)
3
+
4
+ bootstrap-timepicker-rails-addon project integrates Timepicker for Twitter Bootstrap 2.x with Rails 3 and 4 assets pipeline.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'bootstrap-sass', '~> 2.3.2.0'
11
+ gem 'bootstrap-timepicker-rails-addon'
12
+
13
+ Or you can install from latest build:
14
+
15
+ ```ruby
16
+ gem 'bootstrap-sass', '~> 2.3.2.0'
17
+ gem 'bootstrap-timepicker-rails-addon', :require => 'bootstrap-timepicker-rails-addon',
18
+ :git => 'git://github.com/ywjno/bootstrap-timepicker-rails-addon.git'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install bootstrap-timepicker-rails-addon
28
+
29
+ ## Usage
30
+
31
+ Add this line to app/assets/javascripts/application.js
32
+
33
+ //= require bootstrap-timepicker
34
+
35
+ Add this line to app/assets/stylesheets/application.css
36
+
37
+ *= require bootstrap-timepicker
38
+
39
+ Just call timepicker() with any selector in view.
40
+
41
+ ```javascript
42
+ $('#timepicker').timepicker();
43
+ ```
44
+
45
+ And here is the html code sample.
46
+
47
+ ```html
48
+ <div class="input-append bootstrap-timepicker">
49
+ <input id="timepicker" type="text" class="input-small">
50
+ <span class="add-on"><i class="icon-time"></i></span>
51
+ </div>
52
+ ```
53
+
54
+ Please view the bootstrap-timepicker <a href="http://jdewit.github.io/bootstrap-timepicker/">demos & documentation</a>.
55
+
56
+ ## Contributing
57
+
58
+ 1. Fork it
59
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
60
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
61
+ 4. Push to the branch (`git push origin my-new-feature`)
62
+ 5. Create new Pull Request
@@ -1,12 +1,12 @@
1
- require "bootstrap-timepicker-rails-addon/version"
2
-
3
- module Bootstrap
4
- module Timepicker
5
- module Rails
6
- module Addon
7
- class Engine < ::Rails::Engine
8
- end
9
- end
10
- end
11
- end
12
- end
1
+ require "bootstrap-timepicker-rails-addon/version"
2
+
3
+ module Bootstrap
4
+ module Timepicker
5
+ module Rails
6
+ module Addon
7
+ class Engine < ::Rails::Engine
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,9 +1,9 @@
1
- module Bootstrap
2
- module Timepicker
3
- module Rails
4
- module Addon
5
- VERSION = "0.2.6.1"
6
- end
7
- end
8
- end
9
- end
1
+ module Bootstrap
2
+ module Timepicker
3
+ module Rails
4
+ module Addon
5
+ VERSION = "0.2.6.2"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,1097 +1,1111 @@
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);
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) || (e.keyCode >= 96 && e.keyCode <= 105)) {
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
+ $(document).on(
1098
+ 'focus.timepicker.data-api click.timepicker.data-api',
1099
+ '[data-provide="timepicker"]',
1100
+ function(e){
1101
+ var $this = $(this);
1102
+ if ($this.data('timepicker')) {
1103
+ return;
1104
+ }
1105
+ e.preventDefault();
1106
+ // component click requires us to explicitly show it
1107
+ $this.timepicker();
1108
+ }
1109
+ );
1110
+
1111
+ })(jQuery, window, document);