PageSourceSearch

https://triunfo.pe.gov.br/pm_tr430/wp-content/themes/idata-gov/js/…/plugins/bootstrap-datepicker.js?ver=1.24

js triunfo.pe.gov.br collected 2026-10-02 13:39:12 UTC 63,983 bytes, 2,056 lines download raw bytes

vendor: 36,173 bytes, lines 1-1151
1/*!
2 * Datepicker for Bootstrap v1.7.0-dev (https://github.com/uxsolutions/bootstrap-datepicker)
3 *
4 * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
5 */
6
7(function(factory) {
8  if (typeof define === "function" && define.amd) {
9    define(["jquery"], factory);
10  } else if (typeof exports === 'object') {
11    factory(require('jquery'));
12  } else {
13    factory(jQuery);
14  }
15}(function($, undefined) {
16  function UTCDate() {
17    return new Date(Date.UTC.apply(Date, arguments));
18  }
19
20  function UTCToday() {
21    var today = new Date();
22    return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
23  }
24
25  function isUTCEquals(date1, date2) {
26    return (
27      date1.getUTCFullYear() === date2.getUTCFullYear() &&
28      date1.getUTCMonth() === date2.getUTCMonth() &&
29      date1.getUTCDate() === date2.getUTCDate()
30    );
31  }
32
33  function alias(method, deprecationMsg) {
34    return function() {
35      if (deprecationMsg !== undefined) {
36        $.fn.datepicker.deprecated(deprecationMsg);
37      }
38
39      return this[method].apply(this, arguments);
40    };
41  }
42
43  function isValidDate(d) {
44    return d && !isNaN(d.getTime());
45  }
46
47  var DateArray = (function() {
48    var extras = {
49      get: function(i) {
50        return this.slice(i)[0];
51      },
52      contains: function(d) {
53        // Array.indexOf is not cross-browser;
54        // $.inArray doesn't work with Dates
55        var val = d && d.valueOf();
56        for (var i = 0, l = this.length; i < l; i++)
57          // Use date arithmetic to allow dates with different times to match
58          if (0 <= this[i].valueOf() - val && this[i].valueOf() - val < 1000 * 60 * 60 * 24)
59            return i;
60        return -1;
61      },
62      remove: function(i) {
63        this.splice(i, 1);
64      },
65      replace: function(new_array) {
66        if (!new_array)
67          return;
68        if (!$.isArray(new_array))
69          new_array = [new_array];
70        this.clear();
71        this.push.apply(this, new_array);
72      },
73      clear: function() {
74        this.length = 0;
75      },
76      copy: function() {
77        var a = new DateArray();
78        a.replace(this);
79        return a;
80      }
81    };
82
83    return function() {
84      var a = [];
85      a.push.apply(a, arguments);
86      $.extend(a, extras);
87      return a;
88    };
89  })();
90
91
92  // Picker object
93
94  var Datepicker = function(element, options) {
95    $.data(element, 'datepicker', this);
96    this._process_options(options);
97
98    this.dates = new DateArray();
99    this.viewDate = this.o.defaultViewDate;
100    this.focusDate = null;
101
102    this.element = $(element);
103    this.isInput = this.element.is('input');
104    this.inputField = this.isInput ? this.element : this.element.find('input');
105    this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false;
106    if (this.component && this.component.length === 0)
107      this.component = false;
108    this.isInline = !this.component && this.element.is('div');
109
110    this.picker = $(DPGlobal.template);
111
112    // Checking templates and inserting
113    if (this._check_template(this.o.templates.leftArrow)) {
114      this.picker.find('.prev').html(this.o.templates.leftArrow);
115    }
116
117    if (this._check_template(this.o.templates.rightArrow)) {
118      this.picker.find('.next').html(this.o.templates.rightArrow);
119    }
120
121    this._buildEvents();
122    this._attachEvents();
123
124    if (this.isInline) {
125      this.picker.addClass('datepicker-inline').appendTo(this.element);
126    } else {
127      this.picker.addClass('datepicker-dropdown dropdown-menu');
128    }
129
130    if (this.o.rtl) {
131      this.picker.addClass('datepicker-rtl');
132    }
133
134    if (this.o.calendarWeeks) {
135      this.picker.find('.datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear')
136        .attr('colspan', function(i, val) {
137          return Number(val) + 1;
138        });
139    }
140
141    this._process_options({
142      startDate: this._o.startDate,
143      endDate: this._o.endDate,
144      daysOfWeekDisabled: this.o.daysOfWeekDisabled,
145      daysOfWeekHighlighted: this.o.daysOfWeekHighlighted,
146      datesDisabled: this.o.datesDisabled
147    });
148
149    this._allow_update = false;
150    this.setViewMode(this.o.startView);
151    this._allow_update = true;
152
153    this.fillDow();
154    this.fillMonths();
155
156    this.update();
157
158    if (this.isInline) {
159      this.show();
160    }
161  };
162
163  Datepicker.prototype = {
164    constructor: Datepicker,
165
166    _resolveViewName: function(view) {
167      $.each(DPGlobal.viewModes, function(i, viewMode) {
168        if (view === i || $.inArray(view, viewMode.names) !== -1) {
169          view = i;
170          return false;
171        }
172      });
173
174      return view;
175    },
176
177    _resolveDaysOfWeek: function(daysOfWeek) {
178      if (!$.isArray(daysOfWeek))
179        daysOfWeek = daysOfWeek.split(/[,\s]*/);
180      return $.map(daysOfWeek, Number);
181    },
182
183    _check_template: function(tmp) {
184      try {
185        // If empty
186        if (tmp === undefined || tmp === "") {
187          return false;
188        }
189        // If no html, everything ok
190        if ((tmp.match(/[<>]/g) || []).length <= 0) {
191          return true;
192        }
193        // Checking if html is fine
194        var jDom = $(tmp);
195        return jDom.length > 0;
196      } catch (ex) {
197        return false;
198      }
199    },
200
201    _process_options: function(opts) {
202      // Store raw options for reference
203      this._o = $.extend({}, this._o, opts);
204      // Processed options
205      var o = this.o = $.extend({}, this._o);
206
207      // Check if "de-DE" style date is available, if not language should
208      // fallback to 2 letter code eg "de"
209      var lang = o.language;
210      if (!dates[lang]) {
211        lang = lang.split('-')[0];
212        if (!dates[lang])
213          lang = defaults.language;
214      }
215      o.language = lang;
216
217      // Retrieve view index from any aliases
218      o.startView = this._resolveViewName(o.startView);
219      o.minViewMode = this._resolveViewName(o.minViewMode);
220      o.maxViewMode = this._resolveViewName(o.maxViewMode);
221
222      // Check view is between min and max
223      o.startView = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, o.startView));
224
225      // true, false, or Number > 0
226      if (o.multidate !== true) {
227        o.multidate = Number(o.multidate) || false;
228        if (o.multidate !== false)
229          o.multidate = Math.max(0, o.multidate);
230      }
231      o.multidateSeparator = String(o.multidateSeparator);
232
233      o.weekStart %= 7;
234      o.weekEnd = (o.weekStart + 6) % 7;
235
236      var format = DPGlobal.parseFormat(o.format);
237      if (o.startDate !== -Infinity) {
238        if (!!o.startDate) {
239          if (o.startDate instanceof Date)
240            o.startDate = this._local_to_utc(this._zero_time(o.startDate));
241          else
242            o.startDate = DPGlobal.parseDate(o.startDate, format, o.language, o.assumeNearbyYear);
243        } else {
244          o.startDate = -Infinity;
245        }
246      }
247      if (o.endDate !== Infinity) {
248        if (!!o.endDate) {
249          if (o.endDate instanceof Date)
250            o.endDate = this._local_to_utc(this._zero_time(o.endDate));
251          else
252            o.endDate = DPGlobal.parseDate(o.endDate, format, o.language, o.assumeNearbyYear);
253        } else {
254          o.endDate = Infinity;
255        }
256      }
257
258      o.daysOfWeekDisabled = this._resolveDaysOfWeek(o.daysOfWeekDisabled || []);
259      o.daysOfWeekHighlighted = this._resolveDaysOfWeek(o.daysOfWeekHighlighted || []);
260
261      o.datesDisabled = o.datesDisabled || [];
262      if (!$.isArray(o.datesDisabled)) {
263        o.datesDisabled = o.datesDisabled.split(',');
264      }
265      o.datesDisabled = $.map(o.datesDisabled, function(d) {
266        return DPGlobal.parseDate(d, format, o.language, o.assumeNearbyYear);
267      });
268
269      var plc = String(o.orientation).toLowerCase().split(/\s+/g),
270        _plc = o.orientation.toLowerCase();
271      plc = $.grep(plc, function(word) {
272        return /^auto|left|right|top|bottom$/.test(word);
273      });
274      o.orientation = {
275        x: 'auto',
276        y: 'auto'
277      };
278      if (!_plc || _plc === 'auto')
279      ; // no action
280      else if (plc.length === 1) {
281        switch (plc[0]) {
282          case 'top':
283          case 'bottom':
284            o.orientation.y = plc[0];
285            break;
286          case 'left':
287          case 'right':
288            o.orientation.x = plc[0];
289            break;
290        }
291      } else {
292        _plc = $.grep(plc, function(word) {
293          return /^left|right$/.test(word);
294        });
295        o.orientation.x = _plc[0] || 'auto';
296
297        _plc = $.grep(plc, function(word) {
298          return /^top|bottom$/.test(word);
299        });
300        o.orientation.y = _plc[0] || 'auto';
301      }
302      if (o.defaultViewDate instanceof Date || typeof o.defaultViewDate === 'string') {
303        o.defaultViewDate = DPGlobal.parseDate(o.defaultViewDate, format, o.language, o.assumeNearbyYear);
304      } else if (o.defaultViewDate) {
305        var year = o.defaultViewDate.year || new Date().getFullYear();
306        var month = o.defaultViewDate.month || 0;
307        var day = o.defaultViewDate.day || 1;
308        o.defaultViewDate = UTCDate(year, month, day);
309      } else {
310        o.defaultViewDate = UTCToday();
311      }
312    },
313    _events: [],
314    _secondaryEvents: [],
315    _applyEvents: function(evs) {
316      for (var i = 0, el, ch, ev; i < evs.length; i++) {
317        el = evs[i][0];
318        if (evs[i].length === 2) {
319          ch = undefined;
320          ev = evs[i][1];
321        } else if (evs[i].length === 3) {
322          ch = evs[i][1];
323          ev = evs[i][2];
324        }
325        el.on(ev, ch);
326      }
327    },
328    _unapplyEvents: function(evs) {
329      for (var i = 0, el, ev, ch; i < evs.length; i++) {
330        el = evs[i][0];
331        if (evs[i].length === 2) {
332          ch = undefined;
333          ev = evs[i][1];
334        } else if (evs[i].length === 3) {
335          ch = evs[i][1];
336          ev = evs[i][2];
337        }
338        el.off(ev, ch);
339      }
340    },
341    _buildEvents: function() {
342      var events = {
343        keyup: $.proxy(function(e) {
344          if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
345            this.update();
346        }, this),
347        keydown: $.proxy(this.keydown, this),
348        paste: $.proxy(this.paste, this)
349      };
350
351      if (this.o.showOnFocus === true) {
352        events.focus = $.proxy(this.show, this);
353      }
354
355      if (this.isInput) { // single input
356        this._events = [
357          [this.element, events]
358        ];
359      }
360      // component: input + button
361      else if (this.component && this.inputField.length) {
362        this._events = [
363          // For components that are not readonly, allow keyboard nav
364          [this.inputField, events],
365          [this.component, {
366            click: $.proxy(this.show, this)
367          }]
368        ];
369      } else {
370        this._events = [
371          [this.element, {
372            click: $.proxy(this.show, this),
373            keydown: $.proxy(this.keydown, this)
374          }]
375        ];
376      }
377      this._events.push(
378        // Component: listen for blur on element descendants
379        [this.element, '*', {
380          blur: $.proxy(function(e) {
381            this._focused_from = e.target;
382          }, this)
383        }],
384        // Input: listen for blur on element
385        [this.element, {
386          blur: $.proxy(function(e) {
387            this._focused_from = e.target;
388          }, this)
389        }]
390      );
391
392      if (this.o.immediateUpdates) {
393        // Trigger input updates immediately on changed year/month
394        this._events.push([this.element, {
395          'changeYear changeMonth': $.proxy(function(e) {
396            this.update(e.date);
397          }, this)
398        }]);
399      }
400
401      this._secondaryEvents = [
402        [this.picker, {
403          click: $.proxy(this.click, this)
404        }],
405        [this.picker, '.prev, .next', {
406          click: $.proxy(this.navArrowsClick, this)
407        }],
408        [$(window), {
409          resize: $.proxy(this.place, this)
410        }],
411        [$(document), {
412          'mousedown touchstart': $.proxy(function(e) {
413            // Clicked outside the datepicker, hide it
414            if (!(
415                this.element.is(e.target) ||
416                this.element.find(e.target).length ||
417                this.picker.is(e.target) ||
418                this.picker.find(e.target).length ||
419                this.isInline
420              )) {
421              this.hide();
422            }
423          }, this)
424        }]
425      ];
426    },
427    _attachEvents: function() {
428      this._detachEvents();
429      this._applyEvents(this._events);
430    },
431    _detachEvents: function() {
432      this._unapplyEvents(this._events);
433    },
434    _attachSecondaryEvents: function() {
435      this._detachSecondaryEvents();
436      this._applyEvents(this._secondaryEvents);
437    },
438    _detachSecondaryEvents: function() {
439      this._unapplyEvents(this._secondaryEvents);
440    },
441    _trigger: function(event, altdate) {
442      var date = altdate || this.dates.get(-1),
443        local_date = this._utc_to_local(date);
444
445      this.element.trigger({
446        type: event,
447        date: local_date,
448        viewMode: this.viewMode,
449        dates: $.map(this.dates, this._utc_to_local),
450        format: $.proxy(function(ix, format) {
451          if (arguments.length === 0) {
452            ix = this.dates.length - 1;
453            format = this.o.format;
454          } else if (typeof ix === 'string') {
455            format = ix;
456            ix = this.dates.length - 1;
457          }
458          format = format || this.o.format;
459          var date = this.dates.get(ix);
460          return DPGlobal.formatDate(date, format, this.o.language);
461        }, this)
462      });
463    },
464
465    show: function() {
466      if (this.inputField.prop('disabled') || (this.inputField.prop('readonly') && this.o.enableOnReadonly === false))
467        return;
468      if (!this.isInline)
469        this.picker.appendTo(this.o.container);
470      this.place();
471      this.picker.show();
472      this._attachSecondaryEvents();
473      this._trigger('show');
474      if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) {
475        $(this.element).blur();
476      }
477      return this;
478    },
479
480    hide: function() {
481      if (this.isInline || !this.picker.is(':visible'))
482        return this;
483      this.focusDate = null;
484      this.picker.hide().detach();
485      this._detachSecondaryEvents();
486      this.setViewMode(this.o.startView);
487
488      if (this.o.forceParse && this.inputField.val())
489        this.setValue();
490      this._trigger('hide');
491      return this;
492    },
493
494    destroy: function() {
495      this.hide();
496      this._detachEvents();
497      this._detachSecondaryEvents();
498      this.picker.remove();
499      delete this.element.data().datepicker;
500      if (!this.isInput) {
501        delete this.element.data().date;
502      }
503      return this;
504    },
505
506    paste: function(e) {
507      var dateString;
508      if (e.originalEvent.clipboardData && e.originalEvent.clipboardData.types &&
509        $.inArray('text/plain', e.originalEvent.clipboardData.types) !== -1) {
510        dateString = e.originalEvent.clipboardData.getData('text/plain');
511      } else if (window.clipboardData) {
512        dateString = window.clipboardData.getData('Text');
513      } else {
514        return;
515      }
516      this.setDate(dateString);
517      this.update();
518      e.preventDefault();
519    },
520
521    _utc_to_local: function(utc) {
522      if (!utc) {
523        return utc;
524      }
525
526      var local = new Date(utc.getTime() + (utc.getTimezoneOffset() * 60000));
527
528      if (local.getTimezoneOffset() !== utc.getTimezoneOffset()) {
529        local = new Date(utc.getTime() + (local.getTimezoneOffset() * 60000));
530      }
531
532      return local;
533    },
534    _local_to_utc: function(local) {
535      return local && new Date(local.getTime() - (local.getTimezoneOffset() * 60000));
536    },
537    _zero_time: function(local) {
538      return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
539    },
540    _zero_utc_time: function(utc) {
541      return utc && UTCDate(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());
542    },
543
544    getDates: function() {
545      return $.map(this.dates, this._utc_to_local);
546    },
547
548    getUTCDates: function() {
549      return $.map(this.dates, function(d) {
550        return new Date(d);
551      });
552    },
553
554    getDate: function() {
555      return this._utc_to_local(this.getUTCDate());
556    },
557
558    getUTCDate: function() {
559      var selected_date = this.dates.get(-1);
560      if (selected_date !== undefined) {
561        return new Date(selected_date);
562      } else {
563        return null;
564      }
565    },
566
567    clearDates: function() {
568      this.inputField.val('');
569      this.update();
570      this._trigger('changeDate');
571
572      if (this.o.autoclose) {
573        this.hide();
574      }
575    },
576
577    setDates: function() {
578      var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
579      this.update.apply(this, args);
580      this._trigger('changeDate');
581      this.setValue();
582      return this;
583    },
584
585    setUTCDates: function() {
586      var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
587      this.setDates.apply(this, $.map(args, this._utc_to_local));
588      return this;
589    },
590
591    setDate: alias('setDates'),
592    setUTCDate: alias('setUTCDates'),
593    remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead'),
594
595    setValue: function() {
596      var formatted = this.getFormattedDate();
597      this.inputField.val(formatted);
598      return this;
599    },
600
601    getFormattedDate: function(format) {
602      if (format === undefined)
603        format = this.o.format;
604
605      var lang = this.o.language;
606      return $.map(this.dates, function(d) {
607        return DPGlobal.formatDate(d, format, lang);
608      }).join(this.o.multidateSeparator);
609    },
610
611    getStartDate: function() {
612      return this.o.startDate;
613    },
614
615    setStartDate: function(startDate) {
616      this._process_options({
617        startDate: startDate
618      });
619      this.update();
620      this.updateNavArrows();
621      return this;
622    },
623
624    getEndDate: function() {
625      return this.o.endDate;
626    },
627
628    setEndDate: function(endDate) {
629      this._process_options({
630        endDate: endDate
631      });
632      this.update();
633      this.updateNavArrows();
634      return this;
635    },
636
637    setDaysOfWeekDisabled: function(daysOfWeekDisabled) {
638      this._process_options({
639        daysOfWeekDisabled: daysOfWeekDisabled
640      });
641      this.update();
642      return this;
643    },
644
645    setDaysOfWeekHighlighted: function(daysOfWeekHighlighted) {
646      this._process_options({
647        daysOfWeekHighlighted: daysOfWeekHighlighted
648      });
649      this.update();
650      return this;
651    },
652
653    setDatesDisabled: function(datesDisabled) {
654      this._process_options({
655        datesDisabled: datesDisabled
656      });
657      this.update();
658      return this;
659    },
660
661    place: function() {
662      if (this.isInline)
663        return this;
664      var calendarWidth = this.picker.outerWidth(),
665        calendarHeight = this.picker.outerHeight(),
666        visualPadding = 10,
667        container = $(this.o.container),
668        windowWidth = container.width(),
669        scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(),
670        appendOffset = container.offset();
671
672      var parentsZindex = [0];
673      this.element.parents().each(function() {
674        var itemZIndex = $(this).css('z-index');
675        if (itemZIndex !== 'auto' && Number(itemZIndex) !== 0) parentsZindex.push(Number(itemZIndex));
676      });
677      var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset;
678      var offset = this.component ? this.component.parent().offset() : this.element.offset();
679      var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
680      var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
681      var left = offset.left - appendOffset.left;
682      var top = offset.top - appendOffset.top;
683
684      if (this.o.container !== 'body') {
685        top += scrollTop;
686      }
687
688      this.picker.removeClass(
689        'datepicker-orient-top datepicker-orient-bottom ' +
690        'datepicker-orient-right datepicker-orient-left'
691      );
692
693      if (this.o.orientation.x !== 'auto') {
694        this.picker.addClass('datepicker-orient-' + this.o.orientation.x);
695        if (this.o.orientation.x === 'right')
696          left -= calendarWidth - width;
697      }
698      // auto x orientation is best-placement: if it crosses a window
699      // edge, fudge it sideways
700      else {
701        if (offset.left < 0) {
702          // component is outside the window on the left side. Move it into visible range
703          this.picker.addClass('datepicker-orient-left');
704          left -= offset.left - visualPadding;
705        } else if (left + calendarWidth > windowWidth) {
706          // the calendar passes the widow right edge. Align it to component right side
707          this.picker.addClass('datepicker-orient-right');
708          left += width - calendarWidth;
709        } else {
710          if (this.o.rtl) {
711            // Default to right
712            this.picker.addClass('datepicker-orient-right');
713          } else {
714            // Default to left
715            this.picker.addClass('datepicker-orient-left');
716          }
717        }
718      }
719
720      // auto y orientation is best-situation: top or bottom, no fudging,
721      // decision based on which shows more of the calendar
722      var yorient = this.o.orientation.y,
723        top_overflow;
724      if (yorient === 'auto') {
725        top_overflow = -scrollTop + top - calendarHeight;
726        yorient = top_overflow < 0 ? 'bottom' : 'top';
727      }
728
729      this.picker.addClass('datepicker-orient-' + yorient);
730      if (yorient === 'top')
731        top -= calendarHeight + parseInt(this.picker.css('padding-top'));
732      else
733        top += height;
734
735      if (this.o.rtl) {
736        var right = windowWidth - (left + width);
737        this.picker.css({
738          top: top,
739          right: right,
740          zIndex: zIndex
741        });
742      } else {
743        this.picker.css({
744          top: top,
745          left: left,
746          zIndex: zIndex
747        });
748      }
749      return this;
750    },
751
752    _allow_update: true,
753    update: function() {
754      if (!this._allow_update)
755        return this;
756
757      var oldDates = this.dates.copy(),
758        dates = [],
759        fromArgs = false;
760      if (arguments.length) {
761        $.each(arguments, $.proxy(function(i, date) {
762          if (date instanceof Date)
763            date = this._local_to_utc(date);
764          dates.push(date);
765        }, this));
766        fromArgs = true;
767      } else {
768        dates = this.isInput ?
769          this.element.val() :
770          this.element.data('date') || this.inputField.val();
771        if (dates && this.o.multidate)
772          dates = dates.split(this.o.multidateSeparator);
773        else
774          dates = [dates];
775        delete this.element.data().date;
776      }
777
778      dates = $.map(dates, $.proxy(function(date) {
779        return DPGlobal.parseDate(date, this.o.format, this.o.language, this.o.assumeNearbyYear);
780      }, this));
781      dates = $.grep(dates, $.proxy(function(date) {
782        return (!this.dateWithinRange(date) ||
783          !date
784        );
785      }, this), true);
786      this.dates.replace(dates);
787
788      if (this.o.updateViewDate) {
789        if (this.dates.length)
790          this.viewDate = new Date(this.dates.get(-1));
791        else if (this.viewDate < this.o.startDate)
792          this.viewDate = new Date(this.o.startDate);
793        else if (this.viewDate > this.o.endDate)
794          this.viewDate = new Date(this.o.endDate);
795        else
796          this.viewDate = this.o.defaultViewDate;
797      }
798
799      if (fromArgs) {
800        // setting date by clicking
801        this.setValue();
802        this.element.change();
803      } else if (this.dates.length) {
804        // setting date by typing
805        if (typeof this.o.format === 'string') {
806          if ((String(this.element[0].value).length === String(this.o.format).length) && (String(oldDates) !== String(this.dates)))
807            this._trigger('changeDate');
808          this.element.change();
809        } else if (String(oldDates) !== String(this.dates)) {
810          this._trigger('changeDate');
811          this.element.change();
812        }
813      }
814      if (!this.dates.length && oldDates.length) {
815        this._trigger('clearDate');
816        this.element.change();
817      }
818
819      this.fill();
820      return this;
821    },
822
823    fillDow: function() {
824      var dowCnt = this.o.weekStart,
825        html = '<tr>';
826      if (this.o.calendarWeeks) {
827        html += '<th class="cw">&#160;</th>';
828      }
829      while (dowCnt < this.o.weekStart + 7) {
830        html += '<th class="dow';
831        if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) !== -1)
832          html += ' disabled';
833        html += '">' + dates[this.o.language].daysMin[(dowCnt++) % 7] + '</th>';
834      }
835      html += '</tr>';
836      this.picker.find('.datepicker-days thead').append(html);
837    },
838
839    fillMonths: function() {
840      var localDate = this._utc_to_local(this.viewDate);
841      var html = '';
842      var focused;
843      for (var i = 0; i < 12; i++) {
844        focused = localDate && localDate.getMonth() === i ? ' focused' : '';
845        html += '<span class="month' + focused + '">' + dates[this.o.language].monthsShort[i] + '</span>';
846      }
847      this.picker.find('.datepicker-months td').html(html);
848    },
849
850    setRange: function(range) {
851      if (!range || !range.length)
852        delete this.range;
853      else
854        this.range = $.map(range, function(d) {
855          return d.valueOf();
856        });
857      this.fill();
858    },
859
860    getClassNames: function(date) {
861      var cls = [],
862        year = this.viewDate.getUTCFullYear(),
863        month = this.viewDate.getUTCMonth(),
864        today = UTCToday();
865      if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)) {
866        cls.push('old');
867      } else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)) {
868        cls.push('new');
869      }
870      if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
871        cls.push('focused');
872      // Compare internal UTC date with UTC today, not local today
873      if (this.o.todayHighlight && isUTCEquals(date, today)) {
874        cls.push('today');
875      }
876      if (this.dates.contains(date) !== -1)
877        cls.push('active');
878      if (!this.dateWithinRange(date)) {
879        cls.push('disabled');
880      }
881      if (this.dateIsDisabled(date)) {
882        cls.push('disabled', 'disabled-date');
883      }
884      if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1) {
885        cls.push('highlighted');
886      }
887
888      if (this.range) {
889        if (date > this.range[0] && date < this.range[this.range.length - 1]) {
890          cls.push('range');
891        }
892        if ($.inArray(date.valueOf(), this.range) !== -1) {
893          cls.push('selected');
894        }
895        if (date.valueOf() === this.range[0]) {
896          cls.push('range-start');
897        }
898        if (date.valueOf() === this.range[this.range.length - 1]) {
899          cls.push('range-end');
900        }
901      }
902      return cls;
903    },
904
905    _fill_yearsView: function(selector, cssClass, factor, year, startYear, endYear, beforeFn) {
906      var html = '';
907      var step = factor / 10;
908      var view = this.picker.find(selector);
909      var startVal = Math.floor(year / factor) * factor;
910      var endVal = startVal + step * 9;
911      var focusedVal = Math.floor(this.viewDate.getFullYear() / step) * step;
912      var selected = $.map(this.dates, function(d) {
913        return Math.floor(d.getUTCFullYear() / step) * step;
914      });
915
916      var classes, tooltip, before;
917      for (var currVal = startVal - step; currVal <= endVal + step; currVal += step) {
918        classes = [cssClass];
919        tooltip = null;
920
921        if (currVal === startVal - step) {
922          classes.push('old');
923        } else if (currVal === endVal + step) {
924          classes.push('new');
925        }
926        if ($.inArray(currVal, selected) !== -1) {
927          classes.push('active');
928        }
929        if (currVal < startYear || currVal > endYear) {
930          classes.push('disabled');
931        }
932        if (currVal === focusedVal) {
933          classes.push('focused');
934        }
935
936        if (beforeFn !== $.noop) {
937          before = beforeFn(new Date(currVal, 0, 1));
938          if (before === undefined) {
939            before = {};
940          } else if (typeof before === 'boolean') {
941            before = {
942              enabled: before
943            };
944          } else if (typeof before === 'string') {
945            before = {
946              classes: before
947            };
948          }
949          if (before.enabled === false) {
950            classes.push('disabled');
951          }
952          if (before.classes) {
953            classes = classes.concat(before.classes.split(/\s+/));
954          }
955          if (before.tooltip) {
956            tooltip = before.tooltip;
957          }
958        }
959
960        html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + currVal + '</span>';
961      }
962
963      view.find('.datepicker-switch').text(startVal + '-' + endVal);
964      view.find('td').html(html);
965    },
966
967    fill: function() {
968      var d = new Date(this.viewDate),
969        year = d.getUTCFullYear(),
970        month = d.getUTCMonth(),
971        startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
972        startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
973        endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
974        endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
975        todaytxt = dates[this.o.language].today || dates['en'].today || '',
976        cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
977        titleFormat = dates[this.o.language].titleFormat || dates['en'].titleFormat,
978        tooltip,
979        before;
980      if (isNaN(year) || isNaN(month))
981        return;
982      this.picker.find('.datepicker-days .datepicker-switch')
983        .text(DPGlobal.formatDate(d, titleFormat, this.o.language));
984      this.picker.find('tfoot .today')
985        .text(todaytxt)
986        .toggle(this.o.todayBtn !== false);
987      this.picker.find('tfoot .clear')
988        .text(cleartxt)
989        .toggle(this.o.clearBtn !== false);
990      this.picker.find('thead .datepicker-title')
991        .text(this.o.title)
992        .toggle(this.o.title !== '');
993      this.updateNavArrows();
994      this.fillMonths();
995      var prevMonth = UTCDate(year, month, 0),
996        day = prevMonth.getUTCDate();
997      prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7) % 7);
998      var nextMonth = new Date(prevMonth);
999      if (prevMonth.getUTCFullYear() < 100) {
1000        nextMonth.setUTCFullYear(prevMonth.getUTCFullYear());
1001      }
1002      nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
1003      nextMonth = nextMonth.valueOf();
1004      var html = [];
1005      var weekDay, clsName;
1006      while (prevMonth.valueOf() < nextMonth) {
1007        weekDay = prevMonth.getUTCDay();
1008        if (weekDay === this.o.weekStart) {
1009          html.push('<tr>');
1010          if (this.o.calendarWeeks) {
1011            // ISO 8601: First week contains first thursday.
1012            // ISO also states week starts on Monday, but we can be more abstract here.
1013            var
1014              // Start of current week: based on weekstart/current date
1015              ws = new Date(+prevMonth + (this.o.weekStart - weekDay - 7) % 7 * 864e5),
1016              // Thursday of this week
1017              th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
1018              // First Thursday of year, year from thursday
1019              yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay()) % 7 * 864e5),
1020              // Calendar week: ms between thursdays, div ms per day, div 7 days
1021              calWeek = (th - yth) / 864e5 / 7 + 1;
1022            html.push('<td class="cw">' + calWeek + '</td>');
1023          }
1024        }
1025        clsName = this.getClassNames(prevMonth);
1026        clsName.push('day');
1027
1028        if (this.o.beforeShowDay !== $.noop) {
1029          before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
1030          if (before === undefined)
1031            before = {};
1032          else if (typeof before === 'boolean')
1033            before = {
1034              enabled: before
1035            };
1036          else if (typeof before === 'string')
1037            before = {
1038              classes: before
1039            };
1040          if (before.enabled === false)
1041            clsName.push('disabled');
1042          if (before.classes)
1043            clsName = clsName.concat(before.classes.split(/\s+/));
1044          if (before.tooltip)
1045            tooltip = before.tooltip;
1046        }
1047
1048        //Check if uniqueSort exists (supported by jquery >=1.12 and >=2.2)
1049        //Fallback to unique function for older jquery versions
1050        if ($.isFunction($.uniqueSort)) {
1051          clsName = $.uniqueSort(clsName);
1052        } else {
1053          clsName = $.unique(clsName);
1054        }
1055
1056        // Creative Tim - we added a div inside each td for design purposes
1057        html.push('<td class="' + clsName.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + (this.o.dateCells ? ' data-date="' + prevMonth.getTime().toString() + '"' : '') + '><div>' + prevMonth.getUTCDate() + '</div></td>');
1058        tooltip = null;
1059        if (weekDay === this.o.weekEnd) {
1060          html.push('</tr>');
1061        }
1062        prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
1063      }
1064      this.picker.find('.datepicker-days tbody').html(html.join(''));
1065
1066      var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months';
1067      var months = this.picker.find('.datepicker-months')
1068        .find('.datepicker-switch')
1069        .text(this.o.maxViewMode < 2 ? monthsTitle : year)
1070        .end()
1071        .find('tbody span').removeClass('active');
1072
1073      $.each(this.dates, function(i, d) {
1074        if (d.getUTCFullYear() === year)
1075          months.eq(d.getUTCMonth()).addClass('active');
1076      });
1077
1078      if (year < startYear || year > endYear) {
1079        months.addClass('disabled');
1080      }
1081      if (year === startYear) {
1082        months.slice(0, startMonth).addClass('disabled');
1083      }
1084      if (year === endYear) {
1085        months.slice(endMonth + 1).addClass('disabled');
1086      }
1087
1088      if (this.o.beforeShowMonth !== $.noop) {
1089        var that = this;
1090        $.each(months, function(i, month) {
1091          var moDate = new Date(year, i, 1);
1092          var before = that.o.beforeShowMonth(moDate);
1093          if (before === undefined)
1094            before = {};
1095          else if (typeof before === 'boolean')
1096            before = {
1097              enabled: before
1098            };
1099          else if (typeof before === 'string')
1100            before = {
1101              classes: before
1102            };
1103          if (before.enabled === false && !$(month).hasClass('disabled'))
1104            $(month).addClass('disabled');
1105          if (before.classes)
1106            $(month).addClass(before.classes);
1107          if (before.tooltip)
1108            $(month).prop('title', before.tooltip);
1109        });
1110      }
1111
1112      // Generating decade/years picker
1113      this._fill_yearsView(
1114        '.datepicker-years',
1115        'year',
1116        10,
1117        year,
1118        startYear,
1119        endYear,
1120        this.o.beforeShowYear
1121      );
1122
1123      // Generating century/decades picker
1124      this._fill_yearsView(
1125        '.datepicker-decades',
1126        'decade',
1127        100,
1128        year,
1129        startYear,
1130        endYear,
1131        this.o.beforeShowDecade
1132      );
1133
1134      // Generating millennium/centuries picker
1135      this._fill_yearsView(
1136        '.datepicker-centuries',
1137        'century',
1138        1000,
1139        year,
1140        startYear,
1141        endYear,
1142        this.o.beforeShowCentury
1143      );
1144    },
1145
1146    updateNavArrows: function() {
1147      if (!this._allow_update)
1148        return;
1149
1150      var d = new Date(this.viewDate),
1151        year = d.getUTCFullYear(),
1152        month = d.getUTCMonth(),
1153        startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
1154        startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
1155        endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
1156        endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
1157        prevIsDisabled,
1158        nextIsDisabled,
1159        factor = 1;
1160      switch (this.viewMode) {
1161        case 0:
1162          prevIsDisabled = year <= startYear && month <= startMonth;
1163          nextIsDisabled = year >= endYear && month >= endMonth;
1164          break;
1165        case 4:
1166          factor *= 10;
1167          /* falls through */
1168        case 3:
1169          factor *= 10;
1170          /* falls through */
1171        case 2:
1172          factor *= 10;
1173          /* falls through */
1174        case 1:
1175          prevIsDisabled = Math.floor(year / factor) * factor <= startYear;
1176          nextIsDisabled = Math.floor(year / factor) * factor + factor >= endYear;
1177          break;
1178      }
1179
1180      this.picker.find('.prev').toggleClass('disabled', prevIsDisabled);
1181      this.picker.find('.next').toggleClass('disabled', nextIsDisabled);
1182    },
1183
1184    click: function(e) {
1185      e.preventDefault();
1186      e.stopPropagation();
1187
1188      var target, dir, day, year, month;
1189      target = $(e.target);
1190
1191      // Clicked on the switch
1192      if (target.hasClass('datepicker-switch') && this.viewMode !== this.o.maxViewMode) {
1193        this.setViewMode(this.viewMode + 1);
1194      }
1195
1196      // Clicked on today button
1197      if (target.hasClass('today') && !target.hasClass('day')) {
1198        this.setViewMode(0);
1199        this._setDate(UTCToday(), this.o.todayBtn === 'linked' ? null : 'view');
1200      }
1201
1202      // Clicked on clear button
1203      if (target.hasClass('clear')) {
1204        this.clearDates();
1205      }
1206
1207      if (!target.hasClass('disabled')) {
1208        // Clicked on a day
1209        if (target.hasClass('day')) {
1210          day = Number(target.text());
1211          year = this.viewDate.getUTCFullYear();
1212          month = this.viewDate.getUTCMonth();
1213
1214          if (target.hasClass('old') || target.hasClass('new')) {
1215            dir = target.hasClass('old') ? -1 : 1;
1216            month = (month + dir + 12) % 12;
1217            if ((dir === -1 && month === 11) || (dir === 1 && month === 0)) {
1218              year += dir;
1219              if (this.o.updateViewDate) {
1220                this._trigger('changeYear', this.viewDate);
1221              }
1222            }
1223            if (this.o.updateViewDate) {
1224              this._trigger('changeMonth', this.viewDate);
1225            }
1226          }
1227          this._setDate(UTCDate(year, month, day));
1228        }
1229
1230        // Clicked on a month, year, decade, century
1231        if (target.hasClass('month') ||
1232          target.hasClass('year') ||
1233          target.hasClass('decade') ||
1234          target.hasClass('century')) {
1235          this.viewDate.setUTCDate(1);
1236
1237          day = 1;
1238          if (this.viewMode === 1) {
1239            month = target.parent().find('span').index(target);
1240            year = this.viewDate.getUTCFullYear();
1241            this.viewDate.setUTCMonth(month);
1242          } else {
1243            month = 0;
1244            year = Number(target.text());
1245            this.viewDate.setUTCFullYear(year);
1246          }
1247
1248          this._trigger(DPGlobal.viewModes[this.viewMode - 1].e, this.viewDate);
1249
1250          if (this.viewMode === this.o.minViewMode) {
1251            this._setDate(UTCDate(year, month, day));
1252          } else {
1253            this.setViewMode(this.viewMode - 1);
1254            this.fill();
1255          }
1256        }
1257      }
1258
1259      if (this.picker.is(':visible') && this._focused_from) {
1260        this._focused_from.focus();
1261      }
1262      delete this._focused_from;
1263    },
1264
1265    // Clicked on prev or next
1266    navArrowsClick: function(e) {
1267      var target = $(e.target);
1268      var dir = target.hasClass('prev') ? -1 : 1;
1269      if (this.viewMode !== 0) {
1270        dir *= DPGlobal.viewModes[this.viewMode].navStep * 12;
1271      }
1272      this.viewDate = this.moveMonth(this.viewDate, dir);
vendor: 23,277 bytes, lines 1273-2040
1273      this._trigger(DPGlobal.viewModes[this.viewMode].e, this.viewDate);
1274      this.fill();
1275    },
1276
1277    _toggle_multidate: function(date) {
1278      var ix = this.dates.contains(date);
1279      if (!date) {
1280        this.dates.clear();
1281      }
1282
1283      if (ix !== -1) {
1284        if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive) {
1285          this.dates.remove(ix);
1286        }
1287      } else if (this.o.multidate === false) {
1288        this.dates.clear();
1289        this.dates.push(date);
1290      } else {
1291        this.dates.push(date);
1292      }
1293
1294      if (typeof this.o.multidate === 'number')
1295        while (this.dates.length > this.o.multidate)
1296          this.dates.remove(0);
1297    },
1298
1299    _setDate: function(date, which) {
1300      if (!which || which === 'date')
1301        this._toggle_multidate(date && new Date(date));
1302      if ((!which && this.o.updateViewDate) || which === 'view')
1303        this.viewDate = date && new Date(date);
1304
1305      this.fill();
1306      this.setValue();
1307      if (!which || which !== 'view') {
1308        this._trigger('changeDate');
1309      }
1310      this.inputField.trigger('change');
1311      if (this.o.autoclose && (!which || which === 'date')) {
1312        this.hide();
1313      }
1314    },
1315
1316    moveDay: function(date, dir) {
1317      var newDate = new Date(date);
1318      newDate.setUTCDate(date.getUTCDate() + dir);
1319
1320      return newDate;
1321    },
1322
1323    moveWeek: function(date, dir) {
1324      return this.moveDay(date, dir * 7);
1325    },
1326
1327    moveMonth: function(date, dir) {
1328      if (!isValidDate(date))
1329        return this.o.defaultViewDate;
1330      if (!dir)
1331        return date;
1332      var new_date = new Date(date.valueOf()),
1333        day = new_date.getUTCDate(),
1334        month = new_date.getUTCMonth(),
1335        mag = Math.abs(dir),
1336        new_month, test;
1337      dir = dir > 0 ? 1 : -1;
1338      if (mag === 1) {
1339        test = dir === -1
1340          // If going back one month, make sure month is not current month
1341          // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
1342          ?
1343          function() {
1344            return new_date.getUTCMonth() === month;
1345          }
1346          // If going forward one month, make sure month is as expected
1347          // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
1348          :
1349          function() {
1350            return new_date.getUTCMonth() !== new_month;
1351          };
1352        new_month = month + dir;
1353        new_date.setUTCMonth(new_month);
1354        // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
1355        new_month = (new_month + 12) % 12;
1356      } else {
1357        // For magnitudes >1, move one month at a time...
1358        for (var i = 0; i < mag; i++)
1359          // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
1360          new_date = this.moveMonth(new_date, dir);
1361        // ...then reset the day, keeping it in the new month
1362        new_month = new_date.getUTCMonth();
1363        new_date.setUTCDate(day);
1364        test = function() {
1365          return new_month !== new_date.getUTCMonth();
1366        };
1367      }
1368      // Common date-resetting loop -- if date is beyond end of month, make it
1369      // end of month
1370      while (test()) {
1371        new_date.setUTCDate(--day);
1372        new_date.setUTCMonth(new_month);
1373      }
1374      return new_date;
1375    },
1376
1377    moveYear: function(date, dir) {
1378      return this.moveMonth(date, dir * 12);
1379    },
1380
1381    moveAvailableDate: function(date, dir, fn) {
1382      do {
1383        date = this[fn](date, dir);
1384
1385        if (!this.dateWithinRange(date))
1386          return false;
1387
1388        fn = 'moveDay';
1389      }
1390      while (this.dateIsDisabled(date));
1391
1392      return date;
1393    },
1394
1395    weekOfDateIsDisabled: function(date) {
1396      return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1;
1397    },
1398
1399    dateIsDisabled: function(date) {
1400      return (
1401        this.weekOfDateIsDisabled(date) ||
1402        $.grep(this.o.datesDisabled, function(d) {
1403          return isUTCEquals(date, d);
1404        }).length > 0
1405      );
1406    },
1407
1408    dateWithinRange: function(date) {
1409      return date >= this.o.startDate && date <= this.o.endDate;
1410    },
1411
1412    keydown: function(e) {
1413      if (!this.picker.is(':visible')) {
1414        if (e.keyCode === 40 || e.keyCode === 27) { // allow down to re-show picker
1415          this.show();
1416          e.stopPropagation();
1417        }
1418        return;
1419      }
1420      var dateChanged = false,
1421        dir, newViewDate,
1422        focusDate = this.focusDate || this.viewDate;
1423      switch (e.keyCode) {
1424        case 27: // escape
1425          if (this.focusDate) {
1426            this.focusDate = null;
1427            this.viewDate = this.dates.get(-1) || this.viewDate;
1428            this.fill();
1429          } else
1430            this.hide();
1431          e.preventDefault();
1432          e.stopPropagation();
1433          break;
1434        case 37: // left
1435        case 38: // up
1436        case 39: // right
1437        case 40: // down
1438          if (!this.o.keyboardNavigation || this.o.daysOfWeekDisabled.length === 7)
1439            break;
1440          dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1;
1441          if (this.viewMode === 0) {
1442            if (e.ctrlKey) {
1443              newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
1444
1445              if (newViewDate)
1446                this._trigger('changeYear', this.viewDate);
1447            } else if (e.shiftKey) {
1448              newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
1449
1450              if (newViewDate)
1451                this._trigger('changeMonth', this.viewDate);
1452            } else if (e.keyCode === 37 || e.keyCode === 39) {
1453              newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay');
1454            } else if (!this.weekOfDateIsDisabled(focusDate)) {
1455              newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek');
1456            }
1457          } else if (this.viewMode === 1) {
1458            if (e.keyCode === 38 || e.keyCode === 40) {
1459              dir = dir * 4;
1460            }
1461            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
1462          } else if (this.viewMode === 2) {
1463            if (e.keyCode === 38 || e.keyCode === 40) {
1464              dir = dir * 4;
1465            }
1466            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
1467          }
1468          if (newViewDate) {
1469            this.focusDate = this.viewDate = newViewDate;
1470            this.setValue();
1471            this.fill();
1472            e.preventDefault();
1473          }
1474          break;
1475        case 13: // enter
1476          if (!this.o.forceParse)
1477            break;
1478          focusDate = this.focusDate || this.dates.get(-1) || this.viewDate;
1479          if (this.o.keyboardNavigation) {
1480            this._toggle_multidate(focusDate);
1481            dateChanged = true;
1482          }
1483          this.focusDate = null;
1484          this.viewDate = this.dates.get(-1) || this.viewDate;
1485          this.setValue();
1486          this.fill();
1487          if (this.picker.is(':visible')) {
1488            e.preventDefault();
1489            e.stopPropagation();
1490            if (this.o.autoclose)
1491              this.hide();
1492          }
1493          break;
1494        case 9: // tab
1495          this.focusDate = null;
1496          this.viewDate = this.dates.get(-1) || this.viewDate;
1497          this.fill();
1498          this.hide();
1499          break;
1500      }
1501      if (dateChanged) {
1502        if (this.dates.length)
1503          this._trigger('changeDate');
1504        else
1505          this._trigger('clearDate');
1506        this.inputField.trigger('change');
1507      }
1508    },
1509
1510    setViewMode: function(viewMode) {
1511      this.viewMode = viewMode;
1512      this.picker
1513        .children('div')
1514        .hide()
1515        .filter('.datepicker-' + DPGlobal.viewModes[this.viewMode].clsName)
1516        .show();
1517      this.updateNavArrows();
1518      this._trigger('changeViewMode', new Date(this.viewDate));
1519    }
1520  };
1521
1522  var DateRangePicker = function(element, options) {
1523    $.data(element, 'datepicker', this);
1524    this.element = $(element);
1525    this.inputs = $.map(options.inputs, function(i) {
1526      return i.jquery ? i[0] : i;
1527    });
1528    delete options.inputs;
1529
1530    this.keepEmptyValues = options.keepEmptyValues;
1531    delete options.keepEmptyValues;
1532
1533    datepickerPlugin.call($(this.inputs), options)
1534      .on('changeDate', $.proxy(this.dateUpdated, this));
1535
1536    this.pickers = $.map(this.inputs, function(i) {
1537      return $.data(i, 'datepicker');
1538    });
1539    this.updateDates();
1540  };
1541  DateRangePicker.prototype = {
1542    updateDates: function() {
1543      this.dates = $.map(this.pickers, function(i) {
1544        return i.getUTCDate();
1545      });
1546      this.updateRanges();
1547    },
1548    updateRanges: function() {
1549      var range = $.map(this.dates, function(d) {
1550        return d.valueOf();
1551      });
1552      $.each(this.pickers, function(i, p) {
1553        p.setRange(range);
1554      });
1555    },
1556    dateUpdated: function(e) {
1557      // `this.updating` is a workaround for preventing infinite recursion
1558      // between `changeDate` triggering and `setUTCDate` calling.  Until
1559      // there is a better mechanism.
1560      if (this.updating)
1561        return;
1562      this.updating = true;
1563
1564      var dp = $.data(e.target, 'datepicker');
1565
1566      if (dp === undefined) {
1567        return;
1568      }
1569
1570      var new_date = dp.getUTCDate(),
1571        keep_empty_values = this.keepEmptyValues,
1572        i = $.inArray(e.target, this.inputs),
1573        j = i - 1,
1574        k = i + 1,
1575        l = this.inputs.length;
1576      if (i === -1)
1577        return;
1578
1579      $.each(this.pickers, function(i, p) {
1580        if (!p.getUTCDate() && (p === dp || !keep_empty_values))
1581          p.setUTCDate(new_date);
1582      });
1583
1584      if (new_date < this.dates[j]) {
1585        // Date being moved earlier/left
1586        while (j >= 0 && new_date < this.dates[j]) {
1587          this.pickers[j--].setUTCDate(new_date);
1588        }
1589      } else if (new_date > this.dates[k]) {
1590        // Date being moved later/right
1591        while (k < l && new_date > this.dates[k]) {
1592          this.pickers[k++].setUTCDate(new_date);
1593        }
1594      }
1595      this.updateDates();
1596
1597      delete this.updating;
1598    },
1599    destroy: function() {
1600      $.map(this.pickers, function(p) {
1601        p.destroy();
1602      });
1603      $(this.inputs).off('changeDate', this.dateUpdated);
1604      delete this.element.data().datepicker;
1605    },
1606    remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead')
1607  };
1608
1609  function opts_from_el(el, prefix) {
1610    // Derive options from element data-attrs
1611    var data = $(el).data(),
1612      out = {},
1613      inkey,
1614      replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])');
1615    prefix = new RegExp('^' + prefix.toLowerCase());
1616
1617    function re_lower(_, a) {
1618      return a.toLowerCase();
1619    }
1620    for (var key in data)
1621      if (prefix.test(key)) {
1622        inkey = key.replace(replace, re_lower);
1623        out[inkey] = data[key];
1624      }
1625    return out;
1626  }
1627
1628  function opts_from_locale(lang) {
1629    // Derive options from locale plugins
1630    var out = {};
1631    // Check if "de-DE" style date is available, if not language should
1632    // fallback to 2 letter code eg "de"
1633    if (!dates[lang]) {
1634      lang = lang.split('-')[0];
1635      if (!dates[lang])
1636        return;
1637    }
1638    var d = dates[lang];
1639    $.each(locale_opts, function(i, k) {
1640      if (k in d)
1641        out[k] = d[k];
1642    });
1643    return out;
1644  }
1645
1646  var old = $.fn.datepicker;
1647  var datepickerPlugin = function(option) {
1648    var args = Array.apply(null, arguments);
1649    args.shift();
1650    var internal_return;
1651    this.each(function() {
1652      var $this = $(this),
1653        data = $this.data('datepicker'),
1654        options = typeof option === 'object' && option;
1655      if (!data) {
1656        var elopts = opts_from_el(this, 'date'),
1657          // Preliminary otions
1658          xopts = $.extend({}, defaults, elopts, options),
1659          locopts = opts_from_locale(xopts.language),
1660          // Options priority: js args, data-attrs, locales, defaults
1661          opts = $.extend({}, defaults, locopts, elopts, options);
1662        if ($this.hasClass('input-daterange') || opts.inputs) {
1663          $.extend(opts, {
1664            inputs: opts.inputs || $this.find('input').toArray()
1665          });
1666          data = new DateRangePicker(this, opts);
1667        } else {
1668          data = new Datepicker(this, opts);
1669        }
1670        $this.data('datepicker', data);
1671      }
1672      if (typeof option === 'string' && typeof data[option] === 'function') {
1673        internal_return = data[option].apply(data, args);
1674      }
1675    });
1676
1677    if (
1678      internal_return === undefined ||
1679      internal_return instanceof Datepicker ||
1680      internal_return instanceof DateRangePicker
1681    )
1682      return this;
1683
1684    if (this.length > 1)
1685      throw new Error('Using only allowed for the collection of a single element (' + option + ' function)');
1686    else
1687      return internal_return;
1688  };
1689  $.fn.datepicker = datepickerPlugin;
1690
1691  var defaults = $.fn.datepicker.defaults = {
1692    assumeNearbyYear: false,
1693    autoclose: false,
1694    beforeShowDay: $.noop,
1695    beforeShowMonth: $.noop,
1696    beforeShowYear: $.noop,
1697    beforeShowDecade: $.noop,
1698    beforeShowCentury: $.noop,
1699    calendarWeeks: false,
1700    clearBtn: false,
1701    toggleActive: false,
1702    daysOfWeekDisabled: [],
1703    daysOfWeekHighlighted: [],
1704    datesDisabled: [],
1705    endDate: Infinity,
1706    forceParse: true,
1707    format: 'mm/dd/yyyy',
1708    keepEmptyValues: false,
1709    keyboardNavigation: true,
1710    language: 'en',
1711    minViewMode: 0,
1712    maxViewMode: 4,
1713    multidate: false,
1714    multidateSeparator: ',',
1715    orientation: "auto",
1716    rtl: false,
1717    startDate: -Infinity,
1718    startView: 0,
1719    todayBtn: false,
1720    todayHighlight: false,
1721    updateViewDate: true,
1722    weekStart: 0,
1723    disableTouchKeyboard: false,
1724    enableOnReadonly: true,
1725    showOnFocus: true,
1726    zIndexOffset: 10,
1727    container: 'body',
1728    immediateUpdates: false,
1729    dateCells: false,
1730    title: '',
1731    templates: {
1732      leftArrow: '&#x00AB;',
1733      rightArrow: '&#x00BB;'
1734    }
1735  };
1736  var locale_opts = $.fn.datepicker.locale_opts = [
1737    'format',
1738    'rtl',
1739    'weekStart'
1740  ];
1741  $.fn.datepicker.Constructor = Datepicker;
1742  var dates = $.fn.datepicker.dates = {
1743    en: {
1744      days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
1745      daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
1746      daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
1747      months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
1748      monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
1749      today: "Today",
1750      clear: "Clear",
1751      titleFormat: "MM yyyy"
1752    }
1753  };
1754
1755  var DPGlobal = {
1756    viewModes: [{
1757        names: ['days', 'month'],
1758        clsName: 'days',
1759        e: 'changeMonth'
1760      },
1761      {
1762        names: ['months', 'year'],
1763        clsName: 'months',
1764        e: 'changeYear',
1765        navStep: 1
1766      },
1767      {
1768        names: ['years', 'decade'],
1769        clsName: 'years',
1770        e: 'changeDecade',
1771        navStep: 10
1772      },
1773      {
1774        names: ['decades', 'century'],
1775        clsName: 'decades',
1776        e: 'changeCentury',
1777        navStep: 100
1778      },
1779      {
1780        names: ['centuries', 'millennium'],
1781        clsName: 'centuries',
1782        e: 'changeMillennium',
1783        navStep: 1000
1784      }
1785    ],
1786    validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
1787    nonpunctuation: /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,
1788    parseFormat: function(format) {
1789      if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function')
1790        return format;
1791      // IE treats \0 as a string end in inputs (truncating the value),
1792      // so it's a bad format delimiter, anyway
1793      var separators = format.replace(this.validParts, '\0').split('\0'),
1794        parts = format.match(this.validParts);
1795      if (!separators || !separators.length || !parts || parts.length === 0) {
1796        throw new Error("Invalid date format.");
1797      }
1798      return {
1799        separators: separators,
1800        parts: parts
1801      };
1802    },
1803    parseDate: function(date, format, language, assumeNearby) {
1804      if (!date)
1805        return undefined;
1806      if (date instanceof Date)
1807        return date;
1808      if (typeof format === 'string')
1809        format = DPGlobal.parseFormat(format);
1810      if (format.toValue)
1811        return format.toValue(date, format, language);
1812      var fn_map = {
1813          d: 'moveDay',
1814          m: 'moveMonth',
1815          w: 'moveWeek',
1816          y: 'moveYear'
1817        },
1818        dateAliases = {
1819          yesterday: '-1d',
1820          today: '+0d',
1821          tomorrow: '+1d'
1822        },
1823        parts, part, dir, i, fn;
1824      if (date in dateAliases) {
1825        date = dateAliases[date];
1826      }
1827      if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(date)) {
1828        parts = date.match(/([\-+]\d+)([dmwy])/gi);
1829        date = new Date();
1830        for (i = 0; i < parts.length; i++) {
1831          part = parts[i].match(/([\-+]\d+)([dmwy])/i);
1832          dir = Number(part[1]);
1833          fn = fn_map[part[2].toLowerCase()];
1834          date = Datepicker.prototype[fn](date, dir);
1835        }
1836        return Datepicker.prototype._zero_utc_time(date);
1837      }
1838
1839      parts = date && date.match(this.nonpunctuation) || [];
1840
1841      function applyNearbyYear(year, threshold) {
1842        if (threshold === true)
1843          threshold = 10;
1844
1845        // if year is 2 digits or less, than the user most likely is trying to get a recent century
1846        if (year < 100) {
1847          year += 2000;
1848          // if the new year is more than threshold years in advance, use last century
1849          if (year > ((new Date()).getFullYear() + threshold)) {
1850            year -= 100;
1851          }
1852        }
1853
1854        return year;
1855      }
1856
1857      var parsed = {},
1858        setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
1859        setters_map = {
1860          yyyy: function(d, v) {
1861            return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
1862          },
1863          m: function(d, v) {
1864            if (isNaN(d))
1865              return d;
1866            v -= 1;
1867            while (v < 0) v += 12;
1868            v %= 12;
1869            d.setUTCMonth(v);
1870            while (d.getUTCMonth() !== v)
1871              d.setUTCDate(d.getUTCDate() - 1);
1872            return d;
1873          },
1874          d: function(d, v) {
1875            return d.setUTCDate(v);
1876          }
1877        },
1878        val, filtered;
1879      setters_map['yy'] = setters_map['yyyy'];
1880      setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1881      setters_map['dd'] = setters_map['d'];
1882      date = UTCToday();
1883      var fparts = format.parts.slice();
1884      // Remove noop parts
1885      if (parts.length !== fparts.length) {
1886        fparts = $(fparts).filter(function(i, p) {
1887          return $.inArray(p, setters_order) !== -1;
1888        }).toArray();
1889      }
1890      // Process remainder
1891      function match_part() {
1892        var m = this.slice(0, parts[i].length),
1893          p = parts[i].slice(0, m.length);
1894        return m.toLowerCase() === p.toLowerCase();
1895      }
1896      if (parts.length === fparts.length) {
1897        var cnt;
1898        for (i = 0, cnt = fparts.length; i < cnt; i++) {
1899          val = parseInt(parts[i], 10);
1900          part = fparts[i];
1901          if (isNaN(val)) {
1902            switch (part) {
1903              case 'MM':
1904                filtered = $(dates[language].months).filter(match_part);
1905                val = $.inArray(filtered[0], dates[language].months) + 1;
1906                break;
1907              case 'M':
1908                filtered = $(dates[language].monthsShort).filter(match_part);
1909                val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1910                break;
1911            }
1912          }
1913          parsed[part] = val;
1914        }
1915        var _date, s;
1916        for (i = 0; i < setters_order.length; i++) {
1917          s = setters_order[i];
1918          if (s in parsed && !isNaN(parsed[s])) {
1919            _date = new Date(date);
1920            setters_map[s](_date, parsed[s]);
1921            if (!isNaN(_date))
1922              date = _date;
1923          }
1924        }
1925      }
1926      return date;
1927    },
1928    formatDate: function(date, format, language) {
1929      if (!date)
1930        return '';
1931      if (typeof format === 'string')
1932        format = DPGlobal.parseFormat(format);
1933      if (format.toDisplay)
1934        return format.toDisplay(date, format, language);
1935      var val = {
1936        d: date.getUTCDate(),
1937        D: dates[language].daysShort[date.getUTCDay()],
1938        DD: dates[language].days[date.getUTCDay()],
1939        m: date.getUTCMonth() + 1,
1940        M: dates[language].monthsShort[date.getUTCMonth()],
1941        MM: dates[language].months[date.getUTCMonth()],
1942        yy: date.getUTCFullYear().toString().substring(2),
1943        yyyy: date.getUTCFullYear()
1944      };
1945      val.dd = (val.d < 10 ? '0' : '') + val.d;
1946      val.mm = (val.m < 10 ? '0' : '') + val.m;
1947      date = [];
1948      var seps = $.extend([], format.separators);
1949      for (var i = 0, cnt = format.parts.length; i <= cnt; i++) {
1950        if (seps.length)
1951          date.push(seps.shift());
1952        date.push(val[format.parts[i]]);
1953      }
1954      return date.join('');
1955    },
1956    headTemplate: '<thead>' +
1957      '<tr>' +
1958      '<th colspan="7" class="datepicker-title"></th>' +
1959      '</tr>' +
1960      '<tr>' +
1961      '<th class="prev">&laquo;</th>' +
1962      '<th colspan="5" class="datepicker-switch"></th>' +
1963      '<th class="next">&raquo;</th>' +
1964      '</tr>' +
1965      '</thead>',
1966    contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
1967    footTemplate: '<tfoot>' +
1968      '<tr>' +
1969      '<th colspan="7" class="today"></th>' +
1970      '</tr>' +
1971      '<tr>' +
1972      '<th colspan="7" class="clear"></th>' +
1973      '</tr>' +
1974      '</tfoot>'
1975  };
1976  DPGlobal.template = '<div class="datepicker">' +
1977    '<div class="datepicker-days">' +
1978    '<table class="table-condensed">' +
1979    DPGlobal.headTemplate +
1980    '<tbody></tbody>' +
1981    DPGlobal.footTemplate +
1982    '</table>' +
1983    '</div>' +
1984    '<div class="datepicker-months">' +
1985    '<table class="table-condensed">' +
1986    DPGlobal.headTemplate +
1987    DPGlobal.contTemplate +
1988    DPGlobal.footTemplate +
1989    '</table>' +
1990    '</div>' +
1991    '<div class="datepicker-years">' +
1992    '<table class="table-condensed">' +
1993    DPGlobal.headTemplate +
1994    DPGlobal.contTemplate +
1995    DPGlobal.footTemplate +
1996    '</table>' +
1997    '</div>' +
1998    '<div class="datepicker-decades">' +
1999    '<table class="table-condensed">' +
2000    DPGlobal.headTemplate +
2001    DPGlobal.contTemplate +
2002    DPGlobal.footTemplate +
2003    '</table>' +
2004    '</div>' +
2005    '<div class="datepicker-centuries">' +
2006    '<table class="table-condensed">' +
2007    DPGlobal.headTemplate +
2008    DPGlobal.contTemplate +
2009    DPGlobal.footTemplate +
2010    '</table>' +
2011    '</div>' +
2012    '</div>';
2013
2014  $.fn.datepicker.DPGlobal = DPGlobal;
2015
2016
2017  /* DATEPICKER NO CONFLICT
2018   * =================== */
2019
2020  $.fn.datepicker.noConflict = function() {
2021    $.fn.datepicker = old;
2022    return this;
2023  };
2024
2025  /* DATEPICKER VERSION
2026   * =================== */
2027  $.fn.datepicker.version = '1.7.0-dev';
2028
2029  $.fn.datepicker.deprecated = function(msg) {
2030    var console = window.console;
2031    if (console && console.warn) {
2032      console.warn('DEPRECATED: ' + msg);
2033    }
2034  };
2035
2036
2037  /* DATEPICKER DATA-API
2038   * ================== */
2039
2040  $(document).on(
2041    'focus.datepicker.data-api click.datepicker.data-api',
2042    '[data-provide="datepicker"]',
2043    function(e) {
2044      var $this = $(this);
2045      if ($this.data('datepicker'))
2046        return;
2047      e.preventDefault();
2048      // component click requires us to explicitly show it
2049      datepickerPlugin.call($this, 'show');
2050    }
2051  );
2052  $(function() {
2053    datepickerPlugin.call($('[data-provide="datepicker-inline"]'));
2054  });
2055
2056}));

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.