PageSourceSearch

https://seoup.su/bitrix/templates/seoup/assets/plugins/bootstrap-d…/daterangepicker.js?158750099733823

js seoup.su collected 2026-10-05 00:08:28 UTC 33,823 bytes, 864 lines download raw bytes

1/**
2* @version: 1.2
3* @author: Dan Grossman http://www.dangrossman.info/
4*
5* @Improved by KeenThemes for Metronic Bootstrap 3.0
6
7* @date: 2013-07-25
8* @copyright: Copyright (c) 2012-2013 Dan Grossman. All rights reserved.
9* @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0
10* @website: http://www.improvely.com/
11*/
12!function ($) {
13
14    var DateRangePicker = function (element, options, cb) {
15        var hasOptions = typeof options == 'object';
16        var localeObject;
17
18        //option defaults
19
20        this.startDate = moment().startOf('day');
21        this.endDate = moment().startOf('day');
22        this.minDate = false;
23        this.maxDate = false;
24        this.dateLimit = false;
25
26        this.showDropdowns = false;
27        this.showWeekNumbers = false;
28        this.timePicker = false;
29        this.timePickerIncrement = 30;
30        this.timePicker12Hour = true;
31        this.ranges = {};
32        this.opens = 'right';
33
34        this.buttonClasses = ['btn', 'btn-small'];
35        this.applyClass = 'green';
36        this.cancelClass = 'default';
37
38        this.format = 'MM/DD/YYYY';
39        this.separator = ' - ';
40
41        this.locale = {
42            applyLabel: 'Apply',
43            cancelLabel: 'Cancel',
44            fromLabel: 'From',
45            toLabel: 'To',
46            weekLabel: 'W',
47            customRangeLabel: 'Custom Range',
48            daysOfWeek: moment()._lang._weekdaysMin.slice(),
49            monthNames: moment()._lang._monthsShort.slice(),
50            firstDay: 0
51        };
52
53        this.cb = function () { };
54
55        //element that triggered the date range picker
56        this.element = $(element);
57
58        if (this.element.hasClass('pull-right'))
59            this.opens = 'left';
60
61        if (this.element.is('input')) {
62            this.element.on({
63                click: $.proxy(this.show, this),
64                focus: $.proxy(this.show, this)
65            });
66        } else {
67            this.element.on('click', $.proxy(this.show, this));
68        }
69
70        localeObject = this.locale;
71
72        if (hasOptions) {
73            if (typeof options.locale == 'object') {
74                $.each(localeObject, function (property, value) {
75                    localeObject[property] = options.locale[property] || value;
76                });
77            }
78
79            if (options.applyClass) {
80                this.applyClass = options.applyClass;
81            }
82
83            if (options.cancelClass) {
84                this.cancelClass = options.cancelClass;
85            }
86        }
87
88
89        var DRPTemplate = '<div class="daterangepicker dropdown-menu">' +
90                '<div class="calendar left"></div>' +
91                '<div class="calendar right"></div>' +
92                '<div class="ranges">' +
93                  '<div class="range_inputs">' +
94                    '<div class="daterangepicker_start_input" style="float: left">' +
95                      '<label for="daterangepicker_start">' + this.locale.fromLabel + '</label>' +
96                      '<input class="input-mini" type="text" name="daterangepicker_start" value="" disabled="disabled" />' +
97                    '</div>' +
98                    '<div class="daterangepicker_end_input" style="float: left; padding-left: 11px">' +
99                      '<label for="daterangepicker_end">' + this.locale.toLabel + '</label>' +
100                      '<input class="input-mini" type="text" name="daterangepicker_end" value="" disabled="disabled" />' +
101                    '</div>' +
102                    '<button class="' + this.applyClass + ' applyBtn" disabled="disabled">' + this.locale.applyLabel + '</button>&nbsp;' +
103                    '<button class="' + this.cancelClass + ' cancelBtn">' + this.locale.cancelLabel + '</button>' +
104                  '</div>' +
105                '</div>' +
106              '</div>';
107
108        this.container = $(DRPTemplate).appendTo('body');
109
110        if (hasOptions) {
111
112            if (typeof options.format == 'string')
113                this.format = options.format;
114
115            if (typeof options.separator == 'string')
116                this.separator = options.separator;
117
118            if (typeof options.startDate == 'string')
119                this.startDate = moment(options.startDate, this.format);
120
121            if (typeof options.endDate == 'string')
122                this.endDate = moment(options.endDate, this.format);
123
124            if (typeof options.minDate == 'string')
125                this.minDate = moment(options.minDate, this.format);
126
127            if (typeof options.maxDate == 'string')
128                this.maxDate = moment(options.maxDate, this.format);
129
130            if (typeof options.startDate == 'object')
131                this.startDate = moment(options.startDate);
132
133            if (typeof options.endDate == 'object')
134                this.endDate = moment(options.endDate);
135
136            if (typeof options.minDate == 'object')
137                this.minDate = moment(options.minDate);
138
139            if (typeof options.maxDate == 'object')
140                this.maxDate = moment(options.maxDate);
141
142            if (typeof options.ranges == 'object') {
143                for (var range in options.ranges) {
144
145                    var start = moment(options.ranges[range][0]);
146                    var end = moment(options.ranges[range][1]);
147
148                    // If we have a min/max date set, bound this range
149                    // to it, but only if it would otherwise fall
150                    // outside of the min/max.
151                    if (this.minDate && start.isBefore(this.minDate))
152                        start = moment(this.minDate);
153
154                    if (this.maxDate && end.isAfter(this.maxDate))
155                        end = moment(this.maxDate);
156
157                    // If the end of the range is before the minimum (if min is set) OR
158                    // the start of the range is after the max (also if set) don't display this
159                    // range option.
160                    if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) {
161                        continue;
162                    }
163
164                    this.ranges[range] = [start, end];
165                }
166
167                var list = '<ul>';
168                for (var range in this.ranges) {
169                    list += '<li>' + range + '</li>';
170                }
171                list += '<li>' + this.locale.customRangeLabel + '</li>';
172                list += '</ul>';
173                this.container.find('.ranges').prepend(list);
174            }
175
176            if (typeof options.dateLimit == 'object')
177                this.dateLimit = options.dateLimit;
178
179            // update day names order to firstDay
180            if (typeof options.locale == 'object') {
181                if (typeof options.locale.firstDay == 'number') {
182                    this.locale.firstDay = options.locale.firstDay;
183                    var iterator = options.locale.firstDay;
184                    while (iterator > 0) {
185                        this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());
186                        iterator--;
187                    }
188                }
189            }
190
191            if (typeof options.opens == 'string')
192                this.opens = options.opens;
193
194            if (typeof options.showWeekNumbers == 'boolean') {
195                this.showWeekNumbers = options.showWeekNumbers;
196            }
197
198            if (typeof options.buttonClasses == 'string') {
199                this.buttonClasses = [options.buttonClasses];
200            }
201
202            if (typeof options.buttonClasses == 'object') {
203                this.buttonClasses = options.buttonClasses;
204            }
205
206            if (typeof options.showDropdowns == 'boolean') {
207                this.showDropdowns = options.showDropdowns;
208            }
209
210            if (typeof options.timePicker == 'boolean') {
211                this.timePicker = options.timePicker;
212            }
213
214            if (typeof options.timePickerIncrement == 'number') {
215                this.timePickerIncrement = options.timePickerIncrement;
216            }
217
218            if (typeof options.timePicker12Hour == 'boolean') {
219                this.timePicker12Hour = options.timePicker12Hour;
220            }
221
222        }
223
224        if (!this.timePicker) {
225            this.startDate = this.startDate.startOf('day');
226            this.endDate = this.endDate.startOf('day');
227        }
228
229        //apply CSS classes to buttons
230        var c = this.container;
231        $.each(this.buttonClasses, function (idx, val) {
232            c.find('button').addClass(val);
233        });
234
235        if (this.opens == 'right') {
236            //swap calendar positions
237            var left = this.container.find('.calendar.left');
238            var right = this.container.find('.calendar.right');
239            left.removeClass('left').addClass('right');
240            right.removeClass('right').addClass('left');
241        }
242
243        if (typeof options == 'undefined' || typeof options.ranges == 'undefined') {
244            this.container.find('.calendar').show();
245            this.move();
246        }
247
248        if (typeof cb == 'function')
249            this.cb = cb;
250
251        this.container.addClass('opens' + this.opens);
252
253        //try parse date if in text input
254        if (!hasOptions || (typeof options.startDate == 'undefined' && typeof options.endDate == 'undefined')) {
255            if ($(this.element).is('input[type=text]')) {
256                var val = $(this.element).val();
257                var split = val.split(this.separator);
258                var start, end;
259                if (split.length == 2) {
260                    start = moment(split[0], this.format);
261                    end = moment(split[1], this.format);
262                }
263                if (start != null && end != null) {
264                    this.startDate = start;
265                    this.endDate = end;
266                }
267            }
268        }
269
270        //state
271        this.oldStartDate = this.startDate.clone();
272        this.oldEndDate = this.endDate.clone();
273
274        this.leftCalendar = {
275            month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]),
276            calendar: []
277        };
278
279        this.rightCalendar = {
280            month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]),
281            calendar: []
282        };
283
284        //event listeners
285        this.container.on('mousedown', $.proxy(this.mousedown, this));
286        this.container.find('.calendar').on('click', '.prev', $.proxy(this.clickPrev, this));
287        this.container.find('.calendar').on('click', '.next', $.proxy(this.clickNext, this));
288        this.container.find('.ranges').on('click', 'button.applyBtn', $.proxy(this.clickApply, this));
289        this.container.find('.ranges').on('click', 'button.cancelBtn', $.proxy(this.clickCancel, this));
290
291        this.container.find('.ranges').on('click', '.daterangepicker_start_input', $.proxy(this.showCalendars, this));
292        this.container.find('.ranges').on('click', '.daterangepicker_end_input', $.proxy(this.showCalendars, this));
293
294        this.container.find('.calendar').on('click', 'td.available', $.proxy(this.clickDate, this));
295        this.container.find('.calendar').on('mouseenter', 'td.available', $.proxy(this.enterDate, this));
296        this.container.find('.calendar').on('mouseleave', 'td.available', $.proxy(this.updateView, this));
297
298        this.container.find('.ranges').on('click', 'li', $.proxy(this.clickRange, this));
299        this.container.find('.ranges').on('mouseenter', 'li', $.proxy(this.enterRange, this));
300        this.container.find('.ranges').on('mouseleave', 'li', $.proxy(this.updateView, this));
301
302        this.container.find('.calendar').on('change', 'select.yearselect', $.proxy(this.updateMonthYear, this));
303        this.container.find('.calendar').on('change', 'select.monthselect', $.proxy(this.updateMonthYear, this));
304
305        this.container.find('.calendar').on('change', 'select.hourselect', $.proxy(this.updateTime, this));
306        this.container.find('.calendar').on('change', 'select.minuteselect', $.proxy(this.updateTime, this));
307        this.container.find('.calendar').on('change', 'select.ampmselect', $.proxy(this.updateTime, this));
308
309        this.element.on('keyup', $.proxy(this.updateFromControl, this));
310
311        this.updateView();
312        this.updateCalendars();
313
314    };
315
316    DateRangePicker.prototype = {
317
318        constructor: DateRangePicker,
319
320        mousedown: function (e) {
321            e.stopPropagation();
322        },
323
324        updateView: function () {
325            this.leftCalendar.month.month(this.startDate.month()).year
325(this.startDate.year());
326            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());
327
328            this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format));
329            this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format));
330
331            if (this.startDate.isSame(this.endDate) || this.startDate.isBefore(this.endDate)) {
332                this.container.find('button.applyBtn').removeAttr('disabled');
333            } else {
334                this.container.find('button.applyBtn').attr('disabled', 'disabled');
335            }
336        },
337
338        updateFromControl: function () {
339            if (!this.element.is('input')) return;
340            if (!this.element.val().length) return;
341
342            var dateString = this.element.val().split(this.separator);
343            var start = moment(dateString[0], this.format);
344            var end = moment(dateString[1], this.format);
345
346            if (start == null || end == null) return;
347            if (end.isBefore(start)) return;
348
349            this.startDate = start;
350            this.endDate = end;
351
352            this.notify();
353            this.updateCalendars();
354        },
355
356        notify: function () {
357            this.updateView();
358            this.cb(this.startDate, this.endDate);
359        },
360
361        move: function () {
362            var minWidth = $(this.container).find('.ranges').outerWidth();
363            if ($(this.container).find('.calendar').is(':visible')) {
364                var padding = 24; // FIXME: this works for the default styling, but isn't flexible
365                minWidth += $(this.container).find('.calendar').outerWidth() * 2 + padding;
366            }
367            if (this.opens == 'left') {
368                this.container.css({
369                    top: this.element.offset().top + this.element.outerHeight(),
370                    right: $(window).width() - this.element.offset().left - this.element.outerWidth(),
371                    left: 'auto',
372                    'min-width': minWidth
373                });
374                if (this.container.offset().left < 0) {
375                    this.container.css({
376                        right: 'auto',
377                        left: 9
378                    });
379                }
380            } else {
381                this.container.css({
382                    top: this.element.offset().top + this.element.outerHeight(),
383                    left: this.element.offset().left,
384                    right: 'auto',
385                    'min-width': minWidth
386                });
387                if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {
388                    this.container.css({
389                        left: 'auto',
390                        right: 0
391                    });
392                }
393            }
394        },
395
396        show: function (e) {
397            this.container.show();
398            this.move();
399
400            if (e) {
401                e.stopPropagation();
402                e.preventDefault();
403            }
404
405            $(document).on('mousedown', $.proxy(this.hide, this));
406            this.element.trigger('shown', {target: e.target, picker: this});
407        },
408
409        hide: function (e) {
410            this.container.hide();
411
412            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))
413                this.notify();
414
415            this.oldStartDate = this.startDate.clone();
416            this.oldEndDate = this.endDate.clone();
417
418            $(document).off('mousedown', this.hide);
419            this.element.trigger('hidden', { picker: this });
420        },
421
422        enterRange: function (e) {
423            var label = e.target.innerHTML;
424            if (label == this.locale.customRangeLabel) {
425                this.updateView();
426            } else {
427                var dates = this.ranges[label];
428                this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format));
429                this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format));
430            }
431        },
432
433        showCalendars: function() {
434            this.container.find('.calendar').show();
435            this.move();
436        },
437
438        updateInputText: function() {
439            if (this.element.is('input'))
440                this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));
441        },
442
443        clickRange: function (e) {
444            var label = e.target.innerHTML;
445            if (label == this.locale.customRangeLabel) {
446                this.showCalendars();
447            } else {
448                var dates = this.ranges[label];
449
450                this.startDate = dates[0];
451                this.endDate = dates[1];
452
453                if (!this.timePicker) {
454                    this.startDate.startOf('day');
455                    this.endDate.startOf('day');
456                }
457
458                this.leftCalendar.month.month(this.startDate.month()).year
458(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute());
459                this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute());
460                this.updateCalendars();
461
462                this.updateInputText();
463
464                this.container.find('.calendar').hide();
465                this.hide();
466            }
467        },
468
469        clickPrev: function (e) {
470            var cal = $(e.target).parents('.calendar');
471            if (cal.hasClass('left')) {
472                this.leftCalendar.month.subtract('month', 1);
473            } else {
474                this.rightCalendar.month.subtract('month', 1);
475            }
476            this.updateCalendars();
477        },
478
479        clickNext: function (e) {
480            var cal = $(e.target).parents('.calendar');
481            if (cal.hasClass('left')) {
482                this.leftCalendar.month.add('month', 1);
483            } else {
484                this.rightCalendar.month.add('month', 1);
485            }
486            this.updateCalendars();
487        },
488
489        enterDate: function (e) {
490
491            var title = $(e.target).attr('data-title');
492            var row = title.substr(1, 1);
493            var col = title.substr(3, 1);
494            var cal = $(e.target).parents('.calendar');
495
496            if (cal.hasClass('left')) {
497                this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format));
498            } else {
499                this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format));
500            }
501
502        },
503
504        clickDate: function (e) {
505            var title = $(e.target).attr('data-title');
506            var row = title.substr(1, 1);
507            var col = title.substr(3, 1);
508            var cal = $(e.target).parents('.calendar');
509
510            if (cal.hasClass('left')) {
511                var startDate = this.leftCalendar.calendar[row][col];
512                var endDate = this.endDate;
513                if (typeof this.dateLimit == 'object') {
514                    var maxDate = moment(startDate).add(this.dateLimit).startOf('day');
515                    if (endDate.isAfter(maxDate)) {
516                        endDate = maxDate;
517                    }
518                }
519            } else {
520                var startDate = this.startDate;
521                var endDate = this.rightCalendar.calendar[row][col];
522                if (typeof this.dateLimit == 'object') {
523                    var minDate = moment(endDate).subtract(this.dateLimit).startOf('day');
524                    if (startDate.isBefore(minDate)) {
525                        startDate = minDate;
526                    }
527                }
528            }
529
530            cal.find('td').removeClass('active');
531
532            if (startDate.isSame(endDate) || startDate.isBefore(endDate)) {
533                $(e.target).addClass('active');
534                this.startDate = startDate;
535                this.endDate = endDate;
536            } else if (startDate.isAfter(endDate)) {
537                $(e.target).addClass('active');
538                this.startDate = startDate;
539                this.endDate = moment(startDate).add('day', 1).startOf('day');
540            }
541
542            this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());
543            this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());
544            this.updateCalendars();
545        },
546
547        clickApply: function (e) {
548            this.updateInputText();
549            this.hide();
550        },
551
552        clickCancel: function (e) {
553            this.startDate = this.oldStartDate;
554            this.endDate = this.oldEndDate;
555            this.updateView();
556            this.updateCalendars();
557            this.hide();
558        },
559
560        updateMonthYear: function (e) {
561
562            var isLeft = $(e.target).closest('.calendar').hasClass('left');
563            var cal = this.container.find('.calendar.left');
564            if (!isLeft)
565                cal = this.container.find('.calendar.right');
566
567            var month = cal.find('.monthselect').val();
568            var year = cal.find('.yearselect').val();
569
570            if (isLeft) {
571                this.leftCalendar.month.month(month).year(year);
572            } else {
573                this.rightCalendar.month.month(month).year(year);
574            }
575
576            this.updateCalendars();
577
578        },
579
580        updateTime: function(e) {
581
582            var isLeft = $(e.target).closest('.calendar').hasClass('left');
583            var cal = this.container.find('.calendar.left');
584            if (!isLeft)
585                cal = this.container.find('.calendar.right');
586
587            var hour = parseInt(cal.find('.hourselect').val());
588            var minute = parseInt(cal.find('.minuteselect').val());
589
590            if (this.timePicker12Hour) {
591                var ampm = cal.find('.ampmselect').val();
592                if (ampm == 'PM' && hour < 12)
593                    hour += 12;
594                if (ampm == 'AM' && hour == 12)
595                    hour = 0;
596            }
597
598            if (isLeft) {
599                var start = this.startDate;
600                start.hour(hour);
601                start.minute(minute);
602                this.startDate = start;
603                this.leftCalendar.month.hour(hour).minute(minute);
604            } else {
605                var end = this.endDate;
606                end.hour(hour);
607                end.minute(minute);
608                this.endDate = end;
609                this.rightCalendar.month.hour(hour).minute(minute);
610            }
611
612            this.updateCalendars();
613
614        },
615
616        updateCalendars: function () {
617            this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), 'left');
618            this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), 'right');
619            this.container.find('.calendar.left').html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate));
620            this.container.find('.calendar.right').html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate));
621
622            this.container.find('.ranges li').removeClass('active');
623            var customRange = true;
624            var i = 0;
625            for (var range in this.ranges) {
626                if (this.timePicker) {
627                    if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {
628                        customRange = false;
629                        this.container.find('.ranges li:eq(' + i + ')').addClass('active');
630                    }
631                } else {
632                    //ignore times when comparing dates if time picker is not enabled
633                    if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) {
634                        customRange = false;
635                        this.container.find('.ranges li:eq(' + i + ')').addClass('active');
636                    }
637                }
638                i++;
639            }
640            if (customRange)
641                this.container.find('.ranges li:last').addClass('active');
642        },
643
644        buildCalendar: function (month, year, hour, minute, side) {
645
646            var firstDay = moment([year, month, 1]);
647            var lastMonth = moment(firstDay).subtract('month', 1).month();
648            var lastYear = moment(firstDay).subtract('month', 1).year();
649
650            var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();
651
652            var dayOfWeek = firstDay.day();
653
654            //initialize a 6 rows x 7 columns array for the calendar
655            var calendar = [];
656            for (var i = 0; i < 6; i++) {
657                calendar[i] = [];
658            }
659
660            //populate the calendar with date objects
661            var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;
662            if (startDay > daysInLastMonth)
663                startDay -= 7;
664
665            if (dayOfWeek == this.locale.firstDay)
666                startDay = daysInLastMonth - 6;
667
668            var curDate = moment([lastYear, lastMonth, startDay, hour, minute]);
669            for (var i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('day', 1)) {
670                if (i > 0 && col % 7 == 0) {
671                    col = 0;
672                    row++;
673                }
674                calendar[row][col] = curDate;
675            }
676
677            return calendar;
678
679        },
680
681        renderDropdowns: function (selected, minDate, maxDate) {
682            var currentMonth = selected.month();
683            var monthHtml = '<select class="monthselect">';
684            var inMinYear = false;
685            var inMaxYear = false;
686
687            for (var m = 0; m < 12; m++) {
688                if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) {
689                    monthHtml += "<option value='" + m + "'" +
690                        (m === currentMonth ? " selected='selected'" : "") +
691                        ">" + this.locale.monthNames[m] + "</option>";
692                }
693            }
694            monthHtml += "</select>";
695
696            var currentYear = selected.year();
697            var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);
698            var minYear = (minDate && minDate.year()) || (currentYear - 50);
699            var yearHtml = '<select class="yearselect">'
700
701            for (var y = minYear; y <= maxYear; y++) {
702                yearHtml += '<option value="' + y + '"' +
703                    (y === currentYear ? ' selected="selected"' : '') +
704                    '>' + y + '</option>';
705            }
706
707            yearHtml += '</select>';
708
709            return monthHtml + yearHtml;
710        },
711
712        renderCalendar: function (calendar, selected, minDate, maxDate) {
713
714            var html = '<div class="calendar-date">';
715            html += '<table class="table-condensed">';
716            html += '<thead>';
717            html += '<tr>';
718
719            // add empty cell for week number
720            if (this.showWeekNumbers)
721                html += '<th></th>';
722
723            if (!minDate || minDate.isBefore(calendar[1][1])) {
724                html += '<th class="prev available"><i class="fa fa-angle-left"></i></th>';
725            } else {
726                html += '<th></th>';
727            }
728
729            var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY");
730
731            if (this.showDropdowns) {
732                dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate);
733            }
734
735            html += '<th colspan="5" style="width: auto">' + dateHtml + '</th>';
736            if (!maxDate || maxDate.isAfter(calendar[1][1])) {
737                html += '<th class="next available"><i class="fa fa-angle-right"></i></th>';
738            } else {
739                html += '<th></th>';
740            }
741
742            html += '</tr>';
743            html += '<tr>';
744
745            // add week number label
746            if (this.showWeekNumbers)
747                html += '<th class="week">' + this.locale.weekLabel + '</th>';
748
749            $.each(this.locale.daysOfWeek, function (index, dayOfWeek) {
750                html += '<th>' + dayOfWeek + '</th>';
751            });
752
753            html += '</tr>';
754            html += '</thead>';
755            html += '<tbody>';
756
757            for (var row = 0; row < 6; row++) {
758                html += '<tr>';
759
760                // add week number
761                if (this.showWeekNumbers)
762                    html += '<td class="week">' + calendar[row][0].week() + '</td>';
763
764                for (var col = 0; col < 7; col++) {
765                    var cname = 'available ';
766                    cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off';
767
768                    if ((minDate && calendar[row][col].isBefore(minDate)) || (maxDate && calendar[row][col].isAfter(maxDate))) {
769                        cname = ' off disabled ';
770                    } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) {
771                        cname += ' active ';
772                        if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) {
773                            cname += ' start-date ';
774                        }
775                        if (calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) {
776                            cname += ' end-date ';
777                        }
778                    } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) {
779                        cname += ' in-range ';
780                        if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; }
781                        if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; }
782                    }
783
784                    var title = 'r' + row + 'c' + col;
785                    html += '<td class="' + cname.replace(/\s+/g, ' ').replace(/^\s?(.*?)\s?$/, '$1') + '" data-title="' + title + '">' + calendar[row][col].date() + '</td>';
786                }
787                html += '</tr>';
788            }
789
790            html += '</tbody>';
791            html += '</table>';
792            html += '</div>';
793
794            if (this.timePicker) {
795
796                html += '<div class="calendar-time">';
797                html += '<select class="hourselect">';
798                var start = 0;
799                var end = 23;
800                var selected_hour = selected.hour();
801                if (this.timePicker12Hour) {
802                    start = 1;
803                    end = 12;
804                    if (selected_hour >= 12)
805                        selected_hour -= 12;
806                    if (selected_hour == 0)
807                        selected_hour = 12;
808                }
809
810                for (var i = start; i <= end; i++) {
811                    if (i == selected_hour) {
812                        html += '<option value="' + i + '" selected="selected">' + i + '</option>';
813                    } else {
814                        html += '<option value="' + i + '">' + i + '</option>';
815                    }
816                }
817
818                html += '</select> : ';
819
820                html += '<select class="minuteselect">';
821
822                for (var i = 0; i < 60; i += this.timePickerIncrement) {
823                    var num = i;
824                    if (num < 10)
825                        num = '0' + num;
826                    if (i == selected.minute()) {
827                        html += '<option value="' + i + '" selected="selected">' + num + '</option>';
828                    } else {
829                        html += '<option value="' + i + '">' + num + '</option>';
830                    }
831                }
832
833                html += '</select> ';
834
835                if (this.timePicker12Hour) {
836                    html += '<select class="ampmselect">';
837                    if (selected.hour() >= 12) {
838                        html += '<option value="AM">AM</option><option value="PM" selected="selected">PM</option>';
839                    } else {
840                        html += '<option value="AM" selected="selected">AM</option><option value="PM">PM</option>';
841                    }
842                    html += '</select>';
843                }
844
845                html += '</div>';
846
847            }
848
849            return html;
850
851        }
852
853    };
854
855    $.fn.daterangepicker = function (options, cb) {
856        this.each(function () {
857            var el = $(this);
858            if (!el.data('daterangepicker'))
859                el.data('daterangepicker', new DateRangePicker(el, options, cb));
860        });
861        return this;
862    };
863
864}(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.