解除各种网页限制,网站列表请看代码,也可以添加自定义网站
// ==UserScript== // @namespace ATGT // @name remove page limit // @name:zh-CN 解除网页限制,网站列表请看代码,也可以添加自定义网站 // @description Remove various page limit, check the code for website list, or add other websites // quora.com: Remove login page // other domains: Remove copy or select limit // How to remove other web page's copy or select limit: // 1. Add domain to @match *://*.your.domain/* // 2. (Optional): Add your unlock handlers to variable `unlockPageHandlers' below // @description:zh-CN 解除各种网页限制,网站列表请看代码,也可以添加自定义网站 // quora.com: 移除登录页面 // 其它网站:解除选择和复制限制 // 怎么移除其它网页的限制: // 1. 将域名加到 @match,格式如下: // // @match *://*.your.domain/* // 2. (可选):将解除限制的方法加到 `unlockPageHandlers' 这个数组 // // @version 1.4.8 // @match *://*.quora.com/* // @match *://*.360doc.com/* // @match *://*.baidu.com/* // @match *://*.sdifen.com/* // @match *://*.popbee.com/* // @match *://*.baikemy.com/* // @exclude *://pan.baidu.com/* // @exclude *://ditu.baidu.com/* // @exclude *://map.baidu.com/* // @exclude *://maps.baidu.com/* // @run-at document-start // ==/UserScript== /* ChangeLog: v1.4.8: 5 Mar 2020, Delay before enable copy handler v1.4.7: 9 Nov 2019, Enable user select by css rules on '*' selector, Match baikemy.com v1.4.6: 16 Oct 2019, remove dead site, merge baidu handlers v1.4.5: 15 Oct 2019, skip hijack baidu login verify page v1.4.4: 18 Aug 2019, exclucde baidu map v1.4.3: 30 Jun 2019, Try remove all limit by default, may not work for all sites. v1.4: 27 Nov 2018, Add wenku.baidu.com v1.3: 29 Jan 2018, Added generic functions: 1. Intercept event handlers. 2. Wait for some node and do the unlock v1.1: someday, Enable user select. v1: someday, Remove quora login page. */ console.log(`=== unlock-page ${location.href} ===`); (function () { var unlockPageHandlers = [ /* !!! Need to add the global match to @include also */ /* Formats: * [ /domain name regex/, [ selector-string or node-object, event-type, event-handler, delay-ms-before-run-event-handle, event-handler-parameter ] ] * -- or -- * [ /domain name regex/, [ selector-string or node-object, event-type, event-handler, observed-object-to-be-added-dynamicly-before-run-event-handle, event-handler-parameter ] ] * -- or multiple handlers for the domain, syntax similar to previous ones -- * [ /domain name regex/, [ * [ selector-string or node-object, event-type, event-handler, delay or observed-object before run event handler, event-handler-parameter ], * [ selector-string or node-object, event-type, event-handler, delay or observed-object before run event handler, event-handler-parameter ], ] * ] * Notes: * 1. empty selector-string/node-object and event-type means run immediately/after-some-delay at document-start * 2. some event does not need a node to run on, e.g. DOMContentLoaded * 3. DOMContentLoaded is trigger before window's load event, since window's load event will trigger after external script/resource are loaded. */ [ /quora\.com/, [ /* not needed for event DOMContentLoaded */, 'DOMContentLoaded', quoraHandler, 0] ], [ /360doc\.com/, [window, 'load', enableCopyHandler, 0] ], [ /popbee\.com/, [window, 'load', enableCopyHandler, 0] ], [ /wenku\.baidu\.com/, [ [, , interceptJackEvent, 0], /* no selector/node and no event means run immediately at document-start */ [window, 'load', enableCopyHandler, 0, '.bd.doc-reader'], ] ], [ /^https?:\/\/([^/?&#%]*\.)?baidu\.com/, // <=> http*://*.baidu.com [ [, , interceptJackEvent, 0, '.vcode-body'], [, 'DOMContentLoaded', enableUserSelect, 0, 'body'], [window, 'load', enableCopyHandler, 0], ] ], [ /sdifen\.com/, [ [, , interceptJackEvent, 0], [, 'DOMContentLoaded', enableUserSelect, 0, 'body'], [window, 'load', enableCopyHandler, 0], ] ], [ /.*/, [ [, , interceptJackEvent, 0], [, 'DOMContentLoaded', enableUserSelect, 0, 'body'], [window, 'load', enableCopyHandler, 1000], ] ], ]; function quoraHandler() { console.log(new Date().toLocaleString(), ' ', arguments.callee.name); for (var d of document.body.childNodes) { if (/signup_wall_wrapper$/.test(d.id)) { d.remove(); break; } } document.body.style.overflow = 'visible'; } function replaceAddEventListener() { console.log('replaceAddEventListener'); var r0_EventTargetRegFunc = EventTarget.prototype.addEventListener; //var r1_documentRegFunc = document.addEventListener; function dummyEvtRegFunc(type, listener, options) { //console.log('dummyEvtRegFunc', this, type, listener, options); var regFunc = r0_EventTargetRegFunc; if (window.ATGT_noHijackNodes) { let nhjk = document.querySelectorAll(window.ATGT_noHijackNodes); for (let n of nhjk) { if (n.contains(this)) { console.log('dummyEvtRegFunc skip hijack', this); regFunc.call(this, type, listener, options); return; } } } if (!this.ATGT_disabledEventHandlers) this.ATGT_disabledEventHandlers = {}; if (!this.ATGT_enabledEventHandlers) this.ATGT_enabledEventHandlers = {}; //console.log('window.ATGT_eventFilter', window.ATGT_eventFilter); if (window.ATGT_eventFilter && window.ATGT_eventFilter.test(type)) { console.log('dummyEvtRegFunc', this, type, listener, options); console.log('this event is %cdisabled.', 'color: red;'); this.ATGT_disabledEventHandlers[type] = [listener, options]; } else { //console.log('dummyEvtRegFunc', this, type, listener, options); //console.log('this event is %cregistered.', 'color: green;'); this.ATGT_enabledEventHandlers[type] = [listener, options]; regFunc.call(this, type, listener, options); } } EventTarget.prototype.addEventListener = dummyEvtRegFunc; if (document.addEventListener !== dummyEvtRegFunc) document.addEventListener = dummyEvtRegFunc; } function injectFunction(func) { var script = document.createElement('script'); //script.appendChild(document.createTextNode('('+ func +')();')); script.appendChild(document.createTextNode('(function (){' + '(' + func + ')();' + '})();')); (document.body || document.head || document.documentElement).appendChild(script); } //console.log(''+injectFunction); injectFunction(replaceAddEventListener); function interceptJackEvent(noHijackNodes = '') { console.log(`interceptJackEvent noHijackNodes='${noHijackNodes}'`); var f = function setEventFilter() { var eventFilter = /copy|selectstart|mouseup|mousedown|contextmenu|keydown|keyup/; window.ATGT_eventFilter = eventFilter; window.ATGT_noHijackNodes = '__noHijackNodes__'; }; f = f.toString().replace('__noHijackNodes__', noHijackNodes); injectFunction(f); } function addStyleSheet(cssContent) { let cssid = `ATGT-remove-page-limit-css`; if (document.querySelector(`#${cssid}`)) return; let style = document.createElement('STYLE'); style.type = 'text/css'; style.id = cssid; style.appendChild(document.createTextNode(cssContent)); document.head.appendChild(style); } function enableUserSelect(sel) { console.log('enableUserSelect ', sel); var b = document.body; if (sel) b = document.querySelector(sel); var uselattrs = ['-webkit-touch-callout', '-webkit-user-select', '-khtml-user-select', '-moz-user-select', '-ms-user-select', 'user-select', ]; for (var usel of uselattrs) { try { if (b && usel in b.style) { console.log('Found style user-select: ' + b.style[usel] + ', replace it.'); b.style[usel] = 'text'; } } catch (e) { console.log(e); } } console.log('add css rule to enable user select'); addStyleSheet(` * { user-select: unset!important; }`); } function enableCopyHandler(sel) { var body = document.body || document.querySelector('body'); var doc = document; console.log('enableCopyHandler', new Date().toLocaleString(), ' ', arguments.callee.name, body.oncopy, doc.oncopy); function replaceUserHandlers(n) { if (!n) return; if (n.onclick) n.onclick = null; if (n.oncontextmenu) n.oncontextmenu = null; if (n.oncopy) n.oncopy = null; if (n.onmouseup) n.onmouseup = null; if (n.onmousedown) n.onmousedown = null; if (n.onselectstart) n.onselectstart = null; } //console.log('body', body); replaceUserHandlers(body); replaceUserHandlers(doc); var node = document.querySelector(sel); //for (var n of nodes) console.log('sel', sel, '=>', node); replaceUserHandlers(node); } function waitForNode(targetSel, nodeFilter, nodeHandler, attrHandler) { console.log('waitForNode ', targetSel, nodeFilter, nodeHandler, attrHandler); // Select the node that will be observed for mutations var targetNode = document; if (typeof targetSel === 'object') targetNode = targetSel; else if (typeof targetSel === 'string') targetNode = document.querySelector(targetSel); // console.log('targetNode', targetNode); // Options for the observer (which mutations to observe) var config = { attributes: !!attrHandler, childList: !!nodeHandler, subtree: true, }; // Callback function to execute when mutations are observed var callback = function (mutationsList) { for (var mutation of mutationsList) { if (nodeHandler && mutation.type == 'childList') { //console.log('A child node has been added ', mutation.addedNodes, ' or removed.'); for (var node of mutation.addedNodes) { if (node.querySelector instanceof Function && node.querySelector(nodeFilter) || node === node.parentNode.querySelector(nodeFilter)) { setTimeout(nodeHandler, 0); this.disconnect(); break; } } } else if (attrHandler && mutation.type == 'attributes') { //console.log('The ' + mutation.attributeName + ' attribute was modified.'); setTimeout(attrHandler, 0); } } }; // Create an observer instance linked to the callback function var observer = new MutationObserver(callback); // Start observing the target node for configured mutations observer.observe(targetNode, config); // Later, you can stop observing //observer.disconnect(); } function runHandler(url, info) { try { console.log(new Date().toLocaleString(), ' handle ', url, ' with ', info); var nodeSel = info[0]; var evt = info[1]; var func = info[2]; var delay_or_observe = info[3]; var param = info[4]; var node = document; var handler; if (typeof delay_or_observe === 'number') { handler = function () { setTimeout(func, delay_or_observe, param); }; } else { handler = function () { waitForNode(delay_or_observe, param, function () { func(param); }); }; } if (typeof nodeSel === 'object') node = nodeSel; else if (typeof nodeSel === 'string') node = document.querySelector(nodeSel); console.info('nodeSel', nodeSel, 'node', node); if (evt) node && node.addEventListener(evt, () => { handler(param); }); else handler(param); } catch (e) { console.log('Error handling ', url, ' ', e); } } for (var ph of unlockPageHandlers) { var url = ph[0]; if (url.test(location.href)) { var info_list = ph[1]; if (!(info_list[0] instanceof Array)) { try { runHandler(url, info_list); } catch (e) { console.log(e); } } else for (var info of info_list) { try { runHandler(url, info); } catch (e) { console.log(e); } } // only one rule runs on one site break; } } })(); console.log(`=== /unlock-page ${location.href} ===`);