@whitesev/domutils 1.8.9 → 1.9.1

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.amd.js CHANGED
@@ -1,6 +1,6 @@
1
1
  define((function () { 'use strict';
2
2
 
3
- const version = "1.8.9";
3
+ const version = "1.9.1";
4
4
 
5
5
  class WindowApi {
6
6
  /** 默认的配置 */
@@ -311,9 +311,10 @@ define((function () { 'use strict';
311
311
  */
312
312
  matches($el, selector) {
313
313
  selector = selector.trim();
314
- if ($el == null) {
314
+ if ($el == null)
315
+ return false;
316
+ if ($el instanceof Document)
315
317
  return false;
316
- }
317
318
  if (selector.match(/[^\s]{1}:empty$/gi)) {
318
319
  // empty 语法
319
320
  selector = selector.replace(/:empty$/gi, "");
@@ -357,6 +358,10 @@ define((function () { 'use strict';
357
358
  }
358
359
  closest($el, selector) {
359
360
  selector = selector.trim();
361
+ if ($el == null)
362
+ return null;
363
+ if ($el instanceof Document)
364
+ return null;
360
365
  if (selector.match(/[^\s]{1}:empty$/gi)) {
361
366
  // empty 语法
362
367
  selector = selector.replace(/:empty$/gi, "");
@@ -1441,17 +1446,17 @@ define((function () { 'use strict';
1441
1446
  /**
1442
1447
  * 如果是once,那么删除该监听和元素上的事件和监听
1443
1448
  */
1444
- function checkOptionOnceToRemoveEventListener() {
1449
+ const checkOptionOnceToRemoveEventListener = () => {
1445
1450
  if (listenerOption.once) {
1446
1451
  that.off(element, eventType, selector, callback, option);
1447
1452
  }
1448
- }
1453
+ };
1449
1454
  $elList.forEach((elementItem) => {
1450
1455
  /**
1451
1456
  * 事件回调
1452
1457
  * @param event
1453
1458
  */
1454
- function domUtilsEventCallBack(event) {
1459
+ const handlerCallBack = function (event) {
1455
1460
  if (selectorList.length) {
1456
1461
  /* 存在子元素选择器 */
1457
1462
  // 这时候的this和target都是子元素选择器的元素
@@ -1499,10 +1504,10 @@ define((function () { 'use strict';
1499
1504
  listenerCallBack.call(elementItem, event);
1500
1505
  checkOptionOnceToRemoveEventListener();
1501
1506
  }
1502
- }
1507
+ };
1503
1508
  /* 遍历事件名设置元素事件 */
1504
1509
  eventTypeList.forEach((eventName) => {
1505
- elementItem.addEventListener(eventName, domUtilsEventCallBack, listenerOption);
1510
+ elementItem.addEventListener(eventName, handlerCallBack, listenerOption);
1506
1511
  /* 获取对象上的事件 */
1507
1512
  const elementEvents = Reflect.get(elementItem, GlobalData.domEventSymbol) || {};
1508
1513
  /* 初始化对象上的xx事件 */
@@ -1510,8 +1515,8 @@ define((function () { 'use strict';
1510
1515
  elementEvents[eventName].push({
1511
1516
  selector: selectorList,
1512
1517
  option: listenerOption,
1513
- callback: domUtilsEventCallBack,
1514
- originCallBack: listenerCallBack,
1518
+ handlerCallBack: handlerCallBack,
1519
+ callback: listenerCallBack,
1515
1520
  });
1516
1521
  /* 覆盖事件 */
1517
1522
  Reflect.set(elementItem, GlobalData.domEventSymbol, elementEvents);
@@ -1527,11 +1532,11 @@ define((function () { 'use strict';
1527
1532
  },
1528
1533
  /**
1529
1534
  * 主动触发事件
1530
- * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
1531
- * @param useDispatchToEmit 是否使用dispatchEvent来触发事件,默认true,如果为false,则直接调用callback,但是这种会让使用了selectorTarget的没有值
1535
+ * @param extraDetails 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
1536
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true,如果为false,则直接调用callback,但是这种会让使用了$selector的没有值
1532
1537
  */
1533
- emit: (details, useDispatchToEmit) => {
1534
- that.emit($elList, eventTypeList, details, useDispatchToEmit);
1538
+ emit: (extraDetails, useDispatchToTriggerEvent) => {
1539
+ that.emit($elList, eventTypeList, extraDetails, useDispatchToTriggerEvent);
1535
1540
  },
1536
1541
  };
1537
1542
  }
@@ -1627,7 +1632,7 @@ define((function () { 'use strict';
1627
1632
  for (let index = 0; index < filterHandler.length; index++) {
1628
1633
  const handler = filterHandler[index];
1629
1634
  let flag = true;
1630
- if (flag && listenerCallBack && handler.originCallBack !== listenerCallBack) {
1635
+ if (flag && listenerCallBack && handler.callback !== listenerCallBack) {
1631
1636
  // callback不同
1632
1637
  flag = false;
1633
1638
  }
@@ -1644,7 +1649,7 @@ define((function () { 'use strict';
1644
1649
  flag = false;
1645
1650
  }
1646
1651
  if (flag || isRemoveAll) {
1647
- $elItem.removeEventListener(eventName, handler.callback, handler.option);
1652
+ $elItem.removeEventListener(eventName, handler.handlerCallBack, handler.option);
1648
1653
  const findIndex = handlers.findIndex((item) => item === handler);
1649
1654
  if (findIndex !== -1) {
1650
1655
  handlers.splice(findIndex, 1);
@@ -1700,8 +1705,8 @@ define((function () { 'use strict';
1700
1705
  return;
1701
1706
  }
1702
1707
  for (const handler of handlers) {
1703
- $elItem.removeEventListener(eventName, handler.callback, {
1704
- capture: handler["option"]["capture"],
1708
+ $elItem.removeEventListener(eventName, handler.handlerCallBack, {
1709
+ capture: handler.option.capture,
1705
1710
  });
1706
1711
  }
1707
1712
  const events = Reflect.get($elItem, symbolItem);
@@ -1715,36 +1720,6 @@ define((function () { 'use strict';
1715
1720
  // 异步回调
1716
1721
  let resolve = void 0;
1717
1722
  const that = this;
1718
- /**
1719
- * 检测文档是否加载完毕
1720
- */
1721
- function checkDOMReadyState() {
1722
- try {
1723
- if (that.windowApi.document.readyState === "complete" ||
1724
- (that.windowApi.document.readyState !== "loading" &&
1725
- !that.windowApi.document.documentElement.doScroll)) {
1726
- return true;
1727
- }
1728
- else {
1729
- return false;
1730
- }
1731
- }
1732
- catch {
1733
- return false;
1734
- }
1735
- }
1736
- /**
1737
- * 成功加载完毕后触发的回调函数
1738
- */
1739
- function completed() {
1740
- removeDomReadyListener();
1741
- if (typeof callback === "function") {
1742
- callback();
1743
- }
1744
- if (typeof resolve === "function") {
1745
- resolve();
1746
- }
1747
- }
1748
1723
  /**
1749
1724
  * 监听目标
1750
1725
  */
@@ -1752,59 +1727,97 @@ define((function () { 'use strict';
1752
1727
  {
1753
1728
  target: that.windowApi.document,
1754
1729
  eventType: "DOMContentLoaded",
1755
- callback: completed,
1730
+ callback: () => {
1731
+ ReadyChecker.completed();
1732
+ },
1756
1733
  },
1757
1734
  {
1758
1735
  target: that.windowApi.window,
1759
1736
  eventType: "load",
1760
- callback: completed,
1737
+ callback: () => {
1738
+ ReadyChecker.completed();
1739
+ },
1761
1740
  },
1762
1741
  ];
1763
- /**
1764
- * 添加监听
1765
- */
1766
- function addDomReadyListener() {
1767
- for (const item of listenTargetList) {
1768
- that.on(item.target, item.eventType, item.callback);
1769
- }
1770
- }
1771
- /**
1772
- * 移除监听
1773
- */
1774
- function removeDomReadyListener() {
1775
- for (const item of listenTargetList) {
1776
- that.off(item.target, item.eventType, item.callback);
1777
- }
1778
- }
1779
- /**
1780
- * 执行检查
1781
- */
1782
- function check() {
1783
- if (checkDOMReadyState()) {
1784
- /* 检查document状态 */
1785
- setTimeout(completed, 0);
1786
- }
1787
- else {
1788
- /* 添加监听 */
1789
- addDomReadyListener();
1790
- }
1791
- }
1792
- if (args.length === 0) {
1793
- return new Promise((__resolve__) => {
1794
- resolve = __resolve__;
1795
- check();
1796
- });
1797
- }
1798
- else {
1799
- check();
1800
- }
1742
+ const ReadyChecker = {
1743
+ init() {
1744
+ if (args.length === 0) {
1745
+ return new Promise((__resolve__) => {
1746
+ resolve = __resolve__;
1747
+ ReadyChecker.check();
1748
+ });
1749
+ }
1750
+ else {
1751
+ ReadyChecker.check();
1752
+ }
1753
+ },
1754
+ check() {
1755
+ if (ReadyChecker.isReady()) {
1756
+ /* 检查document状态 */
1757
+ setTimeout(() => {
1758
+ ReadyChecker.completed();
1759
+ }, 0);
1760
+ }
1761
+ else {
1762
+ /* 添加监听 */
1763
+ ReadyChecker.onCompleted();
1764
+ }
1765
+ },
1766
+ /**
1767
+ * 检测文档是否加载完毕
1768
+ */
1769
+ isReady() {
1770
+ try {
1771
+ if (that.windowApi.document.readyState === "complete" ||
1772
+ // @ts-expect-error
1773
+ (that.windowApi.document.readyState !== "loading" && !that.windowApi.document.documentElement.doScroll)) {
1774
+ return true;
1775
+ }
1776
+ else {
1777
+ return false;
1778
+ }
1779
+ }
1780
+ catch {
1781
+ return false;
1782
+ }
1783
+ },
1784
+ /**
1785
+ * 成功加载完毕后触发的回调函数
1786
+ */
1787
+ completed() {
1788
+ ReadyChecker.offCompleted();
1789
+ if (typeof callback === "function") {
1790
+ callback();
1791
+ }
1792
+ if (typeof resolve === "function") {
1793
+ resolve();
1794
+ }
1795
+ },
1796
+ /**
1797
+ * 添加监听
1798
+ */
1799
+ onCompleted() {
1800
+ for (const item of listenTargetList) {
1801
+ that.on(item.target, item.eventType, item.callback);
1802
+ }
1803
+ },
1804
+ /**
1805
+ * 移除监听
1806
+ */
1807
+ offCompleted() {
1808
+ for (const item of listenTargetList) {
1809
+ that.off(item.target, item.eventType, item.callback);
1810
+ }
1811
+ },
1812
+ };
1813
+ return ReadyChecker.init();
1801
1814
  }
1802
1815
  /**
1803
1816
  * 主动触发事件
1804
1817
  * @param element 需要触发的元素|元素数组|window
1805
1818
  * @param eventType 需要触发的事件
1806
- * @param details 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
1807
- * @param useDispatchToEmit 是否使用dispatchEvent来触发事件,默认true,如果为false,则直接调用callback,但是这种会让使用了selectorTarget的没有值
1819
+ * @param extraDetails 赋予触发的Event的额外属性,如果是Event类型,那么将自动代替默认new的Event对象
1820
+ * @param useDispatchToTriggerEvent 是否使用dispatchEvent来触发事件,默认true,如果为false,则直接调用通过.on监听的callback(),但是这种只有一个入参,如果使用$selector则没有值
1808
1821
  * @example
1809
1822
  * // 触发元素a.xx的click事件
1810
1823
  * DOMUtils.emit(document.querySelector("a.xx"),"click")
@@ -1813,7 +1826,7 @@ define((function () { 'use strict';
1813
1826
  * DOMUtils.emit(document.querySelector("a.xx"),"click tap hover")
1814
1827
  * DOMUtils.emit("a.xx",["click","tap","hover"])
1815
1828
  */
1816
- emit(element, eventType, details, useDispatchToEmit = true) {
1829
+ emit(element, eventType, extraDetails, useDispatchToTriggerEvent = true) {
1817
1830
  const that = this;
1818
1831
  if (typeof element === "string") {
1819
1832
  element = that.selectorAll(element);
@@ -1840,25 +1853,25 @@ define((function () { 'use strict';
1840
1853
  const elementEvents = Reflect.get($elItem, GlobalData.domEventSymbol) || {};
1841
1854
  eventTypeList.forEach((eventTypeItem) => {
1842
1855
  let event = null;
1843
- if (details && details instanceof Event) {
1844
- event = details;
1856
+ if (extraDetails && extraDetails instanceof Event) {
1857
+ event = extraDetails;
1845
1858
  }
1846
1859
  else {
1847
1860
  // 构造事件
1848
1861
  event = new Event(eventTypeItem);
1849
- if (details) {
1850
- const detailKeys = Object.keys(details);
1862
+ if (typeof extraDetails === "object" && extraDetails != null) {
1863
+ const detailKeys = Object.keys(extraDetails);
1851
1864
  detailKeys.forEach((keyName) => {
1852
- const value = Reflect.get(details, keyName);
1865
+ const value = Reflect.get(extraDetails, keyName);
1853
1866
  // 在event上添加属性
1854
1867
  Reflect.set(event, keyName, value);
1855
1868
  });
1856
1869
  }
1857
1870
  }
1858
- if (useDispatchToEmit == false && eventTypeItem in elementEvents) {
1871
+ if (useDispatchToTriggerEvent == false && eventTypeItem in elementEvents) {
1859
1872
  // 直接调用监听的事件
1860
1873
  elementEvents[eventTypeItem].forEach((eventsItem) => {
1861
- eventsItem.callback(event);
1874
+ eventsItem.handlerCallBack(event);
1862
1875
  });
1863
1876
  }
1864
1877
  else {
@@ -2344,14 +2357,14 @@ define((function () { 'use strict';
2344
2357
  isDoubleClick: true,
2345
2358
  });
2346
2359
  }, options);
2347
- const touchEndListener = this.on($el, "pointerup", selector, (evt, selectorTarget) => {
2360
+ const touchEndListener = this.on($el, "pointerup", selector, (evt, $selector) => {
2348
2361
  this.preventEvent(evt);
2349
2362
  if (evt.pointerType === "touch") {
2350
2363
  isMobileTouch = true;
2351
2364
  }
2352
2365
  clearTimeout(timer);
2353
2366
  timer = void 0;
2354
- if (isDoubleClick && $click === selectorTarget) {
2367
+ if (isDoubleClick && $click === $selector) {
2355
2368
  isDoubleClick = false;
2356
2369
  $click = null;
2357
2370
  /* 判定为双击 */
@@ -2368,7 +2381,7 @@ define((function () { 'use strict';
2368
2381
  });
2369
2382
  }, checkClickTime);
2370
2383
  isDoubleClick = true;
2371
- $click = selectorTarget;
2384
+ $click = $selector;
2372
2385
  }
2373
2386
  }, options);
2374
2387
  return {
@@ -3572,6 +3585,41 @@ define((function () { 'use strict';
3572
3585
  return parseHTMLByCreateDom();
3573
3586
  }
3574
3587
  }
3588
+ /**
3589
+ * 将字符串转为Element元素数组
3590
+ * @param html
3591
+ * @param useParser 是否使用DOMParser来生成元素,有些时候通过DOMParser生成的元素有点问题
3592
+ * + true 使用DOMPraser来转换字符串
3593
+ * + false (默认)创建一个div,里面放入字符串,然后提取childNodes
3594
+ * @example
3595
+ * // 将字符串转为Element元素数组
3596
+ * DOMUtils.toElements("<a href='xxxx'></a>")
3597
+ * > [<a href="xxxx"></a>]
3598
+ * @example
3599
+ * // 使用DOMParser将字符串转为Element元素数组
3600
+ * DOMUtils.toElements("<a href='xxxx'></a>",true)
3601
+ * > [<a href="xxxx"></a>]
3602
+ */
3603
+ toElements(html, useParser = false) {
3604
+ const that = this;
3605
+ // 去除html前后的空格
3606
+ html = html.trim();
3607
+ function parseHTMLByDOMParser() {
3608
+ const parser = new DOMParser();
3609
+ return Array.from(parser.parseFromString(html, "text/html").body.childNodes);
3610
+ }
3611
+ function parseHTMLByCreateDom() {
3612
+ const $el = that.windowApi.document.createElement("div");
3613
+ that.html($el, html);
3614
+ return Array.from($el.childNodes);
3615
+ }
3616
+ if (useParser) {
3617
+ return parseHTMLByDOMParser();
3618
+ }
3619
+ else {
3620
+ return parseHTMLByCreateDom();
3621
+ }
3622
+ }
3575
3623
  /**
3576
3624
  * 序列化表单元素
3577
3625
  * @param $form 表单元素
@@ -3580,26 +3628,29 @@ define((function () { 'use strict';
3580
3628
  * > xxx=xxx&aaa=
3581
3629
  */
3582
3630
  serialize($form) {
3631
+ if (!($form instanceof HTMLFormElement)) {
3632
+ throw new TypeError("DOMUtils.serialize 参数必须是HTMLFormElement");
3633
+ }
3583
3634
  const elements = $form.elements;
3584
3635
  const serializedArray = [];
3585
- for (let i = 0; i < elements.length; i++) {
3586
- const element = elements[i];
3587
- if (element.name &&
3588
- !element.disabled &&
3589
- (element.checked ||
3590
- ["text", "hidden", "password", "textarea", "select-one", "select-multiple"].includes(element.type))) {
3591
- if (element.type === "select-multiple") {
3592
- for (let j = 0; j < element.options.length; j++) {
3593
- if (element.options[j].selected) {
3636
+ for (let index = 0; index < elements.length; index++) {
3637
+ const $el = elements[index];
3638
+ if ($el.name &&
3639
+ !$el.disabled &&
3640
+ ($el.checked ||
3641
+ ["text", "hidden", "password", "textarea", "select-one", "select-multiple"].includes($el.type))) {
3642
+ if ($el.type === "select-multiple") {
3643
+ for (let j = 0; j < $el.options.length; j++) {
3644
+ if ($el.options[j].selected) {
3594
3645
  serializedArray.push({
3595
- name: element.name,
3596
- value: element.options[j].value,
3646
+ name: $el.name,
3647
+ value: $el.options[j].value,
3597
3648
  });
3598
3649
  }
3599
3650
  }
3600
3651
  }
3601
3652
  else {
3602
- serializedArray.push({ name: element.name, value: element.value });
3653
+ serializedArray.push({ name: $el.name, value: $el.value });
3603
3654
  }
3604
3655
  }
3605
3656
  }