bootstrap-daterangepicker-rails 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 74d416af849d9db6a14e6c7f8482f1004e50b412
4
- data.tar.gz: 797929b9a3d13cf612c4e46eace69c57618cb678
3
+ metadata.gz: f1d75cabce4f55c23f925accb2b9d42a1b52f79b
4
+ data.tar.gz: 21aae648963dd016bcdfb1676b5123fe5d19d81f
5
5
  SHA512:
6
- metadata.gz: e439b6cfe45fee1e62511918638de8e8ca626615dae18f4637199937dd6905cb2c58bee20767434fe31f71f118f1dcd96d177952cdbc0d2b41b8e7743f311293
7
- data.tar.gz: e0492dcca44816bfab49044b360a4b7f8a91ef42f3b78ed1a91d4d797facc2f74097139ab308af86e48939d0423e80b02d672bbe220b62b20716449c03cb7fa7
6
+ metadata.gz: c62e627da471ab781c336f2209b5b0f8c3ecdad7241395758782df032c80230e312125ef08690616a31a353ebb2b2b0c141a486c103b2a4a39d6158b8d24a904
7
+ data.tar.gz: b02190fa29cec461a390f52bd55b68cdd6ba1a4ad6d7d146657d4e8f4fa933caa768e894cc10917dc19efeee3ccefbae27a60a93c8e08894c804c68cdb7b834b
data/README.md CHANGED
@@ -1,10 +1,5 @@
1
1
  # Date Range Picker for Twitter Bootstrap
2
2
 
3
- To use with Rails 4.x, use this branch: https://github.com/jordanbrock/bootstrap-daterangepicker-rails/tree/rails4
4
-
5
- Thanks to https://github.com/allomov for doing all the work on the 4.x branch.
6
-
7
-
8
3
  _Description from DateRangePicker for Twitter Bootstrap_
9
4
 
10
5
  This date range picker component for Twitter Bootstrap creates a dropdown menu from which a user can
@@ -17,20 +12,21 @@ into the text box. Otherwise, you can provide a custom callback function to rece
17
12
 
18
13
  [Live demo & option usage examples](http://www.dangrossman.info/2012/08/20/a-date-range-picker-for-twitter-bootstrap/)
19
14
 
20
- ## Usage
15
+ ## Installation and Usage
21
16
 
22
17
  This component relies on [Twitter Bootstrap](http://twitter.github.com/bootstrap/),
23
18
  [momentjs](http://www.momentjs.com/) and [jQuery](http://jquery.com/).
24
19
 
25
- Basic usage:
20
+ Basic usage (with Bootstrap 3)
21
+
22
+ (Suffix `daterangepicker` with `-bs2` or `-bs3` for your version of Bootstrap.)
26
23
 
27
24
  ```
28
25
 
29
26
  # Gemfile
30
27
  gem 'jquery-rails'
28
+ gem 'momentjs-rails'
31
29
  gem 'bootstrap-daterangepicker-rails'
32
- gem 'coffee-rails'
33
-
34
30
 
35
31
  # application.js
36
32
 
@@ -42,7 +38,7 @@ gem 'coffee-rails'
42
38
 
43
39
  /*
44
40
  *= require bootstrap
45
- *= require daterangepicker
41
+ *= require daterangepicker-bs3
46
42
  */
47
43
 
48
44
 
@@ -64,6 +60,11 @@ Additional options allow:
64
60
 
65
61
  Syntax for all the options can be found in the examples.html file.
66
62
 
63
+
64
+ ## Thanks
65
+
66
+ Thanks to https://github.com/allomov for doing all the work on the 4.x branch.
67
+
67
68
  ## License
68
69
 
69
70
  This code is made available under the [Apache License v2.0](http://www.apache.org/licenses/LICENSE-2.0),
@@ -1,7 +1,7 @@
1
1
  module Bootstrap
2
2
  module Daterangepicker
3
3
  module Rails
4
- VERSION = '0.0.8'
4
+ VERSION = '0.0.9'
5
5
  end
6
6
  end
7
7
  end
@@ -1,53 +1,14 @@
1
1
  /**
2
- * @version: 1.2
2
+ * @version: 1.3.8
3
3
  * @author: Dan Grossman http://www.dangrossman.info/
4
- * @date: 2013-07-25
5
- * @copyright: Copyright (c) 2012-2013 Dan Grossman. All rights reserved.
4
+ * @date: 2014-07-10
5
+ * @copyright: Copyright (c) 2012-2014 Dan Grossman. All rights reserved.
6
6
  * @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0
7
7
  * @website: http://www.improvely.com/
8
8
  */
9
- !function ($) {
9
+ !function ($, moment) {
10
10
 
11
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-small'];
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
12
 
52
13
  // by default, the daterangepicker element is placed at the bottom of HTML body
53
14
  this.parentEl = 'body';
@@ -55,131 +16,182 @@
55
16
  //element that triggered the date range picker
56
17
  this.element = $(element);
57
18
 
58
- if (this.element.hasClass('pull-right'))
59
- this.opens = 'left';
60
-
61
- if (this.element.is('input')) {
62
- this.element.on({
63
- click: $.proxy(this.show, this),
64
- focus: $.proxy(this.show, this)
65
- });
66
- } else {
67
- this.element.on('click', $.proxy(this.show, this));
68
- }
69
-
70
- localeObject = this.locale;
71
-
72
- if (hasOptions) {
73
- if (typeof options.locale == 'object') {
74
- $.each(localeObject, function (property, value) {
75
- localeObject[property] = options.locale[property] || value;
76
- });
77
- }
78
-
79
- if (options.applyClass) {
80
- this.applyClass = options.applyClass;
81
- }
82
-
83
- if (options.cancelClass) {
84
- this.cancelClass = options.cancelClass;
85
- }
86
- }
19
+ //tracks visible state
20
+ this.isShowing = false;
87
21
 
22
+ //create the picker HTML object
88
23
  var DRPTemplate = '<div class="daterangepicker dropdown-menu">' +
89
24
  '<div class="calendar left"></div>' +
90
25
  '<div class="calendar right"></div>' +
91
26
  '<div class="ranges">' +
92
27
  '<div class="range_inputs">' +
93
- '<div class="daterangepicker_start_input" style="float: left">' +
94
- '<label for="daterangepicker_start">' + this.locale.fromLabel + '</label>' +
95
- '<input class="input-mini" type="text" name="daterangepicker_start" value="" disabled="disabled" />' +
28
+ '<div class="daterangepicker_start_input">' +
29
+ '<label for="daterangepicker_start"></label>' +
30
+ '<input class="input-mini" type="text" name="daterangepicker_start" value="" readonly="readonly" />' +
96
31
  '</div>' +
97
- '<div class="daterangepicker_end_input" style="float: left; padding-left: 11px">' +
98
- '<label for="daterangepicker_end">' + this.locale.toLabel + '</label>' +
99
- '<input class="input-mini" type="text" name="daterangepicker_end" value="" disabled="disabled" />' +
32
+ '<div class="daterangepicker_end_input">' +
33
+ '<label for="daterangepicker_end"></label>' +
34
+ '<input class="input-mini" type="text" name="daterangepicker_end" value="" readonly="readonly" />' +
100
35
  '</div>' +
101
- '<button class="' + this.applyClass + ' applyBtn" disabled="disabled">' + this.locale.applyLabel + '</button>&nbsp;' +
102
- '<button class="' + this.cancelClass + ' cancelBtn">' + this.locale.cancelLabel + '</button>' +
36
+ '<button class="applyBtn" disabled="disabled"></button>&nbsp;' +
37
+ '<button class="cancelBtn"></button>' +
103
38
  '</div>' +
104
39
  '</div>' +
105
40
  '</div>';
106
41
 
107
- this.parentEl = (hasOptions && options.parentEl && $(options.parentEl)) || $(this.parentEl);
108
- //the date range picker
42
+ //custom options
43
+ if (typeof options !== 'object' || options === null)
44
+ options = {};
45
+
46
+ this.parentEl = (typeof options === 'object' && options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl);
109
47
  this.container = $(DRPTemplate).appendTo(this.parentEl);
110
48
 
111
- if (hasOptions) {
49
+ this.setOptions(options, cb);
50
+
51
+ //apply CSS classes and labels to buttons
52
+ var c = this.container;
53
+ $.each(this.buttonClasses, function (idx, val) {
54
+ c.find('button').addClass(val);
55
+ });
56
+ this.container.find('.daterangepicker_start_input label').html(this.locale.fromLabel);
57
+ this.container.find('.daterangepicker_end_input label').html(this.locale.toLabel);
58
+ if (this.applyClass.length)
59
+ this.container.find('.applyBtn').addClass(this.applyClass);
60
+ if (this.cancelClass.length)
61
+ this.container.find('.cancelBtn').addClass(this.cancelClass);
62
+ this.container.find('.applyBtn').html(this.locale.applyLabel);
63
+ this.container.find('.cancelBtn').html(this.locale.cancelLabel);
64
+
65
+ //event listeners
66
+
67
+ this.container.find('.calendar')
68
+ .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))
69
+ .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))
70
+ .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this))
71
+ .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.enterDate, this))
72
+ .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this))
73
+ .on('change.daterangepicker', 'select.yearselect', $.proxy(this.updateMonthYear, this))
74
+ .on('change.daterangepicker', 'select.monthselect', $.proxy(this.updateMonthYear, this))
75
+ .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.ampmselect', $.proxy(this.updateTime, this));
76
+
77
+ this.container.find('.ranges')
78
+ .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))
79
+ .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))
80
+ .on('click.daterangepicker', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this))
81
+ .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))
82
+ .on('mouseenter.daterangepicker', 'li', $.proxy(this.enterRange, this))
83
+ .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));
112
84
 
113
- if (typeof options.format == 'string')
85
+ if (this.element.is('input')) {
86
+ this.element.on({
87
+ 'click.daterangepicker': $.proxy(this.show, this),
88
+ 'focus.daterangepicker': $.proxy(this.show, this),
89
+ 'keyup.daterangepicker': $.proxy(this.updateFromControl, this)
90
+ });
91
+ } else {
92
+ this.element.on('click.daterangepicker', $.proxy(this.toggle, this));
93
+ }
94
+
95
+ };
96
+
97
+ DateRangePicker.prototype = {
98
+
99
+ constructor: DateRangePicker,
100
+
101
+ setOptions: function(options, callback) {
102
+
103
+ this.startDate = moment().startOf('day');
104
+ this.endDate = moment().endOf('day');
105
+ this.minDate = false;
106
+ this.maxDate = false;
107
+ this.dateLimit = false;
108
+
109
+ this.showDropdowns = false;
110
+ this.showWeekNumbers = false;
111
+ this.timePicker = false;
112
+ this.timePickerIncrement = 30;
113
+ this.timePicker12Hour = true;
114
+ this.singleDatePicker = false;
115
+ this.ranges = {};
116
+
117
+ this.opens = 'right';
118
+ if (this.element.hasClass('pull-right'))
119
+ this.opens = 'left';
120
+
121
+ this.buttonClasses = ['btn', 'btn-small btn-sm'];
122
+ this.applyClass = 'btn-success';
123
+ this.cancelClass = 'btn-default';
124
+
125
+ this.format = 'MM/DD/YYYY';
126
+ this.separator = ' - ';
127
+
128
+ this.locale = {
129
+ applyLabel: 'Apply',
130
+ cancelLabel: 'Cancel',
131
+ fromLabel: 'From',
132
+ toLabel: 'To',
133
+ weekLabel: 'W',
134
+ customRangeLabel: 'Custom Range',
135
+ daysOfWeek: moment()._lang._weekdaysMin.slice(),
136
+ monthNames: moment()._lang._monthsShort.slice(),
137
+ firstDay: 0
138
+ };
139
+
140
+ this.cb = function () { };
141
+
142
+ if (typeof options.format === 'string')
114
143
  this.format = options.format;
115
144
 
116
- if (typeof options.separator == 'string')
145
+ if (typeof options.separator === 'string')
117
146
  this.separator = options.separator;
118
147
 
119
- if (typeof options.startDate == 'string')
148
+ if (typeof options.startDate === 'string')
120
149
  this.startDate = moment(options.startDate, this.format);
121
150
 
122
- if (typeof options.endDate == 'string')
151
+ if (typeof options.endDate === 'string')
123
152
  this.endDate = moment(options.endDate, this.format);
124
153
 
125
- if (typeof options.minDate == 'string')
154
+ if (typeof options.minDate === 'string')
126
155
  this.minDate = moment(options.minDate, this.format);
127
156
 
128
- if (typeof options.maxDate == 'string')
157
+ if (typeof options.maxDate === 'string')
129
158
  this.maxDate = moment(options.maxDate, this.format);
130
159
 
131
- if (typeof options.startDate == 'object')
160
+ if (typeof options.startDate === 'object')
132
161
  this.startDate = moment(options.startDate);
133
162
 
134
- if (typeof options.endDate == 'object')
163
+ if (typeof options.endDate === 'object')
135
164
  this.endDate = moment(options.endDate);
136
165
 
137
- if (typeof options.minDate == 'object')
166
+ if (typeof options.minDate === 'object')
138
167
  this.minDate = moment(options.minDate);
139
168
 
140
- if (typeof options.maxDate == 'object')
169
+ if (typeof options.maxDate === 'object')
141
170
  this.maxDate = moment(options.maxDate);
142
171
 
143
- if (typeof options.ranges == 'object') {
144
- for (var range in options.ranges) {
145
-
146
- var start = moment(options.ranges[range][0]);
147
- var end = moment(options.ranges[range][1]);
172
+ if (typeof options.applyClass === 'string')
173
+ this.applyClass = options.applyClass;
148
174
 
149
- // If we have a min/max date set, bound this range
150
- // to it, but only if it would otherwise fall
151
- // outside of the min/max.
152
- if (this.minDate && start.isBefore(this.minDate))
153
- start = moment(this.minDate);
175
+ if (typeof options.cancelClass === 'string')
176
+ this.cancelClass = options.cancelClass;
154
177
 
155
- if (this.maxDate && end.isAfter(this.maxDate))
156
- end = moment(this.maxDate);
178
+ if (typeof options.dateLimit === 'object')
179
+ this.dateLimit = options.dateLimit;
157
180
 
158
- // If the end of the range is before the minimum (if min is set) OR
159
- // the start of the range is after the max (also if set) don't display this
160
- // range option.
161
- if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) {
162
- continue;
163
- }
181
+ // update day names order to firstDay
182
+ if (typeof options.locale === 'object') {
164
183
 
165
- this.ranges[range] = [start, end];
184
+ if (typeof options.locale.daysOfWeek === 'object') {
185
+ // Create a copy of daysOfWeek to avoid modification of original
186
+ // options object for reusability in multiple daterangepicker instances
187
+ this.locale.daysOfWeek = options.locale.daysOfWeek.slice();
166
188
  }
167
189
 
168
- var list = '<ul>';
169
- for (var range in this.ranges) {
170
- list += '<li>' + range + '</li>';
190
+ if (typeof options.locale.monthNames === 'object') {
191
+ this.locale.monthNames = options.locale.monthNames.slice();
171
192
  }
172
- list += '<li>' + this.locale.customRangeLabel + '</li>';
173
- list += '</ul>';
174
- this.container.find('.ranges').prepend(list);
175
- }
176
193
 
177
- if (typeof options.dateLimit == 'object')
178
- this.dateLimit = options.dateLimit;
179
-
180
- // update day names order to firstDay
181
- if (typeof options.locale == 'object') {
182
- if (typeof options.locale.firstDay == 'number') {
194
+ if (typeof options.locale.firstDay === 'number') {
183
195
  this.locale.firstDay = options.locale.firstDay;
184
196
  var iterator = options.locale.firstDay;
185
197
  while (iterator > 0) {
@@ -187,140 +199,215 @@
187
199
  iterator--;
188
200
  }
189
201
  }
202
+
203
+ if (typeof options.locale.applyLabel === 'string') {
204
+ this.locale.applyLabel = options.locale.applyLabel;
205
+ }
206
+
207
+ if (typeof options.locale.cancelLabel === 'string') {
208
+ this.locale.cancelLabel = options.locale.cancelLabel;
209
+ }
210
+
211
+ if (typeof options.locale.fromLabel === 'string') {
212
+ this.locale.fromLabel = options.locale.fromLabel;
213
+ }
214
+
215
+ if (typeof options.locale.toLabel === 'string') {
216
+ this.locale.toLabel = options.locale.toLabel;
217
+ }
218
+
219
+ if (typeof options.locale.weekLabel === 'string') {
220
+ this.locale.weekLabel = options.locale.weekLabel;
221
+ }
222
+
223
+ if (typeof options.locale.customRangeLabel === 'string') {
224
+ this.locale.customRangeLabel = options.locale.customRangeLabel;
225
+ }
190
226
  }
191
227
 
192
- if (typeof options.opens == 'string')
228
+ if (typeof options.opens === 'string')
193
229
  this.opens = options.opens;
194
230
 
195
- if (typeof options.showWeekNumbers == 'boolean') {
231
+ if (typeof options.showWeekNumbers === 'boolean') {
196
232
  this.showWeekNumbers = options.showWeekNumbers;
197
233
  }
198
234
 
199
- if (typeof options.buttonClasses == 'string') {
235
+ if (typeof options.buttonClasses === 'string') {
200
236
  this.buttonClasses = [options.buttonClasses];
201
237
  }
202
238
 
203
- if (typeof options.buttonClasses == 'object') {
239
+ if (typeof options.buttonClasses === 'object') {
204
240
  this.buttonClasses = options.buttonClasses;
205
241
  }
206
242
 
207
- if (typeof options.showDropdowns == 'boolean') {
243
+ if (typeof options.showDropdowns === 'boolean') {
208
244
  this.showDropdowns = options.showDropdowns;
209
245
  }
210
246
 
211
- if (typeof options.timePicker == 'boolean') {
247
+ if (typeof options.singleDatePicker === 'boolean') {
248
+ this.singleDatePicker = options.singleDatePicker;
249
+ }
250
+
251
+ if (typeof options.timePicker === 'boolean') {
212
252
  this.timePicker = options.timePicker;
213
253
  }
214
254
 
215
- if (typeof options.timePickerIncrement == 'number') {
255
+ if (typeof options.timePickerIncrement === 'number') {
216
256
  this.timePickerIncrement = options.timePickerIncrement;
217
257
  }
218
258
 
219
- if (typeof options.timePicker12Hour == 'boolean') {
259
+ if (typeof options.timePicker12Hour === 'boolean') {
220
260
  this.timePicker12Hour = options.timePicker12Hour;
221
261
  }
222
262
 
223
- }
224
-
225
- if (!this.timePicker) {
226
- this.startDate = this.startDate.startOf('day');
227
- this.endDate = this.endDate.startOf('day');
228
- }
263
+ var start, end, range;
264
+
265
+ //if no start/end dates set, check if an input element contains initial values
266
+ if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {
267
+ if ($(this.element).is('input[type=text]')) {
268
+ var val = $(this.element).val();
269
+ var split = val.split(this.separator);
270
+ start = end = null;
271
+ if (split.length == 2) {
272
+ start = moment(split[0], this.format);
273
+ end = moment(split[1], this.format);
274
+ } else if (this.singleDatePicker) {
275
+ start = moment(val, this.format);
276
+ end = moment(val, this.format);
277
+ }
278
+ if (start !== null && end !== null) {
279
+ this.startDate = start;
280
+ this.endDate = end;
281
+ }
282
+ }
283
+ }
229
284
 
230
- //apply CSS classes to buttons
231
- var c = this.container;
232
- $.each(this.buttonClasses, function (idx, val) {
233
- c.find('button').addClass(val);
234
- });
285
+ if (typeof options.ranges === 'object') {
286
+ for (range in options.ranges) {
235
287
 
236
- if (this.opens == 'right') {
237
- //swap calendar positions
238
- var left = this.container.find('.calendar.left');
239
- var right = this.container.find('.calendar.right');
240
- left.removeClass('left').addClass('right');
241
- right.removeClass('right').addClass('left');
242
- }
288
+ start = moment(options.ranges[range][0]);
289
+ end = moment(options.ranges[range][1]);
243
290
 
244
- if (typeof options == 'undefined' || typeof options.ranges == 'undefined') {
245
- this.container.find('.calendar').show();
246
- this.move();
247
- }
291
+ // If we have a min/max date set, bound this range
292
+ // to it, but only if it would otherwise fall
293
+ // outside of the min/max.
294
+ if (this.minDate && start.isBefore(this.minDate))
295
+ start = moment(this.minDate);
248
296
 
249
- if (typeof cb == 'function')
250
- this.cb = cb;
297
+ if (this.maxDate && end.isAfter(this.maxDate))
298
+ end = moment(this.maxDate);
251
299
 
252
- this.container.addClass('opens' + this.opens);
300
+ // If the end of the range is before the minimum (if min is set) OR
301
+ // the start of the range is after the max (also if set) don't display this
302
+ // range option.
303
+ if ((this.minDate && end.isBefore(this.minDate)) || (this.maxDate && start.isAfter(this.maxDate))) {
304
+ continue;
305
+ }
253
306
 
254
- //try parse date if in text input
255
- if (!hasOptions || (typeof options.startDate == 'undefined' && typeof options.endDate == 'undefined')) {
256
- if ($(this.element).is('input[type=text]')) {
257
- var val = $(this.element).val();
258
- var split = val.split(this.separator);
259
- var start, end;
260
- if (split.length == 2) {
261
- start = moment(split[0], this.format);
262
- end = moment(split[1], this.format);
307
+ this.ranges[range] = [start, end];
263
308
  }
264
- if (start != null && end != null) {
265
- this.startDate = start;
266
- this.endDate = end;
309
+
310
+ var list = '<ul>';
311
+ for (range in this.ranges) {
312
+ list += '<li>' + range + '</li>';
267
313
  }
314
+ list += '<li>' + this.locale.customRangeLabel + '</li>';
315
+ list += '</ul>';
316
+ this.container.find('.ranges ul').remove();
317
+ this.container.find('.ranges').prepend(list);
318
+ }
319
+
320
+ if (typeof callback === 'function') {
321
+ this.cb = callback;
322
+ }
323
+
324
+ if (!this.timePicker) {
325
+ this.startDate = this.startDate.startOf('day');
326
+ this.endDate = this.endDate.endOf('day');
268
327
  }
269
- }
270
328
 
271
- //state
272
- this.oldStartDate = this.startDate.clone();
273
- this.oldEndDate = this.endDate.clone();
329
+ if (this.singleDatePicker) {
330
+ this.opens = 'right';
331
+ this.container.find('.calendar.right').show();
332
+ this.container.find('.calendar.left').hide();
333
+ this.container.find('.ranges').hide();
334
+ if (!this.container.find('.calendar.right').hasClass('single'))
335
+ this.container.find('.calendar.right').addClass('single');
336
+ } else {
337
+ this.container.find('.calendar.right').removeClass('single');
338
+ this.container.find('.ranges').show();
339
+ }
274
340
 
275
- this.leftCalendar = {
276
- month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]),
277
- calendar: []
278
- };
341
+ this.oldStartDate = this.startDate.clone();
342
+ this.oldEndDate = this.endDate.clone();
343
+ this.oldChosenLabel = this.chosenLabel;
279
344
 
280
- this.rightCalendar = {
281
- month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]),
282
- calendar: []
283
- };
345
+ this.leftCalendar = {
346
+ month: moment([this.startDate.year(), this.startDate.month(), 1, this.startDate.hour(), this.startDate.minute()]),
347
+ calendar: []
348
+ };
284
349
 
285
- //event listeners
286
- this.container.on('mousedown', $.proxy(this.mousedown, this));
350
+ this.rightCalendar = {
351
+ month: moment([this.endDate.year(), this.endDate.month(), 1, this.endDate.hour(), this.endDate.minute()]),
352
+ calendar: []
353
+ };
287
354
 
288
- this.container.find('.calendar')
289
- .on('click', '.prev', $.proxy(this.clickPrev, this))
290
- .on('click', '.next', $.proxy(this.clickNext, this))
291
- .on('click', 'td.available', $.proxy(this.clickDate, this))
292
- .on('mouseenter', 'td.available', $.proxy(this.enterDate, this))
293
- .on('mouseleave', 'td.available', $.proxy(this.updateFormInputs, this))
294
- .on('change', 'select.yearselect', $.proxy(this.updateMonthYear, this))
295
- .on('change', 'select.monthselect', $.proxy(this.updateMonthYear, this))
296
- .on('change', 'select.hourselect,select.minuteselect,select.ampmselect', $.proxy(this.updateTime, this));
355
+ if (this.opens == 'right') {
356
+ //swap calendar positions
357
+ var left = this.container.find('.calendar.left');
358
+ var right = this.container.find('.calendar.right');
359
+ left.removeClass('left').addClass('right');
360
+ right.removeClass('right').addClass('left');
361
+ }
297
362
 
298
- this.container.find('.ranges')
299
- .on('click', 'button.applyBtn', $.proxy(this.clickApply, this))
300
- .on('click', 'button.cancelBtn', $.proxy(this.clickCancel, this))
301
- .on('click', '.daterangepicker_start_input,.daterangepicker_end_input', $.proxy(this.showCalendars, this))
302
- .on('click', 'li', $.proxy(this.clickRange, this))
303
- .on('mouseenter', 'li', $.proxy(this.enterRange, this))
304
- .on('mouseleave', 'li', $.proxy(this.updateFormInputs, this));
363
+ if (typeof options.ranges === 'undefined' && !this.singleDatePicker) {
364
+ this.container.addClass('show-calendar');
365
+ }
305
366
 
306
- this.element.on('keyup', $.proxy(this.updateFromControl, this));
367
+ this.container.addClass('opens' + this.opens);
307
368
 
308
- this.updateView();
309
- this.updateCalendars();
369
+ this.updateView();
370
+ this.updateCalendars();
310
371
 
311
- };
372
+ },
312
373
 
313
- DateRangePicker.prototype = {
374
+ setStartDate: function(startDate) {
375
+ if (typeof startDate === 'string')
376
+ this.startDate = moment(startDate, this.format);
314
377
 
315
- constructor: DateRangePicker,
378
+ if (typeof startDate === 'object')
379
+ this.startDate = moment(startDate);
380
+
381
+ if (!this.timePicker)
382
+ this.startDate = this.startDate.startOf('day');
383
+
384
+ this.oldStartDate = this.startDate.clone();
385
+
386
+ this.updateView();
387
+ this.updateCalendars();
388
+ this.updateInputText();
389
+ },
316
390
 
317
- mousedown: function (e) {
318
- e.stopPropagation();
391
+ setEndDate: function(endDate) {
392
+ if (typeof endDate === 'string')
393
+ this.endDate = moment(endDate, this.format);
394
+
395
+ if (typeof endDate === 'object')
396
+ this.endDate = moment(endDate);
397
+
398
+ if (!this.timePicker)
399
+ this.endDate = this.endDate.endOf('day');
400
+
401
+ this.oldEndDate = this.endDate.clone();
402
+
403
+ this.updateView();
404
+ this.updateCalendars();
405
+ this.updateInputText();
319
406
  },
320
407
 
321
408
  updateView: function () {
322
- this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());
323
- this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());
409
+ this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute());
410
+ this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year()).hour(this.endDate.hour()).minute(this.endDate.minute());
324
411
  this.updateFormInputs();
325
412
  },
326
413
 
@@ -339,11 +426,20 @@
339
426
  if (!this.element.is('input')) return;
340
427
  if (!this.element.val().length) return;
341
428
 
342
- var dateString = this.element.val().split(this.separator);
343
- var start = moment(dateString[0], this.format);
344
- var end = moment(dateString[1], this.format);
429
+ var dateString = this.element.val().split(this.separator),
430
+ start = null,
431
+ end = null;
432
+
433
+ if(dateString.length === 2) {
434
+ start = moment(dateString[0], this.format);
435
+ end = moment(dateString[1], this.format);
436
+ }
437
+
438
+ if (this.singleDatePicker || start === null || end === null) {
439
+ start = moment(this.element.val(), this.format);
440
+ end = start;
441
+ }
345
442
 
346
- if (start == null || end == null) return;
347
443
  if (end.isBefore(start)) return;
348
444
 
349
445
  this.oldStartDate = this.startDate.clone();
@@ -360,14 +456,18 @@
360
456
 
361
457
  notify: function () {
362
458
  this.updateView();
363
- this.cb(this.startDate, this.endDate);
459
+ this.cb(this.startDate, this.endDate, this.chosenLabel);
364
460
  },
365
461
 
366
462
  move: function () {
367
- var parentOffset = {
368
- top: this.parentEl.offset().top - (this.parentEl.is('body') ? 0 : this.parentEl.scrollTop()),
369
- left: this.parentEl.offset().left - (this.parentEl.is('body') ? 0 : this.parentEl.scrollLeft())
370
- };
463
+ var parentOffset = { top: 0, left: 0 };
464
+ if (!this.parentEl.is('body')) {
465
+ parentOffset = {
466
+ top: this.parentEl.offset().top - this.parentEl.scrollTop(),
467
+ left: this.parentEl.offset().left - this.parentEl.scrollLeft()
468
+ };
469
+ }
470
+
371
471
  if (this.opens == 'left') {
372
472
  this.container.css({
373
473
  top: this.element.offset().top + this.element.outerHeight() - parentOffset.top,
@@ -395,20 +495,56 @@
395
495
  }
396
496
  },
397
497
 
498
+ toggle: function (e) {
499
+ if (this.element.hasClass('active')) {
500
+ this.hide();
501
+ } else {
502
+ this.show();
503
+ }
504
+ },
505
+
398
506
  show: function (e) {
507
+ if (this.isShowing) return;
508
+
509
+ this.element.addClass('active');
399
510
  this.container.show();
400
511
  this.move();
401
512
 
402
- if (e) {
403
- e.stopPropagation();
404
- e.preventDefault();
405
- }
513
+ // Create a click proxy that is private to this instance of datepicker, for unbinding
514
+ this._outsideClickProxy = $.proxy(function (e) { this.outsideClick(e); }, this);
515
+ // Bind global datepicker mousedown for hiding and
516
+ $(document)
517
+ .on('mousedown.daterangepicker', this._outsideClickProxy)
518
+ // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them
519
+ .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)
520
+ // and also close when focus changes to outside the picker (eg. tabbing between controls)
521
+ .on('focusin.daterangepicker', this._outsideClickProxy);
522
+
523
+ this.isShowing = true;
524
+ this.element.trigger('show.daterangepicker', this);
525
+ },
406
526
 
407
- $(document).on('mousedown', $.proxy(this.hide, this));
408
- this.element.trigger('shown', {target: e.target, picker: this});
527
+ outsideClick: function (e) {
528
+ var target = $(e.target);
529
+ // if the page is clicked anywhere except within the daterangerpicker/button
530
+ // itself then call this.hide()
531
+ if (
532
+ target.closest(this.element).length ||
533
+ target.closest(this.container).length ||
534
+ target.closest('.calendar-date').length
535
+ ) return;
536
+ this.hide();
409
537
  },
410
538
 
411
539
  hide: function (e) {
540
+ if (!this.isShowing) return;
541
+
542
+ $(document)
543
+ .off('mousedown.daterangepicker')
544
+ .off('click.daterangepicker', '[data-toggle=dropdown]')
545
+ .off('focusin.daterangepicker');
546
+
547
+ this.element.removeClass('active');
412
548
  this.container.hide();
413
549
 
414
550
  if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))
@@ -417,11 +553,12 @@
417
553
  this.oldStartDate = this.startDate.clone();
418
554
  this.oldEndDate = this.endDate.clone();
419
555
 
420
- $(document).off('mousedown', this.hide);
421
- this.element.trigger('hidden', { picker: this });
556
+ this.isShowing = false;
557
+ this.element.trigger('hide.daterangepicker', this);
422
558
  },
423
559
 
424
560
  enterRange: function (e) {
561
+ // mouse pointer has entered a range label
425
562
  var label = e.target.innerHTML;
426
563
  if (label == this.locale.customRangeLabel) {
427
564
  this.updateView();
@@ -433,17 +570,27 @@
433
570
  },
434
571
 
435
572
  showCalendars: function() {
436
- this.container.find('.calendar').show();
573
+ this.container.addClass('show-calendar');
437
574
  this.move();
575
+ this.element.trigger('showCalendar.daterangepicker', this);
576
+ },
577
+
578
+ hideCalendars: function() {
579
+ this.container.removeClass('show-calendar');
580
+ this.element.trigger('hideCalendar.daterangepicker', this);
438
581
  },
439
582
 
440
583
  updateInputText: function() {
441
- if (this.element.is('input'))
584
+ if (this.element.is('input') && !this.singleDatePicker) {
442
585
  this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));
586
+ } else if (this.element.is('input')) {
587
+ this.element.val(this.startDate.format(this.format));
588
+ }
443
589
  },
444
590
 
445
591
  clickRange: function (e) {
446
592
  var label = e.target.innerHTML;
593
+ this.chosenLabel = label;
447
594
  if (label == this.locale.customRangeLabel) {
448
595
  this.showCalendars();
449
596
  } else {
@@ -454,7 +601,7 @@
454
601
 
455
602
  if (!this.timePicker) {
456
603
  this.startDate.startOf('day');
457
- this.endDate.startOf('day');
604
+ this.endDate.endOf('day');
458
605
  }
459
606
 
460
607
  this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year()).hour(this.startDate.hour()).minute(this.startDate.minute());
@@ -463,8 +610,9 @@
463
610
 
464
611
  this.updateInputText();
465
612
 
466
- this.container.find('.calendar').hide();
613
+ this.hideCalendars();
467
614
  this.hide();
615
+ this.element.trigger('apply.daterangepicker', this);
468
616
  }
469
617
  },
470
618
 
@@ -509,19 +657,20 @@
509
657
  var col = title.substr(3, 1);
510
658
  var cal = $(e.target).parents('.calendar');
511
659
 
660
+ var startDate, endDate;
512
661
  if (cal.hasClass('left')) {
513
- var startDate = this.leftCalendar.calendar[row][col];
514
- var endDate = this.endDate;
515
- if (typeof this.dateLimit == 'object') {
662
+ startDate = this.leftCalendar.calendar[row][col];
663
+ endDate = this.endDate;
664
+ if (typeof this.dateLimit === 'object') {
516
665
  var maxDate = moment(startDate).add(this.dateLimit).startOf('day');
517
666
  if (endDate.isAfter(maxDate)) {
518
667
  endDate = maxDate;
519
668
  }
520
669
  }
521
670
  } else {
522
- var startDate = this.startDate;
523
- var endDate = this.rightCalendar.calendar[row][col];
524
- if (typeof this.dateLimit == 'object') {
671
+ startDate = this.startDate;
672
+ endDate = this.rightCalendar.calendar[row][col];
673
+ if (typeof this.dateLimit === 'object') {
525
674
  var minDate = moment(endDate).subtract(this.dateLimit).startOf('day');
526
675
  if (startDate.isBefore(minDate)) {
527
676
  startDate = minDate;
@@ -529,72 +678,80 @@
529
678
  }
530
679
  }
531
680
 
681
+ if (this.singleDatePicker && cal.hasClass('left')) {
682
+ endDate = startDate.clone();
683
+ } else if (this.singleDatePicker && cal.hasClass('right')) {
684
+ startDate = endDate.clone();
685
+ }
686
+
532
687
  cal.find('td').removeClass('active');
533
688
 
534
689
  if (startDate.isSame(endDate) || startDate.isBefore(endDate)) {
535
690
  $(e.target).addClass('active');
536
691
  this.startDate = startDate;
537
692
  this.endDate = endDate;
693
+ this.chosenLabel = this.locale.customRangeLabel;
538
694
  } else if (startDate.isAfter(endDate)) {
539
695
  $(e.target).addClass('active');
696
+ var difference = this.endDate.diff(this.startDate);
540
697
  this.startDate = startDate;
541
- this.endDate = moment(startDate).add('day', 1).startOf('day');
698
+ this.endDate = moment(startDate).add('ms', difference);
699
+ this.chosenLabel = this.locale.customRangeLabel;
542
700
  }
543
701
 
544
702
  this.leftCalendar.month.month(this.startDate.month()).year(this.startDate.year());
545
703
  this.rightCalendar.month.month(this.endDate.month()).year(this.endDate.year());
546
704
  this.updateCalendars();
705
+
706
+ if (!this.timePicker)
707
+ endDate.endOf('day');
708
+
709
+ if (this.singleDatePicker)
710
+ this.clickApply();
547
711
  },
548
712
 
549
713
  clickApply: function (e) {
550
714
  this.updateInputText();
551
715
  this.hide();
716
+ this.element.trigger('apply.daterangepicker', this);
552
717
  },
553
718
 
554
719
  clickCancel: function (e) {
555
720
  this.startDate = this.oldStartDate;
556
721
  this.endDate = this.oldEndDate;
722
+ this.chosenLabel = this.oldChosenLabel;
557
723
  this.updateView();
558
724
  this.updateCalendars();
559
725
  this.hide();
726
+ this.element.trigger('cancel.daterangepicker', this);
560
727
  },
561
728
 
562
729
  updateMonthYear: function (e) {
563
-
564
- var isLeft = $(e.target).closest('.calendar').hasClass('left');
565
- var cal = this.container.find('.calendar.left');
566
- if (!isLeft)
567
- cal = this.container.find('.calendar.right');
730
+ var isLeft = $(e.target).closest('.calendar').hasClass('left'),
731
+ leftOrRight = isLeft ? 'left' : 'right',
732
+ cal = this.container.find('.calendar.'+leftOrRight);
568
733
 
569
734
  // Month must be Number for new moment versions
570
735
  var month = parseInt(cal.find('.monthselect').val(), 10);
571
736
  var year = cal.find('.yearselect').val();
572
737
 
573
- if (isLeft) {
574
- this.leftCalendar.month.month(month).year(year);
575
- } else {
576
- this.rightCalendar.month.month(month).year(year);
577
- }
578
-
738
+ this[leftOrRight+'Calendar'].month.month(month).year(year);
579
739
  this.updateCalendars();
580
-
581
740
  },
582
741
 
583
742
  updateTime: function(e) {
584
743
 
585
- var isLeft = $(e.target).closest('.calendar').hasClass('left');
586
- var cal = this.container.find('.calendar.left');
587
- if (!isLeft)
588
- cal = this.container.find('.calendar.right');
744
+ var cal = $(e.target).closest('.calendar'),
745
+ isLeft = cal.hasClass('left');
589
746
 
590
- var hour = parseInt(cal.find('.hourselect').val());
591
- var minute = parseInt(cal.find('.minuteselect').val());
747
+ var hour = parseInt(cal.find('.hourselect').val(), 10);
748
+ var minute = parseInt(cal.find('.minuteselect').val(), 10);
592
749
 
593
750
  if (this.timePicker12Hour) {
594
751
  var ampm = cal.find('.ampmselect').val();
595
- if (ampm == 'PM' && hour < 12)
752
+ if (ampm === 'PM' && hour < 12)
596
753
  hour += 12;
597
- if (ampm == 'AM' && hour == 12)
754
+ if (ampm === 'AM' && hour === 12)
598
755
  hour = 0;
599
756
  }
600
757
 
@@ -613,14 +770,13 @@
613
770
  }
614
771
 
615
772
  this.updateCalendars();
616
-
617
773
  },
618
774
 
619
775
  updateCalendars: function () {
620
776
  this.leftCalendar.calendar = this.buildCalendar(this.leftCalendar.month.month(), this.leftCalendar.month.year(), this.leftCalendar.month.hour(), this.leftCalendar.month.minute(), 'left');
621
777
  this.rightCalendar.calendar = this.buildCalendar(this.rightCalendar.month.month(), this.rightCalendar.month.year(), this.rightCalendar.month.hour(), this.rightCalendar.month.minute(), 'right');
622
- this.container.find('.calendar.left').html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate));
623
- this.container.find('.calendar.right').html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate));
778
+ this.container.find('.calendar.left').empty().html(this.renderCalendar(this.leftCalendar.calendar, this.startDate, this.minDate, this.maxDate));
779
+ this.container.find('.calendar.right').empty().html(this.renderCalendar(this.rightCalendar.calendar, this.endDate, this.startDate, this.maxDate));
624
780
 
625
781
  this.container.find('.ranges li').removeClass('active');
626
782
  var customRange = true;
@@ -629,23 +785,26 @@
629
785
  if (this.timePicker) {
630
786
  if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {
631
787
  customRange = false;
632
- this.container.find('.ranges li:eq(' + i + ')').addClass('active');
788
+ this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')
789
+ .addClass('active').html();
633
790
  }
634
791
  } else {
635
792
  //ignore times when comparing dates if time picker is not enabled
636
793
  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')) {
637
794
  customRange = false;
638
- this.container.find('.ranges li:eq(' + i + ')').addClass('active');
795
+ this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')')
796
+ .addClass('active').html();
639
797
  }
640
798
  }
641
799
  i++;
642
800
  }
643
- if (customRange)
644
- this.container.find('.ranges li:last').addClass('active');
801
+ if (customRange) {
802
+ this.chosenLabel = this.container.find('.ranges li:last')
803
+ .addClass('active').html();
804
+ }
645
805
  },
646
806
 
647
807
  buildCalendar: function (month, year, hour, minute, side) {
648
-
649
808
  var firstDay = moment([year, month, 1]);
650
809
  var lastMonth = moment(firstDay).subtract('month', 1).month();
651
810
  var lastYear = moment(firstDay).subtract('month', 1).year();
@@ -654,9 +813,11 @@
654
813
 
655
814
  var dayOfWeek = firstDay.day();
656
815
 
816
+ var i;
817
+
657
818
  //initialize a 6 rows x 7 columns array for the calendar
658
819
  var calendar = [];
659
- for (var i = 0; i < 6; i++) {
820
+ for (i = 0; i < 6; i++) {
660
821
  calendar[i] = [];
661
822
  }
662
823
 
@@ -669,8 +830,9 @@
669
830
  startDay = daysInLastMonth - 6;
670
831
 
671
832
  var curDate = moment([lastYear, lastMonth, startDay, 12, minute]);
672
- for (var i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('hour', 24)) {
673
- if (i > 0 && col % 7 == 0) {
833
+ var col, row;
834
+ for (i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add('hour', 24)) {
835
+ if (i > 0 && col % 7 === 0) {
674
836
  col = 0;
675
837
  row++;
676
838
  }
@@ -679,7 +841,6 @@
679
841
  }
680
842
 
681
843
  return calendar;
682
-
683
844
  },
684
845
 
685
846
  renderDropdowns: function (selected, minDate, maxDate) {
@@ -725,7 +886,7 @@
725
886
  html += '<th></th>';
726
887
 
727
888
  if (!minDate || minDate.isBefore(calendar[1][1])) {
728
- html += '<th class="prev available"><i class="icon-arrow-left glyphicon glyphicon-arrow-left"></i></th>';
889
+ html += '<th class="prev available"><i class="fa fa-arrow-left icon-arrow-left glyphicon glyphicon-arrow-left"></i></th>';
729
890
  } else {
730
891
  html += '<th></th>';
731
892
  }
@@ -736,9 +897,9 @@
736
897
  dateHtml = this.renderDropdowns(calendar[1][1], minDate, maxDate);
737
898
  }
738
899
 
739
- html += '<th colspan="5" style="width: auto">' + dateHtml + '</th>';
900
+ html += '<th colspan="5" class="month">' + dateHtml + '</th>';
740
901
  if (!maxDate || maxDate.isAfter(calendar[1][1])) {
741
- html += '<th class="next available"><i class="icon-arrow-right glyphicon glyphicon-arrow-right"></i></th>';
902
+ html += '<th class="next available"><i class="fa fa-arrow-right icon-arrow-right glyphicon glyphicon-arrow-right"></i></th>';
742
903
  } else {
743
904
  html += '<th></th>';
744
905
  }
@@ -769,7 +930,7 @@
769
930
  var cname = 'available ';
770
931
  cname += (calendar[row][col].month() == calendar[1][1].month()) ? '' : 'off';
771
932
 
772
- if ((minDate && calendar[row][col].isBefore(minDate)) || (maxDate && calendar[row][col].isAfter(maxDate))) {
933
+ if ((minDate && calendar[row][col].isBefore(minDate, 'day')) || (maxDate && calendar[row][col].isAfter(maxDate, 'day'))) {
773
934
  cname = ' off disabled ';
774
935
  } else if (calendar[row][col].format('YYYY-MM-DD') == selected.format('YYYY-MM-DD')) {
775
936
  cname += ' active ';
@@ -795,6 +956,7 @@
795
956
  html += '</table>';
796
957
  html += '</div>';
797
958
 
959
+ var i;
798
960
  if (this.timePicker) {
799
961
 
800
962
  html += '<div class="calendar-time">';
@@ -807,11 +969,11 @@
807
969
  end = 12;
808
970
  if (selected_hour >= 12)
809
971
  selected_hour -= 12;
810
- if (selected_hour == 0)
972
+ if (selected_hour === 0)
811
973
  selected_hour = 12;
812
974
  }
813
975
 
814
- for (var i = start; i <= end; i++) {
976
+ for (i = start; i <= end; i++) {
815
977
  if (i == selected_hour) {
816
978
  html += '<option value="' + i + '" selected="selected">' + i + '</option>';
817
979
  } else {
@@ -823,7 +985,7 @@
823
985
 
824
986
  html += '<select class="minuteselect">';
825
987
 
826
- for (var i = 0; i < 60; i += this.timePickerIncrement) {
988
+ for (i = 0; i < 60; i += this.timePickerIncrement) {
827
989
  var num = i;
828
990
  if (num < 10)
829
991
  num = '0' + num;
@@ -852,6 +1014,14 @@
852
1014
 
853
1015
  return html;
854
1016
 
1017
+ },
1018
+
1019
+ remove: function() {
1020
+
1021
+ this.container.remove();
1022
+ this.element.off('.daterangepicker');
1023
+ this.element.removeData('daterangepicker');
1024
+
855
1025
  }
856
1026
 
857
1027
  };
@@ -859,10 +1029,11 @@
859
1029
  $.fn.daterangepicker = function (options, cb) {
860
1030
  this.each(function () {
861
1031
  var el = $(this);
862
- if (!el.data('daterangepicker'))
863
- el.data('daterangepicker', new DateRangePicker(el, options, cb));
1032
+ if (el.data('daterangepicker'))
1033
+ el.data('daterangepicker').remove();
1034
+ el.data('daterangepicker', new DateRangePicker(el, options, cb));
864
1035
  });
865
1036
  return this;
866
1037
  };
867
1038
 
868
- }(window.jQuery);
1039
+ }(window.jQuery, window.moment);