A Universal Script to Re-Enable the Selection and Copying

Enables select, right-click, copy and drag on pages that disable them.

当前为 2021-06-11 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name A Universal Script to Re-Enable the Selection and Copying
  3. // @version 1.4.0
  4. // @description Enables select, right-click, copy and drag on pages that disable them.
  5. // @include /^https?\:\/\//
  6. // @grant none
  7. // @run-at document-start
  8. // @namespace https://greasyfork.org/users/371179
  9. // ==/UserScript==
  10. "use strict";
  11. (function(usrScrDS) {
  12.  
  13. function isDocumentObj(x) {
  14. return x && x.nodeType == 9
  15. }
  16.  
  17. function isHTMLElementObj(x) {
  18. return x && x.nodeType == 1
  19. }
  20.  
  21. function appendCssEnabler(container, cssStyle) {
  22. if (!isHTMLElementObj(container)) return;
  23. try {
  24. var css = document.createElement('style');
  25. css.type = 'text/css';
  26. css.innerHTML = cssStyle;
  27. container.appendChild(css);
  28. } catch (e) {}
  29. }
  30.  
  31. // console.log('script at', location+"")
  32. if (document == null) return;
  33. if (!document.documentElement) return;
  34.  
  35. var mKey = 'dqzadwpujtct';
  36. var nonFalseFunc = '___nff_' + mKey + '___';
  37. var rvSCC = '___returnValue_' + mKey + '___';
  38.  
  39.  
  40. usrScrDS.utSelectionColorHack = 'msmtwejkzrqa';
  41.  
  42. var cssStyleOnReady = '*, body *, div, span, body *::before, body *::after, *:hover, *:link, *:visited, *:active , *[style], *[class]{' +
  43. '-webkit-touch-callout: default !important; -webkit-user-select: auto !important; ' +
  44. '-khtml-user-select: auto !important; -moz-user-select: auto !important; ' +
  45. '-ms-user-select: auto !important; user-select: auto !important;}' +
  46. 'html body *:hover>img[src]{pointer-events:auto;}' +
  47. '[' + usrScrDS.utSelectionColorHack + '] :not(input):not(textarea)::selection{ background-color: Highlight !important; color: HighlightText !important;}' +
  48. '[' + usrScrDS.utSelectionColorHack + '] :not(input):not(textarea)::-moz-selection{ background-color: Highlight !important; color: HighlightText !important;}';
  49.  
  50. //dummy function in case alert replacement is not valid
  51. usrScrDS.mAlert_DOWN = function() {}
  52. usrScrDS.mAlert_UP = function() {}
  53.  
  54. function universaler(originalFunc, pName) {
  55. var uid = (+new Date) + "_" + pName
  56. var resFX = function(ev) {
  57. var func;
  58. var p = false;
  59. try {
  60. func = this[pName];
  61. if (typeof func == 'function' && func.uid === uid) {
  62. p = true;
  63. }
  64. } catch (e) {}
  65. var res = originalFunc.apply(this, arguments);
  66. if (p) {
  67. if (res !== false) {
  68. originalFunc[nonFalseFunc] = true;
  69. this[pName] = originalFunc;
  70. return res;
  71. }
  72. } else {
  73. return res;
  74. }
  75. }
  76. resFX.toString = () => originalFunc.toString()
  77. resFX.uid = uid
  78. return resFX;
  79. }
  80.  
  81.  
  82. usrScrDS.evtListener_disableAll =
  83. function disableAll(event) {
  84. var elmNode = event.target
  85. while (elmNode && elmNode.nodeType > 0) {
  86. var pName = 'on' + event.type
  87. var f = elmNode[pName];
  88. if (f && f[nonFalseFunc] !== true) {
  89. var nf = universaler(f, pName);
  90. nf[nonFalseFunc] = true;
  91. elmNode[pName] = nf;
  92. }
  93. elmNode = elmNode.parentNode;
  94. }
  95. }
  96.  
  97.  
  98. usrScrDS.isAnySelection =
  99. function anySelection() {
  100. var sel = (window.getSelection || function() {})();
  101. if (!sel) return null;
  102. if (typeof sel.isCollapsed == 'boolean') return !sel.isCollapsed;
  103. return sel.toString().length > 0
  104. }
  105.  
  106. usrScrDS.productFakeAlert = function(_alert) {
  107.  
  108. var _mAlert = null;
  109.  
  110. if (_alert && typeof _alert == 'function') {
  111. _mAlert = function alert(msg) {
  112. setTimeout(() => {
  113. alert._click.isDisabled() ? console.log("alert msg disabled: ", msg) : _alert.apply(this, arguments)
  114. }, 9);
  115. };
  116. _mAlert.toString = () => "function alert() { [native code] }"
  117. }
  118.  
  119. return _mAlert
  120.  
  121.  
  122. }
  123.  
  124. function enableSelectClickCopy() {
  125.  
  126. var preventEventList01 = ['copy', 'contextmenu', 'select', 'selectstart', 'dragstart', 'beforecopy'];
  127.  
  128. var isAnySelection = usrScrDS.isAnySelection
  129.  
  130. Event.prototype.preventDefault = (function(f) {
  131. var eys = preventEventList01;
  132. return function preventDefault() {
  133. if (eys.indexOf(this.type) >= 0) return;
  134. if (this.type == 'keydown' || this.type == 'keyup') {
  135. if (this.ctrlKey && this.keyCode == 67 && !this.altKey && !this.shiftKey && isAnySelection() === true) return;
  136. }
  137. return f.apply(this);
  138. }
  139. })(Event.prototype.preventDefault);
  140. Event.prototype.preventDefault.toString = () => "function preventDefault() { [native code] }"
  141.  
  142. var exs = preventEventList01;
  143. Object.defineProperty(Event.prototype, "returnValue", {
  144. get() {
  145. return rvSCC in this ? this[rvSCC] : true;
  146. },
  147. set(newValue) {
  148. if (exs.indexOf(this.type) < 0 && newValue === false) this.preventDefault();
  149. this[rvSCC] = newValue;
  150. },
  151. enumerable: true,
  152. configurable: true
  153. });
  154.  
  155. var ezs = preventEventList01;
  156. var eventsCount = ezs.length;
  157.  
  158. for (var i = 0; i < eventsCount; i++) {
  159. var event = ezs[i];
  160. document.addEventListener(event, usrScrDS.evtListener_disableAll, true);
  161. }
  162.  
  163.  
  164. var _alert = window.alert
  165. if (_alert && typeof _alert == 'function') {
  166. var _mAlert = usrScrDS.productFakeAlert(_alert)
  167. if (_mAlert) {
  168. var clickLog = {
  169. isDisabled: function() {
  170. return this.status == 1 && this.last + 50 > +new Date;
  171. }
  172. }
  173. _mAlert._click = clickLog
  174. usrScrDS.mAlert_DOWN = function() {
  175. clickLog.last = +new Date;
  176. clickLog.status = 1;
  177. }
  178. usrScrDS.mAlert_UP = function() {
  179. clickLog.last = +new Date;
  180. clickLog.status = 0;
  181. }
  182. window.alert = _mAlert
  183. }
  184. }
  185.  
  186.  
  187. usrScrDS.trigger_cssHighlight = () => {
  188. usrScrDS.trigger_cssHighlight = null
  189. try {
  190. //firefox bug: some element, even body, gives wrong bg color -> choose random element on the page.
  191. var s = [...document.querySelectorAll('a,p,div,span,b,i,strong,li')].filter(elm => elm.childElementCount === 0);
  192. var elm = (!s.length) ? document.body : s[s.length >> 1];
  193. var styles = window.getComputedStyle(elm, ':selection');
  194. var bgColor = styles["backgroundColor"]
  195. if (/^rgba\(\d+,\s*\d+,\s*\d+,\s*0\)$/.test(bgColor)) document.documentElement.setAttribute(usrScrDS.utSelectionColorHack, "");
  196. } catch (e) {}
  197.  
  198. };
  199.  
  200.  
  201. }
  202.  
  203. enableSelectClickCopy()
  204. appendCssEnabler(document.documentElement, cssStyleOnReady);
  205.  
  206.  
  207. var cid_mouseup = 0;
  208.  
  209. var alert_bypass_events_down = ["mousedown", "click", "dblclick", "contextmenu"];
  210. var alert_bypass_eventFunc_down = function(evt) {
  211. if (usrScrDS.trigger_cssHighlight) window.requestAnimationFrame(usrScrDS.trigger_cssHighlight);
  212. if (evt.type != "contextmenu" && evt.which != 3) return;
  213. if (cid_mouseup > 0) {
  214. clearTimeout(cid_mouseup)
  215. cid_mouseup = 0;
  216. }
  217. usrScrDS.mAlert_DOWN();
  218. }
  219. var alert_bypass_eventFunc_up = function(evt) {
  220. if (evt.which != 3) return;
  221. cid_mouseup = setTimeout(function() {
  222. usrScrDS.mAlert_UP();
  223. }, 17);
  224. }
  225.  
  226. alert_bypass_events_down.forEach(function(event) {
  227. document.addEventListener(event, alert_bypass_eventFunc_down, true);
  228. })
  229.  
  230. document.addEventListener("mouseup", alert_bypass_eventFunc_up, true);
  231.  
  232.  
  233. })({});