PageSourceSearch

https://vestus.pl/modules/kbstorelocatorpickup/views/js/front/datetimepicker/bootstrap-datetimepicker.js

js vestus.pl collected 2026-10-08 18:38:51 UTC 82,678 bytes, 2,137 lines download raw bytes

1/**
2 * DISCLAIMER
3 *
4 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
5 * versions in the future. If you wish to customize PrestaShop for your
6 * needs please refer to http://www.prestashop.com for more information.
7 * We offer the best and most useful modules PrestaShop and modifications for your online store.
8 *
9 * @author    knowband.com <[email protected]>
10 * @copyright 2018 Knowband
11 * @license   see file: LICENSE.txt
12 * @category  PrestaShop Module
13 *
14 *
15 */
16 
17(function(factory){
18    if (typeof define === 'function' && define.amd)
19      define(['jquery'], factory);
20    else if (typeof exports === 'object')
21      factory(require('jquery'));
22    else
23      factory(jQuery);
24
25}(function($, undefined){
26
27  // Add ECMA262-5 Array methods if not supported natively (IE8)
28  if (!('indexOf' in Array.prototype)) {
29    Array.prototype.indexOf = function (find, i) {
30      if (i === undefined) i = 0;
31      if (i < 0) i += this.length;
32      if (i < 0) i = 0;
33      for (var n = this.length; i < n; i++) {
34        if (i in this && this[i] === find) {
35          return i;
36        }
37      }
38      return -1;
39    }
40  }
41
42  // Add timezone abbreviation support for ie6+, Chrome, Firefox
43  function timeZoneAbbreviation() {
44    var abbreviation, date, formattedStr, i, len, matchedStrings, ref, str;
45    date = (new Date()).toString();
46    formattedStr = ((ref = date.split('(')[1]) != null ? ref.slice(0, -1) : 0) || date.split(' ');
47    if (formattedStr instanceof Array) {
48      matchedStrings = [];
49      for (var i = 0, len = formattedStr.length; i < len; i++) {
50        str = formattedStr[i];
51        if ((abbreviation = (ref = str.match(/\b[A-Z]+\b/)) !== null) ? ref[0] : 0) {
52          matchedStrings.push(abbreviation);
53        }
54      }
55      formattedStr = matchedStrings.pop();
56    }
57    return formattedStr;
58  }
59
60  function UTCDate() {
61    return new Date(Date.UTC.apply(Date, arguments));
62  }
63
64  // Picker object
65  var Datetimepicker = function (element, options) {
66    var that = this;
67
68    this.element = $(element);
69
70    // add container for single page application
71    // when page switch the datetimepicker div will be removed also.
72    this.container = options.container || 'body';
73
74    this.language = options.language || this.element.data('date-language') || 'en';
75    this.language = this.language in dates ? this.language : this.language.split('-')[0]; // fr-CA fallback to fr
76    this.language = this.language in dates ? this.language : 'en';
77    this.isRTL = dates[this.language].rtl || false;
78    this.formatType = options.formatType || this.element.data('format-type') || 'standard';
79    this.format = DPGlobal.parseFormat(options.format || this.element.data('date-format') || dates[this.language].format || DPGlobal.getDefaultFormat(this.formatType, 'input'), this.formatType);
80    this.isInline = false;
81    this.isVisible = false;
82    this.isInput = this.element.is('input');
83    this.fontAwesome = options.fontAwesome || this.element.data('font-awesome') || false;
84
85    this.bootcssVer = options.bootcssVer || (this.isInput ? (this.element.is('.form-control') ? 3 : 2) : ( this.bootcssVer = this.element.is('.input-group') ? 3 : 2 ));
86
87    this.component = this.element.is('.date') ? ( this.bootcssVer === 3 ? this.element.find('.input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .icon-calendar, .input-group-addon .icon-clock-o').parent() : this.element.find('.add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .icon-calendar, .add-on .icon-clock-o').parent()) : false;
88    this.componentReset = this.element.is('.date') ? ( this.bootcssVer === 3 ? this.element.find('.input-group-addon .glyphicon-remove, .input-group-addon .icon-times').parent():this.element.find('.add-on .icon-remove, .add-on .icon-times').parent()) : false;
89    this.hasInput = this.component && this.element.find('input').length;
90    if (this.component && this.component.length === 0) {
91      this.component = false;
92    }
93    this.linkField = options.linkField || this.element.data('link-field') || false;
94    this.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || DPGlobal.getDefaultFormat(this.formatType, 'link'), this.formatType);
95    this.minuteStep = options.minuteStep || this.element.data('minute-step') || 5;
96    this.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'bottom-right';
97    this.showMeridian = options.showMeridian || this.element.data('show-meridian') || false;
98    this.initialDate = options.initialDate || new Date();
99    this.zIndex = options.zIndex || this.element.data('z-index') || undefined;
100    this.title = typeof options.title === 'undefined' ? false : options.title;
101    this.timezone = options.timezone || timeZoneAbbreviation();
102
103    this.icons = {
104      leftArrow: this.fontAwesome ? 'icon-arrow-left' : (this.bootcssVer === 3 ? 'glyphicon-arrow-left' : 'icon-arrow-left'),
105      rightArrow: this.fontAwesome ? 'icon-arrow-right' : (this.bootcssVer === 3 ? 'glyphicon-arrow-right' : 'icon-arrow-right')
106    }
107    this.icontype = 'fa';
108    if (!this.fontAwesome) {
109        this.icontype = 'glyphicon';
110    }
111
112    this._attachEvents();
113
114    this.clickedOutside = function (e) {
115        // Clicked outside the datetimepicker, hide it
116        if ($(e.target).closest('.datetimepicker').length === 0) {
117            that.hide();
118        }
119    }
120
121    this.formatViewType = 'datetime';
122    if ('formatViewType' in options) {
123      this.formatViewType = options.formatViewType;
124    } else if ('formatViewType' in this.element.data()) {
125      this.formatViewType = this.element.data('formatViewType');
126    }
127
128    this.minView = 0;
129    if ('minView' in options) {
130      this.minView = options.minView;
131    } else if ('minView' in this.element.data()) {
132      this.minView = this.element.data('min-view');
133    }
134    this.minView = DPGlobal.convertViewMode(this.minView);
135
136    this.maxView = DPGlobal.modes.length - 1;
137    if ('maxView' in options) {
138      this.maxView = options.maxView;
139    } else if ('maxView' in this.element.data()) {
140      this.maxView = this.element.data('max-view');
141    }
142    this.maxView = DPGlobal.convertViewMode(this.maxView);
143
144    this.wheelViewModeNavigation = false;
145    if ('wheelViewModeNavigation' in options) {
146      this.wheelViewModeNavigation = options.wheelViewModeNavigation;
147    } else if ('wheelViewModeNavigation' in this.element.data()) {
148      this.wheelViewModeNavigation = this.element.data('view-mode-wheel-navigation');
149    }
150
151    this.wheelViewModeNavigationInverseDirection = false;
152
153    if ('wheelViewModeNavigationInverseDirection' in options) {
154      this.wheelViewModeNavigationInverseDirection = options.wheelViewModeNavigationInverseDirection;
155    } else if ('wheelViewModeNavigationInverseDirection' in this.element.data()) {
156      this.wheelViewModeNavigationInverseDirection = this.element.data('view-mode-wheel-navigation-inverse-dir');
157    }
158
159    this.wheelViewModeNavigationDelay = 100;
160    if ('wheelViewModeNavigationDelay' in options) {
161      this.wheelViewModeNavigationDelay = options.wheelViewModeNavigationDelay;
162    } else if ('wheelViewModeNavigationDelay' in this.element.data()) {
163      this.wheelViewModeNavigationDelay = this.element.data('view-mode-wheel-navigation-delay');
164    }
165
166    this.startViewMode = 2;
167    if ('startView' in options) {
168      this.startViewMode = options.startView;
169    } else if ('startView' in this.element.data()) {
170      this.startViewMode = this.element.data('start-view');
171    }
172    this.startViewMode = DPGlobal.convertViewMode(this.startViewMode);
173    this.viewMode = this.startViewMode;
174
175    this.viewSelect = this.minView;
176    if ('viewSelect' in options) {
177      this.viewSelect = options.viewSelect;
178    } else if ('viewSelect' in this.element.data()) {
179      this.viewSelect = this.element.data('view-select');
180    }
181    this.viewSelect = DPGlobal.convertViewMode(this.viewSelect);
182
183    this.forceParse = true;
184    if ('forceParse' in options) {
185      this.forceParse = options.forceParse;
186    } else if ('dateForceParse' in this.element.data()) {
187      this.forceParse = this.element.data('date-force-parse');
188    }
189    var template = this.bootcssVer === 3 ? DPGlobal.templateV3 : DPGlobal.template;
190    while (template.indexOf('{iconType}') !== -1) {
191      template = template.replace('{iconType}', this.icontype);
192    }
193    while (template.indexOf('{leftArrow}') !== -1) {
194      template = template.replace('{leftArrow}', this.icons.leftArrow);
195    }
196    while (template.indexOf('{rightArrow}') !== -1) {
197      template = template.replace('{rightArrow}', this.icons.rightArrow);
198    }
199    this.picker = $(template)
200      .appendTo(this.isInline ? this.element : this.container) // 'body')
201      .on({
202        click:     $.proxy(this.click, this),
203        mousedown: $.proxy(this.mousedown, this)
204      });
205
206    if (this.wheelViewModeNavigation) {
207      if ($.fn.mousewheel) {
208        this.picker.on({mousewheel: $.proxy(this.mousewheel, this)});
209      } else {
210        console.log('Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option');
211      }
212    }
213
214    if (this.isInline) {
215      this.picker.addClass('datetimepicker-inline');
216    } else {
217      this.picker.addClass('datetimepicker-dropdown-' + this.pickerPosition + ' dropdown-menu');
218    }
219    if (this.isRTL) {
220      this.picker.addClass('datetimepicker-rtl');
221      var selector = this.bootcssVer === 3 ? '.prev span, .next span' : '.prev i, .next i';
222      this.picker.find(selector).toggleClass(this.icons.leftArrow + ' ' + this.icons.rightArrow);
223    }
224
225    $(document).on('mousedown touchend', this.clickedOutside);
226
227    this.autoclose = false;
228    if ('autoclose' in options) {
229      this.autoclose = options.autoclose;
230    } else if ('dateAutoclose' in this.element.data()) {
231      this.autoclose = this.element.data('date-autoclose');
232    }
233
234    this.keyboardNavigation = true;
235    if ('keyboardNavigation' in options) {
236      this.keyboardNavigation = options.keyboardNavigation;
237    } else if ('dateKeyboardNavigation' in this.element.data()) {
238      this.keyboardNavigation = this.element.data('date-keyboard-navigation');
239    }
240
241    this.todayBtn = (options.todayBtn || this.element.data('date-today-btn') || false);
242    this.clearBtn = (options.clearBtn || this.element.data('date-clear-btn') || false);
243    this.todayHighlight = (options.todayHighlight || this.element.data('date-today-highlight') || false);
244
245    this.weekStart = 0;
246    if (typeof options.weekStart !== 'undefined') {
247      this.weekStart = options.weekStart;
248    } else if (typeof this.element.data('date-weekstart') !== 'undefined') {
249      this.weekStart = this.element.data('date-weekstart');
250    } else if (typeof dates[this.language].weekStart !== 'undefined') {
251      this.weekStart = dates[this.language].weekStart;
252    }
253    this.weekStart = this.weekStart % 7;
254    this.weekEnd = ((this.weekStart + 6) % 7);
255    this.onRenderDay = function (date) {
256      var render = (options.onRenderDay || function () { return []; })(date);
257      if (typeof render === 'string') {
258        render = [render];
259      }
260      var res = ['day'];
261      return res.concat((render ? render : []));
262    };
263    this.onRenderHour = function (date) {
264      var render = (options.onRenderHour || function () { return []; })(date);
265      var res = ['hour'];
266      if (typeof render === 'string') {
267        render = [render];
268      }
269      return res.concat((render ? render : []));
270    };
271    this.onRenderMinute = function (date) {
272      var render = (options.onRenderMinute || function () { return []; })(date);
273      var res = ['minute'];
274      if (typeof render === 'string') {
275        render = [render];
276      }
277      if (date < this.startDate || date > this.endDate) {
278        res.push('disabled');
279      } else if (Math.floor(this.date.getUTCMinutes() / this.minuteStep) === Math.floor(date.getUTCMinutes() / this.minuteStep)) {
280        res.push('active');
281      }
282      return res.concat((render ? render : []));
283    };
284    this.onRenderYear = function (date) {
285      var render = (options.onRenderYear || function () { return []; })(date);
286      var res = ['year'];
287      if (typeof render === 'string') {
288        render = [render];
289      }
290      if (this.date.getUTCFullYear() === date.getUTCFullYear()) {
291        res.push('active');
292      }
293      var currentYear = date.getUTCFullYear();
294      var endYear = this.endDate.getUTCFullYear();
295      if (date < this.startDate || currentYear > endYear) {
296        res.push('disabled');
297      }
298      return res.concat((render ? render : []));
299    }
300    this.onRenderMonth = function (date) {
301      var render = (options.onRenderMonth || function () { return []; })(date);
302      var res = ['month'];
303      if (typeof render === 'string') {
304        render = [render];
305      }
306      return res.concat((render ? render : []));
307    }
308    this.startDate = new Date(-8639968443048000);
309    this.endDate = new Date(8639968443048000);
310    this.datesDisabled = [];
311    this.daysOfWeekDisabled = [];
312    this.setStartDate(options.startDate || this.element.data('date-startdate'));
313    this.setEndDate(options.endDate || this.element.data('date-enddate'));
314    this.setDatesDisabled(options.datesDisabled || this.element.data('date-dates-disabled'));
315    this.setDaysOfWeekDisabled(options.daysOfWeekDisabled || this.element.data('date-days-of-week-disabled'));
316    this.setMinutesDisabled(options.minutesDisabled || this.element.data('date-minute-disabled'));
317    this.setHoursDisabled(options.hoursDisabled || this.element.data('date-hour-disabled'));
318    this.fillDow();
319    this.fillMonths();
320    this.update();
321    this.showMode();
322
323    if (this.isInline) {
324      this.show();
325    }
326  };
327
328  Datetimepicker.prototype = {
329    constructor: Datetimepicker,
330
331    _events:       [],
332    _attachEvents: function () {
333      this._detachEvents();
334      if (this.isInput) { // single input
335        this._events = [
336          [this.element, {
337            focus:   $.proxy(this.show, this),
338            keyup:   $.proxy(this.update, this),
339            keydown: $.proxy(this.keydown, this)
340          }]
341        ];
342      }
343      else if (this.component && this.hasInput) { // component: input + button
344        this._events = [
345          // For components that are not readonly, allow keyboard nav
346          [this.element.find('input'), {
347            focus:   $.proxy(this.show, this),
348            keyup:   $.proxy(this.update, this),
349            keydown: $.proxy(this.keydown, this)
350          }],
351          [this.component, {
352            click: $.proxy(this.show, this)
353          }]
354        ];
355        if (this.componentReset) {
356          this._events.push([
357            this.componentReset,
358            {click: $.proxy(this.reset, this)}
359          ]);
360        }
361      }
362      else if (this.element.is('div')) {  // inline datetimepicker
363        this.isInline = true;
364      }
365      else {
366        this._events = [
367          [this.element, {
368            click: $.proxy(this.show, this)
369          }]
370        ];
371      }
372      for (var i = 0, el, ev; i < this._events.length; i++) {
373        el = this._events[i][0];
374        ev = this._events[i][1];
375        el.on(ev);
376      }
377    },
378
379    _detachEvents: function () {
380      for (var i = 0, el, ev; i < this._events.length; i++) {
381        el = this._events[i][0];
382        ev = this._events[i][1];
383        el.off(ev);
384      }
385      this._events = [];
386    },
387
388    show: function (e) {
389      this.picker.show();
390      this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
391      if (this.forceParse) {
392        this.update();
393      }
394      this.place();
395      $(window).on('resize', $.proxy(this.place, this));
396      if (e) {
397        e.stopPropagation();
398        e.preventDefault();
399      }
400      this.isVisi
400ble = true;
401      this.element.trigger({
402        type: 'show',
403        date: this.date
404      });
405    },
406
407    hide: function () {
408      if (!this.isVisible) return;
409      if (this.isInline) return;
410      this.picker.hide();
411      $(window).off('resize', this.place);
412      this.viewMode = this.startViewMode;
413      this.showMode();
414      if (!this.isInput) {
415        $(document).off('mousedown', this.hide);
416      }
417
418      if (
419        this.forceParse &&
420          (
421            this.isInput && this.element.val() ||
422              this.hasInput && this.element.find('input').val()
423            )
424        )
425        this.setValue();
426      this.isVisible = false;
427      this.element.trigger({
428        type: 'hide',
429        date: this.date
430      });
431    },
432
433    remove: function () {
434      this._detachEvents();
435      $(document).off('mousedown', this.clickedOutside);
436      this.picker.remove();
437      delete this.picker;
438      delete this.element.data().datetimepicker;
439    },
440
441    getDate: function () {
442      var d = this.getUTCDate();
443      if (d === null) {
444        return null;
445      }
446      return new Date(d.getTime() + (d.getTimezoneOffset() * 60000));
447    },
448
449    getUTCDate: function () {
450      return this.date;
451    },
452
453    getInitialDate: function () {
454      return this.initialDate
455    },
456
457    setInitialDate: function (initialDate) {
458      this.initialDate = initialDate;
459    },
460
461    setDate: function (d) {
462      this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset() * 60000)));
463    },
464
465    setUTCDate: function (d) {
466      if (d >= this.startDate && d <= this.endDate) {
467        this.date = d;
468        this.setValue();
469        this.viewDate = this.date;
470        this.fill();
471      } else {
472        this.element.trigger({
473          type:      'outOfRange',
474          date:      d,
475          startDate: this.startDate,
476          endDate:   this.endDate
477        });
478      }
479    },
480
481    setFormat: function (format) {
482      this.format = DPGlobal.parseFormat(format, this.formatType);
483      var element;
484      if (this.isInput) {
485        element = this.element;
486      } else if (this.component) {
487        element = this.element.find('input');
488      }
489      if (element && element.val()) {
490        this.setValue();
491      }
492    },
493
494    setValue: function () {
495      var formatted = this.getFormattedDate();
496      if (!this.isInput) {
497        if (this.component) {
498          this.element.find('input').val(formatted);
499        }
500        this.element.data('date', formatted);
501      } else {
502        this.element.val(formatted);
503      }
504      if (this.linkField) {
505        $('#' + this.linkField).val(this.getFormattedDate(this.linkFormat));
506      }
507    },
508
509    getFormattedDate: function (format) {
510      format = format || this.format;
511      return DPGlobal.formatDate(this.date, format, this.language, this.formatType, this.timezone);
512    },
513
514    setStartDate: function (startDate) {
515      this.startDate = startDate || this.startDate;
516      if (this.startDate.valueOf() !== 8639968443048000) {
517        this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language, this.formatType, this.timezone);
518      }
519      this.update();
520      this.updateNavArrows();
521    },
522
523    setEndDate: function (endDate) {
524      this.endDate = endDate || this.endDate;
525      if (this.endDate.valueOf() !== 8639968443048000) {
526        this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language, this.formatType, this.timezone);
527      }
528      this.update();
529      this.updateNavArrows();
530    },
531
532    setDatesDisabled: function (datesDisabled) {
533      this.datesDisabled = datesDisabled || [];
534      if (!$.isArray(this.datesDisabled)) {
535        this.datesDisabled = this.datesDisabled.split(/,\s*/);
536      }
537      var mThis = this;
538      this.datesDisabled = $.map(this.datesDisabled, function (d) {
539        return DPGlobal.parseDate(d, mThis.format, mThis.language, mThis.formatType, mThis.timezone).toDateString();
540      });
541      this.update();
542      this.updateNavArrows();
543    },
544
545    setTitle: function (selector, value) {
546      return this.picker.find(selector)
547        .find('th:eq(1)')
548        .text(this.title === false ? value : this.title);
549    },
550
551    setDaysOfWeekDisabled: function (daysOfWeekDisabled) {
552      this.daysOfWeekDisabled = daysOfWeekDisabled || [];
553      if (!$.isArray(this.daysOfWeekDisabled)) {
554        this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
555      }
556      this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) {
557        return parseInt(d, 10);
558      });
559      this.update();
560      this.updateNavArrows();
561    },
562
563    setMinutesDisabled: function (minutesDisabled) {
564      this.minutesDisabled = minutesDisabled || [];
565      if (!$.isArray(this.minutesDisabled)) {
566        this.minutesDisabled = this.minutesDisabled.split(/,\s*/);
567      }
568      this.minutesDisabled = $.map(this.minutesDisabled, function (d) {
569        return parseInt(d, 10);
570      });
571      this.update();
572      this.updateNavArrows();
573    },
574
575    setHoursDisabled: function (hoursDisabled) {
576      this.hoursDisabled = hoursDisabled || [];
577      if (!$.isArray(this.hoursDisabled)) {
578        this.hoursDisabled = this.hoursDisabled.split(/,\s*/);
579      }
580      this.hoursDisabled = $.map(this.hoursDisabled, function (d) {
581        return parseInt(d, 10);
582      });
583      this.update();
584      this.updateNavArrows();
585    },
586
587    place: function () {
588      if (this.isInline) return;
589
590      if (!this.zIndex) {
591        var index_highest = 0;
592        $('div').each(function () {
593          var index_current = parseInt($(this).css('zIndex'), 10);
594          if (index_current > index_highest) {
595            index_highest = index_current;
596          }
597        });
598        this.zIndex = index_highest + 10;
599      }
600
601      var offset, top, left, containerOffset;
602      if (this.container instanceof $) {
603        containerOffset = this.container.offset();
604      } else {
605        containerOffset = $(this.container).offset();
606      }
607
608      if (this.component) {
609        offset = this.component.offset();
610        left = offset.left;
611        if (this.pickerPosition === 'bottom-left' || this.pickerPosition === 'top-left') {
612          left += this.component.outerWidth() - this.picker.outerWidth();
613        }
614      } else {
615        offset = this.element.offset();
616        left = offset.left;
617        if (this.pickerPosition === 'bottom-left' || this.pickerPosition === 'top-left') {
618          left += this.element.outerWidth() - this.picker.outerWidth();
619        }
620      }
621
622      var bodyWidth = document.body.clientWidth || window.innerWidth;
623      if (left + 220 > bodyWidth) {
624        left = bodyWidth - 220;
625      }
626
627      if (this.pickerPosition === 'top-left' || this.pickerPosition === 'top-right') {
628        top = offset.top - this.picker.outerHeight();
629      } else {
630        top = offset.top + this.height;
631      }
632
633      top = top - containerOffset.top;
634      left = left - containerOffset.left;
635
636      this.picker.css({
637        top:    top,
638        left:   left,
639        zIndex: this.zIndex
640      });
641    },
642
643    hour_minute: "^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]",
644
645    update: function () {
646      var date, fromArgs = false;
647      if (arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
648        date = arguments[0];
649        fromArgs = true;
650      } else {
651        date = (this.isInput ? this.element.val() : this.element.find('input').val()) || this.element.data('date') || this.initialDate;
652        if (typeof date === 'string') {
653          date = date.replace(/^\s+|\s+$/g,'');
654        }
655      }
656
657      if (!date) {
658        date = new Date();
659        fromArgs = false;
660      }
661
662      if (typeof date === "string") {
663        if (new RegExp(this.hour_minute).test(date) || new RegExp(this.hour_minute + ":[
6630-5][0-9]").test(date)) {
664          date = this.getDate()
665        }
666      }
667
668      this.date = DPGlobal.parseDate(date, this.format, this.language, this.formatType, this.timezone);
669
670      if (fromArgs) this.setValue();
671
672      if (this.date < this.startDate) {
673        this.viewDate = new Date(this.startDate);
674      } else if (this.date > this.endDate) {
675        this.viewDate = new Date(this.endDate);
676      } else {
677        this.viewDate = new Date(this.date);
678      }
679      this.fill();
680    },
681
682    fillDow: function () {
683      var dowCnt = this.weekStart,
684        html = '<tr>';
685      while (dowCnt < this.weekStart + 7) {
686        html += '<th class="dow">' + dates[this.language].daysMin[(dowCnt++) % 7] + '</th>';
687      }
688      html += '</tr>';
689      this.picker.find('.datetimepicker-days thead').append(html);
690    },
691
692    fillMonths: function () {
693      var html = '';
694      var d = new Date(this.viewDate);
695      for (var i = 0; i < 12; i++) {
696        d.setUTCMonth(i);
697        var classes = this.onRenderMonth(d);
698        html += '<span class="' + classes.join(' ') + '">' + dates[this.language].monthsShort[i] + '</span>';
699      }
700      this.picker.find('.datetimepicker-months td').html(html);
701    },
702
703    fill: function () {
704      if (!this.date || !this.viewDate) {
705        return;
706      }
707      var d = new Date(this.viewDate),
708        year = d.getUTCFullYear(),
709        month = d.getUTCMonth(),
710        dayMonth = d.getUTCDate(),
711        hours = d.getUTCHours(),
712        startYear = this.startDate.getUTCFullYear(),
713        startMonth = this.startDate.getUTCMonth(),
714        endYear = this.endDate.getUTCFullYear(),
715        endMonth = this.endDate.getUTCMonth() + 1,
716        currentDate = (new UTCDate(this.date.getUTCFullYear(), this.date.getUTCMonth(), this.date.getUTCDate())).valueOf(),
717        today = new Date();
718      this.setTitle('.datetimepicker-days', dates[this.language].months[month] + ' ' + year)
719      if (this.formatViewType === 'time') {
720        var formatted = this.getFormattedDate();
721        this.setTitle('.datetimepicker-hours', formatted);
722        this.setTitle('.datetimepicker-minutes', formatted);
723      } else {
724        this.setTitle('.datetimepicker-hours', dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
725        this.setTitle('.datetimepicker-minutes', dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
726      }
727      this.picker.find('tfoot th.today')
728        .text(dates[this.language].today || dates['en'].today)
729        .toggle(this.todayBtn !== false);
730      this.picker.find('tfoot th.clear')
731        .text(dates[this.language].clear || dates['en'].clear)
732        .toggle(this.clearBtn !== false);
733      this.updateNavArrows();
734      this.fillMonths();
735      var prevMonth = UTCDate(year, month - 1, 28, 0, 0, 0, 0),
736        day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
737      prevMonth.setUTCDate(day);
738      prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7) % 7);
739      var nextMonth = new Date(prevMonth);
740      nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
741      nextMonth = nextMonth.valueOf();
742      var html = [];
743      var classes;
744      while (prevMonth.valueOf() < nextMonth) {
745        if (prevMonth.getUTCDay() === this.weekStart) {
746          html.push('<tr>');
747        }
748        classes = this.onRenderDay(prevMonth);
749        if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() === year && prevMonth.getUTCMonth() < month)) {
750          classes.push('old');
751        } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() === year && prevMonth.getUTCMonth() > month)) {
752          classes.push('new');
753        }
754        // Compare internal UTC date with local today, not UTC today
755        if (this.todayHighlight &&
756          prevMonth.getUTCFullYear() === today.getFullYear() &&
757          prevMonth.getUTCMonth() === today.getMonth() &&
758          prevMonth.getUTCDate() === today.getDate()) {
759          classes.push('today');
760        }
761        if (prevMonth.valueOf() === currentDate) {
762          classes.push('active');
763        }
764        if ((prevMonth.valueOf() + 86400000) <= this.startDate || prevMonth.valueOf() > this.endDate ||
765          $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1 ||
766          $.inArray(prevMonth.toDateString(), this.datesDisabled) !== -1) {
767          classes.push('disabled');
768        }
769        html.push('<td class="' + classes.join(' ') + '">' + prevMonth.getUTCDate() + '</td>');
770        if (prevMonth.getUTCDay() === this.weekEnd) {
771          html.push('</tr>');
772        }
773        prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
774      }
775      this.picker.find('.datetimepicker-days tbody').empty().append(html.join(''));
776
777      html = [];
778      var txt = '', meridian = '', meridianOld = '';
779      var hoursDisabled = this.hoursDisabled || [];
780      d = new Date(this.viewDate)
781      for (var i = 0; i < 24; i++) {
782        d.setUTCHours(i);
783        classes = this.onRenderHour(d);
784        if (hoursDisabled.indexOf(i) !== -1) {
785          classes.push('disabled');
786        }
787        var actual = UTCDate(year, month, dayMonth, i);
788        // We want the previous hour for the startDate
789        if ((actual.valueOf() + 3600000) <= this.startDate || actual.valueOf() > this.endDate) {
790          classes.push('disabled');
791        } else if (hours === i) {
792          classes.push('active');
793        }
794        if (this.showMeridian && dates[this.language].meridiem.length === 2) {
795          meridian = (i < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]);
796          if (meridian !== meridianOld) {
797            if (meridianOld !== '') {
798              html.push('</fieldset>');
799            }
800            html.push('<fieldset class="hour"><legend>' + meridian.toUpperCase() + '</legend>');
801          }
802          meridianOld = meridian;
803          txt = (i % 12 ? i % 12 : 12);
804          if (i < 12) {
805            classes.push('hour_am');
806          } else {
807            classes.push('hour_pm');
808          }
809          html.push('<span class="' + classes.join(' ') + '">' + txt + '</span>');
810          if (i === 23) {
811            html.push('</fieldset>');
812          }
813        } else {
814          txt = i + ':00';
815          html.push('<span class="' + classes.join(' ') + '">' + txt + '</span>');
816        }
817      }
818      this.picker.find('.datetimepicker-hours td').html(html.join(''));
819
820      html = [];
821      txt = '';
822      meridian = '';
823      meridianOld = '';
824      var minutesDisabled = this.minutesDisabled || [];
825      d = new Date(this.viewDate);
826      for (var i = 0; i < 60; i += this.minuteStep) {
827        if (minutesDisabled.indexOf(i) !== -1) continue;
828        d.setUTCMinutes(i);
829        d.setUTCSeconds(0);
830        classes = this.onRenderMinute(d);
831        if (this.showMeridian && dates[this.language].meridiem.length === 2) {
832          meridian = (hours < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]);
833          if (meridian !== meridianOld) {
834            if (meridianOld !== '') {
835              html.push('</fieldset>');
836            }
837            html.push('<fieldset class="minute"><legend>' + meridian.toUpperCase() + '</legend>');
838          }
839          meridianOld = meridian;
840          txt = (hours % 12 ? hours % 12 : 12);
841          html.push('<span class="' + classes.join(' ') + '">' + txt + ':' + (i < 10 ? '0' + i : i) + '</span>');
842          if (i === 59) {
843            html.push('</fieldset>');
844          }
845        } else {
846          txt = i + ':00';
847          html.push('<span class="' + classes.join(' ') + '">' + hours + ':' + (i < 10 ? '0' + i : i) + '</span>');
848        }
849      }
850      this.picker.find('.datetimepicker-minutes td').html(html.join(''));
851
852      var currentYear = this.date.getUTCFullYear();
853      var months = this.setTitle('.datetimepicker-months', year)
854        .end()
855        .find('.month').removeClass('active');
856      if (currentYear === year) {
857        // getUTCMonths() returns 0 based, and we need to select the next one
858        // To cater bootstrap 2 we don't need to select the next one
859        months.eq(this.date.getUTCMonth()).addClass('active');
860      }
861      if (year < startYear || year > endYear) {
862        months.addClass('disabled');
863      }
864      if (year === startYear) {
865        months.slice(0, startMonth).addClass('disabled');
866      }
867      if (year === endYear) {
868        months.slice(endMonth).addClass('disabled');
869      }
870
871      html = '';
872      year = parseInt(year / 10, 10) * 10;
873      var yearCont = this.setTitle('.datetimepicker-years', year + '-' + (year + 9))
874        .end()
875        .find('td');
876      year -= 1;
877      d = new Date(this.viewDate);
878      for (var i = -1; i < 11; i++) {
879        d.setUTCFullYear(year);
880        classes = this.onRenderYear(d);
881        if (i === -1 || i === 10) {
882          classes.push(old);
883        }
884        html += '<span class="' + classes.join(' ') + '">' + year + '</span>';
885        year += 1;
886      }
887      yearCont.html(html);
888      this.place();
889    },
890
891    updateNavArrows: function () {
892      var d = new Date(this.viewDate),
893        year = d.getUTCFullYear(),
894        month = d.getUTCMonth(),
895        day = d.getUTCDate(),
896        hour = d.getUTCHours();
897      switch (this.viewMode) {
898        case 0:
899          if (year <= this.startDate.getUTCFullYear()
900            && month <= this.startDate.getUTCMonth()
901            && day <= this.startDate.getUTCDate()
902            && hour <= this.startDate.getUTCHours()) {
903            this.picker.find('.prev').css({visibility: 'hidden'});
904          } else {
905            this.picker.find('.prev').css({visibility: 'visible'});
906          }
907          if (year >= this.endDate.getUTCFullYear()
908            && month >= this.endDate.getUTCMonth()
909            && day >= this.endDate.getUTCDate()
910            && hour >= this.endDate.getUTCHours()) {
911            this.picker.find('.next').css({visibility: 'hidden'});
912          } else {
913            this.picker.find('.next').css({visibility: 'visible'});
914          }
915          break;
916        case 1:
917          if (year <= this.startDate.getUTCFullYear()
918            && month <= this.startDate.getUTCMonth()
919            && day <= this.startDate.getUTCDate()) {
920            this.picker.find('.prev').css({visibility: 'hidden'});
921          } else {
922            this.picker.find('.prev').css({visibility: 'visible'});
923          }
924          if (year >= this.endDate.getUTCFullYear()
925            && month >= this.endDate.getUTCMonth()
926            && day >= this.endDate.getUTCDate()) {
927            this.picker.find('.next').css({visibility: 'hidden'});
928          } else {
929            this.picker.find('.next').css({visibility: 'visible'});
930          }
931          break;
932        case 2:
933          if (year <= this.startDate.getUTCFullYear()
934            && month <= this.startDate.getUTCMonth()) {
935            this.picker.find('.prev').css({visibility: 'hidden'});
936          } else {
937            this.picker.find('.prev').css({visibility: 'visible'});
938          }
939          if (year >= this.endDate.getUTCFullYear()
940            && month >= this.endDate.getUTCMonth()) {
941            this.picker.find('.next').css({visibility: 'hidden'});
942          } else {
943            this.picker.find('.next').css({visibility: 'visible'});
944          }
945          break;
946        case 3:
947        case 4:
948          if (year <= this.startDate.getUTCFullYear()) {
949            this.picker.find('.prev').css({visibility: 'hidden'});
950          } else {
951            this.picker.find('.prev').css({visibility: 'visible'});
952          }
953          if (year >= this.endDate.getUTCFullYear()) {
954            this.picker.find('.next').css({visibility: 'hidden'});
955          } else {
956            this.picker.find('.next').css({visibility: 'visible'});
957          }
958          break;
959      }
960    },
961
962    mousewheel: function (e) {
963
964      e.preventDefault();
965      e.stopPropagation();
966
967      if (this.wheelPause) {
968        return;
969      }
970
971      this.wheelPause = true;
972
973      var originalEvent = e.originalEvent;
974
975      var delta = originalEvent.wheelDelta;
976
977      var mode = delta > 0 ? 1 : (delta === 0) ? 0 : -1;
978
979      if (this.wheelViewModeNavigationInverseDirection) {
980        mode = -mode;
981      }
982
983      this.showMode(mode);
984
985      setTimeout($.proxy(function () {
986
987        this.wheelPause = false
988
989      }, this), this.wheelViewModeNavigationDelay);
990
991    },
992
993    click: function (e) {
994      e.stopPropagation();
995      e.preventDefault();
996      var target = $(e.target).closest('span, td, th, legend');
997      if (target.is('.' + this.icontype)) {
998        target = $(target).parent().closest('span, td, th, legend');
999      }
1000      if (target.length === 1) {
1001        if (target.is('.disabled')) {
1002          this.element.trigger({
1003            type:      'outOfRange',
1004            date:      this.viewDate,
1005            startDate: this.startDate,
1006            endDate:   this.endDate
1007          });
1008          return;
1009        }
1010        switch (target[0].nodeName.toLowerCase()) {
1011          case 'th':
1012            switch (target[0].className) {
1013              case 'switch':
1014                this.showMode(1);
1015                break;
1016              case 'prev':
1017              case 'next':
1018                var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1);
1019                switch (this.viewMode) {
1020                  case 0:
1021                    this.viewDate = this.moveHour(this.viewDate, dir);
1022                    break;
1023                  case 1:
1024                    this.viewDate = this.moveDate(this.viewDate, dir);
1025                    break;
1026                  case 2:
1027                    this.viewDate = this.moveMonth(this.viewDate, dir);
1028                    break;
1029                  case 3:
1030                  case 4:
1031                    this.viewDate = this.moveYear(this.viewDate, dir);
1032                    break;
1033                }
1034                this.fill();
1035                this.element.trigger({
1036                  type:      target[0].className + ':' + this.convertViewModeText(this.viewMode),
1037                  date:      this.viewDate,
1038                  startDate: this.startDate,
1039                  endDate:   this.endDate
1040                });
1041                break;
1042              case 'clear':
1043                this.reset();
1044                if (this.autoclose) {
1045                  this.hide();
1046                }
1047                break;
1048              case 'today':
1049                var date = new Date();
1050                date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), 0);
1051
1052                // Respect startDate and endDate.
1053                if (date < this.startDate) date = this.startDate;
1054                else if (date > this.endDate) date = this.endDate;
1055
1056                this.viewMode = this.startViewMode;
1057                this.showMode(0);
1058                this._setDate(date);
1059                this.fill();
1060                if (this.autoclose) {
1061                  this.hide();
1062                }
1063                break;
1064            }
1065            break;
1066          case 'span':
1067            if (!target.is('.disabled')) {
1068              var year = this.viewDate.getUTCFullYear(),
1069                month = this.viewDate.getUTCMonth(),
1070                day = this.viewDate.getUTCDate(),
1071                hours = this.viewDate.getUTCHours(),
1072                minutes = this.viewDate.getUTCMinutes(),
1073                seconds = this.viewDate.getUTCSeconds();
1074
1075              if (target.is('.month')) {
1076                this.viewDate.setUTCDate(1);
1077                month = target.parent().find('span').index(target);
1078                day = this.viewDate.getUTCDate();
1079                this.viewDate.setUTCMonth(month);
1080                this.element.trigger({
1081                  type: 'changeMonth',
1082                  date: this.viewDate
1083                });
1084                if (this.viewSelect >= 3) {
1085                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
1086                }
1087              } else if (target.is('.year')) {
1088                this.viewDate.setUTCDate(1);
1089                year = parseInt(target.text(), 10) || 0;
1090                this.viewDate.setUTCFullYear(year);
1091                this.element.trigger({
1092                  type: 'changeYear',
1093                  date: this.viewDate
1094                });
1095                if (this.viewSelect >= 4) {
1096                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
1097                }
1098              } else if (target.is('.hour')) {
1099                hours = parseInt(target.text(), 10) || 0;
1100                if (target.hasClass('hour_am') || target.hasClass('hour_pm')) {
1101                  if (hours === 12 && target.hasClass('hour_am')) {
1102                    hours = 0;
1103                  } else if (hours !== 12 && target.hasClass('hour_pm')) {
1104                    hours += 12;
1105                  }
1106                }
1107                this.viewDate.setUTCHours(hours);
1108                this.element.trigger({
1109                  type: 'changeHour',
1110                  date: this.viewDate
1111                });
1112                if (this.viewSelect >= 1) {
1113                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
1114                }
1115              } else if (target.is('.minute')) {
1116                minutes = parseInt(target.text().substr(target.text().indexOf(':') + 1), 10) || 0;
1117                this.viewDate.setUTCMinutes(minutes);
1118                this.element.trigger({
1119                  type: 'changeMinute',
1120                  date: this.viewDate
1121                });
1122                if (this.viewSelect >= 0) {
1123                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
1124                }
1125              }
1126              if (this.viewMode !== 0) {
1127                var oldViewMode = this.viewMode;
1128                this.showMode(-1);
1129                this.fill();
1130                if (oldViewMode === this.viewMode && this.autoclose) {
1131                  this.hide();
1132                }
1133              } else {
1134                this.fill();
1135                if (this.autoclose) {
1136                  this.hide();
1137                }
1138              }
1139            }
1140            break;
1141          case 'td':
1142            if (target.is('.day') && !target.is('.disabled')) {
1143              var day = parseInt(target.text(), 10) || 1;
1144              var year = this.viewDate.getUTCFullYear(),
1145                month = this.viewDate.getUTCMonth(),
1146                hours = this.viewDate.getUTCHours(),
1147                minutes = this.viewDate.getUTCMinutes(),
1148                seconds = this.viewDate.getUTCSeconds();
1149              if (target.is('.old')) {
1150                if (month === 0) {
1151                  month = 11;
1152                  year -= 1;
1153                } else {
1154                  month -= 1;
1155                }
1156              } else if (target.is('.new')) {
1157                if (month === 11) {
1158                  month = 0;
1159                  year += 1;
1160                } else {
1161                  month += 1;
1162                }
1163              }
1164              this.viewDate.setUTCFullYear(year);
1165              this.viewDate.setUTCMonth(month, day);
1166              this.element.trigger({
1167                type: 'changeDay',
1168                date: this.viewDate
1169              });
1170              if (this.viewSelect >= 2) {
1171                this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
1172              }
1173            }
1174            var oldViewMode = this.viewMode;
1175            this.showMode(-1);
1176            this.fill();
1177            if (oldViewMode === this.viewMode && this.autoclose) {
1178              this.hide();
1179            }
1180            break;
1181        }
1182      }
1183    },
1184
1185    _setDate: function (date, which) {
1186      if (!which || which === 'date')
1187        this.date = date;
1188      if (!which || which === 'view')
1189        this.viewDate = date;
1190      this.fill();
1191      this.setValue();
1192      var element;
1193      if (this.isInput) {
1194        element = this.element;
1195      } else if (this.component) {
1196        element = this.element.find('input');
1197      }
1198      if (element) {
1199        element.change();
1200      }
1201      this.element.trigger({
1202        type: 'changeDate',
1203        date: this.getDate()
1204      });
1205      if(date === null)
1206        this.date = this.viewDate;
1207    },
1208
1209    moveMinute: function (date, dir) {
1210      if (!dir) return date;
1211      var new_date = new Date(date.valueOf());
1212      //dir = dir > 0 ? 1 : -1;
1213      new_date.setUTCMinutes(new_date.getUTCMinutes() + (dir * this.minuteStep));
1214      return new_date;
1215    },
1216
1217    moveHour: function (date, dir) {
1218      if (!dir) return date;
1219      var new_date = new Date(date.valueOf());
1220      //dir = dir > 0 ? 1 : -1;
1221      new_date.setUTCHours(new_date.getUTCHours() + dir);
1222      return new_date;
1223    },
1224
1225    moveDate: function (date, dir) {
1226      if (!dir) return date;
1227      var new_date = new Date(date.valueOf());
1228      //dir = dir > 0 ? 1 : -1;
1229      new_date.setUTCDate(new_date.getUTCDate() + dir);
1230      return new_date;
1231    },
1232
1233    moveMonth: function (date, dir) {
1234      if (!dir) return date;
1235      var new_date = new Date(date.valueOf()),
1236        day = new_date.getUTCDate(),
1237        month = new_date.getUTCMonth(),
1238        mag = Math.abs(dir),
1239        new_month, test;
1240      dir = dir > 0 ? 1 : -1;
1241      if (mag === 1) {
1242        test = dir === -1
1243          // If going back one month, make sure month is not current month
1244          // (eg, Mar 31 -> Feb 31 === Feb 28, not Mar 02)
1245          ? function () {
1246          return new_date.getUTCMonth() === month;
1247        }
1248          // If going forward one month, make sure month is as expected
1249          // (eg, Jan 31 -> Feb 31 === Feb 28, not Mar 02)
1250          : function () {
1251          return new_date.getUTCMonth() !== new_month;
1252        };
1253        new_month = month + dir;
1254        new_date.setUTCMonth(new_month);
1255        // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
1256        if (new_month < 0 || new_month > 11)
1257          new_month = (new_month + 12) % 12;
1258      } else {
1259        // For magnitudes >1, move one month at a time...
1260        for (var i = 0; i < mag; i++)
1261          // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
1262          new_date = this.moveMonth(new_date, dir);
1263        // ...then reset the day, keeping it in the new month
1264        new_month = new_date.getUTCMonth();
1265        new_date.setUTCDate(day);
1266        test = function () {
1267          return new_month !== new_date.getUTCMonth();
1268        };
1269      }
1270      // Common date-resetting loop -- if date is beyond end of month, make it
1271      // end of month
1272      while (test()) {
1273        new_date.setUTCDate(--day);
1274        new_date.setUTCMonth(new_month);
1275      }
1276      return new_date;
1277    },
1278
1279    moveYear: function (date, dir) {
1280      return this.moveMonth(date, dir * 12);
1281    },
1282
1283    dateWithinRange: function (date) {
1284      return date >= this.startDate && date <= this.endDate;
1285    },
1286
1287    keydown: function (e) {
1288      if (this.picker.is(':not(:visible)')) {
1289        if (e.keyCode === 27) // allow escape to hide and re-show picker
1290          this.show();
1291        return;
1292      }
1293      var dateChanged = false,
1294        dir, newDate, newViewDate;
1295      switch (e.keyCode) {
1296        case 27: // escape
1297          this.hide();
1298          e.preventDefault();
1299          break;
1300        case 37: // left
1301        case 39: // right
1302          if (!this.keyboardNavigation) break;
1303          dir = e.keyCode === 37 ? -1 : 1;
1304          var viewMode = this.viewMode;
1305          if (e.ctrlKey) {
1306            viewMode += 2;
1307          } else if (e.shiftKey) {
1308            viewMode += 1;
1309          }
1310          if (viewMode === 4) {
1311            newDate = this.moveYear(this.date, dir);
1312            newViewDate = this.moveYear(this.viewDate, dir);
1313          } else if (viewMode === 3) {
1314            newDate = this.moveMonth(this.date, dir);
1315            newViewDate = this.moveMonth(this.viewDate, dir);
1316          } else if (viewMode === 2) {
1317            newDate = this.moveDate(this.date, dir);
1318            newViewDate = this.moveDate(this.viewDate, dir);
1319          } else if (viewMode === 1) {
1320            newDate = this.moveHour(this.date, dir);
1321            newViewDate = this.moveHour(this.viewDate, dir);
1322          } else if (viewMode === 0) {
1323            newDate = this.moveMinute(this.date, dir);
1324            newViewDate = this.moveMinute(this.viewDate, dir);
1325          }
1326          if (this.dateWithinRange(newDate)) {
1327            this.date = newDate;
1328            this.viewDate = newViewDate;
1329            this.setValue();
1330            this.update();
1331            e.preventDefault();
1332            dateChanged = true;
1333          }
1334          break;
1335        case 38: // up
1336        case 40: // down
1337          if (!this.keyboardNavigation) break;
1338          dir = e.keyCode === 38 ? -1 : 1;
1339          viewMode = this.viewMode;
1340          if (e.ctrlKey) {
1341            viewMode += 2;
1342          } else if (e.shiftKey) {
1343            viewMode += 1;
1344          }
1345          if (viewMode === 4) {
1346            newDate = this.moveYear(this.date, dir);
1347            newViewDate = this.moveYear(this.viewDate, dir);
1348          } else if (viewMode === 3) {
1349            newDate = this.moveMonth(this.date, dir);
1350            newViewDate = this.moveMonth(this.viewDate, dir);
1351          } else if (viewMode === 2) {
1352            newDate = this.moveDate(this.date, dir * 7);
1353            newViewDate = this.moveDate(this.viewDate, dir * 7);
1354          } else if (viewMode === 1) {
1355            if (this.showMeridian) {
1356              newDate = this.moveHour(this.date, dir * 6);
1357              newViewDate = this.moveHour(this.viewDate, dir * 6);
1358            } else {
1359              newDate = this.moveHour(this.date, dir * 4);
1360              newViewDate = this.moveHour(this.viewDate, dir * 4);
1361            }
1362          } else if (viewMode === 0) {
1363            newDate = this.moveMinute(this.date, dir * 4);
1364            newViewDate = this.moveMinute(this.viewDate, dir * 4);
1365          }
1366          if (this.dateWithinRange(newDate)) {
1367            this.date = newDate;
1368            this.viewDate = newViewDate;
1369            this.setValue();
1370            this.update();
1371            e.preventDefault();
1372            dateChanged = true;
1373          }
1374          break;
1375        case 13: // enter
1376          if (this.viewMode !== 0) {
1377            var oldViewMode = this.viewMode;
1378            this.showMode(-1);
1379            this.fill();
1380            if (oldViewMode === this.viewMode && this.autoclose) {
1381              this.hide();
1382            }
1383          } else {
1384            this.fill();
1385            if (this.autoclose) {
1386              this.hide();
1387            }
1388          }
1389          e.preventDefault();
1390          break;
1391        case 9: // tab
1392          this.hide();
1393          break;
1394      }
1395      if (dateChanged) {
1396        var element;
1397        if (this.isInput) {
1398          element = this.element;
1399        } else if (this.component) {
1400          element = this.element.find('input');
1401        }
1402        if (element) {
1403          element.change();
1404        }
1405        this.element.trigger({
1406          type: 'changeDate',
1407          date: this.getDate()
1408        });
1409      }
1410    },
1411
1412    showMode: function (dir) {
1413      if (dir) {
1414        var newViewMode = Math.max(0, Math.min(DPGlobal.modes.length - 1, this.viewMode + dir));
1415        if (newViewMode >= this.minView && newViewMode <= this.maxView) {
1416          this.element.trigger({
1417            type:        'changeMode',
1418            date:        this.viewDate,
1419            oldViewMode: this.viewMode,
1420            newViewMode: newViewMode
1421          });
1422
1423          this.viewMode = newViewMode;
1424        }
1425      }
1426      /*
1427       vitalets: fixing bug of very special conditions:
1428       jquery 1.7.1 + webkit + show inline datetimepicker in bootstrap popover.
1429       Method show() does not set display css correctly and datetimepicker is not shown.
1430       Changed to .css('display', 'block') solve the problem.
1431       See https://github.com/vitalets/x-editable/issues/37
1432
1433       In jquery 1.7.2+ everything works fine.
1434       */
1435      //this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
1436      this.picker.find('>div').hide().filter('.datetimepicker-' + DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
1437      this.updateNavArrows();
1438    },
1439
1440    reset: function () {
1441      this._setDate(null, 'date');
1442    },
1443
1444    convertViewModeText:  function (viewMode) {
1445      switch (viewMode) {
1446        case 4:
1447          return 'decade';
1448        case 3:
1449          return 'year';
1450        case 2:
1451          return 'month';
1452        case 1:
1453          return 'day';
1454        case 0:
1455          return 'hour';
1456      }
1457    }
1458  };
1459
1460  var old = $.fn.datetimepicker;
1461  $.fn.datetimepicker = function (option) {
1462    var args = Array.apply(null, arguments);
1463    args.shift();
1464    var internal_return;
1465    this.each(function () {
1466      var $this = $(this),
1467        data = $this.data('datetimepicker'),
1468        options = typeof option === 'object' && option;
1469      if (!data) {
1470        $this.data('datetimepicker', (data = new Datetimepicker(this, $.extend({}, $.fn.datetimepicker.defaults, options))));
1471      }
1472      if (typeof option === 'string' && typeof data[option] === 'function') {
1473        internal_return = data[option].apply(data, args);
1474        if (internal_return !== undefined) {
1475          return false;
1476        }
1477      }
1478    });
1479    if (internal_return !== undefined)
1480      return internal_return;
1481    else
1482      return this;
1483  };
1484
1485  $.fn.datetimepicker.defaults = {
1486  };
1487  $.fn.datetimepicker.Constructor = Datetimepicker;
1488  var dates = $.fn.datetimepicker.dates = {
1489    en: {
1490      days:        ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
1491      daysShort:   ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
1492      daysMin:     ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
1493      months:      ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
1494      monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1495      meridiem:    ['am', 'pm'],
1496      suffix:      ['st', 'nd', 'rd', 'th'],
1497      today:       'Today',
1498      clear:       'Clear'
1499    },
1500     fr: {
1501        days: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"],
1502        daysShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"],
1503        daysMin: ["D", "L", "Ma", "Me", "J", "V", "S", "D"],
1504        months: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"],
1505        monthsShort: ["Jan", "Fev", "Mar", "Avr", "Mai", "Jui", "Jul", "Aou", "Sep", "Oct", "Nov", "Dec"],
1506        today: "Aujourd'hui",
1507        suffix: [],
1508        meridiem: ["am", "pm"],
1509        weekStart: 1,
1510        format: "dd/mm/yyyy hh:ii"
1511        },
1512        gb: {
1513      days:        ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
1514      daysShort:   ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
1515      daysMin:     ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
1516      months:      ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
1517      monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1518      meridiem:    ['am', 'pm'],
1519      suffix:      ['st', 'nd', 'rd', 'th'],
1520      today:       'Today',
1521      clear:       'Clear'
1522    },
1523     cs: {
1524        days: ['neděle', 'pondělí', 'úterý', 'středa', 'Ŀtvrtek', 'pátek', 'sobota'],
1525        daysShort: ['ne', 'po', 'út', 'st', 'Ŀt', 'pá', 'so'],
1526        daysMin: ['ne', 'po', 'út', 'st', 'Ŀt', 'pá', 'so'],
1527        months: ['leden', 'únor', 'březen', 'duben', 'květen', 'Ŀerven', 'Ŀervenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec'],
1528        monthsShort: ['led', 'úno', 'bře', 'dub', 'kvě', 'Ŀer', 'Ŀvc', 'srp', 'zář', 'říj', 'lis', 'pro'],
1529        today: "?????",
1530        suffix: [],
1531        },
1532        de: {
1533        days: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
1534        daysShort: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
1535        daysMin: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
1536        months: ['Januar', 'Februar', 'MÀrz', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
1537        monthsShort: ['Jan', 'Feb', 'MÀr', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
1538        today: "heute",
1539        suffix: [],
1540        },
1541        el: {
1542        months: ['ΙανουάϿιος', 'ΦεβϿουάϿιος', 'ΜάϿτιος', 'ΑπϿίλιος', 'Μάιος', 'ΙοϿνιος', 'ΙοϿλιος', 'ΑϿγουστος', 'ΣεπτέμβϿιος', 'ΟκτώβϿιος', 'οοέμβϿιος', 'ΔεκέμβϿιος'],
1543        monthsShort: ['Ιαν', 'Φεβ', 'ΜαϿ', 'ΑπϿ', 'Μαι', 'Ιουν', 'Ιουλ', 'Αυγ', 'Σεπ', 'Οκτ', 'οοε', 'Δεκ'],
1544        days: ['ΚυϿιακή', 'ΔευτέϿα', 'ΤϿίτη', 'ΤετάϿτη', 'Πέμπτη', 'ΠαϿασκευή', 'Σάββατο'],
1545        daysShort: ['ΚυϿ', 'Δευ', 'ΤϿι', 'Τετ', 'Πεμ', 'ΠαϿ', 'Σαβ'],
1546        daysMin: ['Κυ', 'Δε', 'ΤϿ', 'Τε', 'Πε', 'Πα', 'Σα'],
1547		today: "??????",
1548        suffix: [],
1549    },
1550    es: {
1551        months: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', '
1551Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
1552        monthsShort: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
1553        days: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
1554        daysShort: ['Dom', 'Lun', 'Mar', 'Mié', 'Juv', 'Vie', 'Sáb'],
1555        daysMin: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sá'],
1556		 today: "hoy dia",
1557        suffix: [],
1558    },
1559    fi: {
1560        months: ['Tammikuu', 'Helmikuu', 'Maaliskuu', 'Huhtikuu', 'Toukokuu', 'KesÀkuu', 'HeinÀkuu', 'Elokuu', 'Syyskuu', 'Lokakuu', 'Marraskuu', 'Joulukuu'],
1561        monthsShort: ['Tammi', 'Helmi', 'Maalis', 'Huhti', 'Touko', 'KesÀ', 'HeinÀ', 'Elo', 'Syys', 'Loka', 'Marras', 'Joulu'],
1562        days: ['Su', 'Ma', 'Ti', 'Ke', 'To', 'Pe', 'La'],
1563        daysShort: ['Sunnuntai', 'Maanantai', 'Tiistai', 'Keskiviikko', 'Torstai', 'Perjantai', 'Lauantai'],
1564        daysMin: ['Su', 'Ma', 'Ti', 'Ke', 'To', 'Pe', 'La'],
1565		today: "t寤客",
1566        suffix: [],
1567    },
1568    hu: {
1569        months: ['Január', 'Február', 'Március', 'ÿprilis', 'Május', 'Június', 'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'],
1570        monthsShort: ['Jan', 'Feb', 'Már', 'ÿpr', 'Máj', 'Jún', 'Júl', 'Aug', 'Szep', 'Okt', 'Nov', 'Dec'],
1571        days: ['Vasárnap', 'Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'],
1572        daysShort: ['Vas', 'Hét', 'Ked', 'Sze', 'Csü', 'Pén', 'Szo'],
1573        daysMin: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],
1574		today: "Ma",
1575        suffix: [],
1576    },
1577    it: {
1578        months: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre'],
1579        monthsShort: ['Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic'],
1580        days: ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'],
1581        daysShort: ['Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab'],
1582        daysMin: ['Do', 'Lu', 'Ma', 'Me', 'Gi', 'Ve', 'Sa'],
1583		today: "oggi",
1584        suffix: [],
1585    },
1586    nl: {
1587        months: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
1588        monthsShort: ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
1589        days: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
1590        daysShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'],
1591        daysMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
1592	today: "vandaag",
1593        meridiem:    ['am', 'pm'],
1594        suffix: [],
1595    },
1596    pl: {
1597        months: ['Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpień', 'Wrzesień', 'Październik', 'Listopad', 'Grudzień'],
1598        monthsShort: ['Sty', 'Lu', 'Mar', 'Kw', 'Maj', 'Cze', 'Lip', 'Sie', 'Wrz', 'Pa', 'Lis', 'Gru'],
1599        days: ['Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'],
1600        daysShort: ['Nie', 'Pn', 'Wt', 'Śr', 'Czw', 'Pt', 'So'],
1601        daysMin: ['N', 'Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'So'],
1602	today: "Dzi?",
1603        meridiem:    ['am', 'pm'],
1604        suffix: [],
1605    },
1606    pt: {
1607        months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
1608        monthsShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
1609        days: ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'],
1610        daysShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],
1611        daysMin: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],
1612	today: "hoje",
1613        meridiem:    ['am', 'pm'],
1614        suffix: [],
1615    },
1616    ro: {
1617        months: ['Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai', 'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie', 'Decembrie'],
1618        monthsShort: ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun', 'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1619        days: ['Duminică', 'Luni', 'Marţi', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'],
1620        daysShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
1621        daysMin: ['Du', 'Lu', 'Ma', 'Mi', 'Jo', 'Vi', 'Sâ'],
1622	today: "azi",
1623        meridiem:    ['am', 'pm'],
1624        suffix: [],
1625    },
1626    ru: {
1627        months: ['Январь', 'Февраль', 'Март', 'ппрель', 'Май', 'Июнь', 'Июль', 'пвгуѿт', 'Сентѿбрь', 'Октѿбрь', 'поѿбрь', 'Декабрь'],
1628        monthsShort: ['Янв', 'Фев', 'Мар', 'ппр', 'Май', 'Июн', 'Июл', 'пвг', 'Сен', 'Окт', 'поѿ', 'Дек'],
1629        days: ['воѿкреѿенье', 'понедельник', 'вторник', 'ѿреда', 'четверг', 'пѿтница', 'ѿуббота'],
1630        daysShort: ['вѿк', 'пнд', 'втр', 'ѿрд', 'чтв', 'птн', 'ѿбт'],
1631        daysMin: ['Вѿ', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
1632	today: "???????",
1633        meridiem:    ['am', 'pm'],
1634        suffix: [],
1635    },
1636    sk: {
1637        months: ['január', 'február', 'marec', 'apríl', 'máj', 'jún', 'júl', 'august', 'september', 'október', 'november', 'december'],
1638        monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'Máj', 'Jún', 'Júl', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'],
1639        days: ['nedeğa', 'pondelok', 'utorok', 'streda', 'štvrtok', 'piatok', 'sobota'],
1640        daysShort: ['Ned', 'Pon', 'Uto', 'Str', 'Å tv', 'Pia', 'Sob'],
1641        daysMin: ['Ne', 'Po', 'Ut', 'St', 'Å t', 'Pia', 'So'],
1642	today: "dnes",
1643        meridiem:    ['am', 'pm'],
1644        suffix: [],
1645    },
1646    sv: {
1647        months: ['Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni', 'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December'],
1648        monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'],
1649        days: ['Sön', 'Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör'],
1650        daysShort: ['Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lördag'],
1651        daysMin: ['Sö', 'Må', 'Ti', 'On', 'To', 'Fr', 'Lö'],
1652	today: "i dag",
1653        meridiem:    ['am', 'pm'],
1654        suffix: [],
1655    },
1656    tr: {
1657        months: ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
1658        monthsShort: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem', 'Ağu', 'Eyl', 'Eki', 'Kas', 'Ara'],
1659        days: ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi'],
1660        daysShort: ['Pz', 'Pt', 'Sa', 'Ça', 'Pe', 'Cu', 'Ct'],
1661        daysMin: ['Pz', 'Pt', 'Sa', 'Ça', 'Pe', 'Cu', 'Ct'],
1662	today: "bug",
1663        meridiem:    ['am', 'pm'],
1664        suffix: [],
1665    },
1666    uk: {
1667        months: ['Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'Вереѿень', 'Жовтень', 'Лиѿтопад', 'Грудень'],
1668        monthsShort: ['Січ', 'Лют', 'Бер', 'Кві', 'Тра', 'Чер', 'Лип', 'Сер', 'Вер', 'Жов', 'Лиѿ', 'Гру'],
1669        days: ['неділѿ', 'понеділок', 'вівторок', 'ѿереда', 'четвер', 'п’ѿтницѿ', 'ѿубота'],
1670        daysShort: ['нед', 'пнд', 'вів', 'ѿрд', 'чтв', 'птн', 'ѿбт'],
1671        daysMin: ['пд', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
1672	today: "????????",
1673        meridiem:    ['am', 'pm'],
1674        suffix: [],
1675    },
1676    
1677        
1678  };
1679
1680  var DPGlobal = {
1681    modes:            [
1682      {
1683        clsName: 'minutes',
1684        navFnc:  'Hours',
1685        navStep: 1
1686      },
1687      {
1688        clsName: 'hours',
1689        navFnc:  'Date',
1690        navStep: 1
1691      },
1692      {
1693        clsName: 'days',
1694        navFnc:  'Month',
1695        navStep: 1
1696      },
1697      {
1698        clsName: 'months',
1699        navFnc:  'FullYear',
1700        navStep: 1
1701      },
1702      {
1703        clsName: 'years',
1704        navFnc:  'FullYear',
1705        navStep: 10
1706      }
1707    ],
1708    isLeapYear:       function (year) {
1709      return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
1710    },
1711    getDaysInMonth:   function (year, month) {
1712      return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
1713    },
1714    getDefaultFormat: function (type, field) {
1715      if (type === 'standard') {
1716        if (field === 'input')
1717          return 'yyyy-mm-dd hh:ii';
1718        else
1719          return 'yyyy-mm-dd hh:ii:ss';
1720      } else if (type === 'php') {
1721        if (field === 'input')
1722          return 'Y-m-d H:i';
1723        else
1724          return 'Y-m-d H:i:s';
1725      } else {
1726        throw new Error('Invalid format type.');
1727      }
1728    },
1729    validParts: function (type) {
1730      if (type === 'standard') {
1731        return /t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g;
1732      } else if (type === 'php') {
1733        return /[dDjlNwzFmMnStyYaABgGhHis]/g;
1734      } else {
1735        throw new Error('Invalid format type.');
1736      }
1737    },
1738    nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,
1739    parseFormat: function (format, type) {
1740      // IE treats \0 as a string end in inputs (truncating the value),
1741      // so it's a bad format delimiter, anyway
1742      var separators = format.replace(this.validParts(type), '\0').split('\0'),
1743        parts = format.match(this.validParts(type));
1744      if (!separators || !separators.length || !parts || parts.length === 0) {
1745        throw new Error('Invalid date format.');
1746      }
1747      return {separators: separators, parts: parts};
1748    },
1749    parseDate: function (date, format, language, type, timezone) {
1750      if (date instanceof Date) {
1751        var dateUTC = new Date(date.valueOf() - date.getTimezoneOffset() * 60000);
1752        dateUTC.setMilliseconds(0);
1753        return dateUTC;
1754      }
1755      if (/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(date)) {
1756        format = this.parseFormat('yyyy-mm-dd', type);
1757      }
1758      if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(date)) {
1759        format = this.parseFormat('yyyy-mm-dd hh:ii', type);
1760      }
1761      if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(date)) {
1762        format = this.parseFormat('yyyy-mm-dd hh:ii:ss', type);
1763      }
1764      if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
1765        var part_re = /([-+]\d+)([dmwy])/,
1766          parts = date.match(/([-+]\d+)([dmwy])/g),
1767          part, dir;
1768        date = new Date();
1769        for (var i = 0; i < parts.length; i++) {
1770          part = part_re.exec(parts[i]);
1771          dir = parseInt(part[1]);
1772          switch (part[2]) {
1773            case 'd':
1774              date.setUTCDate(date.getUTCDate() + dir);
1775              break;
1776            case 'm':
1777              date = Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype, date, dir);
1778              break;
1779            case 'w':
1780              date.setUTCDate(date.getUTCDate() + dir * 7);
1781              break;
1782            case 'y':
1783              date = Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype, date, dir);
1784              break;
1785          }
1786        }
1787        return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), 0);
1788      }
1789      var parts = date && date.toString().match(this.nonpunctuation) || [],
1790        date = new Date(0, 0, 0, 0, 0, 0, 0),
1791        parsed = {},
1792        setters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'D', 'DD', 'd', 'dd', 'H', 'HH', 'p', 'P', 'z', 'Z'],
1793        setters_map = {
1794          hh:   function (d, v) {
1795            return d.setUTCHours(v);
1796          },
1797          h:    function (d, v) {
1798            return d.setUTCHours(v);
1799          },
1800          HH:   function (d, v) {
1801            return d.setUTCHours(v === 12 ? 0 : v);
1802          },
1803          H:    function (d, v) {
1804            return d.setUTCHours(v === 12 ? 0 : v);
1805          },
1806          ii:   function (d, v) {
1807            return d.setUTCMinutes(v);
1808          },
1809          i:    function (d, v) {
1810            return d.setUTCMinutes(v);
1811          },
1812          ss:   function (d, v) {
1813            return d.setUTCSeconds(v);
1814          },
1815          s:    function (d, v) {
1816            return d.setUTCSeconds(v);
1817          },
1818          yyyy: function (d, v) {
1819            return d.setUTCFullYear(v);
1820          },
1821          yy:   function (d, v) {
1822            return d.setUTCFullYear(2000 + v);
1823          },
1824          m:    function (d, v) {
1825            v -= 1;
1826            while (v < 0) v += 12;
1827            v %= 12;
1828            d.setUTCMonth(v);
1829            while (d.getUTCMonth() !== v)
1830              if (isNaN(d.getUTCMonth()))
1831                return d;
1832              else
1833                d.setUTCDate(d.getUTCDate() - 1);
1834            return d;
1835          },
1836          d:    function (d, v) {
1837            return d.setUTCDate(v);
1838          },
1839          p:    function (d, v) {
1840            return d.setUTCHours(v === 1 ? d.getUTCHours() + 12 : d.getUTCHours());
1841          },
1842          z:    function () {
1843            return timezone
1844          }
1845        },
1846        val, filtered, part;
1847      setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1848      setters_map['dd'] = setters_map['d'];
1849      setters_map['P'] = setters_map['p'];
1850      setters_map['Z'] = setters_map['z'];
1851      date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
1852      if (parts.length === format.parts.length) {
1853        for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
1854          val = parseInt(parts[i], 10);
1855          part = format.parts[i];
1856          if (isNaN(val)) {
1857            switch (part) {
1858              case 'MM':
1859                filtered = $(dates[language].months).filter(function () {
1860                  var m = this.slice(0, parts[i].length),
1861                    p = parts[i].slice(0, m.length);
1862                  return m === p;
1863                });
1864                val = $.inArray(filtered[0], dates[language].months) + 1;
1865                break;
1866              case 'M':
1867                filtered = $(dates[language].monthsShort).filter(function () {
1868                  var m = this.slice(0, parts[i].length),
1869                    p = parts[i].slice(0, m.length);
1870                  return m.toLowerCase() === p.toLowerCase();
1871                });
1872                val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1873                break;
1874              case 'p':
1875              case 'P':
1876                val = $.inArray(parts[i].toLowerCase(), dates[language].meridiem);
1877                break;
1878              case 'z':
1879              case 'Z':
1880                timezone;
1881                break;
1882
1883            }
1884          }
1885          parsed[part] = val;
1886        }
1887        for (var i = 0, s; i < setters_order.length; i++) {
1888          s = setters_order[i];
1889          if (s in parsed && !isNaN(parsed[s]))
1890            setters_map[s](date, parsed[s])
1891        }
1892      }
1893      return date;
1894    },
1895    formatDate:       function (date, format, language, type, timezone) {
1896      if (date === null) {
1897        return '';
1898      }
1899      var val;
1900      if (type === 'standard') {
1901        val = {
1902          t:    date.getTime(),
1903          // year
1904          yy:   date.getUTCFullYear().toString().substring(2),
1905          yyyy: date.getUTCFullYear(),
1906          // month
1907          m:    date.getUTCMonth() + 1,
1908          M:    dates[language].monthsShort[date.getUTCMonth()],
1909          MM:   dates[language].months[date.getUTCMonth()],
1910          // day
1911          d:    date.getUTCDate(),
1912          D:    dates[language].daysShort[date.getUTCDay()],
1913          DD:   dates[language].days[date.getUTCDay()],
1914          p:    (dates[language].meridiem.length === 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''),
1915          // hour
1916          h:    date.getUTCHours(),
1917          // minute
1918          i:    date.getUTCMinutes(),
1919          // second
1920          s:    date.getUTCSeconds(),
1921          // timezone
1922          z:    timezone
1923        };
1924
1925        if (dates[language].meridiem.length === 2) {
1926          val.H = (val.h % 12 === 0 ? 12 : val.h % 12);
1927        }
1928        else {
1929          val.H = val.h;
1930        }
1931        val.HH = (val.H < 10 ? '0' : '') + val.H;
1932        val.P = val.p.toUpperCase();
1933        val.Z = val.z;
1934        val.hh = (val.h < 10 ? '0' : '') + val.h;
1935        val.ii = (val.i < 10 ? '0' : '') + val.i;
1936        val.ss = (val.s < 10 ? '0' : '') + val.s;
1937        val.dd = (val.d < 10 ? '0' : '') + val.d;
1938        val.mm = (val.m < 10 ? '0' : '') + val.m;
1939      } else if (type === 'php') {
1940        // php format
1941        val = {
1942          // year
1943          y: date.getUTCFullYear().toString().substring(2),
1944          Y: date.getUTCFullYear(),
1945          // month
1946          F: dates[language].months[date.getUTCMonth()],
1947          M: dates[language].monthsShort[date.getUTCMonth()],
1948          n: date.getUTCMonth() + 1,
1949          t: DPGlobal.getDaysInMonth(date.getUTCFullYear(), date.getUTCMonth()),
1950          // day
1951          j: date.getUTCDate(),
1952          l: dates[language].days[date.getUTCDay()],
1953          D: dates[language].daysShort[date.getUTCDay()],
1954          w: date.getUTCDay(), // 0 -> 6
1955          N: (date.getUTCDay() === 0 ? 7 : date.getUTCDay()),       // 1 -> 7
1956          S: (date.getUTCDate() % 10 <= dates[language].suffix.length ? dates[language].suffix[date.getUTCDate() % 10 - 1] : ''),
1957          // hour
1958          a: (dates[language].meridiem.length === 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''),
1959          g: (date.getUTCHours() % 12 === 0 ? 12 : date.getUTCHours() % 12),
1960          G: date.getUTCHours(),
1961          // minute
1962          i: date.getUTCMinutes(),
1963          // second
1964          s: date.getUTCSeconds()
1965        };
1966        val.m = (val.n < 10 ? '0' : '') + val.n;
1967        val.d = (val.j < 10 ? '0' : '') + val.j;
1968        val.A = val.a.toString().toUpperCase();
1969        val.h = (val.g < 10 ? '0' : '') + val.g;
1970        val.H = (val.G < 10 ? '0' : '') + val.G;
1971        val.i = (val.i < 10 ? '0' : '') + val.i;
1972        val.s = (val.s < 10 ? '0' : '') + val.s;
1973      } else {
1974        throw new Error('Invalid format type.');
1975      }
1976      var date = [],
1977        seps = $.extend([], format.separators);
1978      for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
1979        if (seps.length) {
1980          date.push(seps.shift());
1981        }
1982        date.push(val[format.parts[i]]);
1983      }
1984      if (seps.length) {
1985        date.push(seps.shift());
1986      }
1987      return date.join('');
1988    },
1989    convertViewMode:  function (viewMode) {
1990      switch (viewMode) {
1991        case 4:
1992        case 'decade':
1993          viewMode = 4;
1994          break;
1995        case 3:
1996        case 'year':
1997          viewMode = 3;
1998          break;
1999        case 2:
2000        case 'month':
2001          viewMode = 2;
2002          break;
2003        case 1:
2004        case 'day':
2005          viewMode = 1;
2006          break;
2007        case 0:
2008        case 'hour':
2009          viewMode = 0;
2010          break;
2011      }
2012
2013      return viewMode;
2014    },
2015    headTemplate: '<thead>' +
2016                '<tr>' +
2017                '<th class="prev"><i class="{leftArrow}"/></th>' +
2018                '<th colspan="5" class="switch"></th>' +
2019                '<th class="next"><i class="{rightArrow}"/></th>' +
2020                '</tr>' +
2021      '</thead>',
2022    headTemplateV3: '<thead>' +
2023                '<tr>' +
2024                '<th class="prev"><span class="{leftArrow}"></span> </th>' +
2025                '<th colspan="5" class="switch"></th>' +
2026                '<th class="next"><span class="{rightArrow}"></span> </th>' +
2027                '</tr>' +
2028      '</thead>',
2029    contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
2030    footTemplate: '<tfoot>' + 
2031                    '<tr><th colspan="7" class="today"></th></tr>' +
2032                    '<tr><th colspan="7" class="clear"></th></tr>' +
2033                  '</tfoot>'
2034  };
2035  DPGlobal.template = '<div class="datetimepicker">' +
2036    '<div class="datetimepicker-minutes">' +
2037    '<table class=" table-condensed">' +
2038    DPGlobal.headTemplate +
2039    DPGlobal.contTemplate +
2040    DPGlobal.footTemplate +
2041    '</table>' +
2042    '</div>' +
2043    '<div class="datetimepicker-hours">' +
2044    '<table class=" table-condensed">' +
2045    DPGlobal.headTemplate +
2046    DPGlobal.contTemplate +
2047    DPGlobal.footTemplate +
2048    '</table>' +
2049    '</div>' +
2050    '<div class="datetimepicker-days">' +
2051    '<table class=" table-condensed">' +
2052    DPGlobal.headTemplate +
2053    '<tbody></tbody>' +
2054    DPGlobal.footTemplate +
2055    '</table>' +
2056    '</div>' +
2057    '<div class="datetimepicker-months">' +
2058    '<table class="table-condensed">' +
2059    DPGlobal.headTemplate +
2060    DPGlobal.contTemplate +
2061    DPGlobal.footTemplate +
2062    '</table>' +
2063    '</div>' +
2064    '<div class="datetimepicker-years">' +
2065    '<table class="table-condensed">' +
2066    DPGlobal.headTemplate +
2067    DPGlobal.contTemplate +
2068    DPGlobal.footTemplate +
2069    '</table>' +
2070    '</div>' +
2071    '</div>';
2072  DPGlobal.templateV3 = '<div class="datetimepicker">' +
2073    '<div class="datetimepicker-minutes">' +
2074    '<table class=" table-condensed">' +
2075    DPGlobal.headTemplateV3 +
2076    DPGlobal.contTemplate +
2077    DPGlobal.footTemplate +
2078    '</table>' +
2079    '</div>' +
2080    '<div class="datetimepicker-hours">' +
2081    '<table class=" table-condensed">' +
2082    DPGlobal.headTemplateV3 +
2083    DPGlobal.contTemplate +
2084    DPGlobal.footTemplate +
2085    '</table>' +
2086    '</div>' +
2087    '<div class="datetimepicker-days">' +
2088    '<table class=" table-condensed">' +
2089    DPGlobal.headTemplateV3 +
2090    '<tbody></tbody>' +
2091    DPGlobal.footTemplate +
2092    '</table>' +
2093    '</div>' +
2094    '<div class="datetimepicker-months">' +
2095    '<table class="table-condensed">' +
2096    DPGlobal.headTemplateV3 +
2097    DPGlobal.contTemplate +
2098    DPGlobal.footTemplate +
2099    '</table>' +
2100    '</div>' +
2101    '<div class="datetimepicker-years">' +
2102    '<table class="table-condensed">' +
2103    DPGlobal.headTemplateV3 +
2104    DPGlobal.contTemplate +
2105    DPGlobal.footTemplate +
2106    '</table>' +
2107    '</div>' +
2108    '</div>';
2109  $.fn.datetimepicker.DPGlobal = DPGlobal;
2110
2111  /* DATETIMEPICKER NO CONFLICT
2112   * =================== */
2113
2114  $.fn.datetimepicker.noConflict = function () {
2115    $.fn.datetimepicker = old;
2116    return this;
2117  };
2118
2119  /* DATETIMEPICKER DATA-API
2120   * ================== */
2121
2122  $(document).on(
2123    'focus.datetimepicker.data-api click.datetimepicker.data-api',
2124    '[data-provide="datetimepicker"]',
2125    function (e) {
2126      var $this = $(this);
2127      if ($this.data('datetimepicker')) return;
2128      e.preventDefault();
2129      // component click requires us to explicitly show it
2130      $this.datetimepicker('show');
2131    }
2132  );
2133  $(function () {
2134    $('[data-provide="datetimepicker-inline"]').datetimepicker();
2135  });
2136
2137}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.