您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
移除B站顶部搜索框内的 placeholder 和 title 属性;同时阻止无输入时进行搜索操作时的跳转行为。
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
元素的 placeholder
和 title
属性。input
元素是否具有 nav-search-input
类,只有符合条件的元素才会被处理。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
元素的属性变化,当 placeholder
或 title
属性发生变化时,移除这些属性。input
元素是否具有 nav-search-input
类,只有符合条件的元素才会被监听。MutationObserver
实例,监听 input
元素的属性变化。当属性变化时,检查变化的属性是否是 placeholder
或 title
,如果是则调用 removeAttributes
方法移除这些属性。observer.observe
方法开始监听 input
元素的属性变化。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
方法移除 placeholder
和 title
属性。input
元素调用 observeInput
方法开始监听属性变化。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
标记已绑定的元素,防止重复绑定。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');
});
}
input
或 div
元素,并判断是否具有 nav-search-input
或 nav-search-btn
类。removeAttributes
和 observeInput
方法。preventEmptySearchActions
方法。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
容器(如果存在),否则监听整个文档。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
时可能发生的错误。iframe
handleIframes();
handleIframes
方法,处理当前文档中的所有 iframe
元素。iframe
中的搜索框和按钮被正确处理。