contour 1.1.3 → 1.2.0.pre

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