<!-- Начало: Универсальный скрипт замены © Merlin777 kuban.mybb.ru -->
<script>
document.addEventListener("DOMContentLoaded", function () {
// =========================
// 📦 CONFIG — Настройки
// =========================
const CONFIG = {
observerDelay: 0, // ⏳ Задержка обновления элементов (0 = requestAnimationFrame для максимально плавного обновления)
// ✅ Разрешить покраску ников на главной странице сайта (в статистике)
enableIndexNickColoring: true,
// 🔤 Автозамены текста в профиле, кнопках и мини-профиле
replacements: {
profileElements: [
['.pl-email.profile', 'Профиль', '👤Профиль'], // Заменяем текст "Профиль" на с эмодзи
['.pl-email.email', 'E-mail', '📧Mail'], // "E-mail" → "📧Mail"
['.pl-email.pm', 'ЛС', '✉️\u00A0ЛС'], // "ЛС" → "✉️ ЛС"
['.pl-website.website', 'Вебсайт', '🌐'] // "Вебсайт" → "🌐"
],
postButtons: [
['.pl-edit a', 'Редактировать', '✍️\u00A0Редактировать'], // Кнопка редактирования
['.pl-delete a', 'Удалить', '❌\u00A0Удалить'], // Кнопка удаления
['.pl-quote a', 'Цитировать', '💬\u00A0Цитировать'], // Кнопка цитирования
['.pl-reply a', 'Ответить', '↩️\u00A0Ответить'], // Кнопка ответа
['.pa-posts', 'Сообщений', '📨 Сообщений'], // Кол-во сообщений с эмодзи
],
miniProfile: [
['.pa-ip', 'IP', '🖧 IP'], // IP пользователя
['.pa-sex', 'Пол', '⚧️ Пол'], // Пол с эмодзи
['.pa-fld3', 'Создано тем', '➕ Создано тем'], // Кол-во созданных тем
['.fld-name', 'Откуда', '🧭 Откуда'], // Местоположение
['.pa-respect', 'Уважение', '⭐ Рейтинг'] // Рейтинг
]
},
// 🎨 Селекторы мини-профиля для перекраски
miniProfileSelectors: ["li.pa-title","li.pa-fld1"],
// 🎨 Цвета ников по группам (основной и ховер)
groupColors: {
1: ['#008080','#a1b2cc'], // 🛡️ Админ
2: ['#993232','#d15f13'], // 🧑⚖️ Модератор
3: ['#000000','#B0B0B0'], // 👤 Гость (черный с серым ховером)
4: ['#072387','#5869a3'] // 🧙♂️ Пользователь (темно-синий с светло-синим ховером)
},
// 🎨 Цвета для мини-профиля по именам
miniProfileColors: {
"Модератор": { color: ['#38761d','#6abd46'], groups: [2] }, // Зеленый оттенок
"Администратор": { color: ['#5c1eba','#a1b2cc'], groups: [1] }, // Фиолетовый оттенок
"The Wizard of the Realm": { color: ['#2986cc','#a1b2cc'], groups: [1] } // Синий
}
};
// =========================
// 💬 CSS hover — плавное изменение цвета при наведении
// =========================
const style = document.createElement('style');
style.innerHTML = 'a[data-base-color], span[data-base]{transition: color 0.25s ease; cursor:pointer;}';
document.head.appendChild(style);
// =========================
// 🔄 Функция автозамены текста
// =========================
function ChangeAll(scope=document){
// Объединяем все массивы автозамен
[].concat(CONFIG.replacements.profileElements,
CONFIG.replacements.postButtons,
CONFIG.replacements.miniProfile).forEach(function(r){
var sel = r[0], from = r[1], to = r[2];
// Находим элементы, которые еще не заменены
scope.querySelectorAll(sel+':not([data-replaced])').forEach(function(el){
if(el.innerHTML.indexOf(from) !== -1) el.innerHTML = el.innerHTML.replaceAll(from,to);
el.dataset.replaced = 'true'; // Помечаем элемент как обработанный
});
});
}
// =========================
// 🎨 Покраска ников в постах
// =========================
function recolorPostNicks(users, scope = document) {
const userMap = {};
users.forEach(u => {
if (u.username) userMap[u.username.trim().toLowerCase()] = parseInt(u.group_id);
});
// 🧱 Общая функция покраски по элементу
function colorNick(el, username) {
const group_id = userMap[username.toLowerCase()] || 4; // default group
const colors = CONFIG.groupColors[group_id];
if (!colors) return;
el.style.color = colors[0];
el.dataset.baseColor = colors[0];
el.dataset.hoverColor = colors[1] || colors[0];
}
// 🎯 1. Ники в постах
scope.querySelectorAll('.post a[href^="javascript:to("]').forEach(el => {
if (el.closest('.quote-box, .dropdown, #pun-navlinks, .vote-list, .user-menu')) return;
const username = el.textContent.trim();
colorNick(el, username);
});
// 🏠 2. Ники на главной (например, в #onlinelist)
if (CONFIG.enableIndexNickColoring && document.getElementById('onlinelist')) {
document.querySelectorAll('#onlinelist a[href*="profile.php"]').forEach(el => {
const username = el.textContent.trim();
colorNick(el, username);
});
}
}
// =========================
// 🎨 Покраска мини-профиля
// =========================
function recolorMiniProfile(scope=document){
CONFIG.miniProfileSelectors.forEach(function(sel){
scope.querySelectorAll(sel).forEach(function(el){
if(el.dataset.mpRecolored) return; // Уже перекрашен
let html = el.innerHTML;
Object.entries(CONFIG.miniProfileColors).forEach(function([name,obj]){
const [base,hover] = obj.color;
if(html.includes(name)){
// Заменяем текст на span с цветами
html = html.replace(name,
'<span data-base="'+base+'" data-hover="'+hover+'" style="font-weight:bold;color:'+base+';">'+name+'</span>'
);
}
});
el.innerHTML = html;
el.dataset.mpRecolored = 'true'; // Отмечаем как обработанный
});
});
}
// =========================
// 🎨 Универсальная перекраска всего (посты + мини-профиль)
// =========================
function recolorAll(scope=document){
recolorPostNicks(JSON.parse(localStorage.getItem('UsersAdmList')?.split('|')[1] || '[]'), scope);
recolorMiniProfile(scope);
}
// =========================
// 🌐 Получение пользователей через API
// =========================
function fetchUsersAndRecolor(force=false, scope=document){
var key='UsersAdmList';
var now=Math.floor(Date.now()/1000);
var cached=localStorage.getItem(key);
if(cached && !force){
try{
var arr=cached.split('|');
if((now-parseInt(arr[0]))<24*3600){ // ⏱ кеш на 24 часа
recolorAll(scope);
return;
}
}catch(e){console.warn(e);}
}
// Запрос через API
fetch('/api.php',{
method:'POST',
headers:{'Content-Type':'application/x-www-form-urlencoded'},
body:new URLSearchParams({method:'users.get',limit:'500',fields:'user_id,username,group_id'})
}).then(r=>r.json()).then(function(data){
if(data?.response?.users){
var users=data.response.users;
localStorage.setItem(key,now+'|'+JSON.stringify(users)); // Сохраняем кеш
recolorAll(scope);
}
}).catch(console.error);
}
// =========================
// 👆 Hover — меняем цвет при наведении
// =========================
document.body.addEventListener('mouseover',function(e){
var el = e.target.closest('span[data-base], a[data-base-color]');
if(el) el.style.color = el.dataset.hoverColor || el.dataset.hover || el.style.color;
});
document.body.addEventListener('mouseout',function(e){
var el = e.target.closest('span[data-base], a[data-base-color]');
if(el) el.style.color = el.dataset.baseColor || el.dataset.base || el.style.color;
});
// =========================
// ⏳ Планирование обновления через requestAnimationFrame или setTimeout
// =========================
let scheduled = false;
function scheduleUpdate(){
if(scheduled) return;
scheduled = true;
if(CONFIG.observerDelay === 0){
requestAnimationFrame(()=>{ ChangeAll(); recolorAll(); scheduled=false; });
} else {
setTimeout(()=>{ ChangeAll(); recolorAll(); scheduled=false; }, CONFIG.observerDelay);
}
}
// =========================
// 👁 MutationObserver — следим за изменениями DOM и автоматически перекрашиваем новые элементы
// =========================
const observer = new MutationObserver(()=>scheduleUpdate());
observer.observe(document.body,{childList:true,subtree:true});
// =========================
// ▶ Инициализация при загрузке страницы
// =========================
ChangeAll();
fetchUsersAndRecolor();
// =========================
// 🆕 Live-подгрузка новых постов
// =========================
document.addEventListener('pun_post',function(e){
var scope = e.detail?.post || document.body;
ChangeAll(scope);
fetchUsersAndRecolor(true, scope); // форсируем обновление при новых постах
});
});
</script>
<!-- Конец: Универсальный скрипт замены © Merlin777 kuban.mybb.ru -->