PageSourceSearch

https://www.myintervent.com/Scripts/foundation-datepicker.js?v=12359

js myintervent.com collected 2026-09-24 13:39:34 UTC 59,283 bytes, 1,345 lines download raw bytes

1/* =========================================================
2 * foundation-datepicker.js
3 * Copyright 2015 Peter Beno, [email protected], @benopeter
4 * project website http://foundation-datepicker.peterbeno.com
5 * ========================================================= */
6! function ($) {
7
8    function UTCDate() {
9        return new Date(Date.UTC.apply(Date, arguments));
10    }
11
12    function UTCToday() {
13        var today = new Date();
14        return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
15    }
16
17    var Datepicker = function (element, options) {
18        var that = this;
19
20        this.element = $(element);
21        this.autoShow = options.autoShow || true;
22        this.appendTo = options.appendTo || 'body';
23        this.closeButton = options.closeButton;
24        this.language = options.language || this.element.data('date-language') || "en";
25        this.language = this.language in dates ? this.language : this.language.split('-')[0]; //Check if "de-DE" style date is available, if not language should fallback to 2 letter code eg "de"
26        this.language = this.language in dates ? this.language : "en";
27        this.isRTL = dates[this.language].rtl || false;
28        this.format = DPGlobal.parseFormat(options.format || this.element.data('date-format') || dates[this.language].format || 'mm/dd/yyyy');
29        this.isInline = false;
30        this.isInput = this.element.is('input');
31        this.component = this.element.is('.date') ? this.element.find('.prefix, .postfix') : false;
32        this.hasInput = this.component && this.element.find('input').length;
33        this.disableDblClickSelection = options.disableDblClickSelection;
34        this.onRender = options.onRender || function () { };
35        if (this.component && this.component.length === 0) {
36            this.component = false;
37        }
38        this.linkField = options.linkField || this.element.data('link-field') || false;
39        this.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || 'yyyy-mm-dd hh:ii:ss');
40        this.minuteStep = options.minuteStep || this.element.data('minute-step') || 5;
41        this.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'bottom-right';
42
43        this._attachEvents();
44
45
46        this.minView = 0;
47        if ('minView' in options) {
48            this.minView = options.minView;
49        } else if ('minView' in this.element.data()) {
50            this.minView = this.element.data('min-view');
51        }
52        this.minView = DPGlobal.convertViewMode(this.minView);
53
54        this.maxView = DPGlobal.modes.length - 1;
55        if ('maxView' in options) {
56            this.maxView = options.maxView;
57        } else if ('maxView' in this.element.data()) {
58            this.maxView = this.element.data('max-view');
59        }
60        this.maxView = DPGlobal.convertViewMode(this.maxView);
61
62        this.startViewMode = 'month';
63        if ('startView' in options) {
64            this.startViewMode = options.startView;
65        } else if ('startView' in this.element.data()) {
66            this.startViewMode = this.element.data('start-view');
67        }
68        this.startViewMode = DPGlobal.convertViewMode(this.startViewMode);
69        this.viewMode = this.startViewMode;
70
71        if (!('minView' in options) && !('maxView' in options) && !(this.element.data('min-view') && !(this.element.data('max-view')))) {
72            this.pickTime = false;
73            if ('pickTime' in options) {
74                this.pickTime = options.pickTime;
75            }
76            if (this.pickTime == true) {
77                this.minView = 0;
78                this.maxView = 4;
79            } else {
80                this.minView = 2;
81                this.maxView = 4;
82            }
83        }
84
85        this.forceParse = true;
86        if ('forceParse' in options) {
87            this.forceParse = options.forceParse;
88        } else if ('dateForceParse' in this.element.data()) {
89            this.forceParse = this.element.data('date-force-parse');
90        }
91
92
93        this.picker = $(DPGlobal.template)
94            .appendTo(this.isInline ? this.element : this.appendTo)
95            .on({
96                click: $.proxy(this.click, this),
97                mousedown: $.proxy(this.mousedown, this)
98            });
99        if (this.closeButton) {
100            this.picker.find('a.datepicker-close').show();
101        } else {
102            this.picker.find('a.datepicker-close').hide();
103        }
104
105        if (this.isInline) {
106            this.picker.addClass('datepicker-inline');
107        } else {
108            this.picker.addClass('datepicker-dropdown dropdown-menu');
109        }
110        if (this.isRTL) {
111            this.picker.addClass('datepicker-rtl');
112            this.picker.find('.prev i, .next i')
113                .toggleClass('fa fa-chevron-left fa-chevron-right').toggleClass('fa-chevron-left fa-chevron-right');
114        }
115        $(document).on('mousedown', function (e) {
116            // Clicked outside the datepicker, hide it
117            if ($(e.target).closest('.datepicker.datepicker-inline, .datepicker.datepicker-dropdown').length === 0) {
118                that.hide();
119            }
120        });
121
122        this.autoclose = true;
123        if ('autoclose' in options) {
124            this.autoclose = options.autoclose;
125        } else if ('dateAutoclose' in this.element.data()) {
126            this.autoclose = this.element.data('date-autoclose');
127        }
128
129        this.keyboardNavigation = true;
130        if ('keyboardNavigation' in options) {
131            this.keyboardNavigation = options.keyboardNavigation;
132        } else if ('dateKeyboardNavigation' in this.element.data()) {
133            this.keyboardNavigation = this.element.data('date-keyboard-navigation');
134        }
135
136        this.todayBtn = (options.todayBtn || this.element.data('date-today-btn') || false);
137        this.todayHighlight = (options.todayHighlight || this.element.data('date-today-highlight') || false);
138
139        this.calendarWeeks = false;
140        if ('calendarWeeks' in options) {
141            this.calendarWeeks = options.calendarWeeks;
142        } else if ('dateCalendarWeeks' in this.element.data()) {
143            this.calendarWeeks = this.element.data('date-calendar-weeks');
144        }
145        if (this.calendarWeeks)
146            this.picker.find('tfoot th.today')
147            .attr('colspan', function (i, val) {
148                return parseInt(val) + 1;
149            });
150
151        this.weekStart = ((options.weekStart || this.element.data('date-weekstart') || dates[this.language].weekStart || 0) % 7);
152        this.weekEnd = ((this.weekStart + 6) % 7);
153        this.startDate = -Infinity;
154        this.endDate = Infinity;
155        this.daysOfWeekDisabled = [];
156        this.setStartDate(options.startDate || this.element.data('date-startdate'));
157        this.setEndDate(options.endDate || this.element.data('date-enddate'));
158        this.setDaysOfWeekDisabled(options.daysOfWeekDisabled || this.element.data('date-days-of-week-disabled'));
159
160        this.fillDow();
161        this.fillMonths();
162        this.update();
163
164        this.showMode();
165
166        if (this.isInline) {
167            this.show();
168        }
169    };
170
171    Datepicker.prototype = {
172        constructor: Datepicker,
173
174        _events: [],
175        _attachEvents: function () {
176            this._detachEvents();
177            if (this.isInput) { // single input
178                this._events = [
179                    [this.element, {
180                        focus: (this.autoShow) ? $.proxy(this.show, this) : function () { },
181                        keyup: $.proxy(this.update, this),
182                        keydown: $.proxy(this.keydown, this)
183                    }]
184                ];
185            } else if (this.component && this.hasInput) { // component: input + button
186                this._events = [
187                    // For components that are not readonly, allow keyboard nav
188                    [this.element.find('input'), {
189                        focus: (this.autoShow) ? $.proxy(this.show, this) : function () { },
190                        keyup: $.proxy(this.update, this),
191                        keydown: $.proxy(this.keydown, this)
192                    }],
193                    [this.component, {
194                        click: $.proxy(this.show, this)
195                    }]
196                ];
197            } else if (this.element.is('div')) { // inline datepicker
198                this.isInline = true;
199            } else {
200                this._events = [
201                    [this.element, {
202                        click: $.proxy(this.show, this)
203                    }]
204                ];
205            }
206
207            if (this.disableDblClickSelection) {
208                this._events[this._events.length] = [
209                    this.element, {
210                        dblclick: function (e) {
211                            e.preventDefault();
212                            e.stopPropagation();
213                            $(this).blur()
214                        }
215                    }
216                ];
217            }
218
219            for (var i = 0, el, ev; i < this._events.length; i++) {
220                el = this._events[i][0];
221                ev = this._events[i][1];
222                el.on(ev);
223            }
224        },
225        _detachEvents: function () {
226            for (var i = 0, el, ev; i < this._events.length; i++) {
227                el = this._events[i][0];
228                ev = this._events[i][1];
229                el.off(ev);
230            }
231            this._events = [];
232        },
233
234        show: function (e) {
235            this.picker.show();
236            this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
237            this.update();
238            this.place();
239            $(window).on('resize', $.proxy(this.place, this));
240            if (e) {
241                e.stopPropagation();
242                e.preventDefault();
243            }
244            this.element.trigger({
245                type: 'show',
246                date: this.date
247            });
248        },
249
250        hide: function (e) {
251            if (this.isInline) return;
252            if (!this.picker.is(':visible')) return;
253            this.picker.hide();
254            $(window).off('resize', this.place);
255            this.viewMode = this.startViewMode;
256            this.showMode();
257            if (!this.isInput) {
258                $(document).off('mousedown', this.hide);
259            }
260
261            if (
262                this.forceParse &&
263                (
264                    this.isInput && this.element.val() ||
265                    this.hasInput && this.element.find('input').val()
266                )
267            )
268                this.setValue();
269            this.element.trigger({
270                type: 'hide',
271                date: this.date
272            });
273        },
274
275        remove: function () {
276            this._detachEvents();
277            this.picker.remove();
278            delete this.element.data().datepicker;
279        },
280
281        getDate: function () {
282            var d = this.getUTCDate();
283            return new Date(d.getTime() + (d.getTimezoneOffset() * 60000));
284        },
285
286        getUTCDate: function () {
287            return this.date;
288        },
289
290        setDate: function (d) {
291            this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset() * 60000)));
292        },
293
294        setUTCDate: function (d) {
295            this.date = d;
296            this.setValue();
297        },
298
299        setValue: function () {
300            var formatted = this.getFormattedDate();
301            if (!this.isInput) {
302                if (this.component) {
303                    this.element.find('input').val(formatted);
304                }
305                this.element.data('date', formatted);
306            } else {
307                this.element.val(formatted);
308            }
309        },
310
311        getFormattedDate: function (format) {
312            if (format === undefined)
313                format = this.format;
314            return DPGlobal.formatDate(this.date, format, this.language);
315        },
316
317        setStartDate: function (startDate) {
318            this.startDate = startDate || -Infinity;
319            if (this.startDate !== -Infinity) {
320                this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language);
321            }
322            this.update();
323            this.updateNavArrows();
324        },
325
326        setEndDate: function (endDate) {
327            this.endDate = endDate || Infinity;
328            if (this.endDate !== Infinity) {
329                this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language);
330            }
331            this.update();
332            this.updateNavArrows();
333        },
334
335        setDaysOfWeekDisabled: function (daysOfWeekDisabled) {
336            this.daysOfWeekDisabled = daysOfWeekDisabled || [];
337            if (!$.isArray(this.daysOfWeekDisabled)) {
338                this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/);
339            }
340            this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) {
341                return parseInt(d, 10);
342            });
343            this.update();
344            this.updateNavArrows();
345        },
346
347        place: function () {
348            if (this.isInline) return;
349            var zIndex = parseInt(this.element.parents().filter(function () {
350                return $(this).css('z-index') != 'auto';
351            }).first().css('z-index')) + 10;
352            var textbox = this.component ? this.component : this.element;
353            var offset = textbox.offset();
354            var height = textbox.outerHeight() + parseInt(textbox.css('margin-top'));
355            var width = textbox.outerWidth() + parseInt(textbox.css('margin-left'));
356            var fullOffsetTop = offset.top + height;
357            var offsetLeft = offset.left;
358            // if the datepicker is going to be below the window, show it on top of the input
359            if ((fullOffsetTop + this.picker.outerHeight()) >= $(window).scrollTop() + $(window).height()) {
360                fullOffsetTop = offset.top - this.picker.outerHeight();
361            }
362
363            // if the datepicker is going to go past the right side of the window, we want
364            // to set the right position so the datepicker lines up with the textbox
365            if (offset.left + this.picker.width() >= $(window).width()) {
366                offsetLeft = (offset.left + width) - this.picker.width();
367            }
368            this.picker.css({
369                top: fullOffsetTop,
370                left: offsetLeft,
371                zIndex: zIndex
372            });
373        },
374
375        update: function () {
376            var date, fromArgs = false;
377            if (arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {
378                date = arguments[0];
379                fromArgs = true;
380            } else {
381                date = this.isInput ? this.element.val() : this.element.data('date') || this.element.find('input').val();
382            }
383
384            this.date = DPGlobal.parseDate(date, this.format, this.language);
385
386            if (fromArgs) this.setValue();
387
388            if (this.date < this.startDate) {
389                this.viewDate = new Date(this.startDate.valueOf());
390            } else if (this.date > this.endDate) {
391                this.viewDate = new Date(this.endDate.valueOf());
392            } else {
393                this.viewDate = new Date(this.date.valueOf());
394            }
395            this.fill();
396        },
397
398        fillDow: function () {
399            var dowCnt = this.weekStart,
400                html = '<tr>';
401            if (this.calendarWeeks) {
402                var cell = '<th class="cw">&nbsp;</th>';
403                html += cell;
404                this.picker.find('.datepicker-days thead tr:first-child').prepend(cell);
405            }
406            while (dowCnt < this.weekStart + 7) {
407                html += '<th class="dow">' + dates[this.language].daysMin[(dowCnt++) % 7] + '</th>';
408            }
409            html += '</tr>';
410            this.picker.find('.datepicker-days thead').append(html);
411        },
412
413        fillMonths: function () {
414            var html = '',
415                i = 0;
416            while (i < 12) {
417                html += '<span class="month">' + dates[this.language].monthsShort[i++] + '</span>';
418            }
419            this.picker.find('.datepicker-months td').html(html);
420        },
421
422        fill: function () {
423            if (this.date == null || this.viewDate == null) {
424                return;
425            }
426
427            var d = new Date(this.viewDate.valueOf()),
428                year = d.getUTCFullYear(),
429                month = d.getUTCMonth(),
430                dayMonth = d.getUTCDate(),
431                hours = d.getUTCHours(),
432                minutes = d.getUTCMinutes(),
433                startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
434                startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
435                endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
436                endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
437                currentDate = this.date && this.date.valueOf(),
438                today = new Date(),
439                titleFormat = dates[this.language].titleFormat || dates['en'].titleFormat;
440            // this.picker.find('.datepicker-days thead th.date-switch')
441            // 			.text(DPGlobal.formatDate(new UTCDate(year, month), titleFormat, this.language));
442
443            this.picker.find('.datepicker-days thead th:eq(1)')
444                .text(dates[this.language].months[month] + ' ' + year);
445            this.picker.find('.datepicker-hours thead th:eq(1)')
446                .text(dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
447            this.picker.find('.datepicker-minutes thead th:eq(1)')
448                .text(dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);
449
450
451            this.picker.find('tfoot th.today')
452                .text(dates[this.language].today)
453                .toggle(this.todayBtn !== false);
454            this.updateNavArrows();
455            this.fillMonths();
456            var prevMonth = UTCDate(year, month - 1, 28, 0, 0, 0, 0),
457                day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
458            prevMonth.setUTCDate(day);
459            prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7) % 7);
460            var nextMonth = new Date(prevMonth.valueOf());
461            nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
462            nextMonth = nextMonth.valueOf();
463            var html = [];
464            var clsName;
465            while (prevMonth.valueOf() < nextMonth) {
466                if (prevMonth.getUTCDay() == this.weekStart) {
467                    html.push('<tr>');
468                    if (this.calendarWeeks) {
469                        // adapted from https://github.com/timrwood/moment/blob/master/moment.js#L128
470                        var a = new Date(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth(), prevMonth.getUTCDate() - prevMonth.getDay() + 10 - (this.weekStart && this.weekStart % 7 < 5 && 7)),
471                            b = new Date(a.getFullYear(), 0, 4),
472                            calWeek = ~~((a - b) / 864e5 / 7 + 1.5);
473                        html.push('<td class="cw">' + calWeek + '</td>');
474                    }
475                }
476                clsName = ' ' + this.onRender(prevMonth) + ' ';
477                if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
478                    clsName += ' old';
479                } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {
480                    clsName += ' new';
481                }
482                // Compare internal UTC date with local today, not UTC today
483                if (this.todayHighlight &&
484                    prevMonth.getUTCFullYear() == today.getFullYear() &&
485                    prevMonth.getUTCMonth() == today.getMonth() &&
486                    prevMonth.getUTCDate() == today.getDate()) {
487                    clsName += ' today';
488                }
489                if (currentDate && prevMonth.valueOf() == currentDate) {
490                    clsName += ' active';
491                }
492                if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate ||
493                    $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1) {
494                    clsName += ' disabled';
495                }
496                html.push('<td class="day' + clsName + '">' + prevMonth.getUTCDate() + '</td>');
497                if (prevMonth.getUTCDay() == this.weekEnd) {
498                    html.push('</tr>');
499                }
500                prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
501            }
502            this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
503
504            html = [];
505            for (var i = 0; i < 24; i++) {
506                var actual = UTCDate(year, month, dayMonth, i);
507                clsName = '';
508                // We want the previous hour for the startDate
509                if ((actual.valueOf() + 3600000) < this.startDate || actual.valueOf() > this.endDate) {
510                    clsName += ' disabled';
511                } else if (hours == i) {
512                    clsName += ' active';
513                }
514                html.push('<span class="hour' + clsName + '">' + i + ':00</span>');
515            }
516            this.picker.find('.datepicker-hours td').html(html.join(''));
517
518            html = [];
519            for (var i = 0; i < 60; i += this.minuteStep) {
520                var actual = UTCDate(year, month, dayMonth, hours, i);
521                clsName = '';
522                if (actual.valueOf() < this.startDate || actual.valueOf() > this.endDate) {
523                    clsName += ' disabled';
524                } else if (Math.floor(minutes / this.minuteStep) == Math.floor(i / this.minuteStep)) {
525                    clsName += ' active';
526                }
527                html.push('<span class="minute' + clsName + '">' + hours + ':' + (i < 10 ? '0' + i : i) + '</span>');
528            }
529            this.picker.find('.datepicker-minutes td').html(html.join(''));
530
531
532            var currentYear = this.date && this.date.getUTCFullYear();
533            var months = this.picker.find('.datepicker-months')
534                .find('th:eq(1)')
535                .text(year)
536                .end()
537                .find('span').removeClass('active');
538            if (currentYear && currentYear == year) {
539                months.eq(this.date.getUTCMonth()).addClass('active');
540            }
541            if (year < startYear || year > endYear) {
542                months.addClass('disabled');
543            }
544            if (year == startYear) {
545                months.slice(0, startMonth).addClass('disabled');
546            }
547            if (year == endYear) {
548                months.slice(endMonth + 1).addClass('disabled');
549            }
550
551            html = '';
552            year = parseInt(year / 10, 10) * 10;
553            var yearCont = this.picker.find('.datepicker-years')
554                .find('th:eq(1)')
555                .text(year + '-' + (year + 9))
556                .end()
557                .find('td');
558            year -= 1;
559            for (var i = -1; i < 11; i++) {
560                html += '<span class="year' + (i == -1 || i == 10 ? ' old' : '') + (currentYear == year ? ' active' : '') + (year < startYear || year > endYear ? ' disabled' : '') + '">' + year + '</span>';
561                year += 1;
562            }
563            yearCont.html(html);
564        },
565
566        updateNavArrows: function () {
567            var d = new Date(this.viewDate),
568                year = d.getUTCFullYear(),
569                month = d.getUTCMonth(),
570                day = d.getUTCDate(),
571                hour = d.getUTCHours();
572            switch (this.viewMode) {
573                case 0:
574                    if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth() && day <= this.startDate.getUTCDate() && hour <= this.startDate.getUTCHours()) {
575                        this.picker.find('.prev').css({
576                            visibility: 'hidden'
577                        });
578                    } else {
579                        this.picker.find('.prev').css({
580                            visibility: 'visible'
581                        });
582                    }
583                    if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth() && day >= this.endDate.getUTCDate() && hour >= this.endDate.getUTCHours()) {
584                        this.picker.find('.next').css({
585                            visibility: 'hidden'
586                        });
587                    } else {
588                        this.picker.find('.next').css({
589                            visibility: 'visible'
590                        });
591                    }
592                    break;
593                case 1:
594                    if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth() && day <= this.startDate.getUTCDate()) {
595                        this.picker.find('.prev').css({
596                            visibility: 'hidden'
597                        });
598                    } else {
599                        this.picker.find('.prev').css({
600                            visibility: 'visible'
601                        });
602                    }
603                    if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth() && day >= this.endDate.getUTCDate()) {
604                        this.picker.find('.next').css({
605                            visibility: 'hidden'
606                        });
607                    } else {
608                        this.picker.find('.next').css({
609                            visibility: 'visible'
610                        });
611                    }
612                    break;
613                case 2:
614                    if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
615                        this.picker.find('.prev').css({
616                            visibility: 'hidden'
617                        });
618                    } else {
619                        this.picker.find('.prev').css({
620                            visibility: 'visible'
621                        });
622                    }
623                    if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
624                        this.picker.find('.next').css({
625                            visibility: 'hidden'
626                        });
627                    } else {
628                        this.picker.find('.next').css({
629                            visibility: 'visible'
630                        });
631                    }
632                    break;
633                case 3:
634                case 4:
635                    if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
636                        this.picker.find('.prev').css({
637                            visibility: 'hidden'
638                        });
639                    } else {
640                        this.picker.find('.prev').css({
641                            visibility: 'visible'
642                        });
643                    }
644                    if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
645                        this.picker.find('.next').css({
646                            visibility: 'hidden'
647                        });
648                    } else {
649                        this.picker.find('.next').css({
650                            visibility: 'visible'
651                        });
652                    }
653                    break;
654            }
655        },
656
657        click: function (e) {
658            e.stopPropagation();
659            e.preventDefault();
660
661            if ($(e.target).hasClass('datepicker-close') || $(e.target).parent().hasClass('datepicker-close')) {
662                this.hide();
663            }
664
665            var target = $(e.target).closest('span, td, th');
666            if (target.length == 1) {
667                if (target.is('.disabled')) {
668                    this.element.trigger({
669                        type: 'outOfRange',
670                        date: this.viewDate,
671                        startDate: this.startDate,
672                        endDate: this.endDate
673                    });
674                    return;
675                }
676
677                switch (target[0].nodeName.toLowerCase()) {
678                    case 'th':
679                        switch (target[0].className) {
680                            case 'date-switch':
681                                this.showMode(1);
682                                break;
683                            case 'prev':
684                            case 'next':
685                                var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
686                                switch (this.viewMode) {
687                                    case 0:
688                                        this.viewDate = this.moveHour(this.viewDate, dir);
689                                        break;
690                                    case 1:
691                                        this.viewDate = this.moveDate(this.viewDate, dir);
692                                        break;
693                                    case 2:
694                                        this.viewDate = this.moveMonth(this.viewDate, dir);
695                                        break;
696                                    case 3:
697                                    case 4:
698                                        this.viewDate = this.moveYear(this.viewDate, dir);
699                                        break;
700                                }
701                                this.fill();
702                                break;
703                            case 'today':
704                                var date = new Date();
705                                date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
706
707                                this.viewMode = this.startViewMode;
708                                this.showMode(0);
709                                this._setDate(date);
710                                break;
711                        }
712                        break;
713                    case 'span':
714                        if (!target.is('.disabled')) {
715                            if (target.is('.month')) {
716                                if (this.minView === 3) {
717                                    var month = target.parent().find('span').index(target) || 0;
718                                    var year = this.viewDate.getUTCFullYear(),
719                                        day = 1,
720                                        hours = this.viewDate.getUTCHours(),
721                                        minutes = this.viewDate.getUTCMinutes(),
722                                        seconds = this.viewDate.getUTCSeconds();
723                                    this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
724                                } else {
725                                    this.viewDate.setUTCDate(1);
726                                    var month = target.parent().find('span').index(target);
727                                    this.viewDate.setUTCMonth(month);
728                                    this.element.trigger({
729                                        type: 'changeMonth',
730                                        date: this.viewDate
731                                    });
732                                }
733                            } else if (target.is('.year')) {
734                                if (this.minView === 4) {
735                                    var year = parseInt(target.text(), 10) || 0;
736                                    var month = 0,
737                                        day = 1,
738                                        hours = this.viewDate.getUTCHours(),
739                                        minutes = this.viewDate.getUTCMinutes(),
740                                        seconds = this.viewDate.getUTCSeconds();
741                                    this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
742                                } else {
743                                    this.viewDate.setUTCDate(1);
744                                    var year = parseInt(target.text(), 10) || 0;
745                                    this.viewDate.setUTCFullYear(year);
746                                    this.element.trigger({
747                                        type: 'changeYear',
748                                        date: this.viewDate
749                                    });
750                                }
751                            } else if (target.is('.hour')) {
752                                var hours = parseInt(target.text(), 10) || 0;
753                                var year = this.viewDate.getUTCFullYear(),
754                                    month = this.viewDate.getUTCMonth(),
755                                    day = this.viewDate.getUTCDate(),
756                                    minutes = this.viewDate.getUTCMinutes(),
757                                    seconds = this.viewDate.getUTCSeconds();
758                                this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
759                            } else if (target.is('.minute')) {
760                                var minutes = parseInt(target.text().substr(target.text().indexOf(':') + 1), 10) || 0;
761                                var year = this.viewDate.getUTCFullYear(),
762                                    month = this.viewDate.getUTCMonth(),
763                                    day = this.viewDate.getUTCDate(),
764                                    hours = this.viewDate.getUTCHours(),
765                                    seconds = this.viewDate.getUTCSeconds();
766                                this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
767                            }
768
769
770
771                            if (this.viewMode != 0) {
772
773
774
775                                var oldViewMode = this.viewMode;
776                                this.showMode(-1);
777                                this.fill();
778                                if (oldViewMode == this.viewMode && this.autoclose) {
779                                    this.hide();
780                                }
781                            } else {
782                                this.fill();
783                                if (this.autoclose) {
784                                    this.hide();
785                                }
786                            }
787                        }
788                        break;
789                    case 'td':
790
791
792
793                        if (target.is('.day') && !target.is('.disabled')) {
794                            var day = parseInt(target.text(), 10) || 1;
795                            var year = this.viewDate.getUTCFullYear(),
796                                month = this.viewDate.getUTCMonth(),
797                                hours = this.viewDate.getUTCHours(),
798                                minutes = this.viewDate.getUTCMinutes(),
799                                seconds = this.viewDate.getUTCSeconds();
800                            if (target.is('.old')) {
801                                if (month === 0) {
802                                    month = 11;
803                                    year -= 1;
804                                } else {
805                                    month -= 1;
806                                }
807                            } else if (target.is('.new')) {
808                                if (month == 11) {
809                                    month = 0;
810                                    year += 1;
811                                } else {
812                                    month += 1;
813                                }
814                            }
815                            this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));
816                        }
817
818
819
820                        var oldViewMode = this.viewMode;
821
822
823                        this.showMode(-1);
824
825
826                        this.fill();
827                        if (oldViewMode == this.viewMode && this.autoclose) {
828                            this.hide();
829                        }
830                        break;
831                }
832            }
833        },
834
835        _setDate: function (date, which) {
836
837            if (!which || which == 'date')
838                this.date = date;
839            if (!which || which == 'view')
840                this.viewDate = date;
841            this.fill();
842            this.setValue();
843            this.element.trigger({
844                type: 'changeDate',
845                date: this.date
846            });
847            var element;
848            if (this.isInput) {
849                element = this.element;
850            } else if (this.component) {
851                element = this.element.find('input');
852            }
853            if (element) {
854                element.change();
855                if (this.autoclose && (!which || which == 'date')) {
856                    // this.hide();
857                }
858            }
859        },
860
861        moveHour: function (date, dir) {
862            if (!dir) return date;
863            var new_date = new Date(date.valueOf());
864            dir = dir > 0 ? 1 : -1;
865            new_date.setUTCHours(new_date.getUTCHours() + dir);
866            return new_date;
867        },
868
869        moveDate: function (date, dir) {
870            if (!dir) return date;
871            var new_date = new Date(date.valueOf());
872            dir = dir > 0 ? 1 : -1;
873            new_date.setUTCDate(new_date.getUTCDate() + dir);
874            return new_date;
875        },
876
877        moveMonth: function (date, dir) {
878            if (!dir) return date;
879            var new_date = new Date(date.valueOf()),
880                day = new_date.getUTCDate(),
881                month = new_date.getUTCMonth(),
882                mag = Math.abs(dir),
883                new_month, test;
884            dir = dir > 0 ? 1 : -1;
885            if (mag == 1) {
886                test = dir == -1
887                    // If going back one month, make sure month is not current month
888                    // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
889                    ? function () {
890                        return new_date.getUTCMonth() == month;
891                    }
892                    // If going forward one month, make sure month is as expected
893                    // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
894                    : function () {
895                        return new_date.getUTCMonth() != new_month;
896                    };
897                new_month = month + dir;
898                new_date.setUTCMonth(new_month);
899                // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
900                if (new_month < 0 || new_month > 11)
901                    new_month = (new_month + 12) % 12;
902            } else {
903                // For magnitudes >1, move one month at a time...
904                for (var i = 0; i < mag; i++)
905                    // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
906                    new_date = this.moveMonth(new_date, dir);
907                // ...then reset the day, keeping it in the new month
908                new_month = new_date.getUTCMonth();
909                new_date.setUTCDate(day);
910                test = function () {
911                    return new_month != new_date.getUTCMonth();
912                };
913            }
914            // Common date-resetting loop -- if date is beyond end of month, make it
915            // end of month
916            while (test()) {
917                new_date.setUTCDate(--day);
918                new_date.setUTCMonth(new_month);
919            }
920            return new_date;
921        },
922
923        moveYear: function (date, dir) {
924            return this.moveMonth(date, dir * 12);
925        },
926
927        dateWithinRange: function (date) {
928            return date >= this.startDate && date <= this.endDate;
929        },
930
931        keydown: function (e) {
932            if (this.picker.is(':not(:visible)')) {
933                if (e.keyCode == 27) // allow escape to hide and re-show picker
934                    this.show();
935                return;
936            }
937            var dateChanged = false,
938                dir, day, month,
939                newDate, newViewDate;
940            switch (e.keyCode) {
941                case 27: // escape
942                    this.hide();
943                    e.preventDefault();
944                    break;
945                case 37: // left
946                case 39: // right
947                    if (!this.keyboardNavigation) break;
948                    dir = e.keyCode == 37 ? -1 : 1;
949                    if (e.ctrlKey) {
950                        newDate = this.moveYear(this.date, dir);
951                        newViewDate = this.moveYear(this.viewDate, dir);
952                    } else if (e.shiftKey) {
953                        newDate = this.moveMonth(this.date, dir);
954                        newViewDate = this.moveMonth(this.viewDate, dir);
955                    } else {
956                        newDate = new Date(this.date.valueOf());
957                        newDate.setUTCDate(this.date.getUTCDate() + dir);
958                        newViewDate = new Date(this.viewDate.valueOf());
959                        newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
960                    }
961                    if (this.dateWithinRange(newDate)) {
962                        this.date = newDate;
963                        this.viewDate = newViewDate;
964                        this.setValue();
965                        this.update();
966                        e.preventDefault();
967                        dateChanged = true;
968                    }
969                    break;
970                case 38: // up
971                case 40: // down
972                    if (!this.keyboardNavigation) break;
973                    dir = e.keyCode == 38 ? -1 : 1;
974                    if (e.ctrlKey) {
975                        newDate = this.moveYear(this.date, dir);
976                        newViewDate = this.moveYear(this.viewDate, dir);
977                    } else if (e.shiftKey) {
978                        newDate = this.moveMonth(this.date, dir);
979                        newViewDate = this.moveMonth(this.viewDate, dir);
980                    } else {
981                        newDate = new Date(this.date.valueOf());
982                        newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
983                        newViewDate = new Date(this.viewDate.valueOf());
984                        newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
985                    }
986                    if (this.dateWithinRange(newDate)) {
987                        this.date = newDate;
988                        this.viewDate = newViewDate;
989                        this.setValue();
990                        this.update();
991                        e.preventDefault();
992                        dateChanged = true;
993                    }
994                    break;
995                case 13: // enter
996                    this.hide();
997                    e.preventDefault();
998                    break;
999                case 9: // tab
1000                    this.hide();
1001                    break;
1002            }
1003            if (dateChanged) {
1004                this.element.trigger({
1005                    type: 'changeDate',
1006                    date: this.date
1007                });
1008                var element;
1009                if (this.isInput) {
1010                    element = this.element;
1011                } else if (this.component) {
1012                    element = this.element.find('input');
1013                }
1014                if (element) {
1015                    element.change();
1016                }
1017            }
1018        },
1019
1020        showMode: function (dir) {
1021
1022            if (dir) {
1023                var newViewMode = Math.max(0, Math.min(DPGlobal.modes.length - 1, this.viewMode + dir));
1024                if (newViewMode >= this.minView && newViewMode <= this.maxView) {
1025                    this.viewMode = newViewMode;
1026                }
1027            }
1028            /*
1029            	vitalets: fixing bug of very special conditions:
1030            	jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover.
1031            	Method show() does not set display css correctly and datepicker is not shown.
1032            	Changed to .css('display', 'block') solve the problem.
1033            	See https://github.com/vitalets/x-editable/issues/37
1034
1035            	In jquery 1.7.2+ everything works fine.
1036            */
1037            //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
1038            this.picker.find('>div').hide().filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
1039            this.updateNavArrows();
1040        },
1041        reset: function (e) {
1042            this._setDate(null, 'date');
1043        }
1044    };
1045
1046    $.fn.fdatepicker = function (option) {
1047        var args = Array.apply(null, arguments);
1048        args.shift();
1049        return this.each(function () {
1050            var $this = $(this),
1051                data = $this.data('datepicker'),
1052                options = typeof option == 'object' && option;
1053            if (!data) {
1054                $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.fdatepicker.defaults, options))));
1055            }
1056            if (typeof option == 'string' && typeof data[option] == 'function') {
1057                data[option].apply(data, args);
1058            }
1059        });
1060    };
1061
1062    $.fn.fdatepicker.defaults = {
1063        onRender: function (date) {
1064            return '';
1065        }
1066    };
1067    $.fn.fdatepicker.Constructor = Datepicker;
1068    var dates = $.fn.fdatepicker.dates = {
1069        'en': {
1070            days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
1071            daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
1072            daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
1073            months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
1073November", "December"],
1074            monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
1075            today: "Today",
1076            titleFormat: "MM yyyy"
1077        }
1078    };
1079
1080    var DPGlobal = {
1081        modes: [{
1082            clsName: 'minutes',
1083            navFnc: 'Hours',
1084            navStep: 1
1085        }, {
1086            clsName: 'hours',
1087            navFnc: 'Date',
1088            navStep: 1
1089        }, {
1090            clsName: 'days',
1091            navFnc: 'Month',
1092            navStep: 1
1093        }, {
1094            clsName: 'months',
1095            navFnc: 'FullYear',
1096            navStep: 1
1097        }, {
1098            clsName: 'years',
1099            navFnc: 'FullYear',
1100            navStep: 10
1101        }],
1102        isLeapYear: function (year) {
1103            return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
1104        },
1105        getDaysInMonth: function (year, month) {
1106            return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
1107        },
1108        validParts: /hh?|ii?|ss?|dd?|mm?|MM?|yy(?:yy)?/g,
1109        nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
1110        parseFormat: function (format) {
1111            // IE treats \0 as a string end in inputs (truncating the value),
1112            // so it's a bad format delimiter, anyway
1113            var separators = format.replace(this.validParts, '\0').split('\0'),
1114                parts = format.match(this.validParts);
1115            if (!separators || !separators.length || !parts || parts.length === 0) {
1116                throw new Error("Invalid date format.");
1117            }
1118            return {
1119                separators: separators,
1120                parts: parts
1121            };
1122        },
1123        parseDate: function (date, format, language) {
1124            if (date instanceof Date) return new Date(date.valueOf() - date.getTimezoneOffset() * 60000);
1125            if (/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(date)) {
1126                format = this.parseFormat('yyyy-mm-dd');
1127            }
1128            if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(date)) {
1129                format = this.parseFormat('yyyy-mm-dd hh:ii');
1130            }
1131            if (/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(date)) {
1132                format = this.parseFormat('yyyy-mm-dd hh:ii:ss');
1133            }
1134            if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
1135                var part_re = /([-+]\d+)([dmwy])/,
1136                    parts = date.match(/([-+]\d+)([dmwy])/g),
1137                    part, dir;
1138                date = new Date();
1139                for (var i = 0; i < parts.length; i++) {
1140                    part = part_re.exec(parts[i]);
1141                    dir = parseInt(part[1]);
1142                    switch (part[2]) {
1143                        case 'd':
1144                            date.setUTCDate(date.getUTCDate() + dir);
1145                            break;
1146                        case 'm':
1147                            date = Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype, date, dir);
1148                            break;
1149                        case 'w':
1150                            date.setUTCDate(date.getUTCDate() + dir * 7);
1151                            break;
1152                        case 'y':
1153                            date = Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype, date, dir);
1154                            break;
1155                    }
1156                }
1157                return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
1158            }
1159            var parts = date && date.match(this.nonpunctuation) || [],
1160                date = new Date(),
1161                parsed = {},
1162                setters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
1163                setters_map = {
1164                    hh: function (d, v) {
1165                        return d.setUTCHours(v);
1166                    },
1167                    h: function (d, v) {
1168                        return d.setUTCHours(v);
1169                    },
1170                    ii: function (d, v) {
1171                        return d.setUTCMinutes(v);
1172                    },
1173                    i: function (d, v) {
1174                        return d.setUTCMinutes(v);
1175                    },
1176                    ss: function (d, v) {
1177                        return d.setUTCSeconds(v);
1178                    },
1179                    s: function (d, v) {
1180                        return d.setUTCSeconds(v);
1181                    },
1182                    yyyy: function (d, v) {
1183                        return d.setUTCFullYear(v);
1184                    },
1185                    yy: function (d, v) {
1186                        return d.setUTCFullYear(2000 + v);
1187                    },
1188                    m: function (d, v) {
1189                        v -= 1;
1190                        while (v < 0) v += 12;
1191                        v %= 12;
1192                        d.setUTCMonth(v);
1193                        while (d.getUTCMonth() != v)
1194                            d.setUTCDate(d.getUTCDate() - 1);
1195                        return d;
1196                    },
1197                    d: function (d, v) {
1198                        return d.setUTCDate(v);
1199                    }
1200                },
1201                val, filtered, part;
1202            setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
1203            setters_map['dd'] = setters_map['d'];
1204            date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); //date.getHours(), date.getMinutes(), date.getSeconds());
1205            if (parts.length == format.parts.length) {
1206                for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
1207                    val = parseInt(parts[i], 10);
1208                    part = format.parts[i];
1209                    if (isNaN(val)) {
1210                        switch (part) {
1211                            case 'MM':
1212                                filtered = $(dates[language].months).filter(function () {
1213                                    var m = this.slice(0, parts[i].length),
1214                                        p = parts[i].slice(0, m.length);
1215                                    return m == p;
1216                                });
1217                                val = $.inArray(filtered[0], dates[language].months) + 1;
1218                                break;
1219                            case 'M':
1220                                filtered = $(dates[language].monthsShort).filter(function () {
1221                                    var m = this.slice(0, parts[i].length),
1222                                        p = parts[i].slice(0, m.length);
1223                                    return m == p;
1224                                });
1225                                val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
1226                                break;
1227                        }
1228                    }
1229                    parsed[part] = val;
1230                }
1231                for (var i = 0, s; i < setters_order.length; i++) {
1232                    s = setters_order[i];
1233                    if (s in parsed && !isNaN(parsed[s]))
1234                        setters_map[s](date, parsed[s])
1235                }
1236            }
1237            return date;
1238        },
1239        formatDate: function (date, format, language) {
1240            if (date == null) {
1241                return '';
1242            }
1243            var val = {
1244                h: date.getUTCHours(),
1245                i: date.getUTCMinutes(),
1246                s: date.getUTCSeconds(),
1247                d: date.getUTCDate(),
1248                m: date.getUTCMonth() + 1,
1249                M: dates[language].monthsShort[date.getUTCMonth()],
1250                MM: dates[language].months[date.getUTCMonth()],
1251                yy: date.getUTCFullYear().toString().substring(2),
1252                yyyy: date.getUTCFullYear()
1253            };
1254            val.hh = (val.h < 10 ? '0' : '') + val.h;
1255            val.ii = (val.i < 10 ? '0' : '') + val.i;
1256            val.ss = (val.s < 10 ? '0' : '') + val.s;
1257            val.dd = (val.d < 10 ? '0' : '') + val.d;
1258            val.mm = (val.m < 10 ? '0' : '') + val.m;
1259            var date = [],
1260                seps = $.extend([], format.separators);
1261            for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
1262                if (seps.length)
1263                    date.push(seps.shift())
1264                date.push(val[format.parts[i]]);
1265            }
1266            return date.join('');
1267        },
1268        convertViewMode: function (viewMode) {
1269            switch (viewMode) {
1270                case 4:
1271                case 'decade':
1272                    viewMode = 4;
1273                    break;
1274                case 3:
1275                case 'year':
1276                    viewMode = 3;
1277                    break;
1278                case 2:
1279                case 'month':
1280                    viewMode = 2;
1281                    break;
1282                case 1:
1283                case 'day':
1284                    viewMode = 1;
1285                    break;
1286                case 0:
1287                case 'hour':
1288                    viewMode = 0;
1289                    break;
1290            }
1291
1292            return viewMode;
1293        },
1294        headTemplate: '<thead>' +
1295            '<tr>' +
1296            '<th class="prev"><i class="fa fa-chevron-left fi-arrow-left"/></th>' +
1297            '<th colspan="5" class="date-switch"></th>' +
1298            '<th class="next"><i class="fa fa-chevron-right fi-arrow-right"/></th>' +
1299            '</tr>' +
1300            '</thead>',
1301        contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
1302        footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'
1303    };
1304    DPGlobal.template = '<div class="datepicker">' +
1305        '<div class="datepicker-minutes">' +
1306        '<table class=" table-condensed">' +
1307        DPGlobal.headTemplate +
1308        DPGlobal.contTemplate +
1309        DPGlobal.footTemplate +
1310        '</table>' +
1311        '</div>' +
1312        '<div class="datepicker-hours">' +
1313        '<table class=" table-condensed">' +
1314        DPGlobal.headTemplate +
1315        DPGlobal.contTemplate +
1316        DPGlobal.footTemplate +
1317        '</table>' +
1318        '</div>' +
1319        '<div class="datepicker-days">' +
1320        '<table class=" table-condensed">' +
1321        DPGlobal.headTemplate +
1322        '<tbody></tbody>' +
1323        DPGlobal.footTemplate +
1324        '</table>' +
1325        '</div>' +
1326        '<div class="datepicker-months">' +
1327        '<table class="table-condensed">' +
1328        DPGlobal.headTemplate +
1329        DPGlobal.contTemplate +
1330        DPGlobal.footTemplate +
1331        '</table>' +
1332        '</div>' +
1333        '<div class="datepicker-years">' +
1334        '<table class="table-condensed">' +
1335        DPGlobal.headTemplate +
1336        DPGlobal.contTemplate +
1337        DPGlobal.footTemplate +
1338        '</table>' +
1339        '</div>' +
1340        '<a class="button datepicker-close tiny alert right" style="width:auto;"><i class="fa fa-remove fa-times fi-x"></i></a>' +
1341        '</div>';
1342
1343    $.fn.fdatepicker.DPGlobal = DPGlobal;
1344
1345}(window.jQuery);

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.