Torn – Hide Notes Button (site-wide)

Hides the Notes button across all Torn pages, including dynamic loads and shadow roots.

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         Torn – Hide Notes Button (site-wide)
// @namespace    ASTA-MK
// @version      1.0
// @license      MIT
// @description  Hides the Notes button across all Torn pages, including dynamic loads and shadow roots.
// @match        https://www.torn.com/*
// @run-at       document-start
// @grant        GM_addStyle
// ==/UserScript==

(function () {
  'use strict';

  // Hide via CSS as early as possible (works if not inside a shadow root)
  try {
    if (typeof GM_addStyle === 'function') {
      GM_addStyle(`#notes_panel_button{display:none !important;}`);
    } else {
      const style = document.createElement('style');
      style.textContent = `#notes_panel_button{display:none !important;}`;
      document.documentElement.appendChild(style);
    }
  } catch {}

  // Helper: hide an element robustly
  function hideEl(el) {
    if (!el) return;
    el.setAttribute('hidden', 'true');
    el.setAttribute('aria-hidden', 'true');
    el.style.setProperty('display', 'none', 'important');
    el.style.setProperty('visibility', 'hidden', 'important');
    el.style.setProperty('pointer-events', 'none', 'important');
  }

  // Search a root (document or shadowRoot) for matches
  function hideInRoot(root) {
    if (!root || !root.querySelectorAll) return;
    // Primary target by ID, plus a safe fallback by title (in case ID changes)
    const candidates = root.querySelectorAll(
      '#notes_panel_button, button#notes_panel_button, button[title="Notes"]#notes_panel_button, button[title="Notes"]'
    );
    candidates.forEach(hideEl);
  }

  // Recursively observe document + any shadow roots
  function observeRoot(root) {
    if (!root) return;

    // Initial pass
    hideInRoot(root);

    const mo = new MutationObserver((mutations) => {
      for (const m of mutations) {
        // Check added nodes directly
        m.addedNodes && m.addedNodes.forEach((node) => {
          if (node.nodeType !== 1) return; // ELEMENT_NODE
          // If this node is the button or contains it, hide it
          if (
            node.id === 'notes_panel_button' ||
            (node.matches && node.matches('button[title="Notes"]')) ||
            (node.querySelectorAll && node.querySelectorAll('#notes_panel_button, button[title="Notes"]').length)
          ) {
            hideInRoot(node.ownerDocument || document);
            hideInRoot(node.shadowRoot || node);
          }
          // If this node has a shadow root, observe inside it too
          if (node.shadowRoot) observeRoot(node.shadowRoot);
        });
      }
    });

    mo.observe(root, { childList: true, subtree: true });

    // Also hook into any existing shadow roots under this root
    if (root.querySelectorAll) {
      root.querySelectorAll('*').forEach((el) => {
        if (el.shadowRoot) observeRoot(el.shadowRoot);
      });
    }
  }

  // Start observing as soon as possible
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => observeRoot(document));
  } else {
    observeRoot(document);
  }

  // Extra: catch late-created top-level shadow roots (rare, but cheap)
  new MutationObserver(() => {
    document.querySelectorAll('*').forEach((el) => {
      if (el.shadowRoot && !el.shadowRoot.__tornNotesObserved) {
        el.shadowRoot.__tornNotesObserved = true;
        observeRoot(el.shadowRoot);
      }
    });
  }).observe(document.documentElement, { childList: true, subtree: true });
})();