Humoruniv Simple Blind

간편한 블라인드 강화 기능

Du musst eine Erweiterung wie Tampermonkey, Greasemonkey oder Violentmonkey installieren, um dieses Skript zu installieren.

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

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

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

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

Sie müssten eine Skript Manager Erweiterung installieren damit sie dieses Skript installieren können

(Ich habe schon ein Skript Manager, Lass mich es installieren!)

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.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Humoruniv Simple Blind
// @namespace    http://tampermonkey.net/
// @author       십갈
// @version      2.9
// @description  간편한 블라인드 강화 기능
// @match        https://web.humoruniv.com/*
// @exclude      https://web.humoruniv.com/board/humor/list.html?table=face*
// @exclude      https://web.humoruniv.com/board/humor/list.html?table=fashion*
// @exclude      https://web.humoruniv.com/cr/cr_list.html*
// @exclude      https://web.humoruniv.com/board/humor/report_ok.html?*
// @exclude      https://web.humoruniv.com/board/humor/cash_info.html?*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addValueChangeListener
// ==/UserScript==

(function () {
    'use strict';

    // Prevent the script from running in iframes
    if (window.self !== window.top) {
        return;
    }

    const memosKey = 'userMemos';
    const memoVisibilityKey = 'memoVisibility';
    let memos = GM_getValue(memosKey, []);
    let memoVisible = GM_getValue(memoVisibilityKey, true);
    let currentPage = 0;
    const memosPerPage = 5;

    // Create memo container
    const memoContainer = document.createElement('div');
    memoContainer.style.position = 'fixed';
    memoContainer.style.top = '10px';
    memoContainer.style.right = '10px';
    memoContainer.style.width = '200px';
    memoContainer.style.border = '1px solid #ccc';
    memoContainer.style.backgroundColor = '#f9f9f9';
    memoContainer.style.zIndex = '10000';
    memoContainer.style.padding = '10px';
    memoContainer.style.boxShadow = '0px 0px 10px rgba(0, 0, 0, 0.1)';
    memoContainer.style.maxHeight = '300px';
    memoContainer.style.overflow = 'auto';
    memoContainer.style.display = memoVisible ? 'block' : 'none';
    memoContainer.style.borderRadius = '8px';

    // Create memo input
    const memoInput = document.createElement('input');
    memoInput.type = 'text';
    memoInput.style.width = 'calc(100% - 22px)';
    memoInput.style.marginBottom = '10px';
    memoInput.style.border = '2px solid #007BFF'; // Blue border
    memoInput.style.backgroundColor = '#E9F7FF';  // Light blue background
    memoInput.style.padding = '5px';              // Add padding for better visibility
    memoInput.style.borderRadius = '4px';         // Rounded corners
    memoContainer.appendChild(memoInput);

    // Create add button
    const addButton = document.createElement('button');
    addButton.textContent = '추가';
    addButton.style.marginRight = '10px';
    addButton.style.padding = '5px 10px';
    addButton.style.backgroundColor = '#007BFF';
    addButton.style.color = 'white';
    addButton.style.border = 'none';
    addButton.style.borderRadius = '4px';
    addButton.style.cursor = 'pointer';
    addButton.style.fontSize = '14px';
    memoContainer.appendChild(addButton);

    // Create save button
    const saveButton = document.createElement('button');
    saveButton.textContent = '삭제 저장';
    saveButton.style.padding = '5px 10px';
    saveButton.style.backgroundColor = '#28a745';
    saveButton.style.color = 'white';
    saveButton.style.border = 'none';
    saveButton.style.borderRadius = '4px';
    saveButton.style.cursor = 'pointer';
    saveButton.style.fontSize = '14px';
    memoContainer.appendChild(saveButton);

    // Create hide button
    const hideButton = document.createElement('button');
    hideButton.textContent = '숨기기';
    hideButton.style.padding = '5px 10px';
    hideButton.style.backgroundColor = '#6c757d';
    hideButton.style.color = 'white';
    hideButton.style.border = 'none';
    hideButton.style.borderRadius = '4px';
    hideButton.style.cursor = 'pointer';
    hideButton.style.fontSize = '14px';
    memoContainer.appendChild(hideButton);

    // Create message display
    const messageDisplay = document.createElement('div');
    messageDisplay.style.color = 'red';
    messageDisplay.style.marginBottom = '10px';
    memoContainer.appendChild(messageDisplay);

    // Create memo list container
    const memoListContainer = document.createElement('div');
    memoContainer.appendChild(memoListContainer);

    // Create pagination controls
    const paginationControls = document.createElement('div');
    paginationControls.style.display = 'flex';
    paginationControls.style.justifyContent = 'space-between';
    paginationControls.style.alignItems = 'center'; // Align items vertically
    paginationControls.style.marginTop = '10px';

    const prevButton = document.createElement('button');
    prevButton.textContent = '<<<';
    prevButton.style.padding = '5px 10px';
    prevButton.style.backgroundColor = '#007BFF';
    prevButton.style.color = 'white';
    prevButton.style.border = 'none';
    prevButton.style.borderRadius = '4px';
    prevButton.style.cursor = 'pointer';
    prevButton.style.fontSize = '14px';
    prevButton.disabled = true;
    paginationControls.appendChild(prevButton);

    const pageIndicator = document.createElement('span');
    pageIndicator.style.fontSize = '14px';
    paginationControls.appendChild(pageIndicator);

    const nextButton = document.createElement('button');
    nextButton.textContent = '>>>';
    nextButton.style.padding = '5px 10px';
    nextButton.style.backgroundColor = '#007BFF';
    nextButton.style.color = 'white';
    nextButton.style.border = 'none';
    nextButton.style.borderRadius = '4px';
    nextButton.style.cursor = 'pointer';
    nextButton.style.fontSize = '14px';
    nextButton.disabled = true;
    paginationControls.appendChild(nextButton);

    memoContainer.appendChild(paginationControls);

    // Create show button
    const showButton = document.createElement('button');
    showButton.textContent = '블라인드';
    showButton.style.position = 'fixed';
    showButton.style.top = '10px';
    showButton.style.right = '10px';
    showButton.style.padding = '10px 20px';
    showButton.style.backgroundColor = '#28a745';
    showButton.style.color = 'white';
    showButton.style.border = 'none';
    showButton.style.borderRadius = '4px';
    showButton.style.cursor = 'pointer';
    showButton.style.fontSize = '14px';
    showButton.style.display = memoVisible ? 'none' : 'block';

    // Create memo count display
    const memoCountDisplay = document.createElement('span');
    memoCountDisplay.style.position = 'fixed';
    memoCountDisplay.style.top = '40px';
    memoCountDisplay.style.right = '10px';
    memoCountDisplay.style.padding = '2px 5px';
    memoCountDisplay.style.backgroundColor = '#dc3545';
    memoCountDisplay.style.color = 'white';
    memoCountDisplay.style.borderRadius = '4px';
    memoCountDisplay.style.fontSize = '12px';
    memoCountDisplay.style.display = memoVisible ? 'none' : 'block';
    memoCountDisplay.textContent = memos.length;

    document.body.appendChild(showButton);
    document.body.appendChild(memoContainer);
    document.body.appendChild(memoCountDisplay);

    const commentBlindContainer = document.createElement('div');
    commentBlindContainer.style.position = 'fixed';
    commentBlindContainer.style.bottom = '10px';
    commentBlindContainer.style.right = '10px';
    commentBlindContainer.style.width = '200px';
    commentBlindContainer.style.border = '1px solid #ccc';
    commentBlindContainer.style.backgroundColor = '#f9f9f9';
    commentBlindContainer.style.zIndex = '10000';
    commentBlindContainer.style.padding = '10px';
    commentBlindContainer.style.boxShadow = '0px 0px 10px rgba(0, 0, 0, 0.1)';
    commentBlindContainer.style.borderRadius = '8px';
    commentBlindContainer.innerHTML = `
            <button id="showAllButton" style="padding: 5px 10px; background-color: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px;">모두 보기</button>
            <button id="hideAllButton" style="padding: 5px 10px; background-color: #dc3545; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px;">모두 가리기</button>
        `;
    document.body.appendChild(commentBlindContainer);

    document.getElementById('showAllButton').addEventListener('click', showAll);
    document.getElementById('hideAllButton').addEventListener('click', hideAll);

    function updateMemoList() {
        memoListContainer.innerHTML = '';
        const start = currentPage * memosPerPage;
        const end = Math.min(start + memosPerPage, memos.length);
        const currentMemos = memos.slice(start, end);

        currentMemos.forEach((memo, index) => {
            const memoItem = document.createElement('div');
            memoItem.style.display = 'flex';
            memoItem.style.alignItems = 'center';
            memoItem.style.marginBottom = '5px';

            const memoCheckbox = document.createElement('input');
            memoCheckbox.type = 'checkbox';
            memoCheckbox.style.marginRight = '10px';
            memoCheckbox.style.zoom = 1.5;
            memoCheckbox.checked = true;
            memoCheckbox.addEventListener('change', () => {
                if (memoCheckbox.checked) {
                    memos[start + index] = memo;
                } else {
                    memos[start + index] = null;
                }
            });

            const memoText = document.createElement('span');
            memoText.textContent = memo;

            memoItem.appendChild(memoCheckbox);
            memoItem.appendChild(memoText);
            memoListContainer.appendChild(memoItem);
        });
    }

    function updatePaginationControls() {
        prevButton.disabled = currentPage === 0;
        nextButton.disabled = (currentPage + 1) * memosPerPage >= memos.length;
        const totalPages = Math.max(1, Math.ceil(memos.length / memosPerPage));
        pageIndicator.textContent = `${currentPage + 1} / ${totalPages}`;
    }

    function addMemo() {
        const newMemo = memoInput.value.trim(); // Use value instead of textContent
        if (newMemo === '') return;
        if (memos.includes(newMemo)) {
            if (checkboxClicked === true) {
                messageDisplay.textContent = '';
            } else {
                messageDisplay.textContent = '이미 등록된 사용자입니다.';
            }
        } else {
            messageDisplay.textContent = '';
            memos.unshift(newMemo);
            GM_setValue(memosKey, memos);
            updateMemoList();
            updatePaginationControls();
            applyFilter(); // Reapply filter to ensure new memos have the checkboxes
        }
        memoInput.value = '';
    }

    addButton.addEventListener('click', addMemo); // Pass function reference instead of calling it
    memoInput.addEventListener('keydown', (e) => {
        if (e.key === 'Enter') {
            addMemo();
        }
    });

    prevButton.addEventListener('click', () => {
        if (currentPage > 0) {
            currentPage--;
            updateMemoList();
            updatePaginationControls();
        }
    });

    nextButton.addEventListener('click', () => {
        if ((currentPage + 1) * memosPerPage < memos.length) {
            currentPage++;
            updateMemoList();
            updatePaginationControls();
        }
    });

    saveButton.addEventListener('click', () => {
        memos = memos.filter(memo => memo !== null);
        GM_setValue(memosKey, memos);
        updateMemoList();
        updatePaginationControls();
        applyFilter();
        memoCountDisplay.textContent = memos.length;
    });

    hideButton.addEventListener('click', () => {
        memoContainer.style.display = 'none';
        showButton.style.display = 'block';
        memoCountDisplay.style.display = 'block';
        GM_setValue(memoVisibilityKey, false);
    });

    showButton.addEventListener('click', () => {
        memoContainer.style.display = 'block';
        showButton.style.display = 'none';
        memoCountDisplay.style.display = 'none';
        GM_setValue(memoVisibilityKey, true);
    });

    var checkboxClicked
    function applyFilter() {
        if (window.location.href.includes('https://web.humoruniv.com/user/blind_list.html')
            || ((window.location.href.includes('st=name') || window.location.href.includes('st=subject')) && !window.location.href.includes('read.html'))) {
            return;
        }
        checkboxClicked = false;
        document.querySelectorAll('span.hu_nick_txt').forEach(span => {
            let spanText = span.textContent.trim();
            if (spanText.length === 0) {
                spanText = [...span.querySelectorAll('span')].find(child => child.textContent.length > 0).textContent.trim();
            }
            if (!span.closest('#profile_table > tbody > tr') && !span.closest('span.nick > span > span') && !span.closest('#login_box_mem > dl > dd.a > span > span > span')) {
                var toggleCheckboxHTML;
                let closestTr = span.closest('tr');
                if (closestTr) {
                    if (window.location.href.includes('list.html')) {
                        closestTr = closestTr.closest('tbody').closest('tr');
                    }
                    if (memos.includes(spanText)) {
                        const listBestBox = closestTr.querySelector('td > div#list_best_box');
                        const tdsToHide = listBestBox ? Array.from(closestTr.querySelectorAll('td')).slice(1, 3) : Array.from(closestTr.querySelectorAll('td')).slice(0, 3);
                        tdsToHide.forEach(td => {
                            if (!td.querySelector('.blind-overlay')) {
                                const overlay = document.createElement('div');
                                overlay.className = 'blind-overlay';
                                overlay.style.position = 'absolute';
                                overlay.style.top = '0';
                                overlay.style.left = '0';
                                overlay.style.width = '100%';
                                overlay.style.height = '100%';
                                overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.97)'; // Set opacity to 97%
                                overlay.style.pointerEvents = 'none';
                                td.style.position = 'relative';
                                td.appendChild(overlay);
                            }
                        });
                        // Check if checkboxes already exist
                        if (!closestTr.querySelector('.toggle-hide-checkbox')) {
                            toggleCheckboxHTML = `
                             <tz><br><input type="checkbox" class="toggle-hide-checkbox"><label>보기</label></tz>
                            `
                            if (!closestTr.querySelector('.toggle-blind-checkbox')) {
                                toggleCheckboxHTML = `
                                <tz><br><input type="checkbox" class="toggle-blind-checkbox" checked><label>블라</label></tz>
                            ` + toggleCheckboxHTML;
                            } else {
                                closestTr.querySelector('.toggle-blind-checkbox').checked = true;
                            }
                            closestTr.children[3].children[1].insertAdjacentHTML('beforeend', toggleCheckboxHTML);

                            const toggleHideCheckbox = closestTr.querySelector('.toggle-hide-checkbox');
                            if (toggleHideCheckbox && toggleHideCheckbox.getAttribute('listener') !== 'true') {
                                toggleHideCheckbox.addEventListener('change', (e) => {
                                    const elementChanged = e.target;
                                    elementChanged.setAttribute('listener', 'true')
                                    const isChecked = toggleHideCheckbox.checked;
                                    tdsToHide.forEach(td => {
                                        const overlay = td.querySelector('.blind-overlay');
                                        if (overlay) {
                                            overlay.style.display = isChecked ? 'none' : 'block';
                                        }
                                    });
                                });
                            }
                        }
                    } else if (closestTr.querySelector('.toggle-hide-checkbox')) {
                        closestTr.querySelector('tz:nth-child(2)').remove()
                        const tdsToHide = Array.from(closestTr.querySelectorAll('td')).slice(0, 3);
                        tdsToHide.forEach(td => {
                            if (td.querySelector('.blind-overlay')) {
                                td.querySelector('.blind-overlay').remove()
                            }
                        });
                        closestTr.querySelector('.toggle-blind-checkbox').checked = false;
                    } else if (!closestTr.querySelector('.toggle-blind-checkbox')) {
                        toggleCheckboxHTML = `
                                <tz><br><input type="checkbox" class="toggle-blind-checkbox"><label>블라</label></tz>
                            `;
                        closestTr.children[3].children[1].insertAdjacentHTML('beforeend', toggleCheckboxHTML);
                        closestTr.querySelector('.toggle-blind-checkbox').checked = false;

                    } else {
                        closestTr.querySelector('.toggle-blind-checkbox').checked = false;
                    }
                    const toggleBlindCheckbox = closestTr.querySelector('.toggle-blind-checkbox');
                    if (toggleBlindCheckbox && toggleBlindCheckbox.getAttribute('listener') !== 'true') {
                        toggleBlindCheckbox.addEventListener('change', (e) => {
                            checkboxClicked = true;
                            const elementChanged = e.target;
                            elementChanged.setAttribute('listener', 'true')
                            const isChecked = toggleBlindCheckbox.checked;
                            if (isChecked) {
                                const span = toggleBlindCheckbox.closest('tr').querySelector('span.hu_nick_txt');
                                let spanText = span.textContent.trim();
                                if (spanText.length === 0) {
                                    spanText = [...span.querySelectorAll('span')].find(child => child.textContent.length > 0).textContent.trim();
                                }
                                console.log(spanText);
                                memoInput.value = spanText;
                                addMemo();
                            } else {
                                memos = memos.filter(memo => memo !== spanText);
                                GM_setValue(memosKey, memos);
                                updateMemoList();
                                updatePaginationControls();
                                applyFilter();
                            }
                        });

                    }
                }
            }
        });
    }

    function showAll() {
        document.querySelectorAll('.blind-overlay').forEach(overlay => {
            overlay.style.display = 'none';
        });
        document.querySelectorAll('.toggle-hide-checkbox').forEach(checkbox => {
            checkbox.checked = true;
        });
    }

    function hideAll() {
        document.querySelectorAll('.toggle-hide-checkbox').forEach(checkbox => {
            checkbox.checked = false;
            checkbox.dispatchEvent(new Event('change'));
        });
    }

    // Initialize the memo list, pagination controls, and apply filter
    updateMemoList();
    updatePaginationControls();
    applyFilter();

    // Listen for changes to memos and re-apply filter if necessary
    GM_addValueChangeListener(memosKey, () => {
        memos = GM_getValue(memosKey, []);
        updateMemoList();
        applyFilter();
        memoCountDisplay.textContent = memos.length;
    });
})();