shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

bootstrap-datetimepicker.min.js (58299B)


      1 /*
      2 //! version : 3.1.3
      3 =========================================================
      4 bootstrap-datetimepicker.js
      5 https://github.com/Eonasdan/bootstrap-datetimepicker
      6 =========================================================
      7 The MIT License (MIT)
      8 
      9 Copyright (c) 2014 Jonathan Peterson
     10 
     11 Permission is hereby granted, free of charge, to any person obtaining a copy
     12 of this software and associated documentation files (the "Software"), to deal
     13 in the Software without restriction, including without limitation the rights
     14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     15 copies of the Software, and to permit persons to whom the Software is
     16 furnished to do so, subject to the following conditions:
     17 
     18 The above copyright notice and this permission notice shall be included in
     19 all copies or substantial portions of the Software.
     20 
     21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     27 THE SOFTWARE.
     28 */
     29 ;(function (root, factory) {
     30     'use strict';
     31     if (typeof define === 'function' && define.amd) {
     32         // AMD is used - Register as an anonymous module.
     33         define(['jquery', 'moment'], factory);
     34     } else if (typeof exports === 'object') {
     35         factory(require('jquery'), require('moment'));
     36     }
     37     else {
     38         // Neither AMD or CommonJS used. Use global variables.
     39         if (!jQuery) {
     40             throw new Error('bootstrap-datetimepicker requires jQuery to be loaded first');
     41         }
     42         if (!moment) {
     43             throw new Error('bootstrap-datetimepicker requires moment.js to be loaded first');
     44         }
     45         factory(root.jQuery, moment);
     46     }
     47 }(this, function ($, moment) {
     48     'use strict';
     49     if (typeof moment === 'undefined') {
     50         throw new Error('momentjs is required');
     51     }
     52 
     53     var dpgId = 0,
     54 
     55     DateTimePicker = function (element, options) {
     56         var defaults = $.fn.datetimepicker.defaults,
     57 
     58             icons = {
     59                 time: 'glyphicon glyphicon-time',
     60                 date: 'glyphicon glyphicon-calendar',
     61                 up: 'glyphicon glyphicon-chevron-up',
     62                 down: 'glyphicon glyphicon-chevron-down'
     63             },
     64 
     65             picker = this,
     66             errored = false,
     67             dDate,
     68 
     69         init = function () {
     70             var icon = false, localeData, rInterval;
     71             picker.options = $.extend({}, defaults, options);
     72             picker.options.icons = $.extend({}, icons, picker.options.icons);
     73 
     74             picker.element = $(element);
     75 
     76             dataToOptions();
     77 
     78             if (!(picker.options.pickTime || picker.options.pickDate)) {
     79                 throw new Error('Must choose at least one picker');
     80             }
     81 
     82             picker.id = dpgId++;
     83             moment.locale(picker.options.language);
     84             picker.date = moment();
     85             picker.unset = false;
     86             picker.isInput = picker.element.is('input');
     87             picker.component = false;
     88 
     89             if (picker.element.hasClass('input-group')) {
     90                 if (picker.element.find('.datepickerbutton').size() === 0) {//in case there is more then one 'input-group-addon' Issue #48
     91                     picker.component = picker.element.find('[class^="input-group-"]');
     92                 }
     93                 else {
     94                     picker.component = picker.element.find('.datepickerbutton');
     95                 }
     96             }
     97             picker.format = picker.options.format;
     98 
     99             localeData = moment().localeData();
    100 
    101             if (!picker.format) {
    102                 picker.format = (picker.options.pickDate ? localeData.longDateFormat('L') : '');
    103                 if (picker.options.pickDate && picker.options.pickTime) {
    104                     picker.format += ' ';
    105                 }
    106                 picker.format += (picker.options.pickTime ? localeData.longDateFormat('LT') : '');
    107                 if (picker.options.useSeconds) {
    108                     if (localeData.longDateFormat('LT').indexOf(' A') !== -1) {
    109                         picker.format = picker.format.split(' A')[0] + ':ss A';
    110                     }
    111                     else {
    112                         picker.format += ':ss';
    113                     }
    114                 }
    115             }
    116             picker.use24hours = (picker.format.toLowerCase().indexOf('a') < 0 && picker.format.indexOf('h') < 0);
    117 
    118             if (picker.component) {
    119                 icon = picker.component.find('span');
    120             }
    121 
    122             if (picker.options.pickTime) {
    123                 if (icon) {
    124                     icon.addClass(picker.options.icons.time);
    125                 }
    126             }
    127             if (picker.options.pickDate) {
    128                 if (icon) {
    129                     icon.removeClass(picker.options.icons.time);
    130                     icon.addClass(picker.options.icons.date);
    131                 }
    132             }
    133 
    134             picker.options.widgetParent =
    135                 typeof picker.options.widgetParent === 'string' && picker.options.widgetParent ||
    136                 picker.element.parents().filter(function () {
    137                     return 'scroll' === $(this).css('overflow-y');
    138                 }).get(0) ||
    139                 'body';
    140 
    141             picker.widget = $(getTemplate()).appendTo(picker.options.widgetParent);
    142 
    143             picker.minViewMode = picker.options.minViewMode || 0;
    144             if (typeof picker.minViewMode === 'string') {
    145                 switch (picker.minViewMode) {
    146                     case 'months':
    147                         picker.minViewMode = 1;
    148                         break;
    149                     case 'years':
    150                         picker.minViewMode = 2;
    151                         break;
    152                     default:
    153                         picker.minViewMode = 0;
    154                         break;
    155                 }
    156             }
    157             picker.viewMode = picker.options.viewMode || 0;
    158             if (typeof picker.viewMode === 'string') {
    159                 switch (picker.viewMode) {
    160                     case 'months':
    161                         picker.viewMode = 1;
    162                         break;
    163                     case 'years':
    164                         picker.viewMode = 2;
    165                         break;
    166                     default:
    167                         picker.viewMode = 0;
    168                         break;
    169                 }
    170             }
    171 
    172             picker.viewMode = Math.max(picker.viewMode, picker.minViewMode);
    173 
    174             picker.options.disabledDates = indexGivenDates(picker.options.disabledDates);
    175             picker.options.enabledDates = indexGivenDates(picker.options.enabledDates);
    176 
    177             picker.startViewMode = picker.viewMode;
    178             picker.setMinDate(picker.options.minDate);
    179             picker.setMaxDate(picker.options.maxDate);
    180             fillDow();
    181             fillMonths();
    182             fillHours();
    183             fillMinutes();
    184             fillSeconds();
    185             update();
    186             showMode();
    187             if (!getPickerInput().prop('disabled')) {
    188                 attachDatePickerEvents();
    189             }
    190             if (picker.options.defaultDate !== '' && getPickerInput().val() === '') {
    191                 picker.setValue(picker.options.defaultDate);
    192             }
    193             if (picker.options.minuteStepping !== 1) {
    194                 rInterval = picker.options.minuteStepping;
    195                 picker.date.minutes((Math.round(picker.date.minutes() / rInterval) * rInterval) % 60).seconds(0);
    196             }
    197         },
    198 
    199         getPickerInput = function () {
    200             var input;
    201 
    202             if (picker.isInput) {
    203                 return picker.element;
    204             }
    205             input = picker.element.find('.datepickerinput');
    206             if (input.size() === 0) {
    207                 input = picker.element.find('input');
    208             }
    209             else if (!input.is('input')) {
    210                 throw new Error('CSS class "datepickerinput" cannot be applied to non input element');
    211             }
    212             return input;
    213         },
    214 
    215         dataToOptions = function () {
    216             var eData;
    217             if (picker.element.is('input')) {
    218                 eData = picker.element.data();
    219             }
    220             else {
    221                 eData = picker.element.find('input').data();
    222             }
    223             if (eData.dateFormat !== undefined) {
    224                 picker.options.format = eData.dateFormat;
    225             }
    226             if (eData.datePickdate !== undefined) {
    227                 picker.options.pickDate = eData.datePickdate;
    228             }
    229             if (eData.datePicktime !== undefined) {
    230                 picker.options.pickTime = eData.datePicktime;
    231             }
    232             if (eData.dateUseminutes !== undefined) {
    233                 picker.options.useMinutes = eData.dateUseminutes;
    234             }
    235             if (eData.dateUseseconds !== undefined) {
    236                 picker.options.useSeconds = eData.dateUseseconds;
    237             }
    238             if (eData.dateUsecurrent !== undefined) {
    239                 picker.options.useCurrent = eData.dateUsecurrent;
    240             }
    241             if (eData.calendarWeeks !== undefined) {
    242                 picker.options.calendarWeeks = eData.calendarWeeks;
    243             }
    244             if (eData.dateMinutestepping !== undefined) {
    245                 picker.options.minuteStepping = eData.dateMinutestepping;
    246             }
    247             if (eData.dateMindate !== undefined) {
    248                 picker.options.minDate = eData.dateMindate;
    249             }
    250             if (eData.dateMaxdate !== undefined) {
    251                 picker.options.maxDate = eData.dateMaxdate;
    252             }
    253             if (eData.dateShowtoday !== undefined) {
    254                 picker.options.showToday = eData.dateShowtoday;
    255             }
    256             if (eData.dateCollapse !== undefined) {
    257                 picker.options.collapse = eData.dateCollapse;
    258             }
    259             if (eData.dateLanguage !== undefined) {
    260                 picker.options.language = eData.dateLanguage;
    261             }
    262             if (eData.dateDefaultdate !== undefined) {
    263                 picker.options.defaultDate = eData.dateDefaultdate;
    264             }
    265             if (eData.dateDisableddates !== undefined) {
    266                 picker.options.disabledDates = eData.dateDisableddates;
    267             }
    268             if (eData.dateEnableddates !== undefined) {
    269                 picker.options.enabledDates = eData.dateEnableddates;
    270             }
    271             if (eData.dateIcons !== undefined) {
    272                 picker.options.icons = eData.dateIcons;
    273             }
    274             if (eData.dateUsestrict !== undefined) {
    275                 picker.options.useStrict = eData.dateUsestrict;
    276             }
    277             if (eData.dateDirection !== undefined) {
    278                 picker.options.direction = eData.dateDirection;
    279             }
    280             if (eData.dateSidebyside !== undefined) {
    281                 picker.options.sideBySide = eData.dateSidebyside;
    282             }
    283             if (eData.dateDaysofweekdisabled !== undefined) {
    284                 picker.options.daysOfWeekDisabled = eData.dateDaysofweekdisabled;
    285             }
    286         },
    287 
    288         place = function () {
    289             var position = 'absolute',
    290                 offset = picker.component ? picker.component.offset() : picker.element.offset(),
    291                 $window = $(window),
    292                 placePosition;
    293 
    294             picker.width = picker.component ? picker.component.outerWidth() : picker.element.outerWidth();
    295             offset.top = offset.top + picker.element.outerHeight();
    296 
    297             if (picker.options.direction === 'up') {
    298                 placePosition = 'top';
    299             } else if (picker.options.direction === 'bottom') {
    300                 placePosition = 'bottom';
    301             } else if (picker.options.direction === 'auto') {
    302                 if (offset.top + picker.widget.height() > $window.height() + $window.scrollTop() && picker.widget.height() + picker.element.outerHeight() < offset.top) {
    303                     placePosition = 'top';
    304                 } else {
    305                     placePosition = 'bottom';
    306                 }
    307             }
    308             if (placePosition === 'top') {
    309                 offset.bottom = $window.height() - offset.top + picker.element.outerHeight() + 3;
    310                 picker.widget.addClass('top').removeClass('bottom');
    311             } else {
    312                 offset.top += 1;
    313                 picker.widget.addClass('bottom').removeClass('top');
    314             }
    315 
    316             if (picker.options.width !== undefined) {
    317                 picker.widget.width(picker.options.width);
    318             }
    319 
    320             if (picker.options.orientation === 'left') {
    321                 picker.widget.addClass('left-oriented');
    322                 offset.left = offset.left - picker.widget.width() + 20;
    323             }
    324 
    325             if (isInFixed()) {
    326                 position = 'fixed';
    327                 offset.top -= $window.scrollTop();
    328                 offset.left -= $window.scrollLeft();
    329             }
    330 
    331             if ($window.width() < offset.left + picker.widget.outerWidth()) {
    332                 offset.right = $window.width() - offset.left - picker.width;
    333                 offset.left = 'auto';
    334                 picker.widget.addClass('pull-right');
    335             } else {
    336                 offset.right = 'auto';
    337                 picker.widget.removeClass('pull-right');
    338             }
    339 
    340             if (placePosition === 'top') {
    341                 picker.widget.css({
    342                     position: position,
    343                     bottom: offset.bottom,
    344                     top: 'auto',
    345                     left: offset.left,
    346                     right: offset.right
    347                 });
    348             } else {
    349                 picker.widget.css({
    350                     position: position,
    351                     top: offset.top,
    352                     bottom: 'auto',
    353                     left: offset.left,
    354                     right: offset.right
    355                 });
    356             }
    357         },
    358 
    359         notifyChange = function (oldDate, eventType) {
    360             if (moment(picker.date).isSame(moment(oldDate)) && !errored) {
    361                 return;
    362             }
    363             errored = false;
    364             picker.element.trigger({
    365                 type: 'dp.change',
    366                 date: moment(picker.date),
    367                 oldDate: moment(oldDate)
    368             });
    369 
    370             if (eventType !== 'change') {
    371                 picker.element.change();
    372             }
    373         },
    374 
    375         notifyError = function (date) {
    376             errored = true;
    377             picker.element.trigger({
    378                 type: 'dp.error',
    379                 date: moment(date, picker.format, picker.options.useStrict)
    380             });
    381         },
    382 
    383         update = function (newDate) {
    384             moment.locale(picker.options.language);
    385             var dateStr = newDate;
    386             if (!dateStr) {
    387                 dateStr = getPickerInput().val();
    388                 if (dateStr) {
    389                     picker.date = moment(dateStr, picker.format, picker.options.useStrict);
    390                 }
    391                 if (!picker.date) {
    392                     picker.date = moment();
    393                 }
    394             }
    395             picker.viewDate = moment(picker.date).startOf('month');
    396             fillDate();
    397             fillTime();
    398         },
    399 
    400         fillDow = function () {
    401             moment.locale(picker.options.language);
    402             var html = $('<tr>'), weekdaysMin = moment.weekdaysMin(), i;
    403             if (picker.options.calendarWeeks === true) {
    404                 html.append('<th class="cw">#</th>');
    405             }
    406             if (moment().localeData()._week.dow === 0) { // starts on Sunday
    407                 for (i = 0; i < 7; i++) {
    408                     html.append('<th class="dow">' + weekdaysMin[i] + '</th>');
    409                 }
    410             } else {
    411                 for (i = 1; i < 8; i++) {
    412                     if (i === 7) {
    413                         html.append('<th class="dow">' + weekdaysMin[0] + '</th>');
    414                     } else {
    415                         html.append('<th class="dow">' + weekdaysMin[i] + '</th>');
    416                     }
    417                 }
    418             }
    419             picker.widget.find('.datepicker-days thead').append(html);
    420         },
    421 
    422         fillMonths = function () {
    423             moment.locale(picker.options.language);
    424             var html = '', i, monthsShort = moment.monthsShort();
    425             for (i = 0; i < 12; i++) {
    426                 html += '<span class="month">' + monthsShort[i] + '</span>';
    427             }
    428             picker.widget.find('.datepicker-months td').append(html);
    429         },
    430 
    431         fillDate = function () {
    432             if (!picker.options.pickDate) {
    433                 return;
    434             }
    435             moment.locale(picker.options.language);
    436             var year = picker.viewDate.year(),
    437                 month = picker.viewDate.month(),
    438                 startYear = picker.options.minDate.year(),
    439                 startMonth = picker.options.minDate.month(),
    440                 endYear = picker.options.maxDate.year(),
    441                 endMonth = picker.options.maxDate.month(),
    442                 currentDate,
    443                 prevMonth, nextMonth, html = [], row, clsName, i, days, yearCont, currentYear, months = moment.months();
    444 
    445             picker.widget.find('.datepicker-days').find('.disabled').removeClass('disabled');
    446             picker.widget.find('.datepicker-months').find('.disabled').removeClass('disabled');
    447             picker.widget.find('.datepicker-years').find('.disabled').removeClass('disabled');
    448 
    449             picker.widget.find('.datepicker-days th:eq(1)').text(
    450                 months[month] + ' ' + year);
    451 
    452             prevMonth = moment(picker.viewDate, picker.format, picker.options.useStrict).subtract(1, 'months');
    453             days = prevMonth.daysInMonth();
    454             prevMonth.date(days).startOf('week');
    455             if ((year === startYear && month <= startMonth) || year < startYear) {
    456                 picker.widget.find('.datepicker-days th:eq(0)').addClass('disabled');
    457             }
    458             if ((year === endYear && month >= endMonth) || year > endYear) {
    459                 picker.widget.find('.datepicker-days th:eq(2)').addClass('disabled');
    460             }
    461 
    462             nextMonth = moment(prevMonth).add(42, 'd');
    463             while (prevMonth.isBefore(nextMonth)) {
    464                 if (prevMonth.weekday() === moment().startOf('week').weekday()) {
    465                     row = $('<tr>');
    466                     html.push(row);
    467                     if (picker.options.calendarWeeks === true) {
    468                         row.append('<td class="cw">' + prevMonth.week() + '</td>');
    469                     }
    470                 }
    471                 clsName = '';
    472                 if (prevMonth.year() < year || (prevMonth.year() === year && prevMonth.month() < month)) {
    473                     clsName += ' old';
    474                 } else if (prevMonth.year() > year || (prevMonth.year() === year && prevMonth.month() > month)) {
    475                     clsName += ' new';
    476                 }
    477                 if (prevMonth.isSame(moment({y: picker.date.year(), M: picker.date.month(), d: picker.date.date()}))) {
    478                     clsName += ' active';
    479                 }
    480                 if (isInDisableDates(prevMonth, 'day') || !isInEnableDates(prevMonth)) {
    481                     clsName += ' disabled';
    482                 }
    483                 if (picker.options.showToday === true) {
    484                     if (prevMonth.isSame(moment(), 'day')) {
    485                         clsName += ' today';
    486                     }
    487                 }
    488                 if (picker.options.daysOfWeekDisabled) {
    489                     for (i = 0; i < picker.options.daysOfWeekDisabled.length; i++) {
    490                         if (prevMonth.day() === picker.options.daysOfWeekDisabled[i]) {
    491                             clsName += ' disabled';
    492                             break;
    493                         }
    494                     }
    495                 }
    496                 row.append('<td class="day' + clsName + '">' + prevMonth.date() + '</td>');
    497 
    498                 currentDate = prevMonth.date();
    499                 prevMonth.add(1, 'd');
    500 
    501                 if (currentDate === prevMonth.date()) {
    502                     prevMonth.add(1, 'd');
    503                 }
    504             }
    505             picker.widget.find('.datepicker-days tbody').empty().append(html);
    506             currentYear = picker.date.year();
    507             months = picker.widget.find('.datepicker-months').find('th:eq(1)').text(year).end().find('span').removeClass('active');
    508             if (currentYear === year) {
    509                 months.eq(picker.date.month()).addClass('active');
    510             }
    511             if (year - 1 < startYear) {
    512                 picker.widget.find('.datepicker-months th:eq(0)').addClass('disabled');
    513             }
    514             if (year + 1 > endYear) {
    515                 picker.widget.find('.datepicker-months th:eq(2)').addClass('disabled');
    516             }
    517             for (i = 0; i < 12; i++) {
    518                 if ((year === startYear && startMonth > i) || (year < startYear)) {
    519                     $(months[i]).addClass('disabled');
    520                 } else if ((year === endYear && endMonth < i) || (year > endYear)) {
    521                     $(months[i]).addClass('disabled');
    522                 }
    523             }
    524 
    525             html = '';
    526             year = parseInt(year / 10, 10) * 10;
    527             yearCont = picker.widget.find('.datepicker-years').find(
    528                 'th:eq(1)').text(year + '-' + (year + 9)).parents('table').find('td');
    529             picker.widget.find('.datepicker-years').find('th').removeClass('disabled');
    530             if (startYear > year) {
    531                 picker.widget.find('.datepicker-years').find('th:eq(0)').addClass('disabled');
    532             }
    533             if (endYear < year + 9) {
    534                 picker.widget.find('.datepicker-years').find('th:eq(2)').addClass('disabled');
    535             }
    536             year -= 1;
    537             for (i = -1; i < 11; i++) {
    538                 html += '<span class="year' + (i === -1 || i === 10 ? ' old' : '') + (currentYear === year ? ' active' : '') + ((year < startYear || year > endYear) ? ' disabled' : '') + '">' + year + '</span>';
    539                 year += 1;
    540             }
    541             yearCont.html(html);
    542         },
    543 
    544         fillHours = function () {
    545             moment.locale(picker.options.language);
    546             var table = picker.widget.find('.timepicker .timepicker-hours table'), html = '', current, i, j;
    547             table.parent().hide();
    548             if (picker.use24hours) {
    549                 current = 0;
    550                 for (i = 0; i < 6; i += 1) {
    551                     html += '<tr>';
    552                     for (j = 0; j < 4; j += 1) {
    553                         html += '<td class="hour">' + padLeft(current.toString()) + '</td>';
    554                         current++;
    555                     }
    556                     html += '</tr>';
    557                 }
    558             }
    559             else {
    560                 current = 1;
    561                 for (i = 0; i < 3; i += 1) {
    562                     html += '<tr>';
    563                     for (j = 0; j < 4; j += 1) {
    564                         html += '<td class="hour">' + padLeft(current.toString()) + '</td>';
    565                         current++;
    566                     }
    567                     html += '</tr>';
    568                 }
    569             }
    570             table.html(html);
    571         },
    572 
    573         fillMinutes = function () {
    574             var table = picker.widget.find('.timepicker .timepicker-minutes table'), html = '', current = 0, i, j, step = picker.options.minuteStepping;
    575             table.parent().hide();
    576             if (step === 1)  {
    577                 step = 5;
    578             }
    579             for (i = 0; i < Math.ceil(60 / step / 4) ; i++) {
    580                 html += '<tr>';
    581                 for (j = 0; j < 4; j += 1) {
    582                     if (current < 60) {
    583                         html += '<td class="minute">' + padLeft(current.toString()) + '</td>';
    584                         current += step;
    585                     } else {
    586                         html += '<td></td>';
    587                     }
    588                 }
    589                 html += '</tr>';
    590             }
    591             table.html(html);
    592         },
    593 
    594         fillSeconds = function () {
    595             var table = picker.widget.find('.timepicker .timepicker-seconds table'), html = '', current = 0, i, j;
    596             table.parent().hide();
    597             for (i = 0; i < 3; i++) {
    598                 html += '<tr>';
    599                 for (j = 0; j < 4; j += 1) {
    600                     html += '<td class="second">' + padLeft(current.toString()) + '</td>';
    601                     current += 5;
    602                 }
    603                 html += '</tr>';
    604             }
    605             table.html(html);
    606         },
    607 
    608         fillTime = function () {
    609             if (!picker.date) {
    610                 return;
    611             }
    612             var timeComponents = picker.widget.find('.timepicker span[data-time-component]'),
    613                 hour = picker.date.hours(),
    614                 period = picker.date.format('A');
    615             if (!picker.use24hours) {
    616                 if (hour === 0) {
    617                     hour = 12;
    618                 } else if (hour !== 12) {
    619                     hour = hour % 12;
    620                 }
    621                 picker.widget.find('.timepicker [data-action=togglePeriod]').text(period);
    622             }
    623             timeComponents.filter('[data-time-component=hours]').text(padLeft(hour));
    624             timeComponents.filter('[data-time-component=minutes]').text(padLeft(picker.date.minutes()));
    625             timeComponents.filter('[data-time-component=seconds]').text(padLeft(picker.date.second()));
    626         },
    627 
    628         click = function (e) {
    629             e.stopPropagation();
    630             e.preventDefault();
    631             picker.unset = false;
    632             var target = $(e.target).closest('span, td, th'), month, year, step, day, oldDate = moment(picker.date);
    633             if (target.length === 1) {
    634                 if (!target.is('.disabled')) {
    635                     switch (target[0].nodeName.toLowerCase()) {
    636                         case 'th':
    637                             switch (target[0].className) {
    638                                 case 'picker-switch':
    639                                     showMode(1);
    640                                     break;
    641                                 case 'prev':
    642                                 case 'next':
    643                                     step = dpGlobal.modes[picker.viewMode].navStep;
    644                                     if (target[0].className === 'prev') {
    645                                         step = step * -1;
    646                                     }
    647                                     picker.viewDate.add(step, dpGlobal.modes[picker.viewMode].navFnc);
    648                                     fillDate();
    649                                     break;
    650                             }
    651                             break;
    652                         case 'span':
    653                             if (target.is('.month')) {
    654                                 month = target.parent().find('span').index(target);
    655                                 picker.viewDate.month(month);
    656                             } else {
    657                                 year = parseInt(target.text(), 10) || 0;
    658                                 picker.viewDate.year(year);
    659                             }
    660                             if (picker.viewMode === picker.minViewMode) {
    661                                 picker.date = moment({
    662                                     y: picker.viewDate.year(),
    663                                     M: picker.viewDate.month(),
    664                                     d: picker.viewDate.date(),
    665                                     h: picker.date.hours(),
    666                                     m: picker.date.minutes(),
    667                                     s: picker.date.seconds()
    668                                 });
    669                                 set();
    670                                 notifyChange(oldDate, e.type);
    671                             }
    672                             showMode(-1);
    673                             fillDate();
    674                             break;
    675                         case 'td':
    676                             if (target.is('.day')) {
    677                                 day = parseInt(target.text(), 10) || 1;
    678                                 month = picker.viewDate.month();
    679                                 year = picker.viewDate.year();
    680                                 if (target.is('.old')) {
    681                                     if (month === 0) {
    682                                         month = 11;
    683                                         year -= 1;
    684                                     } else {
    685                                         month -= 1;
    686                                     }
    687                                 } else if (target.is('.new')) {
    688                                     if (month === 11) {
    689                                         month = 0;
    690                                         year += 1;
    691                                     } else {
    692                                         month += 1;
    693                                     }
    694                                 }
    695                                 picker.date = moment({
    696                                     y: year,
    697                                     M: month,
    698                                     d: day,
    699                                     h: picker.date.hours(),
    700                                     m: picker.date.minutes(),
    701                                     s: picker.date.seconds()
    702                                 }
    703                                 );
    704                                 picker.viewDate = moment({
    705                                     y: year, M: month, d: Math.min(28, day)
    706                                 });
    707                                 fillDate();
    708                                 set();
    709                                 notifyChange(oldDate, e.type);
    710                             }
    711                             break;
    712                     }
    713                 }
    714             }
    715         },
    716 
    717         actions = {
    718             incrementHours: function () {
    719                 checkDate('add', 'hours', 1);
    720             },
    721 
    722             incrementMinutes: function () {
    723                 checkDate('add', 'minutes', picker.options.minuteStepping);
    724             },
    725 
    726             incrementSeconds: function () {
    727                 checkDate('add', 'seconds', 1);
    728             },
    729 
    730             decrementHours: function () {
    731                 checkDate('subtract', 'hours', 1);
    732             },
    733 
    734             decrementMinutes: function () {
    735                 checkDate('subtract', 'minutes', picker.options.minuteStepping);
    736             },
    737 
    738             decrementSeconds: function () {
    739                 checkDate('subtract', 'seconds', 1);
    740             },
    741 
    742             togglePeriod: function () {
    743                 var hour = picker.date.hours();
    744                 if (hour >= 12) {
    745                     hour -= 12;
    746                 } else {
    747                     hour += 12;
    748                 }
    749                 picker.date.hours(hour);
    750             },
    751 
    752             showPicker: function () {
    753                 picker.widget.find('.timepicker > div:not(.timepicker-picker)').hide();
    754                 picker.widget.find('.timepicker .timepicker-picker').show();
    755             },
    756 
    757             showHours: function () {
    758                 picker.widget.find('.timepicker .timepicker-picker').hide();
    759                 picker.widget.find('.timepicker .timepicker-hours').show();
    760             },
    761 
    762             showMinutes: function () {
    763                 picker.widget.find('.timepicker .timepicker-picker').hide();
    764                 picker.widget.find('.timepicker .timepicker-minutes').show();
    765             },
    766 
    767             showSeconds: function () {
    768                 picker.widget.find('.timepicker .timepicker-picker').hide();
    769                 picker.widget.find('.timepicker .timepicker-seconds').show();
    770             },
    771 
    772             selectHour: function (e) {
    773                 var hour = parseInt($(e.target).text(), 10);
    774                 if (!picker.use24hours) {
    775                     if (picker.date.hours() >= 12) {
    776                         if (hour !== 12) {
    777                             hour += 12;
    778                         }
    779                     } else {
    780                         if (hour === 12) {
    781                             hour = 0;
    782                         }
    783                     }
    784                 }
    785                 picker.date.hours(hour);
    786                 actions.showPicker.call(picker);
    787             },
    788 
    789             selectMinute: function (e) {
    790                 picker.date.minutes(parseInt($(e.target).text(), 10));
    791                 actions.showPicker.call(picker);
    792             },
    793 
    794             selectSecond: function (e) {
    795                 picker.date.seconds(parseInt($(e.target).text(), 10));
    796                 actions.showPicker.call(picker);
    797             }
    798         },
    799 
    800         doAction = function (e) {
    801             var oldDate = moment(picker.date),
    802                 action = $(e.currentTarget).data('action'),
    803                 rv = actions[action].apply(picker, arguments);
    804             stopEvent(e);
    805             if (!picker.date) {
    806                 picker.date = moment({y: 1970});
    807             }
    808             set();
    809             fillTime();
    810             notifyChange(oldDate, e.type);
    811             return rv;
    812         },
    813 
    814         stopEvent = function (e) {
    815             e.stopPropagation();
    816             e.preventDefault();
    817         },
    818 
    819         keydown = function (e) {
    820             if (e.keyCode === 27) { // allow escape to hide picker
    821                 picker.hide();
    822             }
    823         },
    824 
    825         change = function (e) {
    826             moment.locale(picker.options.language);
    827             var input = $(e.target), oldDate = moment(picker.date), newDate = moment(input.val(), picker.format, picker.options.useStrict);
    828             if (newDate.isValid() && !isInDisableDates(newDate) && isInEnableDates(newDate)) {
    829                 update();
    830                 picker.setValue(newDate);
    831                 notifyChange(oldDate, e.type);
    832                 set();
    833             }
    834             else {
    835                 picker.viewDate = oldDate;
    836                 picker.unset = true;
    837                 notifyChange(oldDate, e.type);
    838                 notifyError(newDate);
    839             }
    840         },
    841 
    842         showMode = function (dir) {
    843             if (dir) {
    844                 picker.viewMode = Math.max(picker.minViewMode, Math.min(2, picker.viewMode + dir));
    845             }
    846             picker.widget.find('.datepicker > div').hide().filter('.datepicker-' + dpGlobal.modes[picker.viewMode].clsName).show();
    847         },
    848 
    849         attachDatePickerEvents = function () {
    850             var $this, $parent, expanded, closed, collapseData;
    851             picker.widget.on('click', '.datepicker *', $.proxy(click, this)); // this handles date picker clicks
    852             picker.widget.on('click', '[data-action]', $.proxy(doAction, this)); // this handles time picker clicks
    853             picker.widget.on('mousedown', $.proxy(stopEvent, this));
    854             picker.element.on('keydown', $.proxy(keydown, this));
    855             if (picker.options.pickDate && picker.options.pickTime) {
    856                 picker.widget.on('click.togglePicker', '.accordion-toggle', function (e) {
    857                     e.stopPropagation();
    858                     $this = $(this);
    859                     $parent = $this.closest('ul');
    860                     expanded = $parent.find('.in');
    861                     closed = $parent.find('.collapse:not(.in)');
    862 
    863                     if (expanded && expanded.length) {
    864                         collapseData = expanded.data('collapse');
    865                         if (collapseData && collapseData.transitioning) {
    866                             return;
    867                         }
    868                         expanded.collapse('hide');
    869                         closed.collapse('show');
    870                         $this.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date);
    871                         if (picker.component) {
    872                             picker.component.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date);
    873                         }
    874                     }
    875                 });
    876             }
    877             if (picker.isInput) {
    878                 picker.element.on({
    879                     'click': $.proxy(picker.show, this),
    880                     'focus': $.proxy(picker.show, this),
    881                     'change': $.proxy(change, this),
    882                     'blur': $.proxy(picker.hide, this)
    883                 });
    884             } else {
    885                 picker.element.on({
    886                     'change': $.proxy(change, this)
    887                 }, 'input');
    888                 if (picker.component) {
    889                     picker.component.on('click', $.proxy(picker.show, this));
    890                     picker.component.on('mousedown', $.proxy(stopEvent, this));
    891                 } else {
    892                     picker.element.on('click', $.proxy(picker.show, this));
    893                 }
    894             }
    895         },
    896 
    897         attachDatePickerGlobalEvents = function () {
    898             $(window).on(
    899                 'resize.datetimepicker' + picker.id, $.proxy(place, this));
    900             if (!picker.isInput) {
    901                 $(document).on(
    902                     'mousedown.datetimepicker' + picker.id, $.proxy(picker.hide, this));
    903             }
    904         },
    905 
    906         detachDatePickerEvents = function () {
    907             picker.widget.off('click', '.datepicker *', picker.click);
    908             picker.widget.off('click', '[data-action]');
    909             picker.widget.off('mousedown', picker.stopEvent);
    910             if (picker.options.pickDate && picker.options.pickTime) {
    911                 picker.widget.off('click.togglePicker');
    912             }
    913             if (picker.isInput) {
    914                 picker.element.off({
    915                     'focus': picker.show,
    916                     'change': change,
    917                     'click': picker.show,
    918                     'blur' : picker.hide
    919                 });
    920             } else {
    921                 picker.element.off({
    922                     'change': change
    923                 }, 'input');
    924                 if (picker.component) {
    925                     picker.component.off('click', picker.show);
    926                     picker.component.off('mousedown', picker.stopEvent);
    927                 } else {
    928                     picker.element.off('click', picker.show);
    929                 }
    930             }
    931         },
    932 
    933         detachDatePickerGlobalEvents = function () {
    934             $(window).off('resize.datetimepicker' + picker.id);
    935             if (!picker.isInput) {
    936                 $(document).off('mousedown.datetimepicker' + picker.id);
    937             }
    938         },
    939 
    940         isInFixed = function () {
    941             if (picker.element) {
    942                 var parents = picker.element.parents(), inFixed = false, i;
    943                 for (i = 0; i < parents.length; i++) {
    944                     if ($(parents[i]).css('position') === 'fixed') {
    945                         inFixed = true;
    946                         break;
    947                     }
    948                 }
    949                 return inFixed;
    950             } else {
    951                 return false;
    952             }
    953         },
    954 
    955         set = function () {
    956             moment.locale(picker.options.language);
    957             var formatted = '';
    958             if (!picker.unset) {
    959                 formatted = moment(picker.date).format(picker.format);
    960             }
    961             getPickerInput().val(formatted);
    962             picker.element.data('date', formatted);
    963             if (!picker.options.pickTime) {
    964                 picker.hide();
    965             }
    966         },
    967 
    968         checkDate = function (direction, unit, amount) {
    969             moment.locale(picker.options.language);
    970             var newDate;
    971             if (direction === 'add') {
    972                 newDate = moment(picker.date);
    973                 if (newDate.hours() === 23) {
    974                     newDate.add(amount, unit);
    975                 }
    976                 newDate.add(amount, unit);
    977             }
    978             else {
    979                 newDate = moment(picker.date).subtract(amount, unit);
    980             }
    981             if (isInDisableDates(moment(newDate.subtract(amount, unit))) || isInDisableDates(newDate)) {
    982                 notifyError(newDate.format(picker.format));
    983                 return;
    984             }
    985 
    986             if (direction === 'add') {
    987                 picker.date.add(amount, unit);
    988             }
    989             else {
    990                 picker.date.subtract(amount, unit);
    991             }
    992             picker.unset = false;
    993         },
    994 
    995         isInDisableDates = function (date, timeUnit) {
    996             moment.locale(picker.options.language);
    997             var maxDate = moment(picker.options.maxDate, picker.format, picker.options.useStrict),
    998                 minDate = moment(picker.options.minDate, picker.format, picker.options.useStrict);
    999 
   1000             if (timeUnit) {
   1001                 maxDate = maxDate.endOf(timeUnit);
   1002                 minDate = minDate.startOf(timeUnit);
   1003             }
   1004 
   1005             if (date.isAfter(maxDate) || date.isBefore(minDate)) {
   1006                 return true;
   1007             }
   1008             if (picker.options.disabledDates === false) {
   1009                 return false;
   1010             }
   1011             return picker.options.disabledDates[date.format('YYYY-MM-DD')] === true;
   1012         },
   1013         isInEnableDates = function (date) {
   1014             moment.locale(picker.options.language);
   1015             if (picker.options.enabledDates === false) {
   1016                 return true;
   1017             }
   1018             return picker.options.enabledDates[date.format('YYYY-MM-DD')] === true;
   1019         },
   1020 
   1021         indexGivenDates = function (givenDatesArray) {
   1022             // Store given enabledDates and disabledDates as keys.
   1023             // This way we can check their existence in O(1) time instead of looping through whole array.
   1024             // (for example: picker.options.enabledDates['2014-02-27'] === true)
   1025             var givenDatesIndexed = {}, givenDatesCount = 0, i;
   1026             for (i = 0; i < givenDatesArray.length; i++) {
   1027                 if (moment.isMoment(givenDatesArray[i]) || givenDatesArray[i] instanceof Date) {
   1028                     dDate = moment(givenDatesArray[i]);
   1029                 } else {
   1030                     dDate = moment(givenDatesArray[i], picker.format, picker.options.useStrict);
   1031                 }
   1032                 if (dDate.isValid()) {
   1033                     givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
   1034                     givenDatesCount++;
   1035                 }
   1036             }
   1037             if (givenDatesCount > 0) {
   1038                 return givenDatesIndexed;
   1039             }
   1040             return false;
   1041         },
   1042 
   1043         padLeft = function (string) {
   1044             string = string.toString();
   1045             if (string.length >= 2) {
   1046                 return string;
   1047             }
   1048             return '0' + string;
   1049         },
   1050 
   1051         getTemplate = function () {
   1052             var
   1053                 headTemplate =
   1054                         '<thead>' +
   1055                             '<tr>' +
   1056                                 '<th class="prev">&lsaquo;</th><th colspan="' + (picker.options.calendarWeeks ? '6' : '5') + '" class="picker-switch"></th><th class="next">&rsaquo;</th>' +
   1057                             '</tr>' +
   1058                         '</thead>',
   1059                 contTemplate =
   1060                         '<tbody><tr><td colspan="' + (picker.options.calendarWeeks ? '8' : '7') + '"></td></tr></tbody>',
   1061                 template = '<div class="datepicker-days">' +
   1062                     '<table class="table-condensed">' + headTemplate + '<tbody></tbody></table>' +
   1063                 '</div>' +
   1064                 '<div class="datepicker-months">' +
   1065                     '<table class="table-condensed">' + headTemplate + contTemplate + '</table>' +
   1066                 '</div>' +
   1067                 '<div class="datepicker-years">' +
   1068                     '<table class="table-condensed">' + headTemplate + contTemplate + '</table>' +
   1069                 '</div>',
   1070                 ret = '';
   1071             if (picker.options.pickDate && picker.options.pickTime) {
   1072                 ret = '<div class="bootstrap-datetimepicker-widget' + (picker.options.sideBySide ? ' timepicker-sbs' : '') + (picker.use24hours ? ' usetwentyfour' : '') + ' dropdown-menu" style="z-index:9999 !important;">';
   1073                 if (picker.options.sideBySide) {
   1074                     ret += '<div class="row">' +
   1075                        '<div class="col-sm-6 datepicker">' + template + '</div>' +
   1076                        '<div class="col-sm-6 timepicker">' + tpGlobal.getTemplate() + '</div>' +
   1077                      '</div>';
   1078                 } else {
   1079                     ret += '<ul class="list-unstyled">' +
   1080                         '<li' + (picker.options.collapse ? ' class="collapse in"' : '') + '>' +
   1081                             '<div class="datepicker">' + template + '</div>' +
   1082                         '</li>' +
   1083                         '<li class="picker-switch accordion-toggle"><a class="btn" style="width:100%"><span class="' + picker.options.icons.time + '"></span></a></li>' +
   1084                         '<li' + (picker.options.collapse ? ' class="collapse"' : '') + '>' +
   1085                             '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' +
   1086                         '</li>' +
   1087                    '</ul>';
   1088                 }
   1089                 ret += '</div>';
   1090                 return ret;
   1091             }
   1092             if (picker.options.pickTime) {
   1093                 return (
   1094                     '<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
   1095                         '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' +
   1096                     '</div>'
   1097                 );
   1098             }
   1099             return (
   1100                 '<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
   1101                     '<div class="datepicker">' + template + '</div>' +
   1102                 '</div>'
   1103             );
   1104         },
   1105 
   1106         dpGlobal = {
   1107             modes: [
   1108                 {
   1109                     clsName: 'days',
   1110                     navFnc: 'month',
   1111                     navStep: 1
   1112                 },
   1113                 {
   1114                     clsName: 'months',
   1115                     navFnc: 'year',
   1116                     navStep: 1
   1117                 },
   1118                 {
   1119                     clsName: 'years',
   1120                     navFnc: 'year',
   1121                     navStep: 10
   1122                 }
   1123             ]
   1124         },
   1125 
   1126         tpGlobal = {
   1127             hourTemplate: '<span data-action="showHours"   data-time-component="hours"   class="timepicker-hour"></span>',
   1128             minuteTemplate: '<span data-action="showMinutes" data-time-component="minutes" class="timepicker-minute"></span>',
   1129             secondTemplate: '<span data-action="showSeconds"  data-time-component="seconds" class="timepicker-second"></span>'
   1130         };
   1131 
   1132         tpGlobal.getTemplate = function () {
   1133             return (
   1134                 '<div class="timepicker-picker">' +
   1135                     '<table class="table-condensed">' +
   1136                         '<tr>' +
   1137                             '<td><a href="#" class="btn" data-action="incrementHours"><span class="' + picker.options.icons.up + '"></span></a></td>' +
   1138                             '<td class="separator"></td>' +
   1139                             '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="incrementMinutes"><span class="' + picker.options.icons.up + '"></span></a>' : '') + '</td>' +
   1140                             (picker.options.useSeconds ?
   1141                                 '<td class="separator"></td><td><a href="#" class="btn" data-action="incrementSeconds"><span class="' + picker.options.icons.up + '"></span></a></td>' : '') +
   1142                             (picker.use24hours ? '' : '<td class="separator"></td>') +
   1143                         '</tr>' +
   1144                         '<tr>' +
   1145                             '<td>' + tpGlobal.hourTemplate + '</td> ' +
   1146                             '<td class="separator">:</td>' +
   1147                             '<td>' + (picker.options.useMinutes ? tpGlobal.minuteTemplate : '<span class="timepicker-minute">00</span>') + '</td> ' +
   1148                             (picker.options.useSeconds ?
   1149                                 '<td class="separator">:</td><td>' + tpGlobal.secondTemplate + '</td>' : '') +
   1150                             (picker.use24hours ? '' : '<td class="separator"></td>' +
   1151                             '<td><button type="button" class="btn btn-primary" data-action="togglePeriod"></button></td>') +
   1152                         '</tr>' +
   1153                         '<tr>' +
   1154                             '<td><a href="#" class="btn" data-action="decrementHours"><span class="' + picker.options.icons.down + '"></span></a></td>' +
   1155                             '<td class="separator"></td>' +
   1156                             '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="decrementMinutes"><span class="' + picker.options.icons.down + '"></span></a>' : '') + '</td>' +
   1157                             (picker.options.useSeconds ?
   1158                                 '<td class="separator"></td><td><a href="#" class="btn" data-action="decrementSeconds"><span class="' + picker.options.icons.down + '"></span></a></td>' : '') +
   1159                             (picker.use24hours ? '' : '<td class="separator"></td>') +
   1160                         '</tr>' +
   1161                     '</table>' +
   1162                 '</div>' +
   1163                 '<div class="timepicker-hours" data-action="selectHour">' +
   1164                     '<table class="table-condensed"></table>' +
   1165                 '</div>' +
   1166                 '<div class="timepicker-minutes" data-action="selectMinute">' +
   1167                     '<table class="table-condensed"></table>' +
   1168                 '</div>' +
   1169                 (picker.options.useSeconds ?
   1170                     '<div class="timepicker-seconds" data-action="selectSecond"><table class="table-condensed"></table></div>' : '')
   1171             );
   1172         };
   1173 
   1174         picker.destroy = function () {
   1175             detachDatePickerEvents();
   1176             detachDatePickerGlobalEvents();
   1177             picker.widget.remove();
   1178             picker.element.removeData('DateTimePicker');
   1179             if (picker.component) {
   1180                 picker.component.removeData('DateTimePicker');
   1181             }
   1182         };
   1183 
   1184         picker.show = function (e) {
   1185             if (getPickerInput().prop('disabled')) {
   1186                 return;
   1187             }
   1188             if (picker.options.useCurrent) {
   1189                 if (getPickerInput().val() === '') {
   1190                     if (picker.options.minuteStepping !== 1) {
   1191                         var mDate = moment(),
   1192                         rInterval = picker.options.minuteStepping;
   1193                         mDate.minutes((Math.round(mDate.minutes() / rInterval) * rInterval) % 60).seconds(0);
   1194                         picker.setValue(mDate.format(picker.format));
   1195                     } else {
   1196                         picker.setValue(moment().format(picker.format));
   1197                     }
   1198                     notifyChange('', e.type);
   1199                 }
   1200             }
   1201             // if this is a click event on the input field and picker is already open don't hide it
   1202             if (e && e.type === 'click' && picker.isInput && picker.widget.hasClass('picker-open')) {
   1203                 return;
   1204             }
   1205             if (picker.widget.hasClass('picker-open')) {
   1206                 picker.widget.hide();
   1207                 picker.widget.removeClass('picker-open');
   1208             }
   1209             else {
   1210                 picker.widget.show();
   1211                 picker.widget.addClass('picker-open');
   1212             }
   1213             picker.height = picker.component ? picker.component.outerHeight() : picker.element.outerHeight();
   1214             place();
   1215             picker.element.trigger({
   1216                 type: 'dp.show',
   1217                 date: moment(picker.date)
   1218             });
   1219             attachDatePickerGlobalEvents();
   1220             if (e) {
   1221                 stopEvent(e);
   1222             }
   1223         };
   1224 
   1225         picker.disable = function () {
   1226             var input = getPickerInput();
   1227             if (input.prop('disabled')) {
   1228                 return;
   1229             }
   1230             input.prop('disabled', true);
   1231             detachDatePickerEvents();
   1232         };
   1233 
   1234         picker.enable = function () {
   1235             var input = getPickerInput();
   1236             if (!input.prop('disabled')) {
   1237                 return;
   1238             }
   1239             input.prop('disabled', false);
   1240             attachDatePickerEvents();
   1241         };
   1242 
   1243         picker.hide = function () {
   1244             // Ignore event if in the middle of a picker transition
   1245             var collapse = picker.widget.find('.collapse'), i, collapseData;
   1246             for (i = 0; i < collapse.length; i++) {
   1247                 collapseData = collapse.eq(i).data('collapse');
   1248                 if (collapseData && collapseData.transitioning) {
   1249                     return;
   1250                 }
   1251             }
   1252             picker.widget.hide();
   1253             picker.widget.removeClass('picker-open');
   1254             picker.viewMode = picker.startViewMode;
   1255             showMode();
   1256             picker.element.trigger({
   1257                 type: 'dp.hide',
   1258                 date: moment(picker.date)
   1259             });
   1260             detachDatePickerGlobalEvents();
   1261         };
   1262 
   1263         picker.setValue = function (newDate) {
   1264             moment.locale(picker.options.language);
   1265             if (!newDate) {
   1266                 picker.unset = true;
   1267                 set();
   1268             } else {
   1269                 picker.unset = false;
   1270             }
   1271             if (!moment.isMoment(newDate)) {
   1272                 newDate = (newDate instanceof Date) ? moment(newDate) : moment(newDate, picker.format, picker.options.useStrict);
   1273             } else {
   1274                 newDate = newDate.locale(picker.options.language);
   1275             }
   1276             if (newDate.isValid()) {
   1277                 picker.date = newDate;
   1278                 set();
   1279                 picker.viewDate = moment({y: picker.date.year(), M: picker.date.month()});
   1280                 fillDate();
   1281                 fillTime();
   1282             }
   1283             else {
   1284                 notifyError(newDate);
   1285             }
   1286         };
   1287 
   1288         picker.getDate = function () {
   1289             if (picker.unset) {
   1290                 return null;
   1291             }
   1292             return moment(picker.date);
   1293         };
   1294 
   1295         picker.setDate = function (date) {
   1296             var oldDate = moment(picker.date);
   1297             if (!date) {
   1298                 picker.setValue(null);
   1299             } else {
   1300                 picker.setValue(date);
   1301             }
   1302             notifyChange(oldDate, 'function');
   1303         };
   1304 
   1305         picker.setDisabledDates = function (dates) {
   1306             picker.options.disabledDates = indexGivenDates(dates);
   1307             if (picker.viewDate) {
   1308                 update();
   1309             }
   1310         };
   1311 
   1312         picker.setEnabledDates = function (dates) {
   1313             picker.options.enabledDates = indexGivenDates(dates);
   1314             if (picker.viewDate) {
   1315                 update();
   1316             }
   1317         };
   1318 
   1319         picker.setMaxDate = function (date) {
   1320             if (date === undefined) {
   1321                 return;
   1322             }
   1323             if (moment.isMoment(date) || date instanceof Date) {
   1324                 picker.options.maxDate = moment(date);
   1325             } else {
   1326                 picker.options.maxDate = moment(date, picker.format, picker.options.useStrict);
   1327             }
   1328             if (picker.viewDate) {
   1329                 update();
   1330             }
   1331         };
   1332 
   1333         picker.setMinDate = function (date) {
   1334             if (date === undefined) {
   1335                 return;
   1336             }
   1337             if (moment.isMoment(date) || date instanceof Date) {
   1338                 picker.options.minDate = moment(date);
   1339             } else {
   1340                 picker.options.minDate = moment(date, picker.format, picker.options.useStrict);
   1341             }
   1342             if (picker.viewDate) {
   1343                 update();
   1344             }
   1345         };
   1346 
   1347         init();
   1348     };
   1349 
   1350     $.fn.datetimepicker = function (options) {
   1351         return this.each(function () {
   1352             var $this = $(this),
   1353                 data = $this.data('DateTimePicker');
   1354             if (!data) {
   1355                 $this.data('DateTimePicker', new DateTimePicker(this, options));
   1356             }
   1357         });
   1358     };
   1359 
   1360     $.fn.datetimepicker.defaults = {
   1361         format: false,
   1362         pickDate: true,
   1363         pickTime: true,
   1364         useMinutes: true,
   1365         useSeconds: false,
   1366         useCurrent: true,
   1367         calendarWeeks: false,
   1368         minuteStepping: 1,
   1369         minDate: moment({y: 1900}),
   1370         maxDate: moment().add(100, 'y'),
   1371         showToday: true,
   1372         collapse: true,
   1373         language: moment.locale(),
   1374         defaultDate: '',
   1375         disabledDates: false,
   1376         enabledDates: false,
   1377         icons: {},
   1378         useStrict: false,
   1379         direction: 'auto',
   1380         sideBySide: false,
   1381         daysOfWeekDisabled: [],
   1382         widgetParent: false
   1383     };
   1384 }));