bootstrap-daterangepicker-rails 0.1.8 → 3.0.3

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: 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
+ }));