如何用Tampermonkey修改Yahoo邮箱搜索框placeholder值?
Let me break down why your original scripts weren't working and walk you through a reliable solution to update that search box placeholder.
Why Your Original Scripts Failed
First Script Issue
Yahoo Mail is a dynamic single-page application (SPA) — it loads content incrementally after the initial page loads. Your script runs immediately when the page first loads, but the search input element hasn't been added to the DOM yet. When you run document.querySelectorAll(...), it returns an empty array, so trying to access [0] does nothing (or throws a silent error).
Second Script Issue
You made two critical mistakes here:
getElementsByClassNameexpects space-separated class names, not dot-separated like CSS selectors. Your string.select-input.react-typeahead-input...is invalid syntax for this method.- Even if you fixed the class name format,
getElementsByClassNamereturns an HTMLCollection (a list of elements), not a single element. You'd need to accessa[0]to target the input, but again, the element isn't present when the script runs initially.
Working Tampermonkey Script
This script waits for the search input to load, updates its placeholder, and even watches for any dynamic resets Yahoo might do to overwrite your change:
// ==UserScript== // @name Yahoo! Mail Search Placeholder // @namespace http://tampermonkey.net/ // @version 0.1 // @description Update Yahoo Mail search box placeholder text // @author Jupiter // @match https://mail.yahoo.com/* // @grant none // ==/UserScript== (function() { 'use strict'; // Helper function to wait for a DOM element to exist function waitForElement(selector, callback) { // Check if the element is already present const element = document.querySelector(selector); if (element) { callback(element); return; } // Watch the DOM for changes until the element is added const observer = new MutationObserver((mutations) => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { const targetElement = node.querySelector(selector) || document.querySelector(selector); if (targetElement) { callback(targetElement); observer.disconnect(); } } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); } // Target the search input using its placeholder text (reliable here) const searchInputSelector = '[placeholder="Find messages, documents, photos or people"]'; // Alternative: Use a concise class selector: '.select-input.react-typeahead-input' waitForElement(searchInputSelector, (input) => { // Set your desired placeholder input.setAttribute('placeholder', 'Search...'); // Optional: Watch for any dynamic resets of the placeholder const placeholderObserver = new MutationObserver((mutations) => { mutations.forEach(mutation => { if (mutation.attributeName === 'placeholder' && input.placeholder !== 'Search...') { input.setAttribute('placeholder', 'Search...'); } }); }); placeholderObserver.observe(input, { attributes: true }); }); })();
How This Works
- Waits for the element: The
waitForElementfunction usesMutationObserverto monitor the DOM until the search input is added. This ensures we never try to modify an element that doesn't exist yet. - Sets the placeholder: Once the element is found, it immediately updates the placeholder to your desired text.
- Guards against resets: Some sites (like Yahoo Mail) might dynamically reset attributes after user interaction. The second
MutationObserverwatches for changes to the placeholder attribute and re-sets it to your text if it gets overwritten.
You can use either the placeholder selector or the class selector — both work, but the placeholder is more specific to this exact input.
内容的提问来源于stack exchange,提问作者NoobCoder

