@whitesev/domutils 1.9.7 → 1.9.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@whitesev/domutils",
4
- "version": "1.9.7",
4
+ "version": "1.9.10",
5
5
  "description": "适合在浏览器中操作DOM的常用工具类",
6
6
  "keywords": [
7
7
  "typescript",
@@ -33,20 +33,20 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "@eslint/js": "^9.39.2",
36
- "@rollup/plugin-commonjs": "^29.0.0",
36
+ "@rollup/plugin-commonjs": "^29.0.1",
37
37
  "@rollup/plugin-json": "^6.1.0",
38
38
  "@rollup/plugin-node-resolve": "^16.0.3",
39
39
  "@rollup/plugin-terser": "^0.4.4",
40
40
  "@rollup/plugin-typescript": "^12.3.0",
41
41
  "browserslist": "^4.28.1",
42
- "caniuse-lite": "^1.0.30001770",
42
+ "caniuse-lite": "^1.0.30001776",
43
43
  "eslint": "^9.39.2",
44
44
  "eslint-config-prettier": "^10.1.8",
45
45
  "eslint-plugin-compat": "^6.0.2",
46
- "eslint-plugin-prettier": "^5.5.4",
46
+ "eslint-plugin-prettier": "^5.5.5",
47
47
  "globals": "^16.5.0",
48
- "oxfmt": "^0.32.0",
49
- "oxlint": "1.46.0",
48
+ "oxfmt": "^0.36.0",
49
+ "oxlint": "1.51.0",
50
50
  "rollup": "^4.54.0",
51
51
  "rollup-plugin-clear": "^2.0.7",
52
52
  "tslib": "^2.8.1",
@@ -162,7 +162,7 @@ class ElementEvent extends ElementAnimate {
162
162
  * @param startIndex
163
163
  * @param option
164
164
  */
165
- function getOption(args: IArguments, startIndex: number, option: DOMUtilsEventListenerOption) {
165
+ const getOption = function (args: IArguments, startIndex: number, option: DOMUtilsEventListenerOption) {
166
166
  const currentParam = args[startIndex];
167
167
  if (typeof currentParam === "boolean") {
168
168
  option.capture = currentParam;
@@ -185,7 +185,7 @@ class ElementEvent extends ElementAnimate {
185
185
  option.isComposedPath = currentParam.isComposedPath;
186
186
  }
187
187
  return option;
188
- }
188
+ };
189
189
 
190
190
  const that = this;
191
191
  // eslint-disable-next-line prefer-rest-params
@@ -220,7 +220,11 @@ class ElementEvent extends ElementAnimate {
220
220
  selectorList.push(selector);
221
221
  }
222
222
  // 事件回调
223
- let listenerCallBack: (this: HTMLElement, event: Event, $selector?: HTMLElement) => void = callback as any;
223
+ let listenerCallBack: (this: Element, event: Event, $selector?: HTMLElement) => void | boolean = callback as (
224
+ this: Element,
225
+ event: Event,
226
+ $selector?: HTMLElement
227
+ ) => void | boolean;
224
228
  // 事件配置
225
229
  let listenerOption: DOMUtilsEventListenerOption = {
226
230
  capture: false,
@@ -240,39 +244,51 @@ class ElementEvent extends ElementAnimate {
240
244
  /**
241
245
  * 如果是once,那么删除该监听和元素上的事件和监听
242
246
  */
243
- const checkOptionOnceToRemoveEventListener = () => {
247
+ const checkOptionOnceToRemoveEventListener = ($el: DOMUtilsElementEventType) => {
244
248
  if (listenerOption.once) {
245
- that.off(element, eventType as any, selector as any, callback as any, option);
249
+ this.off($el, eventTypeList, selector as any, callback as any, option);
246
250
  }
247
251
  };
248
- $elList.forEach((elementItem) => {
252
+ $elList.forEach(($elItem) => {
249
253
  /**
250
254
  * 事件回调
251
255
  * @param event
252
256
  */
253
257
  const handlerCallBack = function (event: Event) {
258
+ let call_this: Element | undefined = void 0;
259
+ let call_event: Event | undefined = void 0;
260
+ let call_$selector: HTMLElement | undefined = void 0;
261
+ let execCallback = false;
254
262
  if (selectorList.length) {
255
- /* 存在子元素选择器 */
263
+ // 存在子元素选择器
256
264
  // 这时候的this和target都是子元素选择器的元素
257
- let eventTarget = listenerOption.isComposedPath
258
- ? (event.composedPath()[0] as HTMLElement)
259
- : (event.target as HTMLElement);
260
- let totalParent = elementItem;
261
- if (CommonUtils.isWin(totalParent)) {
262
- if (totalParent === (that.windowApi.document as any as HTMLElement)) {
263
- totalParent = that.windowApi.document.documentElement;
265
+ let $target: HTMLElement;
266
+ if (listenerOption.isComposedPath) {
267
+ // 可能为空
268
+ const composedPath = event.composedPath();
269
+ if (!composedPath.length && event.target) {
270
+ composedPath.push(event.target);
264
271
  }
272
+ $target = composedPath[0] as HTMLElement;
273
+ } else {
274
+ $target = event.target as HTMLElement;
275
+ }
276
+ let $parent = $elItem;
277
+ if (CommonUtils.isWin($parent)) {
278
+ // window和document共用一个对象
279
+ // 这样就能处理子元素选择器无法匹配的问题
280
+ $parent = that.windowApi.document.documentElement;
265
281
  }
266
- const findValue = selectorList.find((selectorItem) => {
282
+ const findValue = selectorList.find((selectors) => {
267
283
  // 判断目标元素是否匹配选择器
268
- if (that.matches(eventTarget, selectorItem)) {
269
- /* 当前目标可以被selector所匹配到 */
284
+ if (that.matches($target, selectors)) {
285
+ // 当前目标可以被selector所匹配到
270
286
  return true;
271
287
  }
272
- /* 在上层与主元素之间寻找可以被selector所匹配到的 */
273
- const $closestMatches = that.closest<HTMLElement>(eventTarget, selectorItem);
274
- if ($closestMatches && (<HTMLElement>totalParent)?.contains?.($closestMatches)) {
275
- eventTarget = $closestMatches;
288
+ // 在上层与主元素之间寻找可以被selector所匹配到的
289
+ const $closestMatches = that.closest<HTMLElement>($target, selectors);
290
+ if ($closestMatches && (<HTMLElement>$parent)?.contains?.($closestMatches)) {
291
+ $target = $closestMatches;
276
292
  return true;
277
293
  }
278
294
  return false;
@@ -282,30 +298,39 @@ class ElementEvent extends ElementAnimate {
282
298
  try {
283
299
  OriginPrototype.Object.defineProperty(event, "target", {
284
300
  get() {
285
- return eventTarget;
301
+ return $target;
286
302
  },
287
303
  });
288
- } catch {
289
- // TODO
290
- }
291
- listenerCallBack.call(eventTarget, event as any, eventTarget);
292
- checkOptionOnceToRemoveEventListener();
304
+ // oxlint-disable-next-line no-empty
305
+ } catch {}
306
+ execCallback = true;
307
+ call_this = $target;
308
+ call_event = event;
309
+ call_$selector = $target;
293
310
  }
294
311
  } else {
295
- // 这时候的this指向监听的元素
296
- listenerCallBack.call(elementItem as HTMLElement, event as any);
297
- checkOptionOnceToRemoveEventListener();
312
+ execCallback = true;
313
+ call_this = $elItem as Element;
314
+ call_event = event;
315
+ }
316
+ if (execCallback) {
317
+ const result = listenerCallBack.call(call_this!, call_event!, call_$selector!);
318
+ checkOptionOnceToRemoveEventListener($elItem);
319
+ if (typeof result === "boolean" && !result) {
320
+ return false;
321
+ }
298
322
  }
299
323
  };
300
324
 
301
- /* 遍历事件名设置元素事件 */
325
+ // 遍历事件名设置元素事件
302
326
  eventTypeList.forEach((eventName) => {
303
- elementItem.addEventListener(eventName, handlerCallBack, listenerOption);
304
- /* 获取对象上的事件 */
327
+ // add listener
328
+ $elItem.addEventListener(eventName, handlerCallBack, listenerOption);
329
+ // 获取对象上的事件
305
330
  const elementEvents: {
306
331
  [k: string]: DOMUtilsEventListenerOptionsAttribute[];
307
- } = Reflect.get(elementItem, GlobalData.domEventSymbol) || {};
308
- /* 初始化对象上的xx事件 */
332
+ } = Reflect.get($elItem, GlobalData.domEventSymbol) || {};
333
+ // 初始化对象上的xx事件
309
334
  elementEvents[eventName] = elementEvents[eventName] || [];
310
335
  elementEvents[eventName].push({
311
336
  selector: selectorList,
@@ -313,8 +338,8 @@ class ElementEvent extends ElementAnimate {
313
338
  handlerCallBack: handlerCallBack,
314
339
  callback: listenerCallBack,
315
340
  });
316
- /* 覆盖事件 */
317
- Reflect.set(elementItem, GlobalData.domEventSymbol, elementEvents);
341
+ // 覆盖事件
342
+ Reflect.set($elItem, GlobalData.domEventSymbol, elementEvents);
318
343
  });
319
344
  });
320
345
 
@@ -335,7 +360,7 @@ class ElementEvent extends ElementAnimate {
335
360
  /**
336
361
  * 主动触发事件
337
362
  * @param extraDetails 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
338
- * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true,如果为false,则直接调用callback,但是这种会让使用了$selector的没有值
363
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true,如果为false,则直接调用callback,但是这种会让使用了`$selector`的没有值
339
364
  */
340
365
  emit: (extraDetails?: object, useDispatchToTriggerEvent?: boolean) => {
341
366
  that.emit($elList, eventTypeList, extraDetails, useDispatchToTriggerEvent);
@@ -475,7 +500,7 @@ class ElementEvent extends ElementAnimate {
475
500
  * @param startIndex
476
501
  * @param option
477
502
  */
478
- function getOption(args1: IArguments, startIndex: number, option: EventListenerOptions) {
503
+ const getOption = function (args1: IArguments, startIndex: number, option: EventListenerOptions) {
479
504
  const currentParam: EventListenerOptions | boolean = args1[startIndex];
480
505
  if (typeof currentParam === "boolean") {
481
506
  option.capture = currentParam;
@@ -483,7 +508,7 @@ class ElementEvent extends ElementAnimate {
483
508
  option.capture = currentParam.capture;
484
509
  }
485
510
  return option;
486
- }
511
+ };
487
512
  const that = this;
488
513
  // eslint-disable-next-line prefer-rest-params
489
514
  const args = arguments;
@@ -533,15 +558,6 @@ class ElementEvent extends ElementAnimate {
533
558
  // 这是存在selector的情况
534
559
  listenerOption = getOption(args, 4, listenerOption);
535
560
  }
536
- // 是否移除所有事件
537
- let isRemoveAll = false;
538
- if (args.length === 2) {
539
- // 目标函数、事件名
540
- isRemoveAll = true;
541
- } else if ((args.length === 3 && typeof args[2] === "string") || Array.isArray(args[2])) {
542
- // 目标函数、事件名、子元素选择器
543
- isRemoveAll = true;
544
- }
545
561
  if (args.length === 5 && typeof args[4] === "function" && typeof filter !== "function") {
546
562
  // 目标函数、事件名、回调函数、事件配置、过滤函数
547
563
  filter = option as (
@@ -551,7 +567,7 @@ class ElementEvent extends ElementAnimate {
551
567
  ) => boolean;
552
568
  }
553
569
  $elList.forEach(($elItem) => {
554
- /* 获取对象上的事件 */
570
+ // 获取对象上的事件
555
571
  const elementEvents: {
556
572
  [key: string]: DOMUtilsEventListenerOptionsAttribute[];
557
573
  } = Reflect.get($elItem, GlobalData.domEventSymbol) || {};
@@ -579,7 +595,7 @@ class ElementEvent extends ElementAnimate {
579
595
  // 事件的配置项不同
580
596
  flag = false;
581
597
  }
582
- if (flag || isRemoveAll) {
598
+ if (flag) {
583
599
  $elItem.removeEventListener(eventName, handler.handlerCallBack, handler.option);
584
600
  const findIndex = handlers.findIndex((item) => item === handler);
585
601
  if (findIndex !== -1) {
@@ -588,7 +604,7 @@ class ElementEvent extends ElementAnimate {
588
604
  }
589
605
  }
590
606
  if (handlers.length === 0) {
591
- /* 如果没有任意的handler,那么删除该属性 */
607
+ // 如果没有任意的handler,那么删除该属性
592
608
  CommonUtils.delete(elementEvents, eventType);
593
609
  }
594
610
  });
@@ -1283,53 +1299,6 @@ class ElementEvent extends ElementAnimate {
1283
1299
  }
1284
1300
  return that.on(element, "keydown", null, handler, option);
1285
1301
  }
1286
- /**
1287
- * 当按键按下时触发事件
1288
- * keydown - > keypress - > keyup
1289
- * @param element 目标
1290
- * @param handler 事件处理函数
1291
- * @param option 配置
1292
- * @example
1293
- * // 监听a.xx元素的按键按下
1294
- * DOMUtils.keypress(document.querySelector("a.xx"),()=>{
1295
- * console.log("按键按下");
1296
- * })
1297
- * DOMUtils.keypress("a.xx",()=>{
1298
- * console.log("按键按下");
1299
- * })
1300
- */
1301
- onKeypress(
1302
- element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1303
- handler: (this: HTMLElement, event: DOMUtils_Event["keypress"]) => void,
1304
- option?: boolean | DOMUtilsEventListenerOption
1305
- ) {
1306
- const that = this;
1307
- if (element == null) {
1308
- return;
1309
- }
1310
- if (typeof element === "string") {
1311
- element = that.selectorAll(element);
1312
- }
1313
- if (CommonUtils.isNodeList(element)) {
1314
- // 设置
1315
- const listenerList: (DOMUtilsAddEventListenerResult | undefined)[] = [];
1316
- element.forEach(($ele) => {
1317
- const listener = that.onKeypress($ele as HTMLElement, handler, option);
1318
- listenerList.push(listener);
1319
- });
1320
- return {
1321
- off() {
1322
- listenerList.forEach((listener) => {
1323
- if (!listener) {
1324
- return;
1325
- }
1326
- listener.off();
1327
- });
1328
- },
1329
- } as DOMUtilsAddEventListenerResult;
1330
- }
1331
- return that.on(element, "keypress", null, handler, option);
1332
- }
1333
1302
  /**
1334
1303
  * 监听某个元素键盘按键事件或window全局按键事件
1335
1304
  * 按下有值的键时触发,按下Ctrl\Alt\Shift\Meta是无值键。按下先触发keydown事件,再触发keypress事件。
@@ -1395,7 +1364,7 @@ class ElementEvent extends ElementAnimate {
1395
1364
  **/
1396
1365
  onKeyboard(
1397
1366
  element: DOMUtilsTargetElementType | Element | DocumentFragment | Window | Node | typeof globalThis,
1398
- eventName: "keydown" | "keypress" | "keyup" = "keypress",
1367
+ eventName: "keydown" | "keyup" = "keydown",
1399
1368
  handler: (keyName: string, keyValue: number, otherCodeList: string[], event: KeyboardEvent) => void,
1400
1369
  options?: DOMUtilsEventListenerOption | boolean
1401
1370
  ): DOMUtilsAddEventListenerResult {
@@ -1634,7 +1603,7 @@ class ElementEvent extends ElementAnimate {
1634
1603
  * })
1635
1604
  */
1636
1605
  preventEvent(
1637
- $el: HTMLElement,
1606
+ $el: Element | Document | ShadowRoot,
1638
1607
  eventNameList: string | string[],
1639
1608
  option?: {
1640
1609
  /** (可选)是否捕获,默认false */
@@ -1665,7 +1634,7 @@ class ElementEvent extends ElementAnimate {
1665
1634
  * })
1666
1635
  */
1667
1636
  preventEvent(
1668
- $el: HTMLElement,
1637
+ $el: Element | Document | ShadowRoot,
1669
1638
  eventNameList: string | string[],
1670
1639
  selector: string | string[] | null | undefined,
1671
1640
  option?: {
@@ -1683,11 +1652,11 @@ class ElementEvent extends ElementAnimate {
1683
1652
  * 阻止事件的默认行为发生,并阻止事件传播
1684
1653
  */
1685
1654
  const stopEvent = (event: Event, onlyStopPropagation?: boolean) => {
1655
+ // 停止事件的传播,阻止它继续向更上层的元素冒泡,事件将不会再传播给其他的元素
1656
+ event?.stopPropagation();
1657
+ // 阻止事件传播,并且还能阻止元素上的其他事件处理程序被触发
1658
+ event?.stopImmediatePropagation();
1686
1659
  if (typeof onlyStopPropagation === "boolean" && onlyStopPropagation) {
1687
- // 停止事件的传播,阻止它继续向更上层的元素冒泡,事件将不会再传播给其他的元素
1688
- event?.stopPropagation();
1689
- // 阻止事件传播,并且还能阻止元素上的其他事件处理程序被触发
1690
- event?.stopImmediatePropagation();
1691
1660
  return;
1692
1661
  }
1693
1662
  // 阻止事件的默认行为发生。例如,当点击一个链接时,浏览器会默认打开链接的URL,或者在输入框内输入文字
@@ -1699,7 +1668,7 @@ class ElementEvent extends ElementAnimate {
1699
1668
  const onlyStopPropagation: boolean = args[1];
1700
1669
  return stopEvent(args[0], onlyStopPropagation);
1701
1670
  } else {
1702
- const $el: HTMLElement = args[0];
1671
+ const $el: Element | Document | ShadowRoot = args[0];
1703
1672
  let eventNameList: string | string[] = args[1];
1704
1673
  let selector: string | string[] | null | undefined = void 0;
1705
1674
  let capture = false;
@@ -1715,7 +1684,9 @@ class ElementEvent extends ElementAnimate {
1715
1684
  onlyStopPropagation?: boolean;
1716
1685
  }
1717
1686
  | undefined = void 0;
1718
- if (typeof args[2] === "string" || Array.isArray(args[2])) {
1687
+ if (args.length === 2) {
1688
+ // ignore
1689
+ } else if (typeof args[2] === "string" || Array.isArray(args[2])) {
1719
1690
  // selector
1720
1691
  selector = args[2];
1721
1692
  if (typeof args[3] === "object" && args[3] != null) {
package/src/Utils.ts CHANGED
@@ -103,7 +103,6 @@ class Utils {
103
103
  "is",
104
104
  "jquery",
105
105
  "keydown",
106
- "keypress",
107
106
  "keyup",
108
107
  "last",
109
108
  "load",
@@ -47,7 +47,12 @@ export type DOMUtils_MouseEventType = keyof DOMUtils_MouseEvent;
47
47
  export interface DOMUtils_KeyboardEvent {
48
48
  /** 键盘按下事件 */
49
49
  keydown: KeyboardEvent;
50
- /** 键盘按压事件(字符键) */
50
+ /**
51
+ * 键盘按压事件(字符键)
52
+ *
53
+ * @link https://developer.mozilla.org/zh-CN/docs/Web/API/Element/keypress_event
54
+ * @deprecated
55
+ */
51
56
  keypress: KeyboardEvent;
52
57
  /** 键盘释放事件 */
53
58
  keyup: KeyboardEvent;
@@ -364,6 +369,7 @@ export declare type DOMUtilsEventListenerOption = AddEventListenerOptions & {
364
369
  * 是否使用 event.composedPath() 来代替 event.target
365
370
  *
366
371
  * 一般用于设置了selector参数
372
+ * @default false
367
373
  */
368
374
  isComposedPath?: boolean;
369
375
  };