daterangepicker-4.x 4.1.9 → 4.2.1

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.
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.1.9/daterangepicker.min.js"></script>
22
- <link type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker-4.x@4.1.9/daterangepicker.min.css" rel="stylesheet" />
21
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker-4.x@4.2.1/daterangepicker.min.js"></script>
22
+ <link type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker-4.x@4.2.1/daterangepicker.min.css" rel="stylesheet" />
23
23
 
24
24
  <input type="text" id="daterange" />
25
25
 
@@ -56,21 +56,9 @@ isInvalidDate: function(date) {
56
56
 
57
57
  ### `isInvalidTime`
58
58
  ```js
59
- const validRange = [DateTime.fromSQL('2025-03-01 11:30'), DateTime.fromSQL('2025-04-21 18:30')];
60
-
61
59
  isInvalidTime: (time, side, unit) => {
62
- if (side == 'start' && time.hasSame(validRange[0], 'day')) {
63
- if (unit == 'hour') {
64
- return time.hour < validRange[0].hour;
65
- } else {
66
- return time.hasSame(validRange[0], 'hour') ? time.minute < validRange[0].minute : false;
67
- }
68
- } else if (side == 'end' && t.hasSame(validRange[1], 'day')) {
69
- if (unit == 'hour') {
70
- return time.hour > validRange[1].hour;
71
- } else {
72
- return time.hasSame(validRange[1], 'hour') ? time.minute > validRange[1].minute : false;
73
- }
60
+ if (unit == 'hour') {
61
+ return time.hour >= 10 && time.hour <= 14; // Works also with 12-hour clock
74
62
  } else {
75
63
  return false;
76
64
  }
@@ -111,6 +99,7 @@ Compared to [inital repository](https://github.com/dangrossman/daterangepicker),
111
99
  - Added option `minSpan` similar to `maxSpan`
112
100
  - Added option `isInvalidTime` similar to `isInvalidDate`
113
101
  - Added option `onOutsideClick` where you can define whether picker shall apply or revert selected value
102
+ - Added option `initalMonth` to show datepicker without an initial date
114
103
  - Better validation of input parameters, errors are logged to console
115
104
  - Highlight range in calendar when hovering over pre-defined ranges
116
105
  - Option `autoUpdateInput` defines whether the attached `<input>` element is updated when the user clicks on a date value.<br/>
@@ -479,6 +468,7 @@ Options for DateRangePicker
479
468
  | maxDate | [<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> \| <code>null</code> | | The latest date a user may select or `null` for no limit.<br/> Must be a `luxon.DateTime` or `Date` or `string` according to [ISO-8601](ISO-8601) or a string matching `locale.format`. |
480
469
  | minSpan | [<code>Duration</code>](https://moment.github.io/luxon/api-docs/index.html#duration) \| <code>string</code> \| <code>number</code> \| <code>null</code> | | The maximum span between the selected start and end dates.<br/> Must be a `luxon.Duration` or number of seconds or a string according to [ISO-8601](ISO-8601) duration.<br/> Ignored when `singleDatePicker: true` |
481
470
  | maxSpan | [<code>Duration</code>](https://moment.github.io/luxon/api-docs/index.html#duration) \| <code>string</code> \| <code>number</code> \| <code>null</code> | | The minimum span between the selected start and end dates.<br/> Must be a `luxon.Duration` or number of seconds or a string according to [ISO-8601](ISO-8601) duration.<br/> Ignored when `singleDatePicker: true` |
471
+ | initalMonth | [<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> \| <code>null</code> | | Default: `DateTime.now().startOf('month')`<br/> The inital month shown when `startDate: null`. <br/> Must be a `luxon.DateTime` or `Date` or `string` according to [ISO-8601](ISO-8601) or a string matching `locale.format`.<br/> When `initalMonth` is used, then `endDate` is ignored and it works only with `timePicker: false` |
482
472
  | autoApply | <code>boolean</code> | <code>false</code> | Hide the `Apply` and `Cancel` buttons, and automatically apply a new date range as soon as two dates are clicked.<br/> Only useful when `timePicker: false` |
483
473
  | singleDatePicker | <code>boolean</code> | <code>false</code> | Show only a single calendar to choose one date, instead of a range picker with two calendars.<br/> The start and end dates provided to your callback will be the same single date chosen. |
484
474
  | showDropdowns | <code>boolean</code> | <code>false</code> | Show year and month select boxes above calendars to jump to a specific month and year |
@@ -487,8 +477,8 @@ Options for DateRangePicker
487
477
  | showWeekNumbers | <code>boolean</code> | <code>false</code> | Show **localized** week numbers at the start of each week on the calendars |
488
478
  | showISOWeekNumbers | <code>boolean</code> | <code>false</code> | Show **ISO** week numbers at the start of each week on the calendars |
489
479
  | timePicker | <code>boolean</code> | <code>false</code> | Adds select boxes to choose times in addition to dates |
490
- | timePicker24Hour | <code>boolean</code> | <code>false</code> | Use 24-hour instead of 12-hour times, removing the AM/PM selection |
491
- | timePickerStepSize | [<code>Duration</code>](https://moment.github.io/luxon/api-docs/index.html#duration) \| <code>string</code> | | Default: `Duration.fromObject({minutes:1})`<br/>Set the time picker step size.<br/> Must be a `luxon.Duration` or number of seconds or a string according to [ISO-8601](ISO-8601) duration.<br/> Valid values are 1,2,3,4,5,6,10,12,15,20,30 for `Duration.fromObject({seconds: ...})` and `Duration.fromObject({minutes: ...})` and 1,2,3,4,6,(8,12) for `Duration.fromObject({hours: ...})`.<br/> Duration must be greater than `minSpan` and smaller than `maxSpan`.<br/> For example `timePickerStepSize: 600` will disable time picker seconds and time picker minutes are set to step size of 10 Minutes.<br/> Overwrites #timePickerIncrement and #timePickerSeconds |
480
+ | timePicker24Hour | <code>boolean</code> | <code>true</code> | Use 24-hour instead of 12-hour times, removing the AM/PM selection |
481
+ | timePickerStepSize | [<code>Duration</code>](https://moment.github.io/luxon/api-docs/index.html#duration) \| <code>string</code> \| <code>number</code> | | Default: `Duration.fromObject({minutes:1})`<br/>Set the time picker step size.<br/> Must be a `luxon.Duration` or the number of seconds or a string according to [ISO-8601](ISO-8601) duration.<br/> Valid values are 1,2,3,4,5,6,10,12,15,20,30 for `Duration.fromObject({seconds: ...})` and `Duration.fromObject({minutes: ...})` and 1,2,3,4,6,(8,12) for `Duration.fromObject({hours: ...})`.<br/> Duration must be greater than `minSpan` and smaller than `maxSpan`.<br/> For example `timePickerStepSize: 600` will disable time picker seconds and time picker minutes are set to step size of 10 Minutes.<br/> Overwrites `timePickerIncrement` and `timePickerSeconds` |
492
482
  | timePickerSeconds | <code>boolean</code> | <code>boolean</code> | **Deprecated**, use `timePickerStepSize`<br/>Show seconds in the timePicker |
493
483
  | timePickerIncrement | <code>boolean</code> | <code>1</code> | **Deprecated**, use `timePickerStepSize`<br/>Increment of the minutes selection list for times |
494
484
  | autoUpdateInput | <code>boolean</code> | <code>true</code> | Indicates whether the date range picker should instantly update the value of the attached `<input>` element when the selected dates change.<br/>The `<input>` element will be always updated on `Apply` and reverted when user clicks on `Cancel`. |
@@ -60,7 +60,11 @@
60
60
  * @property {external:Duration|string|number|null} maxSpan - The minimum span between the selected start and end dates.<br/>
61
61
  * Must be a `luxon.Duration` or number of seconds or a string according to {@link ISO-8601} duration.<br/>
62
62
  * Ignored when `singleDatePicker: true`
63
-
63
+ * @property {external:DateTime|external:Date|string|null} initalMonth - Default: `DateTime.now().startOf('month')`<br/>
64
+ * The inital month shown when `startDate: null`. <br/>
65
+ * Must be a `luxon.DateTime` or `Date` or `string` according to {@link ISO-8601} or a string matching `locale.format`.<br/>
66
+ * When `initalMonth` is used, then `endDate` is ignored and it works only with `timePicker: false`
67
+
64
68
  * @property {boolean} autoApply=false - Hide the `Apply` and `Cancel` buttons, and automatically apply a new date range as soon as two dates are clicked.<br/>
65
69
  * Only useful when `timePicker: false`
66
70
  * @property {boolean} singleDatePicker=false - Show only a single calendar to choose one date, instead of a range picker with two calendars.<br/>
@@ -72,14 +76,14 @@
72
76
  * @property {boolean} showISOWeekNumbers=false - Show **ISO** week numbers at the start of each week on the calendars
73
77
 
74
78
  * @property {boolean} timePicker=false - Adds select boxes to choose times in addition to dates
75
- * @property {boolean} timePicker24Hour=false - Use 24-hour instead of 12-hour times, removing the AM/PM selection
76
- * @property {external:Duration|string} timePickerStepSize - Default: `Duration.fromObject({minutes:1})`<br/>Set the time picker step size.<br/>
77
- * Must be a `luxon.Duration` or number of seconds or a string according to {@link ISO-8601} duration.<br/>
79
+ * @property {boolean} timePicker24Hour=true - Use 24-hour instead of 12-hour times, removing the AM/PM selection
80
+ * @property {external:Duration|string|number} timePickerStepSize - Default: `Duration.fromObject({minutes:1})`<br/>Set the time picker step size.<br/>
81
+ * Must be a `luxon.Duration` or the number of seconds or a string according to {@link ISO-8601} duration.<br/>
78
82
  * Valid values are 1,2,3,4,5,6,10,12,15,20,30 for `Duration.fromObject({seconds: ...})` and `Duration.fromObject({minutes: ...})`
79
83
  * and 1,2,3,4,6,(8,12) for `Duration.fromObject({hours: ...})`.<br/>
80
84
  * Duration must be greater than `minSpan` and smaller than `maxSpan`.<br/>
81
85
  * For example `timePickerStepSize: 600` will disable time picker seconds and time picker minutes are set to step size of 10 Minutes.<br/>
82
- * Overwrites #timePickerIncrement and #timePickerSeconds
86
+ * Overwrites `timePickerIncrement` and `timePickerSeconds`
83
87
  * @property {boolean} timePickerSeconds=boolean - **Deprecated**, use `timePickerStepSize`<br/>Show seconds in the timePicker
84
88
  * @property {boolean} timePickerIncrement=1 - **Deprecated**, use `timePickerStepSize`<br/>Increment of the minutes selection list for times
85
89
 
@@ -177,6 +181,7 @@
177
181
  this.maxDate = null;
178
182
  this.maxSpan = null;
179
183
  this.minSpan = null;
184
+ this.initalMonth = DateTime.now().startOf('month');
180
185
  this.autoApply = false;
181
186
  this.singleDatePicker = false;
182
187
  this.showDropdowns = false;
@@ -186,7 +191,7 @@
186
191
  this.showISOWeekNumbers = false;
187
192
  this.showCustomRangeLabel = true;
188
193
  this.timePicker = false;
189
- this.timePicker24Hour = false;
194
+ this.timePicker24Hour = true;
190
195
  this.timePickerStepSize = Duration.fromObject({ minutes: 1 });
191
196
  this.linkedCalendars = true;
192
197
  this.autoUpdateInput = true;
@@ -334,16 +339,17 @@
334
339
  if (typeof options.timePickerIncrement === 'number') // backward compatibility
335
340
  this.timePickerStepSize = Duration.fromObject({ minutes: options.timePickerIncrement });
336
341
 
337
- if (['string', 'object'].includes(typeof options.timePickerStepSize)) {
338
- let duration = this.timePickerStepSize;
342
+ if (['string', 'object', 'number'].includes(typeof options.timePickerStepSize)) {
343
+ let duration;
339
344
  if (options.timePickerStepSize instanceof Duration && options.timePickerStepSize.isValid) {
340
345
  duration = options.timePickerStepSize;
341
346
  } else if (Duration.fromISO(options.timePickerStepSize).isValid) {
342
347
  duration = Duration.fromISO(options.timePickerStepSize);
343
- } else if (typeof options[opt] === 'number' && Duration.fromObject({ seconds: this.timePickerStepSize }).isValid) {
344
- duration = Duration.fromObject({ seconds: this.timePickerStepSize });
348
+ } else if (typeof options.timePickerStepSize === 'number' && Duration.fromObject({ seconds: options.timePickerStepSize }).isValid) {
349
+ duration = Duration.fromObject({ seconds: options.timePickerStepSize });
345
350
  } else {
346
351
  console.error(`Option 'timePickerStepSize' is not valid`);
352
+ duration = this.timePickerStepSize;
347
353
  };
348
354
  var valid = [];
349
355
  for (let unit of ['minutes', 'seconds'])
@@ -355,13 +361,16 @@
355
361
  if (valid.some(x => duration.rescale().equals(x))) {
356
362
  if (this.maxSpan && duration > this.maxSpan) {
357
363
  console.error(`Option 'timePickerStepSize' ${JSON.stringify(duration.toObject())} must be smaller than 'maxSpan'`);
364
+ duration = this.timePickerStepSize;
358
365
  } else if (this.minSpan && duration < this.minSpan) {
359
366
  console.error(`Option 'timePickerStepSize' ${JSON.stringify(duration.toObject())} must be greater than 'minSpan'`);
367
+ duration = this.timePickerStepSize;
360
368
  } else {
361
369
  this.timePickerStepSize = duration.rescale();
362
370
  }
363
371
  } else {
364
372
  console.error(`Option 'timePickerStepSize' ${JSON.stringify(duration.toObject())} is not valid`);
373
+ duration = this.timePickerStepSize;
365
374
  }
366
375
  }
367
376
 
@@ -396,7 +405,7 @@
396
405
  }
397
406
  }
398
407
 
399
- for (let opt of ['startDate', 'endDate', 'minDate', 'maxDate']) {
408
+ for (let opt of ['startDate', 'endDate', 'minDate', 'maxDate', 'initalMonth']) {
400
409
  if (opt == 'endDate' && this.singleDatePicker)
401
410
  continue;
402
411
  if (typeof options[opt] === 'object') {
@@ -425,8 +434,13 @@
425
434
  if (this.maxDate)
426
435
  this.maxDate = this.maxDate.endOf('day');
427
436
  }
428
- if (this.singleDatePicker)
437
+ if (this.singleDatePicker) {
438
+ this.endDate = this.startDate;
439
+ } else if (this.endDate < this.startDate) {
429
440
  this.endDate = this.startDate;
441
+ }
442
+ if (!this.startDate && this.initalMonth)
443
+ this.endDate = null;
430
444
 
431
445
  // Do some sanity checks on startDate for minDate, maxDate
432
446
  this.constrainDate();
@@ -594,8 +608,10 @@
594
608
  }
595
609
 
596
610
  if (!this.timePicker) {
597
- this.startDate = this.startDate.startOf('day');
598
- this.endDate = this.endDate.endOf('day');
611
+ if (this.startDate)
612
+ this.startDate = this.startDate.startOf('day');
613
+ if (this.endDate)
614
+ this.endDate = this.endDate.endOf('day');
599
615
  this.container.find('.calendar-time').hide();
600
616
  }
601
617
 
@@ -865,7 +881,7 @@
865
881
  console.warn(`Set startDate${nLog} to ${this.timePicker ? startDate.toISO({ suppressMilliseconds: true }) : startDate.toISODate()} due to 'minDate'`);
866
882
  } else if (this.maxDate && startDate > this.maxDate) {
867
883
  if (this.timePicker) {
868
- while (startDate > this.minDate)
884
+ while (startDate > this.maxDate)
869
885
  startDate = startDate.minus(this.timePickerStepSize);
870
886
  } else {
871
887
  startDate = this.maxDate.startOf('day');
@@ -918,7 +934,15 @@
918
934
  }
919
935
 
920
936
  if (minMax) {
921
- if (this.minDate && endDate < this.minDate) {
937
+ if (this.maxDate && endDate > this.maxDate) {
938
+ if (this.timePicker) {
939
+ while (endDate > this.maxDate)
940
+ endDate = endDate.minus(this.timePickerStepSize);
941
+ } else {
942
+ endDate = this.maxDate.endOf('day');
943
+ }
944
+ console.warn(`Set endDate${nLog} to ${this.timePicker ? endDate.toISO({ suppressMilliseconds: true }) : endDate.toISODate()} due to 'maxDate'`);
945
+ } else if (this.minDate && endDate < this.minDate) {
922
946
  if (this.timePicker) {
923
947
  while (endDate < this.minDate)
924
948
  endDate = endDate.plus(this.timePickerStepSize);
@@ -926,14 +950,6 @@
926
950
  endDate = this.minDate;
927
951
  }
928
952
  console.warn(`Set endDate${nLog} to ${this.timePicker ? endDate.toISO({ suppressMilliseconds: true }) : endDate.toISODate()} due to 'minDate'`);
929
- } else if (this.maxDate && endDate > this.maxDate) {
930
- if (this.timePicker) {
931
- while (endDate > this.minDate)
932
- endDate = endDate.minus(this.timePickerStepSize);
933
- } else {
934
- endDate = this.maxDate.endOf('day');
935
- }
936
- console.warn(`Set endDate${nLog} to ${this.timePicker ? endDate.toISO({ suppressMilliseconds: true }) : endDate.toISODate()} due to 'maxDate'`);
937
953
  }
938
954
  }
939
955
 
@@ -1015,10 +1031,12 @@
1015
1031
  this.container.find('.drp-duration-label').html(duration.toFormat(this.locale.durationFormat));
1016
1032
  }
1017
1033
  }
1018
- if (typeof this.locale.format === 'object') {
1019
- this.container.find('.drp-selected').html(this.startDate.toLocaleString(this.locale.format) + this.locale.separator + this.endDate.toLocaleString(this.locale.format));
1020
- } else {
1021
- this.container.find('.drp-selected').html(this.startDate.toFormat(this.locale.format) + this.locale.separator + this.endDate.toFormat(this.locale.format));
1034
+ if (this.startDate) {
1035
+ if (typeof this.locale.format === 'object') {
1036
+ this.container.find('.drp-selected').html(this.startDate.toLocaleString(this.locale.format) + this.locale.separator + this.endDate.toLocaleString(this.locale.format));
1037
+ } else {
1038
+ this.container.find('.drp-selected').html(this.startDate.toFormat(this.locale.format) + this.locale.separator + this.endDate.toFormat(this.locale.format));
1039
+ }
1022
1040
  }
1023
1041
  }
1024
1042
  this.updateMonthsInView();
@@ -1047,15 +1065,23 @@
1047
1065
  this.rightCalendar.month = this.startDate.startOf('month').plus({ month: 1 });
1048
1066
  }
1049
1067
  } else {
1050
- if (!this.leftCalendar.month.hasSame(this.startDate, 'month') && !this.rightCalendar.month.hasSame(this.startDate, 'month')) {
1051
- this.leftCalendar.month = this.startDate.startOf('month');
1052
- this.rightCalendar.month = this.startDate.startOf('month').plus({ month: 1 });
1068
+ // Inital view without date
1069
+ if (!this.startDate && this.initalMonth) {
1070
+ this.rightCalendar.month = this.initalMonth;
1071
+ this.rightCalendar.month = this.initalMonth.plus({ month: 1 });
1072
+ } else {
1073
+ if (!this.leftCalendar.month.hasSame(this.startDate, 'month') && !this.rightCalendar.month.hasSame(this.startDate, 'month')) {
1074
+ this.leftCalendar.month = this.startDate.startOf('month');
1075
+ this.rightCalendar.month = this.startDate.startOf('month').plus({ month: 1 });
1076
+ }
1053
1077
  }
1054
1078
  }
1079
+
1055
1080
  if (this.maxDate && this.linkedCalendars && !this.singleDatePicker && this.rightCalendar.month > this.maxDate) {
1056
1081
  this.rightCalendar.month = this.maxDate.startOf('month');
1057
1082
  this.leftCalendar.month = this.maxDate.startOf('month').minus({ month: 1 });
1058
1083
  }
1084
+
1059
1085
  },
1060
1086
 
1061
1087
  /**
@@ -1085,13 +1111,6 @@
1085
1111
  if (isNaN(second))
1086
1112
  second = parseInt(this.container.find('.left .secondselect option:last').val(), 10);
1087
1113
  }
1088
- if (!this.timePicker24Hour) {
1089
- var ampm = this.container.find('.left .ampmselect').val();
1090
- if (ampm === 'PM' && hour < 12)
1091
- hour += 12;
1092
- if (ampm === 'AM' && hour === 12)
1093
- hour = 0;
1094
- }
1095
1114
  } else {
1096
1115
  hour = parseInt(this.container.find('.right .hourselect').val(), 10);
1097
1116
  if (isNaN(hour))
@@ -1110,16 +1129,10 @@
1110
1129
  if (isNaN(second))
1111
1130
  second = parseInt(this.container.find('.right .secondselect option:last').val(), 10);
1112
1131
  }
1113
-
1114
- if (!this.timePicker24Hour) {
1115
- var ampm = this.container.find('.right .ampmselect').val();
1116
- if (ampm === 'PM' && hour < 12)
1117
- hour += 12;
1118
- if (ampm === 'AM' && hour === 12)
1119
- hour = 0;
1120
- }
1121
1132
  }
1133
+ //if (this.leftCalendar.month)
1122
1134
  this.leftCalendar.month = this.leftCalendar.month.set({ hour: hour, minute: minute, second: second });
1135
+ //if (this.rightCalendar.month)
1123
1136
  this.rightCalendar.month = this.rightCalendar.month.set({ hour: hour, minute: minute, second: second });
1124
1137
  }
1125
1138
 
@@ -1142,8 +1155,10 @@
1142
1155
  //
1143
1156
  // Build the matrix of dates that will populate the calendar
1144
1157
  //
1145
-
1146
1158
  var calendar = side == 'left' ? this.leftCalendar : this.rightCalendar;
1159
+ if (calendar.month == null && !this.startDate && this.initalMonth)
1160
+ calendar.month = this.initalMonth;
1161
+
1147
1162
  const firstDay = calendar.month.startOf('month');
1148
1163
  const lastDay = calendar.month.endOf('month').startOf('day');
1149
1164
  var theDate = calendar.month.startOf('month').minus({ day: 1 });
@@ -1172,7 +1187,7 @@
1172
1187
  // I have no clue why and how this shall be used in original code. Skip it, maybe I will find out later
1173
1188
  /*if (this.minDate && calendar[row][col].hasSame(this.minDate, 'month') && calendar[row][col] < this.minDate && side == 'left')
1174
1189
  calendar[row][col] = this.minDate;
1175
-
1190
+
1176
1191
  if (this.maxDate && calendar[row][col].hasSame(this.maxDate, 'month') && calendar[row][col] > this.maxDate && side == 'right')
1177
1192
  calendar[row][col] = this.maxDate;
1178
1193
  */
@@ -1314,7 +1329,7 @@
1314
1329
  classes.push('off', 'disabled');
1315
1330
 
1316
1331
  //highlight the currently selected start date
1317
- if (calendar[row][col].hasSame(this.startDate, 'day'))
1332
+ if (this.startDate != null && calendar[row][col].hasSame(this.startDate, 'day'))
1318
1333
  classes.push('active', 'start-date');
1319
1334
 
1320
1335
  //highlight the currently selected end date
@@ -1383,15 +1398,6 @@
1383
1398
  minute: !isNaN(selected.minute) ? selected.minute : timeSelector.find('.minuteselect option:selected').val(),
1384
1399
  second: !isNaN(selected.second) ? selected.second : timeSelector.find('.secondselect option:selected').val()
1385
1400
  });
1386
-
1387
- if (!this.timePicker24Hour) {
1388
- var ampm = timeSelector.find('.ampmselect option:selected').val();
1389
- if (ampm === 'PM' && selected.hour < 12)
1390
- selected = selected.set({ hour: selected.hour + 12 });
1391
- if (ampm === 'AM' && selected.hour === 12)
1392
- selected = selected.set({ hour: 0 });
1393
- }
1394
-
1395
1401
  }
1396
1402
 
1397
1403
  if (selected < this.startDate)
@@ -1406,16 +1412,13 @@
1406
1412
  //
1407
1413
 
1408
1414
  html = '<select class="hourselect">';
1415
+ const ampm = selected.toFormat('a', { locale: 'en-US' });
1416
+ let start = 0;
1417
+ if (!this.timePicker24Hour)
1418
+ start = ampm == 'AM' ? 1 : 13;
1409
1419
 
1410
- var start = this.timePicker24Hour ? 0 : 1;
1411
- var end = this.timePicker24Hour ? 23 : 12;
1412
-
1413
- for (var i = start; i <= end; i += this.timePickerOpts.hourStep) {
1414
- var i_in_24 = i;
1415
- if (!this.timePicker24Hour)
1416
- i_in_24 = selected.hour >= 12 ? (i == 12 ? 12 : i + 12) : (i == 12 ? 0 : i);
1417
-
1418
- let time = selected.set({ hour: i_in_24 });
1420
+ for (var i = start; i <= start + 23; i += this.timePickerOpts.hourStep) {
1421
+ let time = selected.set({ hour: i % 24 });
1419
1422
  let disabled = false;
1420
1423
  if (minDate && time.set({ minute: 59 }) < minDate)
1421
1424
  disabled = true;
@@ -1426,12 +1429,28 @@
1426
1429
  if (!disabled && this.isInvalidTime(time, this.singleDatePicker ? null : (side == 'left' ? 'start' : 'end'), 'hour'))
1427
1430
  disabled = true;
1428
1431
 
1429
- if (i_in_24 == selected.hour && !disabled) {
1430
- html += `<option value="${i}" selected="selected">${i}</option>`;
1431
- } else if (disabled) {
1432
- html += `<option value="${i}" disabled="disabled" class="disabled">${i}</option>`;
1432
+ if (this.timePicker24Hour) {
1433
+ if (!disabled && i == selected.hour) {
1434
+ html += `<option value="${i}" selected="selected">${i}</option>`;
1435
+ } else if (disabled) {
1436
+ html += `<option value="${i}" disabled="disabled" class="disabled">${i}</option>`;
1437
+ } else {
1438
+ html += `<option value="${i}">${i}</option>`;
1439
+ }
1433
1440
  } else {
1434
- html += `<option value="${i}">${i}</option>`;
1441
+ const i_12 = DateTime.fromFormat(`${i % 24}`, 'H').toFormat('h');
1442
+ const i_ampm = DateTime.fromFormat(`${i % 24}`, 'H').toFormat('a', { locale: 'en-US' });
1443
+ if (ampm == i_ampm) {
1444
+ if (!disabled && i == selected.hour) {
1445
+ html += `<option ampm="${i_ampm}" value="${i % 24}" selected="selected">${i_12}</option>`;
1446
+ } else if (disabled) {
1447
+ html += `<option ampm="${i_ampm}" value="${i % 24}" disabled="disabled" class="disabled">${i_12}</option>`;
1448
+ } else {
1449
+ html += `<option ampm="${i_ampm}" value="${i % 24}">${i_12}</option>`;
1450
+ }
1451
+ } else {
1452
+ html += `<option ampm="${i_ampm}" hidden="hidden" value="${i % 24}">${i_12}</option>`;
1453
+ }
1435
1454
  }
1436
1455
  }
1437
1456
 
@@ -1512,26 +1531,32 @@
1512
1531
 
1513
1532
  var am_html = '';
1514
1533
  var pm_html = '';
1534
+ let disabled = false;
1515
1535
 
1516
- if (minDate && selected.startOf('day').plus({ hour: 12 }) < minDate)
1517
- am_html = ' disabled="disabled" class="disabled"';
1518
-
1519
- if (maxDate && selected.startOf('day') > maxDate)
1520
- pm_html = ' disabled="disabled" class="disabled"';
1521
-
1522
- if (minLimit && selected.startOf('day') > minLimit)
1523
- pm_html = ' disabled="disabled" class="disabled"';
1524
-
1525
- if (this.isInvalidTime(time, this.singleDatePicker ? null : (side == 'left' ? 'start' : 'end'), 'ampm')) {
1536
+ if (minDate && selected.startOf('day') < minDate)
1537
+ disabled = true;
1538
+ if (maxDate && selected.endOf('day') > maxDate)
1539
+ disabled = true;
1540
+ if (minLimit && selected.startOf('day') < minLimit)
1541
+ disabled = true;
1542
+ if (disabled) {
1526
1543
  am_html = ' disabled="disabled" class="disabled"';
1527
1544
  pm_html = ' disabled="disabled" class="disabled"';
1545
+ } else {
1546
+ if (this.isInvalidTime(selected, this.singleDatePicker ? null : (side == 'left' ? 'start' : 'end'), 'ampm')) {
1547
+ if (selected.toFormat('a', { locale: 'en-US' }) == 'AM') {
1548
+ pm_html = ' disabled="disabled" class="disabled"';
1549
+ } else {
1550
+ am_html = ' disabled="disabled" class="disabled"';
1551
+ }
1552
+ }
1528
1553
  }
1529
1554
 
1530
1555
  html += `<option value="AM"${am_html}`;
1531
- if (selected.hour < 12)
1556
+ if (selected.toFormat('a', { locale: 'en-US' }) == 'AM')
1532
1557
  html += ' selected="selected"';
1533
1558
  html += `>${Info.meridiems()[0]}</option><option value="PM"${pm_html}`;
1534
- if (selected.hour >= 12)
1559
+ if (selected.toFormat('a', { locale: 'en-US' }) == 'PM')
1535
1560
  html += ' selected="selected"';
1536
1561
  html += `>${Info.meridiems()[1]}</option>`;
1537
1562
 
@@ -1893,32 +1918,37 @@
1893
1918
  //ignore dates that can't be selected
1894
1919
  if (!$(e.target).hasClass('available')) return;
1895
1920
 
1896
- var title = $(e.target).attr('data-title');
1897
- var row = title.substring(1, 2);
1898
- var col = title.substring(3, 4);
1899
- var cal = $(e.target).parents('.drp-calendar');
1921
+ let title = $(e.target).attr('data-title');
1922
+ const row = title.substring(1, 2);
1923
+ const col = title.substring(3, 4);
1924
+ const cal = $(e.target).parents('.drp-calendar');
1900
1925
  var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col];
1901
1926
 
1902
1927
  //highlight the dates between the start date and the date being hovered as a potential end date
1903
- var leftCalendar = this.leftCalendar;
1904
- var rightCalendar = this.rightCalendar;
1905
- var startDate = this.startDate;
1928
+ const leftCalendar = this.leftCalendar;
1929
+ const rightCalendar = this.rightCalendar;
1930
+ const startDate = this.startDate;
1931
+ const initalMonth = this.initalMonth;
1906
1932
  if (!this.endDate) {
1907
1933
  this.container.find('.drp-calendar tbody td').each(function (index, el) {
1908
1934
 
1909
1935
  //skip week numbers, only look at dates
1910
1936
  if ($(el).hasClass('week')) return;
1911
1937
 
1912
- var title = $(el).attr('data-title');
1913
- var row = title.substring(1, 2);
1914
- var col = title.substring(3, 4);
1915
- var cal = $(el).parents('.drp-calendar');
1916
- var dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col];
1938
+ const title = $(el).attr('data-title');
1939
+ const row = title.substring(1, 2);
1940
+ const col = title.substring(3, 4);
1941
+ const cal = $(el).parents('.drp-calendar');
1942
+ const dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col];
1917
1943
 
1918
- if ((dt > startDate) && dt < date || dt.hasSame(date, 'day')) {
1919
- $(el).addClass('in-range');
1920
- } else {
1944
+ if (!startDate && initalMonth) {
1921
1945
  $(el).removeClass('in-range');
1946
+ } else {
1947
+ if ((dt > startDate) && dt < date || dt.hasSame(date, 'day')) {
1948
+ $(el).addClass('in-range');
1949
+ } else {
1950
+ $(el).removeClass('in-range');
1951
+ }
1922
1952
  }
1923
1953
 
1924
1954
  });
@@ -1994,18 +2024,12 @@
1994
2024
  // * if one of the inputs above the calendars was focused, cancel that manual input
1995
2025
  //
1996
2026
 
1997
- if (this.endDate || date < this.startDate.startOf('day')) { //picking start
2027
+ if (this.endDate || !this.startDate || date < this.startDate.startOf('day')) { //picking start
1998
2028
  if (this.timePicker) {
1999
2029
  let hour = parseInt(this.container.find('.left .hourselect').val(), 10);
2000
2030
  if (isNaN(hour))
2001
2031
  hour = parseInt(this.container.find('.left .hourselect option:last').val(), 10);
2002
- if (!this.timePicker24Hour) {
2003
- var ampm = this.container.find('.left .ampmselect').val();
2004
- if (ampm === 'PM' && hour < 12)
2005
- hour += 12;
2006
- if (ampm === 'AM' && hour === 12)
2007
- hour = 0;
2008
- }
2032
+
2009
2033
  let minute = 0;
2010
2034
  if (this.timePickerOpts.showMinutes) {
2011
2035
  minute = parseInt(this.container.find('.left .minuteselect').val(), 10);
@@ -2035,13 +2059,6 @@
2035
2059
  let hour = parseInt(this.container.find('.right .hourselect').val(), 10);
2036
2060
  if (isNaN(hour))
2037
2061
  hour = parseInt(this.container.find('.right .hourselect option:last').val(), 10);
2038
- if (!this.timePicker24Hour) {
2039
- var ampm = this.container.find('.right .ampmselect').val();
2040
- if (ampm === 'PM' && hour < 12)
2041
- hour += 12;
2042
- if (ampm === 'AM' && hour === 12)
2043
- hour = 0;
2044
- }
2045
2062
 
2046
2063
  let minute = 0;
2047
2064
  if (this.timePickerOpts.showMinutes) {
@@ -2225,6 +2242,20 @@
2225
2242
  if (isNaN(hour))
2226
2243
  hour = parseInt(cal.find('.hourselect option:last').val(), 10);
2227
2244
 
2245
+ if (!this.timePicker24Hour) {
2246
+ const ampm = cal.find('.ampmselect').val();
2247
+ if (ampm == null)
2248
+ cal.find('.ampmselect option:last').val();
2249
+ if (ampm != DateTime.fromFormat(`${hour}`, 'H').toFormat('a', { locale: 'en-US' })) {
2250
+ cal.find('.hourselect > option').each(function () {
2251
+ const hidden = $(this).attr('hidden') || false;
2252
+ $(this).attr('hidden', hidden);
2253
+ });
2254
+ const h = DateTime.fromFormat(`${hour}`, 'H').toFormat('h')
2255
+ hour = DateTime.fromFormat(`${h}${ampm}`, 'ha', { locale: 'en-US' }).hour;
2256
+ }
2257
+ }
2258
+
2228
2259
  var minute = 0;
2229
2260
  if (this.timePickerOpts.showMinutes) {
2230
2261
  minute = parseInt(cal.find('.minuteselect').val(), 10);
@@ -2239,17 +2270,11 @@
2239
2270
  second = parseInt(cal.find('.secondselect option:last').val(), 10);
2240
2271
  }
2241
2272
 
2242
- if (!this.timePicker24Hour) {
2243
- var ampm = cal.find('.ampmselect').val();
2244
- if (ampm === 'PM' && hour < 12)
2245
- hour += 12;
2246
- if (ampm === 'AM' && hour === 12)
2247
- hour = 0;
2248
- }
2249
-
2250
2273
  if (isLeft) {
2251
- let start = this.startDate.set({ hour: hour, minute: minute, second: second });
2252
- this.setStartDate(start, true);
2274
+ if (this.startDate) {
2275
+ let start = this.startDate.set({ hour: hour, minute: minute, second: second });
2276
+ this.setStartDate(start, true);
2277
+ }
2253
2278
  if (this.singleDatePicker) {
2254
2279
  this.endDate = this.startDate;
2255
2280
  } else if (this.endDate && this.endDate.hasSame(start, 'day') && this.endDate < start) {
@@ -2337,6 +2362,8 @@
2337
2362
  * @private
2338
2363
  */
2339
2364
  updateElement: function () {
2365
+ if (this.startDate == null && this.initalMonth)
2366
+ return;
2340
2367
  if (this.element.is('input')) {
2341
2368
  let newValue = typeof this.locale.format === 'object' ? this.startDate.toLocaleString(this.locale.format) : this.startDate.toFormat(this.locale.format);
2342
2369
  if (!this.singleDatePicker) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "daterangepicker-4.x",
3
- "version": "4.1.9",
3
+ "version": "4.2.1",
4
4
  "description": "Date range picker with time component and pre-defined ranges",
5
5
  "main": "daterangepicker.js",
6
6
  "style": "daterangepicker.css",
@@ -18,7 +18,7 @@
18
18
  "jsdoc-to-markdown": "^9.0.0"
19
19
  },
20
20
  "author": {
21
- "name": "wernfried Domscheit",
21
+ "name": "Wernfried Domscheit",
22
22
  "url": "https://www.domscheit.ch"
23
23
  },
24
24
  "keywords": [