PageSourceSearch

https://js.carpetexpress.com/js/plugins/bootstrap-datepicker.js?ver=17092026

js carpetexpress.com collected 2026-10-05 02:07:39 UTC 72,119 bytes, 1,703 lines download raw bytes

vendor: 71,799 bytes, lines 1-1693
1(function(factory) {
2    if (typeof define === 'function' && define.amd) {
3        define(['jquery'], factory);
4    } else if (typeof exports === 'object') {
5        factory(require('jquery'));
6    } else {
7        factory(jQuery);
8    }
9}(function($, undefined) {
10    function UTCDate() {
11        return new Date(Date.UTC.apply(Date, arguments));
12    }
13
14    function UTCToday() {
15        var today = new Date();
16        return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
17    }
18
19    function isUTCEquals(date1, date2) {
20        return (date1.getUTCFullYear() === date2.getUTCFullYear() && date1.getUTCMonth() === date2.getUTCMonth() && date1.getUTCDate() === date2.getUTCDate());
21    }
22
23    function alias(method, deprecationMsg) {
24        return function() {
25            if (deprecationMsg !== undefined) {
26                $.fn.datepicker.deprecated(deprecationMsg);
27            }
28            return this[method].apply(this, arguments);
29        };
30    }
31
32    function isValidDate(d) {
33        return d && !isNaN(d.getTime());
34    }
35    var DateArray = (function() {
36        var extras = {
37            get: function(i) {
38                return this.slice(i)[0];
39            },
40            contains: function(d) {
41                var val = d && d.valueOf();
42                for (var i = 0, l = this.length; i < l; i++)
43                    if (0 <= this[i].valueOf() - val && this[i].valueOf() - val < 1000 * 60 * 60 * 24)
44                        return i;
45                return -1;
46            },
47            remove: function(i) {
48                this.splice(i, 1);
49            },
50            replace: function(new_array) {
51                if (!new_array)
52                    return;
53                if (!$.isArray(new_array))
54                    new_array = [new_array];
55                this.clear();
56                this.push.apply(this, new_array);
57            },
58            clear: function() {
59                this.length = 0;
60            },
61            copy: function() {
62                var a = new DateArray();
63                a.replace(this);
64                return a;
65            }
66        };
67        return function() {
68            var a = [];
69            a.push.apply(a, arguments);
70            $.extend(a, extras);
71            return a;
72        };
73    })();
74    var Datepicker = function(element, options) {
75        $.data(element, 'datepicker', this);
76        this._events = [];
77        this._secondaryEvents = [];
78        this._process_options(options);
79        this.dates = new DateArray();
80        this.viewDate = this.o.defaultViewDate;
81        this.focusDate = null;
82        this.element = $(element);
83        this.isInput = this.element.is('input');
84        this.inputField = this.isInput ? this.element : this.element.find('input');
85        this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .input-group-append, .input-group-prepend, .btn') : false;
86        if (this.component && this.component.length === 0)
87            this.component = false;
88        this.isInline = !this.component && this.element.is('div');
89        this.picker = $(DPGlobal.template);
90        if (this._check_template(this.o.templates.leftArrow)) {
91            this.picker.find('.prev').html(this.o.templates.leftArrow);
92        }
93        if (this._check_template(this.o.templates.rightArrow)) {
94            this.picker.find('.next').html(this.o.templates.rightArrow);
95        }
96        this._buildEvents();
97        this._attachEvents();
98        if (this.isInline) {
99            this.picker.addClass('datepicker-inline').appendTo(this.element);
100        } else {
101            this.picker.addClass('datepicker-dropdown dropdown-menu');
102        }
103        if (this.o.rtl) {
104            this.picker.addClass('datepicker-rtl');
105        }
106        if (this.o.calendarWeeks) {
107            this.picker.find('.datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear').attr('colspan', function(i, val) {
108                return Number(val) + 1;
109            });
110        }
111        this._process_options({
112            startDate: this._o.startDate,
113            endDate: this._o.endDate,
114            daysOfWeekDisabled: this.o.daysOfWeekDisabled,
115            daysOfWeekHighlighted: this.o.daysOfWeekHighlighted,
116            datesDisabled: this.o.datesDisabled
117        });
118        this._allow_update = false;
119        this.setViewMode(this.o.startView);
120        this._allow_update = true;
121        this.fillDow();
122        this.fillMonths();
123        this.update();
124        if (this.isInline) {
125            this.show();
126        }
127    };
128    Datepicker.prototype = {
129        constructor: Datepicker,
130        _resolveViewName: function(view) {
131            $.each(DPGlobal.viewModes, function(i, viewMode) {
132                if (view === i || $.inArray(view, viewMode.names) !== -1) {
133                    view = i;
134                    return false;
135                }
136            });
137            return view;
138        },
139        _resolveDaysOfWeek: function(daysOfWeek) {
140            if (!$.isArray(daysOfWeek))
141                daysOfWeek = daysOfWeek.split(/[,\s]*/);
142            return $.map(daysOfWeek, Number);
143        },
144        _check_template: function(tmp) {
145            try {
146                if (tmp === undefined || tmp === "") {
147                    return false;
148                }
149                if ((tmp.match(/[<>]/g) || []).length <= 0) {
150                    return true;
151                }
152                var jDom = $(tmp);
153                return jDom.length > 0;
154            } catch (ex) {
155                return false;
156            }
157        },
158        _process_options: function(opts) {
159            this._o = $.extend({}, this._o, opts);
160            var o = this.o = $.extend({}, this._o);
161            var lang = o.language;
162            if (!dates[lang]) {
163                lang = lang.split('-')[0];
164                if (!dates[lang])
165                    lang = defaults.language;
166            }
167            o.language = lang;
168            o.startView = this._resolveViewName(o.startView);
169            o.minViewMode = this._resolveViewName(o.minViewMode);
170            o.maxViewMode = this._resolveViewName(o.maxViewMode);
171            o.startView = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, o.startView));
172            if (o.multidate !== true) {
173                o.multidate = Number(o.multidate) || false;
174                if (o.multidate !== false)
175                    o.multidate = Math.max(0, o.multidate);
176            }
177            o.multidateSeparator = String(o.multidateSeparator);
178            o.weekStart %= 7;
179            o.weekEnd = (o.weekStart + 6) % 7;
180            var format = DPGlobal.parseFormat(o.format);
181            if (o.startDate !== -Infinity) {
182                if (!!o.startDate) {
183                    if (o.startDate instanceof Date)
184                        o.startDate = this._local_to_utc(this._zero_time(o.startDate));
185                    else
186                        o.startDate = DPGlobal.parseDate(o.startDate, format, o.language, o.assumeNearbyYear);
187                } else {
188                    o.startDate = -Infinity;
189                }
190            }
191            if (o.endDate !== Infinity) {
192                if (!!o.endDate) {
193                    if (o.endDate instanceof Date)
194                        o.endDate = this._local_to_utc(this._zero_time(o.endDate));
195                    else
196                        o.endDate = DPGlobal.parseDate(o.endDate, format, o.language, o.assumeNearbyYear);
197                } else {
198                    o.endDate = Infinity;
199                }
200            }
201            o.daysOfWeekDisabled = this._resolveDaysOfWeek(o.daysOfWeekDisabled || []);
202            o.daysOfWeekHighlighted = this._resolveDaysOfWeek(o.daysOfWeekHighlighted || []);
203            o.datesDisabled = o.datesDisabled || [];
204            if (!$.isArray(o.datesDisabled)) {
205                o.datesDisabled = o.datesDisabled.split(',');
206            }
207            o.datesDisabled = $.map(o.datesDisabled, function(d) {
208                return DPGlobal.parseDate(d, format, o.language, o.assumeNearbyYear);
209            });
210            var plc = String(o.orientation).toLowerCase().split(/\s+/g),
211                _plc = o.orientation.toLowerCase();
212            plc = $.grep(plc, function(word) {
213                return /^auto|left|right|top|bottom$/.test(word);
214            });
215            o.orientation = {
216                x: 'auto',
217                y: 'auto'
218            };
219            if (!_plc || _plc === 'auto');
220            else if (plc.length === 1) {
221                switch (plc[0]) {
222                    case 'top':
223                    case 'bottom':
224                        o.orientation.y = plc[0];
225                        break;
226                    case 'left':
227                    case 'right':
228                        o.orientation.x = plc[0];
229                        break;
230                }
231            } else {
232                _plc = $.grep(plc, function(word) {
233                    return /^left|right$/.test(word);
234                });
235                o.orientation.x = _plc[0] || 'auto';
236                _plc = $.grep(plc, function(word) {
237                    return /^top|bottom$/.test(word);
238                });
239                o.orientation.y = _plc[0] || 'auto';
240            }
241            if (o.defaultViewDate instanceof Date || typeof o.defaultViewDate === 'string') {
242                o.defaultViewDate = DPGlobal.parseDate(o.defaultViewDate, format, o.language, o.assumeNearbyYear);
243            } else if (o.defaultViewDate) {
244                var year = o.defaultViewDate.year || new Date().getFullYear();
245                var month = o.defaultViewDate.month || 0;
246                var day = o.defaultViewDate.day || 1;
247                o.defaultViewDate = UTCDate(year, month, day);
248            } else {
249                o.defaultViewDate = UTCToday();
250            }
251        },
252        _applyEvents: function(evs) {
253            for (var i = 0, el, ch, ev; i < evs.length; i++) {
254                el = evs[i][0];
255                if (evs[i].length === 2) {
256                    ch = undefined;
257                    ev = evs[i][1];
258                } else if (evs[i].length === 3) {
259                    ch = evs[i][1];
260                    ev = evs[i][2];
261                }
262                el.on(ev, ch);
263            }
264        },
265        _unapplyEvents: function(evs) {
266            for (var i = 0, el, ev, ch; i < evs.length; i++) {
267                el = evs[i][0];
268                if (evs[i].length === 2) {
269                    ch = undefined;
270                    ev = evs[i][1];
271                } else if (evs[i].length === 3) {
272                    ch = evs[i][1];
273                    ev = evs[i][2];
274                }
275                el.off(ev, ch);
276            }
277        },
278        _buildEvents: function() {
279            var events = {
280                keyup: $.proxy(function(e) {
281                    if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
282                        this.update();
283                }, this),
284                keydown: $.proxy(this.keydown, this),
285                paste: $.proxy(this.paste, this)
286            };
287            if (this.o.showOnFocus === true) {
288                events.focus = $.proxy(this.show, this);
289            }
290            if (this.isInput) {
291                this._events = [
292                    [this.element, events]
293                ];
294            } else if (this.component && this.inputField.length) {
295                this._events = [
296                    [this.inputField, events],
297                    [this.component, {
298                        click: $.proxy(this.show, this)
299                    }]
300                ];
301            } else {
302                this._events = [
303                    [this.element, {
304                        click: $.proxy(this.show, this),
305                        keydown: $.proxy(this.keydown, this)
306                    }]
307                ];
308            }
309            this._events.push([this.element, '*', {
310                blur: $.proxy(function(e) {
311                    this._focused_from = e.target;
312                }, this)
313            }], [this.element, {
314                blur: $.proxy(function(e) {
315                    this._focused_from = e.target;
316                }, this)
317            }]);
318            if (this.o.immediateUpdates) {
319                this._events.push([this.element, {
320                    'changeYear changeMonth': $.proxy(function(e) {
321                        this.update(e.date);
322                    }, this)
323                }]);
324            }
325            this._secondaryEvents = [
326                [this.picker, {
327                    click: $.proxy(this.click, this)
328                }],
329                [this.picker, '.prev, .next', {
330                    click: $.proxy(this.navArrowsClick, this)
331                }],
332                [this.picker, '.day:not(.disabled)', {
333                    click: $.proxy(this.dayCellClick, this)
334                }],
335                [$(window), {
336                    resize: $.proxy(this.place, this)
337                }],
338                [$(document), {
339                    'mousedown touchstart': $.proxy(function(e) {
340                        if (!(this.element.is(e.target) || this.element.find(e.target).length || this.picker.is(e.target) || this.picker.find(e.target).length || this.isInline)) {
341                            this.hide();
342                        }
343                    }, this)
344                }]
345            ];
346        },
347        _attachEvents: function() {
348            this._detachEvents();
349            this._applyEvents(this._events);
350        },
351        _detachEvents: function() {
352            this._unapplyEvents(this._events);
353        },
354        _attachSecondaryEvents: function() {
355            this._detachSecondaryEvents();
356            this._applyEvents(this._secondaryEvents);
357        },
358        _detachSecondaryEvents: function() {
359            this._unapplyEvents(this._secondaryEvents);
360        },
361        _trigger: function(event, altdate) {
362            var date = altdate || this.dates.get(-1),
363                local_date = this._utc_to_local(date);
364            this.element.trigger({
365                type: event,
366                date: local_date,
367                viewMode: this.viewMode,
368                dates: $.map(this.dates, this._utc_to_local),
369                format: $.proxy(function(ix, format) {
370                    if (arguments.length === 0) {
371                        ix = this.dates.length - 1;
372                        format = this.o.format;
373                    } else if (typeof ix === 'string') {
374                        format = ix;
375                        ix = this.dates.length - 1;
376                    }
377                    format = format || this.o.format;
378                    var date = this.dates.get(ix);
379                    return DPGlobal.formatDate(date, format, this.o.language);
380                }, this)
381            });
382        },
383        show: function() {
384            if (this.inputField.is(':disabled') || (this.inputField.prop('readonly') && this.o.enableOnReadonly === false))
385                return;
386            if (!this.isInline)
387                this.picker.appendTo(this.o.container);
388            this.place();
389            this.picker.show();
390            this._attachSecondaryEvents();
391            this._trigger('show');
392            if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) {
393                $(this.element).blur();
394            }
395            return this;
396        },
397        hide: function() {
398            if (this.isInline || !this.picker.is(':visible'))
399                return this;
400            this.focusDate = null;
401            this.picker.hide().detach();
402            this._detachSecondaryEvents();
403            this.setViewMode(this.o.startView);
404            if (this.o.forceParse && this.inputField.val())
405                this.setValue();
406            this._trigger('hide');
407            return this;
408        },
409        destroy: function() {
410            this.hide();
411            this._detachEvents();
412            this._detachSecondaryEvents();
413            this.picker.remove();
414            delete this.element.data().datepicker;
415            if (!this.isInput) {
416                delete this.element.data().date;
417            }
418            return this;
419        },
420        paste: function(e) {
421            var dateString;
422            if (e.originalEvent.clipboardData && e.originalEvent.clipboardData.types && $.inArray('text/plain', e.originalEvent.clipboardData.types) !== -1) {
423                dateString = e.originalEvent.clipboardData.getData('text/plain');
424            } else if (window.clipboardData) {
425                dateString = window.clipboardData.getData('Text');
426            } else {
427                return;
428            }
429            this.setDate(dateString);
430            this.update();
431            e.preventDefault();
432        },
433        _utc_to_local: function(utc) {
434            if (!utc) {
435                return utc;
436            }
437            var local = new Date(utc.getTime() + (utc.getTimezoneOffset() * 60000));
438            if (local.getTimezoneOffset() !== utc.getTimezoneOffset()) {
439                local = new Date(utc.getTime() + (local.getTimezoneOffset() * 60000));
440            }
441            return local;
442        },
443        _local_to_utc: function(local) {
444            return local && new Date(local.getTime() - (local.getTimezoneOffset() * 60000));
445        },
446        _zero_time: function(local) {
447            return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
448        },
449        _zero_utc_time: function(utc) {
450            return utc && UTCDate(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());
451        },
452        getDates: function() {
453            return $.map(this.dates, this._utc_to_local);
454        },
455        getUTCDates: function() {
456            return $.map(this.dates, function(d) {
457                return new Date(d);
458            });
459        },
460        getDate: function() {
461            return this._utc_to_local(this.getUTCDate());
462        },
463        getUTCDate: function() {
464            var selected_date = this.dates.get(-1);
465            if (selected_date !== undefined) {
466                return new Date(selected_date);
467            } else {
468                return null;
469            }
470        },
471        clearDates: function() {
472            this.inputField.val('');
473            this.update();
474            this._trigger('changeDate');
475            if (this.o.autoclose) {
476                this.hide();
477            }
478        },
479        setDates: function() {
480            var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
481            this.update.apply(this, args);
482            this._trigger('changeDate');
483            this.setValue();
484            return this;
485        },
486        setUTCDates: function() {
487            var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
488            this.setDates.apply(this, $.map(args, this._utc_to_local));
489            return this;
490        },
491        setDate: alias('setDates'),
492        setUTCDate: alias('setUTCDates'),
493        remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead'),
494        setValue: function() {
495            var formatted = this.getFormattedDate();
496            this.inputField.val(formatted);
497            return this;
498        },
499        getFormattedDate: function(format) {
500            if (format === undefined)
501                format = this.o.format;
502            var lang = this.o.language;
503            return $.map(this.dates, function(d) {
504                return DPGlobal.formatDate(d, format, lang);
505            }).join(this.o.multidateSeparator);
506        },
507        getStartDate: function() {
508            return this.o.startDate;
509        },
510        setStartDate: function(startDate) {
511            this._process_options({
512                startDate: startDate
513            });
514            this.update();
515            this.updateNavArrows();
516            return this;
517        },
518        getEndDate: function() {
519            return this.o.endDate;
520        },
521        setEndDate: function(endDate) {
522            this._process_options({
523                endDate: endDate
524            });
525            this.update();
526            this.updateNavArrows();
527            return this;
528        },
529        setDaysOfWeekDisabled: function(daysOfWeekDisabled) {
530            this._process_options({
531                daysOfWeekDisabled: daysOfWeekDisabled
532            });
533            this.update();
534            return this;
535        },
536        setDaysOfWeekHighlighted: function(daysOfWeekHighlighted) {
537            this._process_options({
538                daysOfWeekHighlighted: daysOfWeekHighlighted
539            });
540            this.update();
541            return this;
542        },
543        setDatesDisabled: function(datesDisabled) {
544            this._process_options({
545                datesDisabled: datesDisabled
546            });
547            this.update();
548            return this;
549        },
550        place: function() {
551            if (this.isInline)
552                return this;
553            var calendarWidth = this.picker.outerWidth(),
554                calendarHeight = this.picker.outerHeight(),
555                visualPadding = 10,
556                container = $(this.o.container),
557                windowWidth = container.width(),
558                scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(),
559                appendOffset = container.offset();
560            var parentsZindex = [0];
561            this.element.parents().each(function() {
562                var itemZIndex = $(this).css('z-index');
563                if (itemZIndex !== 'auto' && Number(itemZIndex) !== 0) parentsZindex.push(Number(itemZIndex));
564            });
565            var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset;
566            var offset = this.component ? this.component.parent().offset() : this.element.offset();
567            var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
568            var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
569            var left = offset.left - appendOffset.left;
570            var top = offset.top - appendOffset.top;
571            if (this.o.container !== 'body') {
572                top += scrollTop;
573            }
574            this.picker.removeClass('datepicker-orient-top datepicker-orient-bottom ' +
575                'datepicker-orient-right datepicker-orient-left');
576            if (this.o.orientation.x !== 'auto') {
577                this.picker.addClass('datepicker-orient-' + this.o.orientation.x);
578                if (this.o.orientation.x === 'right')
579                    left -= calendarWidth - width;
580            } else {
581                if (offset.left < 0) {
582                    this.picker.addClass('datepicker-orient-left');
583                    left -= offset.left - visualPadding;
584                } else if (left + calendarWidth > windowWidth) {
585                    this.picker.addClass('datepicker-orient-right');
586                    left += width - calendarWidth;
587                } else {
588                    if (this.o.rtl) {
589                        this.picker.addClass('datepicker-orient-right');
590                    } else {
591                        this.picker.addClass('datepicker-orient-left');
592                    }
593                }
594            }
595            var yorient = this.o.orientation.y,
596                top_overflow;
597            if (yorient === 'auto') {
598                top_overflow = -scrollTop + top - calendarHeight;
599                yorient = top_overflow < 0 ? 'bottom' : 'top';
600            }
601            this.picker.addClass('datepicker-orient-' + yorient);
602            if (yorient === 'top')
603                top -= calendarHeight + parseInt(this.picker.css('padding-top'));
604            else
605                top += height;
606            if (this.o.rtl) {
607                var right = windowWidth - (left + width);
608                this.picker.css({
609                    top: top,
610                    right: right,
611                    zIndex: zIndex
612                });
613            } else {
614                this.picker.css({
615                    top: top,
616                    left: left,
617                    zIndex: zIndex
618                });
619            }
620            return this;
621        },
622        _allow_update: true,
623        update: function() {
624            if (!this._allow_update)
625                return this;
626            var oldDates = this.dates.copy(),
627                dates = [],
628                fromArgs = false;
629            if (arguments.length) {
630                $.each(arguments, $.proxy(function(i, date) {
631                    if (date instanceof Date)
632                        date = this._local_to_utc(date);
633                    dates.push(date);
634                }, this));
635                fromArgs = true;
636            } else {
637                dates = this.isInput ? this.element.val() : this.element.data('date') || this.inputField.val();
638                if (dates && this.o.multidate)
639                    dates = dates.split(this.o.multidateSeparator);
640                else
641                    dates = [dates];
642                delete this.element.data().date;
643            }
644            dates = $.map(dates, $.proxy(function(date) {
645                return DPGlobal.parseDate(date, this.o.format, this.o.language, this.o.assumeNearbyYear);
646            }, this));
647            dates = $.grep(dates, $.proxy(function(date) {
648                return (!this.dateWithinRange(date) || !date);
649            }, this), true);
650            this.dates.replace(dates);
651            if (this.o.updateViewDate) {
652                if (this.dates.length)
653                    this.viewDate = new Date(this.dates.get(-1));
654                else if (this.viewDate < this.o.startDate)
655                    this.viewDate = new Date(this.o.startDate);
656                else if (this.viewDate > this.o.endDate)
657                    this.viewDate = new Date(this.o.endDate);
658                else
659                    this.viewDate = this.o.defaultViewDate;
660            }
661            if (fromArgs) {
662                this.setValue();
663                this.element.change();
664            } else if (this.dates.length) {
665                if (String(oldDates) !== String(this.dates) && fromArgs) {
666                    this._trigger('changeDate');
667                    this.element.change();
668                }
669            }
670            if (!this.dates.length && oldDates.length) {
671                this._trigger('clearDate');
672                this.element.change();
673            }
674            this.fill();
675            return this;
676        },
677        fillDow: function() {
678            if (this.o.showWeekDays) {
679                var dowCnt = this.o.weekStart,
680                    html = '<tr>';
681                if (this.o.calendarWeeks) {
682                    html += '<th class="cw">&#160;</th>';
683                }
684                while (dowCnt < this.o.weekStart + 7) {
685                    html += '<th class="dow';
686                    if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) !== -1)
687                        html += ' disabled';
688                    html += '">' + dates[this.o.language].daysMin[(dowCnt++) % 7] + '</th>';
689                }
690                html += '</tr>';
691                this.picker.find('.datepicker-days thead').append(html);
692            }
693        },
694        fillMonths: function() {
695            var localDate = this._utc_to_local(this.viewDate);
696            var html = '';
697            var focused;
698            for (var i = 0; i < 12; i++) {
699                focused = localDate && localDate.getMonth() === i ? ' focused' : '';
700                html += '<span class="month' + focused + '">' + dates[this.o.language].monthsShort[i] + '</span>';
701            }
702            this.picker.find('.datepicker-months td').html(html);
703        },
704        setRange: function(range) {
705            if (!range || !range.length)
706                delete this.range;
707            else
708                this.range = $.map(range, function(d) {
709                    return d.valueOf();
710                });
711            this.fill();
712        },
713        getClassNames: function(date) {
714            var cls = [],
715                year = this.viewDate.getUTCFullYear(),
716                month = this.viewDate.getUTCMonth(),
717                today = UTCToday();
718            if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)) {
719                cls.push('old');
720            } else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)) {
721                cls.push('new');
722            }
723            if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
724                cls.push('focused');
725            if (this.o.todayHighlight && isUTCEquals(date, today)) {
726                cls.push('today');
727            }
728            if (this.dates.contains(date) !== -1)
729                cls.push('active');
730            if (!this.dateWithinRange(date)) {
731                cls.push('disabled');
732            }
733            if (this.dateIsDisabled(date)) {
734                cls.push('disabled', 'disabled-date');
735            }
736            if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1) {
737                cls.push('highlighted');
738            }
739            if (this.range) {
740                if (date > this.range[0] && date < this.range[this.range.length - 1]) {
741                    cls.push('range');
742                }
743                if ($.inArray(date.valueOf(), this.range) !== -1) {
744                    cls.push('selected');
745                }
746                if (date.valueOf() === this.range[0]) {
747                    cls.push('range-start');
748                }
749                if (date.valueOf() === this.range[this.range.length - 1]) {
750                    cls.push('range-end');
751                }
752            }
753            return cls;
754        },
755        _fill_yearsView: function(selector, cssClass, factor, year, startYear, endYear, beforeFn) {
756            var html = '';
757            var step = factor / 10;
758            var view = this.picker.find(selector);
759            var startVal = Math.floor(year / factor) * factor;
760            var endVal = startVal + step * 9;
761            var focusedVal = Math.floor(this.viewDate.getFullYear() / step) * step;
762            var selected = $.map(this.dates, function(d) {
763                return Math.floor(d.getUTCFullYear() / step) * step;
764            });
765            var classes, tooltip, before;
766            for (var currVal = startVal - step; currVal <= endVal + step; currVal += step) {
767                classes = [cssClass];
768                tooltip = null;
769                if (currVal === startVal - step) {
770                    classes.push('old');
771                } else if (currVal === endVal + step) {
772                    classes.push('new');
773                }
774                if ($.inArray(currVal, selected) !== -1) {
775                    classes.push('active');
776                }
777                if (currVal < startYear || currVal > endYear) {
778                    classes.push('disabled');
779                }
780                if (currVal === focusedVal) {
781                    classes.push('focused');
782                }
783                if (beforeFn !== $.noop) {
784                    before = beforeFn(new Date(currVal, 0, 1));
785                    if (before === undefined) {
786                        before = {};
787                    } else if (typeof before === 'boolean') {
788                        before = {
789                            enabled: before
790                        };
791                    } else if (typeof before === 'string') {
792                        before = {
793                            classes: before
794                        };
795                    }
796                    if (before.enabled === false) {
797                        classes.push('disabled');
798                    }
799                    if (before.classes) {
800                        classes = classes.concat(before.classes.split(/\s+/));
801                    }
802                    if (before.tooltip) {
803                        tooltip = before.tooltip;
804                    }
805                }
806                html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + currVal + '</span>';
807            }
808            view.find('.datepicker-switch').text(startVal + '-' + endVal);
809            view.find('td').html(html);
810        },
811        fill: function() {
812            var d = new Date(this.viewDate),
813                year = d.getUTCFullYear(),
814                month = d.getUTCMonth(),
815                startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
816                startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
817                endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
818                endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
819                todaytxt = dates[this.o.language].today || dates['en'].today || '',
820                cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
821                titleFormat = dates[this.o.language].titleFormat || dates['en'].titleFormat,
822                todayDate = UTCToday(),
823                titleBtnVisible = (this.o.todayBtn === true || this.o.todayBtn === 'linked') && todayDate >= this.o.startDate && todayDate <= this.o.endDate && !this.weekOfDateIsDisabled(todayDate),
824                tooltip, before;
825            if (isNaN(year) || isNaN(month))
826                return;
827            this.picker.find('.datepicker-days .datepicker-switch').text(DPGlobal.formatDate(d, titleFormat, this.o.language));
828            this.picker.find('tfoot .today').text(todaytxt).css('display', titleBtnVisible ? 'table-cell' : 'none');
829            this.picker.find('tfoot .clear').text(cleartxt).css('display', this.o.clearBtn === true ? 'table-cell' : 'none');
830            this.picker.find('thead .datepicker-title').text(this.o.title).css('display', typeof this.o.title === 'string' && this.o.title !== '' ? 'table-cell' : 'none');
831            this.updateNavArrows();
832            this.fillMonths();
833            var prevMonth = UTCDate(year, month, 0),
834                day = prevMonth.getUTCDate();
835            prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7) % 7);
836            var nextMonth = new Date(prevMonth);
837            if (prevMonth.getUTCFullYear() < 100) {
838                nextMonth.setUTCFullYear(prevMonth.getUTCFullYear());
839            }
840            nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
841            nextMonth = nextMonth.valueOf();
842            var html = [];
843            var weekDay, clsName;
844            while (prevMonth.valueOf() < nextMonth) {
845                weekDay = prevMonth.getUTCDay();
846                if (weekDay === this.o.weekStart) {
847                    html.push('<tr>');
848                    if (this.o.calendarWeeks) {
849                        var
850                            ws = new Date(+prevMonth + (this.o.weekStart - weekDay - 7) % 7 * 864e5),
851                            th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
852                            yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay()) % 7 * 864e5),
853                            calWeek = (th - yth) / 864e5 / 7 + 1;
854                        html.push('<td class="cw">' + calWeek + '</td>');
855                    }
856                }
857                clsName = this.getClassNames(prevMonth);
858                clsName.push('day');
859                var content = prevMonth.getUTCDate();
860                if (this.o.beforeShowDay !== $.noop) {
861                    before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
862                    if (before === undefined)
863                        before = {};
864                    else if (typeof before === 'boolean')
865                        before = {
866                            enabled: before
867                        };
868                    else if (typeof before === 'string')
869                        before = {
870                            classes: before
871                        };
872                    if (before.enabled === false)
873                        clsName.push('disabled');
874                    if (before.classes)
875                        clsName = clsName.concat(before.classes.split(/\s+/));
876                    if (before.tooltip)
877                        tooltip = before.tooltip;
878                    if (before.content)
879                        content = before.content;
880                }
881                if ($.isFunction($.uniqueSort)) {
882                    clsName = $.uniqueSort(clsName);
883                } else {
884                    clsName = $.unique(clsName);
885                }
886                html.push('<td class="' + clsName.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + ' data-date="' + prevMonth.getTime().toString() + '">' + content + '</td>');
887                tooltip = null;
888                if (weekDay === this.o.weekEnd) {
889                    html.push('</tr>');
890                }
891                prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
892            }
893            this.picker.find('.datepicker-days tbody').html(html.join(''));
894            var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months';
895            var months = this.picker.find('.datepicker-months').find('.datepicker-switch').text(this.o.maxViewMode < 2 ? monthsTitle : year).end().find('tbody span').removeClass('active');
896            $.each(this.dates, function(i, d) {
897                if (d.getUTCFullYear() === year)
898                    months.eq(d.getUTCMonth()).addClass('active');
899            });
900            if (year < startYear || year > endYear) {
901                months.addClass('disabled');
902            }
903            if (year === startYear) {
904                months.slice(0, startMonth).addClass('disabled');
905            }
906            if (year === endYear) {
907                months.slice(endMonth + 1).addClass('disabled');
908            }
909            if (this.o.beforeShowMonth !== $.noop) {
910                var that = this;
911                $.each(months, function(i, month) {
912                    var moDate = new Date(year, i, 1);
913                    var before = that.o.beforeShowMonth(moDate);
914                    if (before === undefined)
915                        before = {};
916                    else if (typeof before === 'boolean')
917                        before = {
918                            enabled: before
919                        };
920                    else if (typeof before === 'string')
921                        before = {
922                            classes: before
923                        };
924                    if (before.enabled === false && !$(month).hasClass('disabled'))
925                        $(month).addClass('disabled');
926                    if (before.classes)
927                        $(month).addClass(before.classes);
928                    if (before.tooltip)
929                        $(month).prop('title', before.tooltip);
930                });
931            }
932            this._fill_yearsView('.datepicker-years', 'year', 10, year, startYear, endYear, this.o.beforeShowYear);
933            this._fill_yearsView('.datepicker-decades', 'decade', 100, year, startYear, endYear, this.o.beforeShowDecade);
934            this._fill_yearsView('.datepicker-centuries', 'century', 1000, year, startYear, endYear, this.o.beforeShowCentury);
935        },
936        updateNavArrows: function() {
937            if (!this._allow_update)
938                return;
939            var d = new Date(this.viewDate),
940                year = d.getUTCFullYear(),
941                month = d.getUTCMonth(),
942                startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
943                startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
944                endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
945                endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
946                prevIsDisabled, nextIsDisabled, factor = 1;
947            switch (this.viewMode) {
948                case 4:
949                    factor *= 10;
950                case 3:
951                    factor *= 10;
952                case 2:
953                    factor *= 10;
954                case 1:
955                    prevIsDisabled = Math.floor(year / factor) * factor <= startYear;
956                    nextIsDisabled = Math.floor(year / factor) * factor + factor > endYear;
957                    break;
958                case 0:
959                    prevIsDisabled = year <= startYear && month <= startMonth;
960                    nextIsDisabled = year >= endYear && month >= endMonth;
961                    break;
962            }
963            this.picker.find('.prev').toggleClass('disabled', prevIsDisabled);
964            this.picker.find('.next').toggleClass('disabled', nextIsDisabled);
965        },
966        click: function(e) {
967            e.preventDefault();
968            e.stopPropagation();
969            var target, dir, day, year, month;
970            target = $(e.target);
971            if (target.hasClass('datepicker-switch') && this.viewMode !== this.o.maxViewMode) {
972                this.setViewMode(this.viewMode + 1);
973            }
974            if (target.hasClass('today') && !target.hasClass('day')) {
975                this.setViewMode(0);
976                this._setDate(UTCToday(), this.o.todayBtn === 'linked' ? null : 'view');
977            }
978            if (target.hasClass('clear')) {
979                this.clearDates();
980            }
981            if (!target.hasClass('disabled')) {
982                if (target.hasClass('month') || target.hasClass('year') || target.hasClass('decade') || target.hasClass('century')) {
983                    this.viewDate.setUTCDate(1);
984                    day = 1;
985                    if (this.viewMode === 1) {
986                        month = target.parent().find('span').index(target);
987                        year = this.viewDate.getUTCFullYear();
988                        this.viewDate.setUTCMonth(month);
989                    } else {
990                        month = 0;
991                        year = Number(target.text());
992                        this.viewDate.setUTCFullYear(year);
993                    }
994                    this._trigger(DPGlobal.viewModes[this.viewMode - 1].e, this.viewDate);
995                    if (this.viewMode === this.o.minViewMode) {
996                        this._setDate(UTCDate(year, month, day));
997                    } else {
998                        this.setViewMode(this.viewMode - 1);
999                        this.fill();
1000                    }
1001                }
1002            }
1003            if (this.picker.is(':visible') && this._focused_from) {
1004                this._focused_from.focus();
1005            }
1006            delete this._focused_from;
1007        },
1008        dayCellClick: function(e) {
1009            var $target = $(e.currentTarget);
1010            var timestamp = $target.data('date');
1011            var date = new Date(timestamp);
1012            if (this.o.updateViewDate) {
1013                if (date.getUTCFullYear() !== this.viewDate.getUTCFullYear()) {
1014                    this._trigger('changeYear', this.viewDate);
1015                }
1016                if (date.getUTCMonth() !== this.viewDate.getUTCMonth()) {
1017                    this._trigger('changeMonth', this.viewDate);
1018                }
1019            }
1020            this._setDate(date);
1021        },
1022        navArrowsClick: function(e) {
1023            var $target = $(e.currentTarget);
1024            var dir = $target.hasClass('prev') ? -1 : 1;
1025            if (this.viewMode !== 0) {
1026                dir *= DPGlobal.viewModes[this.viewMode].navStep * 12;
1027            }
1028            this.viewDate = this.moveMonth(this.viewDate, dir);
1029            this._trigger(DPGlobal.viewModes[this.viewMode].e, this.viewDate);
1030            this.fill();
1031        },
1032        _toggle_multidate: function(date) {
1033            var ix = this.dates.contains(date);
1034            if (!date) {
1035                this.dates.clear();
1036            }
1037            if (ix !== -1) {
1038                if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive) {
1039                    this.dates.remove(ix);
1040                }
1041            } else if (this.o.multidate === false) {
1042                this.dates.clear();
1043                this.dates.push(date);
1044            } else {
1045                this.dates.push(date);
1046            }
1047            if (typeof this.o.multidate === 'number')
1048                while (this.dates.length > this.o.multidate)
1049                    this.dates.remove(0);
1050        },
1051        _setDate: function(date, which) {
1052            if (!which || which === 'date')
1053                this._toggle_multidate(date && new Date(date));
1054            if ((!which && this.o.updateViewDate) || which === 'view')
1055                this.viewDate = date && new Date(date);
1056            this.fill();
1057            this.setValue();
1058            if (!which || which !== 'view') {
1059                this._trigger('changeDate');
1060            }
1061            this.inputField.trigger('change');
1062            if (this.o.autoclose && (!which || which === 'date')) {
1063                this.hide();
1064            }
1065        },
1066        moveDay: function(date, dir) {
1067            var newDate = new Date(date);
1068            newDate.setUTCDate(date.getUTCDate() + dir);
1069            return newDate;
1070        },
1071        moveWeek: function(date, dir) {
1072            return this.moveDay(date, dir * 7);
1073        },
1074        moveMonth: function(date, dir) {
1075            if (!isValidDate(date))
1076                return this.o.defaultViewDate;
1077            if (!dir)
1078                return date;
1079            var new_date = new Date(date.valueOf()),
1080                day = new_date.getUTCDate(),
1081                month = new_date.getUTCMonth(),
1082                mag = Math.abs(dir),
1083                new_month, test;
1084            dir = dir > 0 ? 1 : -1;
1085            if (mag === 1) {
1086                test = dir === -1 ? function() {
1087                    return new_date.getUTCMonth() === month;
1088                } : function() {
1089                    return new_date.getUTCMonth() !== new_month;
1090                };
1091                new_month = month + dir;
1092                new_date.setUTCMonth(new_month);
1093                new_month = (new_month + 12) % 12;
1094            } else {
1095                for (var i = 0; i < mag; i++)
1096                    new_date = this.moveMonth(new_date, dir);
1097                new_month = new_date.getUTCMonth();
1098                new_date.setUTCDate(day);
1099                test = function() {
1100                    return new_month !== new_date.getUTCMonth();
1101                };
1102            }
1103            while (test()) {
1104                new_date.setUTCDate(--day);
1105                new_date.setUTCMonth(new_month);
1106            }
1107            return new_date;
1108        },
1109        moveYear: function(date, dir) {
1110            return this.moveMonth(date, dir * 12);
1111        },
1112        moveAvailableDate: function(date, dir, fn) {
1113            do {
1114                date = this[fn](date, dir);
1115                if (!this.dateWithinRange(date))
1116                    return false;
1117                fn = 'moveDay';
1118            }
1119            while (this.dateIsDisabled(date));
1120            return date;
1121        },
1122        weekOfDateIsDisabled: function(date) {
1123            return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1;
1124        },
1125        dateIsDisabled: function(date) {
1126            return (this.weekOfDateIsDisabled(date) || $.grep(this.o.datesDisabled, function(d) {
1127                return isUTCEquals(date, d);
1128            }).length > 0);
1129        },
1130        dateWithinRange: function(date) {
1131            return date >= this.o.startDate && date <= this.o.endDate;
1132        },
1133        keydown: function(e) {
1134            if (!this.picker.is(':visible')) {
1135                if (e.keyCode === 40 || e.keyCode === 27) {
1136                    this.show();
1137                    e.stopPropagation();
1138                }
1139                return;
1140            }
1141            var dateChanged = false,
1142                dir, newViewDate, focusDate = this.focusDate || this.viewDate;
1143            switch (e.keyCode) {
1144                case 27:
1145                    if (this.focusDate) {
1146                        this.focusDate = null;
1147                        this.viewDate = this.dates.get(-1) || this.viewDate;
1148                        this.fill();
1149                    } else
1150                        this.hide();
1151                    e.preventDefault();
1152                    e.stopPropagation();
1153                    break;
1154                case 37:
1155                case 38:
1156                case 39:
1157                case 40:
1158                    if (!this.o.keyboardNavigation || this.o.daysOfWeekDisabled.length === 7)
1159                        break;
1160                    dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1;
1161                    if (this.viewMode === 0) {
1162                        if (e.ctrlKey) {
1163                            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
1164                            if (newViewDate)
1165                                this._trigger('changeYear', this.viewDate);
1166                        } else if (e.shiftKey) {
1167                            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
1168                            if (newViewDate)
1169                                this._trigger('changeMonth', this.viewDate);
1170                        } else if (e.keyCode === 37 || e.keyCode === 39) {
1171                            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay');
1172                        } else if (!this.weekOfDateIsDisabled(focusDate)) {
1173                            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek');
1174                        }
1175                    } else if (this.viewMode === 1) {
1176                        if (e.keyCode === 38 || e.keyCode === 40) {
1177                            dir = dir * 4;
1178                        }
1179                        newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
1180                    } else if (this.viewMode === 2) {
1181                        if (e.keyCode === 38 || e.keyCode === 40) {
1182                            dir = dir * 4;
1183                        }
1184                        newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
1185                    }
1186                    if (newViewDate) {
1187                        this.focusDate = this.viewDate = newViewDate;
1188                        this.setValue();
1189                        this.fill();
1190                        e.preventDefault();
1191                    }
1192                    break;
1193                case 13:
1194                    if (!this.o.forceParse)
1195                        break;
1196                    focusDate = this.focusDate || this.dates.get(-1) || this.viewDate;
1197                    if (this.o.keyboardNavigation) {
1198                        this._toggle_multidate(focusDate);
1199                        dateChanged = true;
1200                    }
1201                    this.focusDate = null;
1202                    this.viewDate = this.dates.get(-1) || this.viewDate;
1203                    this.setValue();
1204                    this.fill();
1205                    if (this.picker.is(':visible')) {
1206                        e.preventDefault();
1207                        e.stopPropagation();
1208                        if (this.o.autoclose)
1209                            this.hide();
1210                    }
1211                    break;
1212                case 9:
1213                    this.focusDate = null;
1214                    this.viewDate = this.dates.get(-1) || this.viewDate;
1215                    this.fill();
1216                    this.hide();
1217                    break;
1218            }
1219            if (dateChanged) {
1220                if (this.dates.length)
1221                    this._trigger('changeDate');
1222                else
1223                    this._trigger('clearDate');
1224                this.inputField.trigger('change');
1225            }
1226        },
1227        setViewMode: function(viewMode) {
1228            this.viewMode = viewMode;
1229            this.picker.children('div').hide().filter('.datepicker-' + DPGlobal.viewModes[this.viewMode].clsName).show();
1230            this.updateNavArrows();
1231            this._trigger('changeViewMode', new Date(this.viewDate));
1232        }
1233    };
1234    var DateRangePicker = function(element, options) {
1235        $.data(element, 'datepicker', this);
1236        this.element = $(element);
1237        this.inputs = $.map(options.inputs, function(i) {
1238            return i.jquery ? i[0] : i;
1239        });
1240        delete options.inputs;
1241        this.keepEmptyValues = options.keepEmptyValues;
1242        delete options.keepEmptyValues;
1243        datepickerPlugin.call($(this.inputs), options).on('changeDate', $.proxy(this.dateUpdated, this));
1244        this.pickers = $.map(this.inputs, function(i) {
1245            return $.data(i, 'datepicker');
1246        });
1247        this.updateDates();
1248    };
1249    DateRangePicker.prototype = {
1250        updateDates: function() {
1251            this.dates = $.map(this.pickers, function(i) {
1252                return i.getUTCDate();
1253            });
1254            this.updateRanges();
1255        },
1256        updateRanges: function() {
1257            var range = $.map(this.dates, function(d) {
1258                return d.valueOf();
1259            });
1260            $.each(this.pickers, function(i, p) {
1261                p.setRange(range);
1262            });
1263        },
1264        clearDates: function() {
1265            $.each(this.pickers, function(i, p) {
1266                p.clearDates();
1267            });
1268        },
1269        dateUpdated: function(e) {
1270            if (this.updating)
1271                return;
1272            this.updating = true;
1273            var dp = $.data(e.target, 'datepicker');
1274            if (dp === undefined) {
1275                return;
1276            }
1277            var new_date = dp.getUTCDate(),
1278                keep_empty_values = this.keepEmptyValues,
1279                i = $.inArray(e.target, this.inputs),
1280                j = i - 1,
1281                k = i + 1,
1282                l = this.inputs.length;
1283            if (i === -1)
1284                return;
1285            $.each(this.pickers, function(i, p) {
1286                if (!p.getUTCDate() && (p === dp || !keep_empty_values))
1287                    p.setUTCDate(new_date);
1288            });
1289            if (new_date < this.dates[j]) {
1290                while (j >= 0 && new_date < this.dates[j]) {
1291                    this.pickers[j--].setUTCDate(new_date);
1292                }
1293            } else if (new_date > this.dates[k]) {
1294                while (k < l && new_date > this.dates[k]) {
1295                    this.pickers[k++].setUTCDate(new_date);
1296                }
1297            }
1298            this.updateDates();
1299            delete this.updating;
1300        },
1301        destroy: function() {
1302            $.map(this.pickers, function(p) {
1303                p.destroy();
1304            });
1305            $(this.inputs).off('changeDate', this.dateUpdated);
1306            delete this.element.data().datepicker;
1307        },
1308        remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead')
1309    };
1310
1311    function opts_from_el(el, prefix) {
1312        var data = $(el).data(),
1313            out = {},
1314            inkey, replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])');
1315        prefix = new RegExp('^' + prefix.toLowerCase());
1316
1317        function re_lower(_, a) {
1318            return a.toLowerCase();
1319        }
1320        for (var key in data)
1321            if (prefix.test(key)) {
1322                inkey = key.replace(replace, re_lower);
1323                out[inkey] = data[key];
1324            }
1325        return out;
1326    }
1327
1328    function opts_from_locale(lang) {
1329        var out = {};
1330        if (!dates[lang]) {
1331            lang = lang.split('-')[0];
1332            if (!dates[lang])
1333                return;
1334        }
1335        var d = dates[lang];
1336        $.each(locale_opts, function(i, k) {
1337            if (k in d)
1338                out[k] = d[k];
1339        });
1340        return out;
1341    }
1342    var old = $.fn.datepicker;
1343    var datepickerPlugin = function(option) {
1344        var args = Array.apply(null, arguments);
1345        args.shift();
1346        var internal_return;
1347        this.each(function() {
1348            var $this = $(this),
1349                data = $this.data('datepicker'),
1350                options = typeof option === 'object' && option;
1351            if (!data) {
1352                var elopts = opts_from_el(this, 'date'),
1353                    xopts = $.extend({}, defaults, elopts, options),
1354                    locopts = opts_from_locale(xopts.language),
1355                    opts = $.extend({}, defaults, locopts, elopts, options);
1356                if ($this.hasClass('input-daterange') || opts.inputs) {
1357                    $.extend(opts, {
1358                        inputs: opts.inputs || $this.find('input').toArray()
1359                    });
1360                    data = new DateRangePicker(this, opts);
1361                } else {
1362                    data = new Datepicker(this, opts);
1363                }
1364                $this.data('datepicker', data);
1365            }
1366            if (typeof option === 'string' && typeof data[option] === 'function') {
1367                internal_return = data[option].apply(data, args);
1368            }
1369        });
1370        if (internal_return === undefined || internal_return instanceof Datepicker || internal_return instanceof DateRangePicker)
1371            return this;
1372        if (this.length > 1)
1373            throw new Error('Using only allowed for the collection of a single element (' + option + ' function)');
1374        else
1375            return internal_return;
1376    };
1377    $.fn.datepicker = datepickerPlugin;
1378    var defaults = $.fn.datepicker.defaults = {
1379        assumeNearbyYear: false,
1380        autoclose: false,
1381        beforeShowDay: $.noop,
1382        beforeShowMonth: $.noop,
1383        beforeShowYear: $.noop,
1384        beforeShowDecade: $.noop,
1385        beforeShowCentury: $.noop,
1386        calendarWeeks: false,
1387        clearBtn: false,
1388        toggleActive: false,
1389        daysOfWeekDisabled: [],
1390        daysOfWeekHighlighted: [],
1391        datesDisabled: [],
1392        endDate: Infinity,
1393        forceParse: true,
1394        format: 'mm/dd/yyyy',
1395        keepEmptyValues: false,
1396        keyboardNavigation: true,
1397        language: 'en',
1398        minViewMode: 0,
1399        maxViewMode: 4,
1400        multidate: false,
1401        multidateSeparator: ',',
1402        orientation: "auto",
1403        rtl: false,
1404        startDate: -Infinity,
1405        startView: 0,
1406        todayBtn: false,
1407        todayHighlight: false,
1408        updateViewDate: true,
1409        weekStart: 0,
1410        disableTouchKeyboard: false,
1411        enableOnReadonly: true,
1412        showOnFocus: true,
1413        zIndexOffset: 10,
1414        container: 'body',
1415        immediateUpdates: false,
1416        title: '',
1417        templates: {
1418            leftArrow: '&#x00AB;',
1419            rightArrow: '&#x00BB;'
1420        },
1421        showWeekDays: true
1422    };
1423    var locale_opts = $.fn.datepicker.locale_opts = ['format', 'rtl', 'weekStart'];
1424    $.fn.datepicker.Constructor = Datepicker;
1425    var dates = $.fn.datepicker.dates = {
1426        en: {
1427            days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
1428            daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
1429            daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
1430            months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
1431            monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
1432            today: "Today",
1433            clear: "Clear",
1434            titleFormat: "MM yyyy"
1435        }
1436    };
1437    var DPGlobal = {
1438        viewModes: [{
1439            names: ['days', 'month'],
1440            clsName: 'days',
1441            e: 'changeMonth'
1442        }, {
1443            names: ['months', 'year'],
1444            clsName: 'months',
1445            e: 'changeYear',
1446            navStep: 1
1447        }, {
1448            names: ['years', 'decade'],
1449            clsName: 'years',
1450            e: 'changeDecade',
1451            navStep: 10
1452        }, {
1453            names: ['decades', 'century'],
1454            clsName: 'decades',
1455            e: 'changeCentury',
1456            navStep: 100
1457        }, {
1458            names: ['centuries', 'millennium'],
1459            clsName: 'centuries',
1460            e: 'changeMillennium',
1461            navStep: 1000
1462        }],
1463        validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
1464        nonpunctuation: /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,
1465        parseFormat: function(format) {
1466            if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function')
1467                return format;
1468            var separators = format.replace(this.validParts, '\0').split('\0'),
1469                parts = format.match(this.validParts);
1470            if (!separators || !separators.length || !parts || parts.length === 0) {
1471                throw new Error("Invalid date format.");
1472            }
1473            return {
1474                separators: separators,
1475                parts: parts
1476            };
1477        },
1478        parseDate: function(date, format, language, assumeNearby) {
1479            if (!date)
1480                return undefined;
1481            if (date instanceof Date)
1482                return date;
1483            if (typeof format === 'string')
1484                format = DPGlobal.parseFormat(format);
1485            if (format.toValue)
1486                return format.toValue(date, format, language);
1487            var fn_map = {
1488                    d: 'moveDay',
1489                    m: 'moveMonth',
1490                    w: 'moveWeek',
1491                    y: 'moveYear'
1492                },
1493                dateAliases = {
1494                    yesterday: '-1d',
1495                    today: '+0d',
1496                    tomorrow: '+1d'
1497                },
1498                parts, part, dir, i, fn;
1499            if (date in dateAliases) {
1500                date = dateAliases[date];
1501            }
1502            if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(date)) {
1503                parts = date.match(/([\-+]\d+)([dmwy])/gi);
1504                date = new Date();
1505                for (i = 0; i < parts.length; i++) {
1506                    part = parts[i].match(/([\-+]\d+)([dmwy])/i);
1507                    dir = Number(part[1]);
1508                    fn = fn_map[part[2].toLowerCase()];
1509                    date = Datepicker.prototype[fn](date, dir);
1510                }
1511                return Datepicker.prototype._zero_utc_time(date);
1512            }
1513            parts = date && date.match(this.nonpunctuation) || [];
1514
1515            function applyNearbyYear(year, threshold) {
1516                if (threshold === true)
1517                    threshold = 10;
1518                if (year < 100) {
1519                    year += 2000;
1520                    if (year > ((new Date()).getFullYear() + threshold)) {
1521                        year -= 100;
1522                    }
1523                }
1524                return year;
1525            }
1526            var parsed = {},
1527                setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
1528                setters_map = {
1529                    yyyy: function(d, v) {
1530                        return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
1531                    },
1532                    m: function(d, v) {
1533                        if (isNaN(d))
1534                            return d;
1535                        v -= 1;
1536                        while (v < 0) v += 12;
1537                        v %= 12;
1538                        d.setUTCMonth(v);
1539                        while (d.getUTCMonth() !== v)
1540                            d.setUTCDate(d.getUTCDate() - 1);
1541                        return d;
1542                    },
1543                    d: function(d, v) {
1544                        return d.setUTCDate(v);
1545                    }
1546                },
1547                val, filtered;
1548            setters_map['yy'] = setters_map['yyyy'];
1549            setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1550            setters_map['dd'] = setters_map['d'];
1551            date = UTCToday();
1552            var fparts = format.parts.slice();
1553            if (parts.length !== fparts.length) {
1554                fparts = $(fparts).filter(function(i, p) {
1555                    return $.inArray(p, setters_order) !== -1;
1556                }).toArray();
1557            }
1558
1559            function match_part() {
1560                var m = this.slice(0, parts[i].length),
1561                    p = parts[i].slice(0, m.length);
1562                return m.toLowerCase() === p.toLowerCase();
1563            }
1564            if (parts.length === fparts.length) {
1565                var cnt;
1566                for (i = 0, cnt = fparts.length; i < cnt; i++) {
1567                    val = parseInt(parts[i], 10);
1568                    part = fparts[i];
1569                    if (isNaN(val)) {
1570                        switch (part) {
1571                            case 'MM':
1572                                filtered = $(dates[language].months).filter(match_part);
1573                                val = $.inArray(filtered[0], dates[language].months) + 1;
1574                                break;
1575                            case 'M':
1576                                filtered = $(dates[language].monthsShort).filter(match_part);
1577                                val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1578                                break;
1579                        }
1580                    }
1581                    parsed[part] = val;
1582                }
1583                var _date, s;
1584                for (i = 0; i < setters_order.length; i++) {
1585                    s = setters_order[i];
1586                    if (s in parsed && !isNaN(parsed[s])) {
1587                        _date = new Date(date);
1588                        setters_map[s](_date, parsed[s]);
1589                        if (!isNaN(_date))
1590                            date = _date;
1591                    }
1592                }
1593            }
1594            return date;
1595        },
1596        formatDate: function(date, format, language) {
1597            if (!date)
1598                return '';
1599            if (typeof format === 'string')
1600                format = DPGlobal.parseFormat(format);
1601            if (format.toDisplay)
1602                return format.toDisplay(date, format, language);
1603            var val = {
1604                d: date.getUTCDate(),
1605                D: dates[language].daysShort[date.getUTCDay()],
1606                DD: dates[language].days[date.getUTCDay()],
1607                m: date.getUTCMonth() + 1,
1608                M: dates[language].monthsShort[date.getUTCMonth()],
1609                MM: dates[language].months[date.getUTCMonth()],
1610                yy: date.getUTCFullYear().toString().substring(2),
1611                yyyy: date.getUTCFullYear()
1612            };
1613            val.dd = (val.d < 10 ? '0' : '') + val.d;
1614            val.mm = (val.m < 10 ? '0' : '') + val.m;
1615            date = [];
1616            var seps = $.extend([], format.separators);
1617            for (var i = 0, cnt = format.parts.length; i <= cnt; i++) {
1618                if (seps.length)
1619                    date.push(seps.shift());
1620                date.push(val[format.parts[i]]);
1621            }
1622            return date.join('');
1623        },
1624        headTemplate: '<thead>' +
1625            '<tr>' +
1626            '<th colspan="7" class="datepicker-title"></th>' +
1627            '</tr>' +
1628            '<tr>' +
1629            '<th class="prev">' + defaults.templates.leftArrow + '</th>' +
1630            '<th colspan="5" class="datepicker-switch"></th>' +
1631            '<th class="next">' + defaults.templates.rightArrow + '</th>' +
1632            '</tr>' +
1633            '</thead>',
1634        contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
1635        footTemplate: '<tfoot>' +
1636            '<tr>' +
1637            '<th colspan="7" class="today"></th>' +
1638            '</tr>' +
1639            '<tr>' +
1640            '<th colspan="7" class="clear"></th>' +
1641            '</tr>' +
1642            '</tfoot>'
1643    };
1644    DPGlobal.template = '<div class="datepicker">' +
1645        '<div class="datepicker-days">' +
1646        '<table class="table-condensed">' +
1647        DPGlobal.headTemplate +
1648        '<tbody></tbody>' +
1649        DPGlobal.footTemplate +
1650        '</table>' +
1651        '</div>' +
1652        '<div class="datepicker-months">' +
1653        '<table class="table-condensed">' +
1654        DPGlobal.headTemplate +
1655        DPGlobal.contTemplate +
1656        DPGlobal.footTemplate +
1657        '</table>' +
1658        '</div>' +
1659        '<div class="datepicker-years">' +
1660        '<table class="table-condensed">' +
1661        DPGlobal.headTemplate +
1662        DPGlobal.contTemplate +
1663        DPGlobal.footTemplate +
1664        '</table>' +
1665        '</div>' +
1666        '<div class="datepicker-decades">' +
1667        '<table class="table-condensed">' +
1668        DPGlobal.headTemplate +
1669        DPGlobal.contTemplate +
1670        DPGlobal.footTemplate +
1671        '</table>' +
1672        '</div>' +
1673        '<div class="datepicker-centuries">' +
1674        '<table class="table-condensed">' +
1675        DPGlobal.headTemplate +
1676        DPGlobal.contTemplate +
1677        DPGlobal.footTemplate +
1678        '</table>' +
1679        '</div>' +
1680        '</div>';
1681    $.fn.datepicker.DPGlobal = DPGlobal;
1682    $.fn.datepicker.noConflict = function() {
1683        $.fn.datepicker = old;
1684        return this;
1685    };
1686    $.fn.datepicker.version = '1.9.0';
1687    $.fn.datepicker.deprecated = function(msg) {
1688        var console = window.console;
1689        if (console && console.warn) {
1690            console.warn('DEPRECATED: ' + msg);
1691        }
1692    };
1693    $(document).on('focus.datepicker.data-api click.datepicker.data-api', '[data-
1693provide="datepicker"]', function(e) {
1694        var $this = $(this);
1695        if ($this.data('datepicker'))
1696            return;
1697        e.preventDefault();
1698        datepickerPlugin.call($this, 'show');
1699    });
1700    $(function() {
1701        datepickerPlugin.call($('[data-provide="datepicker-inline"]'));
1702    });
1703}));

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.