blueshift 0.0.1

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