@whitesev/domutils 1.9.9 → 1.9.11

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/dist/index.umd.js CHANGED
@@ -4,7 +4,7 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.DOMUtils = factory());
5
5
  })(this, (function () { 'use strict';
6
6
 
7
- const version = "1.9.9";
7
+ const version = "1.9.11";
8
8
 
9
9
  class WindowApi {
10
10
  /** 默认的配置 */
@@ -1384,7 +1384,7 @@
1384
1384
  * @param startIndex
1385
1385
  * @param option
1386
1386
  */
1387
- function getOption(args, startIndex, option) {
1387
+ const getOption = function (args, startIndex, option) {
1388
1388
  const currentParam = args[startIndex];
1389
1389
  if (typeof currentParam === "boolean") {
1390
1390
  option.capture = currentParam;
@@ -1406,7 +1406,7 @@
1406
1406
  option.isComposedPath = currentParam.isComposedPath;
1407
1407
  }
1408
1408
  return option;
1409
- }
1409
+ };
1410
1410
  const that = this;
1411
1411
  // eslint-disable-next-line prefer-rest-params
1412
1412
  const args = arguments;
@@ -1461,74 +1461,96 @@
1461
1461
  // 这是存在selector的情况
1462
1462
  listenerOption = getOption(args, 4, listenerOption);
1463
1463
  }
1464
- /**
1465
- * 如果是once,那么删除该监听和元素上的事件和监听
1466
- */
1467
- const checkOptionOnceToRemoveEventListener = () => {
1468
- if (listenerOption.once) {
1469
- that.off(element, eventType, selector, callback, option);
1470
- }
1471
- };
1472
- $elList.forEach((elementItem) => {
1473
- /**
1474
- * 事件回调
1475
- * @param event
1476
- */
1477
- const handlerCallBack = function (event) {
1478
- if (selectorList.length) {
1479
- /* 存在子元素选择器 */
1480
- // 这时候的this和target都是子元素选择器的元素
1481
- let eventTarget = listenerOption.isComposedPath
1482
- ? event.composedPath()[0]
1483
- : event.target;
1484
- let totalParent = elementItem;
1485
- if (CommonUtils.isWin(totalParent)) {
1486
- if (totalParent === that.windowApi.document) {
1487
- totalParent = that.windowApi.document.documentElement;
1488
- }
1464
+ $elList.forEach(($elItem) => {
1465
+ // 遍历事件名设置元素事件
1466
+ eventTypeList.forEach((eventName) => {
1467
+ /**
1468
+ * 如果是option.once,那么删除该监听和元素上的事件和监听
1469
+ */
1470
+ const checkOptionOnceToRemoveEventListener = () => {
1471
+ if (listenerOption.once) {
1472
+ this.off($elItem, eventName, selector, callback, option);
1489
1473
  }
1490
- const findValue = selectorList.find((selectorItem) => {
1491
- // 判断目标元素是否匹配选择器
1492
- if (that.matches(eventTarget, selectorItem)) {
1493
- /* 当前目标可以被selector所匹配到 */
1494
- return true;
1474
+ };
1475
+ /**
1476
+ * 事件回调
1477
+ * @param event
1478
+ */
1479
+ const handlerCallBack = function (event) {
1480
+ let call_this = void 0;
1481
+ let call_event = void 0;
1482
+ let call_$selector = void 0;
1483
+ let execCallback = false;
1484
+ if (selectorList.length) {
1485
+ // 存在子元素选择器
1486
+ // 这时候的this和target都是子元素选择器的元素
1487
+ let $target;
1488
+ if (listenerOption.isComposedPath) {
1489
+ // 可能为空
1490
+ const composedPath = event.composedPath();
1491
+ if (!composedPath.length && event.target) {
1492
+ composedPath.push(event.target);
1493
+ }
1494
+ $target = composedPath[0];
1495
1495
  }
1496
- /* 在上层与主元素之间寻找可以被selector所匹配到的 */
1497
- const $closestMatches = that.closest(eventTarget, selectorItem);
1498
- if ($closestMatches && totalParent?.contains?.($closestMatches)) {
1499
- eventTarget = $closestMatches;
1500
- return true;
1496
+ else {
1497
+ $target = event.target;
1501
1498
  }
1502
- return false;
1503
- });
1504
- if (findValue) {
1505
- // 这里尝试使用defineProperty修改event的target值
1506
- try {
1507
- OriginPrototype.Object.defineProperty(event, "target", {
1508
- get() {
1509
- return eventTarget;
1510
- },
1511
- });
1499
+ let $parent = $elItem;
1500
+ if (CommonUtils.isWin($parent)) {
1501
+ // window和document共用一个对象
1502
+ // 这样就能处理子元素选择器无法匹配的问题
1503
+ $parent = that.windowApi.document.documentElement;
1512
1504
  }
1513
- catch {
1514
- // TODO
1505
+ const findValue = selectorList.find((selectors) => {
1506
+ // 判断目标元素是否匹配选择器
1507
+ if (that.matches($target, selectors)) {
1508
+ // 当前目标可以被selector所匹配到
1509
+ return true;
1510
+ }
1511
+ // 在上层与主元素之间寻找可以被selector所匹配到的
1512
+ const $closestMatches = that.closest($target, selectors);
1513
+ if ($closestMatches && $parent?.contains?.($closestMatches)) {
1514
+ $target = $closestMatches;
1515
+ return true;
1516
+ }
1517
+ return false;
1518
+ });
1519
+ if (findValue) {
1520
+ // 这里尝试使用defineProperty修改event的target值
1521
+ try {
1522
+ OriginPrototype.Object.defineProperty(event, "target", {
1523
+ get() {
1524
+ return $target;
1525
+ },
1526
+ });
1527
+ // oxlint-disable-next-line no-empty
1528
+ }
1529
+ catch { }
1530
+ execCallback = true;
1531
+ call_this = $target;
1532
+ call_event = event;
1533
+ call_$selector = $target;
1515
1534
  }
1516
- listenerCallBack.call(eventTarget, event, eventTarget);
1535
+ }
1536
+ else {
1537
+ execCallback = true;
1538
+ call_this = $elItem;
1539
+ call_event = event;
1540
+ }
1541
+ if (execCallback) {
1542
+ const result = listenerCallBack.call(call_this, call_event, call_$selector);
1517
1543
  checkOptionOnceToRemoveEventListener();
1544
+ if (typeof result === "boolean" && !result) {
1545
+ return false;
1546
+ }
1518
1547
  }
1519
- }
1520
- else {
1521
- // 这时候的this指向监听的元素
1522
- listenerCallBack.call(elementItem, event);
1523
- checkOptionOnceToRemoveEventListener();
1524
- }
1525
- };
1526
- /* 遍历事件名设置元素事件 */
1527
- eventTypeList.forEach((eventName) => {
1528
- elementItem.addEventListener(eventName, handlerCallBack, listenerOption);
1529
- /* 获取对象上的事件 */
1530
- const elementEvents = Reflect.get(elementItem, GlobalData.domEventSymbol) || {};
1531
- /* 初始化对象上的xx事件 */
1548
+ };
1549
+ // add listener
1550
+ $elItem.addEventListener(eventName, handlerCallBack, listenerOption);
1551
+ // 获取对象上的事件
1552
+ const elementEvents = Reflect.get($elItem, GlobalData.domEventSymbol) || {};
1553
+ // 初始化对象上的xx事件
1532
1554
  elementEvents[eventName] = elementEvents[eventName] || [];
1533
1555
  elementEvents[eventName].push({
1534
1556
  selector: selectorList,
@@ -1536,8 +1558,8 @@
1536
1558
  handlerCallBack: handlerCallBack,
1537
1559
  callback: listenerCallBack,
1538
1560
  });
1539
- /* 覆盖事件 */
1540
- Reflect.set(elementItem, GlobalData.domEventSymbol, elementEvents);
1561
+ // 覆盖事件
1562
+ Reflect.set($elItem, GlobalData.domEventSymbol, elementEvents);
1541
1563
  });
1542
1564
  });
1543
1565
  return {
@@ -1551,7 +1573,7 @@
1551
1573
  /**
1552
1574
  * 主动触发事件
1553
1575
  * @param extraDetails 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
1554
- * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true,如果为false,则直接调用callback,但是这种会让使用了$selector的没有值
1576
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true,如果为false,则直接调用callback,但是这种会让使用了`$selector`的没有值
1555
1577
  */
1556
1578
  emit: (extraDetails, useDispatchToTriggerEvent) => {
1557
1579
  that.emit($elList, eventTypeList, extraDetails, useDispatchToTriggerEvent);
@@ -1565,7 +1587,7 @@
1565
1587
  * @param startIndex
1566
1588
  * @param option
1567
1589
  */
1568
- function getOption(args1, startIndex, option) {
1590
+ const getOption = function (args1, startIndex, option) {
1569
1591
  const currentParam = args1[startIndex];
1570
1592
  if (typeof currentParam === "boolean") {
1571
1593
  option.capture = currentParam;
@@ -1574,7 +1596,7 @@
1574
1596
  option.capture = currentParam.capture;
1575
1597
  }
1576
1598
  return option;
1577
- }
1599
+ };
1578
1600
  const that = this;
1579
1601
  // eslint-disable-next-line prefer-rest-params
1580
1602
  const args = arguments;
@@ -1632,40 +1654,43 @@
1632
1654
  filter = option;
1633
1655
  }
1634
1656
  $elList.forEach(($elItem) => {
1635
- /* 获取对象上的事件 */
1657
+ // 获取对象上的事件
1636
1658
  const elementEvents = Reflect.get($elItem, GlobalData.domEventSymbol) || {};
1637
1659
  eventTypeList.forEach((eventName) => {
1638
1660
  const handlers = elementEvents[eventName] || [];
1639
- const filterHandler = typeof filter === "function" ? handlers.filter(filter) : handlers;
1640
- for (let index = 0; index < filterHandler.length; index++) {
1641
- const handler = filterHandler[index];
1661
+ // 过滤出需要删除的事件
1662
+ const handlersFiltered = typeof filter === "function" ? handlers.filter(filter) : handlers;
1663
+ for (let index = 0; index < handlersFiltered.length; index++) {
1664
+ const handler = handlersFiltered[index];
1665
+ // 过滤出的事件再根据下面的条件进行判断处理移除
1666
+ // 1. callback内存地址必须相同
1667
+ // 2. selector必须相同
1668
+ // 3. option.capture必须相同
1642
1669
  let flag = true;
1643
1670
  if (flag && listenerCallBack && handler.callback !== listenerCallBack) {
1644
- // callback不同
1645
1671
  flag = false;
1646
1672
  }
1647
1673
  if (flag && selectorList.length && Array.isArray(handler.selector)) {
1648
1674
  if (JSON.stringify(handler.selector) !== JSON.stringify(selectorList)) {
1649
- // 子元素选择器不同
1650
1675
  flag = false;
1651
1676
  }
1652
1677
  }
1653
1678
  if (flag &&
1654
1679
  typeof handler.option.capture === "boolean" &&
1655
1680
  listenerOption.capture !== handler.option.capture) {
1656
- // 事件的配置项不同
1657
1681
  flag = false;
1658
1682
  }
1659
1683
  if (flag) {
1660
1684
  $elItem.removeEventListener(eventName, handler.handlerCallBack, handler.option);
1661
- const findIndex = handlers.findIndex((item) => item === handler);
1662
- if (findIndex !== -1) {
1663
- handlers.splice(findIndex, 1);
1685
+ for (let i = handlers.length - 1; i >= 0; i--) {
1686
+ if (handlers[i] === handler) {
1687
+ handlers.splice(i, 1);
1688
+ }
1664
1689
  }
1665
1690
  }
1666
1691
  }
1667
1692
  if (handlers.length === 0) {
1668
- /* 如果没有任意的handler,那么删除该属性 */
1693
+ // 如果没有任意的handler,那么删除该属性
1669
1694
  CommonUtils.delete(elementEvents, eventType);
1670
1695
  }
1671
1696
  });
@@ -2426,11 +2451,11 @@
2426
2451
  * 阻止事件的默认行为发生,并阻止事件传播
2427
2452
  */
2428
2453
  const stopEvent = (event, onlyStopPropagation) => {
2454
+ // 停止事件的传播,阻止它继续向更上层的元素冒泡,事件将不会再传播给其他的元素
2455
+ event?.stopPropagation();
2456
+ // 阻止事件传播,并且还能阻止元素上的其他事件处理程序被触发
2457
+ event?.stopImmediatePropagation();
2429
2458
  if (typeof onlyStopPropagation === "boolean" && onlyStopPropagation) {
2430
- // 停止事件的传播,阻止它继续向更上层的元素冒泡,事件将不会再传播给其他的元素
2431
- event?.stopPropagation();
2432
- // 阻止事件传播,并且还能阻止元素上的其他事件处理程序被触发
2433
- event?.stopImmediatePropagation();
2434
2459
  return;
2435
2460
  }
2436
2461
  // 阻止事件的默认行为发生。例如,当点击一个链接时,浏览器会默认打开链接的URL,或者在输入框内输入文字