CLIENT GUI Framework
[vnfsdk/refrepo.git] / portal-common / src / main / webapp / common / thirdparty / bootstrap-daterangepicker / daterangepicker.js
1 /**\r
2 * @version: 1.3.17\r
3 * @author: Dan Grossman http://www.dangrossman.info/\r
4 * @date: 2014-11-25\r
5 * @copyright: Copyright (c) 2012-2014 Dan Grossman. All rights reserved.\r
6 * @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php\r
7 * @website: http://www.improvely.com/\r
8 */\r
9 \r
10 (function(root, factory) {\r
11 \r
12   if (typeof define === 'function' && define.amd) {\r
13     define(['moment', 'jquery', 'exports'], function(momentjs, $, exports) {\r
14       root.daterangepicker = factory(root, exports, momentjs, $);\r
15     });\r
16 \r
17   } else if (typeof exports !== 'undefined') {\r
18     var momentjs = require('moment');\r
19     var jQuery;\r
20     try {\r
21       jQuery = require('jquery');\r
22     } catch (err) {\r
23       jQuery = window.jQuery;\r
24       if (!jQuery) throw new Error('jQuery dependency not found');\r
25     }\r
26 \r
27     factory(root, exports, momentjs, jQuery);\r
28 \r
29   // Finally, as a browser global.\r
30   } else {\r
31     root.daterangepicker = factory(root, {}, root.moment, (root.jQuery || root.Zepto || root.ender || root.$));\r
32   }\r
33 \r
34 }(this, function(root, daterangepicker, moment, $) {\r
35 \r
36     var DateRangePicker = function (element, options, cb) {\r
37 \r
38         // by default, the daterangepicker element is placed at the bottom of HTML body\r
39         this.parentEl = 'body';\r
40 \r
41         //element that triggered the date range picker\r
42         this.element = $(element);\r
43 \r
44         //tracks visible state\r
45         this.isShowing = false;\r
46 \r
47         //create the picker HTML object\r
48         var DRPTemplate = '<div class="daterangepicker dropdown-menu">' +\r
49                 '<div class="calendar first left"></div>' +\r
50                 '<div class="calendar second right"></div>' +\r
51                 '<div class="ranges">' +\r
52                   '<div class="range_inputs">' +\r
53                     '<div class="daterangepicker_start_input">' +\r
54                       '<label for="daterangepicker_start"></label>' +\r
55                       '<input class="input-mini" type="text" name="daterangepicker_start" value="" />' +\r
56                     '</div>' +\r
57                     '<div class="daterangepicker_end_input">' +\r
58                       '<label for="daterangepicker_end"></label>' +\r
59                       '<input class="input-mini" type="text" name="daterangepicker_end" value="" />' +\r
60                     '</div>' +\r
61                     '<button class="applyBtn" disabled="disabled"></button>&nbsp;' +\r
62                     '<button class="cancelBtn"></button>' +\r
63                   '</div>' +\r
64                 '</div>' +\r
65               '</div>';\r
66 \r
67         //custom options\r
68         if (typeof options !== 'object' || options === null)\r
69             options = {};\r
70 \r
71         this.parentEl = (typeof options === 'object' && options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl);\r
72         this.container = $(DRPTemplate).appendTo(this.parentEl);\r
73 \r
74         this.setOptions(options, cb);\r
75 \r
76         //apply CSS classes and labels to buttons\r
77         var c = this.container;\r
78         $.each(this.buttonClasses, function (idx, val) {\r
79             c.find('button').addClass(val);\r
80         });\r
81         this.container.find('.daterangepicker_start_input label').html(this.locale.fromLabel);\r
82         this.container.find('.daterangepicker_end_input label').html(this.locale.toLabel);\r
83         if (this.applyClass.length)\r
84             this.container.find('.applyBtn').addClass(this.applyClass);\r
85         if (this.cancelClass.length)\r
86             this.container.find('.cancelBtn').addClass(this.cancelClass);\r
87         this.container.find('.applyBtn').html(this.locale.applyLabel);\r
88         this.container.find('.cancelBtn').html(this.locale.cancelLabel);\r
89 \r
90         //event listeners\r
91 \r
92         this.container.find('.calendar')\r
93             .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))\r
94             .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))\r
95             .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this))\r
96             .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.hoverDate, this))\r
97             .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this))\r
98             .on('change.daterangepicker', 'select.yearselect', $.proxy(this.updateMonthYear, this))\r
99             .on('change.daterangepicker', 'select.monthselect', $.proxy(this.updateMonthYear, this))\r
100             .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.secondselect,select.ampmselect', $.proxy(this.updateTime, this));\r
101 \r
102         this.container.find('.ranges')\r
103             .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))\r
104             .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))\r
105             .on('click.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this))\r
106             .on('change.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.inputsChanged, this))\r
107             .on('keydown.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.inputsKeydown, this))\r
108             .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))\r
109             .on('mouseenter.daterangepicker', 'li', $.proxy(this.enterRange, this))\r
110             .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));\r
111 \r
112         if (this.element.is('input')) {\r
113             this.element.on({\r
114                 'click.daterangepicker': $.proxy(this.show, this),\r
115                 'focus.daterangepicker': $.proxy(this.show, this),\r
116                 'keyup.daterangepicker': $.proxy(this.updateFromControl, this)\r
117             });\r
118         } else {\r
119             this.element.on('click.daterangepicker', $.proxy(this.toggle, this));\r
120         }\r
121 \r
122     };\r
123 \r
124     DateRangePicker.prototype = {\r
125 \r
126         constructor: DateRangePicker,\r
127 \r
128         setOptions: function(options, callback) {\r
129 \r
130             this.startDate = moment().startOf('day');\r
131             this.endDate = moment().endOf('day');\r
132             this.timeZone = moment().zone();\r
133             this.minDate = false;\r
134             this.maxDate = false;\r
135             this.dateLimit = false;\r
136 \r
137             this.showDropdowns = false;\r
138             this.showWeekNumbers = false;\r
139             this.timePicker = false;\r
140             this.timePickerSeconds = false;\r
141             this.timePickerIncrement = 30;\r
142             this.timePicker12Hour = true;\r
143             this.singleDatePicker = false;\r
144             this.ranges = {};\r
145 \r
146             this.opens = 'right';\r
147             if (this.element.hasClass('pull-right'))\r
148                 this.opens = 'left';\r
149 \r
150             this.buttonClasses = ['btn', 'btn-small btn-sm'];\r
151             this.applyClass = 'btn-success';\r
152             this.cancelClass = 'btn-default';\r
153 \r
154             this.format = 'MM/DD/YYYY';\r
155             this.separator = ' - ';\r
156 \r
157             this.locale = {\r
158                 applyLabel: 'Apply',\r
159                 cancelLabel: 'Cancel',\r
160                 fromLabel: 'From',\r
161                 toLabel: 'To',\r
162                 weekLabel: 'W',\r
163                 customRangeLabel: 'Custom Range',\r
164                 daysOfWeek: moment.weekdaysMin(),\r
165                 monthNames: moment.monthsShort(),\r
166                 firstDay: moment.localeData()._week.dow\r
167             };\r
168 \r
169             this.cb = function () { };\r
170 \r
171             if (typeof options.format === 'string')\r
172                 this.format = options.format;\r
173 \r
174             if (typeof options.separator === 'string')\r
175                 this.separator = options.separator;\r
176 \r
177             if (typeof options.startDate === 'string')\r
178                 this.startDate = moment(options.startDate, this.format);\r
179 \r
180             if (typeof options.endDate === 'string')\r
181                 this.endDate = moment(options.endDate, this.format);\r
182 \r
183             if (typeof options.minDate === 'string')\r
184                 this.minDate = moment(options.minDate, this.format);\r
185 \r
186             if (typeof options.maxDate === 'string')\r
187                 this.maxDate = moment(options.maxDate, this.format);\r
188 \r
189             if (typeof options.startDate === 'object')\r
190                 this.startDate = moment(options.startDate);\r
191 \r
192             if (typeof options.endDate === 'object')\r
193                 this.endDate = moment(options.endDate);\r
194 \r
195             if (typeof options.minDate === 'object')\r
196                 this.minDate = moment(options.minDate);\r
197 \r
198             if (typeof options.maxDate === 'object')\r
199                 this.maxDate = moment(options.maxDate);\r
200 \r
201             if (typeof options.applyClass === 'string')\r
202                 this.applyClass = options.applyClass;\r
203 \r
204             if (typeof options.cancelClass === 'string')\r
205                 this.cancelClass = options.cancelClass;\r
206 \r
207             if (typeof options.dateLimit === 'object')\r
208                 this.dateLimit = options.dateLimit;\r
209 \r
210             if (typeof options.locale === 'object') {\r
211 \r
212                 if (typeof options.locale.daysOfWeek === 'object') {\r
213                     // Create a copy of daysOfWeek to avoid modification of original\r
214                     // options object for reusability in multiple daterangepicker instances\r
215                     this.locale.daysOfWeek = options.locale.daysOfWeek.slice();\r
216                 }\r
217 \r
218                 if (typeof options.locale.monthNames === 'object') {\r
219                   this.locale.monthNames = options.locale.monthNames.slice();\r
220                 }\r
221 \r
222                 if (typeof options.locale.firstDay === 'number') {\r
223                   this.locale.firstDay = options.locale.firstDay;\r
224                 }\r
225 \r
226                 if (typeof options.locale.applyLabel === 'string') {\r
227                   this.locale.applyLabel = options.locale.applyLabel;\r
228                 }\r
229 \r
230                 if (typeof options.locale.cancelLabel === 'string') {\r
231                   this.locale.cancelLabel = options.locale.cancelLabel;\r
232                 }\r
233 \r
234                 if (typeof options.locale.fromLabel === 'string') {\r
235                   this.locale.fromLabel = options.locale.fromLabel;\r
236                 }\r
237 \r
238                 if (typeof options.locale.toLabel === 'string') {\r
239                   this.locale.toLabel = options.locale.toLabel;\r
240                 }\r
241 \r
242                 if (typeof options.locale.weekLabel === 'string') {\r
243                   this.locale.weekLabel = options.locale.weekLabel;\r
244                 }\r
245 \r
246                 if (typeof options.locale.customRangeLabel === 'string') {\r
247                   this.locale.customRangeLabel = options.locale.customRangeLabel;\r
248                 }\r
249             }\r
250 \r
251             if (typeof options.opens === 'string')\r
252                 this.opens = options.opens;\r
253 \r
254             if (typeof options.showWeekNumbers === 'boolean') {\r
255                 this.showWeekNumbers = options.showWeekNumbers;\r
256             }\r
257 \r
258             if (typeof options.buttonClasses === 'string') {\r
259                 this.buttonClasses = [options.buttonClasses];\r
260             }\r
261 \r
262             if (typeof options.buttonClasses === 'object') {\r
263                 this.buttonClasses = options.buttonClasses;\r
264             }\r
265 \r
266             if (typeof options.showDropdowns === 'boolean') {\r
267                 this.showDropdowns = options.showDropdowns;\r
268             }\r
269 \r
270             if (typeof options.singleDatePicker === 'boolean') {\r
271                 this.singleDatePicker = options.singleDatePicker;\r
272                 if (this.singleDatePicker) {\r
273                     this.endDate = this.startDate.clone();\r
274                 }\r
275             }\r
276 \r
277             if (typeof options.timePicker === 'boolean') {\r
278                 this.timePicker = options.timePicker;\r
279             }\r
280 \r
281             if (typeof options.timePickerSeconds === 'boolean') {\r
282                 this.timePickerSeconds = options.timePickerSeconds;\r
283             }\r
284 \r
285             if (typeof options.timePickerIncrement === 'number') {\r
286                 this.timePickerIncrement = options.timePickerIncrement;\r
287             }\r
288 \r
289             if (typeof options.timePicker12Hour === 'boolean') {\r
290                 this.timePicker12Hour = options.timePicker12Hour;\r
291             }\r
292 \r
293             // update day names order to firstDay\r
294             if (this.locale.firstDay != 0) {\r
295                 var iterator = this.locale.firstDay;\r
296                 while (iterator > 0) {\r
297                     this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift());\r
298                     iterator--;\r
299                 }\r
300             }\r
301 \r
302             var start, end, range;\r
303 \r
304             //if no start/end dates set, check if an input element contains initial values\r
305             if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {\r
306                 if ($(this.element).is('input[type=text]')) {\r
307                     var val = $(this.element).val(),\r
308                         split = val.split(this.separator);\r
309 \r
310                     start = end = null;\r
311 \r
312                     if (split.length == 2) {\r
313                         start = moment(split[0], this.format);\r
314                         end = moment(split[1], this.format);\r
315                     } else if (this.singleDatePicker && val !== "") {\r
316                         start = moment(val, this.format);\r
317                         end = moment(val, this.format);\r
318                     }\r
319                     if (start !== null && end !== null) {\r
320                         this.startDate = start;\r
321                         this.endDate = end;\r
322                     }\r
323                 }\r
324             }\r
325 \r
326             // bind the time zone used to build the calendar to either the timeZone passed in through the options or the zone of the startDate (which will be the local time zone by default)\r
327             if (typeof options.timeZone === 'string' || typeof options.timeZone === 'number') {\r
328                 this.timeZone = options.timeZone;\r
329                 this.startDate.zone(this.timeZone);\r
330                 this.endDate.zone(this.timeZone);\r
331             } else {\r
332                 this.timeZone = moment(this.startDate).zone();\r
333             }\r
334 \r
335             if (typeof options.ranges === 'object') {\r
336                 for (range in options.ranges) {\r
337 \r
338                     if (typeof options.ranges[range][0] === 'string')\r
339                         start = moment(options.ranges[range][0], this.format);\r
340                     else\r
341                         start = moment(options.ranges[range][0]);\r
342 \r
343                     if (typeof options.ranges[range][1] === 'string')\r
344                         end = moment(options.ranges[range][1], this.format);\r
345                     else\r
346                         end = moment(options.ranges[range][1]);\r
347 \r
348                     // If we have a min/max date set, bound this range\r
349                     // to it, but only if it would otherwise fall\r
350                     // outside of the min/max.\r
351                     if (this.minDate && start.isBefore(this.minDate))\r
352                         start = moment(this.minDate);\r
353 \r
354                     if (this.maxDate && end.isAfter(this.maxDate))\r
355                         end = moment(this.maxDate);\r
356 \r
357                     // If the end of the range is before the minimum (if min is set) OR\r
358                     // the start of the range is after the max (also if set) don't display this\r
359                     // range option.\r
360                     if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) {\r
361                         continue;\r
362                     }\r
363 \r
364                     this.ranges[range] = [start, end];\r
365                 }\r
366 \r
367                 var list = '<ul>';\r
368                 for (range in this.ranges) {\r
369                     list += '<li>' + range + '</li>';\r
370                 }\r
371                 list += '<li>' + this.locale.customRangeLabel + '</li>';\r
372                 list += '</ul>';\r
373                 this.container.find('.ranges ul').remove();\r
374                 this.container.find('.ranges').prepend(list);\r
375             }\r
376 \r
377             if (typeof callback === 'function') {\r
378                 this.cb = callback;\r
379             }\r
380 \r
381             if (!this.timePicker) {\r
382                 this.startDate = this.startDate.startOf('day');\r
383                 this.endDate = this.endDate.endOf('day');\r
384             }\r
385 \r
386             if (this.singleDatePicker) {\r
387                 this.opens = 'right';\r
388                 this.container.addClass('single');\r
389                 this.container.find('.calendar.right').show();\r
390                 this.container.find('.calendar.left').hide();\r
391                 if (!this.timePicker) {\r
392                     this.container.find('.ranges').hide();\r
393                 } else {\r
394                     this.container.find('.ranges .daterangepicker_start_input, .ranges .daterangepicker_end_input').hide();\r
395                 }\r
396                 if (!this.container.find('.calendar.right').hasClass('single'))\r
397                     this.container.find('.calendar.right').addClass('single');\r
398             } else {\r
399                 this.container.removeClass('single');\r
400                 this.container.find('.calendar.right').removeClass('single');\r
401                 this.container.find('.ranges').show();\r
402             }\r
403 \r
404             this.oldStartDate = this.startDate.clone();\r
405             this.oldEndDate = this.endDate.clone();\r
406             this.oldChosenLabel = this.chosenLabel;\r
407 \r
408             this.leftCalendar = {\r
409                 month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute(), this.startDate.second()]),\r
410                 calendar: []\r
411             };\r
412 \r
413             this.rightCalendar = {\r
414                 month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute(), this.endDate.second()]),\r
415                 calendar: []\r
416             };\r
417 \r
418             if (this.opens == 'right' || this.opens == 'center') {\r
419                 //swap calendar positions\r
420                 var first = this.container.find('.calendar.first');\r
421                 var second = this.container.find('.calendar.second');\r
422 \r
423                 if (second.hasClass('single')) {\r
424                     second.removeClass('single');\r
425                     first.addClass('single');\r
426                 }\r
427 \r
428                 first.removeClass('left').addClass('right');\r
429                 second.removeClass('right').addClass('left');\r
430 \r
431                 if (this.singleDatePicker) {\r
432                     first.show();\r
433                     second.hide();\r
434                 }\r
435             }\r
436 \r
437             if (typeof options.ranges === 'undefined' && !this.singleDatePicker) {\r
438                 this.container.addClass('show-calendar');\r
439             }\r
440 \r
441             this.container.addClass('opens' + this.opens);\r
442 \r
443             this.updateView();\r
444             this.updateCalendars();\r
445 \r
446         },\r
447 \r
448         setStartDate: function(startDate) {\r
449             if (typeof startDate === 'string')\r
450                 this.startDate = moment(startDate, this.format).zone(this.timeZone);\r
451 \r
452             if (typeof startDate === 'object')\r
453                 this.startDate = moment(startDate);\r
454 \r
455             if (!this.timePicker)\r
456                 this.startDate = this.startDate.startOf('day');\r
457 \r
458             this.oldStartDate = this.startDate.clone();\r
459 \r
460             this.updateView();\r
461             this.updateCalendars();\r
462             this.updateInputText();\r
463         },\r
464 \r
465         setEndDate: function(endDate) {\r
466             if (typeof endDate === 'string')\r
467                 this.endDate = moment(endDate, this.format).zone(this.timeZone);\r
468 \r
469             if (typeof endDate === 'object')\r
470                 this.endDate = moment(endDate);\r
471 \r
472             if (!this.timePicker)\r
473                 this.endDate = this.endDate.endOf('day');\r
474 \r
475             this.oldEndDate = this.endDate.clone();\r
476 \r
477             this.updateView();\r
478             this.updateCalendars();\r
479             this.updateInputText();\r
480         },\r
481 \r
482         updateView: function () {\r
483             this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute());\r
484             this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute());\r
485             this.updateFormInputs();\r
486         },\r
487 \r
488         updateFormInputs: function () {\r
489             this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.format));\r
490             this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.format));\r
491 \r
492             if (this.startDate.isSame(this.endDate) || this.startDate.isBefore(this.endDate)) {\r
493                 this.container.find('button.applyBtn').removeAttr('disabled');\r
494             } else {\r
495                 this.container.find('button.applyBtn').attr('disabled', 'disabled');\r
496             }\r
497         },\r
498 \r
499         updateFromControl: function () {\r
500             if (!this.element.is('input')) return;\r
501             if (!this.element.val().length) return;\r
502 \r
503             var dateString = this.element.val().split(this.separator),\r
504                 start = null,\r
505                 end = null;\r
506 \r
507             if(dateString.length === 2) {\r
508                 start = moment(dateString[0], this.format).zone(this.timeZone);\r
509                 end = moment(dateString[1], this.format).zone(this.timeZone);\r
510             }\r
511 \r
512             if (this.singleDatePicker || start === null || end === null) {\r
513                 start = moment(this.element.val(), this.format).zone(this.timeZone);\r
514                 end = start;\r
515             }\r
516 \r
517             if (end.isBefore(start)) return;\r
518 \r
519             this.oldStartDate = this.startDate.clone();\r
520             this.oldEndDate = this.endDate.clone();\r
521 \r
522             this.startDate = start;\r
523             this.endDate = end;\r
524 \r
525             if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\r
526                 this.notify();\r
527 \r
528             this.updateCalendars();\r
529         },\r
530 \r
531         notify: function () {\r
532             this.updateView();\r
533             this.cb(this.startDate, this.endDate, this.chosenLabel);\r
534         },\r
535 \r
536         move: function () {\r
537             var parentOffset = { top: 0, left: 0 };\r
538             var parentRightEdge = $(window).width();\r
539             if (!this.parentEl.is('body')) {\r
540                 parentOffset = {\r
541                     top: this.parentEl.offset().top - this.parentEl.scrollTop(),\r
542                     left: this.parentEl.offset().left - this.parentEl.scrollLeft()\r
543                 };\r
544                 parentRightEdge = this.parentEl[0].clientWidth + this.parentEl.offset().left;\r
545             }\r
546 \r
547             if (this.opens == 'left') {\r
548                 this.container.css({\r
549                     top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\r
550                     right: parentRightEdge - this.element.offset().left - this.element.outerWidth(),\r
551                     left: 'auto'\r
552                 });\r
553                 if (this.container.offset().left < 0) {\r
554                     this.container.css({\r
555                         right: 'auto',\r
556                         left: 9\r
557                     });\r
558                 }\r
559             } else if (this.opens == 'center') {\r
560                 this.container.css({\r
561                     top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\r
562                     left: this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2\r
563                             - this.container.outerWidth() / 2,\r
564                     right: 'auto'\r
565                 });\r
566                 if (this.container.offset().left < 0) {\r
567                     this.container.css({\r
568                         right: 'auto',\r
569                         left: 9\r
570                     });\r
571                 }\r
572             } else {\r
573                 this.container.css({\r
574                     top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,\r
575                     left: this.element.offset().left - parentOffset.left,\r
576                     right: 'auto'\r
577                 });\r
578                 if (this.container.offset().left + this.container.outerWidth() > $(window).width()) {\r
579                     this.container.css({\r
580                         left: 'auto',\r
581                         right: 0\r
582                     });\r
583                 }\r
584             }\r
585         },\r
586 \r
587         toggle: function (e) {\r
588             if (this.element.hasClass('active')) {\r
589                 this.hide();\r
590             } else {\r
591                 this.show();\r
592             }\r
593         },\r
594 \r
595         show: function (e) {\r
596             if (this.isShowing) return;\r
597 \r
598             this.element.addClass('active');\r
599             this.container.show();\r
600             this.move();\r
601 \r
602             // Create a click proxy that is private to this instance of datepicker, for unbinding\r
603             this._outsideClickProxy = $.proxy(function (e) { this.outsideClick(e); }, this);\r
604             // Bind global datepicker mousedown for hiding and\r
605             $(document)\r
606               .on('mousedown.daterangepicker', this._outsideClickProxy)\r
607               // also support mobile devices\r
608               .on('touchend.daterangepicker', this._outsideClickProxy)\r
609               // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them\r
610               .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)\r
611               // and also close when focus changes to outside the picker (eg. tabbing between controls)\r
612               .on('focusin.daterangepicker', this._outsideClickProxy);\r
613 \r
614             this.isShowing = true;\r
615             this.element.trigger('show.daterangepicker', this);\r
616         },\r
617 \r
618         outsideClick: function (e) {\r
619             var target = $(e.target);\r
620             // if the page is clicked anywhere except within the daterangerpicker/button\r
621             // itself then call this.hide()\r
622             if (\r
623                 // ie modal dialog fix\r
624                 e.type == "focusin" ||\r
625                 target.closest(this.element).length ||\r
626                 target.closest(this.container).length ||\r
627                 target.closest('.calendar-date').length\r
628                 ) return;\r
629             this.hide();\r
630         },\r
631 \r
632         hide: function (e) {\r
633             if (!this.isShowing) return;\r
634 \r
635             $(document)\r
636               .off('.daterangepicker');\r
637 \r
638             this.element.removeClass('active');\r
639             this.container.hide();\r
640 \r
641             if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))\r
642                 this.notify();\r
643 \r
644             this.oldStartDate = this.startDate.clone();\r
645             this.oldEndDate = this.endDate.clone();\r
646 \r
647             this.isShowing = false;\r
648             this.element.trigger('hide.daterangepicker', this);\r
649         },\r
650 \r
651         enterRange: function (e) {\r
652             // mouse pointer has entered a range label\r
653             var label = e.target.innerHTML;\r
654             if (label == this.locale.customRangeLabel) {\r
655                 this.updateView();\r
656             } else {\r
657                 var dates = this.ranges[label];\r
658                 this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.format));\r
659                 this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.format));\r
660             }\r
661         },\r
662 \r
663         showCalendars: function() {\r
664             this.container.addClass('show-calendar');\r
665             this.move();\r
666             this.element.trigger('showCalendar.daterangepicker', this);\r
667         },\r
668 \r
669         hideCalendars: function() {\r
670             this.container.removeClass('show-calendar');\r
671             this.element.trigger('hideCalendar.daterangepicker', this);\r
672         },\r
673 \r
674         // when a date is typed into the start to end date textboxes\r
675         inputsChanged: function (e) {\r
676             var el = $(e.target);\r
677             var date = moment(el.val(), this.format);\r
678             if (!date.isValid()) return;\r
679 \r
680             var startDate, endDate;\r
681             if (el.attr('name') === 'daterangepicker_start') {\r
682                 startDate = date;\r
683                 endDate = this.endDate;\r
684             } else {\r
685                 startDate = this.startDate;\r
686                 endDate = date;\r
687             }\r
688             this.setCustomDates(startDate, endDate);\r
689         },\r
690 \r
691         inputsKeydown: function(e) {\r
692             if (e.keyCode === 13) {\r
693                 this.inputsChanged(e);\r
694                 this.notify();\r
695             }\r
696         },\r
697 \r
698         updateInputText: function() {\r
699             if (this.element.is('input') && !this.singleDatePicker) {\r
700                 this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));\r
701             } else if (this.element.is('input')) {\r
702                 this.element.val(this.endDate.format(this.format));\r
703             }\r
704         },\r
705 \r
706         clickRange: function (e) {\r
707             var label = e.target.innerHTML;\r
708             this.chosenLabel = label;\r
709             if (label == this.locale.customRangeLabel) {\r
710                 this.showCalendars();\r
711             } else {\r
712                 var dates = this.ranges[label];\r
713 \r
714                 this.startDate = dates[0];\r
715                 this.endDate = dates[1];\r
716 \r
717                 if (!this.timePicker) {\r
718                     this.startDate.startOf('day');\r
719                     this.endDate.endOf('day');\r
720                 }\r
721 \r
722                 this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute());\r
723                 this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute());\r
724                 this.updateCalendars();\r
725 \r
726                 this.updateInputText();\r
727 \r
728                 this.hideCalendars();\r
729                 this.hide();\r
730                 this.element.trigger('apply.daterangepicker', this);\r
731             }\r
732         },\r
733 \r
734         clickPrev: function (e) {\r
735             var cal = $(e.target).parents('.calendar');\r
736             if (cal.hasClass('left')) {\r
737                 this.leftCalendar.month.subtract(1, 'month');\r
738             } else {\r
739                 this.rightCalendar.month.subtract(1, 'month');\r
740             }\r
741             this.updateCalendars();\r
742         },\r
743 \r
744         clickNext: function (e) {\r
745             var cal = $(e.target).parents('.calendar');\r
746             if (cal.hasClass('left')) {\r
747                 this.leftCalendar.month.add(1, 'month');\r
748             } else {\r
749                 this.rightCalendar.month.add(1, 'month');\r
750             }\r
751             this.updateCalendars();\r
752         },\r
753 \r
754         hoverDate: function (e) {\r
755             var title = $(e.target).attr('data-title');\r
756             var row = title.substr(1, 1);\r
757             var col = title.substr(3, 1);\r
758             var cal = $(e.target).parents('.calendar');\r
759 \r
760             if (cal.hasClass('left')) {\r
761                 this.container.find('input[name=daterangepicker_start]').val(this.leftCalendar.calendar[row][col].format(this.format));\r
762             } else {\r
763                 this.container.find('input[name=daterangepicker_end]').val(this.rightCalendar.calendar[row][col].format(this.format));\r
764             }\r
765         },\r
766 \r
767         setCustomDates: function(startDate, endDate) {\r
768             this.chosenLabel = this.locale.customRangeLabel;\r
769             if (startDate.isAfter(endDate)) {\r
770                 var difference = this.endDate.diff(this.startDate);\r
771                 endDate = moment(startDate).add(difference, 'ms');\r
772                 if (this.maxDate && endDate.isAfter(this.maxDate)) {\r
773                   endDate = this.maxDate;\r
774                 }\r
775             }\r
776             this.startDate = startDate;\r
777             this.endDate = endDate;\r
778 \r
779             this.updateView();\r
780             this.updateCalendars();\r
781         },\r
782 \r
783         clickDate: function (e) {\r
784             var title = $(e.target).attr('data-title');\r
785             var row = title.substr(1, 1);\r
786             var col = title.substr(3, 1);\r
787             var cal = $(e.target).parents('.calendar');\r
788 \r
789             var startDate, endDate;\r
790             if (cal.hasClass('left')) {\r
791                 startDate = this.leftCalendar.calendar[row][col];\r
792                 endDate = this.endDate;\r
793                 if (typeof this.dateLimit === 'object') {\r
794                     var maxDate = moment(startDate).add(this.dateLimit).startOf('day');\r
795                     if (endDate.isAfter(maxDate)) {\r
796                         endDate = maxDate;\r
797                     }\r
798                 }\r
799             } else {\r
800                 startDate = this.startDate;\r
801                 endDate = this.rightCalendar.calendar[row][col];\r
802                 if (typeof this.dateLimit === 'object') {\r
803                     var minDate = moment(endDate).subtract(this.dateLimit).startOf('day');\r
804                     if (startDate.isBefore(minDate)) {\r
805                         startDate = minDate;\r
806                     }\r
807                 }\r
808             }\r
809 \r
810             if (this.singleDatePicker && cal.hasClass('left')) {\r
811                 endDate = startDate.clone();\r
812             } else if (this.singleDatePicker && cal.hasClass('right')) {\r
813                 startDate = endDate.clone();\r
814             }\r
815 \r
816             cal.find('td').removeClass('active');\r
817 \r
818             $(e.target).addClass('active');\r
819 \r
820             this.setCustomDates(startDate, endDate);\r
821 \r
822             if (!this.timePicker)\r
823                 endDate.endOf('day');\r
824 \r
825             if (this.singleDatePicker && !this.timePicker)\r
826                 this.clickApply();\r
827         },\r
828 \r
829         clickApply: function (e) {\r
830             this.updateInputText();\r
831             this.hide();\r
832             this.element.trigger('apply.daterangepicker', this);\r
833         },\r
834 \r
835         clickCancel: function (e) {\r
836             this.startDate = this.oldStartDate;\r
837             this.endDate = this.oldEndDate;\r
838             this.chosenLabel = this.oldChosenLabel;\r
839             this.updateView();\r
840             this.updateCalendars();\r
841             this.hide();\r
842             this.element.trigger('cancel.daterangepicker', this);\r
843         },\r
844 \r
845         updateMonthYear: function (e) {\r
846             var isLeft = $(e.target).closest('.calendar').hasClass('left'),\r
847                 leftOrRight = isLeft ? 'left' : 'right',\r
848                 cal = this.container.find('.calendar.'+leftOrRight);\r
849 \r
850             // Month must be Number for new moment versions\r
851             var month = parseInt(cal.find('.monthselect').val(), 10);\r
852             var year = cal.find('.yearselect').val();\r
853 \r
854             this[leftOrRight+'Calendar'].month.month(month).year(year);\r
855             this.updateCalendars();\r
856         },\r
857 \r
858         updateTime: function(e) {\r
859 \r
860             var cal = $(e.target).closest('.calendar'),\r
861                 isLeft = cal.hasClass('left');\r
862 \r
863             var hour = parseInt(cal.find('.hourselect').val(), 10);\r
864             var minute = parseInt(cal.find('.minuteselect').val(), 10);\r
865             var second = 0;\r
866 \r
867             if (this.timePickerSeconds) {\r
868                 second = parseInt(cal.find('.secondselect').val(), 10);\r
869             }\r
870 \r
871             if (this.timePicker12Hour) {\r
872                 var ampm = cal.find('.ampmselect').val();\r
873                 if (ampm === 'PM' && hour < 12)\r
874                     hour += 12;\r
875                 if (ampm === 'AM' && hour === 12)\r
876                     hour = 0;\r
877             }\r
878 \r
879             if (isLeft) {\r
880                 var start = this.startDate.clone();\r
881                 start.hour(hour);\r
882                 start.minute(minute);\r
883                 start.second(second);\r
884                 this.startDate = start;\r
885                 this.leftCalendar.month.hour(hour).minute(minute).second(second);\r
886                 if (this.singleDatePicker)\r
887                     this.endDate = start.clone();\r
888             } else {\r
889                 var end = this.endDate.clone();\r
890                 end.hour(hour);\r
891                 end.minute(minute);\r
892                 end.second(second);\r
893                 this.endDate = end;\r
894                 if (this.singleDatePicker)\r
895                     this.startDate = end.clone();\r
896                 this.rightCalendar.month.hour(hour).minute(minute).second(second);\r
897             }\r
898 \r
899             this.updateView();\r
900             this.updateCalendars();\r
901         },\r
902 \r
903         updateCalendars: function () {\r
904             this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), this.leftCalendar.month.second(), 'left');\r
905             this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), this.rightCalendar.month.second(), 'right');\r
906             this.container.find('.calendar.left').empty().html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate, 'left'));\r
907             this.container.find('.calendar.right').empty().html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.singleDatePicker ? this.minDate : this.startDate, this.maxDate, 'right'));\r
908 \r
909             this.container.find('.ranges li').removeClass('active');\r
910             var customRange = true;\r
911             var i = 0;\r
912             for (var range in this.ranges) {\r
913                 if (this.timePicker) {\r
914                     if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {\r
915                         customRange = false;\r
916                         this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\r
917                             .addClass('active').html();\r
918                     }\r
919                 } else {\r
920                     //ignore times when comparing dates if time picker is not enabled\r
921                     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')) {\r
922                         customRange = false;\r
923                         this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')\r
924                             .addClass('active').html();\r
925                     }\r
926                 }\r
927                 i++;\r
928             }\r
929             if (customRange) {\r
930                 this.chosenLabel = this.container.find('.ranges li:last').addClass('active').html();\r
931                 this.showCalendars();\r
932             }\r
933         },\r
934 \r
935         buildCalendar: function (month, year, hour, minute, second, side) {\r
936             var daysInMonth = moment([year, month]).daysInMonth();\r
937             var firstDay = moment([year, month, 1]);\r
938             var lastDay = moment([year, month, daysInMonth]);\r
939             var lastMonth = moment(firstDay).subtract(1, 'month').month();\r
940             var lastYear = moment(firstDay).subtract(1, 'month').year();\r
941 \r
942             var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth();\r
943 \r
944             var dayOfWeek = firstDay.day();\r
945 \r
946             var i;\r
947 \r
948             //initialize a 6 rows x 7 columns array for the calendar\r
949             var calendar = [];\r
950             calendar.firstDay = firstDay;\r
951             calendar.lastDay = lastDay;\r
952 \r
953             for (i = 0; i < 6; i++) {\r
954                 calendar[i] = [];\r
955             }\r
956 \r
957             //populate the calendar with date objects\r
958             var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1;\r
959             if (startDay > daysInLastMonth)\r
960                 startDay -= 7;\r
961 \r
962             if (dayOfWeek == this.locale.firstDay)\r
963                 startDay = daysInLastMonth - 6;\r
964 \r
965             var curDate = moment([lastYear, lastMonth, startDay, 12, minute, second]).zone(this.timeZone);\r
966 \r
967             var col, row;\r
968             for (i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add(24, 'hour')) {\r
969                 if (i > 0 && col % 7 === 0) {\r
970                     col = 0;\r
971                     row++;\r
972                 }\r
973                 calendar[row][col] = curDate.clone().hour(hour);\r
974                 curDate.hour(12);\r
975 \r
976                 if (this.minDate && calendar[row][col].format('YYYY-MM-DD') == this.minDate.format('YYYY-MM-DD') && calendar[row][col].isBefore(this.minDate) && side == 'left') {\r
977                     calendar[row][col] = this.minDate.clone();\r
978                 }\r
979 \r
980                 if (this.maxDate && calendar[row][col].format('YYYY-MM-DD') == this.maxDate.format('YYYY-MM-DD') && calendar[row][col].isAfter(this.maxDate) && side == 'right') {\r
981                     calendar[row][col] = this.maxDate.clone();\r
982                 }\r
983 \r
984             }\r
985 \r
986             return calendar;\r
987         },\r
988 \r
989         renderDropdowns: function (selected, minDate, maxDate) {\r
990             var currentMonth = selected.month();\r
991             var currentYear = selected.year();\r
992             var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);\r
993             var minYear = (minDate && minDate.year()) || (currentYear - 50);\r
994 \r
995             var monthHtml = '<select class="monthselect">';\r
996             var inMinYear = currentYear == minYear;\r
997             var inMaxYear = currentYear == maxYear;\r
998 \r
999             for (var m = 0; m < 12; m++) {\r
1000                 if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) {\r
1001                     monthHtml += "<option value='" + m + "'" +\r
1002                         (m === currentMonth ? " selected='selected'" : "") +\r
1003                         ">" + this.locale.monthNames[m] + "</option>";\r
1004                 }\r
1005             }\r
1006             monthHtml += "</select>";\r
1007 \r
1008             var yearHtml = '<select class="yearselect">';\r
1009 \r
1010             for (var y = minYear; y <= maxYear; y++) {\r
1011                 yearHtml += '<option value="' + y + '"' +\r
1012                     (y === currentYear ? ' selected="selected"' : '') +\r
1013                     '>' + y + '</option>';\r
1014             }\r
1015 \r
1016             yearHtml += '</select>';\r
1017 \r
1018             return monthHtml + yearHtml;\r
1019         },\r
1020 \r
1021         renderCalendar: function (calendar, selected, minDate, maxDate, side) {\r
1022 \r
1023             var html = '<div class="calendar-date">';\r
1024             html += '<table class="table-condensed">';\r
1025             html += '<thead>';\r
1026             html += '<tr>';\r
1027 \r
1028             // add empty cell for week number\r
1029             if (this.showWeekNumbers)\r
1030                 html += '<th></th>';\r
1031 \r
1032             if (!minDate || minDate.isBefore(calendar.firstDay)) {\r
1033                 html += '<th class="prev available"><i class="fa fa-arrow-left icon icon-arrow-left glyphicon glyphicon-arrow-left"></i></th>';\r
1034             } else {\r
1035                 html += '<th></th>';\r
1036             }\r
1037 \r
1038             var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY");\r
1039 \r
1040             if (this.showDropdowns) {\r
1041                 dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate);\r
1042             }\r
1043 \r
1044             html += '<th colspan="5" class="month">' + dateHtml + '</th>';\r
1045             if (!maxDate || maxDate.isAfter(calendar.lastDay)) {\r
1046                 html += '<th class="next available"><i class="fa fa-arrow-right icon icon-arrow-right glyphicon glyphicon-arrow-right"></i></th>';\r
1047             } else {\r
1048                 html += '<th></th>';\r
1049             }\r
1050 \r
1051             html += '</tr>';\r
1052             html += '<tr>';\r
1053 \r
1054             // add week number label\r
1055             if (this.showWeekNumbers)\r
1056                 html += '<th class="week">' + this.locale.weekLabel + '</th>';\r
1057 \r
1058             $.each(this.locale.daysOfWeek, function (index, dayOfWeek) {\r
1059                 html += '<th>' + dayOfWeek + '</th>';\r
1060             });\r
1061 \r
1062             html += '</tr>';\r
1063             html += '</thead>';\r
1064             html += '<tbody>';\r
1065 \r
1066             for (var row = 0; row < 6; row++) {\r
1067                 html += '<tr>';\r
1068 \r
1069                 // add week number\r
1070                 if (this.showWeekNumbers)\r
1071                     html += '<td class="week">' + calendar[row][0].week() + '</td>';\r
1072 \r
1073                 for (var col = 0; col < 7; col++) {\r
1074                     var cname = 'available ';\r
1075                     cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off';\r
1076 \r
1077                     if ((minDate && calendar[row][col].isBefore(minDate, 'day')) || (maxDate && calendar[row][col].isAfter(maxDate, 'day'))) {\r
1078                         cname = ' off disabled ';\r
1079                     } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) {\r
1080                         cname += ' active ';\r
1081                         if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) {\r
1082                             cname += ' start-date ';\r
1083                         }\r
1084                         if (calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) {\r
1085                             cname += ' end-date ';\r
1086                         }\r
1087                     } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) {\r
1088                         cname += ' in-range ';\r
1089                         if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; }\r
1090                         if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; }\r
1091                     }\r
1092 \r
1093                     var title = 'r' + row + 'c' + col;\r
1094                     html += '<td class="' + cname.replace(/\s+/g, ' ').replace(/^\s?(.*?)\s?$/, '$1') + '" data-title="' + title + '">' + calendar[row][col].date() + '</td>';\r
1095                 }\r
1096                 html += '</tr>';\r
1097             }\r
1098 \r
1099             html += '</tbody>';\r
1100             html += '</table>';\r
1101             html += '</div>';\r
1102 \r
1103             var i;\r
1104             if (this.timePicker) {\r
1105 \r
1106                 html += '<div class="calendar-time">';\r
1107                 html += '<select class="hourselect">';\r
1108 \r
1109                 // Disallow selections before the minDate or after the maxDate\r
1110                 var min_hour = 0;\r
1111                 var max_hour = 23;\r
1112 \r
1113                 if (minDate && (side == 'left' || this.singleDatePicker) && selected.format('YYYY-MM-DD') == minDate.format('YYYY-MM-DD')) {\r
1114                     min_hour = minDate.hour();\r
1115                     if (selected.hour() < min_hour)\r
1116                         selected.hour(min_hour);\r
1117                     if (this.timePicker12Hour && min_hour >= 12 && selected.hour() >= 12)\r
1118                         min_hour -= 12;\r
1119                     if (this.timePicker12Hour && min_hour == 12)\r
1120                         min_hour = 1;\r
1121                 }\r
1122 \r
1123                 if (maxDate && (side == 'right' || this.singleDatePicker) && selected.format('YYYY-MM-DD') == maxDate.format('YYYY-MM-DD')) {\r
1124                     max_hour = maxDate.hour();\r
1125                     if (selected.hour() > max_hour)\r
1126                         selected.hour(max_hour);\r
1127                     if (this.timePicker12Hour && max_hour >= 12 && selected.hour() >= 12)\r
1128                         max_hour -= 12;\r
1129                 }\r
1130 \r
1131                 var start = 0;\r
1132                 var end = 23;\r
1133                 var selected_hour = selected.hour();\r
1134                 if (this.timePicker12Hour) {\r
1135                     start = 1;\r
1136                     end = 12;\r
1137                     if (selected_hour >= 12)\r
1138                         selected_hour -= 12;\r
1139                     if (selected_hour === 0)\r
1140                         selected_hour = 12;\r
1141                 }\r
1142 \r
1143                 for (i = start; i <= end; i++) {\r
1144 \r
1145                     if (i == selected_hour) {\r
1146                         html += '<option value="' + i + '" selected="selected">' + i + '</option>';\r
1147                     } else if (i < min_hour || i > max_hour) {\r
1148                         html += '<option value="' + i + '" disabled="disabled" class="disabled">' + i + '</option>';\r
1149                     } else {\r
1150                         html += '<option value="' + i + '">' + i + '</option>';\r
1151                     }\r
1152                 }\r
1153 \r
1154                 html += '</select> : ';\r
1155 \r
1156                 html += '<select class="minuteselect">';\r
1157 \r
1158                 // Disallow selections before the minDate or after the maxDate\r
1159                 var min_minute = 0;\r
1160                 var max_minute = 59;\r
1161 \r
1162                 if (minDate && (side == 'left' || this.singleDatePicker) && selected.format('YYYY-MM-DD h A') == minDate.format('YYYY-MM-DD h A')) {\r
1163                     min_minute = minDate.minute();\r
1164                     if (selected.minute() < min_minute)\r
1165                         selected.minute(min_minute);\r
1166                 }\r
1167 \r
1168                 if (maxDate && (side == 'right' || this.singleDatePicker) && selected.format('YYYY-MM-DD h A') == maxDate.format('YYYY-MM-DD h A')) {\r
1169                     max_minute = maxDate.minute();\r
1170                     if (selected.minute() > max_minute)\r
1171                         selected.minute(max_minute);\r
1172                 }\r
1173 \r
1174                 for (i = 0; i < 60; i += this.timePickerIncrement) {\r
1175                     var num = i;\r
1176                     if (num < 10)\r
1177                         num = '0' + num;\r
1178                     if (i == selected.minute()) {\r
1179                         html += '<option value="' + i + '" selected="selected">' + num + '</option>';\r
1180                     } else if (i < min_minute || i > max_minute) {\r
1181                         html += '<option value="' + i + '" disabled="disabled" class="disabled">' + num + '</option>';\r
1182                     } else {\r
1183                         html += '<option value="' + i + '">' + num + '</option>';\r
1184                     }\r
1185                 }\r
1186 \r
1187                 html += '</select> ';\r
1188 \r
1189                 if (this.timePickerSeconds) {\r
1190                     html += ': <select class="secondselect">';\r
1191 \r
1192                     for (i = 0; i < 60; i += this.timePickerIncrement) {\r
1193                         var num = i;\r
1194                         if (num < 10)\r
1195                             num = '0' + num;\r
1196                         if (i == selected.second()) {\r
1197                             html += '<option value="' + i + '" selected="selected">' + num + '</option>';\r
1198                         } else {\r
1199                             html += '<option value="' + i + '">' + num + '</option>';\r
1200                         }\r
1201                     }\r
1202 \r
1203                     html += '</select>';\r
1204                 }\r
1205 \r
1206                 if (this.timePicker12Hour) {\r
1207                     html += '<select class="ampmselect">';\r
1208 \r
1209                     // Disallow selection before the minDate or after the maxDate\r
1210                     var am_html = '';\r
1211                     var pm_html = '';\r
1212 \r
1213                     if (minDate && (side == 'left' || this.singleDatePicker) && selected.format('YYYY-MM-DD') == minDate.format('YYYY-MM-DD') && minDate.hour() >= 12) {\r
1214                         am_html = ' disabled="disabled" class="disabled"';\r
1215                     }\r
1216 \r
1217                     if (maxDate && (side == 'right' || this.singleDatePicker) && selected.format('YYYY-MM-DD') == maxDate.format('YYYY-MM-DD') && maxDate.hour() < 12) {\r
1218                         pm_html = ' disabled="disabled" class="disabled"';\r
1219                     }\r
1220 \r
1221                     if (selected.hour() >= 12) {\r
1222                         html += '<option value="AM"' + am_html + '>AM</option><option value="PM" selected="selected"' + pm_html + '>PM</option>';\r
1223                     } else {\r
1224                         html += '<option value="AM" selected="selected"' + am_html + '>AM</option><option value="PM"' + pm_html + '>PM</option>';\r
1225                     }\r
1226                     html += '</select>';\r
1227                 }\r
1228 \r
1229                 html += '</div>';\r
1230 \r
1231             }\r
1232 \r
1233             return html;\r
1234 \r
1235         },\r
1236 \r
1237         remove: function() {\r
1238 \r
1239             this.container.remove();\r
1240             this.element.off('.daterangepicker');\r
1241             this.element.removeData('daterangepicker');\r
1242 \r
1243         }\r
1244 \r
1245     };\r
1246 \r
1247     $.fn.daterangepicker = function (options, cb) {\r
1248         this.each(function () {\r
1249             var el = $(this);\r
1250             if (el.data('daterangepicker'))\r
1251                 el.data('daterangepicker').remove();\r
1252             el.data('daterangepicker', new DateRangePicker(el, options, cb));\r
1253         });\r
1254         return this;\r
1255     };\r
1256 \r
1257 }));\r