jquery-timepicker-rails 1.1.0.0 → 1.2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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