您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Change color of clicked links in body with color presets and custom hex input
当前为
// ==UserScript== // @name Change clicked link's color // @license MIT // @namespace http://tampermonkey.net/ // @author [email protected] // @homepageURL https://gf.qytechs.cn/vi/scripts/501244-change-clicked-link-s-color // @version 1.2.1 // @description Change color of clicked links in body with color presets and custom hex input // @match *://*/* // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM_addStyle // @icon https://cdn-icons-png.flaticon.com/512/4906/4906292.png // ==/UserScript== (function() { 'use strict'; const ClickedLinkColor = { // Config p_color_clicked: GM_getValue('colorClicked', '#800080'), p_apply_all: GM_getValue('applyAll', true), p_apply_domains: GM_getValue('applyDomains', ''), // Constants style_id: "clicked-link-color-style", css_a_clicked: ` a:visited:not(nav a):not(.nav a):not(.navbar a):not(.menu a):not(.navigation a), a:visited:not(nav a):not(.nav a):not(.navbar a):not(.menu a):not(.navigation a) *, a.custom-visited, a.custom-visited * { color: %COLOR% !important; }`, colorPresets: { 'Purple': '#800080', 'Red': '#FF0000', 'Blue': '#0000FF', 'Green': '#008000', 'Orange': '#FFA500', 'Pink': '#FFC0CB', 'Brown': '#A52A2A', 'Gray': '#808080', 'Cyan': '#00FFFF', 'Magenta': '#FF00FF', 'Lime': '#00FF00' }, // Methods isDomainApplied: function(domains, site) { if (this.p_apply_all) return true; if (domains.trim() === '') return false; let domainList = domains.split(","); return domainList.some(domain => site.includes(domain.trim())); }, assignColor: function(css, color) { return css.replace(/%COLOR%/ig, color); }, main: function() { try { let url = document.documentURI; let css = this.assignColor(this.css_a_clicked, this.p_color_clicked); if (this.isDomainApplied(this.p_apply_domains, url)) { GM_addStyle(css); this.addClickListener(); } } catch (error) { console.error("ClickedLinkColor main error:", error); } }, addClickListener: function() { document.body.addEventListener('click', (e) => { if (e.target.tagName === 'A') { e.target.classList.add('custom-visited'); } }); }, observeDOMChanges: function() { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { this.main(); } }); }); observer.observe(document.body, { childList: true, subtree: true }); }, createDialog: function(id, content) { const wrapper = document.createElement('div'); wrapper.attachShadow({ mode: 'closed' }); const dialog = document.createElement('dialog'); dialog.id = id; const style = document.createElement('style'); style.textContent = ` :host { all: initial; display: block; } dialog { all: initial; font-family: Arial, sans-serif; position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); max-width: 400px; width: 90%; border: 2px solid #007bff; border-radius: 8px; padding: 16px; background-color: #fff; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); z-index: 2147483647; } dialog::backdrop { background-color: rgba(0, 0, 0, 0.5); } form { margin: 0; padding: 0; } h3 { margin-top: 0; color: #333; } input, select, textarea, button { font-family: inherit; font-size: 14px; margin: 5px 0; padding: 5px; box-sizing: border-box; } button { cursor: pointer; padding: 8px 16px; border-radius: 4px; border: none; } #applyBtn { background-color: #007bff; color: #fff; } #cancelBtn { background-color: #ccc; color: #000; } `; dialog.innerHTML = ` <form method="dialog"> ${content} </form> `; wrapper.shadowRoot.appendChild(style); wrapper.shadowRoot.appendChild(dialog); document.body.appendChild(wrapper); dialog.showModal(); return dialog; }, showColorSelector: function() { const content = ` <h3>Change Clicked Link's Color</h3> <div class="section"> <label for="colorPreset">Choose a preset color:</label> <select id="colorPreset" style="width: 100%;"> <option value="">-- Choose a preset color --</option> ${Object.entries(this.colorPresets).map(([name, value]) => `<option value="${value}" style="background-color: ${value}; color: white;">${name} (${value})</option>` ).join('')} </select> </div> <div class="section"> <label for="customColor">Or enter a custom hex color:</label> <div style="display: flex; align-items: center; gap: 10px;"> <input type="text" id="customColor" placeholder="#RRGGBB" pattern="^#[0-9A-Fa-f]{6}$" style="flex: 1;"> <input type="color" id="colorPicker" value="${this.p_color_clicked}"> </div> </div> <div class="button-container" style="margin-top: 20px;"> <button type="submit" id="applyBtn">Apply</button> <button type="button" id="cancelBtn">Cancel</button> </div> `; const dialog = this.createDialog('colorDialog', content); const colorPreset = dialog.querySelector('#colorPreset'); const customColor = dialog.querySelector('#customColor'); const colorPicker = dialog.querySelector('#colorPicker'); const cancelBtn = dialog.querySelector('#cancelBtn'); colorPreset.value = this.p_color_clicked; customColor.value = this.p_color_clicked; colorPicker.value = this.p_color_clicked; colorPreset.addEventListener('change', function() { if (this.value) { customColor.value = this.value; colorPicker.value = this.value; } }); colorPicker.addEventListener('input', function() { customColor.value = this.value; }); cancelBtn.addEventListener('click', () => dialog.close('cancel')); dialog.addEventListener('close', () => { if (dialog.returnValue !== 'cancel') { const newColor = customColor.value; if (/^#[0-9A-Fa-f]{6}$/i.test(newColor)) { this.p_color_clicked = newColor; GM_setValue('colorClicked', this.p_color_clicked); this.main(); } else { alert("Invalid color code. Please use hex format (e.g., #800080)."); } } document.body.removeChild(dialog.parentNode); }); }, showDomainSettings: function() { const content = ` <h3>Manage Enabled Domains</h3> <div class="section"> <label for="enabledSites">Enable on these sites (one per line):</label> <textarea id="enabledSites" rows="10" style="width: 100%;">${this.p_apply_domains.replace(/,/g, '\n')}</textarea> </div> <div class="section" style="margin-top: 10px;"> <label> <input type="checkbox" id="enableAllSites" ${this.p_apply_all ? 'checked' : ''}> Apply to all websites </label> </div> <div class="button-container" style="display: flex; justify-content: space-between; margin-top: 20px;"> <button type="button" id="addThisSite">Add this site</button> <div class="button-group" style="display: flex; gap: 10px;"> <button type="submit" id="applyBtn">Save</button> <button type="button" id="cancelBtn">Cancel</button> </div> </div> `; const dialog = this.createDialog('domainDialog', content); const enabledSitesTextarea = dialog.querySelector('#enabledSites'); const addThisSiteBtn = dialog.querySelector('#addThisSite'); const cancelBtn = dialog.querySelector('#cancelBtn'); const enableAllSitesCheckbox = dialog.querySelector('#enableAllSites'); addThisSiteBtn.addEventListener('click', () => { const currentDomain = window.location.hostname.replace(/^www\./, ''); const domainList = enabledSitesTextarea.value.split('\n').map(site => site.trim()).filter(Boolean); if (!domainList.includes(currentDomain)) { domainList.push(currentDomain); enabledSitesTextarea.value = domainList.join('\n'); } }); cancelBtn.addEventListener('click', () => dialog.close('cancel')); dialog.addEventListener('close', () => { if (dialog.returnValue !== 'cancel') { const newEnabledSites = enabledSitesTextarea.value.split('\n').map(site => site.trim()).filter(Boolean); const newEnableAllSites = enableAllSitesCheckbox.checked; if (JSON.stringify(newEnabledSites) !== JSON.stringify(this.p_apply_domains.split(',')) || newEnableAllSites !== this.p_apply_all) { this.p_apply_domains = newEnabledSites.join(','); this.p_apply_all = newEnableAllSites; GM_setValue('applyDomains', this.p_apply_domains); GM_setValue('applyAll', this.p_apply_all); this.main(); } } document.body.removeChild(dialog.parentNode); }); }, init: function() { // Menu commands GM_registerMenuCommand("🎨 Change clicked link's color", () => this.showColorSelector(), "C"); GM_registerMenuCommand("🌐 Domain settings", () => this.showDomainSettings(), "D"); // Run main function immediately this.main(); // Observe DOM changes this.observeDOMChanges(); } }; // Initialize the script ClickedLinkColor.init(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址