移除B站搜索框和输入框内的占位符
你可以点击 此处 或者在其他Greasy Fork镜像网站来直接获取该脚本。
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元素的placeholder和title属性。 - 检查
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元素的属性变化,当placeholder或title属性发生变化时,移除这些属性。 - 检查
input元素是否具有nav-search-input类,只有符合条件的元素才会被监听。 - 创建一个
MutationObserver实例,监听input元素的属性变化。当属性变化时,检查变化的属性是否是placeholder或title,如果是则调用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方法移除placeholder和title属性。 - 对每个
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');
});
}
- 该函数用于处理新增的节点,检查是否包含搜索框或搜索按钮,并对其进行处理。
- 遍历新增的节点,检查是否是
input或div元素,并判断是否具有nav-search-input或nav-search-btn类。 - 对新增的搜索框调用
removeAttributes和observeInput方法。 - 对新增的搜索按钮调用
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中的搜索框和按钮被正确处理。