Shared utility functions for Torn userscripts
このスクリプトは単体で利用できません。右のようなメタデータを含むスクリプトから、ライブラリとして読み込まれます: // @require https://update.greasyfork.org/scripts/569328/1772270/Torn%20Utils%20Library.js
// ==UserScript==
// @name Torn Utils Library
// @namespace https://www.torn.com/
// @version 1.0
// @description Shared utility functions for Torn userscripts
// @author PFangy
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
// Create global namespace if it doesn't exist
window.TornUtils = window.TornUtils || {};
/**
* Wait for a DOM element to appear
* Useful for SPA / React pages like Torn
*
* @param {string} selector
* @param {number} timeout
* @returns {Promise<Element>}
*/
window.TornUtils.waitForElement = function (selector, timeout = 10000) {
return new Promise((resolve, reject) => {
const element = document.querySelector(selector);
if (element) {
resolve(element);
return;
}
const observer = new MutationObserver(() => {
const el = document.querySelector(selector);
if (el) {
observer.disconnect();
resolve(el);
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
if (timeout) {
setTimeout(() => {
observer.disconnect();
reject(new Error(`waitForElement timeout: ${selector}`));
}, timeout);
}
});
};
/**
* Wait for multiple elements
*/
window.TornUtils.waitForElements = function (selector, timeout = 10000) {
return new Promise((resolve, reject) => {
const elements = document.querySelectorAll(selector);
if (elements.length) {
resolve(elements);
return;
}
const observer = new MutationObserver(() => {
const els = document.querySelectorAll(selector);
if (els.length) {
observer.disconnect();
resolve(els);
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
if (timeout) {
setTimeout(() => {
observer.disconnect();
reject(new Error(`waitForElements timeout: ${selector}`));
}, timeout);
}
});
};
/**
* Observe element changes
*/
window.TornUtils.observe = function (target, callback, options = { childList: true, subtree: true }) {
const observer = new MutationObserver(callback);
observer.observe(target, options);
return observer;
};
/**
* Wait until DOM ready
*/
window.TornUtils.domReady = function () {
return new Promise(resolve => {
if (document.readyState === 'complete' || document.readyState === 'interactive') {
resolve();
} else {
document.addEventListener('DOMContentLoaded', resolve);
}
});
};
})();