DOMUtils

使用js重新对jQuery的部分函数进行了仿写

当前为 2024-04-15 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/465772/1360574/DOMUtils.js

  1. /// <reference path="./core.d.ts" />
  2. /**
  3. * 自己常用的元素工具类
  4. * @copyright GPL-3.0-only
  5. * @author WhiteSev
  6. **/
  7. (function (global, factory) {
  8. /**
  9. * 不使用define
  10. * typeof define === "function" && define.amd
  11. * define(factory)
  12. */
  13. if (typeof exports === "object" && typeof module !== "undefined") {
  14. /* 适用于NodeJs或typeScript */
  15. module.exports = factory();
  16. } else {
  17. global = typeof globalThis !== "undefined" ? globalThis : global || self;
  18. /* 适用于浏览器中,且this对象是window,如果this是其它,那么会在其它对象下注册(不可用)对象 */
  19. global.DOMUtils = factory(global.DOMUtils);
  20. }
  21. })(typeof window !== "undefined" ? window : this, function (AnotherDOMUtils) {
  22. const OriginPrototype = {
  23. Object: {
  24. defineProperty: Object.defineProperty,
  25. },
  26. };
  27. /** @type {DOMUtils} */
  28. const DOMUtils = {};
  29. DOMUtils.version = "2024-3-15";
  30.  
  31. /** 通用工具类 */
  32. const CommonDOMUtils = {
  33. /**
  34. * 判断元素是否已显示或已连接
  35. * @param {HTMLElement} element
  36. * @returns {boolean}
  37. */
  38. isShow(element) {
  39. return Boolean(element.getClientRects().length);
  40. },
  41. /**
  42. * 用于显示元素并获取它的高度宽度等其它属性
  43. * @param {HTMLElement} element
  44. * @returns {{recovery: Function}} - 恢复
  45. */
  46. showElement(element) {
  47. let dupNode = element.cloneNode(true);
  48. dupNode.setAttribute(
  49. "style",
  50. "visibility: hidden !important;display:block !important;"
  51. );
  52. document.documentElement.appendChild(dupNode);
  53. return {
  54. recovery() {
  55. dupNode.remove();
  56. },
  57. };
  58. },
  59. /**
  60. * 获取元素上的Float格式的属性px
  61. * @param {HTMLElement|CSSStyleDeclaration} element
  62. * @param {string} styleName style名
  63. * @return {number}
  64. */
  65. getStyleValue(element, styleName) {
  66. let view = null;
  67. let styles = null;
  68. if (element instanceof CSSStyleDeclaration) {
  69. /* 直接就获取了style属性 */
  70. styles = element;
  71. } else {
  72. view = element.ownerDocument.defaultView;
  73. if (!view || !view.opener) {
  74. view = window;
  75. }
  76. styles = view.getComputedStyle(element);
  77. }
  78. let value = parseFloat(styles[styleName]);
  79. if (isNaN(value)) {
  80. return 0;
  81. } else {
  82. return value;
  83. }
  84. },
  85. /**
  86. * 判断是否是window,例如window、self、globalThis
  87. * @param {any} target
  88. * @returns {boolean}
  89. */
  90. isWin(target) {
  91. if (!typeof target === "object") {
  92. return false;
  93. }
  94. if (target instanceof Node) {
  95. return false;
  96. }
  97. if (target === globalThis) {
  98. return true;
  99. }
  100. if (target === window) {
  101. return true;
  102. }
  103. if (target === self) {
  104. return true;
  105. }
  106. if (typeof unsafeWindow !== "undefined" && target === unsafeWindow) {
  107. return true;
  108. }
  109. if (target?.Math?.toString() !== "[object Math]") {
  110. return false;
  111. }
  112. return true;
  113. },
  114. };
  115.  
  116. /* 数据 */
  117. const DOMUtilsData = {
  118. /** .on绑定的事件 */
  119. SymbolEvents: Symbol(
  120. "events_" +
  121. (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
  122. ),
  123. };
  124.  
  125. DOMUtils.attr = function (element, attrName, attrValue) {
  126. if (typeof element === "string") {
  127. element = document.querySelector(element);
  128. }
  129. if (element == void 0) {
  130. return;
  131. }
  132. if (attrValue === void 0) {
  133. return element.getAttribute(attrName);
  134. } else {
  135. element.setAttribute(attrName, attrValue);
  136. }
  137. };
  138.  
  139. DOMUtils.createElement = function (tagName, property, attributes) {
  140. let tempElement = document.createElement(tagName);
  141. if (typeof property === "string") {
  142. tempElement.innerHTML = property;
  143. return tempElement;
  144. }
  145. if (property == void 0) {
  146. property = {};
  147. }
  148. if (attributes == void 0) {
  149. attributes = {};
  150. }
  151. Object.keys(property).forEach((key) => {
  152. let value = property[key];
  153. tempElement[key] = value;
  154. });
  155. Object.keys(attributes).forEach((key) => {
  156. let value = attributes[key];
  157. if (typeof value === "object") {
  158. /* object转字符串 */
  159. value = JSON.stringify(value);
  160. } else if (typeof value === "function") {
  161. /* function转字符串 */
  162. value = value.toString();
  163. }
  164. tempElement.setAttribute(key, value);
  165. });
  166. return tempElement;
  167. };
  168.  
  169. DOMUtils.css = function (element, property, value) {
  170. /**
  171. * 把纯数字没有px的加上
  172. */
  173. function handlePixe(propertyName, propertyValue) {
  174. let allowAddPixe = [
  175. "width",
  176. "height",
  177. "top",
  178. "left",
  179. "right",
  180. "bottom",
  181. "font-size",
  182. ];
  183. if (typeof propertyValue === "number") {
  184. propertyValue = propertyValue.toString();
  185. }
  186. if (
  187. typeof propertyValue === "string" &&
  188. allowAddPixe.includes(propertyName) &&
  189. propertyValue.match(/[0-9]$/gi)
  190. ) {
  191. propertyValue = propertyValue + "px";
  192. }
  193. return propertyValue;
  194. }
  195. if (typeof element === "string") {
  196. element = document.querySelector(element);
  197. }
  198. if (element == void 0) {
  199. return;
  200. }
  201. if (typeof property === "string") {
  202. if (value === void 0) {
  203. return getComputedStyle(element).getPropertyValue(property);
  204. } else {
  205. if (value === "string" && value.includes("!important")) {
  206. element.style.setProperty(property, value, "important");
  207. } else {
  208. value = handlePixe(property, value);
  209. element.style.setProperty(property, value);
  210. }
  211. }
  212. } else if (typeof property === "object") {
  213. for (let prop in property) {
  214. if (
  215. typeof property[prop] === "string" &&
  216. property[prop].includes("!important")
  217. ) {
  218. element.style.setProperty(prop, property[prop], "important");
  219. } else {
  220. property[prop] = handlePixe(prop, property[prop]);
  221. element.style.setProperty(prop, property[prop]);
  222. }
  223. }
  224. }
  225. };
  226.  
  227. DOMUtils.text = function (element, text) {
  228. if (typeof element === "string") {
  229. element = document.querySelector(element);
  230. }
  231. if (element == void 0) {
  232. return;
  233. }
  234. if (text === void 0) {
  235. return element.textContent || element.innerText;
  236. } else {
  237. if (text instanceof Node) {
  238. text = text.textContent || text.innerText;
  239. }
  240. if ("textContent" in element) {
  241. element.textContent = text;
  242. } else if ("innerText" in element) {
  243. element.innerText = text;
  244. }
  245. }
  246. };
  247.  
  248. DOMUtils.html = function (element, html) {
  249. if (typeof element === "string") {
  250. element = document.querySelector(element);
  251. }
  252. if (element == void 0) {
  253. return;
  254. }
  255. if (html == void 0) {
  256. return element.innerHTML;
  257. } else {
  258. if (html instanceof Node) {
  259. html = html.innerHTML;
  260. }
  261. if ("innerHTML" in element) {
  262. element.innerHTML = html;
  263. }
  264. }
  265. };
  266.  
  267. DOMUtils.click = function (
  268. element,
  269. handler,
  270. details,
  271. useDispatchToTriggerEvent = true
  272. ) {
  273. if (typeof element === "string") {
  274. element = document.querySelector(element);
  275. }
  276. if (element == void 0) {
  277. return;
  278. }
  279. if (handler === void 0) {
  280. DOMUtils.trigger(element, "click", details, useDispatchToTriggerEvent);
  281. } else {
  282. DOMUtils.on(element, "click", null, handler);
  283. }
  284. };
  285.  
  286. DOMUtils.blur = function (
  287. element,
  288. handler,
  289. details,
  290. useDispatchToTriggerEvent = true
  291. ) {
  292. if (typeof element === "string") {
  293. element = document.querySelector(element);
  294. }
  295. if (element == void 0) {
  296. return;
  297. }
  298. if (handler === void 0) {
  299. DOMUtils.trigger(element, "blur", details, useDispatchToTriggerEvent);
  300. } else {
  301. DOMUtils.on(element, "blur", null, handler);
  302. }
  303. };
  304.  
  305. DOMUtils.focus = function (
  306. element,
  307. handler,
  308. details,
  309. useDispatchToTriggerEvent = true
  310. ) {
  311. if (typeof element === "string") {
  312. element = document.querySelector(element);
  313. }
  314. if (element == void 0) {
  315. return;
  316. }
  317. if (handler === void 0) {
  318. DOMUtils.trigger(element, "focus", details, useDispatchToTriggerEvent);
  319. } else {
  320. DOMUtils.on(element, "focus", null, handler);
  321. }
  322. };
  323.  
  324. DOMUtils.getTransform = function (element, isShow = false) {
  325. let transform_left = 0;
  326. let transform_top = 0;
  327. if (!(isShow || (!isShow && CommonDOMUtils.isShow(element)))) {
  328. /* 未显示 */
  329. let { recovery } = CommonDOMUtils.showElement(element);
  330. let transformInfo = DOMUtils.getTransform(element, true);
  331. recovery();
  332. return transformInfo;
  333. }
  334. let elementTransform = getComputedStyle(element).transform;
  335. if (
  336. elementTransform !== "none" &&
  337. elementTransform != null &&
  338. elementTransform !== ""
  339. ) {
  340. let elementTransformSplit = elementTransform
  341. .match(/\((.+)\)/)[1]
  342. .split(",");
  343. transform_left = Math.abs(parseInt(elementTransformSplit[4]));
  344. transform_top = Math.abs(parseInt(elementTransformSplit[5]));
  345. }
  346. return {
  347. transformLeft: transform_left,
  348. transformTop: transform_top,
  349. };
  350. };
  351.  
  352. DOMUtils.val = function (element, value) {
  353. if (typeof element === "string") {
  354. element = document.querySelector(element);
  355. }
  356. if (element == void 0) {
  357. return;
  358. }
  359. if (value == void 0) {
  360. if (
  361. element.localName === "input" &&
  362. (element.type === "checkbox" || element.type === "radio")
  363. ) {
  364. return element.checked;
  365. } else {
  366. return element.value;
  367. }
  368. } else {
  369. if (
  370. element.localName === "input" &&
  371. (element.type === "checkbox" || element.type === "radio")
  372. ) {
  373. element.checked = !!value;
  374. } else {
  375. element.value = value;
  376. }
  377. }
  378. };
  379.  
  380. DOMUtils.prop = function (element, propName, propValue) {
  381. if (typeof element === "string") {
  382. element = document.querySelector(element);
  383. }
  384. if (element == void 0) {
  385. return;
  386. }
  387. if (propValue == void 0) {
  388. return element[propName];
  389. } else {
  390. element[propName] = propValue;
  391. }
  392. };
  393.  
  394. DOMUtils.removeAttr = function (element, attrName) {
  395. if (typeof element === "string") {
  396. element = document.querySelector(element);
  397. }
  398. if (element == void 0) {
  399. return;
  400. }
  401. element.removeAttribute(attrName);
  402. };
  403.  
  404. DOMUtils.removeClass = function (element, className) {
  405. if (typeof element === "string") {
  406. element = document.querySelector(element);
  407. }
  408. if (element == void 0) {
  409. return;
  410. }
  411. if (className == void 0) {
  412. return;
  413. }
  414. element.classList.remove(className);
  415. };
  416.  
  417. DOMUtils.removeProp = function (element, propName) {
  418. if (typeof element === "string") {
  419. element = document.querySelector(element);
  420. }
  421. if (element == void 0) {
  422. return;
  423. }
  424. delete element[propName];
  425. };
  426.  
  427. DOMUtils.replaceWith = function (element, newElement) {
  428. if (typeof element === "string") {
  429. element = document.querySelector(element);
  430. }
  431. if (element == void 0) {
  432. return;
  433. }
  434. if (typeof newElement === "string") {
  435. newElement = DOMUtils.parseHTML(newElement, false, false);
  436. }
  437. if (element instanceof NodeList || element instanceof Array) {
  438. element.forEach((item) => {
  439. DOMUtils.replaceWith(item, newElement);
  440. });
  441. } else {
  442. element.parentElement.replaceChild(newElement, element);
  443. }
  444. };
  445.  
  446. DOMUtils.addClass = function (element, className) {
  447. if (typeof element === "string") {
  448. element = document.querySelector(element);
  449. }
  450. if (element == void 0) {
  451. return;
  452. }
  453. element.classList.add(className);
  454. };
  455.  
  456. DOMUtils.append = function (element, content) {
  457. if (typeof element === "string") {
  458. element = document.querySelector(element);
  459. }
  460. if (element == void 0) {
  461. return;
  462. }
  463. if (typeof content === "string") {
  464. element.insertAdjacentHTML("beforeend", content);
  465. } else {
  466. element.appendChild(content);
  467. }
  468. };
  469.  
  470. DOMUtils.prepend = function (element, content) {
  471. if (typeof element === "string") {
  472. element = document.querySelector(element);
  473. }
  474. if (element == void 0) {
  475. return;
  476. }
  477. if (typeof content === "string") {
  478. element.insertAdjacentHTML("afterbegin", content);
  479. } else {
  480. element.insertBefore(content, element.firstChild);
  481. }
  482. };
  483.  
  484. DOMUtils.after = function (element, content) {
  485. if (typeof element === "string") {
  486. element = document.querySelector(element);
  487. }
  488. if (element == void 0) {
  489. return;
  490. }
  491. if (typeof content === "string") {
  492. element.insertAdjacentHTML("afterend", content);
  493. } else {
  494. element.parentElement.insertBefore(content, element.nextSibling);
  495. }
  496. };
  497.  
  498. DOMUtils.before = function (element, content) {
  499. if (typeof element === "string") {
  500. element = document.querySelector(element);
  501. }
  502. if (element == void 0) {
  503. return;
  504. }
  505. if (typeof content === "string") {
  506. element.insertAdjacentHTML("beforebegin", content);
  507. } else {
  508. element.parentElement.insertBefore(content, element);
  509. }
  510. };
  511.  
  512. DOMUtils.remove = function (target) {
  513. if (typeof target === "string") {
  514. target = document.querySelectorAll(target);
  515. }
  516. if (target == void 0) {
  517. return;
  518. }
  519. if (target instanceof NodeList || target instanceof Array) {
  520. for (const element of target) {
  521. DOMUtils.remove(element);
  522. }
  523. } else {
  524. target.remove();
  525. }
  526. };
  527.  
  528. DOMUtils.empty = function (element) {
  529. if (typeof element === "string") {
  530. element = document.querySelector(element);
  531. }
  532. if (element == void 0) {
  533. return;
  534. }
  535. element.innerHTML = "";
  536. };
  537.  
  538. DOMUtils.on = function (element, eventType, selector, callback, option) {
  539. /**
  540. * 获取option配置
  541. * @param {any[]} args
  542. * @param {number} startIndex
  543. * @param {AddEventListenerOptions} option
  544. * @returns {AddEventListenerOptions}
  545. */
  546. function getOption(args, startIndex, option) {
  547. if (typeof args[startIndex] === "boolean") {
  548. option.capture = args[startIndex];
  549. if (typeof args[startIndex + 1] === "boolean") {
  550. option.once = args[startIndex + 1];
  551. }
  552. if (typeof args[startIndex + 2] === "boolean") {
  553. option.passive = args[startIndex + 2];
  554. }
  555. } else if (
  556. typeof args[startIndex] === "object" &&
  557. ("capture" in args[startIndex] ||
  558. "once" in args[startIndex] ||
  559. "passive" in args[startIndex])
  560. ) {
  561. option.capture = args[startIndex].capture;
  562. option.once = args[startIndex].once;
  563. option.passive = args[startIndex].passive;
  564. }
  565. return option;
  566. }
  567.  
  568. let args = arguments;
  569. if (typeof element === "string") {
  570. element = document.querySelectorAll(element);
  571. }
  572. if (element == null) {
  573. return;
  574. }
  575. /**
  576. * @type {HTMLElement[]}
  577. */
  578. let elementList = [];
  579. if (element instanceof NodeList || Array.isArray(element)) {
  580. elementList = [...element];
  581. } else {
  582. elementList.push(element);
  583. }
  584. /**
  585. * @type {string[]}
  586. */
  587. let eventTypeList = [];
  588. if (Array.isArray(eventType)) {
  589. eventTypeList = eventTypeList.concat(eventType);
  590. } else if (typeof eventType === "string") {
  591. eventTypeList = eventTypeList.concat(eventType.split(" "));
  592. }
  593. /**
  594. * @type {?string}
  595. */
  596. let _selector_ = selector;
  597. /**
  598. * @type {(event:Event)=>{}}
  599. */
  600. let _callback_ = callback;
  601. /**
  602. * @type {AddEventListenerOptions}
  603. */
  604. let _option_ = {
  605. capture: false,
  606. once: false,
  607. passive: false,
  608. };
  609. if (typeof selector === "function") {
  610. /* 这是为没有selector的情况 */
  611. _selector_ = void 0;
  612. _callback_ = selector;
  613. _option_ = getOption(args, 3, _option_);
  614. } else {
  615. /* 这是存在selector的情况 */
  616. _option_ = getOption(args, 4, _option_);
  617. }
  618. /**
  619. * 如果是once,那么删除该监听和元素上的事件和监听
  620. */
  621. function checkOptionOnceToRemoveEventListener() {
  622. if (_option_.once) {
  623. DOMUtils.off(element, eventType, selector, callback, option);
  624. }
  625. }
  626. elementList.forEach((elementItem) => {
  627. function ownCallBack(event) {
  628. let target = event.target;
  629. if (_selector_) {
  630. /* 存在自定义子元素选择器 */
  631. let totalParent = CommonDOMUtils.isWin(elementItem)
  632. ? document.documentElement
  633. : elementItem;
  634. if (target.matches(_selector_)) {
  635. /* 当前目标可以被selector所匹配到 */
  636. _callback_.call(target, event);
  637. checkOptionOnceToRemoveEventListener();
  638. } else if (
  639. target.closest(_selector_) &&
  640. totalParent.contains(target.closest(_selector_))
  641. ) {
  642. /* 在上层与主元素之间寻找可以被selector所匹配到的 */
  643. let closestElement = target.closest(_selector_);
  644. /* event的target值不能直接修改 */
  645. OriginPrototype.Object.defineProperty(event, "target", {
  646. get() {
  647. return closestElement;
  648. },
  649. });
  650. _callback_.call(closestElement, event);
  651. checkOptionOnceToRemoveEventListener();
  652. }
  653. } else {
  654. _callback_.call(elementItem, event);
  655. checkOptionOnceToRemoveEventListener();
  656. }
  657. }
  658.  
  659. /* 遍历事件名设置元素事件 */
  660. eventTypeList.forEach((eventName) => {
  661. elementItem.addEventListener(eventName, ownCallBack, _option_);
  662.  
  663. if (_callback_ && _callback_.delegate) {
  664. elementItem.setAttribute("data-delegate", _selector_);
  665. }
  666. /* 获取对象上的事件 */
  667. let elementEvents = elementItem[DOMUtilsData.SymbolEvents] || {};
  668. /* 初始化对象上的xx事件 */
  669. elementEvents[eventName] = elementEvents[eventName] || [];
  670. elementEvents[eventName].push({
  671. selector: _selector_,
  672. option: _option_,
  673. callback: ownCallBack,
  674. originCallBack: _callback_,
  675. });
  676. /* 覆盖事件 */
  677. elementItem[DOMUtilsData.SymbolEvents] = elementEvents;
  678. });
  679. });
  680. };
  681.  
  682. DOMUtils.off = function (
  683. element,
  684. eventType,
  685. selector,
  686. callback,
  687. option,
  688. filter
  689. ) {
  690. /**
  691. * 获取option配置
  692. * @param {any[]} args
  693. * @param {number} startIndex
  694. * @param {EventListenerOptions} option
  695. * @returns {EventListenerOptions}
  696. */
  697. function getOption(args, startIndex, option) {
  698. if (typeof args[startIndex] === "boolean") {
  699. option.capture = args[startIndex];
  700. } else if (
  701. typeof args[startIndex] === "object" &&
  702. "capture" in args[startIndex]
  703. ) {
  704. option.capture = args[startIndex].capture;
  705. }
  706. return option;
  707. }
  708.  
  709. let args = arguments;
  710. if (typeof element === "string") {
  711. element = document.querySelectorAll(element);
  712. }
  713. if (element == null) {
  714. return;
  715. }
  716. /**
  717. * @type {HTMLElement[]}
  718. */
  719. let elementList = [];
  720. if (element instanceof NodeList || Array.isArray(element)) {
  721. elementList = [...element];
  722. } else {
  723. elementList.push(element);
  724. }
  725. /**
  726. * @type {string[]}
  727. */
  728. let eventTypeList = [];
  729. if (Array.isArray(eventType)) {
  730. eventTypeList = eventTypeList.concat(eventType);
  731. } else if (typeof eventType === "string") {
  732. eventTypeList = eventTypeList.concat(eventType.split(" "));
  733. }
  734. /**
  735. * 子元素选择器
  736. * @type {?string}
  737. */
  738. let _selector_ = selector;
  739. /**
  740. * 事件的回调函数
  741. * @type {(event:Event)=>{}}
  742. */
  743. let _callback_ = callback;
  744.  
  745. /**
  746. * 事件的配置
  747. * @type {EventListenerOptions}
  748. */
  749. let _option_ = {
  750. capture: false,
  751. };
  752. if (typeof selector === "function") {
  753. /* 这是为没有selector的情况 */
  754. _selector_ = void 0;
  755. _callback_ = selector;
  756. _option_ = getOption(args, 3, _option_);
  757. } else {
  758. _option_ = getOption(args, 4, _option_);
  759. }
  760. elementList.forEach((elementItem) => {
  761. /* 获取对象上的事件 */
  762. let elementEvents = elementItem[DOMUtilsData.SymbolEvents] || {};
  763. eventTypeList.forEach((eventName) => {
  764. /** @type {DOMUtilsEventListenerOptionsAttribute[]} */
  765. let handlers = elementEvents[eventName] || [];
  766. if (typeof filter === "function") {
  767. handlers = handlers.filter(filter);
  768. }
  769. for (let index = 0; index < handlers.length; index++) {
  770. let handler = handlers[index];
  771. let flag = false;
  772. if (!_selector_ || handler.selector === _selector_) {
  773. /* selector不为空,进行selector判断 */
  774. flag = true;
  775. }
  776. if (
  777. !_callback_ ||
  778. handler.callback === _callback_ ||
  779. handler.originCallBack === _callback_
  780. ) {
  781. /* callback不为空,进行callback判断 */
  782. flag = true;
  783. }
  784.  
  785. if (flag) {
  786. elementItem.removeEventListener(
  787. eventName,
  788. handler.callback,
  789. _option_
  790. );
  791. handlers.splice(index--, 1);
  792. }
  793. }
  794. if (handlers.length === 0) {
  795. /* 如果没有任意的handler,那么删除该属性 */
  796. delete elementEvents[eventType];
  797. }
  798. });
  799. elementItem[DOMUtilsData.SymbolEvents] = elementEvents;
  800. });
  801. };
  802.  
  803. DOMUtils.offAll = function (element, eventType) {
  804. if (typeof element === "string") {
  805. element = document.querySelectorAll(element);
  806. }
  807. if (element == null) {
  808. return;
  809. }
  810. /**
  811. * @type {HTMLElement[]}
  812. */
  813. let elementList = [];
  814. if (element instanceof NodeList || Array.isArray(element)) {
  815. elementList = [...element];
  816. } else {
  817. elementList.push(element);
  818. }
  819. /**
  820. * @type {string[]}
  821. */
  822. let eventTypeList = [];
  823. if (Array.isArray(eventType)) {
  824. eventTypeList = eventTypeList.concat(eventType);
  825. } else if (typeof eventType === "string") {
  826. eventTypeList = eventTypeList.concat(eventType.split(" "));
  827. }
  828. elementList.forEach((elementItem) => {
  829. Object.getOwnPropertySymbols(elementItem).forEach((symbolEvents) => {
  830. if (!symbolEvents.toString().startsWith("Symbol(events_")) {
  831. return;
  832. }
  833. let elementEvents = elementItem[symbolEvents] || {};
  834. let iterEventNameList = eventTypeList.length
  835. ? eventTypeList
  836. : Object.keys(elementEvents);
  837. iterEventNameList.forEach((eventName) => {
  838. let handlers = elementEvents[eventName];
  839. if (!handlers) {
  840. return;
  841. }
  842. for (const handler of handlers) {
  843. elementItem.removeEventListener(eventName, handler.callback, {
  844. capture: handler["option"]["capture"],
  845. });
  846. }
  847. delete elementItem[symbolEvents][eventName];
  848. });
  849. });
  850. });
  851. };
  852.  
  853. DOMUtils.trigger = function (
  854. element,
  855. eventType,
  856. details,
  857. useDispatchToTriggerEvent = true
  858. ) {
  859. if (typeof element === "string") {
  860. element = document.querySelector(element);
  861. }
  862. if (element == null) {
  863. return;
  864. }
  865. let elementList = [];
  866. if (element instanceof NodeList || Array.isArray(element)) {
  867. elementList = [...element];
  868. } else {
  869. elementList = [element];
  870. }
  871. let eventTypeList = [];
  872. if (Array.isArray(eventType)) {
  873. eventTypeList = eventType;
  874. } else if (typeof eventType === "string") {
  875. eventTypeList = eventType.split(" ");
  876. }
  877.  
  878. elementList.forEach((elementItem) => {
  879. /* 获取对象上的事件 */
  880. let events = elementItem[DOMUtilsData.SymbolEvents] || {};
  881. eventTypeList.forEach((_eventType_) => {
  882. let event = null;
  883. if (details && details instanceof Event) {
  884. event = details;
  885. } else {
  886. event = new Event(_eventType_);
  887. if (details) {
  888. Object.keys(details).forEach((keyName) => {
  889. event[keyName] = details[keyName];
  890. });
  891. }
  892. }
  893. if (useDispatchToTriggerEvent == false && _eventType_ in events) {
  894. events[_eventType_].forEach((eventsItem) => {
  895. eventsItem.callback(event);
  896. });
  897. } else {
  898. elementItem.dispatchEvent(event);
  899. }
  900. });
  901. });
  902. };
  903.  
  904. DOMUtils.offset = function (element) {
  905. if (typeof element === "string") {
  906. element = document.querySelector(element);
  907. }
  908. if (element == void 0) {
  909. return;
  910. }
  911. let rect = element.getBoundingClientRect();
  912. return {
  913. top: rect.top + globalThis.scrollY,
  914. left: rect.left + globalThis.scrollX,
  915. };
  916. };
  917.  
  918. DOMUtils.width = function (element, isShow = false) {
  919. if (CommonDOMUtils.isWin(element)) {
  920. return window.document.documentElement.clientWidth;
  921. }
  922. if (typeof element === "string") {
  923. element = document.querySelector(element);
  924. }
  925. if (element == void 0) {
  926. return;
  927. }
  928. if (element.nodeType === 9) {
  929. /* 文档节点 */
  930. return Math.max(
  931. element.body.scrollWidth,
  932. element.documentElement.scrollWidth,
  933. element.body.offsetWidth,
  934. element.documentElement.offsetWidth,
  935. element.documentElement.clientWidth
  936. );
  937. }
  938. if (isShow || (!isShow && CommonDOMUtils.isShow(element))) {
  939. /* 已显示 */
  940. /* 不从style中获取对应的宽度,因为可能使用了class定义了width !important */
  941.  
  942. /* 如果element.style.width为空 则从css里面获取是否定义了width信息如果定义了 则读取css里面定义的宽度width */
  943. if (parseFloat(CommonDOMUtils.getStyleValue(element, "width")) > 0) {
  944. return parseFloat(CommonDOMUtils.getStyleValue(element, "width"));
  945. }
  946.  
  947. /* 如果从css里获取到的值不是大于0 可能是auto 则通过offsetWidth来进行计算 */
  948. if (element.offsetWidth > 0) {
  949. let borderLeftWidth = CommonDOMUtils.getStyleValue(
  950. element,
  951. "borderLeftWidth"
  952. );
  953. let borderRightWidth = CommonDOMUtils.getStyleValue(
  954. element,
  955. "borderRightWidth"
  956. );
  957. let paddingLeft = CommonDOMUtils.getStyleValue(element, "paddingLeft");
  958. let paddingRight = CommonDOMUtils.getStyleValue(
  959. element,
  960. "paddingRight"
  961. );
  962. let backHeight =
  963. parseFloat(element.offsetWidth) -
  964. parseFloat(borderLeftWidth) -
  965. parseFloat(borderRightWidth) -
  966. parseFloat(paddingLeft) -
  967. parseFloat(paddingRight);
  968. return parseFloat(backHeight);
  969. }
  970. return 0;
  971. } else {
  972. /* 未显示 */
  973. let { recovery } = CommonDOMUtils.showElement(element);
  974. let width = DOMUtils.width(element, true);
  975. recovery();
  976. return width;
  977. }
  978. };
  979.  
  980. DOMUtils.height = function (element, isShow = false) {
  981. if (CommonDOMUtils.isWin(element)) {
  982. return window.document.documentElement.clientHeight;
  983. }
  984. if (typeof element === "string") {
  985. element = document.querySelector(element);
  986. }
  987. if (element == void 0) {
  988. return;
  989. }
  990. if (element.nodeType === 9) {
  991. /* 文档节点 */
  992. return Math.max(
  993. element.body.scrollHeight,
  994. element.documentElement.scrollHeight,
  995. element.body.offsetHeight,
  996. element.documentElement.offsetHeight,
  997. element.documentElement.clientHeight
  998. );
  999. }
  1000. if (isShow || (!isShow && CommonDOMUtils.isShow(element))) {
  1001. /* 已显示 */
  1002. /* 从style中获取对应的高度,因为可能使用了class定义了width !important */
  1003. /* 如果element.style.height为空 则从css里面获取是否定义了height信息如果定义了 则读取css里面定义的高度height */
  1004. if (parseFloat(CommonDOMUtils.getStyleValue(element, "height")) > 0) {
  1005. return parseFloat(CommonDOMUtils.getStyleValue(element, "height"));
  1006. }
  1007.  
  1008. /* 如果从css里获取到的值不是大于0 可能是auto 则通过offsetHeight来进行计算 */
  1009. if (element.offsetHeight > 0) {
  1010. let borderTopWidth = CommonDOMUtils.getStyleValue(
  1011. element,
  1012. "borderTopWidth"
  1013. );
  1014. let borderBottomWidth = CommonDOMUtils.getStyleValue(
  1015. element,
  1016. "borderBottomWidth"
  1017. );
  1018. let paddingTop = CommonDOMUtils.getStyleValue(element, "paddingTop");
  1019. let paddingBottom = CommonDOMUtils.getStyleValue(
  1020. element,
  1021. "paddingBottom"
  1022. );
  1023. let backHeight =
  1024. parseFloat(element.offsetHeight) -
  1025. parseFloat(borderTopWidth) -
  1026. parseFloat(borderBottomWidth) -
  1027. parseFloat(paddingTop) -
  1028. parseFloat(paddingBottom);
  1029. return parseFloat(backHeight);
  1030. }
  1031. return 0;
  1032. } else {
  1033. /* 未显示 */
  1034. let { recovery } = CommonDOMUtils.showElement(element);
  1035. let height = DOMUtils.height(element, true);
  1036. recovery();
  1037. return height;
  1038. }
  1039. };
  1040.  
  1041. DOMUtils.outerWidth = function (element, isShow = false) {
  1042. if (CommonDOMUtils.isWin(element)) {
  1043. return window.innerWidth;
  1044. }
  1045. if (typeof element === "string") {
  1046. element = document.querySelector(element);
  1047. }
  1048. if (element == void 0) {
  1049. return;
  1050. }
  1051. if (isShow || (!isShow && CommonDOMUtils.isShow(element))) {
  1052. let style = getComputedStyle(element, null);
  1053. let marginLeft = CommonDOMUtils.getStyleValue(style, "marginLeft");
  1054. let marginRight = CommonDOMUtils.getStyleValue(style, "marginRight");
  1055. return element.offsetWidth + marginLeft + marginRight;
  1056. } else {
  1057. let { recovery } = CommonDOMUtils.showElement(element);
  1058. let outerWidth = DOMUtils.outerWidth(element, true);
  1059. recovery();
  1060. return outerWidth;
  1061. }
  1062. };
  1063.  
  1064. DOMUtils.outerHeight = function (element, isShow = false) {
  1065. if (CommonDOMUtils.isWin(element)) {
  1066. return window.innerHeight;
  1067. }
  1068. if (typeof element === "string") {
  1069. element = document.querySelector(element);
  1070. }
  1071. if (element == void 0) {
  1072. return;
  1073. }
  1074. if (isShow || (!isShow && CommonDOMUtils.isShow(element))) {
  1075. let style = getComputedStyle(element, null);
  1076. let marginTop = CommonDOMUtils.getStyleValue(style, "marginTop");
  1077. let marginBottom = CommonDOMUtils.getStyleValue(style, "marginBottom");
  1078. return element.offsetHeight + marginTop + marginBottom;
  1079. } else {
  1080. let { recovery } = CommonDOMUtils.showElement(element);
  1081. let outerHeight = DOMUtils.outerHeight(element, true);
  1082. recovery();
  1083. return outerHeight;
  1084. }
  1085. };
  1086.  
  1087. DOMUtils.ready = function (callback) {
  1088. function completed() {
  1089. document.removeEventListener("DOMContentLoaded", completed);
  1090. globalThis.removeEventListener("load", completed);
  1091. callback();
  1092. }
  1093. if (
  1094. document.readyState === "complete" ||
  1095. (document.readyState !== "loading" && !document.documentElement.doScroll)
  1096. ) {
  1097. setTimeout(callback);
  1098. } else {
  1099. /* 监听DOMContentLoaded事件 */
  1100. document.addEventListener("DOMContentLoaded", completed);
  1101. /* 监听load事件 */
  1102. globalThis.addEventListener("load", completed);
  1103. }
  1104. };
  1105.  
  1106. DOMUtils.animate = function (
  1107. element,
  1108. styles,
  1109. duration = 1000,
  1110. callback = null
  1111. ) {
  1112. if (typeof element === "string") {
  1113. element = document.querySelector(element);
  1114. }
  1115. if (element == void 0) {
  1116. return;
  1117. }
  1118. if (typeof duration !== "number" || duration <= 0) {
  1119. throw new TypeError("duration must be a positive number");
  1120. }
  1121. if (typeof callback !== "function" && callback !== void 0) {
  1122. throw new TypeError("callback must be a function or null");
  1123. }
  1124. if (typeof styles !== "object" || styles === void 0) {
  1125. throw new TypeError("styles must be an object");
  1126. }
  1127. if (Object.keys(styles).length === 0) {
  1128. throw new Error("styles must contain at least one property");
  1129. }
  1130. let start = performance.now();
  1131. let from = {};
  1132. let to = {};
  1133. for (let prop in styles) {
  1134. from[prop] = element.style[prop] || getComputedStyle(element)[prop];
  1135. to[prop] = styles[prop];
  1136. }
  1137. let timer = setInterval(function () {
  1138. let timePassed = performance.now() - start;
  1139. let progress = timePassed / duration;
  1140. if (progress > 1) {
  1141. progress = 1;
  1142. }
  1143. for (let prop in styles) {
  1144. element.style[prop] =
  1145. from[prop] + (to[prop] - from[prop]) * progress + "px";
  1146. }
  1147. if (progress === 1) {
  1148. clearInterval(timer);
  1149. if (callback) {
  1150. callback();
  1151. }
  1152. }
  1153. }, 10);
  1154. };
  1155.  
  1156. DOMUtils.wrap = function (element, wrapperHTML) {
  1157. if (typeof element === "string") {
  1158. element = document.querySelector(element);
  1159. }
  1160. if (element == void 0) {
  1161. return;
  1162. }
  1163. // 创建一个新的div元素,并将wrapperHTML作为其innerHTML
  1164. let wrapper = document.createElement("div");
  1165. wrapper.innerHTML = wrapperHTML;
  1166.  
  1167. wrapper = wrapper.firstChild;
  1168. // 将要包裹的元素插入目标元素前面
  1169. element.parentElement.insertBefore(wrapper, element);
  1170.  
  1171. // 将要包裹的元素移动到wrapper中
  1172. wrapper.appendChild(element);
  1173. };
  1174.  
  1175. DOMUtils.prev = function (element) {
  1176. if (typeof element === "string") {
  1177. element = document.querySelector(element);
  1178. }
  1179. if (element == void 0) {
  1180. return;
  1181. }
  1182. return element.previousElementSibling;
  1183. };
  1184.  
  1185. DOMUtils.next = function (element) {
  1186. if (typeof element === "string") {
  1187. element = document.querySelector(element);
  1188. }
  1189. if (element == void 0) {
  1190. return;
  1191. }
  1192. return element.nextElementSibling;
  1193. };
  1194.  
  1195. DOMUtils.noConflict = function () {
  1196. if (window.DOMUtils) {
  1197. delete window.DOMUtils;
  1198. }
  1199. if (AnotherDOMUtils) {
  1200. window.DOMUtils = AnotherDOMUtils;
  1201. }
  1202. return DOMUtils;
  1203. };
  1204.  
  1205. DOMUtils.siblings = function (element) {
  1206. if (typeof element === "string") {
  1207. element = document.querySelector(element);
  1208. }
  1209. if (element == void 0) {
  1210. return;
  1211. }
  1212. return Array.from(element.parentElement.children).filter(
  1213. (child) => child !== element
  1214. );
  1215. };
  1216.  
  1217. DOMUtils.parent = function (element) {
  1218. if (typeof element === "string") {
  1219. element = document.querySelector(element);
  1220. }
  1221. if (element == void 0) {
  1222. return;
  1223. }
  1224. if (element instanceof NodeList || element instanceof Array) {
  1225. let resultArray = [];
  1226. element.forEach((item) => {
  1227. resultArray = resultArray.concat(this.parent(item));
  1228. });
  1229. return resultArray;
  1230. } else {
  1231. return element.parentElement;
  1232. }
  1233. };
  1234.  
  1235. DOMUtils.parseHTML = function (html, useParser = false, isComplete = false) {
  1236. function parseHTMLByDOMParser() {
  1237. let parser = new DOMParser();
  1238. if (isComplete) {
  1239. return parser.parseFromString(html, "text/html");
  1240. } else {
  1241. return parser.parseFromString(html, "text/html").body.firstChild;
  1242. }
  1243. }
  1244. function parseHTMLByCreateDom() {
  1245. let tempDIV = document.createElement("div");
  1246. tempDIV.innerHTML = html;
  1247. if (isComplete) {
  1248. return tempDIV;
  1249. } else {
  1250. return tempDIV.firstChild;
  1251. }
  1252. }
  1253. if (useParser) {
  1254. return parseHTMLByDOMParser();
  1255. } else {
  1256. return parseHTMLByCreateDom();
  1257. }
  1258. };
  1259.  
  1260. DOMUtils.hover = function (element, handler, option) {
  1261. if (typeof element === "string") {
  1262. element = document.querySelector(element);
  1263. }
  1264. if (element == void 0) {
  1265. return;
  1266. }
  1267. DOMUtils.on(element, "mouseenter", null, handler, option);
  1268. DOMUtils.on(element, "mouseleave", null, handler, option);
  1269. };
  1270.  
  1271. DOMUtils.show = function (target) {
  1272. if (target == void 0) {
  1273. return;
  1274. }
  1275. if (typeof target === "string") {
  1276. target = document.querySelectorAll(target);
  1277. }
  1278. if (target instanceof NodeList || target instanceof Array) {
  1279. for (const element of target) {
  1280. DOMUtils.show(element);
  1281. }
  1282. } else {
  1283. target.style.display = "";
  1284. }
  1285. };
  1286.  
  1287. DOMUtils.hide = function (target) {
  1288. if (target == void 0) {
  1289. return;
  1290. }
  1291. if (typeof target === "string") {
  1292. target = document.querySelectorAll(target);
  1293. }
  1294. if (target instanceof NodeList || target instanceof Array) {
  1295. for (const element of target) {
  1296. DOMUtils.hide(element);
  1297. }
  1298. } else {
  1299. target.style.display = "none";
  1300. }
  1301. };
  1302.  
  1303. DOMUtils.keyup = function (target, handler, option) {
  1304. if (target == void 0) {
  1305. return;
  1306. }
  1307. if (typeof target === "string") {
  1308. target = document.querySelector(target);
  1309. }
  1310. DOMUtils.on(target, "keyup", null, handler, option);
  1311. };
  1312.  
  1313. DOMUtils.keydown = function (target, handler, option) {
  1314. if (target == void 0) {
  1315. return;
  1316. }
  1317. if (typeof target === "string") {
  1318. target = document.querySelector(target);
  1319. }
  1320. DOMUtils.on(target, "keydown", null, handler, option);
  1321. };
  1322.  
  1323. DOMUtils.keypress = function (target, handler, option) {
  1324. if (target == void 0) {
  1325. return;
  1326. }
  1327. if (typeof target === "string") {
  1328. target = document.querySelector(target);
  1329. }
  1330. DOMUtils.on(target, "keypress", null, handler, option);
  1331. };
  1332.  
  1333. DOMUtils.fadeIn = function (element, duration = 400, callback) {
  1334. if (element == void 0) {
  1335. return;
  1336. }
  1337. if (typeof element === "string") {
  1338. element = document.querySelector(element);
  1339. }
  1340. element.style.opacity = 0;
  1341. element.style.display = "";
  1342. let start = null;
  1343. let timer = null;
  1344. function step(timestamp) {
  1345. if (!start) start = timestamp;
  1346. let progress = timestamp - start;
  1347. element.style.opacity = Math.min(progress / duration, 1);
  1348. if (progress < duration) {
  1349. window.requestAnimationFrame(step);
  1350. } else {
  1351. if (callback && typeof callback === "function") {
  1352. callback();
  1353. }
  1354. window.cancelAnimationFrame(timer);
  1355. }
  1356. }
  1357. timer = window.requestAnimationFrame(step);
  1358. };
  1359.  
  1360. DOMUtils.fadeOut = function (element, duration = 400, callback) {
  1361. if (element == void 0) {
  1362. return;
  1363. }
  1364. if (typeof element === "string") {
  1365. element = document.querySelector(element);
  1366. }
  1367. element.style.opacity = 1;
  1368. let start = null;
  1369. let timer = null;
  1370. function step(timestamp) {
  1371. if (!start) start = timestamp;
  1372. let progress = timestamp - start;
  1373. element.style.opacity = Math.max(1 - progress / duration, 0);
  1374. if (progress < duration) {
  1375. window.requestAnimationFrame(step);
  1376. } else {
  1377. element.style.display = "none";
  1378. if (typeof callback === "function") {
  1379. callback();
  1380. }
  1381. window.cancelAnimationFrame(timer);
  1382. }
  1383. }
  1384. timer = window.requestAnimationFrame(step);
  1385. };
  1386.  
  1387. DOMUtils.toggle = function (element) {
  1388. if (typeof element === "string") {
  1389. element = document.querySelector(element);
  1390. }
  1391. if (element == void 0) {
  1392. return;
  1393. }
  1394. if (getComputedStyle(element).getPropertyValue("display") === "none") {
  1395. DOMUtils.show(element);
  1396. } else {
  1397. DOMUtils.hide(element);
  1398. }
  1399. };
  1400. return DOMUtils;
  1401. });

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址