add: dateSelector

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

View File

@ -348,7 +348,7 @@
}
}
.ui-grid-date-cell {
.ui-date-cell {
line-height: 22px;
box-sizing: border-box;
padding: var(--spacing-cell);

71
lib/ui/date.d.ts vendored Normal file
View File

@ -0,0 +1,71 @@
/**
*
* @param min
* @param max
* @returns
*/
export function createDateInput(min?: string, max?: string): HTMLInputElement;
/**
*
* @param date <br/><br/>
* <br/><br/>
* `"2024-01-26"`<br/>
* `"1/26/2024"`<br/>
* `"638418240000000000"`<br/>
* `new Date('2024-01-26')`<br/>
* @returns M/d/yyyy
*/
export function formatDate(date: Date | number | string): string;
/**
*
* @param element
* @param val {@linkcode formatDate}
*/
export function setDateValue(element: HTMLElement, val: Date | number | string): void;
/**
*
* @param element
* @param formatter `Date`
* @returns `ticks`
*/
export function getDateValue(element: HTMLInputElement, formatter?: (date: Date) => string): string;
/** 日期选择框类 */
export class DateSelector {
/**
*
* @param date
*/
onDateChanged?: (date: Date | any) => void;
/**
*
* @param opts
*/
constructor(opts: {
/** 父容器元素,可以为 `string` 作为选择器 */
parent: HTMLElement | string,
/** 最小可选择日期 */
minDate?: string,
/** 最大可选择日期 */
maxDate?: string,
/**
*
* @param date
* @returns
*/
valueFormatter?: (date: Date) => any
});
get enabled(): boolean;
set enabled(flag: boolean);
get value(): Date | any;
set value(val: Date | number | string);
set minDate(date: string);
set maxDate(date: string);
}

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;
}
}

View File

@ -1,11 +1,11 @@
import { global } from "../../utility";
// import { nullOrEmpty } from "../../utility/strings";
import { createElement } from "../../functions";
import { createIcon } from "../icon";
import { createCheckbox } from "../checkbox";
// import { setTooltip } from "../tooltip";
import { Dropdown } from "../dropdown";
import { convertCssStyle } from "../extension";
import { createDateInput, formatDate, setDateValue, getDateValue } from "../date";
export class GridColumn {
static create() {
@ -296,87 +296,25 @@ export class GridDateColumn extends GridColumn {
if (enabled === false) {
return super.create();
}
const date = createElement('input', 'ui-grid-date-cell');
date.required = true;
date.type = 'date';
if (col.dateMin != null) {
date.min = col.dateMin;
}
if (col.dateMax != null) {
date.max = col.dateMax;
}
const date = createDateInput(col.dateMin, col.dateMax);
// date.addEventListener('change', trigger);
date.addEventListener('blur', trigger);
return date;
}
static setValue(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 = this._toDateValue(new Date(val));
} else {
element.value = '';
}
} else {
if (!(val instanceof Date)) {
val = new Date((val - 621355968e9) / 1e4);
}
element.value = this._toDateValue(val);
}
} else {
element.innerText = this.formatDate(val);
}
setDateValue(element, val);
}
static getValue(e, col) {
const date = e.target?.valueAsDate;
if (date instanceof Date && !isNaN(date)) {
const year = date.getFullYear();
if (year < 1900 || year > 9999) {
return '';
}
if (typeof col.dateValueFormatter === 'function') {
return col.dateValueFormatter(date);
}
return String(date.getTime() * 1e4 + 621355968e9);
}
return '';
return getDateValue(e.target, col.dateValueFormatter);
}
static setEnabled(element, enabled) {
element.disabled = enabled === false;
}
static _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}`;
}
static _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);
}
static formatDate(date) {
date = this._resolveDate(date);
if (date instanceof Date && !isNaN(date)) {
return `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`;
}
return '';
return formatDate(date);
}
}