daterangepicker-4.x 4.9.7 → 4.10.0

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.
Files changed (3) hide show
  1. package/README.md +50 -38
  2. package/daterangepicker.js +147 -192
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -18,8 +18,8 @@ Above samples are based on the [original repository](https://github.com/dangross
18
18
  ```html
19
19
  <script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
20
20
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/luxon@3.5.0/build/global/luxon.min.js"></script>
21
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker-4.x@4.9.7/daterangepicker.min.js"></script>
22
- <link type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker-4.x@4.9.7/daterangepicker.min.css" rel="stylesheet" />
21
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker-4.x@4.10.0/daterangepicker.min.js"></script>
22
+ <link type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker-4.x@4.10.0/daterangepicker.min.css" rel="stylesheet" />
23
23
 
24
24
  <input type="text" id="daterange" />
25
25
 
@@ -188,6 +188,9 @@ Licensed under the [MIT license](LICENSE).
188
188
  ## Events
189
189
 
190
190
  <dl>
191
+ <dt><a href="#event_violated.daterangepicker">"violated.daterangepicker" (this, violations)</a> ⇒ <code>boolean</code></dt>
192
+ <dd><p>Emitted if the input values are not compliant to all constraints</p>
193
+ </dd>
191
194
  <dt><a href="#event_beforeRenderCalendar.daterangepicker">"beforeRenderCalendar.daterangepicker" (this)</a></dt>
192
195
  <dd><p>Emitted before the calendar is rendered.
193
196
  Useful to remove any manually added elements.</p>
@@ -247,7 +250,7 @@ use <a href="#event_timeChange.daterangepicker">&quot;timeChange.daterangepicker
247
250
  <dt><a href="#Range">Range</a> : <code>Object</code></dt>
248
251
  <dd><p>A single predefined range</p>
249
252
  </dd>
250
- <dt><a href="#constraintOptions">constraintOptions</a> : <code>Object</code></dt>
253
+ <dt><a href="#InputViolation">InputViolation</a> : <code>Object</code></dt>
251
254
  <dd></dd>
252
255
  <dt><a href="#callback">callback</a> : <code>function</code></dt>
253
256
  <dd></dd>
@@ -264,7 +267,7 @@ use <a href="#event_timeChange.daterangepicker">&quot;timeChange.daterangepicker
264
267
  * [.setStartDate(startDate, isValid)](#DateRangePicker+setStartDate)
265
268
  * [.setEndDate(endDate, isValid)](#DateRangePicker+setEndDate)
266
269
  * [.setPeriod(startDate, endDate, isValid)](#DateRangePicker+setPeriod)
267
- * [.constrainDate(options, [range])](#DateRangePicker+constrainDate) ⇒ <code>Array</code>
270
+ * [.validateInput([range])](#DateRangePicker+validateInput) ⇒ <code>Array</code> \| <code>null</code>
268
271
  * [.updateView()](#DateRangePicker+updateView)
269
272
  * [.showCalendars()](#DateRangePicker+showCalendars)
270
273
  * [.hideCalendars()](#DateRangePicker+hideCalendars)
@@ -290,9 +293,8 @@ Sets the date range picker's currently selected start date to the provided date.
290
293
  `startDate` must be a `luxon.DateTime` or `Date` or `string` according to [ISO-8601](ISO-8601) or
291
294
  a string matching `locale.format`.
292
295
  The value of the attached `<input>` element is also updated.
293
- Date value is rounded to match option `timePickerStepSize`<br/>
294
- Functions `isInvalidDate` and `isInvalidTime` are not evaluated, you may set date/time which is not selectable in calendar.<br/>
295
- If the `startDate` does not fall into `minDate` and `maxDate` then `startDate` is shifted and a warning is written to console.
296
+ Date value is rounded to match option `timePickerStepSize` unless skipped by `violated.daterangepicker` event handler.<br/>
297
+ If the `startDate` does not fall into `minDate` and `maxDate` then `startDate` is shifted unless skipped by `violated.daterangepicker` event handler.
296
298
 
297
299
  **Kind**: instance method of [<code>DateRangePicker</code>](#DateRangePicker)
298
300
  **Throws**:
@@ -303,7 +305,7 @@ If the `startDate` does not fall into `minDate` and `maxDate` then `startDate` i
303
305
  | Param | Type | Default | Description |
304
306
  | --- | --- | --- | --- |
305
307
  | startDate | [<code>DateTime</code>](https://moment.github.io/luxon/api-docs/index.html#datetime) \| [<code>Date</code>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) \| <code>string</code> | | startDate to be set |
306
- | isValid | <code>boolean</code> | <code>false</code> | If `true` then the `startDate` is not checked against `minDate` and `maxDate`<br/> Use this option only if you are really sure about the value you put in. |
308
+ | isValid | <code>boolean</code> | <code>false</code> | If `true` then the `startDate` is not checked against `minDate` and `maxDate`<br/> Use this option only if you are sure about the value you put in. |
307
309
 
308
310
  **Example**
309
311
  ```js
@@ -318,10 +320,9 @@ Sets the date range picker's currently selected end date to the provided date.<b
318
320
  `endDate` must be a `luxon.DateTime` or `Date` or `string` according to [ISO-8601](ISO-8601) or
319
321
  a string matching`locale.format`.
320
322
  The value of the attached `<input>` element is also updated.
321
- Date value is rounded to match option `timePickerStepSize`<br/>
322
- Functions `isInvalidDate` and `isInvalidTime` are not evaluated, you may set date/time which is not selectable in calendar.<br/>
323
+ Date value is rounded to match option `timePickerStepSize` unless skipped by `violated.daterangepicker` event handler.<br/>
323
324
  If the `endDate` does not fall into `minDate` and `maxDate` or into `minSpan` and `maxSpan`
324
- then `endDate` is shifted and a warning is written to console.
325
+ then `endDate` is shifted unless skipped by `violated.daterangepicker` event handler
325
326
 
326
327
  **Kind**: instance method of [<code>DateRangePicker</code>](#DateRangePicker)
327
328
  **Throws**:
@@ -332,7 +333,7 @@ then `endDate` is shifted and a warning is written to console.
332
333
  | Param | Type | Default | Description |
333
334
  | --- | --- | --- | --- |
334
335
  | endDate | [<code>DateTime</code>](https://moment.github.io/luxon/api-docs/index.html#datetime) \| [<code>Date</code>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) \| <code>string</code> | | endDate to be set |
335
- | isValid | <code>boolean</code> | <code>false</code> | If `true` then the `endDate` is not checked against `minDate`, `maxDate` and `minSpan`, `maxSpan`<br/> Use this option only if you are really sure about the value you put in. |
336
+ | isValid | <code>boolean</code> | <code>false</code> | If `true` then the `endDate` is not checked against `minDate`, `maxDate` and `minSpan`, `maxSpan`<br/> Use this option only if you are sure about the value you put in. |
336
337
 
337
338
  **Example**
338
339
  ```js
@@ -354,7 +355,7 @@ Shortcut for [setStartDate](#DateRangePicker+setStartDate) and [setEndDate](#Dat
354
355
  | --- | --- | --- | --- |
355
356
  | startDate | [<code>DateTime</code>](https://moment.github.io/luxon/api-docs/index.html#datetime) \| [<code>Date</code>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) \| <code>string</code> | | startDate to be set |
356
357
  | endDate | [<code>DateTime</code>](https://moment.github.io/luxon/api-docs/index.html#datetime) \| [<code>Date</code>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) \| <code>string</code> | | endDate to be set |
357
- | isValid | <code>boolean</code> | <code>false</code> | If `true` then the `startDate` and `endDate` are not checked against `minDate`, `maxDate` and `minSpan`, `maxSpan`<br/> Use this option only if you are really sure about the value you put in. |
358
+ | isValid | <code>boolean</code> | <code>false</code> | If `true` then the `startDate` and `endDate` are not checked against `minDate`, `maxDate` and `minSpan`, `maxSpan`<br/> Use this option only if you are sure about the value you put in. |
358
359
 
359
360
  **Example**
360
361
  ```js
@@ -362,31 +363,25 @@ const DateTime = luxon.DateTime;
362
363
  const drp = $('#picker').data('daterangepicker');
363
364
  drp.setPeriod(DateTime.now().startOf('week'), DateTime.now().startOf('week').plus({days: 10}));
364
365
  ```
365
- <a name="DateRangePicker+constrainDate"></a>
366
+ <a name="DateRangePicker+validateInput"></a>
366
367
 
367
- ### dateRangePicker.constrainDate(options, [range]) ⇒ <code>Array</code>
368
+ ### dateRangePicker.validateInput([range]) ⇒ <code>Array</code> \| <code>null</code>
368
369
  Validate `startDate` and `endDate` or `range` against `timePickerStepSize`, `minDate`, `maxDate`,
369
- `minSpan`, `maxSpan`, `invalidDate` and `invalidTime` and modifies them, if needed.
370
- When `startDate` or `endDate` are modified, then a warning is written to console by default.
370
+ `minSpan`, `maxSpan`, `invalidDate` and `invalidTime` and corrects them, if needed.
371
+ Correction can be skipped by returning `true` at event listener for `violated.daterangepicker`
371
372
 
372
373
  **Kind**: instance method of [<code>DateRangePicker</code>](#DateRangePicker)
373
- **Returns**: <code>Array</code> - - Corrected range as array of `[startDate, endDate, isInvalid]` when range is set, otherwise just `isInvalid` object
374
- **Throws**:
375
-
376
- - `RangeError` if 'minDate' contradicts to 'minSpan'
377
-
374
+ **Returns**: <code>Array</code> \| <code>null</code> - - Corrected range as array of `[startDate, endDate]` when `range` is defined
375
+ **Emits**: <code>event:&quot;violated.daterangepicker&quot;</code>
378
376
 
379
377
  | Param | Type | Description |
380
378
  | --- | --- | --- |
381
- | options | [<code>constraintOptions</code>](#constraintOptions) | Defines which constraints shall be validated |
382
379
  | [range] | <code>Array</code> | Used to check prefefined range instead of `startDate` and `endDate` => `[name, startDate, endDate]` When set, then function does not modify anything, just returning corrected range. |
383
380
 
384
381
  **Example**
385
382
  ```js
386
- constrainDate({}, [DateTime.fromISO('2025-02-03'), DateTime.fromISO('2025-02-25')]) =>
387
- [ DateTime.fromISO('2025-02-05'), DateTime.fromISO('2025-02-20'), { startDate: { stepped: ... }, endDate: { stepped: ..., modified: [{old: ... new: ..., reason: 'minSpan'}] } } ]
388
- constrainDate({span: false, invalidDate: true, invalidTime: true}) =>
389
- { startDate: {stepped: ..., modified: [{old: ... new: ..., reason: 'minDate'}], isInvalidDate: true, isInvalidTime: false}, endDate: {stepped: ..., isInvalidDate: false, isInvalidTime: true} } ]
383
+ validateInput([DateTime.fromISO('2025-02-03'), DateTime.fromISO('2025-02-25')]) =>
384
+ [ DateTime.fromISO('2025-02-05'), DateTime.fromISO('2025-02-20'), { startDate: { violations: [{old: ..., new: ..., reasson: 'minDate'}] } } ]
390
385
  ```
391
386
  <a name="DateRangePicker+updateView"></a>
392
387
 
@@ -436,6 +431,24 @@ Initiate a new DateRangePicker
436
431
  | options | [<code>Options</code>](#Options) | Object to configure the DateRangePicker |
437
432
  | callback | [<code>callback</code>](#callback) | Callback function executed when date is changed.<br/> Callback function is executed if selected date values has changed, before picker is hidden and before the attached `<input>` element is updated. As alternative listen to the ["apply.daterangepicker"](#event_apply.daterangepicker) event |
438
433
 
434
+ <a name="event_violated.daterangepicker"></a>
435
+
436
+ ## "violated.daterangepicker" (this, violations) ⇒ <code>boolean</code>
437
+ Emitted if the input values are not compliant to all constraints
438
+
439
+ **Kind**: event emitted
440
+ **Returns**: <code>boolean</code> - skip - If `true`, then input values are not corrected and remain invalid
441
+
442
+ | Param | Type | Description |
443
+ | --- | --- | --- |
444
+ | this | [<code>DateRangePicker</code>](#DateRangePicker) | The daterangepicker object |
445
+ | violations | [<code>InputViolation</code>](#InputViolation) | An object of input violations |
446
+
447
+ **Example**
448
+ ```js
449
+ $('#picker').on('violated.daterangepicker', (ev, picker, violations))
450
+ [ DateTime.fromISO('2025-02-05'), DateTime.fromISO('2025-02-20'), { startDate: { violations: [{old: ..., new: ..., reasson: 'minDate'}] } } ]
451
+ ```
439
452
  <a name="event_beforeRenderCalendar.daterangepicker"></a>
440
453
 
441
454
  ## "beforeRenderCalendar.daterangepicker" (this)
@@ -627,7 +640,7 @@ Options for DateRangePicker
627
640
  | isCustomDate | <code>function</code> | <code>false</code> | A function that is passed each date in the two calendars before they are displayed, and may return a string or array of CSS class names to apply to that date's calendar cell.<br/> Signature: `isCustomDate(date)` |
628
641
  | altInput | <code>string</code> \| <code>Array</code> | <code>null</code> | A [jQuery selector](https://api.jquery.com/category/selectors/) string for an alternative ouput (typically hidden) `<input>` element. Requires `altFormat` to be set.<br/> Must be a single string for `singleDatePicker: true` or an array of two strings for `singleDatePicker: false`<br/> Example: `['#start', '#end']` |
629
642
  | altFormat | <code>function</code> \| <code>string</code> | <code></code> | The output format used for `altInput`.<br/> Either a string used with [toFormat()](https://moment.github.io/luxon/api-docs/index.html#datetimetoformat) or a function.<br/> Examples: `'yyyyMMddHHmm'`, `(date) => date.toUnixInteger()` |
630
- | warnings | <code>boolean</code> | <code>true</code> | When enabled, then warning are printed to console if input date violates `minDate`, `maxDate`, `minSpan`, `maxSpan`, `timePickerStepSize`, `isInvalidDate`, `isInvalidTime` |
643
+ | ~~warnings~~ | <code>boolean</code> | | Not used anymore. Listen to event `violated.daterangepicker` to react on invalid input data |
631
644
  | applyButtonClasses | <code>string</code> | <code>&quot;btn-primary&quot;</code> | CSS class names that will be added only to the apply button |
632
645
  | cancelButtonClasses | <code>string</code> | <code>&quot;btn-default&quot;</code> | CSS class names that will be added only to the cancel button |
633
646
  | buttonClasses | <code>string</code> | | Default: `'btn btn-sm'`<br/>CSS class names that will be added to both the apply and cancel buttons. |
@@ -693,20 +706,19 @@ A single predefined range
693
706
  ```js
694
707
  { Today: [DateTime.now().startOf('day'), DateTime.now().endOf('day')] }
695
708
  ```
696
- <a name="constraintOptions"></a>
709
+ <a name="InputViolation"></a>
697
710
 
698
- ## constraintOptions : <code>Object</code>
711
+ ## InputViolation : <code>Object</code>
699
712
  **Kind**: global typedef
700
713
  **Properties**
701
714
 
702
- | Name | Type | Default | Description |
703
- | --- | --- | --- | --- |
704
- | stepSize | <code>boolean</code> | <code>true</code> | If `true`, then `startDate` and `endDate` are rounded to match `timePickerStepSize` (no warning) |
705
- | minMax | <code>boolean</code> | <code>true</code> | If `true` and `startDate` and `endDate` do not fall into `minDate` and `maxDate` then dates are shifted and a warning is written to console. |
706
- | span | <code>boolean</code> | <code>true</code> | If `true` and `startDate` and `endDate` do not fall into `minDate` and `maxSpan` then `endDate` is shifted and a warning is written to console. |
707
- | invalidDate | <code>boolean</code> | <code>false</code> | If `true` and `invalidDate` returns `true`, then an error is logged to console |
708
- | invalidTime | <code>boolean</code> | <code>false</code> | If `true` and `invalidTime` returns `true`, then an error is logged to console |
709
- | writeWarning | <code>boolean</code> | <code>true</code> | If `true` a warning is written to console if `startDate` or `endDate` is modified with the exception of rounding due to `timePickerStepSize`. |
715
+ | Name | Type | Description |
716
+ | --- | --- | --- |
717
+ | startDate | [<code>DateTime</code>](https://moment.github.io/luxon/api-docs/index.html#datetime) | Violation of startDate |
718
+ | endDate | [<code>DateTime</code>](https://moment.github.io/luxon/api-docs/index.html#datetime) \| <code>undefined</code> | Violation of endDate |
719
+ | reason | <code>Array</code> | The constraint which violates the input |
720
+ | old | [<code>DateTime</code>](https://moment.github.io/luxon/api-docs/index.html#datetime) | Old value startDate/endDate |
721
+ | new | [<code>DateTime</code>](https://moment.github.io/luxon/api-docs/index.html#datetime) | Corrected value of startDate/endDate |
710
722
 
711
723
  <a name="callback"></a>
712
724
 
@@ -121,8 +121,7 @@
121
121
  * @property {function|string} altFormat=null - The output format used for `altInput`.<br/>
122
122
  * Either a string used with {@link https://moment.github.io/luxon/api-docs/index.html#datetimetoformat|toFormat()} or a function.<br/>
123
123
  * Examples: `'yyyyMMddHHmm'`, `(date) => date.toUnixInteger()`
124
- * @property {boolean} warnings=true - When enabled, then warning are printed to console if input date violates
125
- * `minDate`, `maxDate`, `minSpan`, `maxSpan`, `timePickerStepSize`, `isInvalidDate`, `isInvalidTime`
124
+ * @property {boolean} ~~warnings~~ - Not used anymore. Listen to event `violated.daterangepicker` to react on invalid input data
126
125
 
127
126
  * @property {string} applyButtonClasses=btn-primary - CSS class names that will be added only to the apply button
128
127
  * @property {string} cancelButtonClasses=btn-default - CSS class names that will be added only to the cancel button
@@ -233,7 +232,6 @@
233
232
  this.weekendClasses = 'weekend';
234
233
  this.weekendDayClasses = 'weekend-day';
235
234
  this.todayClasses = 'today';
236
- this.warnings = true;
237
235
  this.altInput = null;
238
236
  this.altFormat = null;
239
237
  this.ranges = {};
@@ -362,7 +360,7 @@
362
360
 
363
361
  for (let key of ['timePicker24Hour', 'showWeekNumbers', 'showISOWeekNumbers',
364
362
  'showDropdowns', 'linkedCalendars', 'showCustomRangeLabel',
365
- 'alwaysShowCalendars', 'autoApply', 'autoUpdateInput', 'warnings']) {
363
+ 'alwaysShowCalendars', 'autoApply', 'autoUpdateInput']) {
366
364
  if (typeof options[key] === 'boolean')
367
365
  this[key] = options[key];
368
366
  }
@@ -411,7 +409,7 @@
411
409
  }
412
410
 
413
411
  if (this.timePicker) {
414
- if (typeof options.timePickerSeconds === 'boolean') // backward compatibility
412
+ if (typeof options.timePickerSeconds === 'boolean') // backward compatibility
415
413
  this.timePickerStepSize = Duration.fromObject({ [options.timePickerSeconds ? 'seconds' : 'minutes']: 1 });
416
414
  if (typeof options.timePickerIncrement === 'number') // backward compatibility
417
415
  this.timePickerStepSize = Duration.fromObject({ minutes: options.timePickerIncrement });
@@ -531,6 +529,9 @@
531
529
  }
532
530
  }
533
531
 
532
+ if (options.warnings !== undefined)
533
+ console.warn(`Option 'warnings' not used anymore. Listen to event 'violated.daterangepicker'`);
534
+
534
535
  if (!this.startDate && this.initalMonth) {
535
536
  // No initial date selected
536
537
  this.endDate = null;
@@ -538,7 +539,7 @@
538
539
  console.error(`Option 'initalMonth' works only with 'timePicker: false'`);
539
540
  } else {
540
541
  // Do some sanity checks on startDate and endDate for minDate, maxDate, minSpan, maxSpan, etc.
541
- this.constrainDate();
542
+ this.validateInput();
542
543
  }
543
544
 
544
545
  if (typeof options.opens === 'string') {
@@ -602,7 +603,7 @@
602
603
  if (start == null || end == null)
603
604
  continue;
604
605
 
605
- const validRange = this.constrainDate({ span: false }, [range, start, end]);
606
+ const validRange = this.validateInput({ span: false }, [range, start, end]);
606
607
  options.ranges[range] = [validRange[0], validRange[1]];
607
608
 
608
609
  //Support unicode chars in the range names.
@@ -716,12 +717,11 @@
716
717
  * `startDate` must be a `luxon.DateTime` or `Date` or `string` according to {@link ISO-8601} or
717
718
  * a string matching `locale.format`.
718
719
  * The value of the attached `<input>` element is also updated.
719
- * Date value is rounded to match option `timePickerStepSize`<br/>
720
- * Functions `isInvalidDate` and `isInvalidTime` are not evaluated, you may set date/time which is not selectable in calendar.<br/>
721
- * If the `startDate` does not fall into `minDate` and `maxDate` then `startDate` is shifted and a warning is written to console.
720
+ * Date value is rounded to match option `timePickerStepSize` unless skipped by `violated.daterangepicker` event handler.<br/>
721
+ * If the `startDate` does not fall into `minDate` and `maxDate` then `startDate` is shifted unless skipped by `violated.daterangepicker` event handler.
722
722
  * @param {external:DateTime|external:Date|string} startDate - startDate to be set
723
723
  * @param {boolean} isValid=false - If `true` then the `startDate` is not checked against `minDate` and `maxDate`<br/>
724
- * Use this option only if you are really sure about the value you put in.
724
+ * Use this option only if you are sure about the value you put in.
725
725
  * @throws `RangeError` for invalid date values.
726
726
  * @example const DateTime = luxon.DateTime;
727
727
  * const drp = $('#picker').data('daterangepicker');
@@ -754,7 +754,7 @@
754
754
  }
755
755
 
756
756
  if (isValid === undefined || !isValid)
757
- this.constrainDate();
757
+ this.validateInput();
758
758
 
759
759
  if (!this.singleDatePicker && !this.endDate) {
760
760
  if (this.locale.durationFormat)
@@ -779,13 +779,12 @@
779
779
  * `endDate` must be a `luxon.DateTime` or `Date` or `string` according to {@link ISO-8601} or
780
780
  * a string matching`locale.format`.
781
781
  * The value of the attached `<input>` element is also updated.
782
- * Date value is rounded to match option `timePickerStepSize`<br/>
783
- * Functions `isInvalidDate` and `isInvalidTime` are not evaluated, you may set date/time which is not selectable in calendar.<br/>
782
+ * Date value is rounded to match option `timePickerStepSize` unless skipped by `violated.daterangepicker` event handler.<br/>
784
783
  * If the `endDate` does not fall into `minDate` and `maxDate` or into `minSpan` and `maxSpan`
785
- * then `endDate` is shifted and a warning is written to console.
784
+ * then `endDate` is shifted unless skipped by `violated.daterangepicker` event handler
786
785
  * @param {external:DateTime|external:Date|string} endDate - endDate to be set
787
786
  * @param {boolean} isValid=false - If `true` then the `endDate` is not checked against `minDate`, `maxDate` and `minSpan`, `maxSpan`<br/>
788
- * Use this option only if you are really sure about the value you put in.
787
+ * Use this option only if you are sure about the value you put in.
789
788
  * @throws `RangeError` for invalid date values.
790
789
  * @example const drp = $('#picker').data('daterangepicker');
791
790
  * drp.setEndDate('2025-03-28T18:30:00');
@@ -817,7 +816,7 @@
817
816
  }
818
817
 
819
818
  if (isValid === undefined || !isValid)
820
- this.constrainDate();
819
+ this.validateInput();
821
820
 
822
821
  this.previousRightTime = this.endDate;
823
822
 
@@ -848,7 +847,7 @@
848
847
  * @param {external:DateTime|external:Date|string} startDate - startDate to be set
849
848
  * @param {external:DateTime|external:Date|string} endDate - endDate to be set
850
849
  * @param {boolean} isValid=false - If `true` then the `startDate` and `endDate` are not checked against `minDate`, `maxDate` and `minSpan`, `maxSpan`<br/>
851
- * Use this option only if you are really sure about the value you put in.
850
+ * Use this option only if you are sure about the value you put in.
852
851
  * @throws `RangeError` for invalid date values.
853
852
  * @example const DateTime = luxon.DateTime;
854
853
  * const drp = $('#picker').data('daterangepicker');
@@ -861,7 +860,7 @@
861
860
  this.setStartDate(startDate, true);
862
861
  this.setEndDate(endDate, true);
863
862
  if (!isValid)
864
- this.constrainDate();
863
+ this.validateInput();
865
864
  }
866
865
  },
867
866
 
@@ -870,92 +869,81 @@
870
869
  },
871
870
 
872
871
  /**
873
- * @typedef constraintOptions
872
+ * @typedef InputViolation
874
873
  * @type {Object}
875
- * @property {boolean} stepSize=true If `true`, then `startDate` and `endDate` are rounded to match `timePickerStepSize` (no warning)
876
- * @property {boolean} minMax=true If `true` and `startDate` and `endDate` do not fall into `minDate` and `maxDate`
877
- * then dates are shifted and a warning is written to console.
878
- * @property {boolean} span=true If `true` and `startDate` and `endDate` do not fall into `minDate` and `maxSpan`
879
- * then `endDate` is shifted and a warning is written to console.
880
- * @property {boolean} invalidDate=false If `true` and `invalidDate` returns `true`, then an error is logged to console
881
- * @property {boolean} invalidTime=false If `true` and `invalidTime` returns `true`, then an error is logged to console
882
- * @property {boolean} writeWarning=true If `true` a warning is written to console if `startDate` or `endDate` is modified
883
- * with the exception of rounding due to `timePickerStepSize`.
874
+ * @property {external:DateTime} startDate - Violation of startDate
875
+ * @property {external:DateTime|undefined} endDate - Violation of endDate
876
+ * @property {Array} reason - The constraint which violates the input
877
+ * @property {external:DateTime} old - Old value startDate/endDate
878
+ * @property {external:DateTime} new - Corrected value of startDate/endDate
884
879
  */
885
880
 
886
881
  /**
887
882
  * Validate `startDate` and `endDate` or `range` against `timePickerStepSize`, `minDate`, `maxDate`,
888
- * `minSpan`, `maxSpan`, `invalidDate` and `invalidTime` and modifies them, if needed.
889
- * When `startDate` or `endDate` are modified, then a warning is written to console by default.
890
- * @param {constraintOptions} options - Defines which constraints shall be validated
883
+ * `minSpan`, `maxSpan`, `invalidDate` and `invalidTime` and corrects them, if needed.
884
+ * Correction can be skipped by returning `true` at event listener for `violated.daterangepicker`
891
885
  * @param {Array} [range] - Used to check prefefined range instead of `startDate` and `endDate` => `[name, startDate, endDate]`
892
886
  * When set, then function does not modify anything, just returning corrected range.
893
- * @throws `RangeError` if 'minDate' contradicts to 'minSpan'
894
- * @returns {Array} - Corrected range as array of `[startDate, endDate, isInvalid]` when range is set, otherwise just `isInvalid` object
887
+ * @emits "violated.daterangepicker"
888
+ * @returns {Array|null} - Corrected range as array of `[startDate, endDate]` when `range` is defined
895
889
  * @example
896
- * constrainDate({}, [DateTime.fromISO('2025-02-03'), DateTime.fromISO('2025-02-25')]) =>
897
- * [ DateTime.fromISO('2025-02-05'), DateTime.fromISO('2025-02-20'), { startDate: { stepped: ... }, endDate: { stepped: ..., modified: [{old: ... new: ..., reason: 'minSpan'}] } } ]
898
- * constrainDate({span: false, invalidDate: true, invalidTime: true}) =>
899
- * { startDate: {stepped: ..., modified: [{old: ... new: ..., reason: 'minDate'}], isInvalidDate: true, isInvalidTime: false}, endDate: {stepped: ..., isInvalidDate: false, isInvalidTime: true} } ]
890
+ * validateInput([DateTime.fromISO('2025-02-03'), DateTime.fromISO('2025-02-25')]) =>
891
+ * [ DateTime.fromISO('2025-02-05'), DateTime.fromISO('2025-02-20'), { startDate: { violations: [{old: ..., new: ..., reasson: 'minDate'}] } } ]
900
892
  */
901
- constrainDate: function ({ minMax = true, span = true, stepSize = true, invalidDate = false, invalidTime = false, writeWarning = this.warnings } = {}, range) {
902
- const name = range === undefined ? null : range[0];
903
- const nLog = range === undefined ? '' : ` of range '${name}'`;
893
+ validateInput: function (range) {
904
894
  let startDate = range === undefined ? this.startDate : range[1];
905
895
  let endDate = range === undefined ? this.endDate : range[2];
906
896
 
897
+ /**
898
+ * Emitted if the input values are not compliant to all constraints
899
+ * @event
900
+ * @name "violated.daterangepicker"
901
+ * @param {DateRangePicker} this - The daterangepicker object
902
+ * @param {InputViolation} violations - An object of input violations
903
+ * @return {boolean} skip - If `true`, then input values are not corrected and remain invalid
904
+ * @example
905
+ * $('#picker').on('violated.daterangepicker', (ev, picker, violations))
906
+ * [ DateTime.fromISO('2025-02-05'), DateTime.fromISO('2025-02-20'), { startDate: { violations: [{old: ..., new: ..., reasson: 'minDate'}] } } ]
907
+ */
908
+
907
909
  if (!startDate)
908
910
  return;
909
911
 
910
- let result = { startDate: { modified: [] } };
911
- if (invalidDate)
912
- result.startDate.isInvalidDate = false;
913
- if (invalidTime)
914
- result.startDate.isInvalidTime = false;
912
+ let result = { startDate: { violations: [] } };
915
913
 
916
- if (stepSize) {
917
- let modified = { old: startDate, reason: stepSize && this.timePicker ? 'timePickerStepSize' : 'No timePicker' };
918
- if (this.timePicker) {
919
- // Round time to step size
920
- const secs = this.timePickerStepSize.as('seconds');
921
- startDate = DateTime.fromSeconds(secs * Math.round(startDate.toSeconds() / secs));
922
- } else {
923
- startDate = startDate.startOf('day');
924
- }
925
- modified.new = startDate;
926
- if (modified.new != modified.old)
927
- result.startDate.modified.push(modified);
928
- }
929
-
930
-
931
- if (minMax) {
932
- if (this.minDate && startDate < this.minDate) {
933
- // If the startDate is earlier than minDate option, shift the startDate to allowable date
934
- let modified = { old: startDate, reason: 'minDate' };
935
- while (startDate < this.minDate)
936
- startDate = startDate.plus(this.timePicker ? this.timePickerStepSize : { days: 1 });
937
- modified.new = startDate;
938
- if (modified.new != modified.old) {
939
- result.startDate.modified.push(modified);
940
- if (writeWarning)
941
- console.warn(`Set 'startDate'${nLog} to ${this.logDate(startDate)} due to 'minDate'`);
942
- }
943
- } else if (this.maxDate && startDate > this.maxDate) {
944
- // If the startDate is later than maxDate option, shift the startDate to allowable date
945
- let modified = { old: startDate, reason: 'maxDate' };
946
- while (startDate > this.maxDate)
947
- startDate = startDate.minus(this.timePicker ? this.timePickerStepSize : { days: 1 });
948
- modified.new = startDate;
949
- if (modified.new != modified.old) {
950
- result.startDate.modified.push(modified);
951
- if (writeWarning)
952
- console.warn(`Set 'startDate'${nLog} to ${this.logDate(startDate)} due to 'maxDate'`);
953
- }
954
- }
914
+ let violation = { old: startDate, reason: this.timePicker ? 'timePickerStepSize' : 'timePicker' };
915
+ if (this.timePicker) {
916
+ // Round time to step size
917
+ const secs = this.timePickerStepSize.as('seconds');
918
+ startDate = DateTime.fromSeconds(secs * Math.round(startDate.toSeconds() / secs));
919
+ } else {
920
+ startDate = startDate.startOf('day');
921
+ }
922
+ violation.new = startDate;
923
+ if (!violation.new.equals(violation.old))
924
+ result.startDate.violations.push(violation);
925
+
926
+
927
+ if (this.minDate && startDate < this.minDate) {
928
+ // If the startDate is earlier than minDate option, shift the startDate to allowable date
929
+ violation = { old: startDate, reason: 'minDate' };
930
+ while (startDate < this.minDate)
931
+ startDate = startDate.plus(this.timePicker ? this.timePickerStepSize : { days: 1 });
932
+ violation.new = startDate;
933
+ if (!violation.new.equals(violation.old))
934
+ result.startDate.violations.push(violation);
935
+ } else if (this.maxDate && startDate > this.maxDate) {
936
+ // If the startDate is later than maxDate option, shift the startDate to allowable date
937
+ violation = { old: startDate, reason: 'maxDate' };
938
+ while (startDate > this.maxDate)
939
+ startDate = startDate.minus(this.timePicker ? this.timePickerStepSize : { days: 1 });
940
+ violation.new = startDate;
941
+ if (!violation.new.equals(violation.old))
942
+ result.startDate.violations.push(violation);
955
943
  }
956
944
 
957
945
  let units = ['hour'];
958
- if (invalidTime && this.timePicker) {
946
+ if (this.timePicker) {
959
947
  if (this.timePickerOpts.showMinutes)
960
948
  units.push('minute');
961
949
  if (this.timePickerOpts.showSeconds)
@@ -964,140 +952,107 @@
964
952
  units.push('ampm');
965
953
  }
966
954
 
967
- if (invalidDate && this.isInvalidDate(startDate)) {
968
- result.startDate.isInvalidDate = true;
969
- if (writeWarning)
970
- console.warn(`The 'startDate'${nLog} ${this.logDate(startDate)} is invalid by 'isInvalidDate'`);
971
- }
972
-
973
- if (invalidTime && this.timePicker) {
955
+ if (this.isInvalidDate(startDate))
956
+ result.startDate.violations.push({ old: startDate, new: startDate, reason: 'isInvalidDate' });
957
+ if (this.timePicker) {
974
958
  for (let unit of units) {
975
959
  if (this.isInvalidTime(startDate, unit, 'start'))
976
- result.startDate.isInvalidTime = true;
977
- if (writeWarning)
978
- console.warn(`The 'startDate'${nLog} ${this.logDate(startDate)} ${unit} is invalid by 'isInvalidTime'`);
960
+ result.startDate.violations.push({ old: startDate, new: startDate, reason: 'isInvalidTime', unit: unit });
979
961
  }
980
962
  }
981
963
 
982
- if (result.startDate.modified.length === 0)
983
- delete result.startDate.modified;
984
-
985
964
  if (this.singleDatePicker) {
986
965
  endDate = startDate;
987
966
  if (range === undefined) {
988
- this.startDate = startDate;
989
- this.endDate = endDate;
990
- return result;
967
+ if (result.startDate.violations.length > 0) {
968
+ if (!this.element.triggerHandler('violated.daterangepicker', [this, result])) {
969
+ this.startDate = startDate;
970
+ this.endDate = endDate;
971
+ }
972
+ }
973
+ return;
991
974
  } else {
992
975
  return [startDate, endDate, result];
993
976
  }
994
977
  }
995
-
996
978
  if (endDate == null)
997
- return result;
998
-
999
- result.endDate = { modified: [] };
1000
- if (invalidDate)
1001
- result.endDate.isInvalidDate = false;
1002
- if (invalidTime)
1003
- result.endDate.isInvalidTime = false;
979
+ return;
1004
980
 
1005
- if (stepSize) {
1006
- let modified = { old: endDate, reason: stepSize && this.timePicker ? 'timePickerStepSize' : 'No timePicker' };
1007
- if (this.timePicker) {
1008
- // Round time to step size
1009
- const secs = this.timePickerStepSize.as('seconds');
1010
- endDate = DateTime.fromSeconds(secs * Math.round(endDate.toSeconds() / secs));
1011
- } else {
1012
- endDate = endDate.endOf('day');
1013
- }
1014
- modified.new = endDate;
1015
- if (modified.new != modified.old)
1016
- result.endDate.modified.push(modified);
1017
- }
981
+ result.endDate = { violations: [] };
1018
982
 
1019
- if (minMax) {
1020
- if (this.maxDate && endDate > this.maxDate) {
1021
- // If the endDate is later than maxDate option, shorten the range to the allowable period.
1022
- let modified = { old: endDate, reason: 'maxDate' };
1023
- while (endDate > this.maxDate)
983
+ violation = { old: endDate, reason: this.timePicker ? 'stepSize' : 'timePicker' };
984
+ if (this.timePicker) {
985
+ // Round time to step size
986
+ const secs = this.timePickerStepSize.as('seconds');
987
+ endDate = DateTime.fromSeconds(secs * Math.round(endDate.toSeconds() / secs));
988
+ } else {
989
+ endDate = endDate.endOf('day');
990
+ }
991
+ violation.new = endDate;
992
+ if (!violation.new.equals(violation.old))
993
+ result.endDate.violations.push(violation);
994
+
995
+ if (this.maxDate && endDate > this.maxDate) {
996
+ // If the endDate is later than maxDate option, shorten the range to the allowable period.
997
+ violation = { old: endDate, reason: 'maxDate' };
998
+ while (endDate > this.maxDate)
999
+ endDate = endDate.minus(this.timePicker ? this.timePickerStepSize : { days: 1 });
1000
+ violation.new = endDate;
1001
+ if (!violation.new.equals(violation.old))
1002
+ result.endDate.violations.push(violation);
1003
+ } else if (this.minDate && endDate < this.minDate) {
1004
+ // If the endDate is earlier than minDate option, shorten the range to the allowable period.
1005
+ violation = { old: endDate, reason: 'minDate' };
1006
+ while (endDate < this.minDate)
1007
+ endDate = endDate.plus(this.timePicker ? this.timePickerStepSize : { days: 1 });
1008
+ violation.new = endDate;
1009
+ if (!violation.new.equals(violation.old))
1010
+ result.endDate.violations.push(violation);
1011
+ }
1012
+
1013
+ if (this.maxSpan) {
1014
+ // If the endDate exceeds those allowed by the maxSpan option, shorten the range to the allowable period.
1015
+ const maxDate = startDate.plus(this.maxSpan);
1016
+ if (endDate > maxDate) {
1017
+ violation = { old: endDate, reason: 'maxSpan' };
1018
+ while (endDate > maxDate)
1024
1019
  endDate = endDate.minus(this.timePicker ? this.timePickerStepSize : { days: 1 });
1025
- modified.new = endDate;
1026
- if (modified.new != modified.old) {
1027
- result.endDate.modified.push(modified);
1028
- if (writeWarning)
1029
- console.warn(`Set 'endDate'${nLog} to ${this.logDate(endDate)} due to 'maxDate'`);
1030
- }
1031
- } else if (this.minDate && endDate < this.minDate) {
1032
- // If the endDate is earlier than minDate option, shorten the range to the allowable period.
1033
- let modified = { old: endDate, reason: 'minDate' };
1034
- while (endDate < this.minDate)
1035
- endDate = endDate.plus(this.timePicker ? this.timePickerStepSize : { days: 1 });
1036
- modified.new = endDate;
1037
- if (modified.new != modified.old) {
1038
- result.endDate.modified.push(modified);
1039
- if (writeWarning)
1040
- console.warn(`Set 'endDate'${nLog} to ${this.logDate(endDate)} due to 'minDate'`);
1041
- }
1020
+ violation.new = endDate;
1021
+ if (!violation.new.equals(violation.old))
1022
+ result.endDate.violations.push(violation);
1042
1023
  }
1043
1024
  }
1044
1025
 
1045
- if (span) {
1046
- if (this.maxSpan) {
1047
- // If the endDate exceeds those allowed by the maxSpan option, shorten the range to the allowable period.
1048
- const maxDate = startDate.plus(this.maxSpan);
1049
- if (endDate > maxDate) {
1050
- let modified = { old: endDate, reason: 'maxSpan' };
1051
- while (endDate > maxDate)
1052
- endDate = endDate.minus(this.timePicker ? this.timePickerStepSize : { days: 1 });
1053
- modified.new = endDate;
1054
- if (modified.new != modified.old) {
1055
- result.endDate.modified.push(modified);
1056
- if (writeWarning)
1057
- console.warn(`Set 'endDate'${nLog} to ${this.logDate(endDate)} due to 'maxSpan'`);
1058
- }
1059
- }
1060
- }
1061
-
1062
- if (this.minSpan) {
1063
- // If the endDate falls below those allowed by the minSpan option, expand the range to the allowable period.
1064
- const minDate = startDate.plus(this.minSpan);
1065
- if (endDate < minDate) {
1066
- let modified = { old: endDate, reason: 'minSpan' };
1067
- while (endDate < minDate)
1068
- endDate = endDate.plus(this.timePicker ? this.timePickerStepSize : { days: 1 });
1069
- modified.new = endDate;
1070
- if (modified.new != modified.old) {
1071
- result.endDate.modified.push(modified);
1072
- if (writeWarning)
1073
- console.warn(`Set 'endDate'${nLog} to ${this.logDate(endDate)} due to 'minSpan'`);
1074
- }
1075
- }
1026
+ if (this.minSpan) {
1027
+ // If the endDate falls below those allowed by the minSpan option, expand the range to the allowable period.
1028
+ const minDate = startDate.plus(this.minSpan);
1029
+ if (endDate < minDate) {
1030
+ violation = { old: endDate, reason: 'minSpan' };
1031
+ while (endDate < minDate)
1032
+ endDate = endDate.plus(this.timePicker ? this.timePickerStepSize : { days: 1 });
1033
+ violation.new = endDate;
1034
+ if (!violation.new.equals(violation.old))
1035
+ result.endDate.violations.push(violation);
1076
1036
  }
1077
1037
  }
1078
1038
 
1079
- if (invalidDate && this.isInvalidDate(endDate)) {
1080
- result.endDate.isInvalidDate = true;
1081
- if (writeWarning)
1082
- console.warn(`The 'endDate'${nLog} ${this.logDate(endDate)} is invalid by 'isInvalidDate'`);
1083
- }
1084
-
1085
- if (invalidTime && this.timePicker) {
1039
+ if (this.isInvalidDate(endDate))
1040
+ result.endDate.violations.push({ old: endDate, new: endDate, reason: 'isInvalidDate' });
1041
+ if (this.timePicker) {
1086
1042
  for (let unit of units) {
1087
1043
  if (this.isInvalidTime(endDate, unit, 'end'))
1088
- result.endDate.isInvalidTime = true;
1089
- if (writeWarning)
1090
- console.warn(`The 'endDate'${nLog} ${this.logDate(endDate)} ${unit} is invalid by 'isInvalidTime'`);
1044
+ result.endDate.violations.push({ old: endDate, new: endDate, reason: 'isInvalidTime', unit: unit });
1091
1045
  }
1092
1046
  }
1093
1047
 
1094
- if (result.endDate.modified.length === 0)
1095
- delete result.endDate.modified;
1096
-
1097
1048
  if (range === undefined) {
1098
- this.startDate = startDate;
1099
- this.endDate = endDate;
1100
- return result;
1049
+ if (result.startDate.violations.length > 0 + result.endDate.violations.length > 0) {
1050
+ if (!this.element.triggerHandler('violated.daterangepicker', [this, result])) {
1051
+ this.startDate = startDate;
1052
+ this.endDate = endDate;
1053
+ }
1054
+ }
1055
+ return;
1101
1056
  } else {
1102
1057
  return [startDate, endDate, result];
1103
1058
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "daterangepicker-4.x",
3
- "version": "4.9.7",
3
+ "version": "4.10.0",
4
4
  "description": "Date range picker with time component and pre-defined ranges",
5
5
  "main": "daterangepicker.js",
6
6
  "style": "daterangepicker.css",