您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Простая настройка фона, цвета, окантовки, добавление верхней навигации и свечения текста для forum.blackrussia.online.
当前为
// ==UserScript== // @name (v3.3 Simple+Border+TopNav+Glow) Стиль для BR Forum // @namespace http://tampermonkey.net/ // @version 3.3 // <-- Увеличил версию // @description Простая настройка фона, цвета, окантовки, добавление верхней навигации и свечения текста для forum.blackrussia.online. // @author Maras Ageev // @match https://forum.blackrussia.online/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @run-at document-start // @license MIT // ==/UserScript== (function() { 'use strict'; console.log('[BR Style+Border+TopNav+Glow v3.3] Инициализация...'); // Обновил лог const STYLE_ID = 'blackrussia-custom-style-v33'; // Обновил ID для версии const PANEL_ID = 'blackrussia-settings-panel-v33'; // Обновил ID для версии const TOP_NAV_ID = 'blackrussia-top-nav-bar-v33'; // Обновил ID для версии const TOP_NAV_HEIGHT = '45px'; let settingsPanel = null; let currentSettings = {}; // --- Стандартные Настройки (с окантовкой) --- const defaultSettings = { bgImageUrl: '', opacityValue: 0.9, borderRadius: '8px', bgColor: '#2E2E2E', enableRounding: true, // Настройки окантовки enableEdge: true, edgeColor: '#FFEB3B', edgeWidth: '1px', edgeOpacity: 0.7 // Настройку для свечения можно добавить сюда, если нужно будет ее включать/выключать }; // --- Вспомогательные Функции --- function hexToRgb(hex) { if (!hex || typeof hex !== 'string') return null; let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } // --- Управление Настройками --- async function loadSettings() { console.log('[BR Style] Загрузка настроек...'); currentSettings = {}; try { for (const key in defaultSettings) { const savedValue = await GM_getValue(key, defaultSettings[key]); if (typeof defaultSettings[key] === 'boolean') { currentSettings[key] = (savedValue === true || savedValue === 'true'); } else if (key === 'opacityValue' || key === 'edgeOpacity') { currentSettings[key] = parseFloat(savedValue) || defaultSettings[key]; } else if (typeof defaultSettings[key] === 'number') { currentSettings[key] = parseInt(savedValue, 10) || defaultSettings[key]; } else { currentSettings[key] = savedValue; } } console.log('[BR Style] Настройки загружены:', currentSettings); } catch (e) { console.error('[BR Style] Ошибка загрузки настроек!', e); currentSettings = { ...defaultSettings }; alert('[BR Style] Ошибка загрузки настроек! Применены стандартные значения.'); } } async function saveSettings(settingsToSave) { console.log('[BR Style] Сохранение настроек...'); try { for (const key in settingsToSave) { if (defaultSettings.hasOwnProperty(key)) { await GM_setValue(key, settingsToSave[key]); } } currentSettings = { ...settingsToSave }; console.log('[BR Style] Настройки сохранены.'); return true; } catch (e) { console.error('[BR Style] Ошибка сохранения настроек!', e); alert('[BR Style] Ошибка сохранения настроек!'); return false; } } // --- Применение Динамических Стилей Форума (на основе настроек) --- function applyForumStyles(settings) { console.log('[BR Style] Применение динамических стилей...'); let styleElement = document.getElementById(STYLE_ID); if (!styleElement) { styleElement = document.createElement('style'); styleElement.id = STYLE_ID; styleElement.type = 'text/css'; (document.head || document.documentElement).appendChild(styleElement); console.log('[BR Style] Создан элемент style для динамических стилей.'); } try { // Основной фон элементов const bgRgb = hexToRgb(settings.bgColor); const elementBgColor = bgRgb ? `rgba(${bgRgb.r}, ${bgRgb.g}, ${bgRgb.b}, ${settings.opacityValue})` : defaultSettings.bgColor; // Fallback // Окантовка const edgeRgb = hexToRgb(settings.edgeColor); const edgeColorWithOpacity = edgeRgb ? `rgba(${edgeRgb.r}, ${edgeRgb.g}, ${edgeRgb.b}, ${settings.edgeOpacity})` : 'transparent'; const finalEdgeBoxShadow = settings.enableEdge ? `0 0 0 ${settings.edgeWidth} ${edgeColorWithOpacity}` : 'none'; // Скругление const finalBorderRadius = settings.enableRounding ? settings.borderRadius : '0px'; const fallbackBgColor = settings.bgColor || '#1e1e1e'; // Селекторы (основные элементы, к которым применяем фон, радиус и окантовку) const mainElementsSelector = ` .block-container, .block-filterBar, .message-inner, .widget-container .widget, .bbCodeBlock-content, .formPopup .menu-content, .tooltip-content, .structItem, .notice-content, .overlay-container .overlay-content, .p-header, .p-nav, .p-navSticky.is-sticky .p-nav, .p-footer `; // Селекторы элементов, которые должны оставаться прозрачными const transparentElementsSelector = ` .p-body-inner, .message, .message-cell, .block-body, .bbCodeBlock, .widget-container, .notice, .overlay-container .overlay `; // Специальный селектор для главного контейнера страницы (для фона body и отступов) const pageWrapperSelector = '.p-pageWrapper'; const forumCss = ` /* Фон для body (если картинка задана) */ body { ${settings.bgImageUrl ? ` background-image: url('${settings.bgImageUrl}') !important; background-size: cover !important; background-attachment: fixed !important; background-position: center center !important; background-repeat: no-repeat !important; ` : ''} background-color: ${fallbackBgColor} !important; /* Всегда задаем фоновый цвет */ } /* Стиль для основного контейнера страницы */ ${pageWrapperSelector} { background-color: ${elementBgColor} !important; border-radius: ${finalBorderRadius} !important; box-shadow: ${finalEdgeBoxShadow} !important; /* Окантовка через тень */ ${settings.enableRounding ? 'overflow: hidden;' : ''} /* Отступ сверху из-за фиксированной панели навигации - УЖЕ В СТАТИЧНЫХ СТИЛЯХ */ } /* Стили для других основных блоков */ ${mainElementsSelector} { background-color: ${elementBgColor} !important; border-radius: ${finalBorderRadius} !important; box-shadow: ${finalEdgeBoxShadow} !important; /* Окантовка через тень */ ${settings.enableRounding ? 'overflow: hidden;' : ''} } /* Сброс фона и границ для вложенных элементов */ ${transparentElementsSelector} { background: none !important; border: none !important; /* Сбрасываем тень у вложенных, если она была */ box-shadow: none !important; } `; styleElement.textContent = forumCss; console.log('[BR Style] Динамические стили применены.'); } catch (e) { console.error('[BR Style] Ошибка применения динамических стилей!', e); alert(`[BR Style] Ошибка применения динамических стилей! ${e.message}`); if (styleElement) styleElement.textContent = '/* Ошибка применения динамических стилей */'; } } // --- UI Панель Настроек --- function createPanel() { console.log('[BR Style] Создание панели настроек...'); if (document.getElementById(PANEL_ID)) return document.getElementById(PANEL_ID); try { settingsPanel = document.createElement('div'); settingsPanel.id = PANEL_ID; // HTML панели остается прежним settingsPanel.innerHTML = ` <h3>🎨 Настройки Стиля (v3.3)</h3> <div class="setting-group"> <label for="s_bgImageUrl_simple">URL Фона:</label> <input type="text" id="s_bgImageUrl_simple" name="bgImageUrl" placeholder="Ссылка на картинку..."> </div> <div class="setting-group"> <label for="s_bgColor_simple">Цвет Фона Элементов:</label> <input type="color" id="s_bgColor_simple" name="bgColor"> </div> <div class="setting-group"> <label for="s_opacityValue_simple">Прозрачность Фона Элементов (0-1):</label> <input type="number" id="s_opacityValue_simple" name="opacityValue" min="0" max="1" step="0.05"> </div> <hr> <div class="setting-group"> <input type="checkbox" id="s_enableRounding_simple" name="enableRounding"> <label for="s_enableRounding_simple" class="inline-label">Включить скругление</label> <div class="sub-settings"> <label for="s_borderRadius_simple">Радиус Скругления:</label> <input type="text" id="s_borderRadius_simple" name="borderRadius" placeholder="Например: 8px, 10px"> </div> </div> <hr> <div class="setting-group"> <input type="checkbox" id="s_enableEdge_simple" name="enableEdge"> <label for="s_enableEdge_simple" class="inline-label">Цветная Окантовка</label> <div class="sub-settings"> <div> <label for="s_edgeColor_simple">Цвет Окантовки:</label> <input type="color" id="s_edgeColor_simple" name="edgeColor"> </div> <div style="margin-top: 8px;"> <label for="s_edgeWidth_simple">Толщина Окантовки:</label> <input type="text" id="s_edgeWidth_simple" name="edgeWidth" placeholder="Например: 1px, 2px"> </div> <div style="margin-top: 8px;"> <label for="s_edgeOpacity_simple">Прозрачность Окантовки (0-1):</label> <input type="number" id="s_edgeOpacity_simple" name="edgeOpacity" min="0" max="1" step="0.05"> </div> </div> </div> <div class="button-group"> <button id="save-btn-simple">Сохранить</button> <button id="close-btn-simple">Закрыть</button> </div> `; document.body.appendChild(settingsPanel); console.log('[BR Style] Панель настроек создана.'); // Логика кнопок settingsPanel.querySelector('#save-btn-simple').addEventListener('click', async () => { console.log('[BR Style] Нажата кнопка Сохранить.'); const newSettings = {}; const inputs = settingsPanel.querySelectorAll('input[name]'); inputs.forEach(input => { const key = input.name; if (defaultSettings.hasOwnProperty(key)) { if (input.type === 'checkbox') { newSettings[key] = input.checked; } else if (input.type === 'number') { newSettings[key] = parseFloat(input.value) || defaultSettings[key]; if (key === 'opacityValue' || key === 'edgeOpacity') { newSettings[key] = Math.max(0, Math.min(1, newSettings[key])); } } else { newSettings[key] = input.value; } } }); const success = await saveSettings(newSettings); if (success) { applyForumStyles(currentSettings); // Применяем динамические стили closePanel(); } }); settingsPanel.querySelector('#close-btn-simple').addEventListener('click', () => { console.log('[BR Style] Нажата кнопка Закрыть.'); closePanel(); }); return settingsPanel; } catch (e) { console.error('[BR Style] Ошибка создания панели настроек!', e); alert('[BR Style] Не удалось создать панель настроек!'); return null; } } function openPanel() { console.log('[BR Style] Открытие панели настроек...'); try { if (!settingsPanel) { settingsPanel = createPanel(); if (!settingsPanel) return; } const inputs = settingsPanel.querySelectorAll('input[name]'); inputs.forEach(input => { const key = input.name; if (currentSettings.hasOwnProperty(key)) { if (input.type === 'checkbox') { input.checked = currentSettings[key]; } else { input.value = currentSettings[key] ?? ''; } } }); settingsPanel.style.display = 'block'; console.log('[BR Style] Панель настроек открыта.'); } catch (e) { console.error('[BR Style] Ошибка открытия панели настроек!', e); alert('[BR Style] Не удалось открыть панель настроек!'); } } function closePanel() { if (settingsPanel) { settingsPanel.style.display = 'none'; console.log('[BR Style] Панель настроек закрыта.'); } } // --- Добавление HTML для верхней навигационной панели --- function addTopNavBarHTML() { console.log('[BR TopNav] Добавление HTML верхней панели...'); if (document.getElementById(TOP_NAV_ID)) return; try { const topNav = document.createElement('nav'); topNav.id = TOP_NAV_ID; topNav.className = 'br-top-nav-bar'; // --- ЗАМЕНИТЕ ЭТИ ССЫЛКИ И НАЗВАНИЯ --- const link1_href = "https://forum.blackrussia.online/"; const link1_text = "Главная Форума"; const link2_href = "https://forum.blackrussia.online/index.php?forums/%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%B0-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%BE%D0%B2.10/"; const link2_text = "Правила"; const link3_href = "https://forum.blackrussia.online/index.php?forums/%D0%96%D0%B0%D0%BB%D0%BE%D0%B1%D1%8B.14/"; const link3_text = "Жалобы"; // --------------------------------------- topNav.innerHTML = ` <a href="${link1_href}">${link1_text}</a> <a href="${link2_href}">${link2_text}</a> <a href="${link3_href}">${link3_text}</a> `; document.body.insertBefore(topNav, document.body.firstChild); console.log('[BR TopNav] HTML верхней панели добавлен.'); } catch (e) { console.error('[BR TopNav] Ошибка добавления HTML верхней панели!', e); alert('[BR TopNav] Не удалось добавить верхнюю панель навигации!'); } } // --- Внедрение Статичных CSS (Панель настроек, Верхняя панель, СВЕЧЕНИЕ ТЕКСТА) --- function injectStaticStyles() { console.log('[BR Style] Внедрение статичных CSS...'); try { const staticCss = ` /* ============ ДОБАВЛЕНО: Легкое свечение для ВСЕГО текста ============ */ * { /* Белое свечение: смещение 0 0, размытие 5px, цвет белый с 60% непрозрачностью */ /* Вы можете настроить размытие (5px) и прозрачность (0.6) */ text-shadow: 0 0 5px rgba(255, 255, 255, 0.6); /* Альтернатива: светло-серое свечение (если белый слишком яркий) */ /* text-shadow: 0 0 5px rgba(200, 200, 200, 0.5); */ } /* =================================================================== */ /* === Стили для Верхней Навигационной Панели === */ #${TOP_NAV_ID} { background-color: #222; box-shadow: 0 2px 5px rgba(0,0,0,0.3); height: ${TOP_NAV_HEIGHT}; width: 100%; position: fixed; top: 0; left: 0; z-index: 9998; display: flex; justify-content: center; align-items: center; padding: 0 15px; box-sizing: border-box; } #${TOP_NAV_ID} a { color: #eee; text-decoration: none; padding: 0 15px; font-size: 16px; font-weight: bold; line-height: ${TOP_NAV_HEIGHT}; transition: color 0.2s ease; /* Если свечение на ссылках панели мешает, раскомментируйте строку ниже */ /* text-shadow: none !important; */ } #${TOP_NAV_ID} a:hover { color: #FFEB3B; } /* === Отступ для контента из-за фиксированной верхней панели === */ .p-pageWrapper { margin-top: ${TOP_NAV_HEIGHT} !important; } /* === Стили для Панели Настроек === */ #${PANEL_ID} { position: fixed; z-index: 9999; bottom: 10px; left: 10px; width: 300px; background: #333; color: #eee; padding: 15px; border-radius: 5px; box-shadow: 0 3px 10px rgba(0,0,0,0.5); display: none; border: 1px solid #555; font-family: sans-serif; font-size: 13px; max-height: calc(100vh - 30px); overflow-y: auto; /* Отключаем глобальное свечение для текста панели настроек для лучшей читаемости */ text-shadow: none !important; } #${PANEL_ID} * { /* Убедимся, что и вложенные элементы панели не наследуют свечение */ text-shadow: none !important; } #${PANEL_ID} h3 { margin: 0 0 15px; text-align: center; font-size: 16px; border-bottom: 1px solid #555; padding-bottom: 8px;} #${PANEL_ID} div.setting-group { margin-bottom: 12px; } #${PANEL_ID} label { display: block; margin-bottom: 4px; font-weight: bold; color: #ccc; } #${PANEL_ID} input[type="text"], #${PANEL_ID} input[type="number"] { width: calc(100% - 12px); padding: 5px; background: #444; border: 1px solid #666; color: #eee; border-radius: 3px; box-sizing: border-box; } #${PANEL_ID} input[type="color"] { padding: 0; border: 1px solid #666; height: 25px; width: 35px; vertical-align: middle; margin-left: 5px; border-radius: 3px; cursor: pointer;} #${PANEL_ID} input[type="checkbox"] { vertical-align: middle; margin-right: 5px; } #${PANEL_ID} label.inline-label { display: inline; font-weight: normal; vertical-align: middle; } #${PANEL_ID} .button-group { margin-top: 15px; text-align: right; border-top: 1px solid #555; padding-top: 10px; } #${PANEL_ID} button { padding: 6px 12px; margin-left: 8px; border: none; border-radius: 3px; cursor: pointer; font-weight: bold;} #${PANEL_ID} #save-btn-simple { background-color: #4CAF50; color: white; } #${PANEL_ID} #close-btn-simple { background-color: #f44336; color: white; } #${PANEL_ID} hr { border: none; border-top: 1px solid #555; margin: 15px 0; } #${PANEL_ID} .sub-settings { margin-left: 20px; padding-left: 10px; border-left: 2px solid #555; margin-top: 8px; } `; GM_addStyle(staticCss); console.log('[BR Style] Статичные CSS внедрены (включая свечение текста).'); // Обновил лог } catch (e) { console.error('[BR Style] Ошибка внедрения статичных CSS!', e); alert('[BR Style] Ошибка внедрения статичных CSS!'); } } // --- Инициализация Скрипта --- async function initialize() { try { injectStaticStyles(); // Внедряем статичные CSS (панель, верхняя панель, ОТСТУП, СВЕЧЕНИЕ ТЕКСТА) addTopNavBarHTML(); await loadSettings(); applyForumStyles(currentSettings); // Применяем динамические стили (фон, окантовка, скругление) GM_registerMenuCommand('🎨 Настроить стиль (+Окантовка)', openPanel, 'b'); console.log('[BR Style+Border+TopNav+Glow v3.3] Инициализация завершена.'); // Обновил лог } catch (e) { console.error('[BR Style] Ошибка инициализации!', e); alert('[BR Style] Ошибка инициализации скрипта!'); } } // --- Запуск --- if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initialize); } else { initialize(); } })();