Disable 'disable right click'

Disables the ugly feature that disables right click

  1. // ==UserScript==
  2. // @name Disable 'disable right click'
  3. // @namespace https://github.com/mosaicer
  4. // @author mosaicer
  5. // @description Disables the ugly feature that disables right click
  6. // @version 2.0.3
  7. // @include *
  8. // @run-at document-idle
  9. // @grant GM_addStyle
  10. // @license MIT
  11. // ==/UserScript==
  12. (() => {
  13. 'use strict';
  14.  
  15. const EVENT_NAMES = [
  16. 'oncontextmenu', 'oncopy', 'onpaste', 'onmousedown', 'onselectstart'
  17. ];
  18.  
  19. const updateStyles =
  20. function overwriteStylesToEnableSelectElements() {
  21. GM_addStyle(`* {
  22. -ms-user-select: auto !important;
  23. -moz-user-select: auto !important;
  24. -khtml-user-select: auto !important;
  25. -webkit-user-select: auto !important;
  26. user-select: auto !important;
  27. }`);
  28. };
  29.  
  30. const defineJQueryFunctions =
  31. function defineJQueryManipulatingEventsFunctionsIfJQueryAvailable() {
  32. try {
  33. $.fn.getEvents = function (eventName) {
  34. const events = $._data($(this)[0], 'events') || $(this).data('events');
  35. if (events && events[eventName]) {
  36. return events[eventName];
  37. } else {
  38. return [];
  39. }
  40. };
  41.  
  42. $.fn.setEvents = function (eventName, events) {
  43. events.forEach(e => $(this).setEvent(eventName, e));
  44. };
  45.  
  46. $.fn.setEvent = function (eventName, e) {
  47. if ($.isFunction($.fn.on)) {
  48. $(this).on(eventName, e.selector, e.data, e.handler);
  49. } else {
  50. $(this).bind(eventName, e.handler);
  51. }
  52. };
  53.  
  54. $.fn.removeEvents = function (eventName) {
  55. if ($.isFunction($.fn.off)) {
  56. $(this).off(eventName);
  57. } else {
  58. $(this).unbind(eventName);
  59. }
  60. };
  61.  
  62. $.fn.enableRightClick = function (eventName) {
  63. const events = $(this).getEvents(eventName).map(
  64. e => ({
  65. selector: e.selector,
  66. data: e.data,
  67. handler: makeHandlerReturnTrue(e.handler)
  68. })
  69. );
  70.  
  71. $(this).removeEvents(eventName);
  72. $(this).setEvents(eventName, events);
  73. };
  74. } catch (e) {
  75. if (e instanceof ReferenceError && e.message === '$ is not defined') {
  76. console.info('JQuery is not available.');
  77. } else {
  78. console.error(
  79. `Disable 'disable right click': Unexpected exception: ${e}.`
  80. );
  81. }
  82. }
  83. };
  84.  
  85. const replaceFalseWithTrue =
  86. function replaceFalseTheFunctionReturnsWithTrue(funcText) {
  87. const returnValue = funcText.match(
  88. /return[\s\(]*([^\s;\}\)]+)[\s\)]*;?\s*\}?$/
  89. );
  90. if (returnValue && eval(returnValue[1]) === false) {
  91. return funcText.replace(
  92. new RegExp(
  93. `(return[\\s\\(]*)${returnValue[1]}([\\s\\)]*;?\\s*\\}?)$`
  94. ),
  95. '$1 true$2'
  96. );
  97. } else {
  98. return funcText;
  99. }
  100. };
  101.  
  102. const makeHandlerReturnTrue =
  103. function makeTheHandlerReturnTrueInsteadOfFalseIfExists(handler) {
  104. if (typeof handler === 'undefined' || handler === null) {
  105. return null;
  106. }
  107.  
  108. const handlerText = handler.toString();
  109.  
  110. let output;
  111. // ex: function () {return false;}
  112. if (handlerText.startsWith('function')) {
  113. output = replaceFalseWithTrue(handlerText)
  114. .replace(/^function\s*(\(.*?\))/, '$1 =>');
  115. }
  116. // ex: () => {return false;}
  117. else if (/^\(?.+?\)?\s*=>\s*\{/.test(handlerText)) {
  118. output = replaceFalseWithTrue(handlerText);
  119. }
  120. // ex: () => false
  121. else {
  122. output = handlerText.replace(/^(\(?.+?\)?\s*=>\s*)false$/, '$1true');
  123. }
  124.  
  125. return eval(output);
  126. };
  127.  
  128. const tryToEnableRightClickWithJQuery =
  129. function tryToEnableRightClickToTheSpecificElementByUsingJQuery(
  130. element, eventName
  131. ) {
  132. try {
  133. $(element).enableRightClick(eventName.replace('on', ''));
  134. } catch (e) {
  135. if (
  136. !(e instanceof ReferenceError) || e.message !== '$ is not defined'
  137. ) {
  138. console.error(
  139. `Disable 'disable right click': Unexpected exception: ${e}.`
  140. );
  141. }
  142. }
  143. };
  144.  
  145. // main
  146.  
  147. defineJQueryFunctions();
  148.  
  149. document.querySelectorAll('*').forEach(node =>
  150. EVENT_NAMES.forEach(name => {
  151. const attr = node.getAttribute(name);
  152.  
  153. if (attr) {
  154. // ex: return false;
  155. node.setAttribute(name, replaceFalseWithTrue(attr));
  156. }
  157.  
  158. tryToEnableRightClickWithJQuery(node, name);
  159. })
  160. );
  161.  
  162. [window, document].forEach(et =>
  163. EVENT_NAMES.forEach(name => {
  164. et[name] = makeHandlerReturnTrue(et[name]);
  165.  
  166. tryToEnableRightClickWithJQuery(et, name);
  167. })
  168. );
  169.  
  170. updateStyles();
  171. })();