Дата: Среда, 18.02.2026, 02:52 | Сообщение # 1 |
|
Написал: Узнаваемый
Автор темы
Мурчанн
не в сети
Сообщений: 211
Приветствую, уважаемый читатель! Обычно этот раздел остается без внимания: для многих он кажется чем-то непонятным, почти как китайская грамота. Но на самом деле здесь скрыта настоящая увлекательность , ведь так интересно создавать что-то своими руками. Возможно, платформа Юкоз не является самым очевидным выбором для подобных экспериментов, но именно в этом и заключается настоящий вызов. Обычно никакая статистика по шаблонам ВКонтакте не ведётся там просто нет разделов, к которым был бы доступ. Да, существует целый блок с информацией о том, какие пользователи онлайн, и, вероятно, на Юкозе можно реализовать что-то подобное. Все необходимые переменные для этого уже есть, так что мы будем двигаться в этом направлении и кастомизировать функционал. Проблема лишь в том, что мне приходится делать всё в одиночку у меня нет команды разработчиков, которая могла бы ускорить процесс. Иначе за месяц или два можно было бы создать уникальный шаблон, подобный ВКонтакте.В общем, создал небольшой блок статистики , скорее в стиле Юкоза, но, как мне кажется, даже минимальная статистика необходима. Она позволяет наглядно оценить посещаемость сайта , очень удобная вещь. HTML блок ... Код
<!-- Статистика --> <div class="vk-info"> <div class="vk-info-head"> <!-- ИКОНКА АВАТАР (через ссылку) --> <span class="vk-avatar"> <img src="https://www.svgrepo.com/show/509003/avatar-thinking-6.svg" alt="avatar"> </span> <div class="vk-info-title">Echo LinkUp</div> </div> <div class="vk-info-desc"> Социальная платформа общения, обмена контентом и связи между пользователями. </div> <div class="vk-info-badge"> <span class="vk-icon vk-star"></span> Социальная сеть нового поколения </div> <div class="vk-info-meta"> <span class="vk-icon vk-link"></span> Работает на $POWERED_BY$ </div> <!-- ===== НИЖНЯЯ СТАТИСТИКА ===== --> <div class="vk-info-stats"> <div class="vk-online-count"> 🟢 Сейчас онлайн: $ONLINE_COUNTER$ чел. </div> <div class="vk-online-users"> <strong>Активные пользователи:</strong> $ONLINE_USERS_LIST$ </div> <div class="vk-today"> 📅 Сегодня: $DATE$ | Время: $TIME$ </div> </div> </div> <!-- Статистика -->
Полностью главная страница каталога статей: Код
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>BRO Account</title> <link rel="stylesheet" href="/css/bro-style.css" media="all"> </head> <body> <!-- МЕНЮ --> <div class="header"> <div class="header-inner"> <a href="/" class="logo">Echo <span class="logo-box">LinkUp</span></a> <form class="vk-search" action="/search" method="get"> <span class="vk-search-icon"></span> <input type="text" name="q" placeholder="Поиск" /> </form> <!-- Колокольчик и всплывающее окно --> <div class="vk-alerts" id="vkAlerts"> <!-- КОЛОКОЛ --> <div class="vk-bell" id="vkBell"> <svg viewBox="0 0 24 24"> <path d="M12 22a2 2 0 0 0 2-2h-4a2 2 0 0 0 2 2zm6-6V11a6 6 0 1 0-12 0v5l-2 2v1h16v-1l-2-2z"/> </svg> <div class="vk-bell-count" id="vkBellCount">2</div> </div> <!-- ВСПЛЫВАЮЩЕЕ ОКНО --> <div class="vk-alerts-wrap" id="vkPopup"> <!-- ХВОСТИК --> <div class="vk-alert-tail"></div> <!-- ОКНО --> <div class="vk-alerts-win" id="vkPopupContent"> <!-- СТАТИЧЕСКИЕ БЛОКИ (БЕЗ СКРОЛЛА) --> <?if(!$USER_LOGGED_IN$)?> <div class="vk-alert-item"> <div class="vk-alert-title">Вы не авторизованы</div> <div class="vk-alert-text">Присоединяйтесь к сообществу 🙂</div> <a class="vk-alert-link" href="$LOGIN_LINK$">Авторизация</a> </div> <?endif?> <div class="vk-alert-item vk-alert-vacancy"> <div class="vk-alert-title">👉 Вакансии</div> <div class="vk-alert-text">Требуется контент-менеджер</div> <a class="vk-alert-link" href="#">Смотреть вакансии</a> </div> <!-- ЕДИНСТВЕННЫЙ СКРОЛЛ --> <div class="vk-alert-pm-wrap" id="vkAlertPMs"> <!-- JS добавляет сюда сообщения --> </div> </div> </div> </div> <script> const bell = document.getElementById("vkBell"); const popup = document.getElementById("vkPopup"); const pmWrap = document.getElementById("vkAlertPMs"); const bellCount = document.getElementById("vkBellCount"); const CHECK_DELAY = 15000; const DEFAULT_AVA = "/files/person.png"; const RECIPIENT = "<?=$USER_NAME$?>"; // открыть / закрыть bell.addEventListener("click", e => { e.stopPropagation(); popup.classList.toggle("active"); }); document.addEventListener("click", e => { if (!document.getElementById("vkAlerts").contains(e.target)) { popup.classList.remove("active"); } }); // аватар async function fetchAvatar(profileUrl){ if(!profileUrl) return DEFAULT_AVA; try{ const html = await fetch(profileUrl + "?r=" + Math.random()).then(r=>r.text()); const div = document.createElement("div"); div.innerHTML = html; const bg = div.querySelector(".profile-photo")?.style.backgroundImage || ""; const m = bg.match(/url\(['"]?(.*?)['"]?\)/i); return m ? m[1] : DEFAULT_AVA; }catch(e){ return DEFAULT_AVA; } } <?if($USER_LOGGED_IN$)?> async function checkPM(){ try{ pmWrap.innerHTML = ""; // === 1. Статические уведомления, кроме вакансий === const staticItems = document.querySelectorAll("#vkPopupContent > .vk-alert-item:not(.vk-alert-pm):not(.vk-alert-vacancy)"); let staticCount = 0; staticItems.forEach(item => { const clone = item.cloneNode(true); pmWrap.appendChild(clone); staticCount++; }); // === 2. Динамические непрочитанные сообщения === const html = await fetch("/index/14?" + Math.random()).then(r=>r.text()); const div = document.createElement("div"); div.innerHTML = html; const unread = div.querySelectorAll("b.unread"); for(const b of unread){ const row = b.closest("tr, li, div"); // ник const nickLink = row.querySelector("a[href*='/index/8-0-']"); const sender = nickLink ? nickLink.textContent.trim() : "Пользователь"; // ссылка на ЛС let pmLink = row.querySelector("a[href*='/index/14']") || row.querySelector("a[href*='read']") || null; let href = pmLink ? pmLink.getAttribute("href") : "/index/14"; if(href.startsWith("/")) href = location.origin + href; const avatar = await fetchAvatar(nickLink?.href); const title = b.textContent.trim(); let description = "Пришло новое сообщение. Можно прочитать чуть позже."; if(title.includes("Предложение дружбы")){ description = `Пользователь «${sender}» добавил вас в друзья.`; } else if(title.includes("Новый подарок") || title.includes("Новая награда")){ description = `Пользователь «${sender}» сделал вам подарок.`; } else if(title.includes("Изменен уровень замечаний")){ description = `Здравствуйте, ${RECIPIENT}. Пользователь «${sender}» изменил вам уровень замечаний.`; } const pmDiv = document.createElement("div"); pmDiv.className = "vk-alert-pm vk-alert-item"; pmDiv.innerHTML = ` <img src="${avatar}"> <div> <div class="pm-nick">${title}</div> <div style="font-size:12px;color:#555">${description}</div> </div> `; pmDiv.onclick = () => location.href = href; pmWrap.appendChild(pmDiv); } // === 3. Обновляем колокольчик === // учитываем вакансию + статические блоки + динамические const vacancyCount = document.querySelectorAll("#vkPopupContent > .vk-alert-vacancy").length; bellCount.textContent = vacancyCount + staticCount + unread.length; }catch(e){ console.warn("Ошибка уведомлений", e); } setTimeout(checkPM, CHECK_DELAY); } checkPM(); <?endif?> <?if(!$USER_LOGGED_IN$)?> setInterval(()=>{ bell.classList.add("shake"); setTimeout(()=>bell.classList.remove("shake"), 500); }, 5000); <?endif?> </script> <?if($USER_LOGGED_IN$)?> <style> /* ======= СТИЛЬ СТАРОГО ВК ======= */ /* ======= OLD VK STYLE REWORK ======= */ .vk-notify{ position:fixed; right:20px; bottom:20px; width:300px; font-family:Tahoma, Arial, sans-serif; font-size:12px; border-radius:8px; overflow:hidden; display:none; z-index:9999; background:#e9edf3; box-shadow:0 8px 22px rgba(0,0,0,0.25); transition:all .25s ease; } /* ===== ШАПКА ===== */ .vk-notify-header{ background:linear-gradient(#5b84b6,#4a76a8); color:#fff; padding:9px 10px; font-weight:bold; cursor:pointer; display:flex; justify-content:space-between; align-items:center; border-bottom:1px solid rgba(0,0,0,0.15); } .vk-notify-header b{ background:#fff; color:#4a76a8; border-radius:50px; padding:1px 7px; font-weight:bold; box-shadow:0 1px 2px rgba(0,0,0,0.2); } #vkNotifyToggle{ background:none; border:none; color:#fff; font-size:12px; cursor:pointer; opacity:.85; transition:.15s; } #vkNotifyToggle:hover{ opacity:1; transform:scale(1.1); } /* ===== ТЕЛО ===== */ .vk-notify-body{ max-height:365px; overflow-y:auto; background:#f0f3f7; padding:4px; } /* СКРОЛЛ */ .vk-notify-body::-webkit-scrollbar{ width:6px; } .vk-notify-body::-webkit-scrollbar-thumb{ background:#c7ced8; border-radius:10px; } .vk-notify-body::-webkit-scrollbar-track{ background:transparent; } /* ===== СООБЩЕНИЕ ===== */ .vk-item{ display:flex; align-items:center; gap:8px; padding:8px 10px; margin:4px 2px; cursor:pointer; /* форма: слева капсула, справа почти ровно */ border-radius:10px 10px 8px 10px; /* мягкий светлый желтый */ background:linear-gradient(#fffbe6,#fff3b0); border:1px solid #eadf9b; /* объём */ box-shadow: inset 0 1px 0 rgba(255,255,255,0.75), 0 1px 2px rgba(0,0,0,0.08); transition:all .15s ease; } /* HOVER — мягкий old VK */ .vk-item:hover{ background:linear-gradient(#fff7c9,#ffe88c); border-color:#e2d276; box-shadow: inset 0 1px 0 rgba(255,255,255,0.85), 0 2px 5px rgba(0,0,0,0.12); transform:translateY(-1px); } /* HOVER как в старом VK */ .vk-item:hover{ background:linear-gradient(#fff7c9,#ffe88c); border-color:#e2d276; box-shadow: inset 0 1px 0 rgba(255,255,255,0.8), 0 2px 5px rgba(0,0,0,0.12); transform:translateY(-1px); } /* АВАТАР */ .vk-item img{ width:42px; height:42px; border-radius:50%; object-fit:cover; border:1px solid #cfd6e0; background:#fff; box-shadow:0 1px 2px rgba(0,0,0,0.2); } /* ТЕКСТ */ .vk-item-title{ font-weight:bold; color:#2a5885; margin-bottom:1px; } .vk-item-text{ color:#111; font-size:13px; line-height:1.25; } .vk-item-date{ color:#7c8796; font-size:11px; margin-top:2px; } .vk-notify-empty{ padding:12px; text-align:center; color:#6f7b8c; } /* ===== СВЕРНУТО ===== */ .vk-notify.collapsed .vk-notify-body{ max-height:0 !important; padding:0 !important; overflow:hidden; } </style> <div id="vkNotifyPanel" class="vk-notify"> <div class="vk-notify-header"> <span>Личные сообщения <b id="vkNotifyBadge">0</b></span> <button id="vkNotifyToggle">—</button> </div> <div class="vk-notify-body"> <div class="vk-notify-empty">Загрузка сообщений...</div> </div> </div> <script> window.friends = window.friends || {}; (function ($, friends) { const DEFAULT_AVA = "/files/person.png"; const CHECK_DELAY = 20000; const STORAGE_KEY = "vkNotifyCollapsed"; const avatarCache = {}; const panel = $("#vkNotifyPanel"); const body = panel.find(".vk-notify-body"); const badge = $("#vkNotifyBadge"); const toggleBtn = $("#vkNotifyToggle"); /* ================= СОСТОЯНИЕ ПАНЕЛИ ================= */ function setCollapsed(state){ if(state){ panel.addClass("collapsed").removeClass("expanded"); toggleBtn.text("+"); localStorage.setItem(STORAGE_KEY, "1"); }else{ panel.removeClass("collapsed").addClass("expanded"); toggleBtn.text("—"); localStorage.setItem(STORAGE_KEY, "0"); } } setCollapsed(localStorage.getItem(STORAGE_KEY) === "1"); toggleBtn.on("click", function(e){ e.stopPropagation(); setCollapsed(!panel.hasClass("collapsed")); }); panel.find(".vk-notify-header").on("click", function(e){ if($(e.target).is("#vkNotifyToggle")) return; toggleBtn.click(); }); /* ================= ПОЛУЧЕНИЕ АВАТАРА (С КЭШЕМ) ================= */ async function fetchAvatar(profileUrl){ if(!profileUrl) return DEFAULT_AVA; if(avatarCache[profileUrl]) return avatarCache[profileUrl]; try{ const html = await $.get(profileUrl + "?r=" + Math.random()); const bg = $(html).find(".profile-photo").first().css("background-image") || ""; const m = bg.match(/url\(['"]?(.*?)['"]?\)/i); avatarCache[profileUrl] = m ? m[1] : DEFAULT_AVA; return avatarCache[profileUrl]; }catch(e){ return DEFAULT_AVA; } } /* ================= ЗАГРУЗКА СООБЩЕНИЙ ================= */ async function loadMessages(){ try{ const html = await $.get("/index/14?" + Math.random()); const $dom = $("<div>").append($.parseHTML(html)); const $msgs = $dom.find("b.unread"); badge.text($msgs.length); if($msgs.length === 0){ panel.fadeOut(200); body.html('<div class="vk-notify-empty">Нет новых сообщений</div>'); return; } panel.fadeIn(200); const oldScroll = body.scrollTop(); const atBottom = body[0].scrollHeight - body.innerHeight() - oldScroll < 15; body.empty(); for(const el of $msgs.toArray()){ const $msg = $(el); const $row = $msg.closest("tr, li, div"); const title = $msg.text().trim() || "Новое сообщение"; const $nick = $row.find("a[href*='/index/8-0-']").last(); let sender = $nick.text().trim() || "Пользователь"; let profile = $nick.attr("href"); if(profile && profile.startsWith("/")) profile = location.origin + profile; const avatar = await fetchAvatar(profile); const dateText = $row.find("td:nth-child(3), .message-date, time") .first().text().trim() || ""; const link = $msg.parent().attr("href") || "#"; body.append(` <div class="vk-item" onclick="window.location.href='${link}'"> <img src="${avatar}" onerror="this.src='${DEFAULT_AVA}'"> <div> <div class="vk-item-title">${sender}</div> <div class="vk-item-text">${title}</div> <div class="vk-item-date">${dateText}</div> </div> </div> `); } /* сохраняем позицию скролла */ if(atBottom){ body.scrollTop(body[0].scrollHeight); }else{ body.scrollTop(oldScroll); } }catch(e){ console.error("PM Load Error:", e); body.html('<div class="vk-notify-empty">Ошибка загрузки</div>'); } } /* ================= АВТО ОБНОВЛЕНИЕ ================= */ friends.checkPm = function(){ loadMessages(); setTimeout(friends.checkPm, CHECK_DELAY); }; friends.checkPm(); })(jQuery, window.friends); </script> <?else?> <!-- Гости ничего не видят --> <?endif?> <?if(!$USER_LOGGED_IN$)?> <div class="buttons-row"> <a href="$LOGIN_LINK$" class="btn btn-login">Войти</a> <a href="/index/3" class="btn btn-join">Присоединиться</a> </div> <?endif?> <?if($USER_LOGGED_IN$)?> <div class="nav-cta-wrapper"> <div class="nav-cta"> <!-- Пользователь --> <div class="user-box" id="userMenu"> <!-- НИК (слева, как в старом ВК) --> <span class="user-name">$USERNAME$</span> <!-- Аватар --> <img src="$USER_AVATAR_URL$" alt="$USERNAME$" class="user-avatar real-avatar" onerror="this.style.display='none'; this.nextElementSibling.style.display='block';"> <!-- Дефолтный аватар --> <img src="/.s/src/profile/img/profile_photo_thumbnail.png" alt="default" class="user-avatar default-avatar" style="display:none;"> <!-- Выпадающее меню --> <div class="user-dropdown"> <div class="user-dropdown-header"> <span class="username">$USERNAME$</span> </div> <a href="/index/14" class="dropdown-item icon-messages">Личные сообщения</a> <a href="/index/11" class="dropdown-item icon-settings">Настройки</a> <a href="/index/8" class="dropdown-item icon-profile">Моя страница</a> <a href="/index/15" class="dropdown-item icon-users">Пользователи</a> <div class="dropdown-separator"></div> <a href="$LOGOUT_LINK$" class="dropdown-item icon-logout logout">Выход</a> </div> </div> </div> </div> <script> document.addEventListener("click", function (e) { const userBox = document.getElementById("userMenu"); if (!userBox) return; if (userBox.contains(e.target)) { userBox.classList.toggle("active"); } else { userBox.classList.remove("active"); } }); </script> <?endif?> </div> </div> </div> </div> </div> <!-- КОНТЕНТ --> <div class="container"> <!-- Левая колонка --> <div class=""> $GLOBAL_MENU$ </div> <!-- Центральная колонка --> <div class="center-col"> <div class="cover block"> <img src="https://bro.usite.pro/m0.jpg" alt="cover"> </div> <div class="center-small block"> <!-- Аватар --> <div class="profile-header-bg"> <?if($USER_LOGGED_IN$)?> <div class="profile-photo" style="background-image: url('<?if($USER_AVATAR_URL$)?><?$USER_AVATAR_URL$?><?else?>https://bro.usite.pro/icon/p1_3004531_da07dd0f.jpg<?endif?>');"> </div> <?else?> <div class="profile-photo" style="background-image: url('/.s/src/profile/img/profile_photo_thumbnail.png');"> </div> <?endif?> </div> <!-- Информация профиля --> <div class="profile-info"> <!-- Ник --> <div class="profile-name-main"> <?if($USER_FULL_NAME$)?><h1 class="username"><a href="$PERSONAL_PAGE_LINK$">$USER_FULL_NAME$</a></h1> <?else?><h1 class="username"><a href="$PERSONAL_PAGE_LINK$">$USERNAME$</a></h1><?endif?> </div> <style> /* Контейнер подписи + города */ .profile-signature-wrapper { display: flex; flex-direction: column; justify-content: flex-start; /* подпись сверху */ position: relative; min-height: 70px; /* минимальная высота блока, чтобы город был ниже */ margin-top: -4px; /* поднимаем контейнер чуть выше */ padding-bottom: -10px; /* отступ снизу для города */ } /* Подпись */ .profile-signature-main { font-size: 14px; color: #6d7885; line-height: 1.4; } /* Город — всегда фиксирован снизу */ .profile-city-main { display: flex; align-items: center; position: absolute; bottom: 0; /* всегда снизу */ left: 0; gap: 4px; font-size: 15px; color: #666; } .profile-city-main svg { display: block; vertical-align: middle; color: #666; width: 20px; height: 20px; } </style> <!-- Подпись --> <div class="profile-signature-wrapper"> <!-- Подпись --> <div class="profile-signature-main" id="profileSignature" style="display:none;"> <span class="signature-text-main"></span> </div> <!-- Город --> <div class="profile-city-main" id="profileCity" style="display:none;"> <span class="city-icon-main vk-place-icon-main"> <svg aria-hidden="true" viewBox="0 0 20 20"> <g fill="none" fill-rule="evenodd"> <path d="M0 0h20v20H0z" opacity=".4"></path> <path fill="currentColor" fill-rule="nonzero" d="M10 1c4.148 0 7.5 3.433 7.5 7.5 0 2.85-1.843 6.172-5.435 10.095a2.8 2.8 0 0 1-4.13 0C4.343 14.672 2.5 11.35 2.5 8.5 2.5 4.433 5.852 1 10 1m0 1.5c-3.382 0-6 2.825-6 6q0 3.574 5.041 9.082a1.3 1.3 0 0 0 1.918 0Q15.999 12.075 16 8.5c0-3.175-2.618-6-6-6M10 5a3.5 3.5 0 1 1-.001 7.001A3.5 3.5 0 0 1 10 5m0 1.5a2 2 0 1 0 .001 4.001A2 2 0 0 0 10 6.5"></path> </g> </svg> </span> <span class="city-text-main"></span> </div> </div> </div> <script src="https://bro.usite.pro/js/signature.js"></script> <script> document.addEventListener("DOMContentLoaded", function () { var userId = "$USER_ID$"; if (!userId || userId === "0") return; var PROFILE_URL = "/index/8-" + userId; var MAX_LETTERS = 121; /* ===== KEYS ===== */ var SIG_KEY = "usig_" + userId; var SIG_HASH = "usig_hash_" + userId; var CITY_KEY = "ucity_" + userId; var CITY_HASH = "ucity_hash_" + userId; /* ===== 1. ПЕРВОЕ ОТОБРАЖЕНИЕ ИЗ КЭША ===== */ var cachedSig = localStorage.getItem(SIG_KEY); if (cachedSig) renderSignature(cachedSig); else renderSignature("У пользователя пока нет подписи. Добавьте немного информации о себе в профиле, чтобы она отображалась здесь."); // если кэша нет — выводим заглушку var cachedCity = localStorage.getItem(CITY_KEY); if (cachedCity) renderCity(cachedCity); /* ===== 2. ТИХАЯ ПРОВЕРКА ПРОФИЛЯ ===== */ fetch(PROFILE_URL, { credentials: "same-origin" }) .then(r => r.text()) .then(html => { var doc = new DOMParser().parseFromString(html, "text/html"); /* --- ПОДПИСЬ --- */ var newSig = extractSignature(doc); if (!newSig) { newSig = "У пользователя пока нет подписи. Добавьте немного информации о себе в профиле, чтобы она отображалась здесь."; // если подписи нет, задаём стандарт localStorage.removeItem(SIG_HASH); // очищаем старый хеш localStorage.setItem(SIG_KEY, newSig); } var sigHashNew = makeHash(newSig); var sigHashOld = localStorage.getItem(SIG_HASH); if (sigHashNew !== sigHashOld) { localStorage.setItem(SIG_KEY, newSig); localStorage.setItem(SIG_HASH, sigHashNew); renderSignature(newSig); } /* --- ГОРОД --- */ var newCity = extractCity(doc); if (newCity) { var cityHashNew = makeHash(newCity); var cityHashOld = localStorage.getItem(CITY_HASH); if (cityHashNew !== cityHashOld) { localStorage.setItem(CITY_KEY, newCity); localStorage.setItem(CITY_HASH, cityHashNew); renderCity(newCity); } } }) .catch(() => {}); /* ===== ПАРСЕРЫ ===== */ function extractSignature(doc) { var sig = ""; doc.querySelectorAll(".profile-section").forEach(section => { var title = section.querySelector(".profile-section-name"); if (title && title.textContent.trim() === "Подпись (о себе)") { var content = section.querySelector(".profile-section-content"); if (content) sig = content.textContent.trim(); } }); return sig; } function extractCity(doc) { var city = ""; doc.querySelectorAll(".profile-row").forEach(row => { var name = row.querySelector(".profile-row-name"); if (name && name.textContent.trim() === "Город:") { var content = row.querySelector(".profile-row-content"); if (content) city = content.textContent.trim(); } }); return city; } /* ===== РЕНДЕР ===== */ function renderSignature(sig) { if (sig.length > MAX_LETTERS) { sig = sig.slice(0, MAX_LETTERS) + "…"; } var el = document.getElementById("profileSignature"); if (!el) return; el.querySelector(".signature-text-main").textContent = sig; el.style.display = "block"; } function renderCity(city) { var el = document.getElementById("profileCity"); if (!el) return; el.querySelector(".city-text-main").textContent = city; el.style.display = "flex"; } /* ===== HASH ===== */ function makeHash(str) { var hash = 0; for (var i = 0; i < str.length; i++) { hash = ((hash << 5) - hash) + str.charCodeAt(i); hash |= 0; } return hash.toString(); } }); </script> <!-- ОБЕРТКА ВСЕГО САЙТА --> <div id="siteWrapper" style="position: relative; max-width: 1200px; margin: 0 auto; background: #f5f5f5; min-height: 100vh;"> <!-- Кнопка "Send Message" --> <a href="javascript:void(0);" id="openArticleForm" style=" position: absolute; right: -450px; top: 50%; background: #3b5998; color: #fff; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif; font-size: 14px; font-weight: 500; padding: 11px 30px; border-radius: 8px 0 0 8px; text-decoration: none; box-shadow: 0 6px 16px rgba(76,117,163,0.45); transition: all 0.3s ease; z-index: 9999; " onmouseover=" this.style.background='#3f6691'; this.style.paddingRight='115px'; this.style.boxShadow='0 10px 24px rgba(76,117,163,0.55)'; " onmouseout=" this.style.background='#3b5998'; this.style.paddingRight='30px'; this.style.boxShadow='0 6px 16px rgba(76,117,163,0.45)'; " > 💬 Send Message </a> </div> <!-- показываем только авторизованным --> <?if($USER_ID$>0)?> <!-- POPUP Overlay --> <div id="publOverlay" style=" position: fixed; inset: 0; background: rgba(0,0,0,.6); display: none; align-items: center; justify-content: center; z-index: 999999; "> <div id="publModal" style=" width: 500px; background: #fff; border-radius: 5px; transform: translateX(100%); transition: transform 0.3s ease; "> <div class="publHeader" style=" background: #4c75a3; color: #fff; padding: 14px; display: flex; justify-content: space-between; "> Закрепить пост на стене <span id="closePubl" style="cursor:pointer;">✖</span> </div> <!-- СТАТУС СООБЩЕНИЯ ВВЕРХУ --> <div id="p_status"></div> <div class="publBody" style="padding:14px;"> <label>Заголовок *</label> <input type="text" id="p_title"> <label>Категория *</label> <select id="p_cat"> <option value="1">Стена</option> </select> <link rel="stylesheet" href="/css/vk-pubmodal.css" media="all"> <!-- ===== Краткое описание с кнопкой смайлов ===== --> <div class="publBody" style="padding:0px; position: relative; margin-bottom:10px;"> <script type="text/javascript" src="https://bro.usite.pro/js/bbcodes.js"></script> <!-- Панель BB-кодов --> <div class="ucoz-editor-bbpanel" style="margin-bottom:5px;"> <!-- Основные стили --> <input type="button" value="B" title="Bold" onclick="simpletag('b','','','p_brief','')" /> <input type="button" value="I" title="Italic" onclick="simpletag('i','','','p_brief','')" /> <input type="button" value="U" title="Underline" onclick="simpletag('u','','','p_brief','')" /> <input type="button" value="URL" title="URL" onclick="tag_url('p_brief','')" /> <input type="button" value="IMG" title="Image" onclick="tag_image('p_brief','')" /> <input type="button" value="List" title="List" onclick="tag_list('p_brief','')" /> <input type="button" value="Hide" title="Hide from Guest" onclick="simpletag('hide','','','p_brief','')" /> <!-- Выравнивание текста --> <input type="button" value="Left" title="Влево" onclick="simpletag('l','','','p_brief','')" /> <input type="button" value="Center" title="По центру" onclick="simpletag('c','','','p_brief','')" /> <input type="button" value="Right" title="Вправо" onclick="simpletag('r','','','p_brief','')" /> </div> <label>Краткое описание *</label> <textarea id="p_brief" style="height:100px; width:475px; padding-right:5px;"></textarea> <!-- Кнопка смайлов --> <button type="button" id="emojiBtnBrief" style=" position: absolute; right: 15px; top: 220px; /* позиция кнопки по высоте textarea */ width: 28px; height: 28px; background: #f5f5f5; border: 1px solid #ccc; border-radius: 50%; cursor: pointer; font-size: 16px; display: flex; align-items: center; justify-content: center; ">😊</button> <!-- Панель смайлов --> <div id="emojiPanelBrief" style=" position: absolute; right: 0; top: 10px; width: 220px; max-height: 250px; overflow-y: auto; background: #fff; border: 1px solid #ccc; border-radius: 6px; display: none; padding: 5px; box-shadow: 0 5px 15px rgba(0,0,0,0.2); z-index: 10000; display: flex; flex-wrap: wrap; gap: 4px; "> <!-- Сюда скрипт вставит все смайлы --> </div> </div> <script> $(document).ready(function(){ const textareaBrief = $('#p_brief'); const emojiBtnBrief = $('#emojiBtnBrief'); const emojiPanelBrief = $('#emojiPanelBrief'); // массив смайлов (юкоЗовские стандартные) const emojis = [ '😀','😁','😂','🤣','😃','😄','😅','😆','😉','😊','😋','😎','😍','😘', '😗','😙','😚','🙂','🤗','🤩','🤔','🤨','😐','😑','😶','🙄','😏','😣', '😥','😮','🤐','😯','😪','😫','🥱','😴','😌','😛','😜','😝','🤤','😒', '😓','😔','😕','🙃','🤑','😲','☹️','🙁','😖','😞','😟','😤','😢','😭', '😦','😧','😨','😩','🤯','😬','😰','😱','🥵','🥶','😳','🤪','😵','🥴','😠','😡' ]; // добавляем смайлы в панель emojis.forEach(e=>{ emojiPanelBrief.append(`<span class="emojiItem" style="cursor:pointer; font-size:16px;">${e}</span>`); }); // показать/скрыть панель emojiBtnBrief.on('click', function(e){ e.stopPropagation(); emojiPanelBrief.toggle(); }); // клик по смайлу — вставка emojiPanelBrief.on('click', '.emojiItem', function(){ const emoji = $(this).text(); const start = textareaBrief[0].selectionStart; const end = textareaBrief[0].selectionEnd; const text = textareaBrief.val(); textareaBrief.val(text.substring(0,start) + emoji + text.substring(end)); textareaBrief[0].selectionStart = textareaBrief[0].selectionEnd = start + emoji.length; textareaBrief.focus(); }); // закрываем панель, если клик вне $(document).on('click', function(e){ if(!$(e.target).closest('#emojiPanelBrief, #emojiBtnBrief').length){ emojiPanelBrief.hide(); } }); }); </script> <!-- ===== Кнопка для показа текстовой статьи ===== --> <div class="publBody" style="padding:0px; position: relative; margin-bottom:10px;"> <button type="button" id="toggleTextBtn" style=" background: #4c75a3; color: #fff; border: none; border-radius: 60px; padding: 10px 14px; font-weight: 600; cursor: pointer; transition: all 0.25s ease; ">Добавить текст статьи</button> <!-- Поле текст статьи (скрыто по умолчанию) --> <div id="textContainer" style="display:none; position: relative; margin-top:10px;"> <label>Текст статьи</label> <textarea id="p_text" style="height:100px; width:475px; padding-right:5px;"></textarea> <!-- Кнопка смайлов --> <button type="button" id="emojiBtn" style=" position: absolute; right: 5px; top: 95px; width: 28px; height: 28px; background: #f5f5f5; border: 1px solid #ccc; border-radius: 50%; cursor: pointer; font-size: 16px; display: flex; align-items: center; justify-content: center; ">😊</button> <!-- Панель смайлов --> <div id="emojiPanel" style=" position: absolute; right: 0; top: 10px; width: 220px; max-height: 250px; overflow-y: auto; background: #fff; border: 1px solid #ccc; border-radius: 6px; display: none; padding: 5px; box-shadow: 0 5px 15px rgba(0,0,0,0.2); z-index: 10000; display: flex; flex-wrap: wrap; gap: 4px; "> <!-- Сюда скрипт вставит все смайлы --> </div> </div> </div> <script> $(document).ready(function(){ const textContainer = $('#textContainer'); const toggleTextBtn = $('#toggleTextBtn'); // Показать/скрыть поле текст статьи toggleTextBtn.on('click', function(){ textContainer.toggle(); if(textContainer.is(':visible')){ $(this).text('Скрыть текст статьи'); } else { $(this).text('Добавить текст статьи'); } }); const textarea = $('#p_text'); const emojiBtn = $('#emojiBtn'); const emojiPanel = $('#emojiPanel'); // массив смайлов (юкоЗовские стандартные) const emojis = [ '😀','😁','😂','🤣','😃','😄','😅','😆','😉','😊','😋','😎','😍','😘', '😗','😙','😚','🙂','🤗','🤩','🤔','🤨','😐','😑','😶','🙄','😏','😣', '😥','😮','🤐','😯','😪','😫','🥱','😴','😌','😛','😜','😝','🤤','😒', '😓','😔','😕','🙃','🤑','😲','☹️','🙁','😖','😞','😟','😤','😢','😭', '😦','😧','😨','😩','🤯','😬','😰','😱','🥵','🥶','😳','🤪','😵','🥴','😠','😡' ]; // добавляем смайлы в панель emojis.forEach(e=>{ emojiPanel.append(`<span class="emojiItem" style="cursor:pointer; font-size:16px;">${e}</span>`); }); // показать/скрыть панель смайлов emojiBtn.on('click', function(e){ e.stopPropagation(); emojiPanel.toggle(); }); // клик по смайлу — вставка emojiPanel.on('click', '.emojiItem', function(){ const emoji = $(this).text(); const start = textarea[0].selectionStart; const end = textarea[0].selectionEnd; const text = textarea.val(); textarea.val(text.substring(0,start) + emoji + text.substring(end)); textarea[0].selectionStart = textarea[0].selectionEnd = start + emoji.length; textarea.focus(); }); // закрываем панель, если клик вне $(document).on('click', function(e){ if(!$(e.target).closest('#emojiPanel, #emojiBtn').length){ emojiPanel.hide(); } }); }); </script> <button id="p_send">Создать запись</button> </div> </div> </div> <?endif?> <!-- для перехвата ssid --> <iframe id="ssidFrame" src="/publ/1-0-0-0-1" style="display:none;"></iframe> <script src="https://bro.usite.pro/js/ssid_ucodes.js"></script> </div> <div class="bottom-row"> <!-- Лента новостей --> <!-- Основной контейнер с материалами --> <div id="ajaxBody"> <!-- ===== ПЕРВЫЙ БЛОК (только для авторизованных) ===== --> <?if($USER_ID$)?> <div class="vk-modern-post1"> <div class="vk-photos-header"> <span class="vk-photos-title">Мои фотографии</span> <span class="vk-photos-count" id="vkPhotosCount">0</span> </div> $GLOBAL_BILD$ <style> /* Контейнер кнопок справа */ .bro-actions { position: absolute; right: 10px; top: 14%; transform: translateY(-50%); display: flex; gap: 8px; z-index: 10; } /* Кнопка в стиле ВК */ .bro-action-btn { width: 24px; height: 24px; border-radius: 15%; background: transparent; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color 0.15s ease, transform 0.12s ease; } .bro-action-btn:hover { background: rgba(42, 88, 133, 0.12); /* VK blue hover */ transform: scale(1.08); } .bro-action-btn:active { transform: scale(0.95); } /* Иконки — как в ВК */ .bro-icon { width: 25px; height: 25px; fill: none; stroke: #2a5885; stroke-width: 1.8; opacity: 0.85; transition: stroke 0.15s ease, opacity 0.15s ease; } .bro-action-btn:hover .bro-icon { stroke: #1d5fd1; opacity: 1; } </style> <!-- Кнопки справа --> <div class="bro-actions"> <a href="/photo/0-1-0-17-$USER_ID$" class="bro-action-btn" aria-label="Просмотры"> <svg class="bro-icon bro-icon-eye" viewBox="0 0 24 24"> <path d="M12 5C7 5 3 9 1.5 12 3 15 7 19 12 19s9-4 10.5-7C21 9 17 5 12 5zm0 11a4 4 0 1 1 0-8 4 4 0 0 1 0 8z"/> </svg> </a> <a href="/photo/0-0-0-1-2" class="bro-action-btn" aria-label="Скачать всё"> <svg class="bro-icon bro-icon-download" viewBox="0 0 24 24"> <path d="M12 3v10m0 0 4-4m-4 4-4-4M5 21h14"/> </svg> </a> </div> </div> <?endif?> <?if($USER_ID$==0)?> <style> /* ===== ДЛЯ ГОСТЕЙ ===== */ /* Скрываем блок фотографий */ .vk-modern-post1 { display: none; /* полностью скрыт */ } /* Убираем место под блок */ #ajaxBody::before { height: 0px; } </style> <?endif?> <!-- ===== ВТОРОЙ БЛОК ===== --> <div class="vk-post-anchor vk-post-anchor-2"></div> <div class="vk-modern-post2"> <div class="vk-create-post-wrapper"> <!-- Кнопка по центру --> <a href="/publ/1-0-0-0-1" class="vk-btn-create"> <span class="vk-icon">+</span> <span class="vk-text">Создать пост</span> </a> <!-- Кнопки справа --> <div class="vk-btn-right-group"> <a href="/video/viadd" class="vk-btn-icon" aria-label="Клип"> <span class="vk-icon">🎞️</span> </a> <a href="/photo/0-0-0-1-2" class="vk-btn-icon" aria-label="Статья"> <span class="vk-icon">🖼️</span> </a> <a href="/publ/1-0-0-0-1" class="vk-btn-icon" aria-label="Статья"> <span class="vk-icon">📝</span> </a> </div> </div> </div> $BODY$ </div> <!-- Скрытая пагинация --> <div id="selector" style="display:none;"> $PAGE_SELECTOR$ </div> <script src="https://bro.usite.pro/js/ajaxfotonew.js"></script> <!-- Правая колонка (липкая) --> <div class="right-col blockbro"> <div class="right-sticky-limit"> <div class="">$GLOBAL_BRO$</div> <div class="">$GLOBAL_SUBSCRIBE$</div> <div class="">$GLOBAL_TODAY$</div> <div class="">$GLOBAL_MPG$</div> <!-- Статистика --> <div class="vk-info"> <div class="vk-info-head"> <!-- ИКОНКА АВАТАР (через ссылку) --> <span class="vk-avatar"> <img src="https://www.svgrepo.com/show/509003/avatar-thinking-6.svg" alt="avatar"> </span> <div class="vk-info-title">Echo LinkUp</div> </div> <div class="vk-info-desc"> Социальная платформа общения, обмена контентом и связи между пользователями. </div> <div class="vk-info-badge"> <span class="vk-icon vk-star"></span> Социальная сеть нового поколения </div> <div class="vk-info-meta"> <span class="vk-icon vk-link"></span> Работает на $POWERED_BY$ </div> <!-- ===== НИЖНЯЯ СТАТИСТИКА ===== --> <div class="vk-info-stats"> <div class="vk-online-count"> 🟢 Сейчас онлайн: $ONLINE_COUNTER$ чел. </div> <div class="vk-online-users"> <strong>Активные пользователи:</strong> $ONLINE_USERS_LIST$ </div> <div class="vk-today"> 📅 Сегодня: $DATE$ | Время: $TIME$ </div> </div> </div> <!-- Статистика --> </div> </div> </div> </div> </div> </body> </html>
Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.