bootstrap-daterangepicker-rails 0.1.8 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 76934f745d599235be8e6437db3d3ecee454655c
4
- data.tar.gz: 9c363953307d0b4fb5fb98468b397f2a49b4de3c
3
+ metadata.gz: c1d30cf3e62506c3a57490f56aea3624dd417f0d
4
+ data.tar.gz: 11262214b438942bfd090eb773dac79b2bc2038b
5
5
  SHA512:
6
- metadata.gz: 50661d0d1adeafa0998161f3ee983959e2327feb58d5d250bd708a9bba72e06530d836d83c9f02c68eab4c3c1f90840b6e6cfb0ce3b94e57c3a3a0d51091ab98
7
- data.tar.gz: 96f17a9795c20d433b282c2b009f7136d64b1bbb4cd940c9a24596d73d0db329646735a4836238634a4f6924f31608e7eec15042ae343e82b0e31ee336c59058
6
+ metadata.gz: c9f8f78ccf2109dd17fd48679c49d44bedd438cec80d00814fc7ea6e47121639e3160dde6b4e50f581b5a166eedf7a0663cc9d61f29b8c8de711e4990bed6a9b
7
+ data.tar.gz: 809f408a66c2761b3788039098a048bd9a1a384097252873160ceaf2b75069da558eb74eba83f288c5e4e9728fd2892e28ac0e43802a845d51dfac53a4721def
data/README.md CHANGED
@@ -38,7 +38,7 @@ gem 'bootstrap-daterangepicker-rails'
38
38
 
39
39
  /*
40
40
  *= require bootstrap
41
- *= require daterangepicker-bs3
41
+ *= require daterangepickers
42
42
  */
43
43
 
44
44
 
@@ -1,7 +1,7 @@
1
1
  module Bootstrap
2
2
  module Daterangepicker
3
3
  module Rails
4
- VERSION = '0.1.8'
4
+ VERSION = '3.0.3'
5
5
  end
6
6
  end
7
7
  end
@@ -1,39 +1,33 @@
1
1
  /**
2
- * @version: 2.1.19
2
+ * @version: 3.0.3
3
3
  * @author: Dan Grossman http://www.dangrossman.info/
4
- * @copyright: Copyright (c) 2012-2015 Dan Grossman. All rights reserved.
4
+ * @copyright: Copyright (c) 2012-2018 Dan Grossman. All rights reserved.
5
5
  * @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php
6
- * @website: https://www.improvely.com/
6
+ * @website: http://www.daterangepicker.com/
7
7
  */
8
-
9
- (function(root, factory) {
10
-
11
- if (typeof define === 'function' && define.amd) {
12
- define(['moment', 'jquery', 'exports'], function(momentjs, $, exports) {
13
- root.daterangepicker = factory(root, exports, momentjs, $);
14
- });
15
-
16
- } else if (typeof exports !== 'undefined') {
17
- var momentjs = require('moment');
18
- var jQuery = (typeof window != 'undefined') ? window.jQuery : undefined; //isomorphic issue
19
- if (!jQuery) {
20
- try {
21
- jQuery = require('jquery');
22
- if (!jQuery.fn) jQuery.fn = {}; //isomorphic issue
23
- } catch (err) {
24
- if (!jQuery) throw new Error('jQuery dependency not found');
25
- }
26
- }
27
-
28
- factory(root, exports, momentjs, jQuery);
29
-
30
- // Finally, as a browser global.
31
- } else {
32
- root.daterangepicker = factory(root, {}, root.moment || moment, (root.jQuery || root.Zepto || root.ender || root.$));
33
- }
34
-
35
- }(this || {}, function(root, daterangepicker, moment, $) { // 'this' doesn't exist on a server
36
-
8
+ // Following the UMD template https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js
9
+ (function (root, factory) {
10
+ if (typeof define === 'function' && define.amd) {
11
+ // AMD. Make globaly available as well
12
+ define(['moment', 'jquery'], function (moment, jquery) {
13
+ if (!jquery.fn) jquery.fn = {}; // webpack server rendering
14
+ return factory(moment, jquery);
15
+ });
16
+ } else if (typeof module === 'object' && module.exports) {
17
+ // Node / Browserify
18
+ //isomorphic issue
19
+ var jQuery = (typeof window != 'undefined') ? window.jQuery : undefined;
20
+ if (!jQuery) {
21
+ jQuery = require('jquery');
22
+ if (!jQuery.fn) jQuery.fn = {};
23
+ }
24
+ var moment = (typeof window != 'undefined' && typeof window.moment != 'undefined') ? window.moment : require('moment');
25
+ module.exports = factory(moment, jQuery);
26
+ } else {
27
+ // Browser globals
28
+ root.daterangepicker = factory(root.moment, root.jQuery);
29
+ }
30
+ }(this, function(moment, $) {
37
31
  var DateRangePicker = function(element, options, cb) {
38
32
 
39
33
  //default settings for options
@@ -43,12 +37,15 @@
43
37
  this.endDate = moment().endOf('day');
44
38
  this.minDate = false;
45
39
  this.maxDate = false;
46
- this.dateLimit = false;
40
+ this.maxSpan = false;
47
41
  this.autoApply = false;
48
42
  this.singleDatePicker = false;
49
43
  this.showDropdowns = false;
44
+ this.minYear = moment().subtract(100, 'year').format('YYYY');
45
+ this.maxYear = moment().add(100, 'year').format('YYYY');
50
46
  this.showWeekNumbers = false;
51
47
  this.showISOWeekNumbers = false;
48
+ this.showCustomRangeLabel = true;
52
49
  this.timePicker = false;
53
50
  this.timePicker24Hour = false;
54
51
  this.timePickerIncrement = 1;
@@ -67,11 +64,12 @@
67
64
  this.drops = 'up';
68
65
 
69
66
  this.buttonClasses = 'btn btn-sm';
70
- this.applyClass = 'btn-success';
71
- this.cancelClass = 'btn-default';
67
+ this.applyButtonClasses = 'btn-primary';
68
+ this.cancelButtonClasses = 'btn-default';
72
69
 
73
70
  this.locale = {
74
- format: 'MM/DD/YYYY',
71
+ direction: 'ltr',
72
+ format: moment.localeData().longDateFormat('L'),
75
73
  separator: ' - ',
76
74
  applyLabel: 'Apply',
77
75
  cancelLabel: 'Cancel',
@@ -99,34 +97,21 @@
99
97
 
100
98
  //html template for the picker UI
101
99
  if (typeof options.template !== 'string' && !(options.template instanceof $))
102
- options.template = '<div class="daterangepicker dropdown-menu">' +
103
- '<div class="calendar left">' +
104
- '<div class="daterangepicker_input">' +
105
- '<input class="input-mini" type="text" name="daterangepicker_start" value="" />' +
106
- '<i class="fa fa-calendar glyphicon glyphicon-calendar"></i>' +
107
- '<div class="calendar-time">' +
108
- '<div></div>' +
109
- '<i class="fa fa-clock-o glyphicon glyphicon-time"></i>' +
110
- '</div>' +
111
- '</div>' +
100
+ options.template =
101
+ '<div class="daterangepicker">' +
102
+ '<div class="ranges"></div>' +
103
+ '<div class="drp-calendar left">' +
112
104
  '<div class="calendar-table"></div>' +
105
+ '<div class="calendar-time"></div>' +
113
106
  '</div>' +
114
- '<div class="calendar right">' +
115
- '<div class="daterangepicker_input">' +
116
- '<input class="input-mini" type="text" name="daterangepicker_end" value="" />' +
117
- '<i class="fa fa-calendar glyphicon glyphicon-calendar"></i>' +
118
- '<div class="calendar-time">' +
119
- '<div></div>' +
120
- '<i class="fa fa-clock-o glyphicon glyphicon-time"></i>' +
121
- '</div>' +
122
- '</div>' +
107
+ '<div class="drp-calendar right">' +
123
108
  '<div class="calendar-table"></div>' +
109
+ '<div class="calendar-time"></div>' +
124
110
  '</div>' +
125
- '<div class="ranges">' +
126
- '<div class="range_inputs">' +
127
- '<button class="applyBtn" disabled="disabled" type="button"></button> ' +
128
- '<button class="cancelBtn" type="button"></button>' +
129
- '</div>' +
111
+ '<div class="drp-buttons">' +
112
+ '<span class="drp-selected"></span>' +
113
+ '<button class="cancelBtn" type="button"></button>' +
114
+ '<button class="applyBtn" disabled="disabled" type="button"></button> ' +
130
115
  '</div>' +
131
116
  '</div>';
132
117
 
@@ -139,6 +124,9 @@
139
124
 
140
125
  if (typeof options.locale === 'object') {
141
126
 
127
+ if (typeof options.locale.direction === 'string')
128
+ this.locale.direction = options.locale.direction;
129
+
142
130
  if (typeof options.locale.format === 'string')
143
131
  this.locale.format = options.locale.format;
144
132
 
@@ -163,10 +151,15 @@
163
151
  if (typeof options.locale.weekLabel === 'string')
164
152
  this.locale.weekLabel = options.locale.weekLabel;
165
153
 
166
- if (typeof options.locale.customRangeLabel === 'string')
167
- this.locale.customRangeLabel = options.locale.customRangeLabel;
168
-
154
+ if (typeof options.locale.customRangeLabel === 'string'){
155
+ //Support unicode chars in the custom range name.
156
+ var elem = document.createElement('textarea');
157
+ elem.innerHTML = options.locale.customRangeLabel;
158
+ var rangeHtml = elem.value;
159
+ this.locale.customRangeLabel = rangeHtml;
160
+ }
169
161
  }
162
+ this.container.addClass(this.locale.direction);
170
163
 
171
164
  if (typeof options.startDate === 'string')
172
165
  this.startDate = moment(options.startDate, this.locale.format);
@@ -200,14 +193,23 @@
200
193
  if (this.maxDate && this.endDate.isAfter(this.maxDate))
201
194
  this.endDate = this.maxDate.clone();
202
195
 
203
- if (typeof options.applyClass === 'string')
204
- this.applyClass = options.applyClass;
196
+ if (typeof options.applyButtonClasses === 'string')
197
+ this.applyButtonClasses = options.applyButtonClasses;
198
+
199
+ if (typeof options.applyClass === 'string') //backwards compat
200
+ this.applyButtonClasses = options.applyClass;
201
+
202
+ if (typeof options.cancelButtonClasses === 'string')
203
+ this.cancelButtonClasses = options.cancelButtonClasses;
205
204
 
206
- if (typeof options.cancelClass === 'string')
207
- this.cancelClass = options.cancelClass;
205
+ if (typeof options.cancelClass === 'string') //backwards compat
206
+ this.cancelButtonClasses = options.cancelClass;
208
207
 
209
- if (typeof options.dateLimit === 'object')
210
- this.dateLimit = options.dateLimit;
208
+ if (typeof options.maxSpan === 'object')
209
+ this.maxSpan = options.maxSpan;
210
+
211
+ if (typeof options.dateLimit === 'object') //backwards compat
212
+ this.maxSpan = options.dateLimit;
211
213
 
212
214
  if (typeof options.opens === 'string')
213
215
  this.opens = options.opens;
@@ -230,6 +232,15 @@
230
232
  if (typeof options.showDropdowns === 'boolean')
231
233
  this.showDropdowns = options.showDropdowns;
232
234
 
235
+ if (typeof options.minYear === 'number')
236
+ this.minYear = options.minYear;
237
+
238
+ if (typeof options.maxYear === 'number')
239
+ this.maxYear = options.maxYear;
240
+
241
+ if (typeof options.showCustomRangeLabel === 'boolean')
242
+ this.showCustomRangeLabel = options.showCustomRangeLabel;
243
+
233
244
  if (typeof options.singleDatePicker === 'boolean') {
234
245
  this.singleDatePicker = options.singleDatePicker;
235
246
  if (this.singleDatePicker)
@@ -260,6 +271,9 @@
260
271
  if (typeof options.isInvalidDate === 'function')
261
272
  this.isInvalidDate = options.isInvalidDate;
262
273
 
274
+ if (typeof options.isCustomDate === 'function')
275
+ this.isCustomDate = options.isCustomDate;
276
+
263
277
  if (typeof options.alwaysShowCalendars === 'boolean')
264
278
  this.alwaysShowCalendars = options.alwaysShowCalendars;
265
279
 
@@ -276,7 +290,7 @@
276
290
 
277
291
  //if no start/end dates set, check if an input element contains initial values
278
292
  if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') {
279
- if ($(this.element).is('input[type=text]')) {
293
+ if ($(this.element).is(':text')) {
280
294
  var val = $(this.element).val(),
281
295
  split = val.split(this.locale.separator);
282
296
 
@@ -309,20 +323,21 @@
309
323
  else
310
324
  end = moment(options.ranges[range][1]);
311
325
 
312
- // If the start or end date exceed those allowed by the minDate or dateLimit
326
+ // If the start or end date exceed those allowed by the minDate or maxSpan
313
327
  // options, shorten the range to the allowable period.
314
328
  if (this.minDate && start.isBefore(this.minDate))
315
329
  start = this.minDate.clone();
316
330
 
317
331
  var maxDate = this.maxDate;
318
- if (this.dateLimit && start.clone().add(this.dateLimit).isAfter(maxDate))
319
- maxDate = start.clone().add(this.dateLimit);
332
+ if (this.maxSpan && maxDate && start.clone().add(this.maxSpan).isAfter(maxDate))
333
+ maxDate = start.clone().add(this.maxSpan);
320
334
  if (maxDate && end.isAfter(maxDate))
321
335
  end = maxDate.clone();
322
336
 
323
337
  // If the end of the range is before the minimum or the start of the range is
324
338
  // after the maximum, don't display this range option at all.
325
- if ((this.minDate && end.isBefore(this.minDate)) || (maxDate && start.isAfter(maxDate)))
339
+ if ((this.minDate && end.isBefore(this.minDate, this.timepicker ? 'minute' : 'day'))
340
+ || (maxDate && start.isAfter(maxDate, this.timepicker ? 'minute' : 'day')))
326
341
  continue;
327
342
 
328
343
  //Support unicode chars in the range names.
@@ -335,9 +350,11 @@
335
350
 
336
351
  var list = '<ul>';
337
352
  for (range in this.ranges) {
338
- list += '<li>' + range + '</li>';
353
+ list += '<li data-range-key="' + range + '">' + range + '</li>';
354
+ }
355
+ if (this.showCustomRangeLabel) {
356
+ list += '<li data-range-key="' + this.locale.customRangeLabel + '">' + this.locale.customRangeLabel + '</li>';
339
357
  }
340
- list += '<li>' + this.locale.customRangeLabel + '</li>';
341
358
  list += '</ul>';
342
359
  this.container.find('.ranges').prepend(list);
343
360
  }
@@ -356,20 +373,20 @@
356
373
  if (this.timePicker && this.autoApply)
357
374
  this.autoApply = false;
358
375
 
359
- if (this.autoApply && typeof options.ranges !== 'object') {
360
- this.container.find('.ranges').hide();
361
- } else if (this.autoApply) {
362
- this.container.find('.applyBtn, .cancelBtn').addClass('hide');
376
+ if (this.autoApply) {
377
+ this.container.addClass('auto-apply');
363
378
  }
364
379
 
380
+ if (typeof options.ranges === 'object')
381
+ this.container.addClass('show-ranges');
382
+
365
383
  if (this.singleDatePicker) {
366
384
  this.container.addClass('single');
367
- this.container.find('.calendar.left').addClass('single');
368
- this.container.find('.calendar.left').show();
369
- this.container.find('.calendar.right').hide();
370
- this.container.find('.daterangepicker_input input, .daterangepicker_input i').hide();
385
+ this.container.find('.drp-calendar.left').addClass('single');
386
+ this.container.find('.drp-calendar.left').show();
387
+ this.container.find('.drp-calendar.right').hide();
371
388
  if (!this.timePicker) {
372
- this.container.find('.ranges').hide();
389
+ this.container.addClass('auto-apply');
373
390
  }
374
391
  }
375
392
 
@@ -379,20 +396,12 @@
379
396
 
380
397
  this.container.addClass('opens' + this.opens);
381
398
 
382
- //swap the position of the predefined ranges if opens right
383
- if (typeof options.ranges !== 'undefined' && this.opens == 'right') {
384
- var ranges = this.container.find('.ranges');
385
- var html = ranges.clone();
386
- ranges.remove();
387
- this.container.find('.calendar.left').parent().prepend(html);
388
- }
389
-
390
399
  //apply CSS classes and labels to buttons
391
400
  this.container.find('.applyBtn, .cancelBtn').addClass(this.buttonClasses);
392
- if (this.applyClass.length)
393
- this.container.find('.applyBtn').addClass(this.applyClass);
394
- if (this.cancelClass.length)
395
- this.container.find('.cancelBtn').addClass(this.cancelClass);
401
+ if (this.applyButtonClasses.length)
402
+ this.container.find('.applyBtn').addClass(this.applyButtonClasses);
403
+ if (this.cancelButtonClasses.length)
404
+ this.container.find('.cancelBtn').addClass(this.cancelButtonClasses);
396
405
  this.container.find('.applyBtn').html(this.locale.applyLabel);
397
406
  this.container.find('.cancelBtn').html(this.locale.cancelLabel);
398
407
 
@@ -400,48 +409,39 @@
400
409
  // event listeners
401
410
  //
402
411
 
403
- this.container.find('.calendar')
412
+ this.container.find('.drp-calendar')
404
413
  .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this))
405
414
  .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this))
406
- .on('click.daterangepicker', 'td.available', $.proxy(this.clickDate, this))
415
+ .on('mousedown.daterangepicker', 'td.available', $.proxy(this.clickDate, this))
407
416
  .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.hoverDate, this))
408
- .on('mouseleave.daterangepicker', 'td.available', $.proxy(this.updateFormInputs, this))
409
417
  .on('change.daterangepicker', 'select.yearselect', $.proxy(this.monthOrYearChanged, this))
410
418
  .on('change.daterangepicker', 'select.monthselect', $.proxy(this.monthOrYearChanged, this))
411
419
  .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.secondselect,select.ampmselect', $.proxy(this.timeChanged, this))
412
- .on('click.daterangepicker', '.daterangepicker_input input', $.proxy(this.showCalendars, this))
413
- //.on('keyup.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsChanged, this))
414
- .on('change.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsChanged, this));
415
420
 
416
421
  this.container.find('.ranges')
422
+ .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))
423
+
424
+ this.container.find('.drp-buttons')
417
425
  .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this))
418
426
  .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this))
419
- .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this))
420
- .on('mouseenter.daterangepicker', 'li', $.proxy(this.hoverRange, this))
421
- .on('mouseleave.daterangepicker', 'li', $.proxy(this.updateFormInputs, this));
422
427
 
423
- if (this.element.is('input')) {
428
+ if (this.element.is('input') || this.element.is('button')) {
424
429
  this.element.on({
425
430
  'click.daterangepicker': $.proxy(this.show, this),
426
431
  'focus.daterangepicker': $.proxy(this.show, this),
427
432
  'keyup.daterangepicker': $.proxy(this.elementChanged, this),
428
- 'keydown.daterangepicker': $.proxy(this.keydown, this)
433
+ 'keydown.daterangepicker': $.proxy(this.keydown, this) //IE 11 compatibility
429
434
  });
430
435
  } else {
431
436
  this.element.on('click.daterangepicker', $.proxy(this.toggle, this));
437
+ this.element.on('keydown.daterangepicker', $.proxy(this.toggle, this));
432
438
  }
433
439
 
434
440
  //
435
441
  // if attached to a text input, set the initial value
436
442
  //
437
443
 
438
- if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) {
439
- this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
440
- this.element.trigger('change');
441
- } else if (this.element.is('input') && this.autoUpdateInput) {
442
- this.element.val(this.startDate.format(this.locale.format));
443
- this.element.trigger('change');
444
- }
444
+ this.updateElement();
445
445
 
446
446
  };
447
447
 
@@ -462,11 +462,17 @@
462
462
  if (this.timePicker && this.timePickerIncrement)
463
463
  this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
464
464
 
465
- if (this.minDate && this.startDate.isBefore(this.minDate))
466
- this.startDate = this.minDate;
465
+ if (this.minDate && this.startDate.isBefore(this.minDate)) {
466
+ this.startDate = this.minDate.clone();
467
+ if (this.timePicker && this.timePickerIncrement)
468
+ this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
469
+ }
467
470
 
468
- if (this.maxDate && this.startDate.isAfter(this.maxDate))
469
- this.startDate = this.maxDate;
471
+ if (this.maxDate && this.startDate.isAfter(this.maxDate)) {
472
+ this.startDate = this.maxDate.clone();
473
+ if (this.timePicker && this.timePickerIncrement)
474
+ this.startDate.minute(Math.floor(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
475
+ }
470
476
 
471
477
  if (!this.isShowing)
472
478
  this.updateElement();
@@ -482,7 +488,7 @@
482
488
  this.endDate = moment(endDate);
483
489
 
484
490
  if (!this.timePicker)
485
- this.endDate = this.endDate.endOf('day');
491
+ this.endDate = this.endDate.add(1,'d').startOf('day').subtract(1,'second');
486
492
 
487
493
  if (this.timePicker && this.timePickerIncrement)
488
494
  this.endDate.minute(Math.round(this.endDate.minute() / this.timePickerIncrement) * this.timePickerIncrement);
@@ -491,13 +497,15 @@
491
497
  this.endDate = this.startDate.clone();
492
498
 
493
499
  if (this.maxDate && this.endDate.isAfter(this.maxDate))
494
- this.endDate = this.maxDate;
500
+ this.endDate = this.maxDate.clone();
495
501
 
496
- if (this.dateLimit && this.startDate.clone().add(this.dateLimit).isBefore(this.endDate))
497
- this.endDate = this.startDate.clone().add(this.dateLimit);
502
+ if (this.maxSpan && this.startDate.clone().add(this.maxSpan).isBefore(this.endDate))
503
+ this.endDate = this.startDate.clone().add(this.maxSpan);
498
504
 
499
505
  this.previousRightTime = this.endDate.clone();
500
506
 
507
+ this.container.find('.drp-selected').html(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
508
+
501
509
  if (!this.isShowing)
502
510
  this.updateElement();
503
511
 
@@ -508,6 +516,10 @@
508
516
  return false;
509
517
  },
510
518
 
519
+ isCustomDate: function() {
520
+ return false;
521
+ },
522
+
511
523
  updateView: function() {
512
524
  if (this.timePicker) {
513
525
  this.renderTimePicker('left');
@@ -518,13 +530,8 @@
518
530
  this.container.find('.right .calendar-time select').removeAttr('disabled').removeClass('disabled');
519
531
  }
520
532
  }
521
- if (this.endDate) {
522
- this.container.find('input[name="daterangepicker_end"]').removeClass('active');
523
- this.container.find('input[name="daterangepicker_start"]').addClass('active');
524
- } else {
525
- this.container.find('input[name="daterangepicker_end"]').addClass('active');
526
- this.container.find('input[name="daterangepicker_start"]').removeClass('active');
527
- }
533
+ if (this.endDate)
534
+ this.container.find('.drp-selected').html(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
528
535
  this.updateMonthsInView();
529
536
  this.updateCalendars();
530
537
  this.updateFormInputs();
@@ -555,6 +562,10 @@
555
562
  this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month');
556
563
  }
557
564
  }
565
+ if (this.maxDate && this.linkedCalendars && !this.singleDatePicker && this.rightCalendar.month > this.maxDate) {
566
+ this.rightCalendar.month = this.maxDate.clone().date(2);
567
+ this.leftCalendar.month = this.maxDate.clone().date(2).subtract(1, 'month');
568
+ }
558
569
  },
559
570
 
560
571
  updateCalendars: function() {
@@ -670,6 +681,7 @@
670
681
  var minDate = side == 'left' ? this.minDate : this.startDate;
671
682
  var maxDate = this.maxDate;
672
683
  var selected = side == 'left' ? this.startDate : this.endDate;
684
+ var arrow = this.locale.direction == 'ltr' ? {left: 'chevron-left', right: 'chevron-right'} : {left: 'chevron-right', right: 'chevron-left'};
673
685
 
674
686
  var html = '<table class="table-condensed">';
675
687
  html += '<thead>';
@@ -680,7 +692,7 @@
680
692
  html += '<th></th>';
681
693
 
682
694
  if ((!minDate || minDate.isBefore(calendar.firstDay)) && (!this.linkedCalendars || side == 'left')) {
683
- html += '<th class="prev available"><i class="fa fa-chevron-left glyphicon glyphicon-chevron-left"></i></th>';
695
+ html += '<th class="prev available"><span></span></th>';
684
696
  } else {
685
697
  html += '<th></th>';
686
698
  }
@@ -690,8 +702,8 @@
690
702
  if (this.showDropdowns) {
691
703
  var currentMonth = calendar[1][1].month();
692
704
  var currentYear = calendar[1][1].year();
693
- var maxYear = (maxDate && maxDate.year()) || (currentYear + 5);
694
- var minYear = (minDate && minDate.year()) || (currentYear - 50);
705
+ var maxYear = (maxDate && maxDate.year()) || (this.maxYear);
706
+ var minYear = (minDate && minDate.year()) || (this.minYear);
695
707
  var inMinYear = currentYear == minYear;
696
708
  var inMaxYear = currentYear == maxYear;
697
709
 
@@ -722,7 +734,7 @@
722
734
 
723
735
  html += '<th colspan="5" class="month">' + dateHtml + '</th>';
724
736
  if ((!maxDate || maxDate.isAfter(calendar.lastDay)) && (!this.linkedCalendars || side == 'right' || this.singleDatePicker)) {
725
- html += '<th class="next available"><i class="fa fa-chevron-right glyphicon glyphicon-chevron-right"></i></th>';
737
+ html += '<th class="next available"><span></span></th>';
726
738
  } else {
727
739
  html += '<th></th>';
728
740
  }
@@ -742,10 +754,10 @@
742
754
  html += '</thead>';
743
755
  html += '<tbody>';
744
756
 
745
- //adjust maxDate to reflect the dateLimit setting in order to
746
- //grey out end dates beyond the dateLimit
747
- if (this.endDate == null && this.dateLimit) {
748
- var maxLimit = this.startDate.clone().add(this.dateLimit).endOf('day');
757
+ //adjust maxDate to reflect the maxSpan setting in order to
758
+ //grey out end dates beyond the maxSpan
759
+ if (this.endDate == null && this.maxSpan) {
760
+ var maxLimit = this.startDate.clone().add(this.maxSpan).endOf('day');
749
761
  if (!maxDate || maxLimit.isBefore(maxDate)) {
750
762
  maxDate = maxLimit;
751
763
  }
@@ -800,6 +812,15 @@
800
812
  if (this.endDate != null && calendar[row][col] > this.startDate && calendar[row][col] < this.endDate)
801
813
  classes.push('in-range');
802
814
 
815
+ //apply custom classes for this date
816
+ var isCustom = this.isCustomDate(calendar[row][col]);
817
+ if (isCustom !== false) {
818
+ if (typeof isCustom === 'string')
819
+ classes.push(isCustom);
820
+ else
821
+ Array.prototype.push.apply(classes, isCustom);
822
+ }
823
+
803
824
  var cname = '', disabled = false;
804
825
  for (var i = 0; i < classes.length; i++) {
805
826
  cname += classes[i] + ' ';
@@ -818,31 +839,35 @@
818
839
  html += '</tbody>';
819
840
  html += '</table>';
820
841
 
821
- this.container.find('.calendar.' + side + ' .calendar-table').html(html);
842
+ this.container.find('.drp-calendar.' + side + ' .calendar-table').html(html);
822
843
 
823
844
  },
824
845
 
825
846
  renderTimePicker: function(side) {
826
847
 
848
+ // Don't bother updating the time picker if it's currently disabled
849
+ // because an end date hasn't been clicked yet
850
+ if (side == 'right' && !this.endDate) return;
851
+
827
852
  var html, selected, minDate, maxDate = this.maxDate;
828
853
 
829
- if (this.dateLimit && (!this.maxDate || this.startDate.clone().add(this.dateLimit).isAfter(this.maxDate)))
830
- maxDate = this.startDate.clone().add(this.dateLimit);
854
+ if (this.maxSpan && (!this.maxDate || this.startDate.clone().add(this.maxSpan).isAfter(this.maxDate)))
855
+ maxDate = this.startDate.clone().add(this.maxSpan);
831
856
 
832
857
  if (side == 'left') {
833
858
  selected = this.startDate.clone();
834
859
  minDate = this.minDate;
835
860
  } else if (side == 'right') {
836
- selected = this.endDate ? this.endDate.clone() : this.previousRightTime.clone();
861
+ selected = this.endDate.clone();
837
862
  minDate = this.startDate;
838
863
 
839
864
  //Preserve the time already selected
840
- var timeSelector = this.container.find('.calendar.right .calendar-time div');
865
+ var timeSelector = this.container.find('.drp-calendar.right .calendar-time');
841
866
  if (timeSelector.html() != '') {
842
867
 
843
- selected.hour(timeSelector.find('.hourselect option:selected').val() || selected.hour());
844
- selected.minute(timeSelector.find('.minuteselect option:selected').val() || selected.minute());
845
- selected.second(timeSelector.find('.secondselect option:selected').val() || selected.second());
868
+ selected.hour(selected.hour() || timeSelector.find('.hourselect option:selected').val());
869
+ selected.minute(selected.minute() || timeSelector.find('.minuteselect option:selected').val());
870
+ selected.second(selected.second() || timeSelector.find('.secondselect option:selected').val());
846
871
 
847
872
  if (!this.timePicker24Hour) {
848
873
  var ampm = timeSelector.find('.ampmselect option:selected').val();
@@ -852,13 +877,14 @@
852
877
  selected.hour(0);
853
878
  }
854
879
 
855
- if (selected.isBefore(this.startDate))
856
- selected = this.startDate.clone();
880
+ }
857
881
 
858
- if (selected.isAfter(maxDate))
859
- selected = maxDate.clone();
882
+ if (selected.isBefore(this.startDate))
883
+ selected = this.startDate.clone();
884
+
885
+ if (maxDate && selected.isAfter(maxDate))
886
+ selected = maxDate.clone();
860
887
 
861
- }
862
888
  }
863
889
 
864
890
  //
@@ -974,20 +1000,12 @@
974
1000
  html += '</select>';
975
1001
  }
976
1002
 
977
- this.container.find('.calendar.' + side + ' .calendar-time div').html(html);
1003
+ this.container.find('.drp-calendar.' + side + ' .calendar-time').html(html);
978
1004
 
979
1005
  },
980
1006
 
981
1007
  updateFormInputs: function() {
982
1008
 
983
- //ignore mouse movements while an above-calendar text input has focus
984
- if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
985
- return;
986
-
987
- this.container.find('input[name=daterangepicker_start]').val(this.startDate.format(this.locale.format));
988
- if (this.endDate)
989
- this.container.find('input[name=daterangepicker_end]').val(this.endDate.format(this.locale.format));
990
-
991
1009
  if (this.singleDatePicker || (this.endDate && (this.startDate.isBefore(this.endDate) || this.startDate.isSame(this.endDate)))) {
992
1010
  this.container.find('button.applyBtn').removeAttr('disabled');
993
1011
  } else {
@@ -1012,7 +1030,7 @@
1012
1030
  containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top;
1013
1031
  else
1014
1032
  containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top;
1015
- this.container[this.drops == 'up' ? 'addClass' : 'removeClass']('dropup');
1033
+ this.container[this.drops == 'up' ? 'addClass' : 'removeClass']('drop-up');
1016
1034
 
1017
1035
  if (this.opens == 'left') {
1018
1036
  this.container.css({
@@ -1095,7 +1113,7 @@
1095
1113
 
1096
1114
  //if a new date range was selected, invoke the user callback function
1097
1115
  if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate))
1098
- this.callback(this.startDate, this.endDate, this.chosenLabel);
1116
+ this.callback(this.startDate.clone(), this.endDate.clone(), this.chosenLabel);
1099
1117
 
1100
1118
  //if picker is attached to a text input, update it
1101
1119
  this.updateElement();
@@ -1127,6 +1145,7 @@
1127
1145
  target.closest('.calendar-table').length
1128
1146
  ) return;
1129
1147
  this.hide();
1148
+ this.element.trigger('outsideClick.daterangepicker', this);
1130
1149
  },
1131
1150
 
1132
1151
  showCalendars: function() {
@@ -1140,25 +1159,8 @@
1140
1159
  this.element.trigger('hideCalendar.daterangepicker', this);
1141
1160
  },
1142
1161
 
1143
- hoverRange: function(e) {
1144
-
1145
- //ignore mouse movements while an above-calendar text input has focus
1146
- if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
1147
- return;
1148
-
1149
- var label = e.target.innerHTML;
1150
- if (label == this.locale.customRangeLabel) {
1151
- this.updateView();
1152
- } else {
1153
- var dates = this.ranges[label];
1154
- this.container.find('input[name=daterangepicker_start]').val(dates[0].format(this.locale.format));
1155
- this.container.find('input[name=daterangepicker_end]').val(dates[1].format(this.locale.format));
1156
- }
1157
-
1158
- },
1159
-
1160
1162
  clickRange: function(e) {
1161
- var label = e.target.innerHTML;
1163
+ var label = e.target.getAttribute('data-range-key');
1162
1164
  this.chosenLabel = label;
1163
1165
  if (label == this.locale.customRangeLabel) {
1164
1166
  this.showCalendars();
@@ -1179,7 +1181,7 @@
1179
1181
  },
1180
1182
 
1181
1183
  clickPrev: function(e) {
1182
- var cal = $(e.target).parents('.calendar');
1184
+ var cal = $(e.target).parents('.drp-calendar');
1183
1185
  if (cal.hasClass('left')) {
1184
1186
  this.leftCalendar.month.subtract(1, 'month');
1185
1187
  if (this.linkedCalendars)
@@ -1191,7 +1193,7 @@
1191
1193
  },
1192
1194
 
1193
1195
  clickNext: function(e) {
1194
- var cal = $(e.target).parents('.calendar');
1196
+ var cal = $(e.target).parents('.drp-calendar');
1195
1197
  if (cal.hasClass('left')) {
1196
1198
  this.leftCalendar.month.add(1, 'month');
1197
1199
  } else {
@@ -1204,32 +1206,21 @@
1204
1206
 
1205
1207
  hoverDate: function(e) {
1206
1208
 
1207
- //ignore mouse movements while an above-calendar text input has focus
1208
- if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus"))
1209
- return;
1210
-
1211
1209
  //ignore dates that can't be selected
1212
1210
  if (!$(e.target).hasClass('available')) return;
1213
1211
 
1214
- //have the text inputs above calendars reflect the date being hovered over
1215
1212
  var title = $(e.target).attr('data-title');
1216
1213
  var row = title.substr(1, 1);
1217
1214
  var col = title.substr(3, 1);
1218
- var cal = $(e.target).parents('.calendar');
1215
+ var cal = $(e.target).parents('.drp-calendar');
1219
1216
  var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
1220
1217
 
1221
- if (this.endDate) {
1222
- this.container.find('input[name=daterangepicker_start]').val(date.format(this.locale.format));
1223
- } else {
1224
- this.container.find('input[name=daterangepicker_end]').val(date.format(this.locale.format));
1225
- }
1226
-
1227
1218
  //highlight the dates between the start date and the date being hovered as a potential end date
1228
1219
  var leftCalendar = this.leftCalendar;
1229
1220
  var rightCalendar = this.rightCalendar;
1230
1221
  var startDate = this.startDate;
1231
1222
  if (!this.endDate) {
1232
- this.container.find('.calendar td').each(function(index, el) {
1223
+ this.container.find('.drp-calendar tbody td').each(function(index, el) {
1233
1224
 
1234
1225
  //skip week numbers, only look at dates
1235
1226
  if ($(el).hasClass('week')) return;
@@ -1237,10 +1228,10 @@
1237
1228
  var title = $(el).attr('data-title');
1238
1229
  var row = title.substr(1, 1);
1239
1230
  var col = title.substr(3, 1);
1240
- var cal = $(el).parents('.calendar');
1231
+ var cal = $(el).parents('.drp-calendar');
1241
1232
  var dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col];
1242
1233
 
1243
- if (dt.isAfter(startDate) && dt.isBefore(date)) {
1234
+ if ((dt.isAfter(startDate) && dt.isBefore(date)) || dt.isSame(date, 'day')) {
1244
1235
  $(el).addClass('in-range');
1245
1236
  } else {
1246
1237
  $(el).removeClass('in-range');
@@ -1258,7 +1249,7 @@
1258
1249
  var title = $(e.target).attr('data-title');
1259
1250
  var row = title.substr(1, 1);
1260
1251
  var col = title.substr(3, 1);
1261
- var cal = $(e.target).parents('.calendar');
1252
+ var cal = $(e.target).parents('.drp-calendar');
1262
1253
  var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
1263
1254
 
1264
1255
  //
@@ -1267,9 +1258,10 @@
1267
1258
  // * if the time picker is enabled, apply the hour/minute/second from the select boxes to the clicked date
1268
1259
  // * if autoapply is enabled, and an end date was chosen, apply the selection
1269
1260
  // * if single date picker mode, and time picker isn't enabled, apply the selection immediately
1261
+ // * if one of the inputs above the calendars was focused, cancel that manual input
1270
1262
  //
1271
1263
 
1272
- if (this.endDate || date.isBefore(this.startDate, 'day')) {
1264
+ if (this.endDate || date.isBefore(this.startDate, 'day')) { //picking start
1273
1265
  if (this.timePicker) {
1274
1266
  var hour = parseInt(this.container.find('.left .hourselect').val(), 10);
1275
1267
  if (!this.timePicker24Hour) {
@@ -1289,7 +1281,7 @@
1289
1281
  //special case: clicking the same date for start/end,
1290
1282
  //but the time of the end date is before the start date
1291
1283
  this.setEndDate(this.startDate.clone());
1292
- } else {
1284
+ } else { // picking end
1293
1285
  if (this.timePicker) {
1294
1286
  var hour = parseInt(this.container.find('.right .hourselect').val(), 10);
1295
1287
  if (!this.timePicker24Hour) {
@@ -1318,32 +1310,41 @@
1318
1310
 
1319
1311
  this.updateView();
1320
1312
 
1313
+ //This is to cancel the blur event handler if the mouse was in one of the inputs
1314
+ e.stopPropagation();
1315
+
1321
1316
  },
1322
1317
 
1323
- calculateChosenLabel: function() {
1324
- var customRange = true;
1325
- var i = 0;
1326
- for (var range in this.ranges) {
1318
+ calculateChosenLabel: function () {
1319
+ var customRange = true;
1320
+ var i = 0;
1321
+ for (var range in this.ranges) {
1327
1322
  if (this.timePicker) {
1328
- if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) {
1329
- customRange = false;
1330
- this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html();
1331
- break;
1332
- }
1333
- } else {
1334
- //ignore times when comparing dates if time picker is not enabled
1335
- 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')) {
1336
- customRange = false;
1337
- this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html();
1338
- break;
1339
- }
1340
- }
1341
- i++;
1342
- }
1343
- if (customRange) {
1344
- this.chosenLabel = this.container.find('.ranges li:last').addClass('active').html();
1345
- this.showCalendars();
1346
- }
1323
+ var format = this.timePickerSeconds ? "YYYY-MM-DD hh:mm:ss" : "YYYY-MM-DD hh:mm";
1324
+ //ignore times when comparing dates if time picker seconds is not enabled
1325
+ if (this.startDate.format(format) == this.ranges[range][0].format(format) && this.endDate.format(format) == this.ranges[range][1].format(format)) {
1326
+ customRange = false;
1327
+ this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key');
1328
+ break;
1329
+ }
1330
+ } else {
1331
+ //ignore times when comparing dates if time picker is not enabled
1332
+ 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')) {
1333
+ customRange = false;
1334
+ this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key');
1335
+ break;
1336
+ }
1337
+ }
1338
+ i++;
1339
+ }
1340
+ if (customRange) {
1341
+ if (this.showCustomRangeLabel) {
1342
+ this.chosenLabel = this.container.find('.ranges li:last').addClass('active').attr('data-range-key');
1343
+ } else {
1344
+ this.chosenLabel = null;
1345
+ }
1346
+ this.showCalendars();
1347
+ }
1347
1348
  },
1348
1349
 
1349
1350
  clickApply: function(e) {
@@ -1359,9 +1360,9 @@
1359
1360
  },
1360
1361
 
1361
1362
  monthOrYearChanged: function(e) {
1362
- var isLeft = $(e.target).closest('.calendar').hasClass('left'),
1363
+ var isLeft = $(e.target).closest('.drp-calendar').hasClass('left'),
1363
1364
  leftOrRight = isLeft ? 'left' : 'right',
1364
- cal = this.container.find('.calendar.'+leftOrRight);
1365
+ cal = this.container.find('.drp-calendar.'+leftOrRight);
1365
1366
 
1366
1367
  // Month must be Number for new moment versions
1367
1368
  var month = parseInt(cal.find('.monthselect').val(), 10);
@@ -1402,7 +1403,7 @@
1402
1403
 
1403
1404
  timeChanged: function(e) {
1404
1405
 
1405
- var cal = $(e.target).closest('.calendar'),
1406
+ var cal = $(e.target).closest('.drp-calendar'),
1406
1407
  isLeft = cal.hasClass('left');
1407
1408
 
1408
1409
  var hour = parseInt(cal.find('.hourselect').val(), 10);
@@ -1448,38 +1449,9 @@
1448
1449
 
1449
1450
  },
1450
1451
 
1451
- formInputsChanged: function(e) {
1452
- var isRight = $(e.target).closest('.calendar').hasClass('right');
1453
- var start = moment(this.container.find('input[name="daterangepicker_start"]').val(), this.locale.format);
1454
- var end = moment(this.container.find('input[name="daterangepicker_end"]').val(), this.locale.format);
1455
-
1456
- if (start.isValid() && end.isValid()) {
1457
-
1458
- if (isRight && end.isBefore(start))
1459
- start = end.clone();
1460
-
1461
- this.setStartDate(start);
1462
- this.setEndDate(end);
1463
-
1464
- if (isRight) {
1465
- this.container.find('input[name="daterangepicker_start"]').val(this.startDate.format(this.locale.format));
1466
- } else {
1467
- this.container.find('input[name="daterangepicker_end"]').val(this.endDate.format(this.locale.format));
1468
- }
1469
-
1470
- }
1471
-
1472
- this.updateCalendars();
1473
- if (this.timePicker) {
1474
- this.renderTimePicker('left');
1475
- this.renderTimePicker('right');
1476
- }
1477
- },
1478
-
1479
1452
  elementChanged: function() {
1480
1453
  if (!this.element.is('input')) return;
1481
1454
  if (!this.element.val().length) return;
1482
- if (this.element.val().length < this.locale.format.length) return;
1483
1455
 
1484
1456
  var dateString = this.element.val().split(this.locale.separator),
1485
1457
  start = null,
@@ -1507,15 +1479,25 @@
1507
1479
  if ((e.keyCode === 9) || (e.keyCode === 13)) {
1508
1480
  this.hide();
1509
1481
  }
1482
+
1483
+ //hide on esc and prevent propagation
1484
+ if (e.keyCode === 27) {
1485
+ e.preventDefault();
1486
+ e.stopPropagation();
1487
+
1488
+ this.hide();
1489
+ }
1510
1490
  },
1511
1491
 
1512
1492
  updateElement: function() {
1513
- if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) {
1514
- this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
1515
- this.element.trigger('change');
1516
- } else if (this.element.is('input') && this.autoUpdateInput) {
1517
- this.element.val(this.startDate.format(this.locale.format));
1518
- this.element.trigger('change');
1493
+ if (this.element.is('input') && this.autoUpdateInput) {
1494
+ var newValue = this.startDate.format(this.locale.format);
1495
+ if (!this.singleDatePicker) {
1496
+ newValue += this.locale.separator + this.endDate.format(this.locale.format);
1497
+ }
1498
+ if (newValue !== this.element.val()) {
1499
+ this.element.val(newValue).trigger('change');
1500
+ }
1519
1501
  }
1520
1502
  },
1521
1503
 
@@ -1528,15 +1510,16 @@
1528
1510
  };
1529
1511
 
1530
1512
  $.fn.daterangepicker = function(options, callback) {
1513
+ var implementOptions = $.extend(true, {}, $.fn.daterangepicker.defaultOptions, options);
1531
1514
  this.each(function() {
1532
1515
  var el = $(this);
1533
1516
  if (el.data('daterangepicker'))
1534
1517
  el.data('daterangepicker').remove();
1535
- el.data('daterangepicker', new DateRangePicker(el, options, callback));
1518
+ el.data('daterangepicker', new DateRangePicker(el, implementOptions, callback));
1536
1519
  });
1537
1520
  return this;
1538
1521
  };
1539
1522
 
1540
1523
  return DateRangePicker;
1541
1524
 
1542
- }));
1525
+ }));