PageSourceSearch

https://matexmotors.com/Scripts/js/bootstrap-datetimepicker.js

js matexmotors.com collected 2026-10-02 00:53:35 UTC 70,137 bytes, 1,967 lines download raw bytes

1/* =========================================================
2 * bootstrap-datetimepicker.js
3 * =========================================================
4 * Copyright 2012 Stefan Petre
5 *
6 * Improvements by Andrew Rowls
7 * Improvements by Sébastien Malot
8 * Improvements by Yun Lai
9 * Improvements by Kenneth Henderick
10 * Improvements by CuGBabyBeaR
11 * Improvements by Christian Vaas <[email protected]>
12 *
13 * Project URL : http://www.malot.fr/bootstrap-datetimepicker
14 *
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 * http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 * ========================================================= */
27
28(function(factory){
29    if (typeof define === 'function' && define.amd)
30      define(['jquery'], factory);
31    else if (typeof exports === 'object')
32      factory(require('jquery'));
33    else
34      factory(jQuery);
35
36}(function($, undefined){
37
38  // Add ECMA262-5 Array methods if not supported natively (IE8)
39  if (!('indexOf' in Array.prototype)) {
40    Array.prototype.indexOf = function (find, i) {
41      if (i === undefined) i = 0;
42      if (i < 0) i += this.length;
43      if (i < 0) i = 0;
44      for (var n = this.length; i < n; i++) {
45        if (i in this && this[i] === find) {
46          return i;
47        }
48      }
49      return -1;
50    }
51  }
52
53  // Add timezone abbreviation support for ie6+, Chrome, Firefox
54  function timeZoneAbbreviation() {
55    var abbreviation, date, formattedStr, i, len, matchedStrings, ref, str;
56    date = (new Date()).toString();
57    formattedStr = ((ref = date.split('(')[1]) != null ? ref.slice(0, -1) : 0) || date.split(' ');
58    if (formattedStr instanceof Array) {
59      matchedStrings = [];
60      for (var i = 0, len = formattedStr.length; i < len; i++) {
61        str = formattedStr[i];
62        if ((abbreviation = (ref = str.match(/\b[A-Z]+\b/)) !== null) ? ref[0] : 0) {
63          matchedStrings.push(abbreviation);
64        }
65      }
66      formattedStr = matchedStrings.pop();
67    }
68    return formattedStr;
69  }
70
71  function UTCDate() {
72    return new Date(Date.UTC.apply(Date, arguments));
73  }
74
75  // Picker object
76  var Datetimepicker = function (element, options) {
77    var that = this;
78
79    this.element = $(element);
80
81    // add container for single page application
82    // when page switch the datetimepicker div will be removed also.
83    this.container = options.container || 'body';
84
85    this.language = options.language || this.element.data('date-language') || 'en';
86    this.language = this.language in dates ? this.language : this.language.split('-')[0]; // fr-CA fallback to fr
87    this.language = this.language in dates ? this.language : 'en';
88    this.isRTL = dates[this.language].rtl || false;
89    this.formatType = options.formatType || this.element.data('format-type') || 'standard';
90    this.format = DPGlobal.parseFormat(options.format || this.element.data('date-format') || dates[this.language].format || DPGlobal.getDefaultFormat(this.formatType, 'input'), this.formatType);
91    this.isInline = false;
92    this.isVisible = false;
93    this.isInput = this.element.is('input');
94    this.fontAwesome = options.fontAwesome || this.element.data('font-awesome') || false;
95
96    this.bootcssVer = options.bootcssVer || (this.isInput ? (this.element.is('.form-control') ? 3 : 2) : ( this.bootcssVer = this.element.is('.input-group') ? 3 : 2 ));
97
98    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 .fa-calendar, .input-group-addon .fa-clock-o').parent() : this.element.find('.add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o').parent()) : false;
99    this.componentReset = this.element.is('.date') ? ( this.bootcssVer === 3 ? this.element.find('.input-group-addon .glyphicon-remove, .input-group-addon .fa-times').parent():this.element.find('.add-on .icon-remove, .add-on .fa-times').parent()) : false;
100    this.hasInput = this.component && this.element.find('input').length;
101    if (this.component && this.component.length === 0) {
102      this.component = false;
103    }
104    this.linkField = options.linkField || this.element.data('link-field') || false;
105    this.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || DPGlobal.getDefaultFormat(this.formatType, 'link'), this.formatType);
106    this.minuteStep = options.minuteStep || this.element.data('minute-step') || 5;
107    this.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'bottom-right';
108    this.showMeridian = options.showMeridian || this.element.data('show-meridian') || false;
109    this.initialDate = options.initialDate || new Date();
110    this.zIndex = options.zIndex || this.element.data('z-index') || undefined;
111    this.title = typeof options.title === 'undefined' ? false : options.title;
112    this.timezone = options.timezone || timeZoneAbbreviation();
113
114    this.icons = {
115      leftArrow: this.fontAwesome ? 'fa-arrow-left' : (this.bootcssVer === 3 ? 'glyphicon-arrow-left' : 'icon-arrow-left'),
116      rightArrow: this.fontAwesome ? 'fa-arrow-right' : (this.bootcssVer === 3 ? 'glyphicon-arrow-right' : 'icon-arrow-right')
117    }
118    this.icontype = this.fontAwesome ? 'fa' : 'glyphicon';
119
120    this._attachEvents();
121
122    this.clickedOutside = function (e) {
123        // Clicked outside the datetimepicker, hide it
124        if ($(e.target).closest('.datetimepicker').length === 0) {
125            that.hide();
126        }
127    }
128
129    this.formatViewType = 'datetime';
130    if ('formatViewType' in options) {
131      this.formatViewType = options.formatViewType;
132    } else if ('formatViewType' in this.element.data()) {
133      this.formatViewType = this.element.data('formatViewType');
134    }
135
136    this.minView = 0;
137    if ('minView' in options) {
138      this.minView = options.minView;
139    } else if ('minView' in this.element.data()) {
140      this.minView = this.element.data('min-view');
141    }
142    this.minView = DPGlobal.convertViewMode(this.minView);
143
144    this.maxView = DPGlobal.modes.length - 1;
145    if ('maxView' in options) {
146      this.maxView = options.maxView;
147    } else if ('maxView' in this.element.data()) {
148      this.maxView = this.element.data('max-view');
149    }
150    this.maxView = DPGlobal.convertViewMode(this.maxView);
151
152    this.wheelViewModeNavigation = false;
153    if ('wheelViewModeNavigation' in options) {
154      this.wheelViewModeNavigation = options.wheelViewModeNavigation;
155    } else if ('wheelViewModeNavigation' in this.element.data()) {
156      this.wheelViewModeNavigation = this.element.data('view-mode-wheel-navigation');
157    }
158
159    this.wheelViewModeNavigationInverseDirection = false;
160
161    if ('wheelViewModeNavigationInverseDirection' in options) {
162      this.wheelViewModeNavigationInverseDirection = options.wheelViewModeNavigationInverseDirection;
163    } else if ('wheelViewModeNavigationInverseDirection' in this.element.data()) {
164      this.wheelViewModeNavigationInverseDirection = this.element.data('view-mode-wheel-navigation-inverse-dir');
165    }
166
167    this.wheelViewModeNavigationDelay = 100;
168    if ('wheelViewModeNavigationDelay' in options) {
169      this.wheelViewModeNavigationDelay = options.wheelViewModeNavigationDelay;
170    } else if ('wheelViewModeNavigationDelay' in this.element.data()) {
171      this.wheelViewModeNavigationDelay = this.element.data('view-mode-wheel-navigation-delay');
172    }
173
174    this.startViewMode = 2;
175    if ('startView' in options) {
176      this.startViewMode = options.startView;
177    } else if ('startView' in this.element.data()) {
178      this.startViewMode = this.element.data('start-view');
179    }
180    this.startViewMode = DPGlobal.convertViewMode(this.startViewMode);
181    this.viewMode = this.startViewMode;
182
183    this.viewSelect = this.minView;
184    if ('viewSelect' in options) {
185      this.viewSelect = options.viewSelect;
186    } else if ('viewSelect' in this.element.data()) {
187      this.viewSelect = this.element.data('view-select');
188    }
189    this.viewSelect = DPGlobal.convertViewMode(this.viewSelect);
190
191    this.forceParse = true;
192    if ('forceParse' in options) {
193      this.forceParse = options.forceParse;
194    } else if ('dateForceParse' in this.element.data()) {
195      this.forceParse = this.element.data('date-force-parse');
196    }
197    var template = this.bootcssVer === 3 ? DPGlobal.templateV3 : DPGlobal.template;
198    while (template.indexOf('{iconType}') !== -1) {
199      template = template.replace('{iconType}', this.icontype);
200    }
201    while (template.indexOf('{leftArrow}') !== -1) {
202      template = template.replace('{leftArrow}', this.icons.leftArrow);
203    }
204    while (template.indexOf('{rightArrow}') !== -1) {
205      template = template.replace('{rightArrow}', this.icons.rightArrow);
206    }
207    this.picker = $(template)
208      .appendTo(this.isInline ? this.element : this.container) // 'body')
209      .on({
210        click:     $.proxy(this.click, this),
211        mousedown: $.proxy(this.mousedown, this)
212      });
213
214    if (this.wheelViewModeNavigation) {
215      if ($.fn.mousewheel) {
216        this.picker.on({mousewheel: $.proxy(this.mousewheel, this)});
217      } else {
218        console.log('Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option');
219      }
220    }
221
222    if (this.isInline) {
223      this.picker.addClass('datetimepicker-inline');
224    } else {
225      this.picker.addClass('datetimepicker-dropdown-' + this.pickerPosition + ' dropdown-menu');
226    }
227    if (this.isRTL) {
228      this.picker.addClass('datetimepicker-rtl');
229      var selector = this.bootcssVer === 3 ? '.prev span, .next span' : '.prev i, .next i';
230      this.picker.find(selector).toggleClass(this.icons.leftArrow + ' ' + this.icons.rightArrow);
231    }
232
233    $(document).on('mousedown touchend', this.clickedOutside);
234
235    this.autoclose = false;
236    if ('autoclose' in options) {
237      this.autoclose = options.autoclose;
238    } else if ('dateAutoclose' in this.element.data()) {
239      this.autoclose = this.element.data('date-autoclose');
240    }
241
242    this.keyboardNavigation = true;
243    if ('keyboardNavigation' in options) {
244      this.keyboardNavigation = options.keyboardNavigation;
245    } else if ('dateKeyboardNavigation' in this.element.data()) {
246      this.keyboardNavigation = this.element.data('date-keyboard-navigation');
247    }
248
249    this.todayBtn = (options.todayBtn || this.element.data('date-today-btn') || false);
250    this.clearBtn = (options.clearBtn || this.element.data('date-clear-btn') || false);
251    this.todayHighlight = (options.todayHighlight || this.element.data('date-today-highlight') || false);
252
253    this.weekStart = 0;
254    if (typeof options.weekStart !== 'undefined') {
255      this.weekStart = options.weekStart;
256    } else if (typeof this.element.data('date-weekstart') !== 'undefined') {
257      this.weekStart = this.element.data('date-weekstart');
258    } else if (typeof dates[this.language].weekStart !== 'undefined') {
259      this.weekStart = dates[this.language].weekStart;
260    }
261    this.weekStart = this.weekStart % 7;
262    this.weekEnd = ((this.weekStart + 6) % 7);
263    this.onRenderDay = function (date) {
264      var render = (options.onRenderDay || function () { return []; })(date);
265      if (typeof render === 'string') {
266        render = [render];
267      }
268      var res = ['day'];
269      return res.concat((render ? render : []));
270    };
271    this.onRenderHour = function (date) {
272      var render = (options.onRenderHour || function () { return []; })(date);
273      var res = ['hour'];
274      if (typeof render === 'string') {
275        render = [render];
276      }
277      return res.concat((render ? render : []));
278    };
279    this.onRenderMinute = function (date) {
280      var render = (options.onRenderMinute || function () { return []; })(date);
281      var res = ['minute'];
282      if (typeof render === 'string') {
283        render = [render];
284      }
285      if (date < this.startDate || date > this.endDate) {
286        res.push('disabled');
287      } else if (Math.floor(this.date.getUTCMinutes() / this.minuteStep) === Math.floor(date.getUTCMinutes() / this.minuteStep)) {
288        res.push('active');
289      }
290      return res.concat((render ? render : []));
291    };
292    this.onRenderYear = function (date) {
293      var render = (options.onRenderYear || function () { return []; })(date);
294      var res = ['year'];
295      if (typeof render === 'string') {
296        render = [render];
297      }
298      if (this.date.getUTCFullYear() === date.getUTCFullYear()) {
299        res.push('active');
300      }
301      var currentYear = date.getUTCFullYear();
302      var endYear = this.endDate.getUTCFullYear();
303      if (date < this.startDate || currentYear > endYear) {
304        res.push('disabled');
305      }
306      return res.concat((render ? render : []));
307    }
308    this.onRenderMonth = function (date) {
309      var render = (options.onRenderMonth || function () { return []; })(date);
310      var res = ['month'];
311      if (typeof render === 'string') {
312        render = [render];
313      }
314      return res.concat((render ? render : []));
315    }
316    this.startDate = new Date(-8639968443048000);
317    this.endDate = new Date(8639968443048000);
318    this.datesDisabled = [];
319    this.daysOfWeekDisabled = [];
320    this.setStartDate(options.startDate || this.element.data('date-startdate'));
321    this.setEndDate(options.endDate || this.element.data('date-enddate'));
322    this.setDatesDisabled(options.datesDisabled || this.element.data('date-dates-disabled'));
323    this.setDaysOfWeekDisabled(options.daysOfWeekDisabled || this.element.data('date-days-of-week-disabled'));
324    this.setMinutesDisabled(options.minutesDisabled || this.element.data('date-minute-disabled'));
325    this.setHoursDisabled(options.hoursDisabled || this.element.data('date-hour-disabled'));
326    this.fillDow();
327    this.fillMonths();
328    this.update();
329    this.showMode();
330
331    if (this.isInline) {
332      this.show();
333    }
334  };
335
336  Datetimepicker.prototype = {
337    constructor: Datetimepicker,
338
339    _events:       [],
340    _attachEvents: function () {
341      this._detachEvents();
342      if (this.isInput) { // single input
343        this._events = [
344          [this.element, {
345            focus:   $.proxy(this.show, this),
346            keyup:   $.proxy(this.update, this),
347            keydown: $.proxy(this.keydown, this)
348          }]
349        ];
350      }
351      else if (this.component && this.hasInput) { // component: input + button
352        this._events = [
353          // For components that are not readonly, allow keyboard nav
354          [this.element.find('input'), {
355            focus:   $.proxy(this.show, this),
356            keyup:   $.proxy(this.update, this),
357            keydown: $.proxy(this.keydown, this)
358          }],
359          [this.component, {
360            click: $.proxy(this.show, this)
361          }]
362        ];
363        if (this.componentReset) {
364          this._events.push([
365            this.componentReset,
366            {click: $.proxy(this.reset, this)}
367          ]);
368        }
369      }
370      else if (this.element.is('div')) {  // inline datetimepicker
371        this.isInline = true;
372      }
373      else {
374        this._events = [
375          [this.element, {
376            click: $.proxy(this.show, this)
377          }]
378        ];
379      }
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.on(ev);
384      }
385    },
386
387    _detachEvents: function () {
388      for (var i = 0, el, ev; i < this._events.length; i++) {
389        el = this._events[i][0];
390        ev = this._events[i][1];
391        el.off(ev);
392      }
393      this._events = [];
394    },
395
396    show: function (e) {
397      this.picker.show();
398      this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
399      if (this.forceParse) {
400        this.update();
401      }
402      this.place();
403      $(window).on('resize', $.proxy(this.place, this));
404      if (e) {
405        e.stopPropagation();
406        e.preventDefault();
407      }
408      this.isVisible = true;
409      this.element.trigger({
410        type: 'show',
411        date: this.date
412      });
413    },
414
415    hide: function () {
416      if (!this.isVisible) return;
417      if (this.isInline) return;
418      this.picker.hide();
419      $(window).off('resize', this.place);
420      this.viewMode = this.startViewMode;
421      this.showMode();
422      if (!this.isInput) {
423        $(document).off('mousedown', this.hide);
424      }
425
426      if (
427        this.forceParse &&
428          (
429            this.isInput && this.element.val() ||
430              this.hasInput && this.element.find('input').val()
431            )
432        )
433        this.setValue();
434      this.isVisible = false;
435      this.element.trigger({
436        type: 'hide',
437        date: this.date
438      });
439    },
440
441    remove: function () {
442      this._detachEvents();
443      $(document).off('mousedown', this.clickedOutside);
444      this.picker.remove();
445      delete this.picker;
446      delete this.element.data().datetimepicker;
447    },
448
449    getDate: function () {
450      var d = this.getUTCDate();
451        if (d === null || typeof d === 'undefined') {
452        return null;
453      }
454      return new Date(d.getTime() + (d.getTimezoneOffset() * 60000));
455    },
456
457    getUTCDate: function () {
458      return this.date;
459    },
460
461    getInitialDate: function () {
462      return this.initialDate
463    },
464
465    setInitialDate: function (initialDate) {
466      this.initialDate = initialDate;
467    },
468
469    setDate: function (d) {
470      this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset() * 60000)));
471    },
472
473    setUTCDate: function (d) {
474      if (d >= this.startDate && d <= this.endDate) {
475        this.date = d;
476        this.setValue();
477        this.viewDate = this.date;
478        this.fill();
479      } else {
480        this.element.trigger({
481          type:      'outOfRange',
482          date:      d,
483          startDate: this.startDate,
484          endDate:   this.endDate
485        });
486      }
487    },
488
489    setFormat: function (format) {
490      this.format = DPGlobal.parseFormat(format, this.formatType);
491      var element;
492      if (this.isInput) {
493        element = this.element;
494      } else if (this.component) {
495        element = this.element.find('input');
496      }
497      if (element && element.val()) {
498        this.setValue();
499      }
500    },
501
502    setValue: function () {
503      var formatted = this.getFormattedDate();
504      if (!this.isInput) {
505        if (this.component) {
506          this.element.find('input').val(formatted);
507        }
508        this.element.data('date', formatted);
509      } else {
510        this.element.val(formatted);
511      }
512      if (this.linkField) {
513        $('#' + this.linkField).val(this.getFormattedDate(this.linkFormat));
514      }
515    },
516
517    getFormattedDate: function (format) {
518      format = format || this.format;
519      return DPGlobal.formatDate(this.date, format, this.language, this.formatType, this.timezone);
520    },
521
522    setStartDate: function (startDate) {
523      this.startDate = startDate || this.startDate;
524      if (this.startDate.valueOf() !== 8639968443048000) {
525        this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language, this.formatType, this.timezone);
526      }
527      this.update();
528      this.updateNavArrows();
529    },
530
531    setEndDate: function (endDate) {
532      this.endDate = endDate || this.endDate;
533      if (this.endDate.valueOf() !== 8639968443048000) {
534        this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language, this.formatType, this.timezone);
535      }
536      this.update();
537      this.updateNavArrows();
538    },
539
540    setDatesDisabled: function (datesDisabled) {
541      this.datesDisabled = datesDisabled || [];
542      if (!$.isArray(this.datesDisabled)) {
543        this.datesDisabled = this.datesDisabled.split(/,\s*/);
544      }
545      var mThis = this;
546      this.datesDisabled = $.map(this.datesDisabled, function (d) {
547        return DPGlobal.parseDate(d, mThis.format, mThis.language, mThis.formatType, mThis.timezone).toDateString();
548      });
549      this.update();
550      this.updateNavArrows();
551    },
552
553    setTitle: function (selector, value) {
554      return this.picker.find(selector)
555        .find('th:eq(1)')
556        .text(this.title === false ? value : this.title);
557    },
558
559    setDaysOfWeekDisabled: function (daysOfWeekDisabled) {
560      this.daysOfWeekDisabled = daysOfWeekDisabled || [];
561      if (!$.isArray(this.daysOfWeekDisabled)) {
562        this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
563      }
564      this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) {
565        return parseInt(d, 10);
566      });
567      this.update();
568      this.updateNavArrows();
569    },
570
571    setMinutesDisabled: function (minutesDisabled) {
572      this.minutesDisabled = minutesDisabled || [];
573      if (!$.isArray(this.minutesDisabled)) {
574        this.minutesDisabled = this.minutesDisabled.split(/,\s*/);
575      }
576      this.minutesDisabled = $.map(this.minutesDisabled, function (d) {
577        return parseInt(d, 10);
578      });
579      this.update();
580      this.updateNavArrows();
581    },
582
583    setHoursDisabled: function (hoursDisabled) {
584      this.hoursDisabled = hoursDisabled || [];
585      if (!$.isArray(this.hoursDisabled)) {
586        this.hoursDisabled = this.hoursDisabled.split(/,\s*/);
587      }
588      this.hoursDisabled = $.map(this.hoursDisabled, function (d) {
589        return parseInt(d, 10);
590      });
591      this.update();
592      this.updateNavArrows();
593    },
594
595    place: function () {
596      if (this.isInline) return;
597
598      if (!this.zIndex) {
599        var index_highest = 0;
600        $('div').each(function () {
601          var index_current = parseInt($(this).css('zIndex'), 10);
602          if (index_current > index_highest) {
603            index_highest = index_current;
604          }
605        });
606        this.zIndex = index_highest + 10;
607      }
608
609      var offset, top, left, containerOffset;
610      if (this.container instanceof $) {
611        containerOffset = this.container.offset();
612      } else {
613        containerOffset = $(this.container).offset();
614      }
615
616      if (this.component) {
617        offset = this.component.offset();
618        left = offset.left;
619        if (this.pickerPosition === 'bottom-left' || this.pickerPosition === 'top-left') {
620          left += this.component.outerWidth() - this.picker.outerWidth();
621        }
622      } else {
623        offset = this.element.offset();
624        left = offset.left;
625        if (this.pickerPosition === 'bottom-left' || this.pickerPosition === 'top-left') {
626          left += this.element.outerWidth() - this.picker.outerWidth();
627        }
628      }
629
630      var bodyWidth = document.body.clientWidth || window.innerWidth;
631      if (left + 220 > bodyWidth) {
632        left = bodyWidth - 220;
633      }
634
635      if (this.pickerPosition === 'top-left' || this.pickerPosition === 'top-right') {
636        top = offset.top - this.picker.outerHeight();
637      } else {
638        top = offset.top + this.height;
639      }
640
641      top = top - containerOffset.top;
642      left = left - containerOffset.left;
643
644      this.picker.css({
645        top:    top,
646        left:   left,
647        zIndex: this.zIndex
648      });
649    },
650
651    hour_minute: "^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]",
652
653    update: function () {
654      var date, fromArgs = false;
655      if (arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
656        date = arguments[0];
657        fromArgs = true;
658      } else {
659        date = (this.isInput ? this.element.val() : this.element.find('input').val()) || this.element.data('date') || this.initialDate;
660        if (typeof date === 'string') {
661          date = date.replace(/^\s+|\s+$/g,'');
662        }
663      }
664
665      if (!date) {
666        date = new Date();
667        fromArgs = false;
668      }
669
670      if (typeof date === "string") {
671        if (new RegExp(this.hour_minute).test(date) || new RegExp(this.hour_minute + ":[0-5][0-9]").test(date)) {
672          date = this.getDate()
673        }
674      }
675
676      this.date = DPGlobal.parseDate(date, this.format, this.language, this.formatType, this.timezone);
677
678      if (fromArgs) this.setValue();
679
680      if (this.date < this.startDate) {
681        this.viewDate = new Date(this.startDate);
682      } else if (this.date > this.endDate) {
683        this.viewDate = new Date(this.endDate);
684      } else {
685        this.viewDate = new Date(this.date);
686      }
687      this.fill();
688    },
689
690    fillDow: function () {
691      var dowCnt = this.weekStart,
692        html = '<tr>';
693      while (dowCnt < this.weekStart + 7) {
694        html += '<th class="dow">' + dates[this.language].daysMin[(dowCnt++) % 7] + '</th>';
695      }
696      html += '</tr>';
697      this.picker.find('.datetimepicker-days thead').append(html);
698    },
699
700    fillMonths: function () {
701      var html = '';
702      var d = new Date(this.viewDate);
703      for (var i = 0; i < 12; i++) {
704        d.setUTCMonth(i);
705        var classes = this.onRenderMonth(d);
706        html += '<span class="' + classes.join(' ') + '">' + dates[this.language].monthsShort[i] + '</span>';
707      }
708      this.picker.find('.datetimepicker-months td').html(html);
709    },
710
711    fill: function () {
712      if (!this.date || !this.viewDate) {
713        return;
714      }
715      var d = new Date(this.viewDate),
716        year = d.getUTCFullYear(),
717        month = d.getUTCMonth(),
718        dayMonth = d.getUTCDate(),
719        hours = d.getUTCHours(),
720        startYear = this.startDate.getUTCFullYear(),
721        startMonth = this.startDate.getUTCMonth(),
722        endYear = this.endDate.getUTCFullYear(),
723        endMonth = this.endDate.getUTCMonth() + 1,
724        currentDate = (new UTCDate(this.date.getUTCFullYear(), this.date.getUTCMonth(), this.date.getUTCDate())).valueOf(),
725        today = new Date();
726      this.setTitle('.datetimepicker-days', dates[this.language].months[month] + ' ' + year)
727      if (this.formatViewType === 'time') {
728        var formatted = this.getFormattedDate();
729        this.setTitle('.datetimepicker-hours', formatted);
730        this.setTitle('.datetimepicker-minutes', formatted);
731      } else {
732        this.setTitle('.datetimepicker-hours', dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
733        this.setTitle('.datetimepicker-minutes', dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
734      }
735      this.picker.find('tfoot th.today')
736        .text(dates[this.language].today || dates['en'].today)
737        .toggle(this.todayBtn !== false);
738      this.picker.find('tfoot th.clear')
739        .text(dates[this.language].clear || dates['en'].clear)
740        .toggle(this.clearBtn !== false);
741      this.updateNavArrows();
742      this.fillMonths();
743      var prevMonth = UTCDate(year, month - 1, 28, 0, 0, 0, 0),
744        day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
745      prevMonth.setUTCDate(day);
746      prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7) % 7);
747      var nextMonth = new Date(prevMonth);
748      nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
749      nextMonth = nextMonth.valueOf();
750      var html = [];
751      var classes;
752      while (prevMonth.valueOf() < nextMonth) {
753        if (prevMonth.getUTCDay() === this.weekStart) {
754          html.push('<tr>');
755        }
756        classes = this.onRenderDay(prevMonth);
757        if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() === year && prevMonth.getUTCMonth() < month)) {
758          classes.push('old');
759        } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() === year && prevMonth.getUTCMonth() > month)) {
760          classes.push('new');
761        }
762        // Compare internal UTC date with local today, not UTC today
763        if (this.todayHighlight &&
764          prevMonth.getUTCFullYear() === today.getFullYear() &&
765          prevMonth.getUTCMonth() === today.getMonth() &&
766          prevMonth.getUTCDate() === today.getDate()) {
767          classes.push('today');
768        }
769        if (prevMonth.valueOf() === currentDate) {
770          classes.push('active');
771        }
772        if ((prevMonth.valueOf() + 86400000) <= this.startDate || prevMonth.valueOf() > this.endDate ||
773          $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1 ||
774          $.inArray(prevMonth.toDateString(), this.datesDisabled) !== -1) {
775          classes.push('disabled');
776        }
777        html.push('<td class="' + classes.join(' ') + '">' + prevMonth.getUTCDate() + '</td>');
778        if (prevMonth.getUTCDay() === this.weekEnd) {
779          html.push('</tr>');
780        }
781        prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
782      }
783      this.picker.find('.datetimepicker-days tbody').empty().append(html.join(''));
784
785      html = [];
786      var txt = '', meridian = '', meridianOld = '';
787      var hoursDisabled = this.hoursDisabled || [];
788      d = new Date(this.viewDate)
789      for (var i = 0; i < 24; i++) {
790        d.setUTCHours(i);
791        classes = this.onRenderHour(d);
792        if (hoursDisabled.indexOf(i) !== -1) {
793          classes.push('disabled');
794        }
795        var actual = UTCDate(year, month, dayMonth, i);
796        // We want the previous hour for the startDate
797        if ((actual.valueOf() + 3600000) <= this.startDate || actual.valueOf() > this.endDate) {
798          classes.push('disabled');
799        } else if (hours === i) {
800          classes.push('active');
801        }
802        if (this.showMeridian && dates[this.language].meridiem.length === 2) {
803          meridian = (i < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]);
804          if (meridian !== meridianOld) {
805            if (meridianOld !== '') {
806              html.push('</fieldset>');
807            }
808            html.push('<fieldset class="hour"><legend>' + meridian.toUpperCase() + '</legend>');
809          }
810          meridianOld = meridian;
811          txt = (i % 12 ? i % 12 : 12);
812          if (i < 12) {
813            classes.push('hour_am');
814          } else {
815            classes.push('hour_pm');
816          }
817          html.push('<span class="' + classes.join(' ') + '">' + txt + '</span>');
818          if (i === 23) {
819            html.push('</fieldset>');
820          }
821        } else {
822          txt = i + ':00';
823          html.push('<span class="' + classes.join(' ') + '">' + txt + '</span>');
824        }
825      }
826      this.picker.find('.datetimepicker-hours td').html(html.join(''));
827
828      html = [];
829      txt = '';
830      meridian = '';
831      meridianOld = '';
832      var minutesDisabled = this.minutesDisabled || [];
833      d = new Date(this.viewDate);
834      for (var i = 0; i < 60; i += this.minuteStep) {
835        if (minutesDisabled.indexOf(i) !== -1) continue;
836        d.setUTCMinutes(i);
837        d.setUTCSeconds(0);
838        classes = this.onRenderMinute(d);
839        if (this.showMeridian && dates[this.language].meridiem.length === 2) {
840          meridian = (hours < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]);
841          if (meridian !== meridianOld) {
842            if (meridianOld !== '') {
843              html.push('</fieldset>');
844            }
845            html.push('<fieldset class="minute"><legend>' + meridian.toUpperCase() + '</legend>');
846          }
847          meridianOld = meridian;
848          txt = (hours % 12 ? hours % 12 : 12);
849          html.push('<span class="' + classes.join(' ') + '">' + txt + ':' + (i < 10 ? '0' + i : i) + '</span>');
850          if (i === 59) {
851            html.push('</fieldset>');
852          }
853        } else {
854          txt = i + ':00';
855          html.push('<span class="' + classes.join(' ') + '">' + hours + ':' + (i < 10 ? '0' + i : i) + '</span>');
856        }
857      }
858      this.picker.find('.datetimepicker-minutes td').html(html.join(''));
859
860      var currentYear = this.date.getUTCFullYear();
861      var months = this.setTitle('.datetimepicker-months', year)
862        .end()
863        .find('.month').removeClass('active');
864      if (currentYear === year) {
865        // getUTCMonths() returns 0 based, and we need to select the next one
866        // To cater bootstrap 2 we don't need to select the next one
867        months.eq(this.date.getUTCMonth()).addClass('active');
868      }
869      if (year < startYear || year > endYear) {
870        months.addClass('disabled');
871      }
872      if (year === startYear) {
873        months.slice(0, startMonth).addClass('disabled');
874      }
875      if (year === endYear) {
876        months.slice(endMonth).addClass('disabled');
877      }
878
879      html = '';
880      year = parseInt(year / 10, 10) * 10;
881      var yearCont = this.setTitle('.datetimepicker-years', year + '-' + (year + 9))
882        .end()
883        .find('td');
884      year -= 1;
885      d = new Date(this.viewDate);
886      for (var i = -1; i < 11; i++) {
887        d.setUTCFullYear(year);
888        classes = this.onRenderYear(d);
889        if (i === -1 || i === 10) {
890          classes.push(old);
891        }
892        html += '<span class="' + classes.join(' ') + '">' + year + '</span>';
893        year += 1;
894      }
895      yearCont.html(html);
896      this.place();
897    },
898
899    updateNavArrows: function () {
900      var d = new Date(this.viewDate),
901        year = d.getUTCFullYear(),
902        month = d.getUTCMonth(),
903        day = d.getUTCDate(),
904        hour = d.getUTCHours();
905      switch (this.viewMode) {
906        case 0:
907          if (year <= this.startDate.getUTCFullYear()
908            && month <= this.startDate.getUTCMonth()
909            && day <= this.startDate.getUTCDate()
910            && hour <= this.startDate.getUTCHours()) {
911            this.picker.find('.prev').css({visibility: 'hidden'});
912          } else {
913            this.picker.find('.prev').css({visibility: 'visible'});
914          }
915          if (year >= this.endDate.getUTCFullYear()
916            && month >= this.endDate.getUTCMonth()
917            && day >= this.endDate.getUTCDate()
918            && hour >= this.endDate.getUTCHours()) {
919            this.picker.find('.next').css({visibility: 'hidden'});
920          } else {
921            this.picker.find('.next').css({visibility: 'visible'});
922          }
923          break;
924        case 1:
925          if (year <= this.startDate.getUTCFullYear()
926            && month <= this.startDate.getUTCMonth()
927            && day <= this.startDate.getUTCDate()) {
928            this.picker.find('.prev').css({visibility: 'hidden'});
929          } else {
930            this.picker.find('.prev').css({visibility: 'visible'});
931          }
932          if (year >= this.endDate.getUTCFullYear()
933            && month >= this.endDate.getUTCMonth()
934            && day >= this.endDate.getUTCDate()) {
935            this.picker.find('.next').css({visibility: 'hidden'});
936          } else {
937            this.picker.find('.next').css({visibility: 'visible'});
938          }
939          break;
940        case 2:
941          if (year <= this.startDate.getUTCFullYear()
942            && month <= this.startDate.getUTCMonth()) {
943            this.picker.find('.prev').css({visibility: 'hidden'});
944          } else {
945            this.picker.find('.prev').css({visibility: 'visible'});
946          }
947          if (year >= this.endDate.getUTCFullYear()
948            && month >= this.endDate.getUTCMonth()) {
949            this.picker.find('.next').css({visibility: 'hidden'});
950          } else {
951            this.picker.find('.next').css({visibility: 'visible'});
952          }
953          break;
954        case 3:
955        case 4:
956          if (year <= this.startDate.getUTCFullYear()) {
957            this.picker.find('.prev').css({visibility: 'hidden'});
958          } else {
959            this.picker.find('.prev').css({visibility: 'visible'});
960          }
961          if (year >= this.endDate.getUTCFullYear()) {
962            this.picker.find('.next').css({visibility: 'hidden'});
963          } else {
964            this.picker.find('.next').css({visibility: 'visible'});
965          }
966          break;
967      }
968    },
969
970    mousewheel: function (e) {
971
972      e.preventDefault();
973      e.stopPropagation();
974
975      if (this.wheelPause) {
976        return;
977      }
978
979      this.wheelPause = true;
980
981      var originalEvent = e.originalEvent;
982
983      var delta = originalEvent.wheelDelta;
984
985      var mode = delta > 0 ? 1 : (delta === 0) ? 0 : -1;
986
987      if (this.wheelViewModeNavigationInverseDirection) {
988        mode = -mode;
989      }
990
991      this.showMode(mode);
992
993      setTimeout($.proxy(function () {
994
995        this.wheelPause = false
996
997      }, this), this.wheelViewModeNavigationDelay);
998
999    },
1000
1001    click: function (e) {
1002      e.stopPropagation();
1003      e.preventDefault();
1004      var target = $(e.target).closest('span, td, th, legend');
1005      if (target.is('.' + this.icontype)) {
1006        target = $(target).parent().closest('span, td, th, legend');
1007      }
1008      if (target.length === 1) {
1009        if (target.is('.disabled')) {
1010          this.element.trigger({
1011            type:      'outOfRange',
1012            date:      this.viewDate,
1013            startDate: this.startDate,
1014            endDate:   this.endDate
1015          });
1016          return;
1017        }
1018        switch (target[0].nodeName.toLowerCase()) {
1019          case 'th':
1020            switch (target[0].className) {
1021              case 'switch':
1022                this.showMode(1);
1023                break;
1024              case 'prev':
1025              case 'next':
1026                var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1);
1027                switch (this.viewMode) {
1028                  case 0:
1029                    this.viewDate = this.moveHour(this.viewDate, dir);
1030                    break;
1031                  case 1:
1032                    this.viewDate = this.moveDate(this.viewDate, dir);
1033                    break;
1034                  case 2:
1035                    this.viewDate = this.moveMonth(this.viewDate, dir);
1036                    break;
1037                  case 3:
1038                  case 4:
1039                    this.viewDate = this.moveYear(this.viewDate, dir);
1040                    break;
1041                }
1042                this.fill();
1043                this.element.trigger({
1044                  type:      target[0].className + ':' + this.convertViewModeText(this.viewMode),
1045                  date:      this.viewDate,
1046                  startDate: this.startDate,
1047                  endDate:   this.endDate
1048                });
1049                break;
1050              case 'clear':
1051                this.reset();
1052                if (this.autoclose) {
1053                  this.hide();
1054                }
1055                break;
1056              case 'today':
1057                var date = new Date();
1058                date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), 0);
1059
1060                // Respect startDate and endDate.
1061                if (date < this.startDate) date = this.startDate;
1062                else if (date > this.endDate) date = this.endDate;
1063
1064                this.viewMode = this.startViewMode;
1065                this.showMode(0);
1066                this._setDate(date);
1067                this.fill();
1068                if (this.autoclose) {
1069                  this.hide();
1070                }
1071                break;
1072            }
1073            break;
1074          case 'span':
1075            if (!target.is('.disabled')) {
1076              var year = this.viewDate.getUTCFullYear(),
1077                month = this.viewDate.getUTCMonth(),
1078                day = this.viewDate.getUTCDate(),
1079                hours = this.viewDate.getUTCHours(),
1080                minutes = this.viewDate.getUTCMinutes(),
1081                seconds = this.viewDate.getUTCSeconds();
1082
1083              if (target.is('.month')) {
1084                this.viewDate.setUTCDate(1);
1085                month = target.parent().find('span').index(target);
1086                day = this.viewDate.getUTCDate();
1087                this.viewDate.setUTCMonth(month);
1088                this.element.trigger({
1089                  type: 'changeMonth',
1090                  date: this.viewDate
1091                });
1092                if (this.viewSelect >= 3) {
1093                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
1094                }
1095              } else if (target.is('.year')) {
1096                this.viewDate.setUTCDate(1);
1097                year = parseInt(target.text(), 10) || 0;
1098                this.viewDate.setUTCFullYear(year);
1099                this.element.trigger({
1100                  type: 'changeYear',
1101                  date: this.viewDate
1102                });
1103                if (this.viewSelect >= 4) {
1104                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
1105                }
1106              } else if (target.is('.hour')) {
1107                hours = parseInt(target.text(), 10) || 0;
1108                if (target.hasClass('hour_am') || target.hasClass('hour_pm')) {
1109                  if (hours === 12 && target.hasClass('hour_am')) {
1110                    hours = 0;
1111                  } else if (hours !== 12 && target.hasClass('hour_pm')) {
1112                    hours += 12;
1113                  }
1114                }
1115                this.viewDate.setUTCHours(hours);
1116                this.element.trigger({
1117                  type: 'changeHour',
1118                  date: this.viewDate
1119                });
1120                if (this.viewSelect >= 1) {
1121                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
1122                }
1123              } else if (target.is('.minute')) {
1124                minutes = parseInt(target.text().substr(target.text().indexOf(':') + 1), 10) || 0;
1125                this.viewDate.setUTCMinutes(minutes);
1126                this.element.trigger({
1127                  type: 'changeMinute',
1128                  date: this.viewDate
1129                });
1130                if (this.viewSelect >= 0) {
1131                  this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
1132                }
1133              }
1134              if (this.viewMode !== 0) {
1135                var oldViewMode = this.viewMode;
1136                this.showMode(-1);
1137                this.fill();
1138                if (oldViewMode === this.viewMode && this.autoclose) {
1139                  this.hide();
1140                }
1141              } else {
1142                this.fill();
1143                if (this.autoclose) {
1144                  this.hide();
1145                }
1146              }
1147            }
1148            break;
1149          case 'td':
1150            if (target.is('.day') && !target.is('.disabled')) {
1151              var day = parseInt(target.text(), 10) || 1;
1152              var year = this.viewDate.getUTCFullYear(),
1153                month = this.viewDate.getUTCMonth(),
1154                hours = this.viewDate.getUTCHours(),
1155                minutes = this.viewDate.getUTCMinutes(),
1156                seconds = this.viewDate.getUTCSeconds();
1157              if (target.is('.old')) {
1158                if (month === 0) {
1159                  month = 11;
1160                  year -= 1;
1161                } else {
1162                  month -= 1;
1163                }
1164              } else if (target.is('.new')) {
1165                if (month === 11) {
1166                  month = 0;
1167                  year += 1;
1168                } else {
1169                  month += 1;
1170                }
1171              }
1172              this.viewDate.setUTCFullYear(year);
1173              this.viewDate.setUTCMonth(month, day);
1174              this.element.trigger({
1175                type: 'changeDay',
1176                date: this.viewDate
1177              });
1178              if (this.viewSelect >= 2) {
1179                this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
1180              }
1181            }
1182            var oldViewMode = this.viewMode;
1183            this.showMode(-1);
1184            this.fill();
1185            if (oldViewMode === this.viewMode && this.autoclose) {
1186              this.hide();
1187            }
1188            break;
1189        }
1190      }
1191    },
1192
1193    _setDate: function (date, which) {
1194      if (!which || which === 'date')
1195        this.date = date;
1196      if (!which || which === 'view')
1197        this.viewDate = date;
1198      this.fill();
1199      this.setValue();
1200      var element;
1201      if (this.isInput) {
1202        element = this.element;
1203      } else if (this.component) {
1204        element = this.element.find('input');
1205      }
1206      if (element) {
1207        element.change();
1208      }
1209      this.element.trigger({
1210        type: 'changeDate',
1211        date: this.getDate()
1212      });
1213      if(date === null)
1214        this.date = this.viewDate;
1215    },
1216
1217    moveMinute: 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.setUTCMinutes(new_date.getUTCMinutes() + (dir * this.minuteStep));
1222      return new_date;
1223    },
1224
1225    moveHour: 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.setUTCHours(new_date.getUTCHours() + dir);
1230      return new_date;
1231    },
1232
1233    moveDate: function (date, dir) {
1234      if (!dir) return date;
1235      var new_date = new Date(date.valueOf());
1236      //dir = dir > 0 ? 1 : -1;
1237      new_date.setUTCDate(new_date.getUTCDate() + dir);
1238      return new_date;
1239    },
1240
1241    moveMonth: function (date, dir) {
1242      if (!dir) return date;
1243      var new_date = new Date(date.valueOf()),
1244        day = new_date.getUTCDate(),
1245        month = new_date.getUTCMonth(),
1246        mag = Math.abs(dir),
1247        new_month, test;
1248      dir = dir > 0 ? 1 : -1;
1249      if (mag === 1) {
1250        test = dir === -1
1251          // If going back one month, make sure month is not current month
1252          // (eg, Mar 31 -> Feb 31 === Feb 28, not Mar 02)
1253          ? function () {
1254          return new_date.getUTCMonth() === month;
1255        }
1256          // If going forward one month, make sure month is as expected
1257          // (eg, Jan 31 -> Feb 31 === Feb 28, not Mar 02)
1258          : function () {
1259          return new_date.getUTCMonth() !== new_month;
1260        };
1261        new_month = month + dir;
1262        new_date.setUTCMonth(new_month);
1263        // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
1264        if (new_month < 0 || new_month > 11)
1265          new_month = (new_month + 12) % 12;
1266      } else {
1267        // For magnitudes >1, move one month at a time...
1268        for (var i = 0; i < mag; i++)
1269          // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
1270          new_date = this.moveMonth(new_date, dir);
1271        // ...then reset the day, keeping it in the new month
1272        new_month = new_date.getUTCMonth();
1273        new_date.setUTCDate(day);
1274        test = function () {
1275          return new_month !== new_date.getUTCMonth();
1276        };
1277      }
1278      // Common date-resetting loop -- if date is beyond end of month, make it
1279      // end of month
1280      while (test()) {
1281        new_date.setUTCDate(--day);
1282        new_date.setUTCMonth(new_month);
1283      }
1284      return new_date;
1285    },
1286
1287    moveYear: function (date, dir) {
1288      return this.moveMonth(date, dir * 12);
1289    },
1290
1291    dateWithinRange: function (date) {
1292      return date >= this.startDate && date <= this.endDate;
1293    },
1294
1295    keydown: function (e) {
1296      if (this.picker.is(':not(:visible)')) {
1297        if (e.keyCode === 27) // allow escape to hide and re-show picker
1298          this.show();
1299        return;
1300      }
1301      var dateChanged = false,
1302        dir, newDate, newViewDate;
1303      switch (e.keyCode) {
1304        case 27: // escape
1305          this.hide();
1306          e.preventDefault();
1307          break;
1308        case 37: // left
1309        case 39: // right
1310          if (!this.keyboardNavigation) break;
1311          dir = e.keyCode === 37 ? -1 : 1;
1312          var viewMode = this.viewMode;
1313          if (e.ctrlKey) {
1314            viewMode += 2;
1315          } else if (e.shiftKey) {
1316            viewMode += 1;
1317          }
1318          if (viewMode === 4) {
1319            newDate = this.moveYear(this.date, dir);
1320            newViewDate = this.moveYear(this.viewDate, dir);
1321          } else if (viewMode === 3) {
1322            newDate = this.moveMonth(this.date, dir);
1323            newViewDate = this.moveMonth(this.viewDate, dir);
1324          } else if (viewMode === 2) {
1325            newDate = this.moveDate(this.date, dir);
1326            newViewDate = this.moveDate(this.viewDate, dir);
1327          } else if (viewMode === 1) {
1328            newDate = this.moveHour(this.date, dir);
1329            newViewDate = this.moveHour(this.viewDate, dir);
1330          } else if (viewMode === 0) {
1331            newDate = this.moveMinute(this.date, dir);
1332            newViewDate = this.moveMinute(this.viewDate, dir);
1333          }
1334          if (this.dateWithinRange(newDate)) {
1335            this.date = newDate;
1336            this.viewDate = newViewDate;
1337            this.setValue();
1338            this.update();
1339            e.preventDefault();
1340            dateChanged = true;
1341          }
1342          break;
1343        case 38: // up
1344        case 40: // down
1345          if (!this.keyboardNavigation) break;
1346          dir = e.keyCode === 38 ? -1 : 1;
1347          viewMode = this.viewMode;
1348          if (e.ctrlKey) {
1349            viewMode += 2;
1350          } else if (e.shiftKey) {
1351            viewMode += 1;
1352          }
1353          if (viewMode === 4) {
1354            newDate = this.moveYear(this.date, dir);
1355            newViewDate = this.moveYear(this.viewDate, dir);
1356          } else if (viewMode === 3) {
1357            newDate = this.moveMonth(this.date, dir);
1358            newViewDate = this.moveMonth(this.viewDate, dir);
1359          } else if (viewMode === 2) {
1360            newDate = this.moveDate(this.date, dir * 7);
1361            newViewDate = this.moveDate(this.viewDate, dir * 7);
1362          } else if (viewMode === 1) {
1363            if (this.showMeridian) {
1364              newDate = this.moveHour(this.date, dir * 6);
1365              newViewDate = this.moveHour(this.viewDate, dir * 6);
1366            } else {
1367              newDate = this.moveHour(this.date, dir * 4);
1368              newViewDate = this.moveHour(this.viewDate, dir * 4);
1369            }
1370          } else if (viewMode === 0) {
1371            newDate = this.moveMinute(this.date, dir * 4);
1372            newViewDate = this.moveMinute(this.viewDate, dir * 4);
1373          }
1374          if (this.dateWithinRange(newDate)) {
1375            this.date = newDate;
1376            this.viewDate = newViewDate;
1377            this.setValue();
1378            this.update();
1379            e.preventDefault();
1380            dateChanged = true;
1381          }
1382          break;
1383        case 13: // enter
1384          if (this.viewMode !== 0) {
1385            var oldViewMode = this.viewMode;
1386            this.showMode(-1);
1387            this.fill();
1388            if (oldViewMode === this.viewMode && this.autoclose) {
1389              this.hide();
1390            }
1391          } else {
1392            this.fill();
1393            if (this.autoclose) {
1394              this.hide();
1395            }
1396          }
1397          e.preventDefault();
1398          break;
1399        case 9: // tab
1400          this.hide();
1401          break;
1402      }
1403      if (dateChanged) {
1404        var element;
1405        if (this.isInput) {
1406          element = this.element;
1407        } else if (this.component) {
1408          element = this.element.find('input');
1409        }
1410        if (element) {
1411          element.change();
1412        }
1413        this.element.trigger({
1414          type: 'changeDate',
1415          date: this.getDate()
1416        });
1417      }
1418    },
1419
1420    showMode: function (dir) {
1421      if (dir) {
1422        var newViewMode = Math.max(0, Math.min(DPGlobal.modes.length - 1, this.viewMode + dir));
1423        if (newViewMode >= this.minView && newViewMode <= this.maxView) {
1424          this.element.trigger({
1425            type:        'changeMode',
1426            date:        this.viewDate,
1427            oldViewMode: this.viewMode,
1428            newViewMode: newViewMode
1429          });
1430
1431          this.viewMode = newViewMode;
1432        }
1433      }
1434      /*
1435       vitalets: fixing bug of very special conditions:
1436       jquery 1.7.1 + webkit + show inline datetimepicker in bootstrap popover.
1437       Method show() does not set display css correctly and datetimepicker is not shown.
1438       Changed to .css('display', 'block') solve the problem.
1439       See https://github.com/vitalets/x-editable/issues/37
1440
1441       In jquery 1.7.2+ everything works fine.
1442       */
1443      //this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
1444      this.picker.find('>div').hide().filter('.datetimepicker-' + DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
1445      this.updateNavArrows();
1446    },
1447
1448    reset: function () {
1449      this._setDate(null, 'date');
1450    },
1451
1452    convertViewModeText:  function (viewMode) {
1453      switch (viewMode) {
1454        case 4:
1455          return 'decade';
1456        case 3:
1457          return 'year';
1458        case 2:
1459          return 'month';
1460        case 1:
1461          return 'day';
1462        case 0:
1463          return 'hour';
1464      }
1465    }
1466  };
1467
1468  var old = $.fn.datetimepicker;
1469  $.fn.datetimepicker = function (option) {
1470    var args = Array.apply(null, arguments);
1471    args.shift();
1472    var internal_return;
1473    this.each(function () {
1474      var $this = $(this),
1475        data = $this.data('datetimepicker'),
1476        options = typeof option === 'object' && option;
1477      if (!data) {
1478        $this.data('datetimepicker', (data = new Datetimepicker(this, $.extend({}, $.fn.datetimepicker.defaults, options))));
1479      }
1480      if (typeof option === 'string' && typeof data[option] === 'function') {
1481        internal_return = data[option].apply(data, args);
1482        if (internal_return !== undefined) {
1483          return false;
1484        }
1485      }
1486    });
1487    if (internal_return !== undefined)
1488      return internal_return;
1489    else
1490      return this;
1491  };
1492
1493  $.fn.datetimepicker.defaults = {
1494  };
1495  $.fn.datetimepicker.Constructor = Datetimepicker;
1496  var dates = $.fn.datetimepicker.dates = {
1497    en: {
1498      days:        ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
1499      daysShort:   ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
1500      daysMin:     ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
1501      months:      ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
1502      monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1503      meridiem:    ['am', 'pm'],
1504      suffix:      ['st', 'nd', 'rd', 'th'],
1505      today:       'Today',
1506      clear:       'Clear'
1507    }
1508  };
1509
1510  var DPGlobal = {
1511    modes:            [
1512      {
1513        clsName: 'minutes',
1514        navFnc:  'Hours',
1515        navStep: 1
1516      },
1517      {
1518        clsName: 'hours',
1519        navFnc:  'Date',
1520        navStep: 1
1521      },
1522      {
1523        clsName: 'days',
1524        navFnc:  'Month',
1525        navStep: 1
1526      },
1527      {
1528        clsName: 'months',
1529        navFnc:  'FullYear',
1530        navStep: 1
1531      },
1532      {
1533        clsName: 'years',
1534        navFnc:  'FullYear',
1535        navStep: 10
1536      }
1537    ],
1538    isLeapYear:       function (year) {
1539      return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
1540    },
1541    getDaysInMonth:   function (year, month) {
1542      return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
1543    },
1544    getDefaultFormat: function (type, field) {
1545      if (type === 'standard') {
1546        if (field === 'input')
1547          return 'yyyy-mm-dd hh:ii';
1548        else
1549          return 'yyyy-mm-dd hh:ii:ss';
1550      } else if (type === 'php') {
1551        if (field === 'input')
1552          return 'Y-m-d H:i';
1553        else
1554          return 'Y-m-d H:i:s';
1555      } else {
1556        throw new Error('Invalid format type.');
1557      }
1558    },
1559    validParts: function (type) {
1560      if (type === 'standard') {
1561        return /t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g;
1562      } else if (type === 'php') {
1563        return /[dDjlNwzFmMnStyYaABgGhHis]/g;
1564      } else {
1565        throw new Error('Invalid format type.');
1566      }
1567    },
1568    nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,
1569    parseFormat: function (format, type) {
1570      // IE treats \0 as a string end in inputs (truncating the value),
1571      // so it's a bad format delimiter, anyway
1572      var separators = format.replace(this.validParts(type), '\0').split('\0'),
1573        parts = format.match(this.validParts(type));
1574      if (!separators || !separators.length || !parts || parts.length === 0) {
1575        throw new Error('Invalid date format.');
1576      }
1577      return {separators: separators, parts: parts};
1578    },
1579    parseDate: function (date, format, language, type, timezone) {
1580      if (date instanceof Date) {
1581        var dateUTC = new Date(date.valueOf() - date.getTimezoneOffset() * 60000);
1582        dateUTC.setMilliseconds(0);
1583        return dateUTC;
1584      }
1585      if (/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(date)) {
1586        format = this.parseFormat('yyyy-mm-dd', type);
1587      }
1588      if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(date)) {
1589        format = this.parseFormat('yyyy-mm-dd hh:ii', type);
1590      }
1591      if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(date)) {
1592        format = this.parseFormat('yyyy-mm-dd hh:ii:ss', type);
1593      }
1594      if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
1595        var part_re = /([-+]\d+)([dmwy])/,
1596          parts = date.match(/([-+]\d+)([dmwy])/g),
1597          part, dir;
1598        date = new Date();
1599        for (var i = 0; i < parts.length; i++) {
1600          part = part_re.exec(parts[i]);
1601          dir = parseInt(part[1]);
1602          switch (part[2]) {
1603            case 'd':
1604              date.setUTCDate(date.getUTCDate() + dir);
1605              break;
1606            case 'm':
1607              date = Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype, date, dir);
1608              break;
1609            case 'w':
1610              date.setUTCDate(date.getUTCDate() + dir * 7);
1611              break;
1612            case 'y':
1613              date = Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype, date, dir);
1614              break;
1615          }
1616        }
1617        return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), 0);
1618      }
1619      var parts = date && date.toString().match(this.nonpunctuation) || [],
1620        date = new Date(0, 0, 0, 0, 0, 0, 0),
1621        parsed = {},
1622        setters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'D', 'DD', 'd', 'dd', 'H', 'HH', 'p', 'P', 'z', 'Z'],
1623        setters_map = {
1624          hh:   function (d, v) {
1625            return d.setUTCHours(v);
1626          },
1627          h:    function (d, v) {
1628            return d.setUTCHours(v);
1629          },
1630          HH:   function (d, v) {
1631            return d.setUTCHours(v === 12 ? 0 : v);
1632          },
1633          H:    function (d, v) {
1634            return d.setUTCHours(v === 12 ? 0 : v);
1635          },
1636          ii:   function (d, v) {
1637            return d.setUTCMinutes(v);
1638          },
1639          i:    function (d, v) {
1640            return d.setUTCMinutes(v);
1641          },
1642          ss:   function (d, v) {
1643            return d.setUTCSeconds(v);
1644          },
1645          s:    function (d, v) {
1646            return d.setUTCSeconds(v);
1647          },
1648          yyyy: function (d, v) {
1649            return d.setUTCFullYear(v);
1650          },
1651          yy:   function (d, v) {
1652            return d.setUTCFullYear(2000 + v);
1653          },
1654          m:    function (d, v) {
1655            v -= 1;
1656            while (v < 0) v += 12;
1657            v %= 12;
1658            d.setUTCMonth(v);
1659            while (d.getUTCMonth() !== v)
1660              if (isNaN(d.getUTCMonth()))
1661                return d;
1662              else
1663                d.setUTCDate(d.getUTCDate() - 1);
1664            return d;
1665          },
1666          d:    function (d, v) {
1667            return d.setUTCDate(v);
1668          },
1669          p:    function (d, v) {
1670            return d.setUTCHours(v === 1 ? d.getUTCHours() + 12 : d.getUTCHours());
1671          },
1672          z:    function () {
1673            return timezone
1674          }
1675        },
1676        val, filtered, part;
1677      setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1678      setters_map['dd'] = setters_map['d'];
1679      setters_map['P'] = setters_map['p'];
1680      setters_map['Z'] = setters_map['z'];
1681      date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
1682      if (parts.length === format.parts.length) {
1683        for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
1684          val = parseInt(parts[i], 10);
1685          part = format.parts[i];
1686          if (isNaN(val)) {
1687            switch (part) {
1688              case 'MM':
1689                filtered = $(dates[language].months).filter(function () {
1690                  var m = this.slice(0, parts[i].length),
1691                    p = parts[i].slice(0, m.length);
1692                  return m === p;
1693                });
1694                val = $.inArray(filtered[0], dates[language].months) + 1;
1695                break;
1696              case 'M':
1697                filtered = $(dates[language].monthsShort).filter(function () {
1698                  var m = this.slice(0, parts[i].length),
1699                    p = parts[i].slice(0, m.length);
1700                  return m.toLowerCase() === p.toLowerCase();
1701                });
1702                val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1703                break;
1704              case 'p':
1705              case 'P':
1706                val = $.inArray(parts[i].toLowerCase(), dates[language].meridiem);
1707                break;
1708              case 'z':
1709              case 'Z':
1710                timezone;
1711                break;
1712
1713            }
1714          }
1715          parsed[part] = val;
1716        }
1717        for (var i = 0, s; i < setters_order.length; i++) {
1718          s = setters_order[i];
1719          if (s in parsed && !isNaN(parsed[s]))
1720            setters_map[s](date, parsed[s])
1721        }
1722      }
1723      return date;
1724    },
1725    formatDate:       function (date, format, language, type, timezone) {
1726      if (date === null) {
1727        return '';
1728      }
1729      var val;
1730      if (type === 'standard') {
1731        val = {
1732          t:    date.getTime(),
1733          // year
1734          yy:   date.getUTCFullYear().toString().substring(2),
1735          yyyy: date.getUTCFullYear(),
1736          // month
1737          m:    date.getUTCMonth() + 1,
1738          M:    dates[language].monthsShort[date.getUTCMonth()],
1739          MM:   dates[language].months[date.getUTCMonth()],
1740          // day
1741          d:    date.getUTCDate(),
1742          D:    dates[language].daysShort[date.getUTCDay()],
1743          DD:   dates[language].days[date.getUTCDay()],
1744          p:    (dates[language].meridiem.length === 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''),
1745          // hour
1746          h:    date.getUTCHours(),
1747          // minute
1748          i:    date.getUTCMinutes(),
1749          // second
1750          s:    date.getUTCSeconds(),
1751          // timezone
1752          z:    timezone
1753        };
1754
1755        if (dates[language].meridiem.length === 2) {
1756          val.H = (val.h % 12 === 0 ? 12 : val.h % 12);
1757        }
1758        else {
1759          val.H = val.h;
1760        }
1761        val.HH = (val.H < 10 ? '0' : '') + val.H;
1762        val.P = val.p.toUpperCase();
1763        val.Z = val.z;
1764        val.hh = (val.h < 10 ? '0' : '') + val.h;
1765        val.ii = (val.i < 10 ? '0' : '') + val.i;
1766        val.ss = (val.s < 10 ? '0' : '') + val.s;
1767        val.dd = (val.d < 10 ? '0' : '') + val.d;
1768        val.mm = (val.m < 10 ? '0' : '') + val.m;
1769      } else if (type === 'php') {
1770        // php format
1771        val = {
1772          // year
1773          y: date.getUTCFullYear().toString().substring(2),
1774          Y: date.getUTCFullYear(),
1775          // month
1776          F: dates[language].months[date.getUTCMonth()],
1777          M: dates[language].monthsShort[date.getUTCMonth()],
1778          n: date.getUTCMonth() + 1,
1779          t: DPGlobal.getDaysInMonth(date.getUTCFullYear(), date.getUTCMonth()),
1780          // day
1781          j: date.getUTCDate(),
1782          l: dates[language].days[date.getUTCDay()],
1783          D: dates[language].daysShort[date.getUTCDay()],
1784          w: date.getUTCDay(), // 0 -> 6
1785          N: (date.getUTCDay() === 0 ? 7 : date.getUTCDay()),       // 1 -> 7
1786          S: (date.getUTCDate() % 10 <= dates[language].suffix.length ? dates[language].suffix[date.getUTCDate() % 10 - 1] : ''),
1787          // hour
1788          a: (dates[language].meridiem.length === 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''),
1789          g: (date.getUTCHours() % 12 === 0 ? 12 : date.getUTCHours() % 12),
1790          G: date.getUTCHours(),
1791          // minute
1792          i: date.getUTCMinutes(),
1793          // second
1794          s: date.getUTCSeconds()
1795        };
1796        val.m = (val.n < 10 ? '0' : '') + val.n;
1797        val.d = (val.j < 10 ? '0' : '') + val.j;
1798        val.A = val.a.toString().toUpperCase();
1799        val.h = (val.g < 10 ? '0' : '') + val.g;
1800        val.H = (val.G < 10 ? '0' : '') + val.G;
1801        val.i = (val.i < 10 ? '0' : '') + val.i;
1802        val.s = (val.s < 10 ? '0' : '') + val.s;
1803      } else {
1804        throw new Error('Invalid format type.');
1805      }
1806      var date = [],
1807        seps = $.extend([], format.separators);
1808      for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
1809        if (seps.length) {
1810          date.push(seps.shift());
1811        }
1812        date.push(val[format.parts[i]]);
1813      }
1814      if (seps.length) {
1815        date.push(seps.shift());
1816      }
1817      return date.join('');
1818    },
1819    convertViewMode:  function (viewMode) {
1820      switch (viewMode) {
1821        case 4:
1822        case 'decade':
1823          viewMode = 4;
1824          break;
1825        case 3:
1826        case 'year':
1827          viewMode = 3;
1828          break;
1829        case 2:
1830        case 'month':
1831          viewMode = 2;
1832          break;
1833        case 1:
1834        case 'day':
1835          viewMode = 1;
1836          break;
1837        case 0:
1838        case 'hour':
1839          viewMode = 0;
1840          break;
1841      }
1842
1843      return viewMode;
1844    },
1845    headTemplate: '<thead>' +
1846                '<tr>' +
1847                '<th class="prev"><i class="{iconType} {leftArrow}"/></th>' +
1848                '<th colspan="5" class="switch"></th>' +
1849                '<th class="next"><i class="{iconType} {rightArrow}"/></th>' +
1850                '</tr>' +
1851      '</thead>',
1852    headTemplateV3: '<thead>' +
1853                '<tr>' +
1854                '<th class="prev"><span class="{iconType} {leftArrow}"></span> </th>' +
1855                '<th colspan="5" class="switch"></th>' +
1856                '<th class="next"><span class="{iconType} {rightArrow}"></span> </th>' +
1857                '</tr>' +
1858      '</thead>',
1859    contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
1860    footTemplate: '<tfoot>' + 
1861                    '<tr><th colspan="7" class="today"></th></tr>' +
1862                    '<tr><th colspan="7" class="clear"></th></tr>' +
1863                  '</tfoot>'
1864  };
1865  DPGlobal.template = '<div class="datetimepicker">' +
1866    '<div class="datetimepicker-minutes">' +
1867    '<table class=" table-condensed">' +
1868    DPGlobal.headTemplate +
1869    DPGlobal.contTemplate +
1870    DPGlobal.footTemplate +
1871    '</table>' +
1872    '</div>' +
1873    '<div class="datetimepicker-hours">' +
1874    '<table class=" table-condensed">' +
1875    DPGlobal.headTemplate +
1876    DPGlobal.contTemplate +
1877    DPGlobal.footTemplate +
1878    '</table>' +
1879    '</div>' +
1880    '<div class="datetimepicker-days">' +
1881    '<table class=" table-condensed">' +
1882    DPGlobal.headTemplate +
1883    '<tbody></tbody>' +
1884    DPGlobal.footTemplate +
1885    '</table>' +
1886    '</div>' +
1887    '<div class="datetimepicker-months">' +
1888    '<table class="table-condensed">' +
1889    DPGlobal.headTemplate +
1890    DPGlobal.contTemplate +
1891    DPGlobal.footTemplate +
1892    '</table>' +
1893    '</div>' +
1894    '<div class="datetimepicker-years">' +
1895    '<table class="table-condensed">' +
1896    DPGlobal.headTemplate +
1897    DPGlobal.contTemplate +
1898    DPGlobal.footTemplate +
1899    '</table>' +
1900    '</div>' +
1901    '</div>';
1902  DPGlobal.templateV3 = '<div class="datetimepicker">' +
1903    '<div class="datetimepicker-minutes">' +
1904    '<table class=" table-condensed">' +
1905    DPGlobal.headTemplateV3 +
1906    DPGlobal.contTemplate +
1907    DPGlobal.footTemplate +
1908    '</table>' +
1909    '</div>' +
1910    '<div class="datetimepicker-hours">' +
1911    '<table class=" table-condensed">' +
1912    DPGlobal.headTemplateV3 +
1913    DPGlobal.contTemplate +
1914    DPGlobal.footTemplate +
1915    '</table>' +
1916    '</div>' +
1917    '<div class="datetimepicker-days">' +
1918    '<table class=" table-condensed">' +
1919    DPGlobal.headTemplateV3 +
1920    '<tbody></tbody>' +
1921    DPGlobal.footTemplate +
1922    '</table>' +
1923    '</div>' +
1924    '<div class="datetimepicker-months">' +
1925    '<table class="table-condensed">' +
1926    DPGlobal.headTemplateV3 +
1927    DPGlobal.contTemplate +
1928    DPGlobal.footTemplate +
1929    '</table>' +
1930    '</div>' +
1931    '<div class="datetimepicker-years">' +
1932    '<table class="table-condensed">' +
1933    DPGlobal.headTemplateV3 +
1934    DPGlobal.contTemplate +
1935    DPGlobal.footTemplate +
1936    '</table>' +
1937    '</div>' +
1938    '</div>';
1939  $.fn.datetimepicker.DPGlobal = DPGlobal;
1940
1941  /* DATETIMEPICKER NO CONFLICT
1942   * =================== */
1943
1944  $.fn.datetimepicker.noConflict = function () {
1945    $.fn.datetimepicker = old;
1946    return this;
1947  };
1948
1949  /* DATETIMEPICKER DATA-API
1950   * ================== */
1951
1952  $(document).on(
1953    'focus.datetimepicker.data-api click.datetimepicker.data-api',
1954    '[data-provide="datetimepicker"]',
1955    function (e) {
1956      var $this = $(this);
1957      if ($this.data('datetimepicker')) return;
1958      e.preventDefault();
1959      // component click requires us to explicitly show it
1960      $this.datetimepicker('show');
1961    }
1962  );
1963  $(function () {
1964    $('[data-provide="datetimepicker-inline"]').datetimepicker();
1965  });
1966
1967}));

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.