blocks-handler.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /* eslint-disable consistent-return, no-param-reassign */
  2. import simulateEvent from '@/utils/simulate-event';
  3. import handleFormElement from '@/utils/handle-form-element';
  4. function markElement(el, { id, data }) {
  5. if (data.markEl) {
  6. el.setAttribute(`block--${id}`, '');
  7. }
  8. }
  9. function handleElement({ data, id }, callback, errCallback) {
  10. if (!data || !data.selector) return null;
  11. try {
  12. const blockIdAttr = `block--${id}`;
  13. const selector = data.markEl
  14. ? `${data.selector.trim()}:not([${blockIdAttr}])`
  15. : data.selector;
  16. const element = data.multiple
  17. ? document.querySelectorAll(selector)
  18. : document.querySelector(selector);
  19. if (typeof callback === 'boolean' && callback) return element;
  20. if (data.multiple) {
  21. element.forEach((el) => {
  22. markElement(el, { id, data });
  23. callback(el);
  24. });
  25. } else if (element) {
  26. markElement(element, { id, data });
  27. callback(element);
  28. } else if (errCallback) {
  29. errCallback();
  30. }
  31. } catch (error) {
  32. console.error(error);
  33. }
  34. }
  35. export function switchTo(block) {
  36. return new Promise((resolve) => {
  37. handleElement(
  38. block,
  39. (element) => {
  40. if (element.tagName !== 'IFRAME') {
  41. resolve('');
  42. return;
  43. }
  44. resolve({ url: element.src });
  45. },
  46. () => {
  47. resolve('');
  48. }
  49. );
  50. });
  51. }
  52. export function eventClick(block) {
  53. return new Promise((resolve) => {
  54. handleElement(block, (element) => {
  55. element.click();
  56. });
  57. resolve('');
  58. });
  59. }
  60. export function getText(block) {
  61. return new Promise((resolve) => {
  62. let regex;
  63. const { data } = block;
  64. const textResult = [];
  65. if (data.regex) {
  66. regex = new RegExp(data.regex, data.regexExp.join(''));
  67. }
  68. handleElement(block, (element) => {
  69. let text = element.innerText;
  70. if (regex) text = text.match(regex).join(' ');
  71. textResult.push(text);
  72. });
  73. resolve(textResult);
  74. });
  75. }
  76. function incScrollPos(element, data, vertical = true) {
  77. let currentPos = vertical ? element.scrollTop : element.scrollLeft;
  78. if (data.incY) {
  79. currentPos += data.scrollY;
  80. } else if (data.incX) {
  81. currentPos += data.scrollX;
  82. }
  83. return currentPos;
  84. }
  85. const automaScript = `
  86. function automaNextBlock(data) {
  87. window.dispatchEvent(new CustomEvent('__automa-next-block__', { detail: data }));
  88. }
  89. function automaResetTimeout() {
  90. window.dispatchEvent(new CustomEvent('__automa-reset-timeout__'));
  91. }
  92. `;
  93. export function javascriptCode(block) {
  94. return new Promise((resolve) => {
  95. const isScriptExists = document.getElementById('automa-custom-js');
  96. const scriptAttr = `block--${block.id}`;
  97. if (isScriptExists && isScriptExists.hasAttribute(scriptAttr)) {
  98. resolve('');
  99. return;
  100. }
  101. const script = document.createElement('script');
  102. let timeout;
  103. script.setAttribute(scriptAttr, '');
  104. script.id = 'automa-custom-js';
  105. script.innerHTML = `${automaScript} ${block.data.code}`;
  106. window.addEventListener('__automa-next-block__', ({ detail }) => {
  107. clearTimeout(timeout);
  108. script.remove();
  109. resolve(detail || {});
  110. });
  111. window.addEventListener('__automa-reset-timeout__', () => {
  112. clearTimeout(timeout);
  113. timeout = setTimeout(() => {
  114. script.remove();
  115. resolve('');
  116. }, block.data.timeout);
  117. });
  118. document.body.appendChild(script);
  119. timeout = setTimeout(() => {
  120. script.remove();
  121. resolve('');
  122. }, block.data.timeout);
  123. });
  124. }
  125. export function elementScroll(block) {
  126. return new Promise((resolve) => {
  127. const { data } = block;
  128. const behavior = data.smooth ? 'smooth' : 'auto';
  129. handleElement(block, (element) => {
  130. if (data.scrollIntoView) {
  131. element.scrollIntoView({ behavior, block: 'center' });
  132. } else {
  133. element.scroll({
  134. behavior,
  135. top: data.incY ? incScrollPos(element, data) : data.scrollY,
  136. left: data.incX ? incScrollPos(element, data, false) : data.scrollX,
  137. });
  138. }
  139. });
  140. window.dispatchEvent(new Event('scroll'));
  141. resolve('');
  142. });
  143. }
  144. export function attributeValue(block) {
  145. return new Promise((resolve) => {
  146. const result = [];
  147. handleElement(block, (element) => {
  148. const value = element.getAttribute(block.data.attributeName);
  149. result.push(value);
  150. });
  151. resolve(result);
  152. });
  153. }
  154. export function forms(block) {
  155. return new Promise((resolve) => {
  156. const { data } = block;
  157. const elements = handleElement(block, true);
  158. if (data.multiple) {
  159. const promises = Array.from(elements).map((element) => {
  160. return new Promise((eventResolve) => {
  161. markElement(element, block);
  162. handleFormElement(element, data, eventResolve);
  163. });
  164. });
  165. Promise.allSettled(promises).then(() => {
  166. resolve('');
  167. });
  168. } else if (elements) {
  169. markElement(elements, block);
  170. handleFormElement(elements, data, resolve);
  171. } else {
  172. resolve('');
  173. }
  174. });
  175. }
  176. export function triggerEvent(block) {
  177. return new Promise((resolve) => {
  178. const { data } = block;
  179. handleElement(block, (element) => {
  180. simulateEvent(element, data.eventName, data.eventParams);
  181. });
  182. resolve(data.eventName);
  183. });
  184. }
  185. export function link(block) {
  186. return new Promise((resolve) => {
  187. const element = document.querySelector(block.data.selector);
  188. if (!element) {
  189. resolve('');
  190. return;
  191. }
  192. const url = element.href;
  193. if (url) window.location.href = url;
  194. resolve(url);
  195. });
  196. }
  197. export function elementExists({ data }) {
  198. return new Promise((resolve) => {
  199. let trying = 0;
  200. function checkElement() {
  201. if (trying >= (data.tryCount || 1)) {
  202. resolve(false);
  203. return;
  204. }
  205. const element = document.querySelector(data.selector);
  206. if (element) {
  207. resolve(true);
  208. } else {
  209. trying += 1;
  210. setTimeout(checkElement, data.timeout || 500);
  211. }
  212. }
  213. checkElement();
  214. });
  215. }