datetimepicker 0.0.2 → 0.0.3
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.
- data/app/assets/javascripts/datetimepicker.js.coffee +2 -4
- data/app/assets/javascripts/datetimepicker/bootstrap_datepicker.js +503 -125
- data/lib/datetimepicker.rb +1 -1
- data/lib/datetimepicker/simple_form/inputs.rb +3 -0
- data/lib/datetimepicker/simple_form/inputs/datepicker_input.rb +24 -0
- data/lib/datetimepicker/simple_form/inputs/timepicker_input.rb +24 -0
- data/lib/datetimepicker/version.rb +1 -1
- metadata +4 -1
@@ -5,8 +5,6 @@ jQuery () ->
|
|
5
5
|
|
6
6
|
# This format much match up with the format in Time::DATE_FORMATS[:datetimepicker_date]
|
7
7
|
# TODO: automate this conversion for the gemfile drop in version.
|
8
|
-
jQuery(".datetimepicker_date").datepicker(format: "yyyy/mm/dd")
|
9
|
-
|
10
|
-
$(this).datepicker('hide').blur()
|
11
|
-
|
8
|
+
jQuery(".datetimepicker_date").datepicker(format: "yyyy/mm/dd", autoclose: true)
|
9
|
+
|
12
10
|
jQuery(".datetimepicker_time").timepicker(showMeridian: false, template: "modal", defaultTime: "value")
|
@@ -1,8 +1,9 @@
|
|
1
1
|
/* =========================================================
|
2
|
-
* bootstrap-datepicker.js
|
2
|
+
* bootstrap-datepicker.js
|
3
3
|
* http://www.eyecon.ro/bootstrap-datepicker
|
4
4
|
* =========================================================
|
5
5
|
* Copyright 2012 Stefan Petre
|
6
|
+
* Improvements by Andrew Rowls
|
6
7
|
*
|
7
8
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
8
9
|
* you may not use this file except in compliance with the License.
|
@@ -16,177 +17,279 @@
|
|
16
17
|
* See the License for the specific language governing permissions and
|
17
18
|
* limitations under the License.
|
18
19
|
* ========================================================= */
|
19
|
-
|
20
|
+
|
20
21
|
!function( $ ) {
|
21
|
-
|
22
|
+
|
23
|
+
function UTCDate(){
|
24
|
+
return new Date(Date.UTC.apply(Date, arguments));
|
25
|
+
}
|
26
|
+
|
22
27
|
// Picker object
|
23
|
-
|
24
|
-
var Datepicker = function(element, options){
|
28
|
+
|
29
|
+
var Datepicker = function(element, options) {
|
30
|
+
var that = this;
|
31
|
+
|
25
32
|
this.element = $(element);
|
33
|
+
this.language = options.language||this.element.data('date-language')||"en";
|
34
|
+
this.language = this.language in dates ? this.language : "en";
|
26
35
|
this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy');
|
27
36
|
this.picker = $(DPGlobal.template)
|
28
37
|
.appendTo('body')
|
29
38
|
.on({
|
30
|
-
click: $.proxy(this.click, this)
|
31
|
-
mousedown: $.proxy(this.mousedown, this)
|
39
|
+
click: $.proxy(this.click, this)
|
32
40
|
});
|
33
41
|
this.isInput = this.element.is('input');
|
34
42
|
this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
|
35
|
-
|
43
|
+
this.hasInput = this.component && this.element.find('input').length;
|
44
|
+
if(this.component && this.component.length === 0)
|
45
|
+
this.component = false;
|
46
|
+
|
36
47
|
if (this.isInput) {
|
37
48
|
this.element.on({
|
38
49
|
focus: $.proxy(this.show, this),
|
39
|
-
|
40
|
-
|
50
|
+
keyup: $.proxy(this.update, this),
|
51
|
+
keydown: $.proxy(this.keydown, this)
|
41
52
|
});
|
42
53
|
} else {
|
43
|
-
if (this.component){
|
54
|
+
if (this.component && this.hasInput){
|
55
|
+
// For components that are not readonly, allow keyboard nav
|
56
|
+
this.element.find('input').on({
|
57
|
+
focus: $.proxy(this.show, this),
|
58
|
+
keyup: $.proxy(this.update, this),
|
59
|
+
keydown: $.proxy(this.keydown, this)
|
60
|
+
});
|
61
|
+
|
44
62
|
this.component.on('click', $.proxy(this.show, this));
|
45
63
|
} else {
|
46
64
|
this.element.on('click', $.proxy(this.show, this));
|
47
65
|
}
|
48
66
|
}
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
67
|
+
|
68
|
+
$(document).on('mousedown', function (e) {
|
69
|
+
// Clicked outside the datepicker, hide it
|
70
|
+
if ($(e.target).closest('.datepicker').length == 0) {
|
71
|
+
that.hide();
|
72
|
+
}
|
73
|
+
});
|
74
|
+
|
75
|
+
this.autoclose = false;
|
76
|
+
if ('autoclose' in options) {
|
77
|
+
this.autoclose = options.autoclose;
|
78
|
+
} else if ('dateAutoclose' in this.element.data()) {
|
79
|
+
this.autoclose = this.element.data('date-autoclose');
|
80
|
+
}
|
81
|
+
|
82
|
+
this.keyboardNavigation = true;
|
83
|
+
if ('keyboardNavigation' in options) {
|
84
|
+
this.keyboardNavigation = options.keyboardNavigation;
|
85
|
+
} else if ('dateKeyboardNavigation' in this.element.data()) {
|
86
|
+
this.keyboardNavigation = this.element.data('date-keyboard-navigation');
|
87
|
+
}
|
88
|
+
|
89
|
+
switch(options.startView || this.element.data('date-start-view')){
|
90
|
+
case 2:
|
91
|
+
case 'decade':
|
92
|
+
this.viewMode = this.startViewMode = 2;
|
93
|
+
break;
|
94
|
+
case 1:
|
95
|
+
case 'year':
|
96
|
+
this.viewMode = this.startViewMode = 1;
|
97
|
+
break;
|
98
|
+
case 0:
|
99
|
+
case 'month':
|
100
|
+
default:
|
101
|
+
this.viewMode = this.startViewMode = 0;
|
102
|
+
break;
|
103
|
+
}
|
104
|
+
|
105
|
+
this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7);
|
106
|
+
this.weekEnd = ((this.weekStart + 6) % 7);
|
107
|
+
this.startDate = -Infinity;
|
108
|
+
this.endDate = Infinity;
|
109
|
+
this.setStartDate(options.startDate||this.element.data('date-startdate'));
|
110
|
+
this.setEndDate(options.endDate||this.element.data('date-enddate'));
|
53
111
|
this.fillDow();
|
54
112
|
this.fillMonths();
|
55
113
|
this.update();
|
56
114
|
this.showMode();
|
57
115
|
};
|
58
|
-
|
116
|
+
|
59
117
|
Datepicker.prototype = {
|
60
118
|
constructor: Datepicker,
|
61
|
-
|
119
|
+
|
62
120
|
show: function(e) {
|
63
121
|
this.picker.show();
|
64
122
|
this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
|
123
|
+
this.update();
|
65
124
|
this.place();
|
66
125
|
$(window).on('resize', $.proxy(this.place, this));
|
67
126
|
if (e ) {
|
68
127
|
e.stopPropagation();
|
69
128
|
e.preventDefault();
|
70
129
|
}
|
71
|
-
if (!this.isInput) {
|
72
|
-
$(document).on('mousedown', $.proxy(this.hide, this));
|
73
|
-
}
|
74
130
|
this.element.trigger({
|
75
131
|
type: 'show',
|
76
132
|
date: this.date
|
77
133
|
});
|
78
134
|
},
|
79
|
-
|
80
|
-
hide: function(){
|
135
|
+
|
136
|
+
hide: function(e){
|
81
137
|
this.picker.hide();
|
82
138
|
$(window).off('resize', this.place);
|
83
|
-
this.viewMode =
|
139
|
+
this.viewMode = this.startViewMode;
|
84
140
|
this.showMode();
|
85
141
|
if (!this.isInput) {
|
86
142
|
$(document).off('mousedown', this.hide);
|
87
143
|
}
|
88
|
-
|
144
|
+
if (e && e.currentTarget.value)
|
145
|
+
this.setValue();
|
89
146
|
this.element.trigger({
|
90
147
|
type: 'hide',
|
91
148
|
date: this.date
|
92
149
|
});
|
93
150
|
},
|
94
|
-
|
151
|
+
|
95
152
|
setValue: function() {
|
96
|
-
var
|
153
|
+
var formatted = DPGlobal.formatDate(this.date, this.format, this.language);
|
97
154
|
if (!this.isInput) {
|
98
155
|
if (this.component){
|
99
|
-
this.element.find('input').prop('value',
|
156
|
+
this.element.find('input').prop('value', formatted);
|
100
157
|
}
|
101
|
-
this.element.data('date',
|
158
|
+
this.element.data('date', formatted);
|
102
159
|
} else {
|
103
|
-
this.element.prop('value',
|
160
|
+
this.element.prop('value', formatted);
|
161
|
+
}
|
162
|
+
},
|
163
|
+
|
164
|
+
setStartDate: function(startDate){
|
165
|
+
this.startDate = startDate||-Infinity;
|
166
|
+
if (this.startDate !== -Infinity) {
|
167
|
+
this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language);
|
104
168
|
}
|
169
|
+
this.update();
|
170
|
+
this.updateNavArrows();
|
105
171
|
},
|
106
|
-
|
172
|
+
|
173
|
+
setEndDate: function(endDate){
|
174
|
+
this.endDate = endDate||Infinity;
|
175
|
+
if (this.endDate !== Infinity) {
|
176
|
+
this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language);
|
177
|
+
}
|
178
|
+
this.update();
|
179
|
+
this.updateNavArrows();
|
180
|
+
},
|
181
|
+
|
107
182
|
place: function(){
|
183
|
+
var zIndex = parseInt(this.element.parents().filter(function() {
|
184
|
+
return $(this).css('z-index') != 'auto';
|
185
|
+
}).first().css('z-index'))+10;
|
108
186
|
var offset = this.component ? this.component.offset() : this.element.offset();
|
109
187
|
this.picker.css({
|
110
188
|
top: offset.top + this.height,
|
111
|
-
left: offset.left
|
189
|
+
left: offset.left,
|
190
|
+
zIndex: zIndex
|
112
191
|
});
|
113
192
|
},
|
114
|
-
|
193
|
+
|
115
194
|
update: function(){
|
116
195
|
this.date = DPGlobal.parseDate(
|
117
|
-
this.isInput ? this.element.prop('value') : this.element.data('date'),
|
118
|
-
this.format
|
196
|
+
this.isInput ? this.element.prop('value') : this.element.data('date') || this.element.find('input').prop('value'),
|
197
|
+
this.format, this.language
|
119
198
|
);
|
120
|
-
this.
|
199
|
+
if (this.date < this.startDate) {
|
200
|
+
this.viewDate = new Date(this.startDate);
|
201
|
+
} else if (this.date > this.endDate) {
|
202
|
+
this.viewDate = new Date(this.endDate);
|
203
|
+
} else {
|
204
|
+
this.viewDate = new Date(this.date);
|
205
|
+
}
|
121
206
|
this.fill();
|
122
207
|
},
|
123
|
-
|
208
|
+
|
124
209
|
fillDow: function(){
|
125
210
|
var dowCnt = this.weekStart;
|
126
211
|
var html = '<tr>';
|
127
212
|
while (dowCnt < this.weekStart + 7) {
|
128
|
-
html += '<th class="dow">'+
|
213
|
+
html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>';
|
129
214
|
}
|
130
215
|
html += '</tr>';
|
131
216
|
this.picker.find('.datepicker-days thead').append(html);
|
132
217
|
},
|
133
|
-
|
218
|
+
|
134
219
|
fillMonths: function(){
|
135
220
|
var html = '';
|
136
221
|
var i = 0
|
137
222
|
while (i < 12) {
|
138
|
-
html += '<span class="month">'+
|
223
|
+
html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>';
|
139
224
|
}
|
140
|
-
this.picker.find('.datepicker-months td').
|
225
|
+
this.picker.find('.datepicker-months td').html(html);
|
141
226
|
},
|
142
|
-
|
227
|
+
|
143
228
|
fill: function() {
|
144
229
|
var d = new Date(this.viewDate),
|
145
|
-
year = d.
|
146
|
-
month = d.
|
230
|
+
year = d.getUTCFullYear(),
|
231
|
+
month = d.getUTCMonth(),
|
232
|
+
startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
|
233
|
+
startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
|
234
|
+
endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
|
235
|
+
endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
|
147
236
|
currentDate = this.date.valueOf();
|
148
237
|
this.picker.find('.datepicker-days th:eq(1)')
|
149
|
-
.text(
|
150
|
-
|
151
|
-
|
152
|
-
prevMonth
|
153
|
-
|
238
|
+
.text(dates[this.language].months[month]+' '+year);
|
239
|
+
this.updateNavArrows();
|
240
|
+
this.fillMonths();
|
241
|
+
var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
|
242
|
+
day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
|
243
|
+
prevMonth.setUTCDate(day);
|
244
|
+
prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7);
|
154
245
|
var nextMonth = new Date(prevMonth);
|
155
|
-
nextMonth.
|
246
|
+
nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
|
156
247
|
nextMonth = nextMonth.valueOf();
|
157
|
-
html = [];
|
248
|
+
var html = [];
|
158
249
|
var clsName;
|
159
250
|
while(prevMonth.valueOf() < nextMonth) {
|
160
|
-
if (prevMonth.
|
251
|
+
if (prevMonth.getUTCDay() == this.weekStart) {
|
161
252
|
html.push('<tr>');
|
162
253
|
}
|
163
254
|
clsName = '';
|
164
|
-
if (prevMonth.
|
255
|
+
if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
|
165
256
|
clsName += ' old';
|
166
|
-
} else if (prevMonth.
|
257
|
+
} else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {
|
167
258
|
clsName += ' new';
|
168
259
|
}
|
169
260
|
if (prevMonth.valueOf() == currentDate) {
|
170
261
|
clsName += ' active';
|
171
262
|
}
|
172
|
-
|
173
|
-
|
263
|
+
if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate) {
|
264
|
+
clsName += ' disabled';
|
265
|
+
}
|
266
|
+
html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>');
|
267
|
+
if (prevMonth.getUTCDay() == this.weekEnd) {
|
174
268
|
html.push('</tr>');
|
175
269
|
}
|
176
|
-
prevMonth.
|
270
|
+
prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
|
177
271
|
}
|
178
272
|
this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
|
179
|
-
var currentYear = this.date.
|
180
|
-
|
273
|
+
var currentYear = this.date.getUTCFullYear();
|
274
|
+
|
181
275
|
var months = this.picker.find('.datepicker-months')
|
182
276
|
.find('th:eq(1)')
|
183
277
|
.text(year)
|
184
278
|
.end()
|
185
279
|
.find('span').removeClass('active');
|
186
280
|
if (currentYear == year) {
|
187
|
-
months.eq(this.date.
|
281
|
+
months.eq(this.date.getUTCMonth()).addClass('active');
|
282
|
+
}
|
283
|
+
if (year < startYear || year > endYear) {
|
284
|
+
months.addClass('disabled');
|
188
285
|
}
|
189
|
-
|
286
|
+
if (year == startYear) {
|
287
|
+
months.slice(0, startMonth).addClass('disabled');
|
288
|
+
}
|
289
|
+
if (year == endYear) {
|
290
|
+
months.slice(endMonth+1).addClass('disabled');
|
291
|
+
}
|
292
|
+
|
190
293
|
html = '';
|
191
294
|
year = parseInt(year/10, 10) * 10;
|
192
295
|
var yearCont = this.picker.find('.datepicker-years')
|
@@ -196,12 +299,45 @@
|
|
196
299
|
.find('td');
|
197
300
|
year -= 1;
|
198
301
|
for (var i = -1; i < 11; i++) {
|
199
|
-
html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+'">'+year+'</span>';
|
302
|
+
html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>';
|
200
303
|
year += 1;
|
201
304
|
}
|
202
305
|
yearCont.html(html);
|
203
306
|
},
|
204
|
-
|
307
|
+
|
308
|
+
updateNavArrows: function() {
|
309
|
+
var d = new Date(this.viewDate),
|
310
|
+
year = d.getUTCFullYear(),
|
311
|
+
month = d.getUTCMonth();
|
312
|
+
switch (this.viewMode) {
|
313
|
+
case 0:
|
314
|
+
if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
|
315
|
+
this.picker.find('.prev').css({visibility: 'hidden'});
|
316
|
+
} else {
|
317
|
+
this.picker.find('.prev').css({visibility: 'visible'});
|
318
|
+
}
|
319
|
+
if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
|
320
|
+
this.picker.find('.next').css({visibility: 'hidden'});
|
321
|
+
} else {
|
322
|
+
this.picker.find('.next').css({visibility: 'visible'});
|
323
|
+
}
|
324
|
+
break;
|
325
|
+
case 1:
|
326
|
+
case 2:
|
327
|
+
if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
|
328
|
+
this.picker.find('.prev').css({visibility: 'hidden'});
|
329
|
+
} else {
|
330
|
+
this.picker.find('.prev').css({visibility: 'visible'});
|
331
|
+
}
|
332
|
+
if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
|
333
|
+
this.picker.find('.next').css({visibility: 'hidden'});
|
334
|
+
} else {
|
335
|
+
this.picker.find('.next').css({visibility: 'visible'});
|
336
|
+
}
|
337
|
+
break;
|
338
|
+
}
|
339
|
+
},
|
340
|
+
|
205
341
|
click: function(e) {
|
206
342
|
e.stopPropagation();
|
207
343
|
e.preventDefault();
|
@@ -215,64 +351,237 @@
|
|
215
351
|
break;
|
216
352
|
case 'prev':
|
217
353
|
case 'next':
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
354
|
+
var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
|
355
|
+
switch(this.viewMode){
|
356
|
+
case 0:
|
357
|
+
this.viewDate = this.moveMonth(this.viewDate, dir);
|
358
|
+
break;
|
359
|
+
case 1:
|
360
|
+
case 2:
|
361
|
+
this.viewDate = this.moveYear(this.viewDate, dir);
|
362
|
+
break;
|
363
|
+
}
|
223
364
|
this.fill();
|
224
365
|
break;
|
225
366
|
}
|
226
367
|
break;
|
227
368
|
case 'span':
|
228
|
-
if (target.is('.
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
369
|
+
if (!target.is('.disabled')) {
|
370
|
+
this.viewDate.setUTCDate(1);
|
371
|
+
if (target.is('.month')) {
|
372
|
+
var month = target.parent().find('span').index(target);
|
373
|
+
this.viewDate.setUTCMonth(month);
|
374
|
+
this.element.trigger({
|
375
|
+
type: 'changeMonth',
|
376
|
+
date: this.viewDate
|
377
|
+
});
|
378
|
+
} else {
|
379
|
+
var year = parseInt(target.text(), 10)||0;
|
380
|
+
this.viewDate.setUTCFullYear(year);
|
381
|
+
this.element.trigger({
|
382
|
+
type: 'changeYear',
|
383
|
+
date: this.viewDate
|
384
|
+
});
|
385
|
+
}
|
386
|
+
this.showMode(-1);
|
387
|
+
this.fill();
|
234
388
|
}
|
235
|
-
this.showMode(-1);
|
236
|
-
this.fill();
|
237
389
|
break;
|
238
390
|
case 'td':
|
239
|
-
if (target.is('.day')){
|
391
|
+
if (target.is('.day') && !target.is('.disabled')){
|
240
392
|
var day = parseInt(target.text(), 10)||1;
|
241
|
-
var
|
393
|
+
var year = this.viewDate.getUTCFullYear(),
|
394
|
+
month = this.viewDate.getUTCMonth();
|
242
395
|
if (target.is('.old')) {
|
243
|
-
month
|
396
|
+
if (month == 0) {
|
397
|
+
month = 11;
|
398
|
+
year -= 1;
|
399
|
+
} else {
|
400
|
+
month -= 1;
|
401
|
+
}
|
244
402
|
} else if (target.is('.new')) {
|
245
|
-
month
|
403
|
+
if (month == 11) {
|
404
|
+
month = 0;
|
405
|
+
year += 1;
|
406
|
+
} else {
|
407
|
+
month += 1;
|
408
|
+
}
|
246
409
|
}
|
247
|
-
|
248
|
-
this.
|
249
|
-
this.viewDate = new Date(year, month, day,0,0,0,0);
|
410
|
+
this.date = UTCDate(year, month, day,0,0,0,0);
|
411
|
+
this.viewDate = UTCDate(year, month, day,0,0,0,0);
|
250
412
|
this.fill();
|
251
413
|
this.setValue();
|
252
414
|
this.element.trigger({
|
253
415
|
type: 'changeDate',
|
254
416
|
date: this.date
|
255
417
|
});
|
418
|
+
var element;
|
419
|
+
if (this.isInput) {
|
420
|
+
element = this.element;
|
421
|
+
} else if (this.component){
|
422
|
+
element = this.element.find('input');
|
423
|
+
}
|
424
|
+
if (element) {
|
425
|
+
element.change();
|
426
|
+
if (this.autoclose) {
|
427
|
+
this.hide();
|
428
|
+
}
|
429
|
+
}
|
256
430
|
}
|
257
431
|
break;
|
258
432
|
}
|
259
433
|
}
|
260
434
|
},
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
435
|
+
|
436
|
+
moveMonth: function(date, dir){
|
437
|
+
if (!dir) return date;
|
438
|
+
var new_date = new Date(date.valueOf()),
|
439
|
+
day = new_date.getUTCDate(),
|
440
|
+
month = new_date.getUTCMonth(),
|
441
|
+
mag = Math.abs(dir),
|
442
|
+
new_month, test;
|
443
|
+
dir = dir > 0 ? 1 : -1;
|
444
|
+
if (mag == 1){
|
445
|
+
test = dir == -1
|
446
|
+
// If going back one month, make sure month is not current month
|
447
|
+
// (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
|
448
|
+
? function(){ return new_date.getUTCMonth() == month; }
|
449
|
+
// If going forward one month, make sure month is as expected
|
450
|
+
// (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
|
451
|
+
: function(){ return new_date.getUTCMonth() != new_month; };
|
452
|
+
new_month = month + dir;
|
453
|
+
new_date.setUTCMonth(new_month);
|
454
|
+
// Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
|
455
|
+
if (new_month < 0 || new_month > 11)
|
456
|
+
new_month = (new_month + 12) % 12;
|
457
|
+
} else {
|
458
|
+
// For magnitudes >1, move one month at a time...
|
459
|
+
for (var i=0; i<mag; i++)
|
460
|
+
// ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
|
461
|
+
new_date = this.moveMonth(new_date, dir);
|
462
|
+
// ...then reset the day, keeping it in the new month
|
463
|
+
new_month = new_date.getUTCMonth();
|
464
|
+
new_date.setUTCDate(day);
|
465
|
+
test = function(){ return new_month != new_date.getUTCMonth(); };
|
466
|
+
}
|
467
|
+
// Common date-resetting loop -- if date is beyond end of month, make it
|
468
|
+
// end of month
|
469
|
+
while (test()){
|
470
|
+
new_date.setUTCDate(--day);
|
471
|
+
new_date.setUTCMonth(new_month);
|
472
|
+
}
|
473
|
+
return new_date;
|
474
|
+
},
|
475
|
+
|
476
|
+
moveYear: function(date, dir){
|
477
|
+
return this.moveMonth(date, dir*12);
|
478
|
+
},
|
479
|
+
|
480
|
+
dateWithinRange: function(date){
|
481
|
+
return date >= this.startDate && date <= this.endDate;
|
265
482
|
},
|
266
|
-
|
483
|
+
|
484
|
+
keydown: function(e){
|
485
|
+
if (this.picker.is(':not(:visible)')){
|
486
|
+
if (e.keyCode == 27) // allow escape to hide and re-show picker
|
487
|
+
this.show();
|
488
|
+
return;
|
489
|
+
}
|
490
|
+
var dateChanged = false,
|
491
|
+
dir, day, month,
|
492
|
+
newDate, newViewDate;
|
493
|
+
switch(e.keyCode){
|
494
|
+
case 27: // escape
|
495
|
+
this.hide();
|
496
|
+
e.preventDefault();
|
497
|
+
break;
|
498
|
+
case 37: // left
|
499
|
+
case 39: // right
|
500
|
+
if (!this.keyboardNavigation) break;
|
501
|
+
dir = e.keyCode == 37 ? -1 : 1;
|
502
|
+
if (e.ctrlKey){
|
503
|
+
newDate = this.moveYear(this.date, dir);
|
504
|
+
newViewDate = this.moveYear(this.viewDate, dir);
|
505
|
+
} else if (e.shiftKey){
|
506
|
+
newDate = this.moveMonth(this.date, dir);
|
507
|
+
newViewDate = this.moveMonth(this.viewDate, dir);
|
508
|
+
} else {
|
509
|
+
newDate = new Date(this.date);
|
510
|
+
newDate.setUTCDate(this.date.getUTCDate() + dir);
|
511
|
+
newViewDate = new Date(this.viewDate);
|
512
|
+
newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
|
513
|
+
}
|
514
|
+
if (this.dateWithinRange(newDate)){
|
515
|
+
this.date = newDate;
|
516
|
+
this.viewDate = newViewDate;
|
517
|
+
this.setValue();
|
518
|
+
this.update();
|
519
|
+
e.preventDefault();
|
520
|
+
dateChanged = true;
|
521
|
+
}
|
522
|
+
break;
|
523
|
+
case 38: // up
|
524
|
+
case 40: // down
|
525
|
+
if (!this.keyboardNavigation) break;
|
526
|
+
dir = e.keyCode == 38 ? -1 : 1;
|
527
|
+
if (e.ctrlKey){
|
528
|
+
newDate = this.moveYear(this.date, dir);
|
529
|
+
newViewDate = this.moveYear(this.viewDate, dir);
|
530
|
+
} else if (e.shiftKey){
|
531
|
+
newDate = this.moveMonth(this.date, dir);
|
532
|
+
newViewDate = this.moveMonth(this.viewDate, dir);
|
533
|
+
} else {
|
534
|
+
newDate = new Date(this.date);
|
535
|
+
newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
|
536
|
+
newViewDate = new Date(this.viewDate);
|
537
|
+
newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
|
538
|
+
}
|
539
|
+
if (this.dateWithinRange(newDate)){
|
540
|
+
this.date = newDate;
|
541
|
+
this.viewDate = newViewDate;
|
542
|
+
this.setValue();
|
543
|
+
this.update();
|
544
|
+
e.preventDefault();
|
545
|
+
dateChanged = true;
|
546
|
+
}
|
547
|
+
break;
|
548
|
+
case 13: // enter
|
549
|
+
this.hide();
|
550
|
+
e.preventDefault();
|
551
|
+
break;
|
552
|
+
case 9: // tab
|
553
|
+
this.hide();
|
554
|
+
break;
|
555
|
+
}
|
556
|
+
if (dateChanged){
|
557
|
+
this.element.trigger({
|
558
|
+
type: 'changeDate',
|
559
|
+
date: this.date
|
560
|
+
});
|
561
|
+
var element;
|
562
|
+
if (this.isInput) {
|
563
|
+
element = this.element;
|
564
|
+
} else if (this.component){
|
565
|
+
element = this.element.find('input');
|
566
|
+
}
|
567
|
+
if (element) {
|
568
|
+
element.change();
|
569
|
+
}
|
570
|
+
}
|
571
|
+
},
|
572
|
+
|
267
573
|
showMode: function(dir) {
|
268
574
|
if (dir) {
|
269
575
|
this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir));
|
270
576
|
}
|
271
577
|
this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
|
578
|
+
this.updateNavArrows();
|
272
579
|
}
|
273
580
|
};
|
274
|
-
|
581
|
+
|
275
582
|
$.fn.datepicker = function ( option ) {
|
583
|
+
var args = Array.apply(null, arguments);
|
584
|
+
args.shift();
|
276
585
|
return this.each(function () {
|
277
586
|
var $this = $(this),
|
278
587
|
data = $this.data('datepicker'),
|
@@ -280,14 +589,25 @@
|
|
280
589
|
if (!data) {
|
281
590
|
$this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options))));
|
282
591
|
}
|
283
|
-
if (typeof option == 'string'
|
592
|
+
if (typeof option == 'string' && typeof data[option] == 'function') {
|
593
|
+
data[option].apply(data, args);
|
594
|
+
}
|
284
595
|
});
|
285
596
|
};
|
286
597
|
|
287
598
|
$.fn.datepicker.defaults = {
|
288
599
|
};
|
289
600
|
$.fn.datepicker.Constructor = Datepicker;
|
290
|
-
|
601
|
+
var dates = $.fn.datepicker.dates = {
|
602
|
+
en: {
|
603
|
+
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
|
604
|
+
daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
605
|
+
daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
|
606
|
+
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
607
|
+
monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
608
|
+
}
|
609
|
+
}
|
610
|
+
|
291
611
|
var DPGlobal = {
|
292
612
|
modes: [
|
293
613
|
{
|
@@ -305,68 +625,126 @@
|
|
305
625
|
navFnc: 'FullYear',
|
306
626
|
navStep: 10
|
307
627
|
}],
|
308
|
-
dates:{
|
309
|
-
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
|
310
|
-
daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
311
|
-
daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
|
312
|
-
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
313
|
-
monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
314
|
-
},
|
315
628
|
isLeapYear: function (year) {
|
316
629
|
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
|
317
630
|
},
|
318
631
|
getDaysInMonth: function (year, month) {
|
319
632
|
return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
|
320
633
|
},
|
634
|
+
validParts: /dd?|mm?|MM?|yy(?:yy)?/g,
|
635
|
+
nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\r]+/g,
|
321
636
|
parseFormat: function(format){
|
322
|
-
|
323
|
-
|
324
|
-
|
637
|
+
// IE treats \0 as a string end in inputs (truncating the value),
|
638
|
+
// so it's a bad format delimiter, anyway
|
639
|
+
var separators = format.replace(this.validParts, '\0').split('\0'),
|
640
|
+
parts = format.match(this.validParts);
|
641
|
+
if (!separators || !separators.length || !parts || parts.length == 0){
|
325
642
|
throw new Error("Invalid date format.");
|
326
643
|
}
|
327
|
-
return {
|
644
|
+
return {separators: separators, parts: parts};
|
328
645
|
},
|
329
|
-
parseDate: function(date, format) {
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
646
|
+
parseDate: function(date, format, language) {
|
647
|
+
if (date instanceof Date) return date;
|
648
|
+
if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
|
649
|
+
var part_re = /([-+]\d+)([dmwy])/,
|
650
|
+
parts = date.match(/([-+]\d+)([dmwy])/g),
|
651
|
+
part, dir;
|
652
|
+
date = new Date();
|
653
|
+
for (var i=0; i<parts.length; i++) {
|
654
|
+
part = part_re.exec(parts[i]);
|
655
|
+
dir = parseInt(part[1]);
|
656
|
+
switch(part[2]){
|
338
657
|
case 'd':
|
339
|
-
date.
|
658
|
+
date.setUTCDate(date.getUTCDate() + dir);
|
340
659
|
break;
|
341
|
-
case 'mm':
|
342
660
|
case 'm':
|
343
|
-
date.
|
661
|
+
date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir);
|
344
662
|
break;
|
345
|
-
case '
|
346
|
-
date.
|
663
|
+
case 'w':
|
664
|
+
date.setUTCDate(date.getUTCDate() + dir * 7);
|
347
665
|
break;
|
348
|
-
case '
|
349
|
-
date.
|
666
|
+
case 'y':
|
667
|
+
date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir);
|
350
668
|
break;
|
351
669
|
}
|
352
670
|
}
|
671
|
+
return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
|
672
|
+
}
|
673
|
+
var parts = date && date.match(this.nonpunctuation) || [],
|
674
|
+
date = new Date(),
|
675
|
+
parsed = {},
|
676
|
+
setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
|
677
|
+
setters_map = {
|
678
|
+
yyyy: function(d,v){ return d.setUTCFullYear(v); },
|
679
|
+
yy: function(d,v){ return d.setUTCFullYear(2000+v); },
|
680
|
+
m: function(d,v){
|
681
|
+
v -= 1;
|
682
|
+
while (v<0) v += 12;
|
683
|
+
v %= 12;
|
684
|
+
d.setUTCMonth(v);
|
685
|
+
while (d.getUTCMonth() != v)
|
686
|
+
d.setUTCDate(d.getUTCDate()-1);
|
687
|
+
return d;
|
688
|
+
},
|
689
|
+
d: function(d,v){ return d.setUTCDate(v); }
|
690
|
+
},
|
691
|
+
val, filtered, part;
|
692
|
+
setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
|
693
|
+
setters_map['dd'] = setters_map['d'];
|
694
|
+
date = UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
|
695
|
+
if (parts.length == format.parts.length) {
|
696
|
+
for (var i=0, cnt = format.parts.length; i < cnt; i++) {
|
697
|
+
val = parseInt(parts[i], 10);
|
698
|
+
part = format.parts[i];
|
699
|
+
if (isNaN(val)) {
|
700
|
+
switch(part) {
|
701
|
+
case 'MM':
|
702
|
+
filtered = $(dates[language].months).filter(function(){
|
703
|
+
var m = this.slice(0, parts[i].length),
|
704
|
+
p = parts[i].slice(0, m.length);
|
705
|
+
return m == p;
|
706
|
+
});
|
707
|
+
val = $.inArray(filtered[0], dates[language].months) + 1;
|
708
|
+
break;
|
709
|
+
case 'M':
|
710
|
+
filtered = $(dates[language].monthsShort).filter(function(){
|
711
|
+
var m = this.slice(0, parts[i].length),
|
712
|
+
p = parts[i].slice(0, m.length);
|
713
|
+
return m == p;
|
714
|
+
});
|
715
|
+
val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
|
716
|
+
break;
|
717
|
+
}
|
718
|
+
}
|
719
|
+
parsed[part] = val;
|
720
|
+
}
|
721
|
+
for (var i=0, s; i<setters_order.length; i++){
|
722
|
+
s = setters_order[i];
|
723
|
+
if (s in parsed)
|
724
|
+
setters_map[s](date, parsed[s])
|
725
|
+
}
|
353
726
|
}
|
354
727
|
return date;
|
355
728
|
},
|
356
|
-
formatDate: function(date, format){
|
729
|
+
formatDate: function(date, format, language){
|
357
730
|
var val = {
|
358
|
-
d: date.
|
359
|
-
m: date.
|
360
|
-
|
361
|
-
|
731
|
+
d: date.getUTCDate(),
|
732
|
+
m: date.getUTCMonth() + 1,
|
733
|
+
M: dates[language].monthsShort[date.getUTCMonth()],
|
734
|
+
MM: dates[language].months[date.getUTCMonth()],
|
735
|
+
yy: date.getUTCFullYear().toString().substring(2),
|
736
|
+
yyyy: date.getUTCFullYear()
|
362
737
|
};
|
363
738
|
val.dd = (val.d < 10 ? '0' : '') + val.d;
|
364
739
|
val.mm = (val.m < 10 ? '0' : '') + val.m;
|
365
|
-
var date = []
|
740
|
+
var date = [],
|
741
|
+
seps = $.extend([], format.separators);
|
366
742
|
for (var i=0, cnt = format.parts.length; i < cnt; i++) {
|
743
|
+
if (seps.length)
|
744
|
+
date.push(seps.shift())
|
367
745
|
date.push(val[format.parts[i]]);
|
368
746
|
}
|
369
|
-
return date.join(
|
747
|
+
return date.join('');
|
370
748
|
},
|
371
749
|
headTemplate: '<thead>'+
|
372
750
|
'<tr>'+
|
@@ -398,4 +776,4 @@
|
|
398
776
|
'</div>'+
|
399
777
|
'</div>';
|
400
778
|
|
401
|
-
}( window.jQuery )
|
779
|
+
}( window.jQuery );
|
data/lib/datetimepicker.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'simple_form'
|
2
|
+
|
3
|
+
module SimpleForm
|
4
|
+
module Inputs
|
5
|
+
|
6
|
+
class DatepickerInput < StringInput
|
7
|
+
|
8
|
+
def input
|
9
|
+
# Remove defaults that we do not want.
|
10
|
+
html_classes.delete(:datepicker)
|
11
|
+
html_classes.push(:datetimepicker)
|
12
|
+
|
13
|
+
input_html_classes.push(:datetimepicker_date)
|
14
|
+
input_html_options[:type] = "text"
|
15
|
+
|
16
|
+
# Get the input in the correct format.
|
17
|
+
input_html_options[:value] = object.send(attribute_name).try(:strftime, Time::DATE_FORMATS[:datetimepicker_date])
|
18
|
+
@builder.text_field(attribute_name, input_html_options)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'simple_form'
|
2
|
+
|
3
|
+
module SimpleForm
|
4
|
+
module Inputs
|
5
|
+
|
6
|
+
class TimepickerInput < StringInput
|
7
|
+
|
8
|
+
def input
|
9
|
+
# Remove defaults that we do not want.
|
10
|
+
html_classes.delete(:datepicker)
|
11
|
+
html_classes.push(:datetimepicker)
|
12
|
+
|
13
|
+
input_html_classes.push(:datetimepicker_time)
|
14
|
+
input_html_options[:type] = "text"
|
15
|
+
|
16
|
+
# Get the input in the correct format.
|
17
|
+
input_html_options[:value] = object.send(attribute_name).try(:strftime, Time::DATE_FORMATS[:datetimepicker_time])
|
18
|
+
@builder.text_field(attribute_name, input_html_options)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: datetimepicker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -35,7 +35,10 @@ files:
|
|
35
35
|
- lib/datetimepicker/date_and_time_manipulator.rb
|
36
36
|
- lib/datetimepicker/date_formats.rb
|
37
37
|
- lib/datetimepicker/engine.rb
|
38
|
+
- lib/datetimepicker/simple_form/inputs.rb
|
39
|
+
- lib/datetimepicker/simple_form/inputs/datepicker_input.rb
|
38
40
|
- lib/datetimepicker/simple_form/inputs/datetimepicker_input.rb
|
41
|
+
- lib/datetimepicker/simple_form/inputs/timepicker_input.rb
|
39
42
|
- lib/datetimepicker/version.rb
|
40
43
|
homepage: http://github.com/marshill/datetimepicker
|
41
44
|
licenses: []
|