Raw Source
asurpbs / DramaDay Modifier

// ==UserScript==
// @name         DramaDay Modifier
// @author       asurpbs
// @version      25.11.19
// @description  Adds a circular search button that opens a menu with grey icons. The menu auto-hides on scroll and launches searches in a centered popup.
// @author       asurpbs
// @match        *://*.dramaday.me/*
// @updateURL https://openuserjs.org/meta/asurpbs/DramaDay_Universal_Search_Menu.meta.js
// @downloadURL https://openuserjs.org/install/asurpbs/DramaDay_Universal_Search_Menu.user.js
// @grant        GM_addStyle
// @copyright 2025, asurpbs (https://openuserjs.org/users/asurpbs)
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // --- SVG Icons (Reverted to Earlier Grey Style) ---
    const iconFillColor = '#808080';
    const searchTriggerSVG = `
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16px" height="16px" fill="${iconFillColor}">
            <path d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
        </svg>`;

    const googleIconSVG = `
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="20px" height="20px">
            <path fill="${iconFillColor}" d="M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12s5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24s8.955,20,20,20s20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z"/>
        </svg>`;

    const mdlIconSVG = `
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20px" height="20px" fill="${iconFillColor}">
            <path d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
        </svg>`;

    const imdbIconSVG = `
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20px" height="20px" fill="${iconFillColor}">
            <path d="M22 2H2v20h20V2zM8 18H4V6h4v12zm6-12h-4v12h4V6zm6 0h-4v12h4V6z"/>
        </svg>`;

    // --- Inject CSS for the button and menu ---
    GM_addStyle(`
        .userscript-search-container {
            position: relative;
            display: inline-block;
            margin-left: 8px;
            vertical-align: middle;
        }
        .userscript-search-trigger {
            width: 28px; height: 28px;
            border-radius: 50%;
            background-color: #f0f0f0;
            border: 1px solid #e0e0e0;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            transition: background-color 0.2s;
        }
        .dark .userscript-search-trigger { background-color: #333; border-color: #555; }
        .userscript-search-trigger:hover { background-color: #e0e0e0; }
        .dark .userscript-search-trigger:hover { background-color: #444; }
        .userscript-search-menu {
            display: none;
            position: absolute;
            bottom: 120%;
            left: 50%;
            transform: translateX(-50%);
            background-color: white;
            border-radius: 25px;
            box-shadow: 0 4px 15px rgba(0,0,0,0.15);
            z-index: 1000;
            padding: 8px;
            flex-direction: row;
            gap: 8px;
            border: 1px solid #eee;
        }
        .dark .userscript-search-menu { background-color: #2c2c2c; border-color: #444; }
        .userscript-search-menu a {
            padding: 6px;
            border-radius: 50%;
            transition: background-color 0.2s, opacity 0.2s;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .userscript-search-menu a:hover {
            background-color: #f0f0f0;
            opacity: 0.7;
        }
        .dark .userscript-search-menu a:hover {
            background-color: #555;
        }
    `);

    // --- Main Function to Add UI ---
    function addSearchInterface() {
        const cards = document.querySelectorAll('article.mosaic__item');
        cards.forEach(card => {
            const metaSection = card.querySelector('.article__meta');
            if (!metaSection || metaSection.querySelector('.userscript-search-container')) {
                return; // Skip if already added
            }

            const titleElement = card.querySelector('h3.article__title a');
            if (!titleElement) return;

            const title = titleElement.innerText.trim();
            metaSection.style.display = 'flex';
            metaSection.style.alignItems = 'center';

            // URLs
            const isMovie = Array.from(card.querySelectorAll('.article__categories li')).some(cat => cat.innerText.trim().toLowerCase() === 'movie');
            const mdlSearchType = isMovie ? '77' : '68';
            const googleURL = `https://www.google.com/search?q=${encodeURIComponent(title)}+tv+series`;
            const mydramalistURL = `https://mydramalist.com/search?q=${encodeURIComponent(title)}&adv=titles&ty=${mdlSearchType}&co=3&so=relevance`;
            const imdbURL = `https://www.imdb.com/find?q=${encodeURIComponent(title)}`;

            // Create UI
            const container = document.createElement('div');
            container.className = 'userscript-search-container';

            const trigger = document.createElement('div');
            trigger.className = 'userscript-search-trigger';
            trigger.title = 'Open search options';
            trigger.innerHTML = searchTriggerSVG;

            const menu = document.createElement('div');
            menu.className = 'userscript-search-menu';

            menu.appendChild(createPopupLink('Search on Google', googleURL, googleIconSVG));
            menu.appendChild(createPopupLink('Search on MyDramaList', mydramalistURL, mdlIconSVG));
            menu.appendChild(createPopupLink('Search on IMDb', imdbURL, imdbIconSVG));

            // Event Handling
            trigger.addEventListener('click', (e) => {
                e.stopPropagation();
                const isVisible = menu.style.display === 'flex';
                hideOpenMenus(); // Close any other menus
                if (!isVisible) {
                    menu.style.display = 'flex';
                }
            });

            container.appendChild(trigger);
            container.appendChild(menu);
            metaSection.appendChild(container);
        });
    }

    // --- Helper Functions ---
    function createPopupLink(title, url, svg) {
        const link = document.createElement('a');
        link.title = title;
        link.href = url;
        link.innerHTML = svg;
        link.addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            openCenteredPopup(url, 'Search Results', 900, 700);
            this.closest('.userscript-search-menu').style.display = 'none';
        });
        return link;
    }

    function openCenteredPopup(url, title, width, height) {
        const left = (screen.width / 2) - (width / 2);
        const top = (screen.height / 2) - (height / 2);
        window.open(url, title, `toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=no, width=${width}, height=${height}, top=${top}, left=${left}`);
    }

    function hideOpenMenus() {
        document.querySelectorAll('.userscript-search-menu').forEach(menu => {
            menu.style.display = 'none';
        });
    }

    // --- Event Listeners and Observers ---
    document.addEventListener('click', hideOpenMenus);
    window.addEventListener('scroll', hideOpenMenus, { passive: true }); // Hide menu on scroll

    const observer = new MutationObserver(addSearchInterface);
    observer.observe(document.body, { childList: true, subtree: true });
    window.addEventListener('load', addSearchInterface);

})();