Greasy Fork is available in English.

移除B站顶部搜索框内的占位符

移除B站顶部搜索框内的 placeholder 和 title 属性;同时阻止无输入时进行搜索操作时的跳转行为。

作者
GaoQiTa
日安装量
0
总安装量
15
评分
2 0 0
版本
0.3
创建于
2025-01-07
更新于
2025-04-12
大小
8.2 KB
许可证
MIT
适用于

1、removeAttributes 函数

function removeAttributes(input) {
    if (input.classList.contains('nav-search-input')) {
        if (input.hasAttribute('placeholder')) {
            input.removeAttribute('placeholder');
        }
        if (input.hasAttribute('title')) {
            input.removeAttribute('title');
        }
    }
}
  • 该函数用于移除传入的 input 元素的 placeholdertitle 属性。
  • 检查 input 元素是否具有 nav-search-input 类,只有符合条件的元素才会被处理。

2、observeInput 函数

function observeInput(input) {
    if (input.classList.contains('nav-search-input')) {
        const observer = new MutationObserver(function (mutations) {
            mutations.forEach(function (mutation) {
                if (mutation.type === 'attributes' && (mutation.attributeName === 'placeholder' || mutation.attributeName === 'title')) {
                    removeAttributes(mutation.target);
                }
            });
        });

        observer.observe(input, { attributes: true });
    }
}
  • 该函数用于监听传入的 input 元素的属性变化,当 placeholdertitle 属性发生变化时,移除这些属性。
  • 检查 input 元素是否具有 nav-search-input 类,只有符合条件的元素才会被监听。
  • 创建一个 MutationObserver 实例,监听 input 元素的属性变化。当属性变化时,检查变化的属性是否是 placeholdertitle,如果是则调用 removeAttributes 方法移除这些属性。
  • 使用 observer.observe 方法开始监听 input 元素的属性变化。

3、初始处理现有的 input 元素

document.querySelectorAll('input.nav-search-input').forEach(function (input) {
    removeAttributes(input);
    observeInput(input);
});
  • 该代码块用于处理当前文档中具有 nav-search-input 类的 input 元素。
  • 使用 document.querySelectorAll('input.nav-search-input') 获取所有符合条件的 input 元素。
  • 对每个 input 元素调用 removeAttributes 方法移除 placeholdertitle 属性。
  • 对每个 input 元素调用 observeInput 方法开始监听属性变化。

4、preventEmptySearchActions 函数

function preventEmptySearchActions(searchInputSelector, searchButtonSelector) {
    const searchInput = document.querySelector(searchInputSelector);
    const searchButton = document.querySelector(searchButtonSelector);

    if (searchInput && !searchInput.dataset.preventBound) {
        const preventEmptySearch = (e) => {
            if (searchInput.value.trim() === '') {
                e.preventDefault();
                e.stopImmediatePropagation();
            }
        };

        searchInput.addEventListener(
            'keydown',
            (e) => {
                if (e.key === 'Enter') {
                    preventEmptySearch(e);
                }
            },
            true
        );

        searchInput.dataset.preventBound = true;
    }

    if (searchButton && !searchButton.dataset.preventBound) {
        searchButton.addEventListener(
            'click',
            (e) => {
                if (searchInput.value.trim() === '') {
                    e.preventDefault();
                    e.stopImmediatePropagation();
                }
            },
            true
        );

        searchButton.dataset.preventBound = true;
    }
}
  • 该函数用于阻止搜索框为空时的搜索操作。
  • 获取搜索框和搜索按钮,并检查是否已经绑定事件,避免重复绑定。
  • 对搜索框绑定 keydown 事件监听器,在捕获阶段阻止用户按下回车键时的默认行为。
  • 对搜索按钮绑定 click 事件监听器,在捕获阶段阻止用户点击按钮时的默认行为。
  • 使用 dataset.preventBound 标记已绑定的元素,防止重复绑定。

5、processAddedNodes 函数

function processAddedNodes(nodes) {
    const addedInputs = [];
    const addedButtons = [];

    nodes.forEach(function (node) {
        if (node.nodeType === 1) {
            if (node.tagName.toLowerCase() === 'input' && node.classList.contains('nav-search-input')) {
                addedInputs.push(node);
            } else if (node.tagName.toLowerCase() === 'div' && node.classList.contains('nav-search-btn')) {
                addedButtons.push(node);
            } else {
                node.querySelectorAll('input.nav-search-input').forEach((input) => addedInputs.push(input));
                node.querySelectorAll('.nav-search-btn').forEach((button) => addedButtons.push(button));
            }
        }
    });

    addedInputs.forEach((input) => {
        removeAttributes(input);
        observeInput(input);
    });

    addedButtons.forEach(() => {
        preventEmptySearchActions('.nav-search-input', '.nav-search-btn');
    });
}
  • 该函数用于处理新增的节点,检查是否包含搜索框或搜索按钮,并对其进行处理。
  • 遍历新增的节点,检查是否是 inputdiv 元素,并判断是否具有 nav-search-inputnav-search-btn 类。
  • 对新增的搜索框调用 removeAttributesobserveInput 方法。
  • 对新增的搜索按钮调用 preventEmptySearchActions 方法。

6、监听 DOM 变化以处理新添加的节点

const observer = new MutationObserver(function (mutations) {
    const addedNodes = [];
    mutations.forEach(function (mutation) {
        mutation.addedNodes.forEach(function (node) {
            addedNodes.push(node);
        });
    });
    processAddedNodes(addedNodes);
});

const targetContainer = document.querySelector('.nav-container') || document.body;
observer.observe(targetContainer, { childList: true, subtree: true });
  • 使用 MutationObserver 监听特定容器的 DOM 变化,处理新添加的搜索框和按钮。
  • 将新增的节点传递给 processAddedNodes 函数进行批量处理。
  • 缩小监听范围到 .nav-container 容器(如果存在),否则监听整个文档。

7、handleIframes 函数

function handleIframes() {
    document.querySelectorAll('iframe').forEach(function (iframe) {
        try {
            const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
            if (!iframeDocument) return;

            const inputs = iframeDocument.querySelectorAll('input.nav-search-input');
            inputs.forEach(function (input) {
                removeAttributes(input);
                observeInput(input);
            });

            const buttons = iframeDocument.querySelectorAll('.nav-search-btn');
            buttons.forEach(() => {
                preventEmptySearchActions('.nav-search-input', '.nav-search-btn');
            });

            if (!iframeDocument.body.dataset.observed) {
                const iframeObserver = new MutationObserver(function (mutations) {
                    const addedNodes = [];
                    mutations.forEach(function (mutation) {
                        mutation.addedNodes.forEach(function (node) {
                            addedNodes.push(node);
                        });
                    });
                    processAddedNodes(addedNodes);
                });

                iframeObserver.observe(iframeDocument.body, { childList: true, subtree: true });
                iframeDocument.body.dataset.observed = true;
            }
        } catch (e) {
            console.error('无法访问 iframe:', e);
        }
    });
}
  • 该函数用于处理当前文档中的所有 iframe 元素。
  • iframe 中的搜索框和按钮调用相关方法进行处理。
  • 使用 MutationObserver 监听 iframe 的 DOM 变化,并调用 processAddedNodes 处理新增节点。
  • 使用 try...catch 捕获访问 iframe 时可能发生的错误。

8、初始处理现有的 iframe

handleIframes();
  • 调用 handleIframes 方法,处理当前文档中的所有 iframe 元素。
  • 确保 iframe 中的搜索框和按钮被正确处理。