仿真Burning Vocabulary,没有翻译功能,仅限于在经济学人网站上对单词进行标注
// ==UserScript== // @name Burning Vocabulary类似版 // @namespace http://tampermonkey.net/ // @version 1.35 // @description 仿真Burning Vocabulary,没有翻译功能,仅限于在经济学人网站上对单词进行标注 // @author TCH // @match *://www.economist.com // @match *://www.bloomberg.com // @include *://*economist.com/* // @include *://*bloomberg.com/* // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_listValues // @license tangchuanhui // ==/UserScript== (function() { var elmGetter = function() { const win = window.unsafeWindow || document.defaultView || window; const doc = win.document; const listeners = new WeakMap(); let mode = 'css'; let $; const elProto = win.Element.prototype; const matches = elProto.matches || elProto.matchesSelector || elProto.webkitMatchesSelector || elProto.mozMatchesSelector || elProto.oMatchesSelector; const MutationObs = win.MutationObserver || win.WebkitMutationObserver || win.MozMutationObserver; function addObserver(target, callback) { const observer = new MutationObs(mutations => { for (const mutation of mutations) { if (mutation.type === 'attributes') { callback(mutation.target); if (observer.canceled) return; } for (const node of mutation.addedNodes) { if (node instanceof Element) callback(node); if (observer.canceled) return; } } }); observer.canceled = false; observer.observe(target, {childList: true, subtree: true, attributes: true}); return () => { observer.canceled = true; observer.disconnect(); }; } function addFilter(target, filter) { let listener = listeners.get(target); if (!listener) { listener = { filters: new Set(), remove: addObserver(target, el => listener.filters.forEach(f => f(el))) }; listeners.set(target, listener); } listener.filters.add(filter); } function removeFilter(target, filter) { const listener = listeners.get(target); if (!listener) return; listener.filters.delete(filter); if (!listener.filters.size) { listener.remove(); listeners.delete(target); } } function query(all, selector, parent, includeParent, curMode) { switch (curMode) { case 'css': const checkParent = includeParent && matches.call(parent, selector); if (all) { const queryAll = parent.querySelectorAll(selector); return checkParent ? [parent, ...queryAll] : [...queryAll]; } return checkParent ? parent : parent.querySelector(selector); case 'jquery': let jNodes = $(includeParent ? parent : []); jNodes = jNodes.add([...parent.querySelectorAll('*')]).filter(selector); if (all) return $.map(jNodes, el => $(el)); return jNodes.length ? $(jNodes.get(0)) : null; case 'xpath': const ownerDoc = parent.ownerDocument || parent; selector += '/self::*'; if (all) { const xPathR###lt = ownerDoc.evaluate(selector, parent, null, 7, null); const r###lt = []; for (let i = 0; i < xPathR###lt.snapshotLength; i++) { r###lt.push(xPathR###lt.snapshotItem(i)); } return r###lt; } return ownerDoc.evaluate(selector, parent, null, 9, null).singleNodeValue; } } function isJquery(jq) { return jq && jq.fn && typeof jq.fn.jquery === 'string'; } function getOne(selector, parent, timeout) { const curMode = mode; return new Promise(resolve => { const node = query(false, selector, parent, false, curMode); if (node) return resolve(node); let timer; const filter = el => { const node = query(false, selector, el, true, curMode); if (node) { removeFilter(parent, filter); timer && clearTimeout(timer); resolve(node); } }; addFilter(parent, filter); if (timeout > 0) { timer = setTimeout(() => { removeFilter(parent, filter); resolve(null); }, timeout); } }); } return { get currentSelector() { return mode; }, get(selector, ...args) { let parent = typeof args[0] !== 'number' && args.shift() || doc; if (mode === 'jquery' && parent instanceof $) parent = parent.get(0); const timeout = args[0] || 0; if (Array.isArray(selector)) { return Promise.all(selector.map(s => getOne(s, parent, timeout))); } return getOne(selector, parent, timeout); }, each(selector, ...args) { let parent = typeof args[0] !== 'function' && args.shift() || doc; if (mode === 'jquery' && parent instanceof $) parent = parent.get(0); const callback = args[0]; const curMode = mode; const refs = new WeakSet(); for (const node of query(true, selector, parent, false, curMode)) { refs.add(curMode === 'jquery' ? node.get(0) : node); if (callback(node, false) === false) return; } const filter = el => { for (const node of query(true, selector, el, true, curMode)) { const _el = curMode === 'jquery' ? node.get(0) : node; if (refs.has(_el)) break; refs.add(_el); if (callback(node, true) === false) { return removeFilter(parent, filter); } } }; addFilter(parent, filter); }, create(domString, ...args) { const returnList = typeof args[0] === 'boolean' && args.shift(); const parent = args[0]; const template = doc.createElement('template'); template.innerHTML = domString; const node = template.content.firstElementChild; if (!node) return null; parent ? parent.appendChild(node) : node.remove(); if (returnList) { const list = {}; node.querySelectorAll('[id]').forEach(el => list[el.id] = el); list[0] = node; return list; } return node; }, selector(desc) { switch (true) { case isJquery(desc): $ = desc; return mode = 'jquery'; case !desc || typeof desc.toLowerCase !== 'function': return mode = 'css'; case desc.toLowerCase() === 'jquery': for (const jq of [window.jQuery, window.$, win.jQuery, win.$]) { if (isJquery(jq)) { $ = jq; break; }; } return mode = $ ? 'jquery' : 'css'; case desc.toLowerCase() === 'xpath': return mode = 'xpath'; default: return mode = 'css'; } } }; }(); elmGetter.get('main[style]').then(div1 => { rendering(); }); //window.addEventListener("load", rendering()); function rendering() { var allsText = document.getElementsByTagName("body")[0].innerHTML; function makeallcolor(searchVal, nColor, tot) { searchVal = " " + searchVal; var sKey = "<span name='addSpan' style='color:" + nColor + "';>" + " " + "<sup>" + tot + "</sup>" + searchVal + "</span>"; var num = -1; var rStr = new RegExp(searchVal, "g"); var rHtml = new RegExp("\<.*?\>", "ig"); //匹配html元素 var aHtml = allsText.match(rHtml); //存放html元素的数组 allsText = allsText.replace(rHtml, '{~}'); //替换html标签 allsText = allsText.replace(rStr, sKey); //替换key allsText = allsText.replace(/{~}/g, function() { //恢复html标签 num++; return aHtml[num]; }); } function makecolor(searchVal, nColor, tot) { var oDiv = document.getElementsByTagName("body")[0]; var sText = oDiv.innerHTML; var sKey = "<span name='addSpan' style='color:" + nColor + "';>" + " <sup>" + tot + "</sup> " + searchVal + "</span>"; searchVal = " " + searchVal; var num = -1; var rStr = new RegExp(searchVal, "g"); var rHtml = new RegExp("\<.*?\>", "ig"); //匹配html元素 var aHtml = sText.match(rHtml); //存放html元素的数组 sText = sText.replace(rHtml, '{~}'); //替换html标签 sText = sText.replace(rStr, sKey); //替换key sText = sText.replace(/{~}/g, function() { //恢复html标签 num++; return aHtml[num]; }); oDiv.innerHTML = sText; } //alert("开始整体染色1"); let list_value = GM_listValues(); //alert(list_value.length); for (var i = 0; i < list_value.length; i++) { let tot = GM_getValue(list_value[i], 0); makeallcolor(list_value[i], "red", tot); } document.getElementsByTagName("body")[0].innerHTML = allsText; //监听选择文本的动作 var selectionFirst = null; var selectionSecond = null; document.addEventListener("selectionchange", () => { selectionFirst = selectionSecond; selectionSecond = document.getSelection() .toString(); }); //alert("整体染色结束1"); //alert("开始渲染按钮"); let div = document.createElement("div"); div.style = "position:fixed; z-index:90;bottom:20px; left: 0; margin: auto; right: 0;text-align:center;" div.innerHTML = '<span id="biaozhubiaozhu"style="width:150rpx;z-index:100;margin:15px;background-color: red;font-size: 30px;border-color: red;border-radius: 5px;" >标注</span><span id="quxiaobiaozhu" style="width:150rpx;margin:15px;background-color: black;font-size: 30px;color: white;border-radius: 5px;">取消</span>'; document.onclick = function(event) { if (event.target.id == "biaozhubiaozhu") { selectionFirst = selectionSecond; //在有些浏览器,需要把这句去除 if (selectionFirst !== null && selectionFirst !== void 0 && selectionFirst.toString()) { let tot = GM_getValue(selectionFirst, 0); GM_setValue(selectionFirst, tot + 1); if (tot == 0) makecolor(selectionFirst, "red", tot + 1); } } else if (event.target.id == "quxiaobiaozhu") { selectionFirst = selectionSecond; //在有些浏览器,需要把这句去除 if (selectionFirst !== null && selectionFirst !== void 0 && selectionFirst.toString()) { GM_deleteValue(selectionFirst) } } }; document.body.append(div); } })();