Greasy Fork

Burning Vocabulary类似版

仿真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 xPathResult = ownerDoc.evaluate(selector, parent, null, 7, null);
                        const result = [];
                        for (let i = 0; i < xPathResult.snapshotLength; i++) {
                            result.push(xPathResult.snapshotItem(i));
                        }
                        return result;
                    }
                    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);
     
     
     
     
        }
     
     
     
     
    })();