Disable 'disable right click'

Disables the ugly feature that disables right click

目前为 2019-09-09 提交的版本。查看 最新版本

// ==UserScript==
// @name         Disable 'disable right click'
// @namespace    https://github.com/mosaicer
// @author       mosaicer
// @description  Disables the ugly feature that disables right click
// @version      1.5.0
// @include      *
// @run-at       document-idle
// ==/UserScript==
(() => {
  'use strict';

  const EVENT_NAMES = [
    'oncontextmenu', 'oncopy', 'onpaste', 'onmousedown', 'onselectstart'
  ];

  const replaceFalseWithTrue =
    function replaceFalseTheFunctionReturnsWithTrue(funcText) {
      return funcText.replace(/(return[\s\(]+)false([\s\)]*;?)/, '$1true$2');
    };

  const makeHandlerReturnTrue =
    function makeTheHandlerReturnTrueInsteadOfFalseIfExists(handler) {
      if (typeof handler === 'undefined' || handler === null) {
        return null;
      }

      const handlerText = handler.toString();

      let output;
      if (handlerText.startsWith('function')) {
        output = replaceFalseWithTrue(handlerText)
          .replace(/^function\s*(\(.*?\))/, '$1 =>');
      } else if (/^\(?.+?\)?\s*=>\s*\{/.test(handlerText)) {
        output = replaceFalseWithTrue(handlerText);
      } else {
        output = handlerText.replace(/^(\(?.+?\)?\s*=>\s*)false/, '$1true');
      }

      return eval(output);
    };

  document.querySelectorAll('*').forEach(node =>
    EVENT_NAMES.forEach(name => {
      const attr = node.getAttribute(name);

      if (attr) {
        node.setAttribute(name, replaceFalseWithTrue(attr));
      }
    })
  );

  [window, document].forEach(et =>
    EVENT_NAMES.forEach(name => et[name] = makeHandlerReturnTrue(et[name]))
  );

  try {
    $.fn.getEvents = function (eventName) {
      const events = $._data($(this)[0], 'events') || $(this).data('events');
      if (events && events[eventName]) {
        return events[eventName];
      } else {
        return [];
      }
    };

    $.fn.setEvents = function (eventName, events) {
      events.forEach(e => $(this).setEvent(eventName, e));
    };

    $.fn.setEvent = function (eventName, e) {
      if ($.isFunction($.fn.on)) {
        $(this).on(eventName, e.selector, e.data, e.handler);
      } else {
        $(this).bind(eventName, e.handler);
      }
    };

    $.fn.removeEvents = function (eventName) {
      if ($.isFunction($.fn.off)) {
        $(this).off(eventName);
      } else {
        $(this).unbind(eventName);
      }
    };

    EVENT_NAMES.map(name => name.replace('on', '')).forEach(name =>
      [window, document, document.body].forEach(et => {
        const events = $(et).getEvents(name).map(
          e => ({
            selector: e.selector,
            data: e.data,
            handler: makeHandlerReturnTrue(e.handler)
          })
        );

        $(et).removeEvents(name);
        $(et).setEvents(name, events);
      })
    );
  } catch (e) {
    if (e instanceof ReferenceError && e.message === '$ is not defined') {
      console.info('JQuery is not available.');
    } else {
      console.error(`Disable 'disable right click': Unexpected exception: ${e}.`);
    }
  }
})();