// ==UserScript== // @name 左键限制解除 // @description 左键选中 // @version 1.1 // @match *://*/* // @run-at document-start // @grant none // @namespace https://greasyfork.org/users/12375 // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 默认规则配置 var rule = { name: "default", hook_eventNames: "contextmenu|select|selectstart|copy|cut|dragstart", unhook_eventNames: "keydown|keyup", dom0: true, hook_addEventListener: true, hook_preventDefault: true, hook_set_returnValue: true }; // 要处理的 event 列表 var hook_eventNames, unhook_eventNames, eventNames; // 储存名称 var storageName = getRandStr('qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM', parseInt(Math.random() * 12 + 8)); // 储存被 Hook 的函数 var EventTarget_addEventListener = EventTarget.prototype.addEventListener; var document_addEventListener = document.addEventListener; var Event_preventDefault = Event.prototype.preventDefault; // 清理循环 function clearLoop() { var elements = getElements(); for(var i in elements) { for(var j in eventNames) { var name = 'on' + eventNames[j]; if(elements[i][name] !== null && elements[i][name] !== onxxx) { if(unhook_eventNames.indexOf(eventNames[j]) >= 0) { elements[i][storageName + name] = elements[i][name]; elements[i][name] = onxxx; } else { elements[i][name] = null; } } } } } // 返回true的函数 function returnTrue(e) { return true; } function unhook_t(e) { return unhook(e, this, storageName + e.type + 't'); } function unhook_f(e) { return unhook(e, this, storageName + e.type + 'f'); } function unhook(e, self, funcsName) { var list = self[funcsName]; for(var i in list) { list[i](e); } e.returnValue = true; return true; } function onxxx(e) { var name = storageName + 'on' + e.type; this[name](e); e.returnValue = true; return true; } // 获取随机字符串 function getRandStr(chs, len) { var str = ''; while(len--) { str += chs[parseInt(Math.random() * chs.length)]; } return str; } // 获取所有元素 包括document function getElements() { var elements = Array.prototype.slice.call(document.getElementsByTagName('*')); elements.push(document); return elements; } // 初始化 function init() { // hook addEventListener if(rule.hook_addEventListener) { EventTarget.prototype.addEventListener = addEventListener; document.addEventListener = addEventListener; } } init(); // 视频控制保护逻辑 const EV = { select: 1, selectstart: 2, copy: 4, cut: 8, contextmenu: 16, mousedown: 32, mouseup: 64, mousemove: 128, click: 256 }; const videoElements = new WeakMap(); const isVideoControl = (target) => { while(target) { if(videoElements.has(target)) return videoElements.get(target); if(target.tagName === 'VIDEO' || target.classList.contains('progress-bar') || target.closest('video, [role="video-controls"]')) { videoElements.set(target, true); return true; } target = target.parentElement; } return false; }; const { addEventListener: protoAdd } = EventTarget.prototype; const { preventDefault: protoPrevent } = Event.prototype; EventTarget.prototype.addEventListener = function(type, listener, options) { const eventFlag = EV[type] || 0; if(eventFlag & 0b00011111 && !isVideoControl(this)) { protoAdd.call(this, type, e => e.stopImmediatePropagation(), { capture: true, ...options }); } else { protoAdd.call(this, type, listener, options); } }; })();