jquery-timepicker-rails 1.1.0.0 → 1.2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  module Jquery
2
2
  module Timepicker
3
3
  module Rails
4
- VERSION = "1.1.0.0"
4
+ VERSION = "1.2.2.0"
5
5
  end
6
6
  end
7
7
  end
@@ -1,10 +1,11 @@
1
1
  $(function() {
2
-
3
- var DATE_FORMAT = 'Y-m-d';
4
2
  var DATEPICKER_FORMAT = 'yyyy-m-d';
3
+ var TIMEPICKER_FORMAT = 'g:ia';
4
+ var DATE_FORMAT = 'Y-n-j'; // for this format see http://php.net/manual/function.date.php
5
5
 
6
6
  $('.datepair input.date').each(function(){
7
7
  var $this = $(this);
8
+
8
9
  $this.datepicker({
9
10
  'format': DATEPICKER_FORMAT,
10
11
  'autoclose': true
@@ -18,13 +19,21 @@ $(function() {
18
19
 
19
20
  $('.datepair input.time').each(function() {
20
21
  var $this = $(this);
21
- var opts = { 'showDuration': true, 'timeFormat': 'g:ia', 'scrollDefaultNow': true };
22
+
23
+ $this.timepicker({
24
+ 'showDuration': true,
25
+ 'timeFormat': TIMEPICKER_FORMAT,
26
+ 'scrollDefaultNow': true
27
+ });
22
28
 
23
29
  if ($this.hasClass('start') || $this.hasClass('end')) {
24
- opts.onSelect = doDatepair;
30
+ $this.on('changeTime change', doDatepair);
25
31
  }
32
+
33
+ if ($this.hasClass('end')) {
34
+ $this.on('focus', function(){$('.ui-timepicker-with-duration').scrollTop(0);});
35
+ }
26
36
 
27
- $this.timepicker(opts);
28
37
  });
29
38
 
30
39
  $('.datepair').each(initDatepair);
@@ -38,11 +47,10 @@ $(function() {
38
47
  var dateDelta = 0;
39
48
 
40
49
  if (startDateInput.length && endDateInput.length) {
41
- var startDate = new Date(startDateInput.val());
42
- var endDate = new Date(endDateInput.val());
50
+ var startDate = parseDate(startDateInput.val(), DATEPICKER_FORMAT);
51
+ var endDate = parseDate(endDateInput.val(), DATEPICKER_FORMAT);
43
52
 
44
53
  dateDelta = endDate.getTime() - startDate.getTime();
45
-
46
54
  container.data('dateDelta', dateDelta);
47
55
  }
48
56
 
@@ -82,17 +90,16 @@ $(function() {
82
90
  {
83
91
  var start = container.find('input.start.date');
84
92
  var end = container.find('input.end.date');
85
-
86
93
  if (!start.length || !end.length) {
87
94
  return;
88
95
  }
89
96
 
90
- var startDate = new Date(start.val());
91
- var endDate = new Date(end.val());
97
+ var startDate = parseDate(start.val(), DATEPICKER_FORMAT);
98
+ var endDate = parseDate(end.val(), DATEPICKER_FORMAT);
92
99
 
93
100
  var oldDelta = container.data('dateDelta');
94
101
 
95
- if (oldDelta && target.hasClass('start')) {
102
+ if (!isNaN(oldDelta) && oldDelta !== null && target.hasClass('start')) {
96
103
  var newEnd = new Date(startDate.getTime()+oldDelta);
97
104
  end.val(newEnd.format(DATE_FORMAT));
98
105
  end.datepicker('update');
@@ -132,20 +139,24 @@ $(function() {
132
139
  var start = container.find('input.start.time');
133
140
  var end = container.find('input.end.time');
134
141
 
135
- if (!start.length || !end.length) {
142
+ if (!start.length) {
136
143
  return;
137
144
  }
138
145
 
139
146
  var startInt = start.timepicker('getSecondsFromMidnight');
140
- var endInt = end.timepicker('getSecondsFromMidnight');
141
-
142
- var oldDelta = container.data('timeDelta');
143
147
  var dateDelta = container.data('dateDelta');
144
148
 
145
149
  if (target.hasClass('start') && (!dateDelta || dateDelta < 86400000)) {
146
150
  end.timepicker('option', 'minTime', startInt);
147
151
  }
148
152
 
153
+ if (!end.length) {
154
+ return;
155
+ }
156
+
157
+ var endInt = end.timepicker('getSecondsFromMidnight');
158
+ var oldDelta = container.data('timeDelta');
159
+
149
160
  var endDateAdvance = 0;
150
161
  var newDelta;
151
162
 
@@ -170,11 +181,11 @@ $(function() {
170
181
 
171
182
  if (newDelta < 0 && (!oldDelta || oldDelta > 0)) {
172
183
  // overnight time span. advance the end date 1 day
173
- var endDateAdvance = 86400000;
184
+ endDateAdvance = 86400000;
174
185
 
175
186
  } else if (newDelta > 0 && oldDelta < 0) {
176
187
  // switching from overnight to same-day time span. decrease the end date 1 day
177
- var endDateAdvance = -86400000;
188
+ endDateAdvance = -86400000;
178
189
  }
179
190
 
180
191
  var startInput = container.find('.start.date');
@@ -189,7 +200,7 @@ $(function() {
189
200
 
190
201
  if (endDateAdvance != 0) {
191
202
  if (dateDelta || dateDelta === 0) {
192
- var endDate = new Date(endInput.val());
203
+ var endDate = parseDate(endInput.val(), DATEPICKER_FORMAT);
193
204
  var newEnd = new Date(endDate.getTime() + endDateAdvance);
194
205
  endInput.val(newEnd.format(DATE_FORMAT));
195
206
  endInput.datepicker('update');
@@ -199,5 +210,17 @@ $(function() {
199
210
  }
200
211
  });
201
212
 
213
+ function parseDate(input, format) {
214
+ if (input == '')
215
+ return new Date('');
216
+
217
+ format = format || 'yyyy-mm-dd'; // default format
218
+ var parts = input.match(/(\d+)/g), i = 0, fmt = {};
219
+ // extract date-part indexes from the format
220
+ format.replace(/(yyyy|dd?|mm?)/g, function(part) { fmt[part] = i++; });
221
+
222
+ return new Date(parts[fmt['yyyy']], parts[fmt['mm'] == undefined ? fmt['m'] : fmt['mm']]-1, parts[fmt['dd'] == undefined ? fmt['d'] : fmt['dd']]);
223
+ }
224
+
202
225
  // Simulates PHP's date function
203
- Date.prototype.format=function(format){var returnStr='';var replace=Date.replaceChars;for(var i=0;i<format.length;i++){var curChar=format.charAt(i);if(replace[curChar]){returnStr+=replace[curChar].call(this);}else{returnStr+=curChar;}}return returnStr;};Date.replaceChars={shortMonths:['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],longMonths:['January','February','March','April','May','June','July','August','September','October','November','December'],shortDays:['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],longDays:['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],d:function(){return(this.getDate()<10?'0':'')+this.getDate();},D:function(){return Date.replaceChars.shortDays[this.getDay()];},j:function(){return this.getDate();},l:function(){return Date.replaceChars.longDays[this.getDay()];},N:function(){return this.getDay()+1;},S:function(){return(this.getDate()%10==1&&this.getDate()!=11?'st':(this.getDate()%10==2&&this.getDate()!=12?'nd':(this.getDate()%10==3&&this.getDate()!=13?'rd':'th')));},w:function(){return this.getDay();},z:function(){return"Not Yet Supported";},W:function(){return"Not Yet Supported";},F:function(){return Date.replaceChars.longMonths[this.getMonth()];},m:function(){return(this.getMonth()<9?'0':'')+(this.getMonth()+1);},M:function(){return Date.replaceChars.shortMonths[this.getMonth()];},n:function(){return this.getMonth()+1;},t:function(){return"Not Yet Supported";},L:function(){return(((this.getFullYear()%4==0)&&(this.getFullYear()%100!=0))||(this.getFullYear()%400==0))?'1':'0';},o:function(){return"Not Supported";},Y:function(){return this.getFullYear();},y:function(){return(''+this.getFullYear()).substr(2);},a:function(){return this.getHours()<12?'am':'pm';},A:function(){return this.getHours()<12?'AM':'PM';},B:function(){return"Not Yet Supported";},g:function(){return this.getHours()%12||12;},G:function(){return this.getHours();},h:function(){return((this.getHours()%12||12)<10?'0':'')+(this.getHours()%12||12);},H:function(){return(this.getHours()<10?'0':'')+this.getHours();},i:function(){return(this.getMinutes()<10?'0':'')+this.getMinutes();},s:function(){return(this.getSeconds()<10?'0':'')+this.getSeconds();},e:function(){return"Not Yet Supported";},I:function(){return"Not Supported";},O:function(){return(-this.getTimezoneOffset()<0?'-':'+')+(Math.abs(this.getTimezoneOffset()/60)<10?'0':'')+(Math.abs(this.getTimezoneOffset()/60))+'00';},P:function(){return(-this.getTimezoneOffset()<0?'-':'+')+(Math.abs(this.getTimezoneOffset()/60)<10?'0':'')+(Math.abs(this.getTimezoneOffset()/60))+':'+(Math.abs(this.getTimezoneOffset()%60)<10?'0':'')+(Math.abs(this.getTimezoneOffset()%60));},T:function(){var m=this.getMonth();this.setMonth(0);var result=this.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/,'$1');this.setMonth(m);return result;},Z:function(){return-this.getTimezoneOffset()*60;},c:function(){return this.format("Y-m-d")+"T"+this.format("H:i:sP");},r:function(){return this.toString();},U:function(){return this.getTime()/1000;}};
226
+ Date.prototype.format=function(format){var returnStr='';var replace=Date.replaceChars;for(var i=0;i<format.length;i++){var curChar=format.charAt(i);if(replace[curChar]){returnStr+=replace[curChar].call(this);}else{returnStr+=curChar;}}return returnStr;};Date.replaceChars={shortMonths:['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],longMonths:['January','February','March','April','May','June','July','August','September','October','November','December'],shortDays:['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],longDays:['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],d:function(){return(this.getDate()<10?'0':'')+this.getDate();},D:function(){return Date.replaceChars.shortDays[this.getDay()];},j:function(){return this.getDate();},l:function(){return Date.replaceChars.longDays[this.getDay()];},N:function(){return this.getDay()+1;},S:function(){return(this.getDate()%10==1&&this.getDate()!=11?'st':(this.getDate()%10==2&&this.getDate()!=12?'nd':(this.getDate()%10==3&&this.getDate()!=13?'rd':'th')));},w:function(){return this.getDay();},z:function(){return"Not Yet Supported";},W:function(){return"Not Yet Supported";},F:function(){return Date.replaceChars.longMonths[this.getMonth()];},m:function(){return(this.getMonth()<9?'0':'')+(this.getMonth()+1);},M:function(){return Date.replaceChars.shortMonths[this.getMonth()];},n:function(){return this.getMonth()+1;},t:function(){return"Not Yet Supported";},L:function(){return(((this.getFullYear()%4==0)&&(this.getFullYear()%100!=0))||(this.getFullYear()%400==0))?'1':'0';},o:function(){return"Not Supported";},Y:function(){return this.getFullYear();},y:function(){return(''+this.getFullYear()).substr(2);},a:function(){return this.getHours()<12?'am':'pm';},A:function(){return this.getHours()<12?'AM':'PM';},B:function(){return"Not Yet Supported";},g:function(){return this.getHours()%12||12;},G:function(){return this.getHours();},h:function(){return((this.getHours()%12||12)<10?'0':'')+(this.getHours()%12||12);},H:function(){return(this.getHours()<10?'0':'')+this.getHours();},i:function(){return(this.getMinutes()<10?'0':'')+this.getMinutes();},s:function(){return(this.getSeconds()<10?'0':'')+this.getSeconds();},e:function(){return"Not Yet Supported";},I:function(){return"Not Supported";},O:function(){return(-this.getTimezoneOffset()<0?'-':'+')+(Math.abs(this.getTimezoneOffset()/60)<10?'0':'')+(Math.abs(this.getTimezoneOffset()/60))+'00';},P:function(){return(-this.getTimezoneOffset()<0?'-':'+')+(Math.abs(this.getTimezoneOffset()/60)<10?'0':'')+(Math.abs(this.getTimezoneOffset()/60))+':'+(Math.abs(this.getTimezoneOffset()%60)<10?'0':'')+(Math.abs(this.getTimezoneOffset()%60));},T:function(){var m=this.getMonth();this.setMonth(0);var result=this.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/,'$1');this.setMonth(m);return result;},Z:function(){return-this.getTimezoneOffset()*60;},c:function(){return this.format("Y-m-d")+"T"+this.format("H:i:sP");},r:function(){return this.toString();},U:function(){return this.getTime()/1000;}};
@@ -1,5 +1,5 @@
1
1
  /************************
2
- jquery-timepicker v1.1
2
+ jquery-timepicker v1.2.2
3
3
  http://jonthornton.github.com/jquery-timepicker/
4
4
 
5
5
  requires jQuery 1.7+
@@ -7,13 +7,13 @@ requires jQuery 1.7+
7
7
 
8
8
 
9
9
  (function (factory) {
10
- if (typeof define === 'function' && define.amd) {
11
- // AMD. Register as an anonymous module.
12
- define(['jquery'], factory);
13
- } else {
14
- // Browser globals
15
- factory(jQuery);
16
- }
10
+ if (typeof define === 'function' && define.amd) {
11
+ // AMD. Register as an anonymous module.
12
+ define(['jquery'], factory);
13
+ } else {
14
+ // Browser globals
15
+ factory(jQuery);
16
+ }
17
17
  }(function ($) {
18
18
  var _baseDate = _generateBaseDate();
19
19
  var _ONE_DAY = 86400;
@@ -32,7 +32,8 @@ requires jQuery 1.7+
32
32
  forceRoundTime: false,
33
33
  appendTo: 'body',
34
34
  disableTimeRanges: [],
35
- closeOnWindowScroll: true
35
+ closeOnWindowScroll: false,
36
+ disableTextInput: false
36
37
  };
37
38
  var _lang = {
38
39
  decimal: '.',
@@ -78,8 +79,9 @@ requires jQuery 1.7+
78
79
  self.data('timepicker-settings', settings);
79
80
  self.prop('autocomplete', 'off');
80
81
  self.on('click.timepicker focus.timepicker', methods.show);
81
- self.on('blur.timepicker', _formatValue);
82
- self.on('keydown.timepicker', _keyhandler);
82
+ self.on('change.timepicker', _formatValue);
83
+ self.on('keydown.timepicker', _keydownhandler);
84
+ self.on('keyup.timepicker', _keyuphandler);
83
85
  self.addClass('ui-timepicker-input');
84
86
 
85
87
  _formatValue.call(self.get(0));
@@ -91,7 +93,7 @@ requires jQuery 1.7+
91
93
  var self = $(this);
92
94
  var settings = self.data('timepicker-settings');
93
95
 
94
- if ('ontouchstart' in document && settings.disableTouchKeyboard) {
96
+ if (_hideKeyboard(self)) {
95
97
  // block the keyboard on mobile devices
96
98
  self.blur();
97
99
  }
@@ -104,18 +106,11 @@ requires jQuery 1.7+
104
106
  }
105
107
 
106
108
  // check if list needs to be rendered
107
- if (!list || list.length === 0) {
109
+ if (!list || list.length === 0 || typeof settings.durationTime === 'function') {
108
110
  _render(self);
109
111
  list = self.data('timepicker-list');
110
112
  }
111
113
 
112
- // check if a flag was set to close this picker
113
- if (self.hasClass('ui-timepicker-hideme')) {
114
- self.removeClass('ui-timepicker-hideme');
115
- list.hide();
116
- return;
117
- }
118
-
119
114
  if (list.is(':visible')) {
120
115
  return;
121
116
  }
@@ -127,23 +122,29 @@ requires jQuery 1.7+
127
122
 
128
123
  if ((self.offset().top + self.outerHeight(true) + list.outerHeight()) > $(window).height() + $(window).scrollTop()) {
129
124
  // position the dropdown on top
130
- list.offset({ 'left':(self.offset().left), 'top': self.offset().top - list.outerHeight() });
125
+ list.offset({
126
+ 'left': self.offset().left + parseInt(list.css('marginLeft').replace('px', ''), 10),
127
+ 'top': self.offset().top - list.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10)
128
+ });
131
129
  } else {
132
130
  // put it under the input
133
- list.offset({ 'left':(self.offset().left), 'top': self.offset().top + self.outerHeight() });
131
+ list.offset({
132
+ 'left':self.offset().left + parseInt(list.css('marginLeft').replace('px', ''), 10),
133
+ 'top': self.offset().top + self.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10)
134
+ });
134
135
  }
135
136
 
136
137
  // position scrolling
137
138
  var selected = list.find('.ui-timepicker-selected');
138
139
 
139
140
  if (!selected.length) {
140
- if (self.val()) {
141
- selected = _findRow(self, list, _time2int(self.val()));
142
- } else if (settings.scrollDefaultNow) {
143
- selected = _findRow(self, list, _time2int(new Date()));
144
- } else if (settings.scrollDefaultTime !== false) {
145
- selected = _findRow(self, list, _time2int(settings.scrollDefaultTime));
146
- }
141
+ if (_getTimeValue(self)) {
142
+ selected = _findRow(self, list, _time2int(_getTimeValue(self)));
143
+ } else if (settings.scrollDefaultNow) {
144
+ selected = _findRow(self, list, _time2int(new Date()));
145
+ } else if (settings.scrollDefaultTime !== false) {
146
+ selected = _findRow(self, list, _time2int(settings.scrollDefaultTime));
147
+ }
147
148
  }
148
149
 
149
150
  if (selected && selected.length) {
@@ -160,7 +161,7 @@ requires jQuery 1.7+
160
161
 
161
162
  hide: function(e)
162
163
  {
163
- $('.ui-timepicker-list:visible').each(function() {
164
+ $('.ui-timepicker-wrapper:visible').each(function() {
164
165
  var list = $(this);
165
166
  var self = list.data('timepicker-input');
166
167
  var settings = self.data('timepicker-settings');
@@ -176,7 +177,7 @@ requires jQuery 1.7+
176
177
 
177
178
  option: function(key, value)
178
179
  {
179
- var self = $(this);
180
+ var self = this;
180
181
  var settings = self.data('timepicker-settings');
181
182
  var list = self.data('timepicker-list');
182
183
 
@@ -199,30 +200,32 @@ requires jQuery 1.7+
199
200
  self.data('timepicker-list', false);
200
201
  }
201
202
 
203
+ return self;
202
204
  },
203
205
 
204
206
  getSecondsFromMidnight: function()
205
207
  {
206
- return _time2int($(this).val());
208
+ return _time2int(_getTimeValue(this));
207
209
  },
208
210
 
209
211
  getTime: function()
210
212
  {
213
+ var self = this;
211
214
  var today = new Date();
212
215
  today.setHours(0, 0, 0, 0);
213
- return new Date(today.valueOf() + (_time2int($(this).val())*1000));
216
+ return new Date(today.valueOf() + (_time2int(_getTimeValue(self))*1000));
214
217
  },
215
218
 
216
219
  setTime: function(value)
217
220
  {
218
- var self = $(this);
221
+ var self = this;
219
222
  var prettyTime = _int2time(_time2int(value), self.data('timepicker-settings').timeFormat);
220
- self.val(prettyTime);
223
+ _setTimeValue(self, prettyTime);
221
224
  },
222
225
 
223
226
  remove: function()
224
227
  {
225
- var self = $(this);
228
+ var self = this;
226
229
 
227
230
  // check if this element is a timepicker
228
231
  if (!self.hasClass('ui-timepicker-input')) {
@@ -255,7 +258,7 @@ requires jQuery 1.7+
255
258
  settings.maxTime = _time2int(settings.maxTime);
256
259
  }
257
260
 
258
- if (settings.durationTime) {
261
+ if (settings.durationTime && typeof settings.durationTime !== 'function') {
259
262
  settings.durationTime = _time2int(settings.durationTime);
260
263
  }
261
264
 
@@ -287,22 +290,26 @@ requires jQuery 1.7+
287
290
  self.data('timepicker-list', false);
288
291
  }
289
292
 
290
- list = $('<ul />', {
291
- 'tabindex': -1,
292
- 'class': 'ui-timepicker-list'
293
- });
293
+ list = $('<ul />', { 'class': 'ui-timepicker-list' });
294
+
295
+ var wrapped_list = $('<div />', { 'class': 'ui-timepicker-wrapper', 'tabindex': -1 });
296
+ wrapped_list.css({'display':'none', 'position': 'absolute' }).append(list);
297
+
294
298
 
295
299
  if (settings.className) {
296
- list.addClass(settings.className);
300
+ wrapped_list.addClass(settings.className);
297
301
  }
298
302
 
299
- list.css({'display':'none', 'position': 'absolute' });
300
-
301
303
  if ((settings.minTime !== null || settings.durationTime !== null) && settings.showDuration) {
302
- list.addClass('ui-timepicker-with-duration');
304
+ wrapped_list.addClass('ui-timepicker-with-duration');
303
305
  }
304
306
 
305
- var durStart = (settings.durationTime !== null) ? settings.durationTime : settings.minTime;
307
+ var durStart = settings.minTime;
308
+ if (typeof settings.durationTime === 'function') {
309
+ durStart = _time2int(settings.durationTime());
310
+ } else if (settings.durationTime !== null) {
311
+ durStart = settings.durationTime;
312
+ }
306
313
  var start = (settings.minTime !== null) ? settings.minTime : 0;
307
314
  var end = (settings.maxTime !== null) ? settings.maxTime : (start + _ONE_DAY - 1);
308
315
 
@@ -311,8 +318,9 @@ requires jQuery 1.7+
311
318
  end += _ONE_DAY;
312
319
  }
313
320
 
314
- var disabledTimeRanges = settings.disableTimeRanges;
315
- var disabledRange = disabledTimeRanges.shift();
321
+ var dr = settings.disableTimeRanges;
322
+ var drCur = 0;
323
+ var drLen = dr.length;
316
324
 
317
325
  for (var i=start; i <= end; i += settings.step*60) {
318
326
  var timeInt = i%_ONE_DAY;
@@ -328,19 +336,21 @@ requires jQuery 1.7+
328
336
  row.append(duration);
329
337
  }
330
338
 
331
- if (disabledRange) {
332
- if (timeInt >= disabledRange[0] && timeInt < disabledRange[1]) {
339
+ if (drCur < drLen) {
340
+ if (timeInt >= dr[drCur][1]) {
341
+ drCur += 1;
342
+ }
343
+
344
+ if (dr[drCur] && timeInt >= dr[drCur][0] && timeInt < dr[drCur][1]) {
333
345
  row.addClass('ui-timepicker-disabled');
334
- } else if (timeInt > disabledRange[1]) {
335
- disabledRange = disabledTimeRanges.shift();
336
346
  }
337
347
  }
338
348
 
339
349
  list.append(row);
340
350
  }
341
351
 
342
- list.data('timepicker-input', self);
343
- self.data('timepicker-list', list);
352
+ wrapped_list.data('timepicker-input', self);
353
+ self.data('timepicker-list', wrapped_list);
344
354
 
345
355
  var appendTo = settings.appendTo;
346
356
  if (typeof appendTo === 'string') {
@@ -348,19 +358,31 @@ requires jQuery 1.7+
348
358
  } else if (typeof appendTo === 'function') {
349
359
  appendTo = appendTo(self);
350
360
  }
351
- appendTo.append(list);
361
+ appendTo.append(wrapped_list);
352
362
  _setSelected(self, list);
353
363
 
354
364
  list.on('click', 'li', function(e) {
355
- self[0].focus();
365
+
366
+ // hack: temporarily disable the focus handler
367
+ // to deal with the fact that IE fires 'focus'
368
+ // events asynchronously
369
+ self.off('focus.timepicker');
370
+ self.on('focus.timepicker-ie-hack', function(){
371
+ self.off('focus.timepicker-ie-hack');
372
+ self.on('focus.timepicker', methods.show);
373
+ });
374
+
375
+ if (!_hideKeyboard(self)) {
376
+ self[0].focus();
377
+ }
356
378
 
357
379
  // make sure only the clicked row is selected
358
380
  list.find('li').removeClass('ui-timepicker-selected');
359
381
  $(this).addClass('ui-timepicker-selected');
360
382
 
361
383
  if (_selectValue(self)) {
362
- self.addClass('ui-timepicker-hideme');
363
- list.hide();
384
+ self.trigger('hideTimepicker');
385
+ wrapped_list.hide();
364
386
  }
365
387
  });
366
388
  }
@@ -387,13 +409,19 @@ requires jQuery 1.7+
387
409
  {
388
410
  var target = $(e.target);
389
411
  var input = target.closest('.ui-timepicker-input');
390
- if (input.length === 0 && target.closest('.ui-timepicker-list').length === 0) {
412
+ if (input.length === 0 && target.closest('.ui-timepicker-wrapper').length === 0) {
391
413
  methods.hide();
392
414
  $('body').unbind('.ui-timepicker');
393
415
  $(window).unbind('.ui-timepicker');
394
416
  }
395
417
  }
396
418
 
419
+ function _hideKeyboard(self)
420
+ {
421
+ var settings = self.data('timepicker-settings');
422
+ return ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && settings.disableTouchKeyboard);
423
+ }
424
+
397
425
  function _findRow(self, list, value)
398
426
  {
399
427
  if (!value && value !== 0) {
@@ -422,10 +450,24 @@ requires jQuery 1.7+
422
450
 
423
451
  function _setSelected(self, list)
424
452
  {
425
- var timeValue = _time2int(self.val());
453
+ list.find('li').removeClass('ui-timepicker-selected');
454
+
455
+ var timeValue = _time2int(_getTimeValue(self));
456
+ if (!timeValue) {
457
+ return;
458
+ }
426
459
 
427
460
  var selected = _findRow(self, list, timeValue);
428
- if (selected) selected.addClass('ui-timepicker-selected');
461
+ if (selected) {
462
+
463
+ var topDelta = selected.offset().top - list.offset().top;
464
+
465
+ if (topDelta + selected.outerHeight() > list.outerHeight() || topDelta < 0) {
466
+ list.scrollTop(list.scrollTop() + selected.position().top - selected.outerHeight());
467
+ }
468
+
469
+ selected.addClass('ui-timepicker-selected');
470
+ }
429
471
  }
430
472
 
431
473
 
@@ -436,6 +478,12 @@ requires jQuery 1.7+
436
478
  }
437
479
 
438
480
  var self = $(this);
481
+ var list = self.data('timepicker-list');
482
+
483
+ if (list && list.is(':visible')) {
484
+ return;
485
+ }
486
+
439
487
  var seconds = _time2int(this.value);
440
488
 
441
489
  if (seconds === null) {
@@ -444,14 +492,22 @@ requires jQuery 1.7+
444
492
  }
445
493
 
446
494
  var settings = self.data('timepicker-settings');
447
-
495
+ var rangeError = false;
448
496
  // check that the time in within bounds
449
497
  if (settings.minTime !== null && seconds < settings.minTime) {
450
- self.trigger('timeRangeError');
498
+ rangeError = true;
451
499
  } else if (settings.maxTime !== null && seconds > settings.maxTime) {
452
- self.trigger('timeRangeError');
500
+ rangeError = true;
453
501
  }
454
502
 
503
+ // check that time isn't within disabled time ranges
504
+ $.each(settings.disableTimeRanges, function(){
505
+ if (seconds >= this[0] && seconds < this[1]) {
506
+ rangeError = true;
507
+ return false;
508
+ }
509
+ });
510
+
455
511
  if (settings.forceRoundTime) {
456
512
  var offset = seconds % (settings.step*60); // step is in minutes
457
513
 
@@ -465,19 +521,62 @@ requires jQuery 1.7+
465
521
  }
466
522
 
467
523
  var prettyTime = _int2time(seconds, settings.timeFormat);
468
- self.val(prettyTime);
524
+
525
+ if (rangeError) {
526
+ if (_setTimeValue(self, prettyTime, 'error')) {
527
+ self.trigger('timeRangeError');
528
+ }
529
+ } else {
530
+ _setTimeValue(self, prettyTime);
531
+ }
469
532
  }
470
533
 
471
- function _keyhandler(e)
534
+ function _getTimeValue(self)
535
+ {
536
+ if (self.is('input')) {
537
+ return self.val();
538
+ } else {
539
+ // use the element's data attributes to store values
540
+ return self.data('ui-timepicker-value');
541
+ }
542
+ }
543
+
544
+ function _setTimeValue(self, value, source)
545
+ {
546
+ if (self.data('ui-timepicker-value') != value) {
547
+ self.data('ui-timepicker-value', value);
548
+ if (self.is('input')) {
549
+ self.val(value);
550
+ }
551
+
552
+ if (source == 'select') {
553
+ self.trigger('selectTime').trigger('changeTime').trigger('change');
554
+ } else if (source != 'error') {
555
+ self.trigger('changeTime');
556
+ }
557
+
558
+ return true;
559
+ } else {
560
+ self.trigger('selectTime');
561
+ return false;
562
+ }
563
+ }
564
+
565
+ /*
566
+ * Keyboard navigation via arrow keys
567
+ */
568
+ function _keydownhandler(e)
472
569
  {
473
570
  var self = $(this);
474
571
  var list = self.data('timepicker-list');
475
572
 
476
573
  if (!list || !list.is(':visible')) {
477
574
  if (e.keyCode == 40) {
478
- self.focus();
575
+ if (!_hideKeyboard(self)) {
576
+ self.focus();
577
+ }
479
578
  } else {
480
- return true;
579
+ return _screenInput(e, self);
481
580
  }
482
581
  }
483
582
 
@@ -495,7 +594,7 @@ requires jQuery 1.7+
495
594
  var selected = list.find('.ui-timepicker-selected');
496
595
 
497
596
  if (!selected.length) {
498
- list.children().each(function(i, obj) {
597
+ list.find('li').each(function(i, obj) {
499
598
  if ($(obj).position().top > 0) {
500
599
  selected = $(obj);
501
600
  return false;
@@ -512,13 +611,13 @@ requires jQuery 1.7+
512
611
  }
513
612
  }
514
613
 
515
- break;
614
+ return false;
516
615
 
517
616
  case 40: // down
518
617
  selected = list.find('.ui-timepicker-selected');
519
618
 
520
619
  if (selected.length === 0) {
521
- list.children().each(function(i, obj) {
620
+ list.find('li').each(function(i, obj) {
522
621
  if ($(obj).position().top > 0) {
523
622
  selected = $(obj);
524
623
  return false;
@@ -535,33 +634,72 @@ requires jQuery 1.7+
535
634
  }
536
635
  }
537
636
 
538
- break;
637
+ return false;
539
638
 
540
639
  case 27: // escape
541
640
  list.find('li').removeClass('ui-timepicker-selected');
542
- list.hide();
641
+ methods.hide();
543
642
  break;
544
643
 
545
644
  case 9: //tab
546
645
  methods.hide();
547
646
  break;
548
647
 
549
- case 16:
550
- case 17:
551
- case 18:
552
- case 19:
553
- case 20:
554
- case 33:
555
- case 34:
556
- case 35:
557
- case 36:
558
- case 37:
559
- case 39:
560
- case 45:
561
- return;
648
+ default:
649
+ return _screenInput(e, self);
650
+ }
651
+ }
652
+
653
+ function _screenInput(e, self)
654
+ {
655
+ return !self.data('timepicker-settings').disableTextInput || e.ctrlKey || e.altKey || e.metaKey || (e.keyCode != 2 && e.keyCode < 46);
656
+ }
657
+
658
+ /*
659
+ * Time typeahead
660
+ */
661
+ function _keyuphandler(e)
662
+ {
663
+ var self = $(this);
664
+ var list = self.data('timepicker-list');
665
+
666
+ if (!list || !list.is(':visible')) {
667
+ return true;
668
+ }
669
+
670
+ switch (e.keyCode) {
671
+
672
+ case 96: // numpad numerals
673
+ case 97:
674
+ case 98:
675
+ case 99:
676
+ case 100:
677
+ case 101:
678
+ case 102:
679
+ case 103:
680
+ case 104:
681
+ case 105:
682
+ case 48: // numerals
683
+ case 49:
684
+ case 50:
685
+ case 51:
686
+ case 52:
687
+ case 53:
688
+ case 54:
689
+ case 55:
690
+ case 56:
691
+ case 57:
692
+ case 65: // a
693
+ case 77: // m
694
+ case 80: // p
695
+ case 186: // colon
696
+ case 8: // backspace
697
+ case 46: // delete
698
+ _setSelected(self, list);
699
+ break;
562
700
 
563
701
  default:
564
- list.find('li').removeClass('ui-timepicker-selected');
702
+ // list.find('li').removeClass('ui-timepicker-selected');
565
703
  return;
566
704
  }
567
705
  }
@@ -582,20 +720,20 @@ requires jQuery 1.7+
582
720
  // selected value found
583
721
  timeValue = cursor.data('time');
584
722
 
585
- } else if (self.val()) {
723
+ } else if (_getTimeValue(self)) {
586
724
 
587
725
  // no selected value; fall back on input value
588
- timeValue = _time2int(self.val());
726
+ timeValue = _time2int(_getTimeValue(self));
589
727
 
590
728
  _setSelected(self, list);
591
729
  }
592
730
 
593
731
  if (timeValue !== null) {
594
732
  var timeString = _int2time(timeValue, settings.timeFormat);
595
- self.val(timeString);
733
+ _setTimeValue(self, timeString, 'select');
596
734
  }
597
735
 
598
- self.trigger('change').trigger('changeTime');
736
+ //self.trigger('change').trigger('selectTime');
599
737
  return true;
600
738
  }
601
739
 
@@ -685,25 +823,29 @@ requires jQuery 1.7+
685
823
  function _time2int(timeString)
686
824
  {
687
825
  if (timeString === '') return null;
688
- if (timeString+0 == timeString) return timeString;
826
+ if (!timeString || timeString+0 == timeString) return timeString;
689
827
 
690
828
  if (typeof(timeString) == 'object') {
691
- timeString = timeString.getHours()+':'+timeString.getMinutes()+':'+timeString.getSeconds();
829
+ timeString = timeString.getHours()+':'+_pad2(timeString.getMinutes())+':'+_pad2(timeString.getSeconds());
692
830
  }
693
831
 
832
+ timeString = timeString.toLowerCase();
833
+
694
834
  var d = new Date(0);
835
+ var time;
695
836
 
696
- var timeRegex;
697
- if (timeString.indexOf(":") === -1 && $.isNumeric(timeString.charAt(1))) {
698
- //zero-required, fixed-position version
699
- timeRegex = /^([0-2][0-9]):?([0-5][0-9])?:?([0-5][0-9])?\s*([pa]?)/;
837
+ // try to parse time input
838
+ if (timeString.indexOf(":") === -1) {
839
+ // no colon present
840
+ time = timeString.match(/^([0-9]):?([0-5][0-9])?:?([0-5][0-9])?\s*([pa]?)m?$/);
841
+
842
+ if (!time) {
843
+ time = timeString.match(/^([0-2][0-9]):?([0-5][0-9])?:?([0-5][0-9])?\s*([pa]?)m?$/);
844
+ }
700
845
  } else {
701
- //colon-delimited version
702
- timeRegex = /^(\d{1,2})(?::(\d{1,2}))?(?::(\d{1,2}))?\s*([pa]?)/;
846
+ time = timeString.match(/^(\d{1,2})(?::([0-5][0-9]))?(?::([0-5][0-9]))?\s*([pa]?)m?$/);
703
847
  }
704
848
 
705
- var time = timeString.toLowerCase().match(timeRegex);
706
-
707
849
  if (!time) {
708
850
  return null;
709
851
  }
@@ -727,6 +869,10 @@ requires jQuery 1.7+
727
869
  return hours*3600 + minutes*60 + seconds;
728
870
  }
729
871
 
872
+ function _pad2(n) {
873
+ return ("0" + n).slice(-2);
874
+ }
875
+
730
876
  // Plugin entry
731
877
  $.fn.timepicker = function(method)
732
878
  {
@@ -734,4 +880,4 @@ requires jQuery 1.7+
734
880
  else if(typeof method === "object" || !method) { return methods.init.apply(this, arguments); }
735
881
  else { $.error("Method "+ method + " does not exist on jQuery.timepicker"); }
736
882
  };
737
- }));
883
+ }));
@@ -1,23 +1,27 @@
1
- .ui-timepicker-list {
1
+ .ui-timepicker-wrapper {
2
2
  overflow-y: auto;
3
3
  height: 150px;
4
4
  width: 6.5em;
5
5
  background: #fff;
6
6
  border: 1px solid #ddd;
7
- margin: 0;
8
- padding: 0;
9
- list-style: none;
10
7
  -webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);
11
8
  -moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);
12
9
  box-shadow:0 5px 10px rgba(0,0,0,0.2);
13
10
  outline: none;
14
11
  z-index: 10001;
12
+ margin: 0;
15
13
  }
16
14
 
17
- .ui-timepicker-list.ui-timepicker-with-duration {
15
+ .ui-timepicker-wrapper.ui-timepicker-with-duration {
18
16
  width: 11em;
19
17
  }
20
18
 
19
+ .ui-timepicker-list {
20
+ margin: 0;
21
+ padding: 0;
22
+ list-style: none;
23
+ }
24
+
21
25
  .ui-timepicker-duration {
22
26
  margin-left: 5px; color: #888;
23
27
  }
@@ -60,4 +64,4 @@ li.ui-timepicker-selected .ui-timepicker-duration,
60
64
  .ui-timepicker-list li.ui-timepicker-disabled:hover,
61
65
  .ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {
62
66
  background: #f2f2f2;
63
- }
67
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jquery-timepicker-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0.0
4
+ version: 1.2.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-01 00:00:00.000000000 Z
12
+ date: 2013-08-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties