Copy & Select Unlocker

Unblock text selection, copy, right‑click but leave video clicks intact

  1. // ==UserScript==
  2. // @name Copy & Select Unlocker
  3. // @namespace http://shinobu-scripts.local/
  4. // @version 2.2
  5. // @description Unblock text selection, copy, right‑click but leave video clicks intact
  6. // @author Shinobu
  7. // @match *://*/*
  8. // @run-at document-end
  9. // @license GPLv3
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. function injectSelectionStyles() {
  16. const css = `
  17. * { user-select: text !important; -webkit-user-select: text !important; }
  18. [style*="user-select: none"] { user-select: text !important; }
  19. `;
  20. const s = document.createElement('style');
  21. s.textContent = css;
  22. document.head.appendChild(s);
  23. }
  24.  
  25. function removeOverlays() {
  26. document.querySelectorAll('div, section').forEach(el => {
  27. if (el.querySelector('video')) return; // don’t touch video holders
  28. const st = getComputedStyle(el);
  29. const z = parseInt(st.zIndex, 10) || 0;
  30. if ((st.position==='fixed'||st.position==='absolute') &&
  31. z > 1000 &&
  32. el.offsetWidth >= innerWidth * .9 &&
  33. el.offsetHeight>= innerHeight * .9) {
  34. el.style.pointerEvents = 'none'; // let clicks pass through
  35. }
  36. });
  37. }
  38.  
  39. function observeOverlays() {
  40. const mo = new MutationObserver(removeOverlays);
  41. mo.observe(document, { childList: true, subtree: true });
  42. removeOverlays();
  43. }
  44.  
  45. function restoreEvents() {
  46. ['onselectstart','onmousedown','ondragstart'].forEach(e => { document[e]=null; });
  47. if (window.getSelection().empty) window.getSelection().empty = ()=>{};
  48. }
  49.  
  50. function stopProp(e) { e.stopImmediatePropagation(); }
  51.  
  52. function init() {
  53. injectSelectionStyles();
  54. ['contextmenu','selectstart','copy'].forEach(evt=>{
  55. document.addEventListener(evt, stopProp, true);
  56. });
  57. document.addEventListener('keydown', e => {
  58. if ((e.ctrlKey||e.metaKey) && e.key==='c') e.stopImmediatePropagation();
  59. }, true);
  60. restoreEvents();
  61. observeOverlays();
  62. console.log('Copy & Select Unlocker v2.2 running');
  63. }
  64.  
  65. if (document.readyState==='loading')
  66. window.addEventListener('load', init);
  67. else init();
  68. })();