TetteLib

A library containing several functions I use often in my other scripts

目前为 2023-10-28 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/478390/1271574/TetteLib.js

  1. // ==UserScript==
  2. // @name TetteLib
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.3
  5. // @description A library containing several functions I use often in my other scripts
  6. // @author TetteDev
  7. // @match *://*/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. function simulateNotification(title, message, type = "info", timeout = 2500) {
  12. const toastId = "simpleToast";
  13. var notificationContainer = document.createElement("div");
  14. notificationContainer.id = toastId;
  15. let existingNotification = document.getElementById(toastId);
  16. if (existingNotification) existingNotification.remove();
  17. notificationContainer.title = "Click to dismiss this message";
  18. var innerContainer = document.createElement("div");
  19. const imgSize = 54;
  20. let imgSrc = "";
  21. let backgroundColor = "";
  22. let fontColor = "";
  23. if (type.toLowerCase() === "debug") {
  24. imgSrc = "https://cdn0.iconfinder.com/data/icons/small-n-flat/24/678124-wrench-screwdriver-64.png";
  25. backgroundColor = "#eac100";
  26. fontColor = "#323232";
  27. }
  28. else if (type.toLowerCase() === "error") {
  29. imgSrc = "https://cdn0.iconfinder.com/data/icons/small-n-flat/24/678069-sign-error-64.png";
  30. backgroundColor = "#ff0000";
  31. fontColor = "#ffffff";
  32. }
  33. else {
  34. imgSrc = "https://cdn0.iconfinder.com/data/icons/small-n-flat/24/678110-sign-info-64.png";
  35. backgroundColor = "#0f0f0f";
  36. fontColor = "#ffffff";
  37. }
  38. notificationContainer.style.cssText
  39. = `position: fixed;
  40. bottom: 15px;
  41. right: 15px;
  42. background-color: ${backgroundColor};
  43. color: ${fontColor};
  44. border: 1px solid #ffffff;
  45. max-width: 20%;
  46. padding-left: 50px;
  47. padding-right: 50px;
  48. padding-top:10px;
  49. box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
  50. z-index: 9999;
  51. opacity: 1;
  52. transition: opacity 1s, border-radius 0.5s;
  53. border-radius: 5px;
  54. cursor: pointer;
  55. `
  56. innerContainer.innerHTML =
  57. `<img src='${imgSrc}' style='width:${imgSize}px;height:${imgSize}px;padding-bottom:10px;display:block;margin:auto;'></img>
  58. <p id='title' style='text-align:center;font-weight:bold;font-size:20px;'>${title}</p>
  59. <p id='message' style='text-align:center;padding-bottom:15px;font-size:15px;'>${message}</p>`;
  60. notificationContainer.appendChild(innerContainer);
  61. notificationContainer.onclick = function() { document.body.removeChild(notificationContainer); notificationContainer = null; }
  62. document.body.appendChild(notificationContainer);
  63. if (type.toLowerCase() === "debug") {
  64. console.warn(`[Youtube AdSkipper][DEBUG] ${title}: ${message}`);
  65. }
  66. else if (type.toLowerCase() === "error") {
  67. console.error(`[Youtube AdSkipper][ERROR] ${title}: ${message}`);
  68. }
  69. // Set a timer to fade out the notification after 'timeout' milliseconds if (if 'timeout' is not -1 or less)
  70. if (timeout > -1) {
  71. setTimeout(function() {
  72. if (notificationContainer == null) return;
  73. notificationContainer.style.opacity = 0;
  74. setTimeout(function() {
  75. if (notificationContainer == null) return;
  76. document.body.removeChild(notificationContainer);
  77. }, 500); // Remove the notification after the fade-out animation (adjust as needed)
  78. }, (timeout < 1 ? 2500 : timeout)); // Start the fade-out animation after 5 seconds (adjust as needed)
  79. }
  80. }
  81. function waitForElement(selector) {
  82. return new Promise((resolve, reject) => {
  83. const el = document.querySelector(selector);
  84. if (el) {resolve(el);}
  85. new MutationObserver((mutationRecords, observer) => {
  86. // Query for elements matching the specified selector
  87. Array.from(document.querySelectorAll(selector)).forEach((element) => {
  88. resolve(element);
  89. //Once we have resolved we don't need the observer anymore.
  90. observer.disconnect();
  91. });
  92. })
  93. .observe(document.documentElement, {
  94. childList: true,
  95. subtree: true
  96. });
  97. });
  98. }
  99. function waitForElementWithTimeout(selector, mustBeVisibleToEye = false, timeout = 3000) {
  100. return new Promise((resolve, reject) => {
  101. if (timeout < 0) timeout = 0;
  102. if (!selector) reject("No selector specified");
  103.  
  104. const el = document.querySelector(selector);
  105. if (el && (mustBeVisibleToEye ? __visible(el) : true)) {
  106. resolve(el);
  107. }
  108.  
  109. const timeoutMessage = `Timeout: Element with selector '${selector}' not found within ${timeout} ms`;
  110. const timer = setTimeout(() => {
  111. reject(new Error(timeoutMessage));
  112. }, timeout);
  113.  
  114. const observer = new MutationObserver((mutationRecords, observer) => {
  115. const elements = Array.from(document.querySelectorAll(selector));
  116. if (elements.length > 0 && mustBeVisibleToEye) elements = elements.find((el) => __visible(el));
  117.  
  118. if (elements.length > 0) {
  119. clearTimeout(timer);
  120. observer.disconnect();
  121. resolve(elements[0]);
  122. }
  123. });
  124.  
  125. observer.observe(document.documentElement, {
  126. childList: true,
  127. subtree: true,
  128. });
  129. });
  130. }
  131. function traverseParentsUntil(startElement, predicateUntil) {
  132. if (!startElement) return null;
  133. if (!predicateUntil || typeof predicateUntil !== "function") return null;
  134. if (!startElement.parentElement) return predicateUntil(startElement) ? startElement : null;
  135. while (startElement.parentElement) {
  136. if (predicateUntil(startElement.parentElement)) return startElement.parentElement;
  137. else startElement = startElement.parentElement;
  138. }
  139. return null;
  140. }
  141. function traverseChildrenUntil(startElement, predicateUntil) {
  142. if (!startElement) return null;
  143. if (!predicateUntil || typeof predicateUntil !== "function") return null;
  144. if (!startElement.firstChild) return predicateUntil(startElement) ? startElement : null;
  145. while (startElement.firstChild) {
  146. if (predicateUntil(startElement.firstChild)) return startElement.firstChild;
  147. else startElement = startElement.firstChild;
  148. }
  149. return null;
  150. }
  151. function __visible(el) {
  152. return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
  153. }
  154. function removeAllEventListeners(el, preserveChildrenEvents = true) {
  155. if (!preserveChildrenEvents) {
  156. el.parentNode.replaceChild(el.cloneNode(true), el);
  157. }
  158. else {
  159. var newEl = el.cloneNode(false);
  160. while (el.hasChildNodes()) newEl.appendChild(el.firstChild);
  161. el.parentNode.replaceChild(newEl, el);
  162. }
  163. return el;
  164. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址