Pop Up Blocker

Simple but effective popup window blocker. Also tries to deny unsolicited redirections.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name        Pop Up Blocker
// @namespace   http://tampermonkey.net/
// @description Simple but effective popup window blocker. Also tries to deny unsolicited redirections.
// @author      Sohag1192
// @include     *
// @version     2.1
// @grant       none
// @run-at      document-start
// ==/UserScript==

(function () {
    'use strict';

    // --- CONFIGURATION ---
    var BLOCK_MODE = {
        'ALL': 0,              // Block all popups
        'CONFIRM': 2,          // Confirm each popup (Useful for debugging)
        'GRANT_PERIOD': 4,     // Block popups NOT initiated by a mouse click (Recommended)
        'ALLOW_SECURE': 8,     // Always allow HTTPS popups
        'ALLOW_REDIRECTS': 16, // Allow redirects (Default: Block unsolicited redirects)
        'CONFIRM_UNLOAD': 32   // Confirm before leaving page (Default: Off)
    };

    // Best Setting: Block popups unless you clicked something recently
    var block_mode = BLOCK_MODE.GRANT_PERIOD; 
    var grant_period = 150;  // Time in ms to allow popup after a click
    var debug = false;       // Set to true to see logs in console

    // --- INTERNALS (DO NOT CHANGE) ---
    var allowed_elements = {'a': true, 'button': {'type': 'submit'}, 'input': true, 'select': true, 'option': true};
    var ts = 0;
    var originalOpen = window.open;
    var lastInteractedElement = null;
    var notifications = 0;

    // --- HELPER FUNCTIONS ---

    function grantperiod_exceeded() {
        if (!(block_mode & BLOCK_MODE.GRANT_PERIOD)) return true; // If mode is off, ignore
        return Date.now() > (ts + grant_period);
    }

    function protocol_allowed() {
        return (block_mode & BLOCK_MODE.ALLOW_SECURE) && location.protocol === 'https:';
    }

    function is_user_triggered() {
        return !grantperiod_exceeded() || protocol_allowed();
    }

    function element_allowed(element) {
        var allowed = element.tagName && allowed_elements[element.tagName.toLowerCase()];
        if (allowed && typeof allowed === "object") {
            for (var property in allowed) {
                if (element[property] !== element[property]) return false;
            }
        }
        return !!allowed;
    }

    // --- EVENT LISTENERS ---
    // Track user interaction to distinguish real clicks from spam scripts
    ['mousedown', 'click', 'change'].forEach(evt => {
        window.addEventListener(evt, function (event) {
            ts = Date.now();
            var element = event.target;
            // Traverse up to find if we clicked a valid link/button
            while (element.parentElement && !element_allowed(element)) {
                element = element.parentElement;
            }
            lastInteractedElement = element;
            if (debug) console.log('[Pop-Up Blocker] User interaction detected on:', element);
        }, true);
    });

    // --- CORE BLOCKING LOGIC ---

    // Override window.open
    window.open = function () {
        var args = Array.prototype.slice.call(arguments);
        var url = args[0];
        var target = args[1];

        if (debug) console.log('[Pop-Up Blocker] window.open called for:', url);

        // Allow if user clicked recently OR if we are in confirm mode and user says YES
        if (is_user_triggered()) {
            if (debug) console.log('[Pop-Up Blocker] Allowed (User Triggered)');
            return originalOpen.apply(window, args);
        } else if (block_mode & BLOCK_MODE.CONFIRM) {
            if (confirm('Pop-Up Blocker: Allow popup to ' + url + '?')) {
                return originalOpen.apply(window, args);
            }
        }

        // BLOCK ACTION
        console.warn('[Pop-Up Blocker] Blocked popup:', url);
        notify('Blocked popup window', url, target, 0, function() {
            // Callback if user clicks the notification to open it anyway
            originalOpen.apply(window, args);
        });

        return null; // Return null to break the script trying to open the popup
    };

    // --- NOTIFICATION UI ---
    function notify(text, uri, title, timeout, onclick, target) {
        var notification = document.createElement('div');
        notification.style.cssText = `
            position: fixed; top: 0; left: 0; width: 100%; z-index: 2147483647;
            background: #ffebee; color: #b71c1c; border-bottom: 2px solid #b71c1c;
            padding: 10px; font-family: sans-serif; font-size: 14px;
            box-shadow: 0 4px 6px rgba(0,0,0,0.1); display: flex; align-items: center; justify-content: space-between;
        `;
        
        var message = document.createElement('span');
        message.innerHTML = '<b>🛑 ' + text + ':</b> ';
        notification.appendChild(message);

        // Link to open it anyway
        var link = document.createElement('a');
        link.href = uri || '#';
        link.innerText = (uri && uri.length > 50) ? uri.substring(0, 50) + '...' : uri;
        link.style.cssText = 'color: #0d47a1; text-decoration: underline; margin-left: 10px; cursor: pointer; font-weight: bold;';
        link.onclick = function(e) {
            e.preventDefault();
            e.stopPropagation();
            removeNotification();
            if (onclick) onclick();
            else if (uri) window.location.href = uri;
        };
        notification.appendChild(link);

        // Close button
        var closeBtn = document.createElement('button');
        closeBtn.innerHTML = '&#10005;';
        closeBtn.style.cssText = 'background: none; border: none; font-size: 16px; cursor: pointer; color: #333; margin-left: 20px;';
        closeBtn.onclick = removeNotification;
        notification.appendChild(closeBtn);

        document.body.appendChild(notification);
        notifications++;

        function removeNotification() {
            if (notification.parentNode) notification.parentNode.removeChild(notification);
            notifications--;
        }

        if (timeout) setTimeout(removeNotification, timeout);
    }
})();