您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Convert the toy size chart information from imperial to metric system from some famous adult toy makers
// ==UserScript== // @name DongleSize2Metric // @namespace https://github.com/yossi99/DongleSize2Metric // @version v0.0.4-beta // @description Convert the toy size chart information from imperial to metric system from some famous adult toy makers // @author Yossi99 // @match https://twintailcreations.com/products/* // @match https://bad-dragon.com/products/* // @icon https://www.google.com/s2/favicons?sz=64&domain=bad-dragon.com // @license MIT // ==/UserScript== const SupportedDomains = Object.freeze({ TwinTail: 'twintailcreations.com', BadDragon: 'bad-dragon.com' }); const patchAttribute = 'patched'; (function() { const domain = window.location.host const supDomains = Object.values(SupportedDomains); if (!supDomains.find(i => i === domain)) { console.error('Domain not supported'); return; } const domainMap = { [SupportedDomains.TwinTail]: PatchTwinTailSizeTable, [SupportedDomains.BadDragon]: PatchBadDragonSizeTable } const observer = new MutationObserver((event) => { domainMap[domain](); }); observer.observe(document.querySelector('body'), {childList: true, subtree: true}); })(); function inches2CmFormated(string) { return `${(+string * 2.54).toFixed(2)} cm`;} function PatchBadDragonSizeTable() { const toySizeTable = [".table.sizing-chart__table", "table.sizing-chart"] .map((i) => document.querySelector(i)) .find((i) => i); if (!toySizeTable) { console.warn("Toy size table not found"); return false; } const tableRows = toySizeTable.querySelectorAll('tbody tr') for (let row of tableRows) { const header = row.querySelector('th'); (header ? patchHeader(header) : console.warn ('Header not found')); const rowData = [...row.querySelectorAll(`td:not([${patchAttribute}])`)] rowData.filter(i => !Number.isNaN(+i.textContent)) ?.forEach(i => patchElement(i)); } return true; function patchElement(element) { if (!(element instanceof Element)) { return; } element.textContent = inches2CmFormated(element.textContent); element.setAttribute(patchAttribute, true); } function patchHeader(header) { if (!(header instanceof Element)) { return; } const headerExp = /(?:\w+| )+ \([\w]+\)$/s; if (!headerExp.test(header.textContent)) { return; } header.textContent = header.textContent.replace(/\([\w]+\)$/s, '(cm)'); } } function PatchTwinTailSizeTable() { const chartBtnSelector = [ '.ProductForm__Label > button', '[data-action=open-modal].ProductForm__LabelLink' ].find(i => document.querySelector(i)); if (!chartBtnSelector) { console.warn('chart button not found'); return; } const chartBtn = document.querySelector(chartBtnSelector); const chartControlName = chartBtn.getAttribute('aria-controls'); if (!chartControlName) { console.error('Chart control name not found'); return false; } const toySizeTable = document.querySelector(`[id=${chartControlName}]`)?.querySelector('table'); if (!toySizeTable) { console.warn('Toy size table not found!'); return false; } const sizeRegExp = /((?:\d*\.)?\d+)(?:"|”)?(?:$|(?="|”))/s; // Get rows and skip header (toy name) const tableRows = [...(document.querySelectorAll('tr') ?? [])].slice(1); for (let row of tableRows) { // Skip category header const rowData = [...(row.querySelectorAll(`td:not([${patchAttribute}])`) ?? [])].slice(1); rowData.filter(i => sizeRegExp.test(i.textContent)) ?.forEach(i => patchElement(i)); } return true; function patchElement(element) { if (!(element instanceof Element)) { return; } const inches = +(sizeRegExp.exec(element.textContent)[1]); if (Number.isNaN(inches)) { console.error("Failed to extract size from: ", element); return; } element.textContent = element.textContent.replace(sizeRegExp, inches2CmFormated(inches)); element.setAttribute(patchAttribute, true); } }