PageSourceSearch

https://www.step.or.kr/step/js/daterangepicker.js?date=1790396611896

js step.or.kr collected 2026-09-26 04:24:49 UTC 70,811 bytes, 1,665 lines download raw bytes

1
2/**
3* @version: 2.1.24
4* @author: Dan Grossman http://www.dangrossman.info/
5* @copyright: Copyright (c) 2012-2016 Dan Grossman. All rights reserved.
6* @license: Licensed under the MIT license. See https://www.opensource.org/licenses/mit-license.php
7* @website: https://www.improvely.com/
8*/
9// Follow the UMD template https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js
10(function (root, factory) {
11    if (typeof define === 'function' && define.amd) {
12        // AMD. Make globaly available as well
13        define(['moment', 'jquery'], function (moment, jquery) {
14            return (root.daterangepicker = factory(moment, jquery));
15        });
16    } else if (typeof module === 'object' && module.exports) {
17        // Node / Browserify
18        //isomorphic issue
19        var jQuery = (typeof window != 'undefined') ? window.jQuery : undefined;
20        if (!jQuery) {
21            jQuery = require('jquery');
22            if (!jQuery.fn) jQuery.fn = {};
23        }
24        module.exports = factory(require('moment'), jQuery);
25    } else {
26        // Browser globals
27        root.daterangepicker = factory(root.moment, root.jQuery);
28    }
29}(this, function (moment, $) {
30    var DateRangePicker = function (element, options, cb) {
31
32        //default settings for options
33        // If there is parentEl options we set it
34        // Otherwise we check if inline options is set and we set the element.parent() by default or the body for a tootlip picker
35        this.parentEl = (options && options.parentEl && $(options.parentEl).length) ? $(options.parentEl) :
36          (options && options.inline) ? element.parent() : $('body');
37        this.element = $(element);
38        this.startDate = moment().startOf('day');
39        this.endDate = moment().endOf('day');
40        this.minDate = false;
41        this.maxDate = false;
42        this.dateLimit = false;
43        this.autoApply = false;
44        this.singleDatePicker = false;
45        this.showDropdowns = false;
46        this.showWeekNumbers = false;
47        this.showISOWeekNumbers = false;
48        this.showCustomRangeLabel = true;
49        this.timePicker = false;
50        this.timePicker24Hour = false;
vendor: 12,890 bytes, lines 51-370
51        this.timePickerIncrement = 1;
52        this.timePickerSeconds = false;
53        this.linkedCalendars = true;
54        this.autoUpdateInput = true;
55        this.alwaysShowCalendars = false;
56        this.inline = false;
57        this.ranges = {};
58
59        this.opens = 'right';
60        if (this.element.hasClass('pull-right'))
61            this.opens = 'left';
62
63        this.drops = 'down';
64        if (this.element.hasClass('dropup'))
65            this.drops = 'up';
66
67        this.buttonClasses = 'btn btn-sm';
68        this.applyClass = 'btn-success';
69        this.cancelClass = 'btn-default';
70
71        this.locale = {
72            direction: 'ltr',
73            format: 'MM/DD/YYYY',
74            separator: ' - ',
75            applyLabel: 'Apply',
76            cancelLabel: 'Cancel',
77            weekLabel: 'W',
78            customRangeLabel: 'Custom Range',
79            daysOfWeek: moment.weekdaysMin(),
80            monthNames: moment.monthsShort(),
81            firstDay: moment.localeData().firstDayOfWeek()
82        };
83
84        this.callback = function () { };
85
86        //some state information
87        this.isShowing = false;
88        this.leftCalendar = {};
89        this.rightCalendar = {};
90
91        //custom options from user
92        if (typeof options !== 'object' || options === null)
93            options = {};
94
95        //allow setting options with data attributes
96        //data-api options will be overwritten with custom javascript options
97        options = $.extend(this.element.data(), options);
98
99        //
100        // handle all the possible options overriding defaults
101        //
102
103        if (typeof options.locale === 'object') {
104
105            if (typeof options.locale.direction === 'string')
106                this.locale.direction = options.locale.direction;
107
108            if (typeof options.locale.format === 'string')
109                this.locale.format = options.locale.format;
110
111            if (typeof options.locale.separator === 'string')
112                this.locale.separator = options.locale.separator;
113
114            if (typeof options.locale.daysOfWeek === 'object')
115                this.locale.daysOfWeek = options.locale.daysOfWeek.slice();
116
117            if (typeof options.locale.monthNames === 'object')
118                this.locale.monthNames = options.locale.monthNames.slice();
119
120            if (typeof options.locale.firstDay === 'number')
121                this.locale.firstDay = options.locale.firstDay;
122
123            if (typeof options.locale.applyLabel === 'string')
124                this.locale.applyLabel = options.locale.applyLabel;
125
126            if (typeof options.locale.cancelLabel === 'string')
127                this.locale.cancelLabel = options.locale.cancelLabel;
128
129            if (typeof options.locale.weekLabel === 'string')
130                this.locale.weekLabel = options.locale.weekLabel;
131
132            if (typeof options.locale.customRangeLabel === 'string')
133                this.locale.customRangeLabel = options.locale.customRangeLabel;
134
135        }
136
137        if (typeof options.startDate === 'string')
138            this.startDate = moment(options.startDate, this.locale.format);
139
140        if (typeof options.endDate === 'string')
141            this.endDate = moment(options.endDate, this.locale.format);
142
143        if (typeof options.minDate === 'string')
144            this.minDate = moment(options.minDate, this.locale.format);
145
146        if (typeof options.maxDate === 'string')
147            this.maxDate = moment(options.maxDate, this.locale.format);
148
149        if (typeof options.startDate === 'object')
150            this.startDate = moment(options.startDate);
151
152        if (typeof options.endDate === 'object')
153            this.endDate = moment(options.endDate);
154
155        if (typeof options.minDate === 'object')
156            this.minDate = moment(options.minDate);
157
158        if (typeof options.maxDate === 'object')
159            this.maxDate = moment(options.maxDate);
160
161        // sanity check for bad options
162        if (this.minDate && this.startDate.isBefore(this.minDate))
163            this.startDate = this.minDate.clone();
164
165        // sanity check for bad options
166        if (this.maxDate && this.endDate.isAfter(this.maxDate))
167            this.endDate = this.maxDate.clone();
168
169        if (typeof options.applyClass === 'string')
170            this.applyClass = options.applyClass;
171
172        if (typeof options.cancelClass === 'string')
173            this.cancelClass = options.cancelClass;
174
175        if (typeof options.dateLimit === 'object')
176            this.dateLimit = options.dateLimit;
177
178        if (typeof options.opens === 'string')
179            this.opens = options.opens;
180
181        if (typeof options.drops === 'string')
182            this.drops = options.drops;
183
184        if (typeof options.showWeekNumbers === 'boolean')
185            this.showWeekNumbers = options.showWeekNumbers;
186
187        if (typeof options.showISOWeekNumbers === 'boolean')
188            this.showISOWeekNumbers = options.showISOWeekNumbers;
189
190        if (typeof options.buttonClasses === 'string')
191            this.buttonClasses = options.buttonClasses;
192
193        if (typeof options.buttonClasses === 'object')
194            this.buttonClasses = options.buttonClasses.join(' ');
195
196        if (typeof options.showDropdowns === 'boolean')
197            this.showDropdowns = options.showDropdowns;
198
199        if (typeof options.showCustomRangeLabel === 'boolean')
200            this.showCustomRangeLabel = options.showCustomRangeLabel;
201
202        if (typeof options.singleDatePicker === 'boolean') {
203            this.singleDatePicker = options.singleDatePicker;
204            if (this.singleDatePicker)
205                this.endDate = this.startDate.clone();
206        }
207
208        if (typeof options.timePicker === 'boolean')
209            this.timePicker = options.timePicker;
210
211        if (typeof options.timePickerSeconds === 'boolean')
212            this.timePickerSeconds = options.timePickerSeconds;
213
214        if (typeof options.timePickerIncrement === 'number')
215            this.timePickerIncrement = options.timePickerIncrement;
216
217        if (typeof options.timePicker24Hour === 'boolean')
218            this.timePicker24Hour = options.timePicker24Hour;
219
220        if (typeof options.autoApply === 'boolean')
221            this.autoApply = options.autoApply;
222
223        if (typeof options.autoUpdateInput === 'boolean')
224            this.autoUpdateInput = options.autoUpdateInput;
225
226        if (typeof options.linkedCalendars === 'boolean')
227            this.linkedCalendars = options.linkedCalendars;
228
229        if (typeof options.isInvalidDate === 'function')
230            this.isInvalidDate = options.isInvalidDate;
231
232        if (typeof options.isCustomDate === 'function')
233            this.isCustomDate = options.isCustomDate;
234
235        if (typeof options.alwaysShowCalendars === 'boolean')
236            this.alwaysShowCalendars = options.alwaysShowCalendars;
237
238        if (typeof options.inline === 'boolean')
239            this.inline = options.inline;
240
241        // update day names order to firstDay
242        if (this.locale.firstDay != 0) {
243            var iterator = this.locale.firstDay;
244            while (iterator > 0) {
245                this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());
246                iterator--;
247            }
248        }
249
250        //html template for the picker UI
251        if (typeof options.template !== 'string' && !(options.template instanceof $))
252            options.template = '<div class="daterangepicker ' + (this.inline ? 'daterangepicker-inline' : 'daterangepicker-tooltip dropdown-menu') + '">' +
253                '<div class="calendar left">' +
254                    '<div class="daterangepicker_input">' +
255                      '<input class="input-mini form-control" type="text" name="daterangepicker_start" value="" />' +
256                      '<i class="fa fa-calendar glyphicon glyphicon-calendar"></i>' +
257                      '<div class="calendar-time">' +
258                        '<div></div>' +
259                        '<i class="fa fa-clock-o glyphicon glyphicon-time"></i>' +
260                      '</div>' +
261                    '</div>' +
262                    '<div class="calendar-table"></div>' +
263                '</div>' +
264                '<div class="calendar right">' +
265                    '<div class="daterangepicker_input">' +
266                      '<input class="input-mini form-control" type="text" name="daterangepicker_end" value="" />' +
267                      '<i class="fa fa-calendar glyphicon glyphicon-calendar"></i>' +
268                      '<div class="calendar-time">' +
269                        '<div></div>' +
270                        '<i class="fa fa-clock-o glyphicon glyphicon-time"></i>' +
271                      '</div>' +
272                    '</div>' +
273                    '<div class="calendar-table"></div>' +
274                '</div>' +
275                '<div class="ranges">' +
276                    '<div class="range_inputs">' +
277                      '<button class="applyBtn" disabled="disabled" type="button"></button>' +
278                      '<button class="cancelBtn" type="button"></button>' +
279                    '</div>' +
280                '</div>' +
281            '</div>';
282
283        this.container = $(options.template).appendTo(this.parentEl);
284        this.container.addClass(this.locale.direction);
285
286        var start, end, range;
287
288        //if no start/end dates set, check if an input element contains initial values
289        if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {
290            if ($(this.element).is('input[type=text]')) {
291                var val = $(this.element).val(),
292                    split = val.split(this.locale.separator);
293
294                start = end = null;
295
296                if (split.length == 2) {
297                    start = moment(split[0], this.locale.format);
298                    end = moment(split[1], this.locale.format);
299                } else if (this.singleDatePicker && val !== "") {
300                    start = moment(val, this.locale.format);
301                    end = moment(val, this.locale.format);
302                }
303                if (start !== null && end !== null) {
304                    this.setStartDate(start);
305                    this.setEndDate(end);
306                }
307            }
308        }
309
310        if (typeof options.ranges === 'object') {
311            for (range in options.ranges) {
312
313                if (typeof options.ranges[range][0] === 'string')
314                    start = moment(options.ranges[range][0], this.locale.format);
315                else
316                    start = moment(options.ranges[range][0]);
317
318                if (typeof options.ranges[range][1] === 'string')
319                    end = moment(options.ranges[range][1], this.locale.format);
320                else
321                    end = moment(options.ranges[range][1]);
322
323                // If the start or end date exceed those allowed by the minDate or dateLimit
324                // options, shorten the range to the allowable period.
325                if (this.minDate && start.isBefore(this.minDate))
326                    start = this.minDate.clone();
327
328                var maxDate = this.maxDate;
329                if (this.dateLimit && maxDate && start.clone().add(this.dateLimit).isAfter(maxDate))
330                    maxDate = start.clone().add(this.dateLimit);
331                if (maxDate && end.isAfter(maxDate))
332                    end = maxDate.clone();
333
334                // If the end of the range is before the minimum or the start of the range is
335                // after the maximum, don't display this range option at all.
336                if ((this.minDate && end.isBefore(this.minDate, this.timepicker ? 'minute' : 'day'))
337                  || (maxDate && start.isAfter(maxDate, this.timepicker ? 'minute' : 'day')))
338                    continue;
339
340                //Support unicode chars in the range names.
341                var elem = document.createElement('textarea');
342                elem.innerHTML = range;
343                var rangeHtml = elem.value;
344
345                this.ranges[rangeHtml] = [start, end];
346            }
347
348            var list = '<ul>';
349            for (range in this.ranges) {
350                list += '<li data-range-key="' + range + '">' + range + '</li>';
351            }
352            if (this.showCustomRangeLabel) {
353                list += '<li data-range-key="' + this.locale.customRangeLabel + '">' + this.locale.customRangeLabel + '</li>';
354            }
355            list += '</ul>';
356            this.container.find('.ranges').prepend(list);
357        }
358
359        if (typeof cb === 'function') {
360            this.callback = cb;
361        }
362
363        if (!this.timePicker) {
364            this.startDate = this.startDate.startOf('day');
365            this.endDate = this.endDate.endOf('day');
366            this.container.find('.calendar-time').hide();
367        }
368
369        // can't be used together for now
370        // You can only use it with inline option
371        if (this.timePicker && this.autoApply && !this.inline)
372            this.autoApply = false;
373
374        if (this.autoApply && typeof options.ranges !== 'object') {
375            this.container.find('.ranges').hide();
376        } else if (this.autoApply) {
377            this.container.find('.applyBtn, .cancelBtn').addClass('hide');
378        }
379
380        if (this.singleDatePicker) {
381            this.container.addClass('single');
382            this.container.find('.calendar.left').addClass('single');
383            this.container.find('.calendar.left').show();
384            this.container.find('.calendar.right').hide();
385            this.container.find('.daterangepicker_input input, .daterangepicker_input > i').hide();
386            if (this.timePicker) {
387                this.container.find('.ranges ul').hide();
388            } else {
389                this.container.find('.ranges').hide();
390            }
391        }
392
393        if ((typeof options.ranges === 'undefined' && !this.singleDatePicker) || this.alwaysShowCalendars) {
394            this.container.addClass('show-calendar');
395        }
396
397        this.container.addClass('opens' + this.opens);
398
399        //swap the position of the predefined ranges if opens right
400        if (typeof options.ranges !== 'undefined' && this.opens == 'right') {
401            this.container.find('.ranges').prependTo(this.container.find('.calendar.left').parent());
402        }
403
404        //apply CSS classes and labels to buttons
405        this.container.find('.applyBtn, .cancelBtn').addClass(this.buttonClasses);
406        if (this.applyClass.length)
407            this.container.find('.applyBtn').addClass(this.applyClass);
408        if (this.cancelClass.length)
409            this.container.find('.cancelBtn').addClass(this.cancelClass);
410        this.container.find('.applyBtn').html(this.locale.applyLabel);
411        this.container.find('.cancelBtn').html(this.locale.cancelLabel);
412
413        //
414        // event listeners
415        //
416
417        this.container.find('.calendar')
418            .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))
419            .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))
420            .on('click.daterangepicker', '.available', $.proxy(this.clickDate, this))
421            .on('click.daterangepicker', '.available', $.proxy(this.hoverDate, this))
422            .on('click.daterangepicker', '.available', $.proxy(this.updateFormInputs, this))
423            .on('change.daterangepicker', 'select.yearselect', $.proxy(this.monthOrYearChanged, this))
424            .on('change.daterangepicker', 'select.monthselect', $.proxy(this.monthOrYearChanged, this))
425            .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.secondselect,select.ampmselect', $.proxy(this.timeChanged, this))
426            .on('click.daterangepicker', '.daterangepicker_input input', $.proxy(this.showCalendars, this))
427            .on('focus.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsFocused, this))
428            .on('blur.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsBlurred, this))
429            .on('change.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsChanged, this));
430
431        this.container.find('.ranges')
432            .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))
433            .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))
434            .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))
435            .on('click.daterangepicker', 'li', $.proxy(this.hoverRange, this))
436            .on('click.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));
437
438        if (this.element.is('input') || this.element.is('button')) {
439            this.element.on({
440                'click.daterangepicker': $.proxy(this.show, this),
441                'focus.daterangepicker': $.proxy(this.show, this),
442                'keyup.daterangepicker': $.proxy(this.elementChanged, this),
443                'keydown.daterangepicker': $.proxy(this.keydown, this)
444            });
445        } else {
446            this.element.on('click.daterangepicker', $.proxy(this.toggle, this));
447        }
448
449        //
450        // if attached to a text input, set the initial value
451        //
452
453        if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) {
454            this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
455            this.element.trigger('change');
456        } else if (this.element.is('input') && this.autoUpdateInput) {
457            this.element.val(this.startDate.format(this.locale.format));
458            this.element.trigger('change');
459        }
460
461        // Show the daterangepicker since it's started for inline mode
vendor: 21,856 bytes, lines 462-956
462        if (this.inline)
463            this.show()
464    };
465
466    DateRangePicker.prototype = {
467
468        constructor: DateRangePicker,
469
470        setStartDate: function (startDate) {
471            if (typeof startDate === 'string')
472                this.startDate = moment(startDate, this.locale.format);
473
474            if (typeof startDate === 'object')
475                this.startDate = moment(startDate);
476
477            if (!this.timePicker)
478                this.startDate = this.startDate.startOf('day');
479
480            if (this.timePicker && this.timePickerIncrement)
481                this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
482
483            if (this.minDate && this.startDate.isBefore(this.minDate)) {
484                this.startDate = this.minDate;
485                if (this.timePicker && this.timePickerIncrement)
486                    this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
487            }
488
489            if (this.maxDate && this.startDate.isAfter(this.maxDate)) {
490                this.startDate = this.maxDate;
491                if (this.timePicker && this.timePickerIncrement)
492                    this.startDate.minute(Math.floor(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
493            }
494
495            if (!this.isShowing)
496                this.updateElement();
497
498            this.updateMonthsInView();
499        },
500
501        setEndDate: function (endDate) {
502            if (typeof endDate === 'string')
503                this.endDate = moment(endDate, this.locale.format);
504
505            if (typeof endDate === 'object')
506                this.endDate = moment(endDate);
507
508            if (!this.timePicker)
509                this.endDate = this.endDate.endOf('day');
510
511            if (this.timePicker && this.timePickerIncrement)
512                this.endDate.minute(Math.round(this.endDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
513
514            if (this.endDate.isBefore(this.startDate))
515                this.endDate = this.startDate.clone();
516
517            if (this.maxDate && this.endDate.isAfter(this.maxDate))
518                this.endDate = this.maxDate;
519
520            if (this.dateLimit && this.startDate.clone().add(this.dateLimit).isBefore(this.endDate))
521                this.endDate = this.startDate.clone().add(this.dateLimit);
522
523            this.previousRightTime = this.endDate.clone();
524
525            if (!this.isShowing)
526                this.updateElement();
527
528            this.updateMonthsInView();
529        },
530
531        isInvalidDate: function () {
532            return false;
533        },
534
535        isCustomDate: function () {
536            return false;
537        },
538
539        updateView: function () {
540            if (this.timePicker) {
541                this.renderTimePicker('left');
542                this.renderTimePicker('right');
543                if (!this.endDate) {
544                    this.container.find('.right .calendar-time select').attr('disabled', 'disabled').addClass('disabled');
545                } else {
546                    this.container.find('.right .calendar-time select').removeAttr('disabled').removeClass('disabled');
547                }
548            }
549            if (this.endDate) {
550                this.container.find('input[name="daterangepicker_end"]').removeClass('active');
551                this.container.find('input[name="daterangepicker_start"]').addClass('active');
552            } else {
553                this.container.find('input[name="daterangepicker_end"]').addClass('active');
554                this.container.find('input[name="daterangepicker_start"]').removeClass('active');
555            }
556            this.updateMonthsInView();
557            this.updateCalendars();
558            this.updateFormInputs();
559        },
560
561        updateMonthsInView: function () {
562            if (this.endDate) {
563
564                //if both dates are visible already, do nothing
565                if (!this.singleDatePicker && this.leftCalendar.month && this.rightCalendar.month &&
566                    (this.startDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.startDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM'))
567                    &&
568                    (this.endDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.endDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM'))
569                    ) {
570                    return;
571                }
572
573                this.leftCalendar.month = this.startDate.clone().date(2);
574                if (!this.linkedCalendars && (this.endDate.month() != this.startDate.month() || this.endDate.year() != this.startDate.year())) {
575                    this.rightCalendar.month = this.endDate.clone().date(2);
576                } else {
577                    this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month');
578                }
579
580            } else {
581                if (this.leftCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM') && this.rightCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM')) {
582                    this.leftCalendar.month = this.startDate.clone().date(2);
583                    this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month');
584                }
585            }
586            if (this.maxDate && this.linkedCalendars && !this.singleDatePicker && this.rightCalendar.month > this.maxDate) {
587                this.rightCalendar.month = this.maxDate.clone().date(2);
588                this.leftCalendar.month = this.maxDate.clone().date(2).subtract(1, 'month');
589            }
590        },
591
592        updateCalendars: function () {
593
594            if (this.timePicker) {
595                var hour, minute, second;
596                if (this.endDate) {
597                    hour = parseInt(this.container.find('.left .hourselect').val(), 10);
598                    minute = parseInt(this.container.find('.left .minuteselect').val(), 10);
599                    second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;
600                    if (!this.timePicker24Hour) {
601                        var ampm = this.container.find('.left .ampmselect').val();
602                        if (ampm === 'PM' && hour < 12)
603                            hour += 12;
604                        if (ampm === 'AM' && hour === 12)
605                            hour = 0;
606                    }
607                } else {
608                    hour = parseInt(this.container.find('.right .hourselect').val(), 10);
609                    minute = parseInt(this.container.find('.right .minuteselect').val(), 10);
610                    second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;
611                    if (!this.timePicker24Hour) {
612                        var ampm = this.container.find('.right .ampmselect').val();
613                        if (ampm === 'PM' && hour < 12)
614                            hour += 12;
615                        if (ampm === 'AM' && hour === 12)
616                            hour = 0;
617                    }
618                }
619                this.leftCalendar.month.hour(hour).minute(minute).second(second);
620                this.rightCalendar.month.hour(hour).minute(minute).second(second);
621            }
622
623            this.renderCalendar('left');
624            this.renderCalendar('right');
625
626            //highlight any predefined range matching the current start and end dates
627            this.container.find('.ranges li').removeClass('active');
628            if (this.endDate == null) return;
629
630            this.calculateChosenLabel();
631        },
632
633        renderCalendar: function (side) {
634
635            //
636            // Build the matrix of dates that will populate the calendar
637            //
638
639            var calendar = side == 'left' ? this.leftCalendar : this.rightCalendar;
640            var month = calendar.month.month();
641            var year = calendar.month.year();
642            var hour = calendar.month.hour();
643            var minute = calendar.month.minute();
644            var second = calendar.month.second();
645            var daysInMonth = moment([year, month]).daysInMonth();
646            var firstDay = moment([year, month, 1]);
647            var lastDay = moment([year, month, daysInMonth]);
648            var lastMonth = moment(firstDay).subtract(1, 'month').month();
649            var lastYear = moment(firstDay).subtract(1, 'month').year();
650            var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();
651            var dayOfWeek = firstDay.day();
652
653            //initialize a 6 rows x 7 columns array for the calendar
654            var calendar = [];
655            calendar.firstDay = firstDay;
656            calendar.lastDay = lastDay;
657
658            for (var i = 0; i < 6; i++) {
659                calendar[i] = [];
660            }
661
662            //populate the calendar with date objects
663            var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;
664            if (startDay > daysInLastMonth)
665                startDay -= 7;
666
667            if (dayOfWeek == this.locale.firstDay)
668                startDay = daysInLastMonth - 6;
669
670            var curDate = moment([lastYear, lastMonth, startDay, 12, minute, second]);
671
672            var col, row;
673            for (var i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add(24, 'hour')) {
674                if (i > 0 && col % 7 === 0) {
675                    col = 0;
676                    row++;
677                }
678                calendar[row][col] = curDate.clone().hour(hour).minute(minute).second(second);
679                curDate.hour(12);
680
681                if (this.minDate && calendar[row][col].format('YYYY-MM-DD') == this.minDate.format('YYYY-MM-DD') && calendar[row][col].isBefore(this.minDate) && side == 'left') {
682                    calendar[row][col] = this.minDate.clone();
683                }
684
685                if (this.maxDate && calendar[row][col].format('YYYY-MM-DD') == this.maxDate.format('YYYY-MM-DD') && calendar[row][col].isAfter(this.maxDate) && side == 'right') {
686                    calendar[row][col] = this.maxDate.clone();
687                }
688
689            }
690
691            //make the calendar object available to hoverDate/clickDate
692            if (side == 'left') {
693                this.leftCalendar.calendar = calendar;
694            } else {
695                this.rightCalendar.calendar = calendar;
696            }
697
698            //
699            // Display the calendar
700            //
701
702            var minDate = side == 'left' ? this.minDate : this.startDate;
703            var maxDate = this.maxDate;
704            var selected = side == 'left' ? this.startDate : this.endDate;
705            var arrow = this.locale.direction == 'ltr' ? { left: 'chevron-left', right: 'chevron-right' } : { left: 'chevron-right', right: 'chevron-left' };
706
707            var html = '<table class="table-condensed">';
708            html += '<thead>';
709            html += '<tr>';
710
711            // add empty cell for week number
712            if (this.showWeekNumbers || this.showISOWeekNumbers)
713                html += '<th></th>';
714
715            if ((!minDate || minDate.isBefore(calendar.firstDay)) && (!this.linkedCalendars || side == 'left')) {
716                html += '<th class="prev available"><i class="fa fa-' + arrow.left + ' glyphicon glyphicon-' + arrow.left + '"></i></th>';
717            } else {
718                html += '<th></th>';
719            }
720
721            //var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY");
722			var dateHtml = calendar[1][1].format(" YYYY") + "년 " + this.locale.monthNames[calendar[1][1].month()];
723			
724            if (this.showDropdowns) {
725                var currentMonth = calendar[1][1].month();
726                var currentYear = calendar[1][1].year();
727                var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);
728                var minYear = (minDate && minDate.year()) || (currentYear - 50);
729                var inMinYear = currentYear == minYear;
730                var inMaxYear = currentYear == maxYear;
731
732                var monthHtml = '<select class="monthselect">';
733                for (var m = 0; m < 12; m++) {
734                    if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) {
735                        monthHtml += "<option value='" + m + "'" +
736                            (m === currentMonth ? " selected='selected'" : "") +
737                            ">" + this.locale.monthNames[m] + "</option>";
738                    } else {
739                        monthHtml += "<option value='" + m + "'" +
740                            (m === currentMonth ? " selected='selected'" : "") +
741                            " disabled='disabled'>" + this.locale.monthNames[m] + "</option>";
742                    }
743                }
744                monthHtml += "</select>";
745
746                var yearHtml = '<select class="yearselect">';
747                for (var y = minYear; y <= maxYear; y++) {
748                    yearHtml += '<option value="' + y + '"' +
749                        (y === currentYear ? ' selected="selected"' : '') +
750                        '>' + y + '</option>';
751                }
752                yearHtml += '</select>';
753
754                dateHtml = monthHtml + yearHtml;
755            }
756
757            html += '<th colspan="5" class="month">' + dateHtml + '</th>';
758            if ((!maxDate || maxDate.isAfter(calendar.lastDay)) && (!this.linkedCalendars || side == 'right' || this.singleDatePicker)) {
759                html += '<th class="next available"><i class="fa fa-' + arrow.right + ' glyphicon glyphicon-' + arrow.right + '"></i></th>';
760            } else {
761                html += '<th></th>';
762            }
763
764            html += '</tr>';
765            html += '<tr>';
766
767            // add week number label
768            if (this.showWeekNumbers || this.showISOWeekNumbers)
769                html += '<th class="week">' + this.locale.weekLabel + '</th>';
770
771            $.each(this.locale.daysOfWeek, function (index, dayOfWeek) {
772                html += '<th>' + dayOfWeek + '</th>';
773            });
774
775            html += '</tr>';
776            html += '</thead>';
777            html += '<tbody>';
778
779            //adjust maxDate to reflect the dateLimit setting in order to
780            //grey out end dates beyond the dateLimit
781            if (this.endDate == null && this.dateLimit) {
782                var maxLimit = this.startDate.clone().add(this.dateLimit).endOf('day');
783                if (!maxDate || maxLimit.isBefore(maxDate)) {
784                    maxDate = maxLimit;
785                }
786            }
787
788            for (var row = 0; row < 6; row++) {
789                html += '<tr>';
790
791                // add week number
792                if (this.showWeekNumbers)
793                    html += '<td class="week">' + calendar[row][0].week() + '</td>';
794                else if (this.showISOWeekNumbers)
795                    html += '<td class="week">' + calendar[row][0].isoWeek() + '</td>';
796
797                for (var col = 0; col < 7; col++) {
798
799                    var classes = [];
800
801                    //highlight today's date
802                    if (calendar[row][col].isSame(new Date(), "day"))
803                        classes.push('today');
804
805                    //highlight weekends
806                    if (calendar[row][col].isoWeekday() > 5)
807                        classes.push('weekend');
808
809                    //grey out the dates in other months displayed at beginning and end of this calendar
810                    if (calendar[row][col].month() != calendar[1][1].month())
811                        classes.push('off');
812
813                    //don't allow selection of dates before the minimum date
814                    if (this.minDate && calendar[row][col].isBefore(this.minDate, 'day'))
815                        classes.push('off', 'disabled');
816
817                    //don't allow selection of dates after the maximum date
818                    if (maxDate && calendar[row][col].isAfter(maxDate, 'day'))
819                        classes.push('off', 'disabled');
820
821                    //don't allow selection of date if a custom function decides it's invalid
822                    if (this.isInvalidDate(calendar[row][col]))
823                        classes.push('off', 'disabled');
824
825                    //highlight the currently selected start date
826                    if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD'))
827                        
828                        classes.push('active', 'start-date');
829
830                    //highlight the currently selected end date
831                    if (this.endDate != null && calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD'))
832                        classes.push('active', 'end-date');
833
834                    //highlight dates in-between the selected dates
835                    if (this.endDate != null && calendar[row][col] > this.startDate && calendar[row][col] < this.endDate)
836                        classes.push('in-range');
837
838                    //apply custom classes for this date
839                    var isCustom = this.isCustomDate(calendar[row][col]);
840                    if (isCustom !== false) {
841                        if (typeof isCustom === 'string')
842                            classes.push(isCustom);
843                        else
844                            Array.prototype.push.apply(classes, isCustom);
845                    }
846
847                    var cname = '', disabled = false;
848                    for (var i = 0; i < classes.length; i++) {
849                        cname += classes[i] + ' ';
850                        if (classes[i] == 'disabled')
851                            disabled = true;
852                    }
853                    if (!disabled)
854                        cname += 'available';
855
856					
857                    html += '<td class="' + cname.replace(/^\s+|\s+$/g, '') + '"><span class="' + cname.replace(/^\s+|\s+$/g, '') + '" data-title="' + 'r' + row + 'c' + col + '">' + calendar[row][col].date() + '</span></td>';
858
859                }
860                html += '</tr>';
861            }
862
863            html += '</tbody>';
864            html += '</table>';
865
866            this.container.find('.calendar.' + side + ' .calendar-table').html(html);
867
868        },
869
870        renderTimePicker: function (side) {
871
872            // Don't bother updating the time picker if it's currently disabled
873            // because an end date hasn't been clicked yet
874            if (side == 'right' && !this.endDate) return;
875
876            var html, selected, minDate, maxDate = this.maxDate;
877
878            if (this.dateLimit && (!this.maxDate || this.startDate.clone().add(this.dateLimit).isAfter(this.maxDate)))
879                maxDate = this.startDate.clone().add(this.dateLimit);
880
881            if (side == 'left') {
882                selected = this.startDate.clone();
883                minDate = this.minDate;
884            } else if (side == 'right') {
885                selected = this.endDate.clone();
886                minDate = this.startDate;
887
888                //Preserve the time already selected
889                var timeSelector = this.container.find('.calendar.right .calendar-time div');
890                if (!this.endDate && timeSelector.html() != '') {
891
892                    selected.hour(timeSelector.find('.hourselect option:selected').val() || selected.hour());
893                    selected.minute(timeSelector.find('.minuteselect option:selected').val() || selected.minute());
894                    selected.second(timeSelector.find('.secondselect option:selected').val() || selected.second());
895
896                    if (!this.timePicker24Hour) {
897                        var ampm = timeSelector.find('.ampmselect option:selected').val();
898                        if (ampm === 'PM' && selected.hour() < 12)
899                            selected.hour(selected.hour() + 12);
900                        if (ampm === 'AM' && selected.hour() === 12)
901                            selected.hour(0);
902                    }
903
904                }
905
906                if (selected.isBefore(this.startDate))
907                    selected = this.startDate.clone();
908
909                if (maxDate && selected.isAfter(maxDate))
910                    selected = maxDate.clone();
911
912            }
913
914            //
915            // hours
916            //
917
918            html = '<select class="hourselect">';
919
920            var start = this.timePicker24Hour ? 0 : 1;
921            var end = this.timePicker24Hour ? 23 : 12;
922
923            for (var i = start; i <= end; i++) {
924                var i_in_24 = i;
925                if (!this.timePicker24Hour)
926                    i_in_24 = selected.hour() >= 12 ? (i == 12 ? 12 : i + 12) : (i == 12 ? 0 : i);
927
928                var time = selected.clone().hour(i_in_24);
929                var disabled = false;
930                if (minDate && time.minute(59).isBefore(minDate))
931                    disabled = true;
932                if (maxDate && time.minute(0).isAfter(maxDate))
933                    disabled = true;
934
935                if (i_in_24 == selected.hour() && !disabled) {
936                    html += '<option value="' + i + '" selected="selected">' + i + '</option>';
937                } else if (disabled) {
938                    html += '<option value="' + i + '" disabled="disabled" class="disabled">' + i + '</option>';
939                } else {
940                    html += '<option value="' + i + '">' + i + '</option>';
941                }
942            }
943
944            html += '</select> ';
945
946            //
947            // minutes
948            //
949
950            html += ': <select class="minuteselect">';
951
952            for (var i = 0; i < 60; i += this.timePickerIncrement) {
953                var padded = i < 10 ? '0' + i : i;
954                var time = selected.clone().minute(i);
955
956                var disabled = false;
957                if (minDate && time.second(59).isBefore(minDate))
958                    disabled = true;
959                if (maxDate && time.second(0).isAfter(maxDate))
960                    disabled = true;
961
962                if (selected.minute() == i && !disabled) {
963                    html += '<option value="' + i + '" selected="selected">' + padded + '</option>';
964                } else if (disabled) {
965                    html += '<option value="' + i + '" disabled="disabled" class="disabled">' + padded + '</option>';
966                } else {
967                    html += '<option value="' + i + '">' + padded + '</option>';
968                }
969            }
970
971            html += '</select> ';
972
973            //
974            // seconds
975            //
976
977            if (this.timePickerSeconds) {
978                html += ': <select class="secondselect">';
979
980                for (var i = 0; i < 60; i++) {
981                    var padded = i < 10 ? '0' + i : i;
982                    var time = selected.clone().second(i);
983
984                    var disabled = false;
985                    if (minDate && time.isBefore(minDate))
986                        disabled = true;
987                    if (maxDate && time.isAfter(maxDate))
988                        disabled = true;
989
990                    if (selected.second() == i && !disabled) {
991                        html += '<option value="' + i + '" selected="selected">' + padded + '</option>';
992                    } else if (disabled) {
993                        html += '<option value="' + i + '" disabled="disabled" class="disabled">' + padded + '</option>';
994                    } else {
995                        html += '<option value="' + i + '">' + padded + '</option>';
996                    }
997                }
998
999                html += '</select> ';
1000            }
1001
1002            //
1003            // AM/PM
1004            //
1005
1006            if (!this.timePicker24Hour) {
1007                html += '<select class="ampmselect">';
1008
1009                var am_html = '';
1010                var pm_html = '';
1011
1012                if (minDate && selected.clone().hour(12).minute(0).second(0).isBefore(minDate))
1013                    am_html = ' disabled="disabled" class="disabled"';
1014
1015                if (maxDate && selected.clone().hour(0).minute(0).second(0).isAfter(maxDate))
1016                    pm_html = ' disabled="disabled" class="disabled"';
1017
1018                if (selected.hour() >= 12) {
1019                    html += '<option value="AM"' + am_html + '>AM</option><option value="PM" selected="selected"' + pm_html + '>PM</option>';
1020                } else {
1021                    html += '<option value="AM" selected="selected"' + am_html + '>AM</option><option value="PM"' + pm_html + '>PM</option>';
1022                }
1023
1024                html += '</select>';
1025            }
1026
1027            this.container.find('.calendar.' + side + ' .calendar-time div').html(html);
1028
1029        },
1030
1031        updateFormInputs: function () {
1032
1033            //ignore mouse movements while an above-calendar text input has focus
1034            if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
1035                return;
1036
1037            this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.locale.format));
1038            if (this.endDate)
1039                this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.locale.format));
1040
1041            if (this.singleDatePicker || (this.endDate && (this.startDate.isBefore(this.endDate) || this.startDate.isSame(this.endDate)))) {
1042                this.container.find('button.applyBtn').removeAttr('disabled');
1043            } else {
1044                this.container.find('button.applyBtn').attr('disabled', 'disabled');
1045            }
1046
1047        },
1048
1049        move: function () {
1050            // Should not move if it's inline mode
1051            if (this.inline)
1052                return;
1053
1054            var parentOffset = { top: 0, left: 0 },
1055                containerTop;
1056            var parentRightEdge = $(window).width();
1057            if (!this.parentEl.is('body')) {
1058                parentOffset = {
1059                    top: this.parentEl.offset().top - this.parentEl.scrollTop(),
1060                    left: this.parentEl.offset().left - this.parentEl.scrollLeft()
1061                };
1062                parentRightEdge = this.parentEl[0].clientWidth + this.parentEl.offset().left;
1063            }
1064
1065            if (this.drops == 'up')
1066                containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top;
1067            else
1068                containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top;
1069            this.container[this.drops == 'up' ? 'addClass' : 'removeClass']('dropup');
1070
1071            if (this.opens == 'left') {
1072                this.container.css({
1073                    top: containerTop,
1074                    right: parentRightEdge - this.element.offset().left - this.element.outerWidth(),
1075                    left: 'auto'
1076                });
1077                if (this.container.offset().left < 0) {
1078                    this.container.css({
1079                        right: 'auto',
1080                        left: 9
1081                    });
1082                }
1083            } else if (this.opens == 'center') {
1084                this.container.css({
1085                    top: containerTop,
1086                    left: this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2
1087                            - this.container.outerWidth() / 2,
1088                    right: 'auto'
1089                });
1090                if (this.container.offset().left < 0) {
1091                    this.container.css({
1092                        right: 'auto',
1093                        left: 9
1094                    });
1095                }
1096            } else {
1097                this.container.css({
1098                    top: containerTop,
1099                    left: this.element.offset().left - parentOffset.left,
1100                    right: 'auto'
1101                });
1102                if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {
1103                    this.container.css({
1104                        left: 'auto',
1105                        right: 0
1106                    });
1107                }
1108            }
1109        },
1110
1111        show: function (e) {
1112            if (this.isShowing) return;
1113
1114            // Create a click proxy that is private to this instance of datepicker, for unbinding
1115            this._outsideClickProxy = $.proxy(function (e) { this.outsideClick(e); }, this);
1116
1117            // Bind global datepicker mousedown for hiding and
1118            $(document)
1119              .on('mousedown.daterangepicker', this._outsideClickProxy)
1120              // also support mobile devices
1121              .on('touchend.daterangepicker', this._outsideClickProxy)
1122              // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them
1123              .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)
1124              // and also close when focus changes to outside the picker (eg. tabbing between controls)
1125              .on('focusin.daterangepicker', this._outsideClickProxy);
1126
1127            // Reposition the picker if the window is resized while it's open
1128            $(window).on('resize.daterangepicker', $.proxy(function (e) { this.move(e); }, this));
1129
1130            this.oldStartDate = this.startDate.clone();
1131            this.oldEndDate = this.endDate.clone();
1132            this.previousRightTime = this.endDate.clone();
1133
1134            this.updateView();
1135            this.container.show();
1136            this.move();
1137            this.element.trigger('show.daterangepicker', this);
1138            this.isShowing = true;
1139        },
1140
1141        hide: function (e) {
1142            if (!this.isShowing) return;
1143
1144            //if picker is attached to a text input, update it
1145            this.updateElement();
1146
1147            $(document).off('.daterangepicker');
1148            $(window).off('.daterangepicker');
1149            this.container.hide();
1150            this.element.trigger('hide.daterangepicker', this);
1151            this.isShowing = false;
1152        },
1153
1154        toggle: function (e) {
1155            if (this.isShowing && !this.inline) {
1156                this.hide();
1157            } else {
1158                this.show();
1159            }
1160        },
1161
1162        outsideClick: function (e) {
1163            var target = $(e.target);
1164            // if the page is clicked anywhere except within the daterangerpicker/button
1165            // itself then call this.hide()
1166            if (
1167                // ie modal dialog fix
1168                e.type == "focusin" ||
1169                target.closest(this.element).length ||
1170                target.closest(this.container).length ||
1171                target.closest('.calendar-table').length ||
1172                this.inline
1173                ) return;
1174            this.hide();
1175            this.element.trigger('outsideClick.daterangepicker', this);
1176        },
1177
1178        showCalendars: function () {
1179            this.container.addClass('show-calendar');
1180            this.move();
1181            this.element.trigger('showCalendar.daterangepicker', this);
1182        },
1183
1184        hideCalendars: function () {
1185            this.container.removeClass('show-calendar');
1186            this.element.trigger('hideCalendar.daterangepicker', this);
1187        },
1188
1189        hoverRange: function (e) {
1190
1191            //ignore mouse movements while an above-calendar text input has focus
1192            if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
1193                return;
1194
1195            var label = e.target.getAttribute('data-range-key');
1196
1197            if (label == this.locale.customRangeLabel) {
1198                this.updateView();
1199            } else {
1200                var dates = this.ranges[label];
1201                this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.locale.format));
1202                this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.locale.format));
1203            }
1204
1205        },
1206
1207        clickRange: function (e) {
1208            var label = e.target.getAttribute('data-range-key');
1209            this.chosenLabel = label;
1210            if (label == this.locale.customRangeLabel) {
1211                this.showCalendars();
1212            } else {
1213                var dates = this.ranges[label];
1214                this.startDate = dates[0];
1215                this.endDate = dates[1];
1216
1217                if (!this.timePicker) {
1218                    this.startDate.startOf('day');
1219                    this.endDate.endOf('day');
1220                }
1221
1222                if (!this.alwaysShowCalendars)
1223                    this.hideCalendars();
1224                this.clickApply();
1225            }
1226        },
1227
1228        clickPrev: function (e) {
1229            var cal = $(e.target).parents('.calendar');
1230            if (cal.hasClass('left')) {
1231                this.leftCalendar.month.subtract(1, 'month');
1232                if (this.linkedCalendars)
1233                    this.rightCalendar.month.subtract(1, 'month');
1234            } else {
1235                this.rightCalendar.month.subtract(1, 'month');
1236            }
1237            this.updateCalendars();
1238        },
1239
1240        clickNext: function (e) {
1241            var cal = $(e.target).parents('.calendar');
1242            if (cal.hasClass('left')) {
1243                this.leftCalendar.month.add(1, 'month');
1244            } else {
1245                this.rightCalendar.month.add(1, 'month');
1246                if (this.linkedCalendars)
1247                    this.leftCalendar.month.add(1, 'month');
1248            }
1249            this.updateCalendars();
1250        },
1251
1252        hoverDate: function (e) {
1253
1254            //ignore mouse movements while an above-calendar text input has focus
1255            //if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
1256            //    return;
1257
1258            //ignore dates that can't be selected
1259            if (!$(e.target).hasClass('available')) return;
1260
1261            //have the text inputs above calendars reflect the date being hovered over
1262            var title = $(e.target).attr('data-title');
1263            var row = title.substr(1, 1);
1264            var col = title.substr(3, 1);
1265            var cal = $(e.target).parents('.calendar');
1266            var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
1267
1268            if (this.endDate && !this.container.find('input[name=daterangepicker_start]').is(":focus")) {
1269                this.container.find('input[name=daterangepicker_start]').val(date.format(this.locale.format));
1270            } else if (!this.endDate && !this.container.find('input[name=daterangepicker_end]').is(":focus")) {
1271                this.container.find('input[name=daterangepicker_end]').val(date.format(this.locale.format));
1272            }
1273
1274            //highlight the dates between the start date and the date being hovered as a potential end date
1275            var leftCalendar = this.leftCalendar;
1276            var rightCalendar = this.rightCalendar;
1277            var startDate = this.startDate;
1278            if (!this.endDate) {
1279                this.container.find('.calendar td').each(function (index, el) {
1280
1281                    //skip week numbers, only look at dates
1282                    if ($(el).hasClass('week')) return;
1283
1284                    var title = $(el).attr('data-title');
1285                    var row = title.substr(1, 1);
1286                    var col = title.substr(3, 1);
1287                    var cal = $(el).parents('.calendar');
1288                    var dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col];
1289
1290                    if ((dt.isAfter(startDate) && dt.isBefore(date)) || dt.isSame(date, 'day')) {
1291                        $(el).addClass('in-range');
1292                    } else {
1293                        $(el).removeClass('in-range');
1294                    }
1295
1296                });
1297            }
1298
1299        },
1300
1301        clickDate: function (e) {
1302
1303            if (!$(e.target).hasClass('available')) return;
1304
1305            var title = $(e.target).attr('data-title');
1306            var row = title.substr(1, 1);
1307            var col = title.substr(3, 1);
1308            var cal = $(e.target).parents('.calendar');
1309            var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
1310
1311            //
1312            // this function needs to do a few things:
1313            // * alternate between selecting a start and end date for the range,
1314            // * if the time picker is enabled, apply the hour/minute/second from the select boxes to the clicked date
1315            // * if autoapply is enabled, and an end date was chosen, apply the selection
1316            // * if single date picker mode, and time picker isn't enabled, apply the selection immediately
1317            // * if one of the inputs above the calendars was focused, cancel that manual input
1318            //
1319
1320            if (this.endDate || date.isBefore(this.startDate, 'day')) { //picking start
1321                if (this.timePicker) {
1322                    var hour = parseInt(this.container.find('.left .hourselect').val(), 10);
1323                    if (!this.timePicker24Hour) {
1324                        var ampm = this.container.find('.left .ampmselect').val();
1325                        if (ampm === 'PM' && hour < 12)
1326                            hour += 12;
1327                        if (ampm === 'AM' && hour === 12)
1328                            hour = 0;
1329                    }
1330                    var minute = parseInt(this.container.find('.left .minuteselect').val(), 10);
1331                    var second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0;
1332                    date = date.clone().hour(hour).minute(minute).second(second);
1333                }
1334                this.endDate = null;
1335                this.setStartDate(date.clone());
1336            } else if (!this.endDate && date.isBefore(this.startDate)) {
1337                //special case: clicking the same date for start/end,
1338                //but the time of the end date is before the start date
1339                this.setEndDate(this.startDate.clone());
1340            } else { // picking end
1341                if (this.timePicker) {
1342                    var hour = parseInt(this.container.find('.right .hourselect').val(), 10);
1343                    if (!this.timePicker24Hour) {
1344                        var ampm = this.container.find('.right .ampmselect').val();
1345                        if (ampm === 'PM' && hour < 12)
1346                            hour += 12;
1347                        if (ampm === 'AM' && hour === 12)
1348                            hour = 0;
1349                    }
1350                    var minute = parseInt(this.container.find('.right .minuteselect').val(), 10);
1351                    var second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0;
1352                    date = date.clone().hour(hour).minute(minute).second(second);
1353                }
1354                this.setEndDate(date.clone());
1355                if (this.autoApply) {
1356                    this.calculateChosenLabel();
1357                    this.clickApply();
1358                }
1359            }
1360
1361            if (this.singleDatePicker) {
1362                this.setEndDate(this.startDate);
1363                if (!this.timePicker)
1364                    this.clickApply();
1365            }
1366
1367            this.updateView();
1368
1369            //This is to cancel the blur event handler if the mouse was in one of the inputs
1370            e.stopPropagation();
1371
1372        },
1373
1374        calculateChosenLabel: function () {
1375            var customRange = true;
1376            var i = 0;
1377            for (var range in this.ranges) {
1378                if (this.timePicker) {
1379                    if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {
1380                        customRange = false;
1381                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html();
1382                        break;
1383                    }
1384                } else {
1385                    //ignore times when comparing dates if time picker is not enabled
1386                    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')) {
1387                        customRange = false;
1388                        this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html();
1389                        break;
1390                    }
1391                }
1392                i++;
1393            }
1394            if (customRange && this.showCustomRangeLabel) {
1395                this.chosenLabel = this.container.find('.ranges li:last').addClass('active').html();
1396                this.showCalendars();
1397            }
1398        },
1399
1400        clickApply: function (e) {
1401            // Should not hide the picker if it's inline mode, but should update the parentElement
1402            (!this.inline) ? this.hide() : this.updateElement();
1403            this.element.trigger('apply.daterangepicker', this);
1404        },
1405
1406        clickCancel: function (e) {
1407            this.startDate = this.oldStartDate;
1408            this.endDate = this.oldEndDate;
1409            // Should not hide the picker if it's inline mode, but should update the parentElement
1410            (!this.inline) ? this.hide() : this.updateElement();
1411            this.element.trigger('cancel.daterangepicker', this);
1412        },
1413
1414        monthOrYearChanged: function (e) {
1415            var isLeft = $(e.target).closest('.calendar').hasClass('left'),
1416                leftOrRight = isLeft ? 'left' : 'right',
1417                cal = this.container.find('.calendar.' + leftOrRight);
1418
1419            // Month must be Number for new moment versions
1420            var month = parseInt(cal.find('.monthselect').val(), 10);
1421            var year = cal.find('.yearselect').val();
1422
1423            if (!isLeft) {
1424                if (year < this.startDate.year() || (year == this.startDate.year() && month < this.startDate.month())) {
1425                    month = this.startDate.month();
1426                    year = this.startDate.year();
1427                }
1428            }
1429
1430            if (this.minDate) {
1431                if (year < this.minDate.year() || (year == this.minDate.year() && month < this.minDate.month())) {
1432                    month = this.minDate.month();
1433                    year = this.minDate.year();
1434                }
1435            }
1436
1437            if (this.maxDate) {
1438                if (year > this.maxDate.year() || (year == this.maxDate.year() && month > this.maxDate.month())) {
1439                    month = this.maxDate.month();
1440                    year = this.maxDate.year();
1441                }
1442            }
1443
1444            if (isLeft) {
1445                this.leftCalendar.month.month(month).year(year);
1446                if (this.linkedCalendars)
1447                    this.rightCalendar.month = this.leftCalendar.month.clone().add(1, 'month');
1448            } else {
1449                this.rightCalendar.month.month(month).year(year);
1450                if (this.linkedCalendars)
1451                    this.leftCalendar.month = this.rightCalendar.month.clone().subtract(1, 'month');
1452            }
1453            this.updateCalendars();
1454        },
1455
1456        timeChanged: function (e) {
1457
1458            var cal = $(e.target).closest('.calendar'),
1459                isLeft = cal.hasClass('left');
1460
1461            var hour = parseInt(cal.find('.hourselect').val(), 10);
1462            var minute = parseInt(cal.find('.minuteselect').val(), 10);
1463            var second = this.timePickerSeconds ? parseInt(cal.find('.secondselect').val(), 10) : 0;
1464
1465            if (!this.timePicker24Hour) {
1466                var ampm = cal.find('.ampmselect').val();
1467                if (ampm === 'PM' && hour < 12)
1468                    hour += 12;
1469                if (ampm === 'AM' && hour === 12)
1470                    hour = 0;
1471            }
1472
1473            if (isLeft) {
1474                var start = this.startDate.clone();
1475                start.hour(hour);
1476                start.minute(minute);
1477                start.second(second);
1478                this.setStartDate(start);
1479                if (this.singleDatePicker) {
1480                    this.endDate = this.startDate.clone();
1481                } else if (this.endDate && this.endDate.format('YYYY-MM-DD') == start.format('YYYY-MM-DD') && this.endDate.isBefore(start)) {
1482                    this.setEndDate(start.clone());
1483                }
1484            } else if (this.endDate) {
1485                var end = this.endDate.clone();
1486                end.hour(hour);
1487                end.minute(minute);
1488                end.second(second);
1489                this.setEndDate(end);
1490            }
1491
1492            // Update the parent element with the autoplay option in inline mode
1493            if (this.inline && this.autoApply)
1494                this.updateElement()
1495
1496            //update the calendars so all clickable dates reflect the new time component
1497            this.updateCalendars();
1498
1499            //update the form inputs above the calendars with the new time
1500            this.updateFormInputs();
1501
1502            //re-render the time pickers because changing one selection can affect what's enabled in another
1503            this.renderTimePicker('left');
1504            this.renderTimePicker('right');
1505
1506        },
1507
1508        formInputsChanged: function (e) {
1509            var isRight = $(e.target).closest('.calendar').hasClass('right');
1510            var start = moment(this.container.find('input[name="daterangepicker_start"]').val(), this.locale.format);
1511            var end = moment(this.container.find('input[name="daterangepicker_end"]').val(), this.locale.format);
1512
1513            if (start.isValid() && end.isValid()) {
1514
1515                if (isRight && end.isBefore(start))
1516                    start = end.clone();
1517
1518                this.setStartDate(start);
1519                this.setEndDate(end);
1520
1521                if (isRight) {
1522                    this.container.find('input[name="daterangepicker_start"]').val(this.startDate.format(this.locale.format));
1523                } else {
1524                    this.container.find('input[name="daterangepicker_end"]').val(this.endDate.format(this.locale.format));
1525                }
1526
1527            }
1528
1529            this.updateView();
1530
1531            // Update the parent element with the autoplay option in inline mode
1532            if (this.inline && this.autoApply)
1533                this.updateElement()
1534        },
1535
1536        formInputsFocused: function (e) {
1537
1538            // Highlight the focused input
1539            this.container.find('input[name="daterangepicker_start"], input[name="daterangepicker_end"]').removeClass('active');
1540            $(e.target).addClass('active');
1541
1542            // Set the state such that if the user goes back to using a mouse,
1543            // the calendars are aware we're selecting the end of the range, not
1544            // the start. This allows someone to edit the end of a date range without
1545            // re-selecting the beginning, by clicking on the end date input then
1546            // using the calendar.
1547            var isRight = $(e.target).closest('.calendar').hasClass('right');
1548            if (isRight) {
1549                this.endDate = null;
1550                this.setStartDate(this.startDate.clone());
1551                this.updateView();
1552            }
1553
1554        },
1555
1556        formInputsBlurred: function (e) {
1557
1558            // this function has one purpose right now: if you tab from the first
1559            // text input to the second in the UI, the endDate is nulled so that
1560            // you can click another, but if you tab out without clicking anything
1561            // or changing the input value, the old endDate should be retained
1562
1563            if (!this.endDate) {
1564                var val = this.container.find('input[name="daterangepicker_end"]').val();
1565                var end = moment(val, this.locale.format);
1566                if (end.isValid()) {
1567                    this.setEndDate(end);
1568                    this.updateView();
1569                }
1570            }
1571
1572        },
1573
1574        elementChanged: function () {
1575            if (!this.element.is('input')) return;
1576            if (!this.element.val().length) return;
1577            if (this.element.val().length < this.locale.format.length) return;
1578
1579            var dateString = this.element.val().split(this.locale.separator),
1580                start = null,
1581                end = null;
1582
1583            if (dateString.length === 2) {
1584                start = moment(dateString[0], this.locale.format);
1585                end = moment(dateString[1], this.locale.format);
1586            }
1587
1588            if (this.singleDatePicker || start === null || end === null) {
1589                start = moment(this.element.val(), this.locale.format);
1590                end = start;
1591            }
1592
1593            if (!start.isValid() || !end.isValid()) return;
1594
1595            this.setStartDate(start);
1596            this.setEndDate(end);
1597            this.updateView();
1598        },
1599
1600        keydown: function (e) {
1601            //hide on tab or enter
1602            if ((e.keyCode === 9) || (e.keyCode === 13)) {
1603                this.hide();
1604            }
1605        },
1606
1607        updateElement: function () {
1608
1609            //incomplete date selection, revert to last values
1610            if (!this.endDate) {
1611                this.startDate = this.oldStartDate.clone();
1612                this.endDate = this.oldEndDate.clone();
1613            }
1614
1615            //if a new date range was selected, invoke the user callback function
1616            if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))
1617                this.callback(this.startDate, this.endDate, this.chosenLabel);
1618
1619            if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) {
1620                this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
1621                this.element.trigger('change');
1622            } else if (this.element.is('input') && this.autoUpdateInput) {
1623                this.element.val(this.startDate.format(this.locale.format));
1624                this.element.trigger('change');
1625            }
1626        },
1627
1628        remove: function () {
1629            this.container.remove();
1630            this.element.off('.daterangepicker');
1631            this.element.removeData();
1632        }
1633
1634    };
1635
1636    $.fn.daterangepicker = function (options, callback) {
1637        this.each(function () {
1638            var el = $(this);
1639            if (el.data('daterangepicker'))
1640                el.data('daterangepicker').remove();
1641            el.data('daterangepicker', new DateRangePicker(el, options, callback));
1642        });
1643        return this;
1644    };
1645
1646    return DateRangePicker;
1647
1648}));
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665

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.