add: dateSelector
This commit is contained in:
parent
0696ecaff0
commit
df42221b52
@ -348,7 +348,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-grid-date-cell {
|
.ui-date-cell {
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: var(--spacing-cell);
|
padding: var(--spacing-cell);
|
||||||
|
71
lib/ui/date.d.ts
vendored
Normal file
71
lib/ui/date.d.ts
vendored
Normal 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
153
lib/ui/date.js
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
import { global } from "../../utility";
|
import { global } from "../../utility";
|
||||||
// import { nullOrEmpty } from "../../utility/strings";
|
|
||||||
import { createElement } from "../../functions";
|
import { createElement } from "../../functions";
|
||||||
import { createIcon } from "../icon";
|
import { createIcon } from "../icon";
|
||||||
import { createCheckbox } from "../checkbox";
|
import { createCheckbox } from "../checkbox";
|
||||||
// import { setTooltip } from "../tooltip";
|
// import { setTooltip } from "../tooltip";
|
||||||
import { Dropdown } from "../dropdown";
|
import { Dropdown } from "../dropdown";
|
||||||
import { convertCssStyle } from "../extension";
|
import { convertCssStyle } from "../extension";
|
||||||
|
import { createDateInput, formatDate, setDateValue, getDateValue } from "../date";
|
||||||
|
|
||||||
export class GridColumn {
|
export class GridColumn {
|
||||||
static create() {
|
static create() {
|
||||||
@ -296,87 +296,25 @@ export class GridDateColumn extends GridColumn {
|
|||||||
if (enabled === false) {
|
if (enabled === false) {
|
||||||
return super.create();
|
return super.create();
|
||||||
}
|
}
|
||||||
const date = createElement('input', 'ui-grid-date-cell');
|
const date = createDateInput(col.dateMin, col.dateMax);
|
||||||
date.required = true;
|
|
||||||
date.type = 'date';
|
|
||||||
if (col.dateMin != null) {
|
|
||||||
date.min = col.dateMin;
|
|
||||||
}
|
|
||||||
if (col.dateMax != null) {
|
|
||||||
date.max = col.dateMax;
|
|
||||||
}
|
|
||||||
// date.addEventListener('change', trigger);
|
// date.addEventListener('change', trigger);
|
||||||
date.addEventListener('blur', trigger);
|
date.addEventListener('blur', trigger);
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
static setValue(element, val) {
|
static setValue(element, val) {
|
||||||
if (element.tagName === 'INPUT') {
|
setDateValue(element, val);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static getValue(e, col) {
|
static getValue(e, col) {
|
||||||
const date = e.target?.valueAsDate;
|
return getDateValue(e.target, col.dateValueFormatter);
|
||||||
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 '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static setEnabled(element, enabled) {
|
static setEnabled(element, enabled) {
|
||||||
element.disabled = enabled === false;
|
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) {
|
static formatDate(date) {
|
||||||
date = this._resolveDate(date);
|
return formatDate(date);
|
||||||
if (date instanceof Date && !isNaN(date)) {
|
|
||||||
return `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`;
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user