utils.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. export function automaRefDataStr(varName) {
  2. return `
  3. function findData(obj, path) {
  4. const paths = path.split('.');
  5. const isWhitespace = paths.length === 1 && !/\\S/.test(paths[0]);
  6. if (path.startsWith('$last') && Array.isArray(obj)) {
  7. paths[0] = obj.length - 1;
  8. }
  9. if (paths.length === 0 || isWhitespace) return obj;
  10. else if (paths.length === 1) return obj[paths[0]];
  11. let result = obj;
  12. for (let i = 0; i < paths.length; i++) {
  13. if (result[paths[i]] == undefined) {
  14. return undefined;
  15. } else {
  16. result = result[paths[i]];
  17. }
  18. }
  19. return result;
  20. }
  21. function automaRefData(keyword, path = '') {
  22. const data = ${varName}[keyword];
  23. if (!data) return;
  24. return findData(data, path);
  25. }
  26. `;
  27. }
  28. function messageTopFrame(windowCtx) {
  29. return new Promise((resolve) => {
  30. let timeout = null;
  31. let isResolved = false;
  32. const messageListener = ({ data }) => {
  33. if (data.type !== 'automa:the-frame-rect' || isResolved) return;
  34. clearTimeout(timeout);
  35. isResolved = true;
  36. windowCtx.removeEventListener('message', messageListener);
  37. resolve(data.frameRect);
  38. };
  39. timeout = setTimeout(() => {
  40. if (isResolved) return;
  41. isResolved = true;
  42. windowCtx.removeEventListener('message', messageListener);
  43. resolve(null);
  44. }, 5000);
  45. windowCtx.addEventListener('message', messageListener);
  46. windowCtx.top.postMessage('automa:get-frame', '*');
  47. });
  48. }
  49. export async function getElementPosition(element) {
  50. const elWindow = element.ownerDocument.defaultView;
  51. const isInFrame = elWindow !== window.top;
  52. const { width, height, x, y } = element.getBoundingClientRect();
  53. const position = {
  54. x: x + width / 2,
  55. y: y + height / 2,
  56. };
  57. if (!isInFrame) return position;
  58. try {
  59. const frameEl = elWindow.frameElement;
  60. let frameRect = null;
  61. if (frameEl) {
  62. frameRect = frameEl.getBoundingClientRect();
  63. } else {
  64. frameRect = await messageTopFrame(elWindow);
  65. if (!frameRect) throw new Error('Iframe not found');
  66. }
  67. position.x += frameRect.x;
  68. position.y += frameRect.y;
  69. return position;
  70. } catch (error) {
  71. console.error(error);
  72. return position;
  73. }
  74. }