listSelector.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { finder } from '@medv/finder';
  2. /* eslint-disable no-cond-assign */
  3. export function getAllSiblings(el, selector) {
  4. const siblings = [el];
  5. const validateElement = (element) => {
  6. const isValidSelector = selector ? element.querySelector(selector) : true;
  7. const isSameTag = el.tagName === element.tagName;
  8. return isValidSelector && isSameTag;
  9. };
  10. let nextSibling = el;
  11. let prevSibling = el;
  12. let elementIndex = 1;
  13. while ((prevSibling = prevSibling?.previousElementSibling)) {
  14. if (validateElement(prevSibling)) {
  15. elementIndex += 1;
  16. siblings.unshift(prevSibling);
  17. }
  18. }
  19. while ((nextSibling = nextSibling?.nextElementSibling)) {
  20. if (validateElement(nextSibling)) {
  21. siblings.push(nextSibling);
  22. }
  23. }
  24. return {
  25. elements: siblings,
  26. index: elementIndex,
  27. };
  28. }
  29. export function getCssPath(el, root = document.body) {
  30. if (!el) return null;
  31. const path = [];
  32. while (el.nodeType === Node.ELEMENT_NODE && !el.isSameNode(root)) {
  33. let selector = el.nodeName.toLowerCase();
  34. if (el.id) {
  35. selector += `#${el.id}`;
  36. path.unshift(selector);
  37. } else {
  38. let nth = 1;
  39. let sib = el;
  40. while ((sib = sib.previousElementSibling)) {
  41. if (sib.nodeName.toLowerCase() === selector) nth += 1;
  42. }
  43. if (nth !== 1) selector += `:nth-of-type(${nth})`;
  44. path.unshift(selector);
  45. }
  46. el = el.parentNode;
  47. }
  48. return path.join(' > ');
  49. }
  50. export function getElementList(el, maxDepth = 50, paths = []) {
  51. if (maxDepth === 0 || !el || el.tagName === 'BODY') return null;
  52. let selector = el.tagName.toLowerCase();
  53. const { elements, index } = getAllSiblings(el, paths.join(' > '));
  54. let siblings = elements;
  55. if (index !== 1) selector += `:nth-of-type(${index})`;
  56. paths.unshift(selector);
  57. if (siblings.length === 1) {
  58. siblings = getElementList(el.parentElement, maxDepth - 1, paths);
  59. }
  60. return siblings;
  61. }
  62. export default function (target, frameElement) {
  63. if (!target) return [];
  64. const automaListEl = target.closest('[automa-el-list]');
  65. let documentCtx = document;
  66. if (frameElement) {
  67. documentCtx = frameElement.contentDocument;
  68. }
  69. if (automaListEl) {
  70. if (target.hasAttribute('automa-el-list')) return [];
  71. const childSelector = finder(target, {
  72. root: automaListEl,
  73. idName: () => false,
  74. });
  75. const elements = documentCtx.querySelectorAll(
  76. `[automa-el-list] ${childSelector}`
  77. );
  78. return Array.from(elements);
  79. }
  80. return getElementList(target) || [target];
  81. }