Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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