utils.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. export function elementSelectorInstance() {
  2. const rootElementExist = document.querySelector(
  3. '#app-container.automa-element-selector'
  4. );
  5. if (rootElementExist) {
  6. rootElementExist.style.display = 'block';
  7. return true;
  8. }
  9. return false;
  10. }
  11. export function getElementRect(target, withAttributes) {
  12. if (!target) return {};
  13. const { x, y, height, width } = target.getBoundingClientRect();
  14. const result = {
  15. width: width + 4,
  16. height: height + 4,
  17. x: x - 2,
  18. y: y - 2,
  19. };
  20. if (withAttributes) {
  21. const attributes = {};
  22. Array.from(target.attributes).forEach(({ name, value }) => {
  23. if (name === 'automa-el-list') return;
  24. attributes[name] = value;
  25. });
  26. result.attributes = attributes;
  27. result.tagName = target.tagName;
  28. }
  29. return result;
  30. }
  31. export function getElementPath(el, root = document.documentElement) {
  32. const path = [el];
  33. /* eslint-disable-next-line */
  34. while ((el = el.parentNode) && !el.isEqualNode(root)) {
  35. path.push(el);
  36. }
  37. return path;
  38. }
  39. export function generateXPath(element, root = document.body) {
  40. if (!element) return null;
  41. if (element.id !== '') return `id("${element.id}")`;
  42. if (element === root) return `//${element.tagName}`;
  43. let ix = 0;
  44. const siblings = element.parentNode.childNodes;
  45. for (let index = 0; index < siblings.length; index += 1) {
  46. const sibling = siblings[index];
  47. if (sibling === element) {
  48. return `${generateXPath(element.parentNode)}/${element.tagName}[${
  49. ix + 1
  50. }]`;
  51. }
  52. if (sibling.nodeType === 1 && sibling.tagName === element.tagName) {
  53. ix += 1;
  54. }
  55. }
  56. return null;
  57. }
  58. export function automaRefDataStr(varName) {
  59. return `
  60. function findData(obj, path) {
  61. const paths = path.split('.');
  62. const isWhitespace = paths.length === 1 && !/\\S/.test(paths[0]);
  63. if (path.startsWith('$last') && Array.isArray(obj)) {
  64. paths[0] = obj.length - 1;
  65. }
  66. if (paths.length === 0 || isWhitespace) return obj;
  67. else if (paths.length === 1) return obj[paths[0]];
  68. let result = obj;
  69. for (let i = 0; i < paths.length; i++) {
  70. if (result[paths[i]] == undefined) {
  71. return undefined;
  72. } else {
  73. result = result[paths[i]];
  74. }
  75. }
  76. return result;
  77. }
  78. function automaRefData(keyword, path = '') {
  79. const data = ${varName}[keyword];
  80. if (!data) return;
  81. return findData(data, path);
  82. }
  83. `;
  84. }
  85. function messageTopFrame(windowCtx) {
  86. return new Promise((resolve) => {
  87. let timeout = null;
  88. const messageListener = ({ data }) => {
  89. if (data.type !== 'automa:the-frame-rect') return;
  90. clearTimeout(timeout);
  91. windowCtx.removeEventListener('message', messageListener);
  92. resolve(data.frameRect);
  93. };
  94. timeout = setTimeout(() => {
  95. windowCtx.removeEventListener('message', messageListener);
  96. resolve(null);
  97. }, 5000);
  98. windowCtx.addEventListener('message', messageListener);
  99. windowCtx.top.postMessage({ type: 'automa:get-frame' }, '*');
  100. });
  101. }
  102. export async function getElementPosition(element) {
  103. const elWindow = element.ownerDocument.defaultView;
  104. const isInFrame = elWindow !== window.top;
  105. const { width, height, x, y } = element.getBoundingClientRect();
  106. const position = {
  107. x: x + width / 2,
  108. y: y + height / 2,
  109. };
  110. if (!isInFrame) return position;
  111. try {
  112. const frameEl = elWindow.frameElement;
  113. let frameRect = null;
  114. if (frameEl) {
  115. frameRect = frameEl.getBoundingClientRect();
  116. } else {
  117. frameRect = await messageTopFrame(elWindow);
  118. if (!frameRect) throw new Error('Iframe not found');
  119. }
  120. position.x += frameRect.x;
  121. position.y += frameRect.y;
  122. return position;
  123. } catch (error) {
  124. console.error(error);
  125. return position;
  126. }
  127. }