taskwarrior-web 1.0.8 → 1.0.9
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/CHANGELOG.md +6 -0
- data/README.md +5 -1
- data/lib/taskwarrior-web/app.rb +14 -41
- data/lib/taskwarrior-web/helpers.rb +1 -1
- data/lib/taskwarrior-web/public/css/datepicker.css +230 -112
- data/lib/taskwarrior-web/public/js/application.js +2 -1
- data/lib/taskwarrior-web/public/js/bootstrap-datepicker.js +570 -135
- data/lib/taskwarrior-web/{command_builders → services/builder}/base.rb +3 -3
- data/lib/taskwarrior-web/{command_builders → services/builder}/v1.rb +1 -2
- data/lib/taskwarrior-web/{command_builders → services/builder}/v2.rb +0 -0
- data/lib/taskwarrior-web/{command_builder.rb → services/builder.rb} +3 -3
- data/lib/taskwarrior-web/{parser → services/parser}/csv.rb +0 -0
- data/lib/taskwarrior-web/{parser → services/parser}/json.rb +0 -0
- data/lib/taskwarrior-web/{parser.rb → services/parser.rb} +2 -2
- data/lib/taskwarrior-web/{runner.rb → services/runner.rb} +0 -0
- data/lib/taskwarrior-web/task.rb +11 -1
- data/lib/taskwarrior-web/views/projects.erb +31 -33
- data/lib/taskwarrior-web/views/task_form.erb +4 -4
- data/lib/taskwarrior-web.rb +3 -3
- data/spec/app/app_spec.rb +68 -1
- data/spec/app/helpers_spec.rb +6 -0
- data/spec/models/task_spec.rb +20 -0
- data/spec/{models/command_builders → services/builder}/base_spec.rb +19 -2
- data/spec/{models/command_builders → services/builder}/v1_spec.rb +7 -4
- data/spec/{models/command_builder_spec.rb → services/builder_spec.rb} +1 -1
- data/spec/services/parser_spec.rb +14 -0
- data/spec/{models → services}/runner_spec.rb +1 -1
- data/taskwarrior-web.gemspec +1 -1
- metadata +39 -39
- data/spec/models/command_builders/v2_spec.rb +0 -0
@@ -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,315 @@
|
|
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
|
+
function UTCToday(){
|
27
|
+
var today = new Date();
|
28
|
+
return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
|
29
|
+
}
|
30
|
+
|
22
31
|
// Picker object
|
23
|
-
|
24
|
-
var Datepicker = function(element, options){
|
32
|
+
|
33
|
+
var Datepicker = function(element, options) {
|
34
|
+
var that = this;
|
35
|
+
|
25
36
|
this.element = $(element);
|
37
|
+
this.language = options.language||this.element.data('date-language')||"en";
|
38
|
+
this.language = this.language in dates ? this.language : "en";
|
26
39
|
this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy');
|
27
40
|
this.picker = $(DPGlobal.template)
|
28
41
|
.appendTo('body')
|
29
42
|
.on({
|
30
|
-
click: $.proxy(this.click, this)
|
31
|
-
mousedown: $.proxy(this.mousedown, this)
|
43
|
+
click: $.proxy(this.click, this)
|
32
44
|
});
|
33
45
|
this.isInput = this.element.is('input');
|
34
46
|
this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
|
35
|
-
|
47
|
+
this.hasInput = this.component && this.element.find('input').length;
|
48
|
+
if(this.component && this.component.length === 0)
|
49
|
+
this.component = false;
|
50
|
+
|
36
51
|
if (this.isInput) {
|
37
52
|
this.element.on({
|
38
53
|
focus: $.proxy(this.show, this),
|
39
|
-
|
40
|
-
|
54
|
+
keyup: $.proxy(this.update, this),
|
55
|
+
keydown: $.proxy(this.keydown, this)
|
41
56
|
});
|
42
57
|
} else {
|
43
|
-
if (this.component){
|
58
|
+
if (this.component && this.hasInput){
|
59
|
+
// For components that are not readonly, allow keyboard nav
|
60
|
+
this.element.find('input').on({
|
61
|
+
focus: $.proxy(this.show, this),
|
62
|
+
keyup: $.proxy(this.update, this),
|
63
|
+
keydown: $.proxy(this.keydown, this)
|
64
|
+
});
|
65
|
+
|
44
66
|
this.component.on('click', $.proxy(this.show, this));
|
45
67
|
} else {
|
46
68
|
this.element.on('click', $.proxy(this.show, this));
|
47
69
|
}
|
48
70
|
}
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
71
|
+
|
72
|
+
$(document).on('mousedown', function (e) {
|
73
|
+
// Clicked outside the datepicker, hide it
|
74
|
+
if ($(e.target).closest('.datepicker').length == 0) {
|
75
|
+
that.hide();
|
76
|
+
}
|
77
|
+
});
|
78
|
+
|
79
|
+
this.autoclose = false;
|
80
|
+
if ('autoclose' in options) {
|
81
|
+
this.autoclose = options.autoclose;
|
82
|
+
} else if ('dateAutoclose' in this.element.data()) {
|
83
|
+
this.autoclose = this.element.data('date-autoclose');
|
84
|
+
}
|
85
|
+
|
86
|
+
this.keyboardNavigation = true;
|
87
|
+
if ('keyboardNavigation' in options) {
|
88
|
+
this.keyboardNavigation = options.keyboardNavigation;
|
89
|
+
} else if ('dateKeyboardNavigation' in this.element.data()) {
|
90
|
+
this.keyboardNavigation = this.element.data('date-keyboard-navigation');
|
91
|
+
}
|
92
|
+
|
93
|
+
switch(options.startView || this.element.data('date-start-view')){
|
94
|
+
case 2:
|
95
|
+
case 'decade':
|
96
|
+
this.viewMode = this.startViewMode = 2;
|
97
|
+
break;
|
98
|
+
case 1:
|
99
|
+
case 'year':
|
100
|
+
this.viewMode = this.startViewMode = 1;
|
101
|
+
break;
|
102
|
+
case 0:
|
103
|
+
case 'month':
|
104
|
+
default:
|
105
|
+
this.viewMode = this.startViewMode = 0;
|
106
|
+
break;
|
107
|
+
}
|
108
|
+
|
109
|
+
this.todayBtn = (options.todayBtn||this.element.data('date-today-btn')||false);
|
110
|
+
this.todayHighlight = (options.todayHighlight||this.element.data('date-today-highlight')||false);
|
111
|
+
|
112
|
+
this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7);
|
113
|
+
this.weekEnd = ((this.weekStart + 6) % 7);
|
114
|
+
this.startDate = -Infinity;
|
115
|
+
this.endDate = Infinity;
|
116
|
+
this.setStartDate(options.startDate||this.element.data('date-startdate'));
|
117
|
+
this.setEndDate(options.endDate||this.element.data('date-enddate'));
|
53
118
|
this.fillDow();
|
54
119
|
this.fillMonths();
|
55
120
|
this.update();
|
56
121
|
this.showMode();
|
57
122
|
};
|
58
|
-
|
123
|
+
|
59
124
|
Datepicker.prototype = {
|
60
125
|
constructor: Datepicker,
|
61
|
-
|
126
|
+
|
62
127
|
show: function(e) {
|
63
128
|
this.picker.show();
|
64
129
|
this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
|
130
|
+
this.update();
|
65
131
|
this.place();
|
66
132
|
$(window).on('resize', $.proxy(this.place, this));
|
67
133
|
if (e ) {
|
68
134
|
e.stopPropagation();
|
69
135
|
e.preventDefault();
|
70
136
|
}
|
71
|
-
if (!this.isInput) {
|
72
|
-
$(document).on('mousedown', $.proxy(this.hide, this));
|
73
|
-
}
|
74
137
|
this.element.trigger({
|
75
138
|
type: 'show',
|
76
139
|
date: this.date
|
77
140
|
});
|
78
141
|
},
|
79
|
-
|
80
|
-
hide: function(){
|
142
|
+
|
143
|
+
hide: function(e){
|
81
144
|
this.picker.hide();
|
82
145
|
$(window).off('resize', this.place);
|
83
|
-
this.viewMode =
|
146
|
+
this.viewMode = this.startViewMode;
|
84
147
|
this.showMode();
|
85
148
|
if (!this.isInput) {
|
86
149
|
$(document).off('mousedown', this.hide);
|
87
150
|
}
|
88
|
-
|
151
|
+
if (e && e.currentTarget.value)
|
152
|
+
this.setValue();
|
89
153
|
this.element.trigger({
|
90
154
|
type: 'hide',
|
91
155
|
date: this.date
|
92
156
|
});
|
93
157
|
},
|
94
|
-
|
158
|
+
|
159
|
+
getDate: function() {
|
160
|
+
var d = this.getUTCDate();
|
161
|
+
return new Date(d.getTime() + (d.getTimezoneOffset()*60000))
|
162
|
+
},
|
163
|
+
|
164
|
+
getUTCDate: function() {
|
165
|
+
return this.date;
|
166
|
+
},
|
167
|
+
|
168
|
+
setDate: function(d) {
|
169
|
+
this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000)));
|
170
|
+
},
|
171
|
+
|
172
|
+
setUTCDate: function(d) {
|
173
|
+
this.date = d;
|
174
|
+
this.setValue();
|
175
|
+
},
|
176
|
+
|
95
177
|
setValue: function() {
|
96
|
-
var
|
178
|
+
var formatted = DPGlobal.formatDate(this.date, this.format, this.language);
|
97
179
|
if (!this.isInput) {
|
98
180
|
if (this.component){
|
99
|
-
this.element.find('input').prop('value',
|
181
|
+
this.element.find('input').prop('value', formatted);
|
100
182
|
}
|
101
|
-
this.element.data('date',
|
183
|
+
this.element.data('date', formatted);
|
102
184
|
} else {
|
103
|
-
this.element.prop('value',
|
185
|
+
this.element.prop('value', formatted);
|
186
|
+
}
|
187
|
+
},
|
188
|
+
|
189
|
+
setStartDate: function(startDate){
|
190
|
+
this.startDate = startDate||-Infinity;
|
191
|
+
if (this.startDate !== -Infinity) {
|
192
|
+
this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language);
|
193
|
+
}
|
194
|
+
this.update();
|
195
|
+
this.updateNavArrows();
|
196
|
+
},
|
197
|
+
|
198
|
+
setEndDate: function(endDate){
|
199
|
+
this.endDate = endDate||Infinity;
|
200
|
+
if (this.endDate !== Infinity) {
|
201
|
+
this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language);
|
104
202
|
}
|
203
|
+
this.update();
|
204
|
+
this.updateNavArrows();
|
105
205
|
},
|
106
|
-
|
206
|
+
|
107
207
|
place: function(){
|
208
|
+
var zIndex = parseInt(this.element.parents().filter(function() {
|
209
|
+
return $(this).css('z-index') != 'auto';
|
210
|
+
}).first().css('z-index'))+10;
|
108
211
|
var offset = this.component ? this.component.offset() : this.element.offset();
|
109
212
|
this.picker.css({
|
110
213
|
top: offset.top + this.height,
|
111
|
-
left: offset.left
|
214
|
+
left: offset.left,
|
215
|
+
zIndex: zIndex
|
112
216
|
});
|
113
217
|
},
|
114
|
-
|
218
|
+
|
115
219
|
update: function(){
|
116
220
|
this.date = DPGlobal.parseDate(
|
117
|
-
this.isInput ? this.element.prop('value') : this.element.data('date'),
|
118
|
-
this.format
|
221
|
+
this.isInput ? this.element.prop('value') : this.element.data('date') || this.element.find('input').prop('value'),
|
222
|
+
this.format, this.language
|
119
223
|
);
|
120
|
-
this.
|
224
|
+
if (this.date < this.startDate) {
|
225
|
+
this.viewDate = new Date(this.startDate);
|
226
|
+
} else if (this.date > this.endDate) {
|
227
|
+
this.viewDate = new Date(this.endDate);
|
228
|
+
} else {
|
229
|
+
this.viewDate = new Date(this.date);
|
230
|
+
}
|
121
231
|
this.fill();
|
122
232
|
},
|
123
|
-
|
233
|
+
|
124
234
|
fillDow: function(){
|
125
235
|
var dowCnt = this.weekStart;
|
126
236
|
var html = '<tr>';
|
127
237
|
while (dowCnt < this.weekStart + 7) {
|
128
|
-
html += '<th class="dow">'+
|
238
|
+
html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>';
|
129
239
|
}
|
130
240
|
html += '</tr>';
|
131
241
|
this.picker.find('.datepicker-days thead').append(html);
|
132
242
|
},
|
133
|
-
|
243
|
+
|
134
244
|
fillMonths: function(){
|
135
245
|
var html = '';
|
136
246
|
var i = 0
|
137
247
|
while (i < 12) {
|
138
|
-
html += '<span class="month">'+
|
248
|
+
html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>';
|
139
249
|
}
|
140
|
-
this.picker.find('.datepicker-months td').
|
250
|
+
this.picker.find('.datepicker-months td').html(html);
|
141
251
|
},
|
142
|
-
|
252
|
+
|
143
253
|
fill: function() {
|
144
254
|
var d = new Date(this.viewDate),
|
145
|
-
year = d.
|
146
|
-
month = d.
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
255
|
+
year = d.getUTCFullYear(),
|
256
|
+
month = d.getUTCMonth(),
|
257
|
+
startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
|
258
|
+
startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
|
259
|
+
endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
|
260
|
+
endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
|
261
|
+
currentDate = this.date.valueOf(),
|
262
|
+
today = new Date();
|
263
|
+
this.picker.find('.datepicker-days thead th:eq(1)')
|
264
|
+
.text(dates[this.language].months[month]+' '+year);
|
265
|
+
this.picker.find('tfoot th.today')
|
266
|
+
.text(dates[this.language].today)
|
267
|
+
.toggle(this.todayBtn === 'linked');
|
268
|
+
this.updateNavArrows();
|
269
|
+
this.fillMonths();
|
270
|
+
var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
|
271
|
+
day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
|
272
|
+
prevMonth.setUTCDate(day);
|
273
|
+
prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7);
|
154
274
|
var nextMonth = new Date(prevMonth);
|
155
|
-
nextMonth.
|
275
|
+
nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
|
156
276
|
nextMonth = nextMonth.valueOf();
|
157
|
-
html = [];
|
277
|
+
var html = [];
|
158
278
|
var clsName;
|
159
279
|
while(prevMonth.valueOf() < nextMonth) {
|
160
|
-
if (prevMonth.
|
280
|
+
if (prevMonth.getUTCDay() == this.weekStart) {
|
161
281
|
html.push('<tr>');
|
162
282
|
}
|
163
283
|
clsName = '';
|
164
|
-
if (prevMonth.
|
284
|
+
if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
|
165
285
|
clsName += ' old';
|
166
|
-
} else if (prevMonth.
|
286
|
+
} else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {
|
167
287
|
clsName += ' new';
|
168
288
|
}
|
289
|
+
// Compare internal UTC date with local today, not UTC today
|
290
|
+
if (this.todayHighlight &&
|
291
|
+
prevMonth.getUTCFullYear() == today.getFullYear() &&
|
292
|
+
prevMonth.getUTCMonth() == today.getMonth() &&
|
293
|
+
prevMonth.getUTCDate() == today.getDate()) {
|
294
|
+
clsName += ' today';
|
295
|
+
}
|
169
296
|
if (prevMonth.valueOf() == currentDate) {
|
170
297
|
clsName += ' active';
|
171
298
|
}
|
172
|
-
|
173
|
-
|
299
|
+
if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate) {
|
300
|
+
clsName += ' disabled';
|
301
|
+
}
|
302
|
+
html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>');
|
303
|
+
if (prevMonth.getUTCDay() == this.weekEnd) {
|
174
304
|
html.push('</tr>');
|
175
305
|
}
|
176
|
-
prevMonth.
|
306
|
+
prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
|
177
307
|
}
|
178
308
|
this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
|
179
|
-
var currentYear = this.date.
|
180
|
-
|
309
|
+
var currentYear = this.date.getUTCFullYear();
|
310
|
+
|
181
311
|
var months = this.picker.find('.datepicker-months')
|
182
312
|
.find('th:eq(1)')
|
183
313
|
.text(year)
|
184
314
|
.end()
|
185
315
|
.find('span').removeClass('active');
|
186
316
|
if (currentYear == year) {
|
187
|
-
months.eq(this.date.
|
317
|
+
months.eq(this.date.getUTCMonth()).addClass('active');
|
318
|
+
}
|
319
|
+
if (year < startYear || year > endYear) {
|
320
|
+
months.addClass('disabled');
|
321
|
+
}
|
322
|
+
if (year == startYear) {
|
323
|
+
months.slice(0, startMonth).addClass('disabled');
|
188
324
|
}
|
189
|
-
|
325
|
+
if (year == endYear) {
|
326
|
+
months.slice(endMonth+1).addClass('disabled');
|
327
|
+
}
|
328
|
+
|
190
329
|
html = '';
|
191
330
|
year = parseInt(year/10, 10) * 10;
|
192
331
|
var yearCont = this.picker.find('.datepicker-years')
|
@@ -196,12 +335,45 @@
|
|
196
335
|
.find('td');
|
197
336
|
year -= 1;
|
198
337
|
for (var i = -1; i < 11; i++) {
|
199
|
-
html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+'">'+year+'</span>';
|
338
|
+
html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>';
|
200
339
|
year += 1;
|
201
340
|
}
|
202
341
|
yearCont.html(html);
|
203
342
|
},
|
204
|
-
|
343
|
+
|
344
|
+
updateNavArrows: function() {
|
345
|
+
var d = new Date(this.viewDate),
|
346
|
+
year = d.getUTCFullYear(),
|
347
|
+
month = d.getUTCMonth();
|
348
|
+
switch (this.viewMode) {
|
349
|
+
case 0:
|
350
|
+
if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
|
351
|
+
this.picker.find('.prev').css({visibility: 'hidden'});
|
352
|
+
} else {
|
353
|
+
this.picker.find('.prev').css({visibility: 'visible'});
|
354
|
+
}
|
355
|
+
if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
|
356
|
+
this.picker.find('.next').css({visibility: 'hidden'});
|
357
|
+
} else {
|
358
|
+
this.picker.find('.next').css({visibility: 'visible'});
|
359
|
+
}
|
360
|
+
break;
|
361
|
+
case 1:
|
362
|
+
case 2:
|
363
|
+
if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
|
364
|
+
this.picker.find('.prev').css({visibility: 'hidden'});
|
365
|
+
} else {
|
366
|
+
this.picker.find('.prev').css({visibility: 'visible'});
|
367
|
+
}
|
368
|
+
if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
|
369
|
+
this.picker.find('.next').css({visibility: 'hidden'});
|
370
|
+
} else {
|
371
|
+
this.picker.find('.next').css({visibility: 'visible'});
|
372
|
+
}
|
373
|
+
break;
|
374
|
+
}
|
375
|
+
},
|
376
|
+
|
205
377
|
click: function(e) {
|
206
378
|
e.stopPropagation();
|
207
379
|
e.preventDefault();
|
@@ -215,64 +387,254 @@
|
|
215
387
|
break;
|
216
388
|
case 'prev':
|
217
389
|
case 'next':
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
390
|
+
var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
|
391
|
+
switch(this.viewMode){
|
392
|
+
case 0:
|
393
|
+
this.viewDate = this.moveMonth(this.viewDate, dir);
|
394
|
+
break;
|
395
|
+
case 1:
|
396
|
+
case 2:
|
397
|
+
this.viewDate = this.moveYear(this.viewDate, dir);
|
398
|
+
break;
|
399
|
+
}
|
223
400
|
this.fill();
|
224
401
|
break;
|
402
|
+
case 'today':
|
403
|
+
var date = new Date();
|
404
|
+
date.setUTCHours(0);
|
405
|
+
date.setUTCMinutes(0);
|
406
|
+
date.setUTCSeconds(0);
|
407
|
+
date.setUTCMilliseconds(0);
|
408
|
+
|
409
|
+
this.showMode(-2);
|
410
|
+
var which = this.todayBtn == 'linked' ? null : 'view';
|
411
|
+
this._setDate(date, which);
|
412
|
+
break;
|
225
413
|
}
|
226
414
|
break;
|
227
415
|
case 'span':
|
228
|
-
if (target.is('.
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
416
|
+
if (!target.is('.disabled')) {
|
417
|
+
this.viewDate.setUTCDate(1);
|
418
|
+
if (target.is('.month')) {
|
419
|
+
var month = target.parent().find('span').index(target);
|
420
|
+
this.viewDate.setUTCMonth(month);
|
421
|
+
this.element.trigger({
|
422
|
+
type: 'changeMonth',
|
423
|
+
date: this.viewDate
|
424
|
+
});
|
425
|
+
} else {
|
426
|
+
var year = parseInt(target.text(), 10)||0;
|
427
|
+
this.viewDate.setUTCFullYear(year);
|
428
|
+
this.element.trigger({
|
429
|
+
type: 'changeYear',
|
430
|
+
date: this.viewDate
|
431
|
+
});
|
432
|
+
}
|
433
|
+
this.showMode(-1);
|
434
|
+
this.fill();
|
234
435
|
}
|
235
|
-
this.showMode(-1);
|
236
|
-
this.fill();
|
237
436
|
break;
|
238
437
|
case 'td':
|
239
|
-
if (target.is('.day')){
|
438
|
+
if (target.is('.day') && !target.is('.disabled')){
|
240
439
|
var day = parseInt(target.text(), 10)||1;
|
241
|
-
var
|
440
|
+
var year = this.viewDate.getUTCFullYear(),
|
441
|
+
month = this.viewDate.getUTCMonth();
|
242
442
|
if (target.is('.old')) {
|
243
|
-
month
|
443
|
+
if (month == 0) {
|
444
|
+
month = 11;
|
445
|
+
year -= 1;
|
446
|
+
} else {
|
447
|
+
month -= 1;
|
448
|
+
}
|
244
449
|
} else if (target.is('.new')) {
|
245
|
-
month
|
450
|
+
if (month == 11) {
|
451
|
+
month = 0;
|
452
|
+
year += 1;
|
453
|
+
} else {
|
454
|
+
month += 1;
|
455
|
+
}
|
246
456
|
}
|
247
|
-
|
248
|
-
this.date = new Date(year, month, day,0,0,0,0);
|
249
|
-
this.viewDate = new Date(year, month, day,0,0,0,0);
|
250
|
-
this.fill();
|
251
|
-
this.setValue();
|
252
|
-
this.element.trigger({
|
253
|
-
type: 'changeDate',
|
254
|
-
date: this.date
|
255
|
-
});
|
457
|
+
this._setDate(UTCDate(year, month, day,0,0,0,0));
|
256
458
|
}
|
257
459
|
break;
|
258
460
|
}
|
259
461
|
}
|
260
462
|
},
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
463
|
+
|
464
|
+
_setDate: function(date, which){
|
465
|
+
if (!which || which == 'date')
|
466
|
+
this.date = date;
|
467
|
+
if (!which || which == 'view')
|
468
|
+
this.viewDate = date;
|
469
|
+
this.fill();
|
470
|
+
this.setValue();
|
471
|
+
this.element.trigger({
|
472
|
+
type: 'changeDate',
|
473
|
+
date: this.date
|
474
|
+
});
|
475
|
+
var element;
|
476
|
+
if (this.isInput) {
|
477
|
+
element = this.element;
|
478
|
+
} else if (this.component){
|
479
|
+
element = this.element.find('input');
|
480
|
+
}
|
481
|
+
if (element) {
|
482
|
+
element.change();
|
483
|
+
if (this.autoclose) {
|
484
|
+
this.hide();
|
485
|
+
}
|
486
|
+
}
|
487
|
+
},
|
488
|
+
|
489
|
+
moveMonth: function(date, dir){
|
490
|
+
if (!dir) return date;
|
491
|
+
var new_date = new Date(date.valueOf()),
|
492
|
+
day = new_date.getUTCDate(),
|
493
|
+
month = new_date.getUTCMonth(),
|
494
|
+
mag = Math.abs(dir),
|
495
|
+
new_month, test;
|
496
|
+
dir = dir > 0 ? 1 : -1;
|
497
|
+
if (mag == 1){
|
498
|
+
test = dir == -1
|
499
|
+
// If going back one month, make sure month is not current month
|
500
|
+
// (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
|
501
|
+
? function(){ return new_date.getUTCMonth() == month; }
|
502
|
+
// If going forward one month, make sure month is as expected
|
503
|
+
// (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
|
504
|
+
: function(){ return new_date.getUTCMonth() != new_month; };
|
505
|
+
new_month = month + dir;
|
506
|
+
new_date.setUTCMonth(new_month);
|
507
|
+
// Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
|
508
|
+
if (new_month < 0 || new_month > 11)
|
509
|
+
new_month = (new_month + 12) % 12;
|
510
|
+
} else {
|
511
|
+
// For magnitudes >1, move one month at a time...
|
512
|
+
for (var i=0; i<mag; i++)
|
513
|
+
// ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
|
514
|
+
new_date = this.moveMonth(new_date, dir);
|
515
|
+
// ...then reset the day, keeping it in the new month
|
516
|
+
new_month = new_date.getUTCMonth();
|
517
|
+
new_date.setUTCDate(day);
|
518
|
+
test = function(){ return new_month != new_date.getUTCMonth(); };
|
519
|
+
}
|
520
|
+
// Common date-resetting loop -- if date is beyond end of month, make it
|
521
|
+
// end of month
|
522
|
+
while (test()){
|
523
|
+
new_date.setUTCDate(--day);
|
524
|
+
new_date.setUTCMonth(new_month);
|
525
|
+
}
|
526
|
+
return new_date;
|
527
|
+
},
|
528
|
+
|
529
|
+
moveYear: function(date, dir){
|
530
|
+
return this.moveMonth(date, dir*12);
|
265
531
|
},
|
266
|
-
|
532
|
+
|
533
|
+
dateWithinRange: function(date){
|
534
|
+
return date >= this.startDate && date <= this.endDate;
|
535
|
+
},
|
536
|
+
|
537
|
+
keydown: function(e){
|
538
|
+
if (this.picker.is(':not(:visible)')){
|
539
|
+
if (e.keyCode == 27) // allow escape to hide and re-show picker
|
540
|
+
this.show();
|
541
|
+
return;
|
542
|
+
}
|
543
|
+
var dateChanged = false,
|
544
|
+
dir, day, month,
|
545
|
+
newDate, newViewDate;
|
546
|
+
switch(e.keyCode){
|
547
|
+
case 27: // escape
|
548
|
+
this.hide();
|
549
|
+
e.preventDefault();
|
550
|
+
break;
|
551
|
+
case 37: // left
|
552
|
+
case 39: // right
|
553
|
+
if (!this.keyboardNavigation) break;
|
554
|
+
dir = e.keyCode == 37 ? -1 : 1;
|
555
|
+
if (e.ctrlKey){
|
556
|
+
newDate = this.moveYear(this.date, dir);
|
557
|
+
newViewDate = this.moveYear(this.viewDate, dir);
|
558
|
+
} else if (e.shiftKey){
|
559
|
+
newDate = this.moveMonth(this.date, dir);
|
560
|
+
newViewDate = this.moveMonth(this.viewDate, dir);
|
561
|
+
} else {
|
562
|
+
newDate = new Date(this.date);
|
563
|
+
newDate.setUTCDate(this.date.getUTCDate() + dir);
|
564
|
+
newViewDate = new Date(this.viewDate);
|
565
|
+
newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
|
566
|
+
}
|
567
|
+
if (this.dateWithinRange(newDate)){
|
568
|
+
this.date = newDate;
|
569
|
+
this.viewDate = newViewDate;
|
570
|
+
this.setValue();
|
571
|
+
this.update();
|
572
|
+
e.preventDefault();
|
573
|
+
dateChanged = true;
|
574
|
+
}
|
575
|
+
break;
|
576
|
+
case 38: // up
|
577
|
+
case 40: // down
|
578
|
+
if (!this.keyboardNavigation) break;
|
579
|
+
dir = e.keyCode == 38 ? -1 : 1;
|
580
|
+
if (e.ctrlKey){
|
581
|
+
newDate = this.moveYear(this.date, dir);
|
582
|
+
newViewDate = this.moveYear(this.viewDate, dir);
|
583
|
+
} else if (e.shiftKey){
|
584
|
+
newDate = this.moveMonth(this.date, dir);
|
585
|
+
newViewDate = this.moveMonth(this.viewDate, dir);
|
586
|
+
} else {
|
587
|
+
newDate = new Date(this.date);
|
588
|
+
newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
|
589
|
+
newViewDate = new Date(this.viewDate);
|
590
|
+
newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
|
591
|
+
}
|
592
|
+
if (this.dateWithinRange(newDate)){
|
593
|
+
this.date = newDate;
|
594
|
+
this.viewDate = newViewDate;
|
595
|
+
this.setValue();
|
596
|
+
this.update();
|
597
|
+
e.preventDefault();
|
598
|
+
dateChanged = true;
|
599
|
+
}
|
600
|
+
break;
|
601
|
+
case 13: // enter
|
602
|
+
this.hide();
|
603
|
+
e.preventDefault();
|
604
|
+
break;
|
605
|
+
case 9: // tab
|
606
|
+
this.hide();
|
607
|
+
break;
|
608
|
+
}
|
609
|
+
if (dateChanged){
|
610
|
+
this.element.trigger({
|
611
|
+
type: 'changeDate',
|
612
|
+
date: this.date
|
613
|
+
});
|
614
|
+
var element;
|
615
|
+
if (this.isInput) {
|
616
|
+
element = this.element;
|
617
|
+
} else if (this.component){
|
618
|
+
element = this.element.find('input');
|
619
|
+
}
|
620
|
+
if (element) {
|
621
|
+
element.change();
|
622
|
+
}
|
623
|
+
}
|
624
|
+
},
|
625
|
+
|
267
626
|
showMode: function(dir) {
|
268
627
|
if (dir) {
|
269
628
|
this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir));
|
270
629
|
}
|
271
630
|
this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
|
631
|
+
this.updateNavArrows();
|
272
632
|
}
|
273
633
|
};
|
274
|
-
|
634
|
+
|
275
635
|
$.fn.datepicker = function ( option ) {
|
636
|
+
var args = Array.apply(null, arguments);
|
637
|
+
args.shift();
|
276
638
|
return this.each(function () {
|
277
639
|
var $this = $(this),
|
278
640
|
data = $this.data('datepicker'),
|
@@ -280,14 +642,26 @@
|
|
280
642
|
if (!data) {
|
281
643
|
$this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options))));
|
282
644
|
}
|
283
|
-
if (typeof option == 'string'
|
645
|
+
if (typeof option == 'string' && typeof data[option] == 'function') {
|
646
|
+
data[option].apply(data, args);
|
647
|
+
}
|
284
648
|
});
|
285
649
|
};
|
286
650
|
|
287
651
|
$.fn.datepicker.defaults = {
|
288
652
|
};
|
289
653
|
$.fn.datepicker.Constructor = Datepicker;
|
290
|
-
|
654
|
+
var dates = $.fn.datepicker.dates = {
|
655
|
+
en: {
|
656
|
+
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
|
657
|
+
daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
658
|
+
daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
|
659
|
+
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
660
|
+
monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
661
|
+
today: "Today"
|
662
|
+
}
|
663
|
+
}
|
664
|
+
|
291
665
|
var DPGlobal = {
|
292
666
|
modes: [
|
293
667
|
{
|
@@ -305,68 +679,126 @@
|
|
305
679
|
navFnc: 'FullYear',
|
306
680
|
navStep: 10
|
307
681
|
}],
|
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
682
|
isLeapYear: function (year) {
|
316
683
|
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
|
317
684
|
},
|
318
685
|
getDaysInMonth: function (year, month) {
|
319
686
|
return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
|
320
687
|
},
|
688
|
+
validParts: /dd?|mm?|MM?|yy(?:yy)?/g,
|
689
|
+
nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\r]+/g,
|
321
690
|
parseFormat: function(format){
|
322
|
-
|
323
|
-
|
324
|
-
|
691
|
+
// IE treats \0 as a string end in inputs (truncating the value),
|
692
|
+
// so it's a bad format delimiter, anyway
|
693
|
+
var separators = format.replace(this.validParts, '\0').split('\0'),
|
694
|
+
parts = format.match(this.validParts);
|
695
|
+
if (!separators || !separators.length || !parts || parts.length == 0){
|
325
696
|
throw new Error("Invalid date format.");
|
326
697
|
}
|
327
|
-
return {
|
698
|
+
return {separators: separators, parts: parts};
|
328
699
|
},
|
329
|
-
parseDate: function(date, format) {
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
700
|
+
parseDate: function(date, format, language) {
|
701
|
+
if (date instanceof Date) return date;
|
702
|
+
if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
|
703
|
+
var part_re = /([-+]\d+)([dmwy])/,
|
704
|
+
parts = date.match(/([-+]\d+)([dmwy])/g),
|
705
|
+
part, dir;
|
706
|
+
date = new Date();
|
707
|
+
for (var i=0; i<parts.length; i++) {
|
708
|
+
part = part_re.exec(parts[i]);
|
709
|
+
dir = parseInt(part[1]);
|
710
|
+
switch(part[2]){
|
338
711
|
case 'd':
|
339
|
-
date.
|
712
|
+
date.setUTCDate(date.getUTCDate() + dir);
|
340
713
|
break;
|
341
|
-
case 'mm':
|
342
714
|
case 'm':
|
343
|
-
date.
|
715
|
+
date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir);
|
344
716
|
break;
|
345
|
-
case '
|
346
|
-
date.
|
717
|
+
case 'w':
|
718
|
+
date.setUTCDate(date.getUTCDate() + dir * 7);
|
347
719
|
break;
|
348
|
-
case '
|
349
|
-
date.
|
720
|
+
case 'y':
|
721
|
+
date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir);
|
350
722
|
break;
|
351
723
|
}
|
352
724
|
}
|
725
|
+
return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
|
726
|
+
}
|
727
|
+
var parts = date && date.match(this.nonpunctuation) || [],
|
728
|
+
date = new Date(),
|
729
|
+
parsed = {},
|
730
|
+
setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
|
731
|
+
setters_map = {
|
732
|
+
yyyy: function(d,v){ return d.setUTCFullYear(v); },
|
733
|
+
yy: function(d,v){ return d.setUTCFullYear(2000+v); },
|
734
|
+
m: function(d,v){
|
735
|
+
v -= 1;
|
736
|
+
while (v<0) v += 12;
|
737
|
+
v %= 12;
|
738
|
+
d.setUTCMonth(v);
|
739
|
+
while (d.getUTCMonth() != v)
|
740
|
+
d.setUTCDate(d.getUTCDate()-1);
|
741
|
+
return d;
|
742
|
+
},
|
743
|
+
d: function(d,v){ return d.setUTCDate(v); }
|
744
|
+
},
|
745
|
+
val, filtered, part;
|
746
|
+
setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
|
747
|
+
setters_map['dd'] = setters_map['d'];
|
748
|
+
date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
|
749
|
+
if (parts.length == format.parts.length) {
|
750
|
+
for (var i=0, cnt = format.parts.length; i < cnt; i++) {
|
751
|
+
val = parseInt(parts[i], 10);
|
752
|
+
part = format.parts[i];
|
753
|
+
if (isNaN(val)) {
|
754
|
+
switch(part) {
|
755
|
+
case 'MM':
|
756
|
+
filtered = $(dates[language].months).filter(function(){
|
757
|
+
var m = this.slice(0, parts[i].length),
|
758
|
+
p = parts[i].slice(0, m.length);
|
759
|
+
return m == p;
|
760
|
+
});
|
761
|
+
val = $.inArray(filtered[0], dates[language].months) + 1;
|
762
|
+
break;
|
763
|
+
case 'M':
|
764
|
+
filtered = $(dates[language].monthsShort).filter(function(){
|
765
|
+
var m = this.slice(0, parts[i].length),
|
766
|
+
p = parts[i].slice(0, m.length);
|
767
|
+
return m == p;
|
768
|
+
});
|
769
|
+
val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
|
770
|
+
break;
|
771
|
+
}
|
772
|
+
}
|
773
|
+
parsed[part] = val;
|
774
|
+
}
|
775
|
+
for (var i=0, s; i<setters_order.length; i++){
|
776
|
+
s = setters_order[i];
|
777
|
+
if (s in parsed && !isNaN(parsed[s]))
|
778
|
+
setters_map[s](date, parsed[s])
|
779
|
+
}
|
353
780
|
}
|
354
781
|
return date;
|
355
782
|
},
|
356
|
-
formatDate: function(date, format){
|
783
|
+
formatDate: function(date, format, language){
|
357
784
|
var val = {
|
358
|
-
d: date.
|
359
|
-
m: date.
|
360
|
-
|
361
|
-
|
785
|
+
d: date.getUTCDate(),
|
786
|
+
m: date.getUTCMonth() + 1,
|
787
|
+
M: dates[language].monthsShort[date.getUTCMonth()],
|
788
|
+
MM: dates[language].months[date.getUTCMonth()],
|
789
|
+
yy: date.getUTCFullYear().toString().substring(2),
|
790
|
+
yyyy: date.getUTCFullYear()
|
362
791
|
};
|
363
792
|
val.dd = (val.d < 10 ? '0' : '') + val.d;
|
364
793
|
val.mm = (val.m < 10 ? '0' : '') + val.m;
|
365
|
-
var date = []
|
794
|
+
var date = [],
|
795
|
+
seps = $.extend([], format.separators);
|
366
796
|
for (var i=0, cnt = format.parts.length; i < cnt; i++) {
|
797
|
+
if (seps.length)
|
798
|
+
date.push(seps.shift())
|
367
799
|
date.push(val[format.parts[i]]);
|
368
800
|
}
|
369
|
-
return date.join(
|
801
|
+
return date.join('');
|
370
802
|
},
|
371
803
|
headTemplate: '<thead>'+
|
372
804
|
'<tr>'+
|
@@ -375,27 +807,30 @@
|
|
375
807
|
'<th class="next"><i class="icon-arrow-right"/></th>'+
|
376
808
|
'</tr>'+
|
377
809
|
'</thead>',
|
378
|
-
contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
|
810
|
+
contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
|
811
|
+
footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'
|
379
812
|
};
|
380
813
|
DPGlobal.template = '<div class="datepicker dropdown-menu">'+
|
381
814
|
'<div class="datepicker-days">'+
|
382
815
|
'<table class=" table-condensed">'+
|
383
816
|
DPGlobal.headTemplate+
|
384
817
|
'<tbody></tbody>'+
|
818
|
+
DPGlobal.footTemplate+
|
385
819
|
'</table>'+
|
386
820
|
'</div>'+
|
387
821
|
'<div class="datepicker-months">'+
|
388
822
|
'<table class="table-condensed">'+
|
389
823
|
DPGlobal.headTemplate+
|
390
824
|
DPGlobal.contTemplate+
|
825
|
+
DPGlobal.footTemplate+
|
391
826
|
'</table>'+
|
392
827
|
'</div>'+
|
393
828
|
'<div class="datepicker-years">'+
|
394
829
|
'<table class="table-condensed">'+
|
395
830
|
DPGlobal.headTemplate+
|
396
831
|
DPGlobal.contTemplate+
|
832
|
+
DPGlobal.footTemplate+
|
397
833
|
'</table>'+
|
398
834
|
'</div>'+
|
399
835
|
'</div>';
|
400
|
-
|
401
|
-
}( window.jQuery )
|
836
|
+
}( window.jQuery );
|