source: pro-violet-viettel/docs/Space/assets/js/uncompressed/date-time/daterangepicker.js @ 290

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