second commit
This commit is contained in:
210
node_modules/flowbite-datepicker/js/DateRangePicker.js
generated
vendored
Normal file
210
node_modules/flowbite-datepicker/js/DateRangePicker.js
generated
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
import {registerListeners, unregisterListeners} from './lib/event.js';
|
||||
import {formatDate} from './lib/date-format.js';
|
||||
import Datepicker from './Datepicker.js';
|
||||
|
||||
// filter out the config options inapproprite to pass to Datepicker
|
||||
function filterOptions(options) {
|
||||
const newOpts = Object.assign({}, options);
|
||||
|
||||
delete newOpts.inputs;
|
||||
delete newOpts.allowOneSidedRange;
|
||||
delete newOpts.maxNumberOfDates; // to ensure each datepicker handles a single date
|
||||
|
||||
return newOpts;
|
||||
}
|
||||
|
||||
function setupDatepicker(rangepicker, changeDateListener, el, options) {
|
||||
registerListeners(rangepicker, [
|
||||
[el, 'changeDate', changeDateListener],
|
||||
]);
|
||||
new Datepicker(el, options, rangepicker);
|
||||
}
|
||||
|
||||
function onChangeDate(rangepicker, ev) {
|
||||
// to prevent both datepickers trigger the other side's update each other
|
||||
if (rangepicker._updating) {
|
||||
return;
|
||||
}
|
||||
rangepicker._updating = true;
|
||||
|
||||
const target = ev.target;
|
||||
if (target.datepicker === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const datepickers = rangepicker.datepickers;
|
||||
const setDateOptions = {render: false};
|
||||
const changedSide = rangepicker.inputs.indexOf(target);
|
||||
const otherSide = changedSide === 0 ? 1 : 0;
|
||||
const changedDate = datepickers[changedSide].dates[0];
|
||||
const otherDate = datepickers[otherSide].dates[0];
|
||||
|
||||
if (changedDate !== undefined && otherDate !== undefined) {
|
||||
// if the start of the range > the end, swap them
|
||||
if (changedSide === 0 && changedDate > otherDate) {
|
||||
datepickers[0].setDate(otherDate, setDateOptions);
|
||||
datepickers[1].setDate(changedDate, setDateOptions);
|
||||
} else if (changedSide === 1 && changedDate < otherDate) {
|
||||
datepickers[0].setDate(changedDate, setDateOptions);
|
||||
datepickers[1].setDate(otherDate, setDateOptions);
|
||||
}
|
||||
} else if (!rangepicker.allowOneSidedRange) {
|
||||
// to prevent the range from becoming one-sided, copy changed side's
|
||||
// selection (no matter if it's empty) to the other side
|
||||
if (changedDate !== undefined || otherDate !== undefined) {
|
||||
setDateOptions.clear = true;
|
||||
datepickers[otherSide].setDate(datepickers[changedSide].dates, setDateOptions);
|
||||
}
|
||||
}
|
||||
datepickers[0].picker.update().render();
|
||||
datepickers[1].picker.update().render();
|
||||
delete rangepicker._updating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing a date range picker
|
||||
*/
|
||||
export default class DateRangePicker {
|
||||
/**
|
||||
* Create a date range picker
|
||||
* @param {Element} element - element to bind a date range picker
|
||||
* @param {Object} [options] - config options
|
||||
*/
|
||||
constructor(element, options = {}) {
|
||||
const inputs = Array.isArray(options.inputs)
|
||||
? options.inputs
|
||||
: Array.from(element.querySelectorAll('input'));
|
||||
if (inputs.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
element.rangepicker = this;
|
||||
this.element = element;
|
||||
this.inputs = inputs.slice(0, 2);
|
||||
this.allowOneSidedRange = !!options.allowOneSidedRange;
|
||||
|
||||
const changeDateListener = onChangeDate.bind(null, this);
|
||||
const cleanOptions = filterOptions(options);
|
||||
// in order for initial date setup to work right when pcicLvel > 0,
|
||||
// let Datepicker constructor add the instance to the rangepicker
|
||||
const datepickers = [];
|
||||
Object.defineProperty(this, 'datepickers', {
|
||||
get() {
|
||||
return datepickers;
|
||||
},
|
||||
});
|
||||
setupDatepicker(this, changeDateListener, this.inputs[0], cleanOptions);
|
||||
setupDatepicker(this, changeDateListener, this.inputs[1], cleanOptions);
|
||||
Object.freeze(datepickers);
|
||||
// normalize the range if inital dates are given
|
||||
if (datepickers[0].dates.length > 0) {
|
||||
onChangeDate(this, {target: this.inputs[0]});
|
||||
} else if (datepickers[1].dates.length > 0) {
|
||||
onChangeDate(this, {target: this.inputs[1]});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Array} - selected date of the linked date pickers
|
||||
*/
|
||||
get dates() {
|
||||
return this.datepickers.length === 2
|
||||
? [
|
||||
this.datepickers[0].dates[0],
|
||||
this.datepickers[1].dates[0],
|
||||
]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new values to the config options
|
||||
* @param {Object} options - config options to update
|
||||
*/
|
||||
setOptions(options) {
|
||||
this.allowOneSidedRange = !!options.allowOneSidedRange;
|
||||
|
||||
const cleanOptions = filterOptions(options);
|
||||
this.datepickers[0].setOptions(cleanOptions);
|
||||
this.datepickers[1].setOptions(cleanOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the DateRangePicker instance
|
||||
* @return {DateRangePicker} - the instance destroyed
|
||||
*/
|
||||
destroy() {
|
||||
this.datepickers[0].destroy();
|
||||
this.datepickers[1].destroy();
|
||||
unregisterListeners(this);
|
||||
delete this.element.rangepicker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the start and end dates of the date range
|
||||
*
|
||||
* The method returns Date objects by default. If format string is passed,
|
||||
* it returns date strings formatted in given format.
|
||||
* The result array always contains 2 items (start date/end date) and
|
||||
* undefined is used for unselected side. (e.g. If none is selected,
|
||||
* the result will be [undefined, undefined]. If only the end date is set
|
||||
* when allowOneSidedRange config option is true, [undefined, endDate] will
|
||||
* be returned.)
|
||||
*
|
||||
* @param {String} [format] - Format string to stringify the dates
|
||||
* @return {Array} - Start and end dates
|
||||
*/
|
||||
getDates(format = undefined) {
|
||||
const callback = format
|
||||
? date => formatDate(date, format, this.datepickers[0].config.locale)
|
||||
: date => new Date(date);
|
||||
|
||||
return this.dates.map(date => date === undefined ? date : callback(date));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the start and end dates of the date range
|
||||
*
|
||||
* The method calls datepicker.setDate() internally using each of the
|
||||
* arguments in start→end order.
|
||||
*
|
||||
* When a clear: true option object is passed instead of a date, the method
|
||||
* clears the date.
|
||||
*
|
||||
* If an invalid date, the same date as the current one or an option object
|
||||
* without clear: true is passed, the method considers that argument as an
|
||||
* "ineffective" argument because calling datepicker.setDate() with those
|
||||
* values makes no changes to the date selection.
|
||||
*
|
||||
* When the allowOneSidedRange config option is false, passing {clear: true}
|
||||
* to clear the range works only when it is done to the last effective
|
||||
* argument (in other words, passed to rangeEnd or to rangeStart along with
|
||||
* ineffective rangeEnd). This is because when the date range is changed,
|
||||
* it gets normalized based on the last change at the end of the changing
|
||||
* process.
|
||||
*
|
||||
* @param {Date|Number|String|Object} rangeStart - Start date of the range
|
||||
* or {clear: true} to clear the date
|
||||
* @param {Date|Number|String|Object} rangeEnd - End date of the range
|
||||
* or {clear: true} to clear the date
|
||||
*/
|
||||
setDates(rangeStart, rangeEnd) {
|
||||
const [datepicker0, datepicker1] = this.datepickers;
|
||||
const origDates = this.dates;
|
||||
|
||||
// If range normalization runs on every change, we can't set a new range
|
||||
// that starts after the end of the current range correctly because the
|
||||
// normalization process swaps start↔︎end right after setting the new start
|
||||
// date. To prevent this, the normalization process needs to run once after
|
||||
// both of the new dates are set.
|
||||
this._updating = true;
|
||||
datepicker0.setDate(rangeStart);
|
||||
datepicker1.setDate(rangeEnd);
|
||||
delete this._updating;
|
||||
|
||||
if (datepicker1.dates[0] !== origDates[1]) {
|
||||
onChangeDate(this, {target: this.inputs[1]});
|
||||
} else if (datepicker0.dates[0] !== origDates[0]) {
|
||||
onChangeDate(this, {target: this.inputs[0]});
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user