Greasy Fork is available in English.

remove page limit

Remove various page limit, check the code for website list, or add other websites

Instalează acest script?
Script sugerat de autor

Poate îți va plăcea șialibaba-ad-distinguish.

Instalează acest script
// ==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} ===`);