datetime_picker_rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bc63273ff09b601d035e2aa7c4dcbeb8148bff06
4
+ data.tar.gz: e758a0b842ce308f4f23e91babc63d50244409fc
5
+ SHA512:
6
+ metadata.gz: ad825f128b647bf7d2fdbf59e9f95cd88108bd8c0b4f6f52c5154121e0625808ef25f02e044395efe18f3505530981c1c9ae842bde62a3daf0db9798afae4006
7
+ data.tar.gz: 1277395f5e2dd9d78a95fcf3776df0c8b0911cec21d14ba9c4105dfef10494eb67e5f2acd4c5f7a4688c65147025f17303f52c2c88afdee01c600aa0e92b2108
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Trevor Strieber
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # datetime_picker_rails
2
+
3
+ Forked from [TrevorS/bootstrap-datetimepicker-rails][original] on Sept 3, 2015.
4
+
5
+ My goal is to make it not require [bootstrap-sass].
6
+
7
+ [original]: https://github.com/TrevorS/bootstrap3-datetimepicker-rails
8
+ [bootstrap-sass]: https://github.com/twbs/bootstrap-sass
9
+
10
+ - - -
11
+
12
+ This gem packages the [bootstrap-datetimepicker]
13
+ for the Rails 3.1+ asset pipeline.
14
+
15
+ [bootstrap-datetimepicker]: https://github.com/Eonasdan/bootstrap-datetimepicker
16
+
17
+ ## Installation
18
+
19
+ Add these lines to your application's Gemfile:
20
+
21
+ ```ruby
22
+ gem "datetime_picker_rails", github: "graysonwright/datetime_picker_rails"
23
+ ```
24
+
25
+ And then execute:
26
+
27
+ ```bash
28
+ $ bundle
29
+ ```
30
+
31
+ If your server is running,
32
+ you will need to **restart Rails** before using the gem.
33
+
34
+ Add the following to your JavaScript manifest file (`application.js`):
35
+ ```js
36
+ //= require moment
37
+ //= require datetime_picker
38
+ ```
39
+
40
+ If you want to include a localization, also add:
41
+ ```js
42
+ //= require moment/<locale>
43
+ ```
44
+
45
+ Add the following to your style sheet file:
46
+
47
+ If you are using SCSS, modify your `application.css.scss`
48
+ ```scss
49
+ @import "datetime_picker";
50
+ ```
51
+
52
+ If you're using plain CSS, modify your `application.css`
53
+ ```css
54
+ *= require datetime_picker
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ Check out the documentation at:
60
+ http://eonasdan.github.io/bootstrap-datetimepicker/
61
+
62
+ ## Problems
63
+
64
+ Clone https://github.com/TrevorS/bs3dp-test and try to reproduce your issue.
65
+
66
+ ## Contributing
67
+
68
+ 1. Fork it
69
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
70
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
71
+ 4. Push to the branch (`git push origin my-new-feature`)
72
+ 5. Create new Pull Request
@@ -0,0 +1,8 @@
1
+ require 'datetime_picker_rails/version'
2
+
3
+ module DateTimePicker
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module DateTimePicker
2
+ module Rails
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,2485 @@
1
+ /*! version : 4.15.35
2
+ =========================================================
3
+ bootstrap-datetimejs
4
+ https://github.com/Eonasdan/bootstrap-datetimepicker
5
+ Copyright (c) 2015 Jonathan Peterson
6
+ =========================================================
7
+ */
8
+ /*
9
+ The MIT License (MIT)
10
+
11
+ Copyright (c) 2015 Jonathan Peterson
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in
21
+ all copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29
+ THE SOFTWARE.
30
+ */
31
+ /*global define:false */
32
+ /*global exports:false */
33
+ /*global require:false */
34
+ /*global jQuery:false */
35
+ /*global moment:false */
36
+ (function (factory) {
37
+ 'use strict';
38
+ if (typeof define === 'function' && define.amd) {
39
+ // AMD is used - Register as an anonymous module.
40
+ define(['jquery', 'moment'], factory);
41
+ } else if (typeof exports === 'object') {
42
+ factory(require('jquery'), require('moment'));
43
+ } else {
44
+ // Neither AMD nor CommonJS used. Use global variables.
45
+ if (typeof jQuery === 'undefined') {
46
+ throw 'bootstrap-datetimepicker requires jQuery to be loaded first';
47
+ }
48
+ if (typeof moment === 'undefined') {
49
+ throw 'bootstrap-datetimepicker requires Moment.js to be loaded first';
50
+ }
51
+ factory(jQuery, moment);
52
+ }
53
+ }(function ($, moment) {
54
+ 'use strict';
55
+ if (!moment) {
56
+ throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first');
57
+ }
58
+
59
+ var dateTimePicker = function (element, options) {
60
+ var picker = {},
61
+ date = moment().startOf('d'),
62
+ viewDate = date.clone(),
63
+ unset = true,
64
+ input,
65
+ component = false,
66
+ widget = false,
67
+ use24Hours,
68
+ minViewModeNumber = 0,
69
+ actualFormat,
70
+ parseFormats,
71
+ currentViewMode,
72
+ datePickerModes = [
73
+ {
74
+ clsName: 'days',
75
+ navFnc: 'M',
76
+ navStep: 1
77
+ },
78
+ {
79
+ clsName: 'months',
80
+ navFnc: 'y',
81
+ navStep: 1
82
+ },
83
+ {
84
+ clsName: 'years',
85
+ navFnc: 'y',
86
+ navStep: 10
87
+ },
88
+ {
89
+ clsName: 'decades',
90
+ navFnc: 'y',
91
+ navStep: 100
92
+ }
93
+ ],
94
+ viewModes = ['days', 'months', 'years', 'decades'],
95
+ verticalModes = ['top', 'bottom', 'auto'],
96
+ horizontalModes = ['left', 'right', 'auto'],
97
+ toolbarPlacements = ['default', 'top', 'bottom'],
98
+ keyMap = {
99
+ 'up': 38,
100
+ 38: 'up',
101
+ 'down': 40,
102
+ 40: 'down',
103
+ 'left': 37,
104
+ 37: 'left',
105
+ 'right': 39,
106
+ 39: 'right',
107
+ 'tab': 9,
108
+ 9: 'tab',
109
+ 'escape': 27,
110
+ 27: 'escape',
111
+ 'enter': 13,
112
+ 13: 'enter',
113
+ 'pageUp': 33,
114
+ 33: 'pageUp',
115
+ 'pageDown': 34,
116
+ 34: 'pageDown',
117
+ 'shift': 16,
118
+ 16: 'shift',
119
+ 'control': 17,
120
+ 17: 'control',
121
+ 'space': 32,
122
+ 32: 'space',
123
+ 't': 84,
124
+ 84: 't',
125
+ 'delete': 46,
126
+ 46: 'delete'
127
+ },
128
+ keyState = {},
129
+
130
+ /********************************************************************************
131
+ *
132
+ * Private functions
133
+ *
134
+ ********************************************************************************/
135
+ isEnabled = function (granularity) {
136
+ if (typeof granularity !== 'string' || granularity.length > 1) {
137
+ throw new TypeError('isEnabled expects a single character string parameter');
138
+ }
139
+ switch (granularity) {
140
+ case 'y':
141
+ return actualFormat.indexOf('Y') !== -1;
142
+ case 'M':
143
+ return actualFormat.indexOf('M') !== -1;
144
+ case 'd':
145
+ return actualFormat.toLowerCase().indexOf('d') !== -1;
146
+ case 'h':
147
+ case 'H':
148
+ return actualFormat.toLowerCase().indexOf('h') !== -1;
149
+ case 'm':
150
+ return actualFormat.indexOf('m') !== -1;
151
+ case 's':
152
+ return actualFormat.indexOf('s') !== -1;
153
+ default:
154
+ return false;
155
+ }
156
+ },
157
+ hasTime = function () {
158
+ return (isEnabled('h') || isEnabled('m') || isEnabled('s'));
159
+ },
160
+
161
+ hasDate = function () {
162
+ return (isEnabled('y') || isEnabled('M') || isEnabled('d'));
163
+ },
164
+
165
+ getDatePickerTemplate = function () {
166
+ var headTemplate = $('<thead>')
167
+ .append($('<tr>')
168
+ .append($('<th>').addClass('prev').attr('data-action', 'previous')
169
+ .append($('<span>').addClass(options.icons.previous))
170
+ )
171
+ .append($('<th>').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5')))
172
+ .append($('<th>').addClass('next').attr('data-action', 'next')
173
+ .append($('<span>').addClass(options.icons.next))
174
+ )
175
+ ),
176
+ contTemplate = $('<tbody>')
177
+ .append($('<tr>')
178
+ .append($('<td>').attr('colspan', (options.calendarWeeks ? '8' : '7')))
179
+ );
180
+
181
+ return [
182
+ $('<div>').addClass('datepicker-days')
183
+ .append($('<table>').addClass('table-condensed')
184
+ .append(headTemplate)
185
+ .append($('<tbody>'))
186
+ ),
187
+ $('<div>').addClass('datepicker-months')
188
+ .append($('<table>').addClass('table-condensed')
189
+ .append(headTemplate.clone())
190
+ .append(contTemplate.clone())
191
+ ),
192
+ $('<div>').addClass('datepicker-years')
193
+ .append($('<table>').addClass('table-condensed')
194
+ .append(headTemplate.clone())
195
+ .append(contTemplate.clone())
196
+ ),
197
+ $('<div>').addClass('datepicker-decades')
198
+ .append($('<table>').addClass('table-condensed')
199
+ .append(headTemplate.clone())
200
+ .append(contTemplate.clone())
201
+ )
202
+ ];
203
+ },
204
+
205
+ getTimePickerMainTemplate = function () {
206
+ var topRow = $('<tr>'),
207
+ middleRow = $('<tr>'),
208
+ bottomRow = $('<tr>');
209
+
210
+ if (isEnabled('h')) {
211
+ topRow.append($('<td>')
212
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Hour'}).addClass('btn').attr('data-action', 'incrementHours')
213
+ .append($('<span>').addClass(options.icons.up))));
214
+ middleRow.append($('<td>')
215
+ .append($('<span>').addClass('timepicker-hour').attr({'data-time-component':'hours', 'title':'Pick Hour'}).attr('data-action', 'showHours')));
216
+ bottomRow.append($('<td>')
217
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Hour'}).addClass('btn').attr('data-action', 'decrementHours')
218
+ .append($('<span>').addClass(options.icons.down))));
219
+ }
220
+ if (isEnabled('m')) {
221
+ if (isEnabled('h')) {
222
+ topRow.append($('<td>').addClass('separator'));
223
+ middleRow.append($('<td>').addClass('separator').html(':'));
224
+ bottomRow.append($('<td>').addClass('separator'));
225
+ }
226
+ topRow.append($('<td>')
227
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Minute'}).addClass('btn').attr('data-action', 'incrementMinutes')
228
+ .append($('<span>').addClass(options.icons.up))));
229
+ middleRow.append($('<td>')
230
+ .append($('<span>').addClass('timepicker-minute').attr({'data-time-component': 'minutes', 'title':'Pick Minute'}).attr('data-action', 'showMinutes')));
231
+ bottomRow.append($('<td>')
232
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Minute'}).addClass('btn').attr('data-action', 'decrementMinutes')
233
+ .append($('<span>').addClass(options.icons.down))));
234
+ }
235
+ if (isEnabled('s')) {
236
+ if (isEnabled('m')) {
237
+ topRow.append($('<td>').addClass('separator'));
238
+ middleRow.append($('<td>').addClass('separator').html(':'));
239
+ bottomRow.append($('<td>').addClass('separator'));
240
+ }
241
+ topRow.append($('<td>')
242
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Second'}).addClass('btn').attr('data-action', 'incrementSeconds')
243
+ .append($('<span>').addClass(options.icons.up))));
244
+ middleRow.append($('<td>')
245
+ .append($('<span>').addClass('timepicker-second').attr({'data-time-component': 'seconds', 'title':'Pick Second'}).attr('data-action', 'showSeconds')));
246
+ bottomRow.append($('<td>')
247
+ .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Second'}).addClass('btn').attr('data-action', 'decrementSeconds')
248
+ .append($('<span>').addClass(options.icons.down))));
249
+ }
250
+
251
+ if (!use24Hours) {
252
+ topRow.append($('<td>').addClass('separator'));
253
+ middleRow.append($('<td>')
254
+ .append($('<button>').addClass('btn btn-primary').attr({'data-action': 'togglePeriod', tabindex: '-1', 'title':'Toggle Period'})));
255
+ bottomRow.append($('<td>').addClass('separator'));
256
+ }
257
+
258
+ return $('<div>').addClass('timepicker-picker')
259
+ .append($('<table>').addClass('table-condensed')
260
+ .append([topRow, middleRow, bottomRow]));
261
+ },
262
+
263
+ getTimePickerTemplate = function () {
264
+ var hoursView = $('<div>').addClass('timepicker-hours')
265
+ .append($('<table>').addClass('table-condensed')),
266
+ minutesView = $('<div>').addClass('timepicker-minutes')
267
+ .append($('<table>').addClass('table-condensed')),
268
+ secondsView = $('<div>').addClass('timepicker-seconds')
269
+ .append($('<table>').addClass('table-condensed')),
270
+ ret = [getTimePickerMainTemplate()];
271
+
272
+ if (isEnabled('h')) {
273
+ ret.push(hoursView);
274
+ }
275
+ if (isEnabled('m')) {
276
+ ret.push(minutesView);
277
+ }
278
+ if (isEnabled('s')) {
279
+ ret.push(secondsView);
280
+ }
281
+
282
+ return ret;
283
+ },
284
+
285
+ getToolbar = function () {
286
+ var row = [];
287
+ if (options.showTodayButton) {
288
+ row.push($('<td>').append($('<a>').attr({'data-action':'today', 'title': options.tooltips.today}).append($('<span>').addClass(options.icons.today))));
289
+ }
290
+ if (!options.sideBySide && hasDate() && hasTime()) {
291
+ row.push($('<td>').append($('<a>').attr({'data-action':'togglePicker', 'title':'Select Time'}).append($('<span>').addClass(options.icons.time))));
292
+ }
293
+ if (options.showClear) {
294
+ row.push($('<td>').append($('<a>').attr({'data-action':'clear', 'title': options.tooltips.clear}).append($('<span>').addClass(options.icons.clear))));
295
+ }
296
+ if (options.showClose) {
297
+ row.push($('<td>').append($('<a>').attr({'data-action':'close', 'title': options.tooltips.close}).append($('<span>').addClass(options.icons.close))));
298
+ }
299
+ return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
300
+ },
301
+
302
+ getTemplate = function () {
303
+ var template = $('<div>').addClass('bootstrap-datetimepicker-widget dropdown-menu'),
304
+ dateView = $('<div>').addClass('datepicker').append(getDatePickerTemplate()),
305
+ timeView = $('<div>').addClass('timepicker').append(getTimePickerTemplate()),
306
+ content = $('<ul>').addClass('list-unstyled'),
307
+ toolbar = $('<li>').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar());
308
+
309
+ if (options.inline) {
310
+ template.removeClass('dropdown-menu');
311
+ }
312
+
313
+ if (use24Hours) {
314
+ template.addClass('usetwentyfour');
315
+ }
316
+ if (isEnabled('s') && !use24Hours) {
317
+ template.addClass('wider');
318
+ }
319
+
320
+ if (options.sideBySide && hasDate() && hasTime()) {
321
+ template.addClass('timepicker-sbs');
322
+ if (options.toolbarPlacement === 'top') {
323
+ template.append(toolbar);
324
+ }
325
+ template.append(
326
+ $('<div>').addClass('row')
327
+ .append(dateView.addClass('col-md-6'))
328
+ .append(timeView.addClass('col-md-6'))
329
+ );
330
+ if (options.toolbarPlacement === 'bottom') {
331
+ template.append(toolbar);
332
+ }
333
+ return template;
334
+ }
335
+
336
+ if (options.toolbarPlacement === 'top') {
337
+ content.append(toolbar);
338
+ }
339
+ if (hasDate()) {
340
+ content.append($('<li>').addClass((options.collapse && hasTime() ? 'collapse in' : '')).append(dateView));
341
+ }
342
+ if (options.toolbarPlacement === 'default') {
343
+ content.append(toolbar);
344
+ }
345
+ if (hasTime()) {
346
+ content.append($('<li>').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView));
347
+ }
348
+ if (options.toolbarPlacement === 'bottom') {
349
+ content.append(toolbar);
350
+ }
351
+ return template.append(content);
352
+ },
353
+
354
+ dataToOptions = function () {
355
+ var eData,
356
+ dataOptions = {};
357
+
358
+ if (element.is('input') || options.inline) {
359
+ eData = element.data();
360
+ } else {
361
+ eData = element.find('input').data();
362
+ }
363
+
364
+ if (eData.dateOptions && eData.dateOptions instanceof Object) {
365
+ dataOptions = $.extend(true, dataOptions, eData.dateOptions);
366
+ }
367
+
368
+ $.each(options, function (key) {
369
+ var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1);
370
+ if (eData[attributeName] !== undefined) {
371
+ dataOptions[key] = eData[attributeName];
372
+ }
373
+ });
374
+ return dataOptions;
375
+ },
376
+
377
+ place = function () {
378
+ var position = (component || element).position(),
379
+ offset = (component || element).offset(),
380
+ vertical = options.widgetPositioning.vertical,
381
+ horizontal = options.widgetPositioning.horizontal,
382
+ parent;
383
+
384
+ if (options.widgetParent) {
385
+ parent = options.widgetParent.append(widget);
386
+ } else if (element.is('input')) {
387
+ parent = element.after(widget).parent();
388
+ } else if (options.inline) {
389
+ parent = element.append(widget);
390
+ return;
391
+ } else {
392
+ parent = element;
393
+ element.children().first().after(widget);
394
+ }
395
+
396
+ // Top and bottom logic
397
+ if (vertical === 'auto') {
398
+ if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() &&
399
+ widget.height() + element.outerHeight() < offset.top) {
400
+ vertical = 'top';
401
+ } else {
402
+ vertical = 'bottom';
403
+ }
404
+ }
405
+
406
+ // Left and right logic
407
+ if (horizontal === 'auto') {
408
+ if (parent.width() < offset.left + widget.outerWidth() / 2 &&
409
+ offset.left + widget.outerWidth() > $(window).width()) {
410
+ horizontal = 'right';
411
+ } else {
412
+ horizontal = 'left';
413
+ }
414
+ }
415
+
416
+ if (vertical === 'top') {
417
+ widget.addClass('top').removeClass('bottom');
418
+ } else {
419
+ widget.addClass('bottom').removeClass('top');
420
+ }
421
+
422
+ if (horizontal === 'right') {
423
+ widget.addClass('pull-right');
424
+ } else {
425
+ widget.removeClass('pull-right');
426
+ }
427
+
428
+ // find the first parent element that has a relative css positioning
429
+ if (parent.css('position') !== 'relative') {
430
+ parent = parent.parents().filter(function () {
431
+ return $(this).css('position') === 'relative';
432
+ }).first();
433
+ }
434
+
435
+ if (parent.length === 0) {
436
+ throw new Error('datetimepicker component should be placed within a relative positioned container');
437
+ }
438
+
439
+ widget.css({
440
+ top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(),
441
+ bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto',
442
+ left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto',
443
+ right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left)
444
+ });
445
+ },
446
+
447
+ notifyEvent = function (e) {
448
+ if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) {
449
+ return;
450
+ }
451
+ element.trigger(e);
452
+ },
453
+
454
+ viewUpdate = function (e) {
455
+ if (e === 'y') {
456
+ e = 'YYYY';
457
+ }
458
+ notifyEvent({
459
+ type: 'dp.update',
460
+ change: e,
461
+ viewDate: viewDate.clone()
462
+ });
463
+ },
464
+
465
+ showMode = function (dir) {
466
+ if (!widget) {
467
+ return;
468
+ }
469
+ if (dir) {
470
+ currentViewMode = Math.max(minViewModeNumber, Math.min(3, currentViewMode + dir));
471
+ }
472
+ widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show();
473
+ },
474
+
475
+ fillDow = function () {
476
+ var row = $('<tr>'),
477
+ currentDate = viewDate.clone().startOf('w').startOf('d');
478
+
479
+ if (options.calendarWeeks === true) {
480
+ row.append($('<th>').addClass('cw').text('#'));
481
+ }
482
+
483
+ while (currentDate.isBefore(viewDate.clone().endOf('w'))) {
484
+ row.append($('<th>').addClass('dow').text(currentDate.format('dd')));
485
+ currentDate.add(1, 'd');
486
+ }
487
+ widget.find('.datepicker-days thead').append(row);
488
+ },
489
+
490
+ isInDisabledDates = function (testDate) {
491
+ return options.disabledDates[testDate.format('YYYY-MM-DD')] === true;
492
+ },
493
+
494
+ isInEnabledDates = function (testDate) {
495
+ return options.enabledDates[testDate.format('YYYY-MM-DD')] === true;
496
+ },
497
+
498
+ isInDisabledHours = function (testDate) {
499
+ return options.disabledHours[testDate.format('H')] === true;
500
+ },
501
+
502
+ isInEnabledHours = function (testDate) {
503
+ return options.enabledHours[testDate.format('H')] === true;
504
+ },
505
+
506
+ isValid = function (targetMoment, granularity) {
507
+ if (!targetMoment.isValid()) {
508
+ return false;
509
+ }
510
+ if (options.disabledDates && granularity === 'd' && isInDisabledDates(targetMoment)) {
511
+ return false;
512
+ }
513
+ if (options.enabledDates && granularity === 'd' && !isInEnabledDates(targetMoment)) {
514
+ return false;
515
+ }
516
+ if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) {
517
+ return false;
518
+ }
519
+ if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) {
520
+ return false;
521
+ }
522
+ if (options.daysOfWeekDisabled && granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {
523
+ return false;
524
+ }
525
+ if (options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && isInDisabledHours(targetMoment)) {
526
+ return false;
527
+ }
528
+ if (options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !isInEnabledHours(targetMoment)) {
529
+ return false;
530
+ }
531
+ if (options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) {
532
+ var found = false;
533
+ $.each(options.disabledTimeIntervals, function () {
534
+ if (targetMoment.isBetween(this[0], this[1])) {
535
+ found = true;
536
+ return false;
537
+ }
538
+ });
539
+ if (found) {
540
+ return false;
541
+ }
542
+ }
543
+ return true;
544
+ },
545
+
546
+ fillMonths = function () {
547
+ var spans = [],
548
+ monthsShort = viewDate.clone().startOf('y').startOf('d');
549
+ while (monthsShort.isSame(viewDate, 'y')) {
550
+ spans.push($('<span>').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM')));
551
+ monthsShort.add(1, 'M');
552
+ }
553
+ widget.find('.datepicker-months td').empty().append(spans);
554
+ },
555
+
556
+ updateMonths = function () {
557
+ var monthsView = widget.find('.datepicker-months'),
558
+ monthsViewHeader = monthsView.find('th'),
559
+ months = monthsView.find('tbody').find('span');
560
+
561
+ monthsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevYear);
562
+ monthsViewHeader.eq(1).attr('title', options.tooltips.selectYear);
563
+ monthsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextYear);
564
+
565
+ monthsView.find('.disabled').removeClass('disabled');
566
+
567
+ if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) {
568
+ monthsViewHeader.eq(0).addClass('disabled');
569
+ }
570
+
571
+ monthsViewHeader.eq(1).text(viewDate.year());
572
+
573
+ if (!isValid(viewDate.clone().add(1, 'y'), 'y')) {
574
+ monthsViewHeader.eq(2).addClass('disabled');
575
+ }
576
+
577
+ months.removeClass('active');
578
+ if (date.isSame(viewDate, 'y') && !unset) {
579
+ months.eq(date.month()).addClass('active');
580
+ }
581
+
582
+ months.each(function (index) {
583
+ if (!isValid(viewDate.clone().month(index), 'M')) {
584
+ $(this).addClass('disabled');
585
+ }
586
+ });
587
+ },
588
+
589
+ updateYears = function () {
590
+ var yearsView = widget.find('.datepicker-years'),
591
+ yearsViewHeader = yearsView.find('th'),
592
+ startYear = viewDate.clone().subtract(5, 'y'),
593
+ endYear = viewDate.clone().add(6, 'y'),
594
+ html = '';
595
+
596
+ yearsViewHeader.eq(0).find('span').attr('title', options.tooltips.nextDecade);
597
+ yearsViewHeader.eq(1).attr('title', options.tooltips.selectDecade);
598
+ yearsViewHeader.eq(2).find('span').attr('title', options.tooltips.prevDecade);
599
+
600
+ yearsView.find('.disabled').removeClass('disabled');
601
+
602
+ if (options.minDate && options.minDate.isAfter(startYear, 'y')) {
603
+ yearsViewHeader.eq(0).addClass('disabled');
604
+ }
605
+
606
+ yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year());
607
+
608
+ if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) {
609
+ yearsViewHeader.eq(2).addClass('disabled');
610
+ }
611
+
612
+ while (!startYear.isAfter(endYear, 'y')) {
613
+ html += '<span data-action="selectYear" class="year' + (startYear.isSame(date, 'y') && !unset ? ' active' : '') + (!isValid(startYear, 'y') ? ' disabled' : '') + '">' + startYear.year() + '</span>';
614
+ startYear.add(1, 'y');
615
+ }
616
+
617
+ yearsView.find('td').html(html);
618
+ },
619
+
620
+ updateDecades = function () {
621
+ var decadesView = widget.find('.datepicker-decades'),
622
+ decadesViewHeader = decadesView.find('th'),
623
+ startDecade = viewDate.isBefore(moment({y: 1999})) ? moment({y: 1899}) : moment({y: 1999}),
624
+ endDecade = startDecade.clone().add(100, 'y'),
625
+ html = '';
626
+
627
+ decadesViewHeader.eq(0).find('span').attr('title', options.tooltips.prevCentury);
628
+ decadesViewHeader.eq(2).find('span').attr('title', options.tooltips.nextCentury);
629
+
630
+ decadesView.find('.disabled').removeClass('disabled');
631
+
632
+ if (startDecade.isSame(moment({y: 1900})) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) {
633
+ decadesViewHeader.eq(0).addClass('disabled');
634
+ }
635
+
636
+ decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year());
637
+
638
+ if (startDecade.isSame(moment({y: 2000})) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) {
639
+ decadesViewHeader.eq(2).addClass('disabled');
640
+ }
641
+
642
+ while (!startDecade.isAfter(endDecade, 'y')) {
643
+ html += '<span data-action="selectDecade" class="decade' + (startDecade.isSame(date, 'y') ? ' active' : '') +
644
+ (!isValid(startDecade, 'y') ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>';
645
+ startDecade.add(12, 'y');
646
+ }
647
+ html += '<span></span><span></span><span></span>'; //push the dangling block over, at least this way it's even
648
+
649
+ decadesView.find('td').html(html);
650
+ },
651
+
652
+ fillDate = function () {
653
+ var daysView = widget.find('.datepicker-days'),
654
+ daysViewHeader = daysView.find('th'),
655
+ currentDate,
656
+ html = [],
657
+ row,
658
+ clsName,
659
+ i;
660
+
661
+ if (!hasDate()) {
662
+ return;
663
+ }
664
+
665
+ daysViewHeader.eq(0).find('span').attr('title', options.tooltips.prevMonth);
666
+ daysViewHeader.eq(1).attr('title', options.tooltips.selectMonth);
667
+ daysViewHeader.eq(2).find('span').attr('title', options.tooltips.nextMonth);
668
+
669
+ daysView.find('.disabled').removeClass('disabled');
670
+ daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat));
671
+
672
+ if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) {
673
+ daysViewHeader.eq(0).addClass('disabled');
674
+ }
675
+ if (!isValid(viewDate.clone().add(1, 'M'), 'M')) {
676
+ daysViewHeader.eq(2).addClass('disabled');
677
+ }
678
+
679
+ currentDate = viewDate.clone().startOf('M').startOf('w').startOf('d');
680
+
681
+ for (i = 0; i < 42; i++) { //always display 42 days (should show 6 weeks)
682
+ if (currentDate.weekday() === 0) {
683
+ row = $('<tr>');
684
+ if (options.calendarWeeks) {
685
+ row.append('<td class="cw">' + currentDate.week() + '</td>');
686
+ }
687
+ html.push(row);
688
+ }
689
+ clsName = '';
690
+ if (currentDate.isBefore(viewDate, 'M')) {
691
+ clsName += ' old';
692
+ }
693
+ if (currentDate.isAfter(viewDate, 'M')) {
694
+ clsName += ' new';
695
+ }
696
+ if (currentDate.isSame(date, 'd') && !unset) {
697
+ clsName += ' active';
698
+ }
699
+ if (!isValid(currentDate, 'd')) {
700
+ clsName += ' disabled';
701
+ }
702
+ if (currentDate.isSame(moment(), 'd')) {
703
+ clsName += ' today';
704
+ }
705
+ if (currentDate.day() === 0 || currentDate.day() === 6) {
706
+ clsName += ' weekend';
707
+ }
708
+ row.append('<td data-action="selectDay" data-day="' + currentDate.format('L') + '" class="day' + clsName + '">' + currentDate.date() + '</td>');
709
+ currentDate.add(1, 'd');
710
+ }
711
+
712
+ daysView.find('tbody').empty().append(html);
713
+
714
+ updateMonths();
715
+
716
+ updateYears();
717
+
718
+ updateDecades();
719
+ },
720
+
721
+ fillHours = function () {
722
+ var table = widget.find('.timepicker-hours table'),
723
+ currentHour = viewDate.clone().startOf('d'),
724
+ html = [],
725
+ row = $('<tr>');
726
+
727
+ if (viewDate.hour() > 11 && !use24Hours) {
728
+ currentHour.hour(12);
729
+ }
730
+ while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) {
731
+ if (currentHour.hour() % 4 === 0) {
732
+ row = $('<tr>');
733
+ html.push(row);
734
+ }
735
+ row.append('<td data-action="selectHour" class="hour' + (!isValid(currentHour, 'h') ? ' disabled' : '') + '">' + currentHour.format(use24Hours ? 'HH' : 'hh') + '</td>');
736
+ currentHour.add(1, 'h');
737
+ }
738
+ table.empty().append(html);
739
+ },
740
+
741
+ fillMinutes = function () {
742
+ var table = widget.find('.timepicker-minutes table'),
743
+ currentMinute = viewDate.clone().startOf('h'),
744
+ html = [],
745
+ row = $('<tr>'),
746
+ step = options.stepping === 1 ? 5 : options.stepping;
747
+
748
+ while (viewDate.isSame(currentMinute, 'h')) {
749
+ if (currentMinute.minute() % (step * 4) === 0) {
750
+ row = $('<tr>');
751
+ html.push(row);
752
+ }
753
+ row.append('<td data-action="selectMinute" class="minute' + (!isValid(currentMinute, 'm') ? ' disabled' : '') + '">' + currentMinute.format('mm') + '</td>');
754
+ currentMinute.add(step, 'm');
755
+ }
756
+ table.empty().append(html);
757
+ },
758
+
759
+ fillSeconds = function () {
760
+ var table = widget.find('.timepicker-seconds table'),
761
+ currentSecond = viewDate.clone().startOf('m'),
762
+ html = [],
763
+ row = $('<tr>');
764
+
765
+ while (viewDate.isSame(currentSecond, 'm')) {
766
+ if (currentSecond.second() % 20 === 0) {
767
+ row = $('<tr>');
768
+ html.push(row);
769
+ }
770
+ row.append('<td data-action="selectSecond" class="second' + (!isValid(currentSecond, 's') ? ' disabled' : '') + '">' + currentSecond.format('ss') + '</td>');
771
+ currentSecond.add(5, 's');
772
+ }
773
+
774
+ table.empty().append(html);
775
+ },
776
+
777
+ fillTime = function () {
778
+ var toggle, newDate, timeComponents = widget.find('.timepicker span[data-time-component]');
779
+
780
+ if (!use24Hours) {
781
+ toggle = widget.find('.timepicker [data-action=togglePeriod]');
782
+ newDate = date.clone().add((date.hours() >= 12) ? -12 : 12, 'h');
783
+
784
+ toggle.text(date.format('A'));
785
+
786
+ if (isValid(newDate, 'h')) {
787
+ toggle.removeClass('disabled');
788
+ } else {
789
+ toggle.addClass('disabled');
790
+ }
791
+ }
792
+ timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh'));
793
+ timeComponents.filter('[data-time-component=minutes]').text(date.format('mm'));
794
+ timeComponents.filter('[data-time-component=seconds]').text(date.format('ss'));
795
+
796
+ fillHours();
797
+ fillMinutes();
798
+ fillSeconds();
799
+ },
800
+
801
+ update = function () {
802
+ if (!widget) {
803
+ return;
804
+ }
805
+ fillDate();
806
+ fillTime();
807
+ },
808
+
809
+ setValue = function (targetMoment) {
810
+ var oldDate = unset ? null : date;
811
+
812
+ // case of calling setValue(null or false)
813
+ if (!targetMoment) {
814
+ unset = true;
815
+ input.val('');
816
+ element.data('date', '');
817
+ notifyEvent({
818
+ type: 'dp.change',
819
+ date: false,
820
+ oldDate: oldDate
821
+ });
822
+ update();
823
+ return;
824
+ }
825
+
826
+ targetMoment = targetMoment.clone().locale(options.locale);
827
+
828
+ if (options.stepping !== 1) {
829
+ targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping) % 60).seconds(0);
830
+ }
831
+
832
+ if (isValid(targetMoment)) {
833
+ date = targetMoment;
834
+ viewDate = date.clone();
835
+ input.val(date.format(actualFormat));
836
+ element.data('date', date.format(actualFormat));
837
+ unset = false;
838
+ update();
839
+ notifyEvent({
840
+ type: 'dp.change',
841
+ date: date.clone(),
842
+ oldDate: oldDate
843
+ });
844
+ } else {
845
+ if (!options.keepInvalid) {
846
+ input.val(unset ? '' : date.format(actualFormat));
847
+ }
848
+ notifyEvent({
849
+ type: 'dp.error',
850
+ date: targetMoment
851
+ });
852
+ }
853
+ },
854
+
855
+ hide = function () {
856
+ ///<summary>Hides the widget. Possibly will emit dp.hide</summary>
857
+ var transitioning = false;
858
+ if (!widget) {
859
+ return picker;
860
+ }
861
+ // Ignore event if in the middle of a picker transition
862
+ widget.find('.collapse').each(function () {
863
+ var collapseData = $(this).data('collapse');
864
+ if (collapseData && collapseData.transitioning) {
865
+ transitioning = true;
866
+ return false;
867
+ }
868
+ return true;
869
+ });
870
+ if (transitioning) {
871
+ return picker;
872
+ }
873
+ if (component && component.hasClass('btn')) {
874
+ component.toggleClass('active');
875
+ }
876
+ widget.hide();
877
+
878
+ $(window).off('resize', place);
879
+ widget.off('click', '[data-action]');
880
+ widget.off('mousedown', false);
881
+
882
+ widget.remove();
883
+ widget = false;
884
+
885
+ notifyEvent({
886
+ type: 'dp.hide',
887
+ date: date.clone()
888
+ });
889
+
890
+ input.blur();
891
+
892
+ return picker;
893
+ },
894
+
895
+ clear = function () {
896
+ setValue(null);
897
+ },
898
+
899
+ /********************************************************************************
900
+ *
901
+ * Widget UI interaction functions
902
+ *
903
+ ********************************************************************************/
904
+ actions = {
905
+ next: function () {
906
+ var navFnc = datePickerModes[currentViewMode].navFnc;
907
+ viewDate.add(datePickerModes[currentViewMode].navStep, navFnc);
908
+ fillDate();
909
+ viewUpdate(navFnc);
910
+ },
911
+
912
+ previous: function () {
913
+ var navFnc = datePickerModes[currentViewMode].navFnc;
914
+ viewDate.subtract(datePickerModes[currentViewMode].navStep, navFnc);
915
+ fillDate();
916
+ viewUpdate(navFnc);
917
+ },
918
+
919
+ pickerSwitch: function () {
920
+ showMode(1);
921
+ },
922
+
923
+ selectMonth: function (e) {
924
+ var month = $(e.target).closest('tbody').find('span').index($(e.target));
925
+ viewDate.month(month);
926
+ if (currentViewMode === minViewModeNumber) {
927
+ setValue(date.clone().year(viewDate.year()).month(viewDate.month()));
928
+ if (!options.inline) {
929
+ hide();
930
+ }
931
+ } else {
932
+ showMode(-1);
933
+ fillDate();
934
+ }
935
+ viewUpdate('M');
936
+ },
937
+
938
+ selectYear: function (e) {
939
+ var year = parseInt($(e.target).text(), 10) || 0;
940
+ viewDate.year(year);
941
+ if (currentViewMode === minViewModeNumber) {
942
+ setValue(date.clone().year(viewDate.year()));
943
+ if (!options.inline) {
944
+ hide();
945
+ }
946
+ } else {
947
+ showMode(-1);
948
+ fillDate();
949
+ }
950
+ viewUpdate('YYYY');
951
+ },
952
+
953
+ selectDecade: function (e) {
954
+ var year = parseInt($(e.target).data('selection'), 10) || 0;
955
+ viewDate.year(year);
956
+ if (currentViewMode === minViewModeNumber) {
957
+ setValue(date.clone().year(viewDate.year()));
958
+ if (!options.inline) {
959
+ hide();
960
+ }
961
+ } else {
962
+ showMode(-1);
963
+ fillDate();
964
+ }
965
+ viewUpdate('YYYY');
966
+ },
967
+
968
+ selectDay: function (e) {
969
+ var day = viewDate.clone();
970
+ if ($(e.target).is('.old')) {
971
+ day.subtract(1, 'M');
972
+ }
973
+ if ($(e.target).is('.new')) {
974
+ day.add(1, 'M');
975
+ }
976
+ setValue(day.date(parseInt($(e.target).text(), 10)));
977
+ if (!hasTime() && !options.keepOpen && !options.inline) {
978
+ hide();
979
+ }
980
+ },
981
+
982
+ incrementHours: function () {
983
+ var newDate = date.clone().add(1, 'h');
984
+ if (isValid(newDate, 'h')) {
985
+ setValue(newDate);
986
+ }
987
+ },
988
+
989
+ incrementMinutes: function () {
990
+ var newDate = date.clone().add(options.stepping, 'm');
991
+ if (isValid(newDate, 'm')) {
992
+ setValue(newDate);
993
+ }
994
+ },
995
+
996
+ incrementSeconds: function () {
997
+ var newDate = date.clone().add(1, 's');
998
+ if (isValid(newDate, 's')) {
999
+ setValue(newDate);
1000
+ }
1001
+ },
1002
+
1003
+ decrementHours: function () {
1004
+ var newDate = date.clone().subtract(1, 'h');
1005
+ if (isValid(newDate, 'h')) {
1006
+ setValue(newDate);
1007
+ }
1008
+ },
1009
+
1010
+ decrementMinutes: function () {
1011
+ var newDate = date.clone().subtract(options.stepping, 'm');
1012
+ if (isValid(newDate, 'm')) {
1013
+ setValue(newDate);
1014
+ }
1015
+ },
1016
+
1017
+ decrementSeconds: function () {
1018
+ var newDate = date.clone().subtract(1, 's');
1019
+ if (isValid(newDate, 's')) {
1020
+ setValue(newDate);
1021
+ }
1022
+ },
1023
+
1024
+ togglePeriod: function () {
1025
+ setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h'));
1026
+ },
1027
+
1028
+ togglePicker: function (e) {
1029
+ var $this = $(e.target),
1030
+ $parent = $this.closest('ul'),
1031
+ expanded = $parent.find('.in'),
1032
+ closed = $parent.find('.collapse:not(.in)'),
1033
+ collapseData;
1034
+
1035
+ if (expanded && expanded.length) {
1036
+ collapseData = expanded.data('collapse');
1037
+ if (collapseData && collapseData.transitioning) {
1038
+ return;
1039
+ }
1040
+ if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it
1041
+ expanded.collapse('hide');
1042
+ closed.collapse('show');
1043
+ } else { // otherwise just toggle in class on the two views
1044
+ expanded.removeClass('in');
1045
+ closed.addClass('in');
1046
+ }
1047
+ if ($this.is('span')) {
1048
+ $this.toggleClass(options.icons.time + ' ' + options.icons.date);
1049
+ } else {
1050
+ $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
1051
+ }
1052
+
1053
+ // NOTE: uncomment if toggled state will be restored in show()
1054
+ //if (component) {
1055
+ // component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
1056
+ //}
1057
+ }
1058
+ },
1059
+
1060
+ showPicker: function () {
1061
+ widget.find('.timepicker > div:not(.timepicker-picker)').hide();
1062
+ widget.find('.timepicker .timepicker-picker').show();
1063
+ },
1064
+
1065
+ showHours: function () {
1066
+ widget.find('.timepicker .timepicker-picker').hide();
1067
+ widget.find('.timepicker .timepicker-hours').show();
1068
+ },
1069
+
1070
+ showMinutes: function () {
1071
+ widget.find('.timepicker .timepicker-picker').hide();
1072
+ widget.find('.timepicker .timepicker-minutes').show();
1073
+ },
1074
+
1075
+ showSeconds: function () {
1076
+ widget.find('.timepicker .timepicker-picker').hide();
1077
+ widget.find('.timepicker .timepicker-seconds').show();
1078
+ },
1079
+
1080
+ selectHour: function (e) {
1081
+ var hour = parseInt($(e.target).text(), 10);
1082
+
1083
+ if (!use24Hours) {
1084
+ if (date.hours() >= 12) {
1085
+ if (hour !== 12) {
1086
+ hour += 12;
1087
+ }
1088
+ } else {
1089
+ if (hour === 12) {
1090
+ hour = 0;
1091
+ }
1092
+ }
1093
+ }
1094
+ setValue(date.clone().hours(hour));
1095
+ actions.showPicker.call(picker);
1096
+ },
1097
+
1098
+ selectMinute: function (e) {
1099
+ setValue(date.clone().minutes(parseInt($(e.target).text(), 10)));
1100
+ actions.showPicker.call(picker);
1101
+ },
1102
+
1103
+ selectSecond: function (e) {
1104
+ setValue(date.clone().seconds(parseInt($(e.target).text(), 10)));
1105
+ actions.showPicker.call(picker);
1106
+ },
1107
+
1108
+ clear: clear,
1109
+
1110
+ today: function () {
1111
+ if (isValid(moment(), 'd')) {
1112
+ setValue(moment());
1113
+ }
1114
+ },
1115
+
1116
+ close: hide
1117
+ },
1118
+
1119
+ doAction = function (e) {
1120
+ if ($(e.currentTarget).is('.disabled')) {
1121
+ return false;
1122
+ }
1123
+ actions[$(e.currentTarget).data('action')].apply(picker, arguments);
1124
+ return false;
1125
+ },
1126
+
1127
+ show = function () {
1128
+ ///<summary>Shows the widget. Possibly will emit dp.show and dp.change</summary>
1129
+ var currentMoment,
1130
+ useCurrentGranularity = {
1131
+ 'year': function (m) {
1132
+ return m.month(0).date(1).hours(0).seconds(0).minutes(0);
1133
+ },
1134
+ 'month': function (m) {
1135
+ return m.date(1).hours(0).seconds(0).minutes(0);
1136
+ },
1137
+ 'day': function (m) {
1138
+ return m.hours(0).seconds(0).minutes(0);
1139
+ },
1140
+ 'hour': function (m) {
1141
+ return m.seconds(0).minutes(0);
1142
+ },
1143
+ 'minute': function (m) {
1144
+ return m.seconds(0);
1145
+ }
1146
+ };
1147
+
1148
+ if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) {
1149
+ return picker;
1150
+ }
1151
+ if (input.val() !== undefined && input.val().trim().length !== 0) {
1152
+ setValue(parseInputDate(input.val().trim()));
1153
+ } else if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) {
1154
+ currentMoment = moment();
1155
+ if (typeof options.useCurrent === 'string') {
1156
+ currentMoment = useCurrentGranularity[options.useCurrent](currentMoment);
1157
+ }
1158
+ setValue(currentMoment);
1159
+ }
1160
+
1161
+ widget = getTemplate();
1162
+
1163
+ fillDow();
1164
+ fillMonths();
1165
+
1166
+ widget.find('.timepicker-hours').hide();
1167
+ widget.find('.timepicker-minutes').hide();
1168
+ widget.find('.timepicker-seconds').hide();
1169
+
1170
+ update();
1171
+ showMode();
1172
+
1173
+ $(window).on('resize', place);
1174
+ widget.on('click', '[data-action]', doAction); // this handles clicks on the widget
1175
+ widget.on('mousedown', false);
1176
+
1177
+ if (component && component.hasClass('btn')) {
1178
+ component.toggleClass('active');
1179
+ }
1180
+ widget.show();
1181
+ place();
1182
+
1183
+ if (options.focusOnShow && !input.is(':focus')) {
1184
+ input.focus();
1185
+ }
1186
+
1187
+ notifyEvent({
1188
+ type: 'dp.show'
1189
+ });
1190
+ return picker;
1191
+ },
1192
+
1193
+ toggle = function () {
1194
+ /// <summary>Shows or hides the widget</summary>
1195
+ return (widget ? hide() : show());
1196
+ },
1197
+
1198
+ parseInputDate = function (inputDate) {
1199
+ if (options.parseInputDate === undefined) {
1200
+ if (moment.isMoment(inputDate) || inputDate instanceof Date) {
1201
+ inputDate = moment(inputDate);
1202
+ } else {
1203
+ inputDate = moment(inputDate, parseFormats, options.useStrict);
1204
+ }
1205
+ } else {
1206
+ inputDate = options.parseInputDate(inputDate);
1207
+ }
1208
+ inputDate.locale(options.locale);
1209
+ return inputDate;
1210
+ },
1211
+
1212
+ keydown = function (e) {
1213
+ var handler = null,
1214
+ index,
1215
+ index2,
1216
+ pressedKeys = [],
1217
+ pressedModifiers = {},
1218
+ currentKey = e.which,
1219
+ keyBindKeys,
1220
+ allModifiersPressed,
1221
+ pressed = 'p';
1222
+
1223
+ keyState[currentKey] = pressed;
1224
+
1225
+ for (index in keyState) {
1226
+ if (keyState.hasOwnProperty(index) && keyState[index] === pressed) {
1227
+ pressedKeys.push(index);
1228
+ if (parseInt(index, 10) !== currentKey) {
1229
+ pressedModifiers[index] = true;
1230
+ }
1231
+ }
1232
+ }
1233
+
1234
+ for (index in options.keyBinds) {
1235
+ if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') {
1236
+ keyBindKeys = index.split(' ');
1237
+ if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) {
1238
+ allModifiersPressed = true;
1239
+ for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) {
1240
+ if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) {
1241
+ allModifiersPressed = false;
1242
+ break;
1243
+ }
1244
+ }
1245
+ if (allModifiersPressed) {
1246
+ handler = options.keyBinds[index];
1247
+ break;
1248
+ }
1249
+ }
1250
+ }
1251
+ }
1252
+
1253
+ if (handler) {
1254
+ handler.call(picker, widget);
1255
+ e.stopPropagation();
1256
+ e.preventDefault();
1257
+ }
1258
+ },
1259
+
1260
+ keyup = function (e) {
1261
+ keyState[e.which] = 'r';
1262
+ e.stopPropagation();
1263
+ e.preventDefault();
1264
+ },
1265
+
1266
+ change = function (e) {
1267
+ var val = $(e.target).val().trim(),
1268
+ parsedDate = val ? parseInputDate(val) : null;
1269
+ setValue(parsedDate);
1270
+ e.stopImmediatePropagation();
1271
+ return false;
1272
+ },
1273
+
1274
+ attachDatePickerElementEvents = function () {
1275
+ input.on({
1276
+ 'change': change,
1277
+ 'blur': options.debug ? '' : hide,
1278
+ 'keydown': keydown,
1279
+ 'keyup': keyup,
1280
+ 'focus': options.allowInputToggle ? show : ''
1281
+ });
1282
+
1283
+ if (element.is('input')) {
1284
+ input.on({
1285
+ 'focus': show
1286
+ });
1287
+ } else if (component) {
1288
+ component.on('click', toggle);
1289
+ component.on('mousedown', false);
1290
+ }
1291
+ },
1292
+
1293
+ detachDatePickerElementEvents = function () {
1294
+ input.off({
1295
+ 'change': change,
1296
+ 'blur': blur,
1297
+ 'keydown': keydown,
1298
+ 'keyup': keyup,
1299
+ 'focus': options.allowInputToggle ? hide : ''
1300
+ });
1301
+
1302
+ if (element.is('input')) {
1303
+ input.off({
1304
+ 'focus': show
1305
+ });
1306
+ } else if (component) {
1307
+ component.off('click', toggle);
1308
+ component.off('mousedown', false);
1309
+ }
1310
+ },
1311
+
1312
+ indexGivenDates = function (givenDatesArray) {
1313
+ // Store given enabledDates and disabledDates as keys.
1314
+ // This way we can check their existence in O(1) time instead of looping through whole array.
1315
+ // (for example: options.enabledDates['2014-02-27'] === true)
1316
+ var givenDatesIndexed = {};
1317
+ $.each(givenDatesArray, function () {
1318
+ var dDate = parseInputDate(this);
1319
+ if (dDate.isValid()) {
1320
+ givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
1321
+ }
1322
+ });
1323
+ return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false;
1324
+ },
1325
+
1326
+ indexGivenHours = function (givenHoursArray) {
1327
+ // Store given enabledHours and disabledHours as keys.
1328
+ // This way we can check their existence in O(1) time instead of looping through whole array.
1329
+ // (for example: options.enabledHours['2014-02-27'] === true)
1330
+ var givenHoursIndexed = {};
1331
+ $.each(givenHoursArray, function () {
1332
+ givenHoursIndexed[this] = true;
1333
+ });
1334
+ return (Object.keys(givenHoursIndexed).length) ? givenHoursIndexed : false;
1335
+ },
1336
+
1337
+ initFormatting = function () {
1338
+ var format = options.format || 'L LT';
1339
+
1340
+ actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) {
1341
+ var newinput = date.localeData().longDateFormat(formatInput) || formatInput;
1342
+ return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740
1343
+ return date.localeData().longDateFormat(formatInput2) || formatInput2;
1344
+ });
1345
+ });
1346
+
1347
+
1348
+ parseFormats = options.extraFormats ? options.extraFormats.slice() : [];
1349
+ if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) {
1350
+ parseFormats.push(actualFormat);
1351
+ }
1352
+
1353
+ use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.replace(/\[.*?\]/g, '').indexOf('h') < 1);
1354
+
1355
+ if (isEnabled('y')) {
1356
+ minViewModeNumber = 2;
1357
+ }
1358
+ if (isEnabled('M')) {
1359
+ minViewModeNumber = 1;
1360
+ }
1361
+ if (isEnabled('d')) {
1362
+ minViewModeNumber = 0;
1363
+ }
1364
+
1365
+ currentViewMode = Math.max(minViewModeNumber, currentViewMode);
1366
+
1367
+ if (!unset) {
1368
+ setValue(date);
1369
+ }
1370
+ };
1371
+
1372
+ /********************************************************************************
1373
+ *
1374
+ * Public API functions
1375
+ * =====================
1376
+ *
1377
+ * Important: Do not expose direct references to private objects or the options
1378
+ * object to the outer world. Always return a clone when returning values or make
1379
+ * a clone when setting a private variable.
1380
+ *
1381
+ ********************************************************************************/
1382
+ picker.destroy = function () {
1383
+ ///<summary>Destroys the widget and removes all attached event listeners</summary>
1384
+ hide();
1385
+ detachDatePickerElementEvents();
1386
+ element.removeData('DateTimePicker');
1387
+ element.removeData('date');
1388
+ };
1389
+
1390
+ picker.toggle = toggle;
1391
+
1392
+ picker.show = show;
1393
+
1394
+ picker.hide = hide;
1395
+
1396
+ picker.disable = function () {
1397
+ ///<summary>Disables the input element, the component is attached to, by adding a disabled="true" attribute to it.
1398
+ ///If the widget was visible before that call it is hidden. Possibly emits dp.hide</summary>
1399
+ hide();
1400
+ if (component && component.hasClass('btn')) {
1401
+ component.addClass('disabled');
1402
+ }
1403
+ input.prop('disabled', true);
1404
+ return picker;
1405
+ };
1406
+
1407
+ picker.enable = function () {
1408
+ ///<summary>Enables the input element, the component is attached to, by removing disabled attribute from it.</summary>
1409
+ if (component && component.hasClass('btn')) {
1410
+ component.removeClass('disabled');
1411
+ }
1412
+ input.prop('disabled', false);
1413
+ return picker;
1414
+ };
1415
+
1416
+ picker.ignoreReadonly = function (ignoreReadonly) {
1417
+ if (arguments.length === 0) {
1418
+ return options.ignoreReadonly;
1419
+ }
1420
+ if (typeof ignoreReadonly !== 'boolean') {
1421
+ throw new TypeError('ignoreReadonly () expects a boolean parameter');
1422
+ }
1423
+ options.ignoreReadonly = ignoreReadonly;
1424
+ return picker;
1425
+ };
1426
+
1427
+ picker.options = function (newOptions) {
1428
+ if (arguments.length === 0) {
1429
+ return $.extend(true, {}, options);
1430
+ }
1431
+
1432
+ if (!(newOptions instanceof Object)) {
1433
+ throw new TypeError('options() options parameter should be an object');
1434
+ }
1435
+ $.extend(true, options, newOptions);
1436
+ $.each(options, function (key, value) {
1437
+ if (picker[key] !== undefined) {
1438
+ picker[key](value);
1439
+ } else {
1440
+ throw new TypeError('option ' + key + ' is not recognized!');
1441
+ }
1442
+ });
1443
+ return picker;
1444
+ };
1445
+
1446
+ picker.date = function (newDate) {
1447
+ ///<signature helpKeyword="$.fn.datetimepicker.date">
1448
+ ///<summary>Returns the component's model current date, a moment object or null if not set.</summary>
1449
+ ///<returns type="Moment">date.clone()</returns>
1450
+ ///</signature>
1451
+ ///<signature>
1452
+ ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
1453
+ ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, Date, moment, null parameter.</param>
1454
+ ///</signature>
1455
+ if (arguments.length === 0) {
1456
+ if (unset) {
1457
+ return null;
1458
+ }
1459
+ return date.clone();
1460
+ }
1461
+
1462
+ if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
1463
+ throw new TypeError('date() parameter must be one of [null, string, moment or Date]');
1464
+ }
1465
+
1466
+ setValue(newDate === null ? null : parseInputDate(newDate));
1467
+ return picker;
1468
+ };
1469
+
1470
+ picker.format = function (newFormat) {
1471
+ ///<summary>test su</summary>
1472
+ ///<param name="newFormat">info about para</param>
1473
+ ///<returns type="string|boolean">returns foo</returns>
1474
+ if (arguments.length === 0) {
1475
+ return options.format;
1476
+ }
1477
+
1478
+ if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) {
1479
+ throw new TypeError('format() expects a sting or boolean:false parameter ' + newFormat);
1480
+ }
1481
+
1482
+ options.format = newFormat;
1483
+ if (actualFormat) {
1484
+ initFormatting(); // reinit formatting
1485
+ }
1486
+ return picker;
1487
+ };
1488
+
1489
+ picker.dayViewHeaderFormat = function (newFormat) {
1490
+ if (arguments.length === 0) {
1491
+ return options.dayViewHeaderFormat;
1492
+ }
1493
+
1494
+ if (typeof newFormat !== 'string') {
1495
+ throw new TypeError('dayViewHeaderFormat() expects a string parameter');
1496
+ }
1497
+
1498
+ options.dayViewHeaderFormat = newFormat;
1499
+ return picker;
1500
+ };
1501
+
1502
+ picker.extraFormats = function (formats) {
1503
+ if (arguments.length === 0) {
1504
+ return options.extraFormats;
1505
+ }
1506
+
1507
+ if (formats !== false && !(formats instanceof Array)) {
1508
+ throw new TypeError('extraFormats() expects an array or false parameter');
1509
+ }
1510
+
1511
+ options.extraFormats = formats;
1512
+ if (parseFormats) {
1513
+ initFormatting(); // reinit formatting
1514
+ }
1515
+ return picker;
1516
+ };
1517
+
1518
+ picker.disabledDates = function (dates) {
1519
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledDates">
1520
+ ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
1521
+ ///<returns type="array">options.disabledDates</returns>
1522
+ ///</signature>
1523
+ ///<signature>
1524
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
1525
+ ///options.enabledDates if such exist.</summary>
1526
+ ///<param name="dates" locid="$.fn.datetimepicker.disabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
1527
+ ///</signature>
1528
+ if (arguments.length === 0) {
1529
+ return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates);
1530
+ }
1531
+
1532
+ if (!dates) {
1533
+ options.disabledDates = false;
1534
+ update();
1535
+ return picker;
1536
+ }
1537
+ if (!(dates instanceof Array)) {
1538
+ throw new TypeError('disabledDates() expects an array parameter');
1539
+ }
1540
+ options.disabledDates = indexGivenDates(dates);
1541
+ options.enabledDates = false;
1542
+ update();
1543
+ return picker;
1544
+ };
1545
+
1546
+ picker.enabledDates = function (dates) {
1547
+ ///<signature helpKeyword="$.fn.datetimepicker.enabledDates">
1548
+ ///<summary>Returns an array with the currently set enabled dates on the component.</summary>
1549
+ ///<returns type="array">options.enabledDates</returns>
1550
+ ///</signature>
1551
+ ///<signature>
1552
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledDates if such exist.</summary>
1553
+ ///<param name="dates" locid="$.fn.datetimepicker.enabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
1554
+ ///</signature>
1555
+ if (arguments.length === 0) {
1556
+ return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates);
1557
+ }
1558
+
1559
+ if (!dates) {
1560
+ options.enabledDates = false;
1561
+ update();
1562
+ return picker;
1563
+ }
1564
+ if (!(dates instanceof Array)) {
1565
+ throw new TypeError('enabledDates() expects an array parameter');
1566
+ }
1567
+ options.enabledDates = indexGivenDates(dates);
1568
+ options.disabledDates = false;
1569
+ update();
1570
+ return picker;
1571
+ };
1572
+
1573
+ picker.daysOfWeekDisabled = function (daysOfWeekDisabled) {
1574
+ if (arguments.length === 0) {
1575
+ return options.daysOfWeekDisabled.splice(0);
1576
+ }
1577
+
1578
+ if ((typeof daysOfWeekDisabled === 'boolean') && !daysOfWeekDisabled) {
1579
+ options.daysOfWeekDisabled = false;
1580
+ update();
1581
+ return picker;
1582
+ }
1583
+
1584
+ if (!(daysOfWeekDisabled instanceof Array)) {
1585
+ throw new TypeError('daysOfWeekDisabled() expects an array parameter');
1586
+ }
1587
+ options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) {
1588
+ currentValue = parseInt(currentValue, 10);
1589
+ if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) {
1590
+ return previousValue;
1591
+ }
1592
+ if (previousValue.indexOf(currentValue) === -1) {
1593
+ previousValue.push(currentValue);
1594
+ }
1595
+ return previousValue;
1596
+ }, []).sort();
1597
+ if (options.useCurrent && !options.keepInvalid) {
1598
+ var tries = 0;
1599
+ while (!isValid(date, 'd')) {
1600
+ date.add(1, 'd');
1601
+ if (tries === 7) {
1602
+ throw 'Tried 7 times to find a valid date';
1603
+ }
1604
+ tries++;
1605
+ }
1606
+ setValue(date);
1607
+ }
1608
+ update();
1609
+ return picker;
1610
+ };
1611
+
1612
+ picker.maxDate = function (maxDate) {
1613
+ if (arguments.length === 0) {
1614
+ return options.maxDate ? options.maxDate.clone() : options.maxDate;
1615
+ }
1616
+
1617
+ if ((typeof maxDate === 'boolean') && maxDate === false) {
1618
+ options.maxDate = false;
1619
+ update();
1620
+ return picker;
1621
+ }
1622
+
1623
+ if (typeof maxDate === 'string') {
1624
+ if (maxDate === 'now' || maxDate === 'moment') {
1625
+ maxDate = moment();
1626
+ }
1627
+ }
1628
+
1629
+ var parsedDate = parseInputDate(maxDate);
1630
+
1631
+ if (!parsedDate.isValid()) {
1632
+ throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate);
1633
+ }
1634
+ if (options.minDate && parsedDate.isBefore(options.minDate)) {
1635
+ throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat));
1636
+ }
1637
+ options.maxDate = parsedDate;
1638
+ if (options.useCurrent && !options.keepInvalid && date.isAfter(maxDate)) {
1639
+ setValue(options.maxDate);
1640
+ }
1641
+ if (viewDate.isAfter(parsedDate)) {
1642
+ viewDate = parsedDate.clone().subtract(options.stepping, 'm');
1643
+ }
1644
+ update();
1645
+ return picker;
1646
+ };
1647
+
1648
+ picker.minDate = function (minDate) {
1649
+ if (arguments.length === 0) {
1650
+ return options.minDate ? options.minDate.clone() : options.minDate;
1651
+ }
1652
+
1653
+ if ((typeof minDate === 'boolean') && minDate === false) {
1654
+ options.minDate = false;
1655
+ update();
1656
+ return picker;
1657
+ }
1658
+
1659
+ if (typeof minDate === 'string') {
1660
+ if (minDate === 'now' || minDate === 'moment') {
1661
+ minDate = moment();
1662
+ }
1663
+ }
1664
+
1665
+ var parsedDate = parseInputDate(minDate);
1666
+
1667
+ if (!parsedDate.isValid()) {
1668
+ throw new TypeError('minDate() Could not parse date parameter: ' + minDate);
1669
+ }
1670
+ if (options.maxDate && parsedDate.isAfter(options.maxDate)) {
1671
+ throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat));
1672
+ }
1673
+ options.minDate = parsedDate;
1674
+ if (options.useCurrent && !options.keepInvalid && date.isBefore(minDate)) {
1675
+ setValue(options.minDate);
1676
+ }
1677
+ if (viewDate.isBefore(parsedDate)) {
1678
+ viewDate = parsedDate.clone().add(options.stepping, 'm');
1679
+ }
1680
+ update();
1681
+ return picker;
1682
+ };
1683
+
1684
+ picker.defaultDate = function (defaultDate) {
1685
+ ///<signature helpKeyword="$.fn.datetimepicker.defaultDate">
1686
+ ///<summary>Returns a moment with the options.defaultDate option configuration or false if not set</summary>
1687
+ ///<returns type="Moment">date.clone()</returns>
1688
+ ///</signature>
1689
+ ///<signature>
1690
+ ///<summary>Will set the picker's inital date. If a boolean:false value is passed the options.defaultDate parameter is cleared.</summary>
1691
+ ///<param name="defaultDate" locid="$.fn.datetimepicker.defaultDate_p:defaultDate">Takes a string, Date, moment, boolean:false</param>
1692
+ ///</signature>
1693
+ if (arguments.length === 0) {
1694
+ return options.defaultDate ? options.defaultDate.clone() : options.defaultDate;
1695
+ }
1696
+ if (!defaultDate) {
1697
+ options.defaultDate = false;
1698
+ return picker;
1699
+ }
1700
+
1701
+ if (typeof defaultDate === 'string') {
1702
+ if (defaultDate === 'now' || defaultDate === 'moment') {
1703
+ defaultDate = moment();
1704
+ }
1705
+ }
1706
+
1707
+ var parsedDate = parseInputDate(defaultDate);
1708
+ if (!parsedDate.isValid()) {
1709
+ throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate);
1710
+ }
1711
+ if (!isValid(parsedDate)) {
1712
+ throw new TypeError('defaultDate() date passed is invalid according to component setup validations');
1713
+ }
1714
+
1715
+ options.defaultDate = parsedDate;
1716
+
1717
+ if (options.defaultDate && options.inline || (input.val().trim() === '' && input.attr('placeholder') === undefined)) {
1718
+ setValue(options.defaultDate);
1719
+ }
1720
+ return picker;
1721
+ };
1722
+
1723
+ picker.locale = function (locale) {
1724
+ if (arguments.length === 0) {
1725
+ return options.locale;
1726
+ }
1727
+
1728
+ if (!moment.localeData(locale)) {
1729
+ throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!');
1730
+ }
1731
+
1732
+ options.locale = locale;
1733
+ date.locale(options.locale);
1734
+ viewDate.locale(options.locale);
1735
+
1736
+ if (actualFormat) {
1737
+ initFormatting(); // reinit formatting
1738
+ }
1739
+ if (widget) {
1740
+ hide();
1741
+ show();
1742
+ }
1743
+ return picker;
1744
+ };
1745
+
1746
+ picker.stepping = function (stepping) {
1747
+ if (arguments.length === 0) {
1748
+ return options.stepping;
1749
+ }
1750
+
1751
+ stepping = parseInt(stepping, 10);
1752
+ if (isNaN(stepping) || stepping < 1) {
1753
+ stepping = 1;
1754
+ }
1755
+ options.stepping = stepping;
1756
+ return picker;
1757
+ };
1758
+
1759
+ picker.useCurrent = function (useCurrent) {
1760
+ var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute'];
1761
+ if (arguments.length === 0) {
1762
+ return options.useCurrent;
1763
+ }
1764
+
1765
+ if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) {
1766
+ throw new TypeError('useCurrent() expects a boolean or string parameter');
1767
+ }
1768
+ if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) {
1769
+ throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', '));
1770
+ }
1771
+ options.useCurrent = useCurrent;
1772
+ return picker;
1773
+ };
1774
+
1775
+ picker.collapse = function (collapse) {
1776
+ if (arguments.length === 0) {
1777
+ return options.collapse;
1778
+ }
1779
+
1780
+ if (typeof collapse !== 'boolean') {
1781
+ throw new TypeError('collapse() expects a boolean parameter');
1782
+ }
1783
+ if (options.collapse === collapse) {
1784
+ return picker;
1785
+ }
1786
+ options.collapse = collapse;
1787
+ if (widget) {
1788
+ hide();
1789
+ show();
1790
+ }
1791
+ return picker;
1792
+ };
1793
+
1794
+ picker.icons = function (icons) {
1795
+ if (arguments.length === 0) {
1796
+ return $.extend({}, options.icons);
1797
+ }
1798
+
1799
+ if (!(icons instanceof Object)) {
1800
+ throw new TypeError('icons() expects parameter to be an Object');
1801
+ }
1802
+ $.extend(options.icons, icons);
1803
+ if (widget) {
1804
+ hide();
1805
+ show();
1806
+ }
1807
+ return picker;
1808
+ };
1809
+
1810
+ picker.tooltips = function (tooltips) {
1811
+ if (arguments.length === 0) {
1812
+ return $.extend({}, options.tooltips);
1813
+ }
1814
+
1815
+ if (!(tooltips instanceof Object)) {
1816
+ throw new TypeError('tooltips() expects parameter to be an Object');
1817
+ }
1818
+ $.extend(options.tooltips, tooltips);
1819
+ if (widget) {
1820
+ hide();
1821
+ show();
1822
+ }
1823
+ return picker;
1824
+ };
1825
+
1826
+ picker.useStrict = function (useStrict) {
1827
+ if (arguments.length === 0) {
1828
+ return options.useStrict;
1829
+ }
1830
+
1831
+ if (typeof useStrict !== 'boolean') {
1832
+ throw new TypeError('useStrict() expects a boolean parameter');
1833
+ }
1834
+ options.useStrict = useStrict;
1835
+ return picker;
1836
+ };
1837
+
1838
+ picker.sideBySide = function (sideBySide) {
1839
+ if (arguments.length === 0) {
1840
+ return options.sideBySide;
1841
+ }
1842
+
1843
+ if (typeof sideBySide !== 'boolean') {
1844
+ throw new TypeError('sideBySide() expects a boolean parameter');
1845
+ }
1846
+ options.sideBySide = sideBySide;
1847
+ if (widget) {
1848
+ hide();
1849
+ show();
1850
+ }
1851
+ return picker;
1852
+ };
1853
+
1854
+ picker.viewMode = function (viewMode) {
1855
+ if (arguments.length === 0) {
1856
+ return options.viewMode;
1857
+ }
1858
+
1859
+ if (typeof viewMode !== 'string') {
1860
+ throw new TypeError('viewMode() expects a string parameter');
1861
+ }
1862
+
1863
+ if (viewModes.indexOf(viewMode) === -1) {
1864
+ throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value');
1865
+ }
1866
+
1867
+ options.viewMode = viewMode;
1868
+ currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber);
1869
+
1870
+ showMode();
1871
+ return picker;
1872
+ };
1873
+
1874
+ picker.toolbarPlacement = function (toolbarPlacement) {
1875
+ if (arguments.length === 0) {
1876
+ return options.toolbarPlacement;
1877
+ }
1878
+
1879
+ if (typeof toolbarPlacement !== 'string') {
1880
+ throw new TypeError('toolbarPlacement() expects a string parameter');
1881
+ }
1882
+ if (toolbarPlacements.indexOf(toolbarPlacement) === -1) {
1883
+ throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value');
1884
+ }
1885
+ options.toolbarPlacement = toolbarPlacement;
1886
+
1887
+ if (widget) {
1888
+ hide();
1889
+ show();
1890
+ }
1891
+ return picker;
1892
+ };
1893
+
1894
+ picker.widgetPositioning = function (widgetPositioning) {
1895
+ if (arguments.length === 0) {
1896
+ return $.extend({}, options.widgetPositioning);
1897
+ }
1898
+
1899
+ if (({}).toString.call(widgetPositioning) !== '[object Object]') {
1900
+ throw new TypeError('widgetPositioning() expects an object variable');
1901
+ }
1902
+ if (widgetPositioning.horizontal) {
1903
+ if (typeof widgetPositioning.horizontal !== 'string') {
1904
+ throw new TypeError('widgetPositioning() horizontal variable must be a string');
1905
+ }
1906
+ widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase();
1907
+ if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) {
1908
+ throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')');
1909
+ }
1910
+ options.widgetPositioning.horizontal = widgetPositioning.horizontal;
1911
+ }
1912
+ if (widgetPositioning.vertical) {
1913
+ if (typeof widgetPositioning.vertical !== 'string') {
1914
+ throw new TypeError('widgetPositioning() vertical variable must be a string');
1915
+ }
1916
+ widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase();
1917
+ if (verticalModes.indexOf(widgetPositioning.vertical) === -1) {
1918
+ throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')');
1919
+ }
1920
+ options.widgetPositioning.vertical = widgetPositioning.vertical;
1921
+ }
1922
+ update();
1923
+ return picker;
1924
+ };
1925
+
1926
+ picker.calendarWeeks = function (calendarWeeks) {
1927
+ if (arguments.length === 0) {
1928
+ return options.calendarWeeks;
1929
+ }
1930
+
1931
+ if (typeof calendarWeeks !== 'boolean') {
1932
+ throw new TypeError('calendarWeeks() expects parameter to be a boolean value');
1933
+ }
1934
+
1935
+ options.calendarWeeks = calendarWeeks;
1936
+ update();
1937
+ return picker;
1938
+ };
1939
+
1940
+ picker.showTodayButton = function (showTodayButton) {
1941
+ if (arguments.length === 0) {
1942
+ return options.showTodayButton;
1943
+ }
1944
+
1945
+ if (typeof showTodayButton !== 'boolean') {
1946
+ throw new TypeError('showTodayButton() expects a boolean parameter');
1947
+ }
1948
+
1949
+ options.showTodayButton = showTodayButton;
1950
+ if (widget) {
1951
+ hide();
1952
+ show();
1953
+ }
1954
+ return picker;
1955
+ };
1956
+
1957
+ picker.showClear = function (showClear) {
1958
+ if (arguments.length === 0) {
1959
+ return options.showClear;
1960
+ }
1961
+
1962
+ if (typeof showClear !== 'boolean') {
1963
+ throw new TypeError('showClear() expects a boolean parameter');
1964
+ }
1965
+
1966
+ options.showClear = showClear;
1967
+ if (widget) {
1968
+ hide();
1969
+ show();
1970
+ }
1971
+ return picker;
1972
+ };
1973
+
1974
+ picker.widgetParent = function (widgetParent) {
1975
+ if (arguments.length === 0) {
1976
+ return options.widgetParent;
1977
+ }
1978
+
1979
+ if (typeof widgetParent === 'string') {
1980
+ widgetParent = $(widgetParent);
1981
+ }
1982
+
1983
+ if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) {
1984
+ throw new TypeError('widgetParent() expects a string or a jQuery object parameter');
1985
+ }
1986
+
1987
+ options.widgetParent = widgetParent;
1988
+ if (widget) {
1989
+ hide();
1990
+ show();
1991
+ }
1992
+ return picker;
1993
+ };
1994
+
1995
+ picker.keepOpen = function (keepOpen) {
1996
+ if (arguments.length === 0) {
1997
+ return options.keepOpen;
1998
+ }
1999
+
2000
+ if (typeof keepOpen !== 'boolean') {
2001
+ throw new TypeError('keepOpen() expects a boolean parameter');
2002
+ }
2003
+
2004
+ options.keepOpen = keepOpen;
2005
+ return picker;
2006
+ };
2007
+
2008
+ picker.focusOnShow = function (focusOnShow) {
2009
+ if (arguments.length === 0) {
2010
+ return options.focusOnShow;
2011
+ }
2012
+
2013
+ if (typeof focusOnShow !== 'boolean') {
2014
+ throw new TypeError('focusOnShow() expects a boolean parameter');
2015
+ }
2016
+
2017
+ options.focusOnShow = focusOnShow;
2018
+ return picker;
2019
+ };
2020
+
2021
+ picker.inline = function (inline) {
2022
+ if (arguments.length === 0) {
2023
+ return options.inline;
2024
+ }
2025
+
2026
+ if (typeof inline !== 'boolean') {
2027
+ throw new TypeError('inline() expects a boolean parameter');
2028
+ }
2029
+
2030
+ options.inline = inline;
2031
+ return picker;
2032
+ };
2033
+
2034
+ picker.clear = function () {
2035
+ clear();
2036
+ return picker;
2037
+ };
2038
+
2039
+ picker.keyBinds = function (keyBinds) {
2040
+ options.keyBinds = keyBinds;
2041
+ return picker;
2042
+ };
2043
+
2044
+ picker.debug = function (debug) {
2045
+ if (typeof debug !== 'boolean') {
2046
+ throw new TypeError('debug() expects a boolean parameter');
2047
+ }
2048
+
2049
+ options.debug = debug;
2050
+ return picker;
2051
+ };
2052
+
2053
+ picker.allowInputToggle = function (allowInputToggle) {
2054
+ if (arguments.length === 0) {
2055
+ return options.allowInputToggle;
2056
+ }
2057
+
2058
+ if (typeof allowInputToggle !== 'boolean') {
2059
+ throw new TypeError('allowInputToggle() expects a boolean parameter');
2060
+ }
2061
+
2062
+ options.allowInputToggle = allowInputToggle;
2063
+ return picker;
2064
+ };
2065
+
2066
+ picker.showClose = function (showClose) {
2067
+ if (arguments.length === 0) {
2068
+ return options.showClose;
2069
+ }
2070
+
2071
+ if (typeof showClose !== 'boolean') {
2072
+ throw new TypeError('showClose() expects a boolean parameter');
2073
+ }
2074
+
2075
+ options.showClose = showClose;
2076
+ return picker;
2077
+ };
2078
+
2079
+ picker.keepInvalid = function (keepInvalid) {
2080
+ if (arguments.length === 0) {
2081
+ return options.keepInvalid;
2082
+ }
2083
+
2084
+ if (typeof keepInvalid !== 'boolean') {
2085
+ throw new TypeError('keepInvalid() expects a boolean parameter');
2086
+ }
2087
+ options.keepInvalid = keepInvalid;
2088
+ return picker;
2089
+ };
2090
+
2091
+ picker.datepickerInput = function (datepickerInput) {
2092
+ if (arguments.length === 0) {
2093
+ return options.datepickerInput;
2094
+ }
2095
+
2096
+ if (typeof datepickerInput !== 'string') {
2097
+ throw new TypeError('datepickerInput() expects a string parameter');
2098
+ }
2099
+
2100
+ options.datepickerInput = datepickerInput;
2101
+ return picker;
2102
+ };
2103
+
2104
+ picker.parseInputDate = function (parseInputDate) {
2105
+ if (arguments.length === 0) {
2106
+ return options.parseInputDate;
2107
+ }
2108
+
2109
+ if (typeof parseInputDate !== 'function') {
2110
+ throw new TypeError('parseInputDate() sholud be as function');
2111
+ }
2112
+
2113
+ options.parseInputDate = parseInputDate;
2114
+
2115
+ return picker;
2116
+ };
2117
+
2118
+ picker.disabledTimeIntervals = function (disabledTimeIntervals) {
2119
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledTimeIntervals">
2120
+ ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
2121
+ ///<returns type="array">options.disabledTimeIntervals</returns>
2122
+ ///</signature>
2123
+ ///<signature>
2124
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
2125
+ ///options.enabledDates if such exist.</summary>
2126
+ ///<param name="dates" locid="$.fn.datetimepicker.disabledTimeIntervals_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
2127
+ ///</signature>
2128
+ if (arguments.length === 0) {
2129
+ return (options.disabledTimeIntervals ? $.extend({}, options.disabledTimeIntervals) : options.disabledTimeIntervals);
2130
+ }
2131
+
2132
+ if (!disabledTimeIntervals) {
2133
+ options.disabledTimeIntervals = false;
2134
+ update();
2135
+ return picker;
2136
+ }
2137
+ if (!(disabledTimeIntervals instanceof Array)) {
2138
+ throw new TypeError('disabledTimeIntervals() expects an array parameter');
2139
+ }
2140
+ options.disabledTimeIntervals = disabledTimeIntervals;
2141
+ update();
2142
+ return picker;
2143
+ };
2144
+
2145
+ picker.disabledHours = function (hours) {
2146
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledHours">
2147
+ ///<summary>Returns an array with the currently set disabled hours on the component.</summary>
2148
+ ///<returns type="array">options.disabledHours</returns>
2149
+ ///</signature>
2150
+ ///<signature>
2151
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
2152
+ ///options.enabledHours if such exist.</summary>
2153
+ ///<param name="hours" locid="$.fn.datetimepicker.disabledHours_p:hours">Takes an [ int ] of values and disallows the user to select only from those hours.</param>
2154
+ ///</signature>
2155
+ if (arguments.length === 0) {
2156
+ return (options.disabledHours ? $.extend({}, options.disabledHours) : options.disabledHours);
2157
+ }
2158
+
2159
+ if (!hours) {
2160
+ options.disabledHours = false;
2161
+ update();
2162
+ return picker;
2163
+ }
2164
+ if (!(hours instanceof Array)) {
2165
+ throw new TypeError('disabledHours() expects an array parameter');
2166
+ }
2167
+ options.disabledHours = indexGivenHours(hours);
2168
+ options.enabledHours = false;
2169
+ if (options.useCurrent && !options.keepInvalid) {
2170
+ var tries = 0;
2171
+ while (!isValid(date, 'h')) {
2172
+ date.add(1, 'h');
2173
+ if (tries === 24) {
2174
+ throw 'Tried 24 times to find a valid date';
2175
+ }
2176
+ tries++;
2177
+ }
2178
+ setValue(date);
2179
+ }
2180
+ update();
2181
+ return picker;
2182
+ };
2183
+
2184
+ picker.enabledHours = function (hours) {
2185
+ ///<signature helpKeyword="$.fn.datetimepicker.enabledHours">
2186
+ ///<summary>Returns an array with the currently set enabled hours on the component.</summary>
2187
+ ///<returns type="array">options.enabledHours</returns>
2188
+ ///</signature>
2189
+ ///<signature>
2190
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledHours if such exist.</summary>
2191
+ ///<param name="hours" locid="$.fn.datetimepicker.enabledHours_p:hours">Takes an [ int ] of values and allows the user to select only from those hours.</param>
2192
+ ///</signature>
2193
+ if (arguments.length === 0) {
2194
+ return (options.enabledHours ? $.extend({}, options.enabledHours) : options.enabledHours);
2195
+ }
2196
+
2197
+ if (!hours) {
2198
+ options.enabledHours = false;
2199
+ update();
2200
+ return picker;
2201
+ }
2202
+ if (!(hours instanceof Array)) {
2203
+ throw new TypeError('enabledHours() expects an array parameter');
2204
+ }
2205
+ options.enabledHours = indexGivenHours(hours);
2206
+ options.disabledHours = false;
2207
+ if (options.useCurrent && !options.keepInvalid) {
2208
+ var tries = 0;
2209
+ while (!isValid(date, 'h')) {
2210
+ date.add(1, 'h');
2211
+ if (tries === 24) {
2212
+ throw 'Tried 24 times to find a valid date';
2213
+ }
2214
+ tries++;
2215
+ }
2216
+ setValue(date);
2217
+ }
2218
+ update();
2219
+ return picker;
2220
+ };
2221
+
2222
+ picker.viewDate = function (newDate) {
2223
+ ///<signature helpKeyword="$.fn.datetimepicker.viewDate">
2224
+ ///<summary>Returns the component's model current viewDate, a moment object or null if not set.</summary>
2225
+ ///<returns type="Moment">viewDate.clone()</returns>
2226
+ ///</signature>
2227
+ ///<signature>
2228
+ ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
2229
+ ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, viewDate, moment, null parameter.</param>
2230
+ ///</signature>
2231
+ if (arguments.length === 0) {
2232
+ return viewDate.clone();
2233
+ }
2234
+
2235
+ if (!newDate) {
2236
+ viewDate = date.clone();
2237
+ return picker;
2238
+ }
2239
+
2240
+ if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
2241
+ throw new TypeError('viewDate() parameter must be one of [string, moment or Date]');
2242
+ }
2243
+
2244
+ viewDate = parseInputDate(newDate);
2245
+ viewUpdate();
2246
+ return picker;
2247
+ };
2248
+
2249
+ // initializing element and component attributes
2250
+ if (element.is('input')) {
2251
+ input = element;
2252
+ } else {
2253
+ input = element.find(options.datepickerInput);
2254
+ if (input.size() === 0) {
2255
+ input = element.find('input');
2256
+ } else if (!input.is('input')) {
2257
+ throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element');
2258
+ }
2259
+ }
2260
+
2261
+ if (element.hasClass('input-group')) {
2262
+ // in case there is more then one 'input-group-addon' Issue #48
2263
+ if (element.find('.datepickerbutton').size() === 0) {
2264
+ component = element.find('.input-group-addon');
2265
+ } else {
2266
+ component = element.find('.datepickerbutton');
2267
+ }
2268
+ }
2269
+
2270
+ if (!options.inline && !input.is('input')) {
2271
+ throw new Error('Could not initialize DateTimePicker without an input element');
2272
+ }
2273
+
2274
+ $.extend(true, options, dataToOptions());
2275
+
2276
+ picker.options(options);
2277
+
2278
+ initFormatting();
2279
+
2280
+ attachDatePickerElementEvents();
2281
+
2282
+ if (input.prop('disabled')) {
2283
+ picker.disable();
2284
+ }
2285
+ if (input.is('input') && input.val().trim().length !== 0) {
2286
+ setValue(parseInputDate(input.val().trim()));
2287
+ }
2288
+ else if (options.defaultDate && input.attr('placeholder') === undefined) {
2289
+ setValue(options.defaultDate);
2290
+ }
2291
+ if (options.inline) {
2292
+ show();
2293
+ }
2294
+ return picker;
2295
+ };
2296
+
2297
+ /********************************************************************************
2298
+ *
2299
+ * jQuery plugin constructor and defaults object
2300
+ *
2301
+ ********************************************************************************/
2302
+
2303
+ $.fn.datetimepicker = function (options) {
2304
+ return this.each(function () {
2305
+ var $this = $(this);
2306
+ if (!$this.data('DateTimePicker')) {
2307
+ // create a private copy of the defaults object
2308
+ options = $.extend(true, {}, $.fn.datetimepicker.defaults, options);
2309
+ $this.data('DateTimePicker', dateTimePicker($this, options));
2310
+ }
2311
+ });
2312
+ };
2313
+
2314
+ $.fn.datetimepicker.defaults = {
2315
+ format: false,
2316
+ dayViewHeaderFormat: 'MMMM YYYY',
2317
+ extraFormats: false,
2318
+ stepping: 1,
2319
+ minDate: false,
2320
+ maxDate: false,
2321
+ useCurrent: true,
2322
+ collapse: true,
2323
+ locale: moment.locale(),
2324
+ defaultDate: false,
2325
+ disabledDates: false,
2326
+ enabledDates: false,
2327
+ icons: {
2328
+ time: 'glyphicon glyphicon-time',
2329
+ date: 'glyphicon glyphicon-calendar',
2330
+ up: 'glyphicon glyphicon-chevron-up',
2331
+ down: 'glyphicon glyphicon-chevron-down',
2332
+ previous: 'glyphicon glyphicon-chevron-left',
2333
+ next: 'glyphicon glyphicon-chevron-right',
2334
+ today: 'glyphicon glyphicon-screenshot',
2335
+ clear: 'glyphicon glyphicon-trash',
2336
+ close: 'glyphicon glyphicon-remove'
2337
+ },
2338
+ tooltips: {
2339
+ today: 'Go to today',
2340
+ clear: 'Clear selection',
2341
+ close: 'Close the picker',
2342
+ selectMonth: 'Select Month',
2343
+ prevMonth: 'Previous Month',
2344
+ nextMonth: 'Next Month',
2345
+ selectYear: 'Select Year',
2346
+ prevYear: 'Previous Year',
2347
+ nextYear: 'Next Year',
2348
+ selectDecade: 'Select Decade',
2349
+ prevDecade: 'Previous Decade',
2350
+ nextDecade: 'Next Decade',
2351
+ prevCentury: 'Previous Century',
2352
+ nextCentury: 'Next Century'
2353
+ },
2354
+ useStrict: false,
2355
+ sideBySide: false,
2356
+ daysOfWeekDisabled: false,
2357
+ calendarWeeks: false,
2358
+ viewMode: 'days',
2359
+ toolbarPlacement: 'default',
2360
+ showTodayButton: false,
2361
+ showClear: false,
2362
+ showClose: false,
2363
+ widgetPositioning: {
2364
+ horizontal: 'auto',
2365
+ vertical: 'auto'
2366
+ },
2367
+ widgetParent: null,
2368
+ ignoreReadonly: false,
2369
+ keepOpen: false,
2370
+ focusOnShow: true,
2371
+ inline: false,
2372
+ keepInvalid: false,
2373
+ datepickerInput: '.datepickerinput',
2374
+ keyBinds: {
2375
+ up: function (widget) {
2376
+ if (!widget) {
2377
+ return;
2378
+ }
2379
+ var d = this.date() || moment();
2380
+ if (widget.find('.datepicker').is(':visible')) {
2381
+ this.date(d.clone().subtract(7, 'd'));
2382
+ } else {
2383
+ this.date(d.clone().add(this.stepping(), 'm'));
2384
+ }
2385
+ },
2386
+ down: function (widget) {
2387
+ if (!widget) {
2388
+ this.show();
2389
+ return;
2390
+ }
2391
+ var d = this.date() || moment();
2392
+ if (widget.find('.datepicker').is(':visible')) {
2393
+ this.date(d.clone().add(7, 'd'));
2394
+ } else {
2395
+ this.date(d.clone().subtract(this.stepping(), 'm'));
2396
+ }
2397
+ },
2398
+ 'control up': function (widget) {
2399
+ if (!widget) {
2400
+ return;
2401
+ }
2402
+ var d = this.date() || moment();
2403
+ if (widget.find('.datepicker').is(':visible')) {
2404
+ this.date(d.clone().subtract(1, 'y'));
2405
+ } else {
2406
+ this.date(d.clone().add(1, 'h'));
2407
+ }
2408
+ },
2409
+ 'control down': function (widget) {
2410
+ if (!widget) {
2411
+ return;
2412
+ }
2413
+ var d = this.date() || moment();
2414
+ if (widget.find('.datepicker').is(':visible')) {
2415
+ this.date(d.clone().add(1, 'y'));
2416
+ } else {
2417
+ this.date(d.clone().subtract(1, 'h'));
2418
+ }
2419
+ },
2420
+ left: function (widget) {
2421
+ if (!widget) {
2422
+ return;
2423
+ }
2424
+ var d = this.date() || moment();
2425
+ if (widget.find('.datepicker').is(':visible')) {
2426
+ this.date(d.clone().subtract(1, 'd'));
2427
+ }
2428
+ },
2429
+ right: function (widget) {
2430
+ if (!widget) {
2431
+ return;
2432
+ }
2433
+ var d = this.date() || moment();
2434
+ if (widget.find('.datepicker').is(':visible')) {
2435
+ this.date(d.clone().add(1, 'd'));
2436
+ }
2437
+ },
2438
+ pageUp: function (widget) {
2439
+ if (!widget) {
2440
+ return;
2441
+ }
2442
+ var d = this.date() || moment();
2443
+ if (widget.find('.datepicker').is(':visible')) {
2444
+ this.date(d.clone().subtract(1, 'M'));
2445
+ }
2446
+ },
2447
+ pageDown: function (widget) {
2448
+ if (!widget) {
2449
+ return;
2450
+ }
2451
+ var d = this.date() || moment();
2452
+ if (widget.find('.datepicker').is(':visible')) {
2453
+ this.date(d.clone().add(1, 'M'));
2454
+ }
2455
+ },
2456
+ enter: function () {
2457
+ this.hide();
2458
+ },
2459
+ escape: function () {
2460
+ this.hide();
2461
+ },
2462
+ //tab: function (widget) { //this break the flow of the form. disabling for now
2463
+ // var toggle = widget.find('.picker-switch a[data-action="togglePicker"]');
2464
+ // if(toggle.length > 0) toggle.click();
2465
+ //},
2466
+ 'control space': function (widget) {
2467
+ if (widget.find('.timepicker').is(':visible')) {
2468
+ widget.find('.btn[data-action="togglePeriod"]').click();
2469
+ }
2470
+ },
2471
+ t: function () {
2472
+ this.date(moment());
2473
+ },
2474
+ 'delete': function () {
2475
+ this.clear();
2476
+ }
2477
+ },
2478
+ debug: false,
2479
+ allowInputToggle: false,
2480
+ disabledTimeIntervals: false,
2481
+ disabledHours: false,
2482
+ enabledHours: false,
2483
+ viewDate: false
2484
+ };
2485
+ }));