add: dateSelector

This commit is contained in:
2024-01-29 13:51:58 +08:00
parent 0696ecaff0
commit df42221b52
4 changed files with 230 additions and 68 deletions

153
lib/ui/date.js Normal file
View File

@ -0,0 +1,153 @@
import { createElement } from "../functions";
export function createDateInput(min, max) {
const date = createElement('input', 'ui-date-cell');
date.required = true;
date.type = 'date';
if (min != null) {
date.min = min;
}
if (max != null) {
date.max = max;
}
return date;
}
function toDateValue(dt) {
if (isNaN(dt)) {
return '';
}
const month = String(dt.getMonth() + 1).padStart(2, '0');
const date = String(dt.getDate()).padStart(2, '0');
return `${dt.getFullYear()}-${month}-${date}`;
}
function resolveDate(s) {
if (s instanceof Date) {
return s;
}
const ticks = Number(s);
if (!isNaN(ticks) && ticks > 0) {
return new Date((ticks - 621355968e9) / 1e4);
}
return new Date(s);
}
export function formatDate(date) {
date = resolveDate(date);
if (date instanceof Date && !isNaN(date)) {
return `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`;
}
return '';
}
export function setDateValue(element, val) {
if (element.tagName === 'INPUT') {
if (val === '') {
element.value = '';
} else if (isNaN(val)) {
if (/^\d{4}-\d{2}-\d{2}$/.test(val)) {
element.value = val;
} else if (/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(val)) {
element.value = toDateValue(new Date(val));
} else {
element.value = '';
}
} else {
if (!(val instanceof Date)) {
val = new Date((val - 621355968e9) / 1e4);
}
element.value = toDateValue(val);
}
} else {
element.innerText = formatDate(val);
}
}
export function getDateValue(element, formatter) {
const date = element?.valueAsDate;
if (date instanceof Date && !isNaN(date)) {
const year = date.getFullYear();
if (year < 1900 || year > 9999) {
return '';
}
if (typeof formatter === 'function') {
return formatter(date);
}
return String(date.getTime() * 1e4 + 621355968e9);
}
return '';
}
export class DateSelector {
_var = {
parent: null,
options: null
};
onDateChanged;
constructor(opts) {
opts ??= {};
if (typeof opts.parent === 'string') {
opts.parent = document.querySelector(opts.parent);
}
if (!(opts.parent instanceof HTMLElement)) {
throw new Error('no specified parent.');
}
this._var.options = opts;
this._var.parent = opts.parent;
const el = createDateInput(opts.minDate, opts.maxDate);
el.addEventListener('blur', e => {
const date = this._getDate(e.target.valueAsDate);
if (date == null) {
e.target.value = '';
}
if (typeof this.onDateChanged === 'function') {
this.onDateChanged(date);
}
});
this._var.el = el;
parent.appendChild(el);
}
get enabled() { return !this._var.el.disabled }
set enabled(flag) {
this._var.el.disabled = flag === false;
}
get value() { return this._getDate(this._var.el.valueAsDate) }
set value(val) {
setDateValue(this._var.el, val);
}
/**
* @param {string} date
*/
set minDate(date) {
this._var.el.min = date;
this._var.options.minDate = date;
}
/**
* @param {string} date
*/
set maxDate(date) {
this._var.el.max = date;
this._var.options.maxDate = date;
}
_getDate(date) {
if (date instanceof Date && !isNaN(date)) {
const year = date.getFullYear();
if (year < 1900 || year > 9999) {
return null;
}
if (typeof this._var.options.valueFormatter === 'function') {
return this._var.options.valueFormatter(date);
}
return date;
}
return null;
}
}