Greasy Fork is available in English.

自动点击菜单

自动点击菜单,支持按ID、类名、文本、位置自动点击,可设定执行次数

  1. // ==UserScript==
  2. // @name 自动点击菜单
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.47.1
  5. // @description 自动点击菜单,支持按ID、类名、文本、位置自动点击,可设定执行次数
  6. // @author YuoHira
  7. // @license MIT
  8. // @match *://*/*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=github.io
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // ==/UserScript==
  13.  
  14. class AutoClickMenu {
  15. constructor() {
  16. this.currentUrl = window.location.origin;
  17. this.autoClickEnabled = GM_getValue(`${this.currentUrl}_autoClickEnabled`, false);
  18. this.lastUpdateTime = new Map();
  19. this.menuItems = [];
  20. this.init();
  21. }
  22.  
  23. init() {
  24. window.onload = () => {
  25. this.createStyles();
  26. this.toggleButton = new ToggleButton(this).createElement();
  27. this.menuContainer = this.createMenuContainer();
  28. this.addMenuTitle(this.menuContainer);
  29. this.saveButton = this.addButton(this.menuContainer, '保存', 'yuohira-button', (e) => {
  30. e.stopPropagation();
  31. this.saveData();
  32. });
  33. this.addButtonElement = this.addButton(this.menuContainer, '+', 'yuohira-button', (e) => {
  34. e.stopPropagation();
  35. this.addInputField();
  36. });
  37. this.toggleAutoClickButton = this.addButton(this.menuContainer, this.autoClickEnabled ? '暂停' : '开始', 'yuohira-button', (e) => {
  38. e.stopPropagation();
  39. this.autoClickEnabled = !this.autoClickEnabled;
  40. this.toggleAutoClickButton.innerText = this.autoClickEnabled ? '暂停' : '开始';
  41. GM_setValue(`${this.currentUrl}_autoClickEnabled`, this.autoClickEnabled);
  42. });
  43. this.inputContainer = document.createElement('div');
  44. this.menuContainer.appendChild(this.inputContainer);
  45. this.loadSavedData();
  46. this.applyAutoClick();
  47. };
  48. }
  49.  
  50. createStyles() {
  51. const style = document.createElement('style');
  52. style.innerHTML = `
  53. .yuohira-button {
  54. background-color: #6cb2e8;
  55. border: 1px solid #0099cc;
  56. color: #fff;
  57. border-radius: 5px;
  58. padding: 5px 10px;
  59. cursor: pointer;
  60. font-size: 14px;
  61. margin: 5px;
  62. box-shadow: 0 0 10px #6cb2e8;
  63. }
  64. .yuohira-button:hover {
  65. background-color: #0099cc;
  66. }
  67. .yuohira-container {
  68. background-color: #b2ebf2;
  69. border: 1px solid #0099cc;
  70. border-radius: 10px;
  71. padding: 10px;
  72. box-shadow: 0 0 20px #6cb2e8;
  73. display: flex;
  74. flex-direction: column;
  75. align-items: center;
  76. }
  77. .yuohira-title {
  78. color: #0099cc;
  79. font-family: 'Courier New', Courier, monospace;
  80. margin-bottom: 10px;
  81. }
  82. .yuohira-input {
  83. border: 1px solid #0099cc;
  84. border-radius: 5px;
  85. padding: 5px;
  86. margin: 5px;
  87. background-color: #a0d3e0;
  88. color: #0099cc;
  89. }
  90. .yuohira-toggle-button {
  91. background-color: #6cb2e8;
  92. border: 1px solid #0099cc;
  93. color: #fff;
  94. border-radius: 50%;
  95. padding: 5px;
  96. cursor: pointer;
  97. font-size: 14px;
  98. width: 30px;
  99. height: 30px;
  100. position: fixed;
  101. top: 10px;
  102. right: 10px;
  103. z-index: 10001;
  104. opacity: 0.5;
  105. transition: opacity 0.3s;
  106. box-shadow: 0 0 10px #6cb2e8;
  107. }
  108. .yuohira-toggle-button:hover {
  109. opacity: 1;
  110. }
  111. .yuohira-input-wrapper {
  112. display: flex;
  113. align-items: center;
  114. margin-bottom: 5px;
  115. position: relative;
  116. padding-bottom: 18px;
  117. }
  118. .yuohira-progress-bar {
  119. height: 5px;
  120. position: absolute;
  121. bottom: 0;
  122. left: 0;
  123. background-color: #6cb2e8;
  124. clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
  125. border-radius: 2.5px;
  126. }
  127. .yuohira-warning {
  128. color: #e74c3c;
  129. font-size: 12px;
  130. position: absolute;
  131. left: 0;
  132. bottom: -13px;
  133. width: 100%;
  134. text-align: left;
  135. z-index: 2;
  136. pointer-events: none;
  137. }
  138. .yuohira-crosshair-overlay {
  139. position: fixed;
  140. top: 0; left: 0; right: 0; bottom: 0;
  141. z-index: 99999;
  142. pointer-events: auto;
  143. background: rgba(0,0,0,0.05);
  144. }
  145. .yuohira-crosshair-line {
  146. position: absolute;
  147. background: #e74c3c;
  148. z-index: 999999;
  149. }
  150. .yuohira-crosshair-label {
  151. position: absolute;
  152. background: #222;
  153. color: #fff;
  154. font-size: 12px;
  155. padding: 2px 6px;
  156. border-radius: 3px;
  157. z-index: 999999;
  158. pointer-events: none;
  159. transform: translateY(-150%);
  160. }
  161. `;
  162. document.head.appendChild(style);
  163. }
  164.  
  165. createMenuContainer() {
  166. const menuContainer = document.createElement('div');
  167. menuContainer.className = 'yuohira-container';
  168. menuContainer.style.position = 'fixed';
  169. menuContainer.style.top = '10px';
  170. menuContainer.style.right = '10px';
  171. menuContainer.style.zIndex = '10000';
  172. menuContainer.style.display = 'none';
  173. document.body.appendChild(menuContainer);
  174. menuContainer.addEventListener('click', (e) => {
  175. e.stopPropagation();
  176. });
  177. return menuContainer;
  178. }
  179.  
  180. addMenuTitle(container) {
  181. const menuTitle = document.createElement('h3');
  182. menuTitle.innerText = '自动点击菜单';
  183. menuTitle.className = 'yuohira-title';
  184. container.appendChild(menuTitle);
  185. }
  186.  
  187. addButton(container, text, className, onClick) {
  188. const button = document.createElement('button');
  189. button.innerText = text;
  190. button.className = className;
  191. button.addEventListener('click', onClick);
  192. container.appendChild(button);
  193. return button;
  194. }
  195.  
  196. loadSavedData() {
  197. const savedData = GM_getValue(this.currentUrl, []);
  198. savedData.forEach(item => {
  199. this.addInputField(item.type, item.value, item.enabled, item.interval, item.count);
  200. });
  201. }
  202.  
  203. saveData() {
  204. const data = this.menuItems.map(item => item.getData());
  205. GM_setValue(this.currentUrl, data);
  206. }
  207.  
  208. addInputField(type = 'id', value = '', enabled = false, interval = 1000, count = -1) {
  209. const menuItem = new MenuItem(type, value, enabled, interval, this, count);
  210. this.menuItems.push(menuItem);
  211. this.inputContainer.appendChild(menuItem.createElement());
  212. }
  213.  
  214. applyAutoClick() {
  215. const autoClick = () => {
  216. if (this.autoClickEnabled && this.menuItems.some(item => item.isEnabled())) {
  217. const currentTime = Date.now();
  218. this.menuItems.forEach(item => item.autoClick(currentTime, this.lastUpdateTime));
  219. }
  220. requestAnimationFrame(autoClick);
  221. };
  222. requestAnimationFrame(autoClick);
  223. }
  224. }
  225.  
  226. class MenuItem {
  227. constructor(type, value, enabled, interval, menu, count = -1) {
  228. this.type = type;
  229. this.value = value;
  230. this.enabled = enabled;
  231. this.interval = interval;
  232. this.menu = menu;
  233. this.count = (typeof count === "number" ? count : -1);
  234. }
  235.  
  236. createElement() {
  237. const MIN_INTERVAL = 1;
  238. const inputWrapper = document.createElement('div');
  239. inputWrapper.className = 'yuohira-input-wrapper';
  240.  
  241. this.select = document.createElement('select');
  242. const optionId = document.createElement('option');
  243. optionId.value = 'id';
  244. optionId.innerText = 'ID';
  245. const optionClass = document.createElement('option');
  246. optionClass.value = 'class';
  247. optionClass.innerText = '类名';
  248. const optionText = document.createElement('option');
  249. optionText.value = 'text';
  250. optionText.innerText = '文本';
  251. const optionPosition = document.createElement('option');
  252. optionPosition.value = 'position';
  253. optionPosition.innerText = '位置';
  254. this.select.appendChild(optionId);
  255. this.select.appendChild(optionClass);
  256. this.select.appendChild(optionText);
  257. this.select.appendChild(optionPosition);
  258. this.select.value = this.type;
  259. this.select.className = 'yuohira-input';
  260. inputWrapper.appendChild(this.select);
  261.  
  262. this.input = document.createElement('input');
  263. this.input.type = 'text';
  264. this.input.value = this.value;
  265. this.input.className = 'yuohira-input';
  266. this.input.placeholder = 'ID/类名/文本/坐标';
  267. inputWrapper.appendChild(this.input);
  268.  
  269. this.selectButton = document.createElement('button');
  270. this.selectButton.innerText = '选取';
  271. this.selectButton.className = 'yuohira-button';
  272. this.selectButton.addEventListener('click', (e) => this.selectElement(e));
  273. inputWrapper.appendChild(this.selectButton);
  274.  
  275. this.select.addEventListener('change', () => {
  276. if (this.select.value === 'text') {
  277. this.selectButton.disabled = true;
  278. this.selectButton.style.backgroundColor = '#d3d3d3';
  279. this.selectButton.style.borderColor = '#a9a9a9';
  280. this.input.placeholder = '请输入文本';
  281. } else if (this.select.value === 'position') {
  282. this.selectButton.disabled = false;
  283. this.selectButton.style.backgroundColor = '';
  284. this.selectButton.style.borderColor = '';
  285. this.input.placeholder = '点击“选取”后屏幕定位';
  286. } else {
  287. this.selectButton.disabled = false;
  288. this.selectButton.style.backgroundColor = '';
  289. this.selectButton.style.borderColor = '';
  290. this.input.placeholder = '请输入ID/类名';
  291. }
  292. });
  293.  
  294. if (this.type === 'text') {
  295. this.selectButton.disabled = true;
  296. this.selectButton.style.backgroundColor = '#d3d3d3';
  297. this.selectButton.style.borderColor = '#a9a9a9';
  298. }
  299.  
  300. this.toggleInputClickButton = document.createElement('button');
  301. this.toggleInputClickButton.className = 'yuohira-button toggle-input-click-button';
  302. this.toggleInputClickButton.innerText = this.enabled ? '暂停' : '开始';
  303. this.toggleInputClickButton.setAttribute('data-enabled', this.enabled);
  304. this.toggleInputClickButton.addEventListener('click', (e) => {
  305. e.stopPropagation();
  306. const isEnabled = this.toggleInputClickButton.innerText === '开始';
  307. this.toggleInputClickButton.innerText = isEnabled ? '暂停' : '开始';
  308. this.toggleInputClickButton.setAttribute('data-enabled', isEnabled);
  309. this.warningMsg && (this.warningMsg.style.display = 'none');
  310. });
  311. inputWrapper.appendChild(this.toggleInputClickButton);
  312.  
  313. const intervalWrapper = document.createElement('div');
  314. intervalWrapper.style.position = 'relative';
  315. intervalWrapper.style.display = 'inline-block';
  316. intervalWrapper.style.width = '100px';
  317. intervalWrapper.style.padding = '0px 140px 0px 0px';
  318.  
  319. this.intervalInput = document.createElement('input');
  320. this.intervalInput.type = 'number';
  321. this.intervalInput.value = this.interval;
  322. this.intervalInput.className = 'yuohira-input';
  323. this.intervalInput.placeholder = '间隔';
  324. this.intervalInput.style.paddingRight = '10px';
  325. this.intervalInput.style.width = '100px';
  326. this.intervalInput.min = MIN_INTERVAL;
  327. this.intervalInput.addEventListener('input', () => {
  328. let val = parseInt(this.intervalInput.value, 10) || 0;
  329. if (val < MIN_INTERVAL) {
  330. val = MIN_INTERVAL;
  331. this.intervalInput.value = MIN_INTERVAL;
  332. }
  333. this.interval = val;
  334. });
  335. intervalWrapper.appendChild(this.intervalInput);
  336.  
  337. const intervalSuffix = document.createElement('span');
  338. intervalSuffix.innerText = 'ms';
  339. intervalSuffix.style.color = '#0099cc';
  340. intervalSuffix.style.position = 'absolute';
  341. intervalSuffix.style.right = '10px';
  342. intervalSuffix.style.top = '50%';
  343. intervalSuffix.style.transform = 'translateY(-50%)';
  344. intervalSuffix.style.pointerEvents = 'none';
  345. intervalSuffix.style.zIndex = '1';
  346. intervalWrapper.appendChild(intervalSuffix);
  347.  
  348. inputWrapper.appendChild(intervalWrapper);
  349.  
  350. // ==== 新增:执行次数输入框 ====
  351. this.countInput = document.createElement('input');
  352. this.countInput.type = 'number';
  353. this.countInput.value = this.count;
  354. this.countInput.className = 'yuohira-input';
  355. this.countInput.style.width = '60px';
  356. this.countInput.style.marginLeft = '8px';
  357. this.countInput.placeholder = '-1为无限';
  358. this.countInput.title = '执行次数,-1为无限';
  359. this.countInput.addEventListener('input', () => {
  360. let val = parseInt(this.countInput.value, 10);
  361. if (isNaN(val)) val = -1;
  362. this.count = val;
  363. });
  364. inputWrapper.appendChild(this.countInput);
  365.  
  366. const countLabel = document.createElement('span');
  367. countLabel.innerText = '次';
  368. countLabel.style.color = '#0099cc';
  369. countLabel.style.marginLeft = '2px';
  370. inputWrapper.appendChild(countLabel);
  371. // ==== 新增结束 ====
  372.  
  373. this.progressBar = document.createElement('div');
  374. this.progressBar.className = 'yuohira-progress-bar';
  375. inputWrapper.appendChild(this.progressBar);
  376.  
  377. // 警告信息
  378. this.warningMsg = document.createElement('div');
  379. this.warningMsg.className = 'yuohira-warning';
  380. this.warningMsg.style.display = 'none';
  381. inputWrapper.appendChild(this.warningMsg);
  382.  
  383. const removeButton = document.createElement('button');
  384. removeButton.innerText = '-';
  385. removeButton.className = 'yuohira-button';
  386. removeButton.addEventListener('click', () => {
  387. inputWrapper.remove();
  388. this.menu.menuItems = this.menu.menuItems.filter(item => item !== this);
  389. });
  390. inputWrapper.appendChild(removeButton);
  391.  
  392. return inputWrapper;
  393. }
  394.  
  395. selectElement(event) {
  396. event.stopPropagation();
  397. if (this.select.value === 'position') {
  398. // 显示全屏十字准星
  399. this.showCrosshairSelector();
  400. return;
  401. }
  402. document.body.style.cursor = 'crosshair';
  403. this.selectButton.disabled = true;
  404.  
  405. const hoverBox = document.createElement('div');
  406. hoverBox.style.position = 'fixed';
  407. hoverBox.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
  408. hoverBox.style.color = 'white';
  409. hoverBox.style.padding = '5px';
  410. hoverBox.style.borderRadius = '5px';
  411. hoverBox.style.pointerEvents = 'none';
  412. hoverBox.style.zIndex = '10002';
  413. document.body.appendChild(hoverBox);
  414.  
  415. const mouseMoveHandler = (e) => {
  416. const elements = document.elementsFromPoint(e.clientX, e.clientY);
  417. elements.forEach((el) => {
  418. el.style.outline = '2px solid red';
  419. });
  420. document.addEventListener('mouseout', () => {
  421. elements.forEach((el) => {
  422. el.style.outline = '';
  423. });
  424. });
  425.  
  426. hoverBox.style.left = `${e.clientX + 10}px`;
  427. hoverBox.style.top = `${e.clientY + 10}px`;
  428. if (this.select.value === 'id' && elements[0].id) {
  429. hoverBox.innerText = `ID: ${elements[0].id}`;
  430. } else if (this.select.value === 'class' && elements[0].className) {
  431. hoverBox.innerText = `Class: ${elements[0].className}`;
  432. } else {
  433. hoverBox.innerText = '无ID或类名';
  434. }
  435. };
  436.  
  437. const clickHandler = (e) => {
  438. e.stopPropagation();
  439. e.preventDefault();
  440. const selectedElement = e.target;
  441. if (this.select.value === 'id' && selectedElement.id) {
  442. this.input.value = selectedElement.id;
  443. } else if (this.select.value === 'class' && selectedElement.className) {
  444. this.input.value = selectedElement.className;
  445. }
  446. document.body.style.cursor = 'default';
  447. document.removeEventListener('mousemove', mouseMoveHandler);
  448. document.removeEventListener('click', clickHandler, true);
  449. this.selectButton.disabled = false;
  450. document.body.removeChild(hoverBox);
  451. };
  452.  
  453. document.addEventListener('mousemove', mouseMoveHandler);
  454. document.addEventListener('click', clickHandler, true);
  455. }
  456.  
  457. showCrosshairSelector() {
  458. // 创建全屏遮罩和十字准星
  459. const overlay = document.createElement('div');
  460. overlay.className = 'yuohira-crosshair-overlay';
  461.  
  462. // 横线
  463. const hLine = document.createElement('div');
  464. hLine.className = 'yuohira-crosshair-line';
  465. hLine.style.height = '1px';
  466. hLine.style.width = '100vw';
  467. hLine.style.top = '50%';
  468. hLine.style.left = '0';
  469. hLine.style.background = '#e74c3c';
  470.  
  471. // 竖线
  472. const vLine = document.createElement('div');
  473. vLine.className = 'yuohira-crosshair-line';
  474. vLine.style.width = '1px';
  475. vLine.style.height = '100vh';
  476. vLine.style.left = '50%';
  477. vLine.style.top = '0';
  478. vLine.style.background = '#e74c3c';
  479.  
  480. // 坐标显示
  481. const label = document.createElement('div');
  482. label.className = 'yuohira-crosshair-label';
  483. label.innerText = '点击以选取位置';
  484. label.style.left = '50%';
  485. label.style.top = '50%';
  486.  
  487. overlay.appendChild(hLine);
  488. overlay.appendChild(vLine);
  489. overlay.appendChild(label);
  490. document.body.appendChild(overlay);
  491.  
  492. // 鼠标移动时更新准星位置和坐标
  493. const moveHandler = (e) => {
  494. hLine.style.top = `${e.clientY}px`;
  495. vLine.style.left = `${e.clientX}px`;
  496. label.style.left = `${e.clientX + 10}px`;
  497. label.style.top = `${e.clientY + 10}px`;
  498. label.innerText = `X: ${e.clientX}, Y: ${e.clientY}`;
  499. };
  500.  
  501. overlay.addEventListener('mousemove', moveHandler);
  502.  
  503. const clickHandler = (e) => {
  504. e.stopPropagation();
  505. e.preventDefault();
  506. this.input.value = `${e.clientX},${e.clientY}`;
  507. document.body.removeChild(overlay);
  508. overlay.removeEventListener('mousemove', moveHandler);
  509. overlay.removeEventListener('click', clickHandler);
  510. };
  511. overlay.addEventListener('click', clickHandler);
  512. }
  513.  
  514. findElementsByText(text) {
  515. const elements = document.querySelectorAll('*');
  516. const matchingElements = [];
  517. elements.forEach(element => {
  518. if (element.textContent.trim() === text) {
  519. matchingElements.push(element);
  520. }
  521. });
  522. return matchingElements;
  523. }
  524.  
  525. getData() {
  526. return {
  527. type: this.select.value,
  528. value: this.input.value,
  529. enabled: this.toggleInputClickButton.getAttribute('data-enabled') === 'true',
  530. interval: parseInt(this.intervalInput.value, 10),
  531. count: parseInt(this.countInput.value, 10)
  532. };
  533. }
  534.  
  535. isEnabled() {
  536. return this.toggleInputClickButton.getAttribute('data-enabled') === 'true';
  537. }
  538.  
  539. simulateMouseClick(element) {
  540. const rect = element.getBoundingClientRect();
  541. const x = rect.left + rect.width / 2;
  542. const y = rect.top + rect.height / 2;
  543. const opts = { bubbles: true, cancelable: true, clientX: x, clientY: y };
  544.  
  545. element.dispatchEvent(new PointerEvent('pointerdown', opts));
  546. element.dispatchEvent(new MouseEvent('mousedown', opts));
  547. element.dispatchEvent(new PointerEvent('pointerup', opts));
  548. element.dispatchEvent(new MouseEvent('mouseup', opts));
  549. element.dispatchEvent(new MouseEvent('click', opts));
  550. }
  551.  
  552.  
  553. autoClick(currentTime, lastUpdateTime) {
  554. if (typeof this.count !== 'number') this.count = -1;
  555. if (this.count === 0) return;
  556. if (!this.isEnabled()) return;
  557.  
  558. const lastTime = lastUpdateTime.get(this) || 0;
  559. const elapsedTime = currentTime - lastTime;
  560.  
  561. if (elapsedTime >= this.interval) {
  562. let elements = [];
  563. let inputVal = (this.input.value || '').trim();
  564. let clicked = false;
  565. if (this.select.value === 'id') {
  566. if (inputVal) {
  567. elements = Array.from(document.querySelectorAll(`#${CSS.escape(inputVal)}`));
  568. }
  569. } else if (this.select.value === 'class') {
  570. if (inputVal) {
  571. elements = Array.from(document.getElementsByClassName(inputVal));
  572. }
  573. } else if (this.select.value === 'text') {
  574. if (inputVal) {
  575. elements = this.findElementsByText(inputVal);
  576. }
  577. } else if (this.select.value === 'position') {
  578. const pos = inputVal.split(',');
  579. if (pos.length === 2) {
  580. const x = parseInt(pos[0].trim(), 10);
  581. const y = parseInt(pos[1].trim(), 10);
  582. if (!isNaN(x) && !isNaN(y)) {
  583. const el = document.elementFromPoint(x, y);
  584.  
  585. if (el && !this.menu.menuContainer.contains(el)) {
  586. elements = [el];
  587. }
  588. }
  589. }
  590. }
  591.  
  592. if (this.select.value !== 'position') {
  593. elements.forEach(element => {
  594. if (!this.menu.menuContainer.contains(element)) {
  595. this.simulateMouseClick(element);
  596. clicked = true;
  597. }
  598. });
  599. } else if (elements.length > 0) {
  600. this.simulateMouseClick(elements[0]);
  601. clicked = true;
  602. }
  603.  
  604. // 点击成功后减少次数
  605. if (clicked && this.count > 0) {
  606. this.count--;
  607. this.countInput.value = this.count;
  608. }
  609.  
  610. // 异常提示处理
  611. if (this.select.value !== 'position') {
  612. if (inputVal && elements.length === 0) {
  613. this.warningMsg.innerText = '未找到目标元素';
  614. this.warningMsg.style.display = 'block';
  615. } else {
  616. this.warningMsg.style.display = 'none';
  617. }
  618. } else {
  619. this.warningMsg.style.display = 'none';
  620. }
  621. this.progressBar.style.width = '100%';
  622. lastUpdateTime.set(this, currentTime);
  623. } else {
  624. let percent = (1 - elapsedTime / this.interval) * 100;
  625. if (percent < 0) percent = 0;
  626. if (percent > 100) percent = 100;
  627. this.progressBar.style.width = `${percent}%`;
  628. }
  629. }
  630. }
  631.  
  632. class ToggleButton {
  633. constructor(menu) {
  634. this.menu = menu;
  635. }
  636.  
  637. createElement() {
  638. const toggleButton = document.createElement('button');
  639. toggleButton.innerText = '>';
  640. toggleButton.className = 'yuohira-toggle-button';
  641. toggleButton.style.width = '15px';
  642. toggleButton.style.height = '15px';
  643. toggleButton.style.fontSize = '10px';
  644. toggleButton.style.textAlign = 'center';
  645. toggleButton.style.lineHeight = '15px';
  646. toggleButton.style.padding = '0';
  647. toggleButton.style.boxSizing = 'border-box';
  648. toggleButton.style.display = 'flex';
  649. toggleButton.style.alignItems = 'center';
  650. toggleButton.style.justifyContent = 'center';
  651.  
  652. document.body.appendChild(toggleButton);
  653.  
  654. toggleButton.addEventListener('click', (e) => {
  655. e.stopPropagation();
  656. if (this.menu.menuContainer.style.display === 'none') {
  657. this.menu.menuContainer.style.display = 'block';
  658. toggleButton.innerText = '<';
  659. } else {
  660. this.menu.menuContainer.style.display = 'none';
  661. toggleButton.innerText = '>';
  662. }
  663. });
  664.  
  665. return toggleButton;
  666. }
  667. }
  668.  
  669. (function () {
  670. 'use strict';
  671. new AutoClickMenu();
  672. })();