Reduce the amount of event listeners in NumberStepper

This commit is contained in:
redphx 2024-10-29 20:11:54 +07:00
parent 38211168e9
commit 4217b89194

View File

@ -25,9 +25,9 @@ export interface BxSelectSettingElement extends HTMLSelectElement, BxBaseSetting
export class SettingElement { export class SettingElement {
static #renderOptions(key: string, setting: PreferenceSetting, currentValue: any, onChange: any): BxSelectSettingElement { static #renderOptions(key: string, setting: PreferenceSetting, currentValue: any, onChange: any): BxSelectSettingElement {
const $control = CE<BxSelectSettingElement>('select', { const $control = CE<BxSelectSettingElement>('select', {
// title: setting.label, // title: setting.label,
tabindex: 0, tabindex: 0,
}); });
let $parent: HTMLElement; let $parent: HTMLElement;
if (setting.optionsGroup) { if (setting.optionsGroup) {
@ -64,10 +64,10 @@ export class SettingElement {
static #renderMultipleOptions(key: string, setting: PreferenceSetting, currentValue: any, onChange: any, params: MultipleOptionsParams={}): BxSelectSettingElement { static #renderMultipleOptions(key: string, setting: PreferenceSetting, currentValue: any, onChange: any, params: MultipleOptionsParams={}): BxSelectSettingElement {
const $control = CE<BxSelectSettingElement>('select', { const $control = CE<BxSelectSettingElement>('select', {
// title: setting.label, // title: setting.label,
multiple: true, multiple: true,
tabindex: 0, tabindex: 0,
}); });
if (params && params.size) { if (params && params.size) {
$control.setAttribute('size', params.size.toString()); $control.setAttribute('size', params.size.toString());
@ -164,6 +164,15 @@ export class SettingElement {
const MAX = options.reverse ? -setting.min! : setting.max!; const MAX = options.reverse ? -setting.min! : setting.max!;
const STEPS = Math.max(setting.steps || 1, 1); const STEPS = Math.max(setting.steps || 1, 1);
let intervalId: number | null;
let isHolding = false;
const clearIntervalId = () => {
console.log('clearIntervalId');
intervalId && clearInterval(intervalId);
intervalId = null;
}
const renderTextValue = (value: any) => { const renderTextValue = (value: any) => {
value = parseInt(value as string); value = parseInt(value as string);
@ -182,6 +191,10 @@ export class SettingElement {
const updateButtonsVisibility = () => { const updateButtonsVisibility = () => {
$btnDec.classList.toggle('bx-inactive', controlValue === MIN); $btnDec.classList.toggle('bx-inactive', controlValue === MIN);
$btnInc.classList.toggle('bx-inactive', controlValue === MAX); $btnInc.classList.toggle('bx-inactive', controlValue === MAX);
if (controlValue === MIN || controlValue === MAX) {
clearIntervalId();
}
} }
const $wrapper = CE<BxHtmlSettingElement>('div', {'class': 'bx-number-stepper', id: `bx_setting_${key}`}, const $wrapper = CE<BxHtmlSettingElement>('div', {'class': 'bx-number-stepper', id: `bx_setting_${key}`},
@ -212,7 +225,7 @@ export class SettingElement {
} }
$range = CE<HTMLInputElement>('input', { $range = CE<HTMLInputElement>('input', {
id: `bx_setting_${key}`, id: `bx_inp_setting_${key}`,
type: 'range', type: 'range',
min: MIN, min: MIN,
max: MAX, max: MAX,
@ -273,18 +286,8 @@ export class SettingElement {
updateButtonsVisibility(); updateButtonsVisibility();
let interval: number; const buttonPressed = (e: Event, $btn: HTMLElement) => {
let isHolding = false; console.log('changeValue');
const onClick = (e: Event) => {
if (isHolding) {
e.preventDefault();
isHolding = false;
return;
}
const $btn = e.target as HTMLElement;
let value = parseInt(controlValue); let value = parseInt(controlValue);
const btnType = $btn.dataset.type; const btnType = $btn.dataset.type;
@ -300,27 +303,45 @@ export class SettingElement {
$text.textContent = renderTextValue(value); $text.textContent = renderTextValue(value);
$range && ($range.value = value.toString()); $range && ($range.value = value.toString());
isHolding = false; onChange && onChange(e, value);
!(e as any).ignoreOnChange && onChange && onChange(e, value);
}
const onMouseDown = (e: PointerEvent) => {
e.preventDefault();
isHolding = true;
const args = arguments;
interval && clearInterval(interval);
interval = window.setInterval(() => {
e.target && BxEvent.dispatch(e.target as HTMLElement, 'click', {
arguments: args,
});
}, 200);
}; };
const onMouseUp = (e: PointerEvent) => { const onClick = (e: Event) => {
e.preventDefault();
if (isHolding) {
return;
}
console.log('click');
const $btn = (e.target as HTMLElement).closest('button') as HTMLElement;
$btn && buttonPressed(e, $btn);
clearIntervalId();
isHolding = false;
};
const onPointerDown = (e: PointerEvent) => {
console.log('down');
clearIntervalId();
const $btn = (e.target as HTMLElement).closest('button') as HTMLElement;
if (!$btn) {
return;
}
isHolding = true;
e.preventDefault(); e.preventDefault();
interval && clearInterval(interval); intervalId = window.setInterval((e: Event) => {
buttonPressed(e, $btn);
}, 200);
window.addEventListener('pointerup', onPointerUp, {once: true});
window.addEventListener('pointercancel', onPointerUp, {once: true});
};
const onPointerUp = (e: PointerEvent) => {
clearIntervalId();
isHolding = false; isHolding = false;
}; };
@ -332,16 +353,9 @@ export class SettingElement {
$range.value = options.reverse ? -value : value; $range.value = options.reverse ? -value : value;
}; };
$btnDec.addEventListener('click', onClick); $wrapper.addEventListener('click', onClick);
$btnDec.addEventListener('pointerdown', onMouseDown); $wrapper.addEventListener('pointerdown', onPointerDown);
$btnDec.addEventListener('pointerup', onMouseUp); $wrapper.addEventListener('contextmenu', onContextMenu);
$btnDec.addEventListener('contextmenu', onContextMenu);
$btnInc.addEventListener('click', onClick);
$btnInc.addEventListener('pointerdown', onMouseDown);
$btnInc.addEventListener('pointerup', onMouseUp);
$btnInc.addEventListener('contextmenu', onContextMenu);
setNearby($wrapper, { setNearby($wrapper, {
focus: $range || $btnInc, focus: $range || $btnInc,
}) })