Elements Blocker

Long press to enter picker mode, click element to hide it forever

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Elements Blocker
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Long press to enter picker mode, click element to hide it forever
// @author       smoochie
// @match        *://*/*
// @run-at       document-end
// @grant        none
// @license      MIT
// ==/UserScript==



(function () {
  'use strict';



  const STORAGE_KEY = 'element-blocker';
  const LONG_PRESS_MS = 600;



  let pickerActive = false;
  let pressTimer = null;
  let highlighted = null;



  function getStored() {
    try {
      return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}');
    } catch { return {}; }
  }



  function applyStored() {
    const all = getStored();
    const host = location.hostname;
    const selectors = all[host] || [];
    selectors.forEach(sel => {
      try {
        document.querySelectorAll(sel).forEach(el => {
          el.style.cssText = 'display:none!important';
        });
      } catch {}
    });
  }



  function saveSelector(sel) {
    const all = getStored();
    const host = location.hostname;
    if (!all[host]) all[host] = [];
    if (!all[host].includes(sel)) {
      all[host].push(sel);
      localStorage.setItem(STORAGE_KEY, JSON.stringify(all));
    }
  }


  function getSelector(el) {
    if (el.id) return `#${CSS.escape(el.id)}`;


    const parts = [];
    let current = el;
    while (current && current !== document.body) {
      let part = current.tagName.toLowerCase();



      if (current.id) {
        part = `#${CSS.escape(current.id)}`;
        parts.unshift(part);
        break;
      }


      if (current.className && typeof current.className === 'string') {
        const classes = current.className.trim().split(/\s+/).slice(0, 2);
        part += '.' + classes.map(c => CSS.escape(c)).join('.');
      }


      const siblings = current.parentElement
        ? [...current.parentElement.children].filter(c => c.tagName === current.tagName)
        : [];
      if (siblings.length > 1) {
        const idx = siblings.indexOf(current) + 1;
        part += `:nth-of-type(${idx})`;
      }



      parts.unshift(part);
      current = current.parentElement;
    }



    return parts.join(' > ');
  }



  function showToast(msg, color = '#1a3a5c') {
    const old = document.getElementById('eb-toast');
    if (old) old.remove();


    const toast = document.createElement('div');
    toast.id = 'eb-toast';
    toast.textContent = msg;
    toast.style.cssText = `
      position: fixed;
      bottom: 30px;
      left: 50%;
      transform: translateX(-50%);
      background: ${color};
      color: #fff;
      padding: 10px 20px;
      font-size: 14px;
      font-family: sans-serif;
      z-index: 2147483647;
      pointer-events: none;
      white-space: nowrap;
    `;
    document.body.appendChild(toast);
    setTimeout(() => toast.remove(), 2500);
  }


  function highlight(el) {
    if (highlighted === el) return;
    clearHighlight();
    highlighted = el;
    el.dataset.ebOutline = el.style.outline || '';
    el.style.outline = '2px solid red';
    el.style.outlineOffset = '2px';
  }



  function clearHighlight() {
    if (highlighted) {
      highlighted.style.outline = highlighted.dataset.ebOutline || '';
      delete highlighted.dataset.ebOutline;
      highlighted = null;
    }
  }


  function enterPicker() {
    pickerActive = true;
    showToast('🔴 Selection mode - click on an item to hide it');
    document.body.style.cursor = 'crosshair';
  }


  function exitPicker() {
    pickerActive = false;
    clearHighlight();
    document.body.style.cursor = '';
  }


  document.addEventListener('touchstart', e => {
    pressTimer = setTimeout(() => {
      if (!pickerActive) enterPicker();
      else exitPicker();
    }, LONG_PRESS_MS);
  }, { passive: true });



  document.addEventListener('touchend', () => {
    clearTimeout(pressTimer);
  }, { passive: true });



  document.addEventListener('touchmove', () => {
    clearTimeout(pressTimer);
  }, { passive: true });



  document.addEventListener('mouseover', e => {
    if (!pickerActive) return;
    highlight(e.target);
  });



  document.addEventListener('click', e => {
    if (!pickerActive) return;
    e.preventDefault();
    e.stopPropagation();


    const el = e.target;
    const sel = getSelector(el);
    saveSelector(sel);
    el.style.cssText = 'display:none!important';
    showToast('✅ The element has been hidden and saved', '#1a6644');
    exitPicker();
  }, true);


  document.addEventListener('keydown', e => {
    if (e.key === 'Escape' && pickerActive) {
      exitPicker();
      showToast('❌ Selection mode has been canceled', '#888');
    }
  });

  applyStored();

  setTimeout(applyStored, 1500);
  setTimeout(applyStored, 4000);

  const observer = new MutationObserver(applyStored);
  observer.observe(document.body, { childList: true, subtree: true });

})();