Дата: Воскресенье, 15.02.2026, 06:15 | Сообщение # 1 |
|
Написал: Узнаваемый
Автор темы
Мурчанн
не в сети
Сообщений: 211
Скрипты изначально создавались для каталога статей на Юкозе. Если вы хотите использовать их в другом модуле, придётся внести некоторые правки вручную, так как отправка данных на сервер настроена именно под каталог статей. Но для тех, кто знаком с платформой, это сделать достаточно просто достаточно адаптировать под свои нужды. В этой теме я лишь демонстрирую возможности Юкоза и показываю, что это принципиально возможно. Логика работы скриптов полностью прозрачна: как только вы откроете их, сразу станет понятно, что аналогичные решения можно реализовать под любой модуль. В этот раз я внес некоторые улучшения: аватарка теперь расположена сверху слева, форма комментариев справа, а кнопка режима «невидимки» находится внизу справа. В скрипт добавлены дополнительные функции: при отправке теперь отображается информация о сеансе отправки или ошибка, если скрипт вдруг перестанет работать. То есть были внесены именно улучшения для удобства и контроля. Видео с демонстрацией будет ниже тестируем всё в реальном времени, чтобы потом никто не мог сказать, что это «мусор» и не работает.Вид материалов Каталог статей Код
<!-- ЛЕНТА НОВОСТЕЙ --> <link rel="stylesheet" href="https://bro.usite.pro/css/bro-anon.css" media="all"> <div class="vk-modern-feed"> <div class="vk-modern-post"> <!-- HEADER --> <div class="vk-modern-header"> <div class="vk-modern-avatar"> <?if($AVATAR_URL$)?><img src="$AVATAR_URL$" alt="$USERNAME$"><?else?><img src="/.s/img/avatar.png"><?endif?> </div> <div class="vk-modern-author"> <div class="vk-modern-name"><a href="$PROFILE_URL$">$USERNAME$</a></div> <div class="vk-modern-time" title="$TIME$"> <img src="https://bro.usite.pro/icon/clock-icon.png" alt="Дата публикации" height="22"> <span>$DATE$</span> </div> </div> <?if($MODER_PANEL$)?><div class="entry-moder-container">$MODER_PANEL$</div><?endif?> <style> /* Скрываем стандартный toggle и шестерёнку */ .u-mpanel-toggle { width: 1px !important; height: 1px !important; opacity: 0 !important; overflow: hidden !important; position: relative; } .custom-edit-btn { display: inline-block; font-size: 16px; font-weight: bold; cursor: pointer; color: #888; /* серый цвет, как в ВК */ user-select: none; position: relative; padding: 2px 6px; transition: color 0.2s; } .custom-edit-btn:hover { color: #555; /* чуть темнее при наведении */ } </style> <script> document.addEventListener('DOMContentLoaded', function() { document.querySelectorAll('.u-mpanel').forEach(panel => { // Проверяем, есть ли уже кнопка if(panel.querySelector('.custom-edit-btn')) return; // Создаём кнопку с тремя точками const btn = document.createElement('div'); btn.className = 'custom-edit-btn'; btn.textContent = '•••'; panel.prepend(btn); // вставляем сверху панели // Клик по кнопке: вызываем стандартный toggle панели btn.addEventListener('click', e => { e.stopPropagation(); const toggle = panel.querySelector('.u-mpanel-toggle'); if(toggle) toggle.click(); // вызывает оригинальный модер панель }); }); }); </script> </div> <!-- TEXT --> <?if($MESSAGE$)?><div class="vk-modern-text"> <div class="post" data-id="$ID$">$MESSAGE$</div> </div><?endif?> <!-- IMAGE --> <?if($COVER_IMAGE$)?><div class="vk-modern-attach"> <picture> <source srcset="$COVER_SMALL_URL$" media="(min-width:769px)"> <img src="$COVER_URL$" alt="$TITLE$" loading="lazy"> </picture> </div><?endif?> <!-- ACTIONS --> <div class="vk-modern-actions"> <div class="vk-actions-left"> <div class="vk-like" data-entryid="$ID$"> <span class="likeHeart" title="Поставить лайк"></span> <span class="uLikeCount">$RATED$</span> </div> <style> /* Контейнер лайка */ .vk-like { display: inline-flex; align-items: center; gap: 6px; font-family: Arial, sans-serif; } /* Сердечко ВК с обводкой */ .likeHeart { cursor: pointer; font-size: 26px; transition: transform 0.2s ease; user-select: none; } .likeHeart::before { content: "❤"; color: #fff; /* белое сердечко */ text-shadow: 0 0 1px #999, /* лёгкая серая обводка */ 0 0 2px #999, /* увеличиваем толщину */ 0 0 3px #999; /* ещё толще */ transition: color 0.3s ease, text-shadow 0.3s ease, transform 0.3s ease; } /* Hover эффект */ .likeHeart:hover::before { color: #ff4d4d; /* красное при наведении */ text-shadow: 0 0 2px #ff9999, 0 0 3px #ff9999, 0 0 4px #ff9999; transform: scale(1.2); } /* Состояние "лайк поставлен" */ .likeHeart.liked::before { color: #ff0000; /* красное сердечко */ text-shadow: none; /* без обводки */ transform: scale(1.1); } /* Счётчик лайков */ .uLikeCount { font-size: 14px; color: #626d7a; user-select: none; } </style> <script> (function() { const likeBlocks = document.querySelectorAll('.vk-like'); let votedPosts = JSON.parse(localStorage.getItem('votedPosts') || '[]'); likeBlocks.forEach(block => { const entryID = parseInt(block.dataset.entryid); const heart = block.querySelector('.likeHeart'); const likeCount = block.querySelector('.uLikeCount'); if (votedPosts.includes(entryID)) { heart.classList.add('liked'); } heart.addEventListener('click', function() { if (heart.classList.contains('liked')) return; heart.classList.add('liked'); votedPosts.push(entryID); localStorage.setItem('votedPosts', JSON.stringify(votedPosts)); if (likeCount) { likeCount.textContent = parseInt(likeCount.textContent || '0') + 1; } _uPostForm('', { type: 'POST', url: '/publ', data: { a: 65, id: entryID, mark: 5, mod: 'publ', ajax: '2' } }); }); }); })(); </script> <!-- COMMENTS --> <?if($COMMENTS_URL$)?> <a class="vk-action" href="$COMMENTS_URL$"> <svg viewBox="0 0 24 24"> <path d="M21 6h-18v10h4v4l4-4h10z"/> </svg> <span>$COMMENTS_NUM$</span> </a> <?endif?> <!-- READS --> <div class="vk-action"> <button class="vkShareBtn" onclick="vkShare(event)" aria-label="Поделиться" title="Поделиться"> <span class="vkShareRipple"></span> <svg viewBox="0 0 24 24" class="vkShareIcon"> <path d="M11.996 3.725A2.15 2.15 0 0 0 10 5.87l-.001 2.117-.02.005a9.904 9.904 0 0 0-7.827 10.721c.083.811 1.116 1.103 1.611.455l.187-.237a9.08 9.08 0 0 1 5.836-3.265l.213-.026.001 2.494a2.15 2.15 0 0 0 3.476 1.692l7.824-6.132a2.15 2.15 0 0 0 0-3.384l-7.824-6.132a2.15 2.15 0 0 0-1.326-.458z" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> <script> function vkShare(e){ const btn = e.currentTarget; const url = location.href; // ripple const rect = btn.getBoundingClientRect(); const ripple = btn.querySelector('.vkShareRipple'); ripple.style.left = (e.clientX - rect.left) + 'px'; ripple.style.top = (e.clientY - rect.top) + 'px'; ripple.classList.remove('show'); void ripple.offsetWidth; ripple.classList.add('show'); // share if (navigator.share) { navigator.share({ url }); } else { window.open('https://vk.com/share.php?url=' + encodeURIComponent(url),'_blank'); } } </script> <style> .vkShareBtn{ position:relative; display:inline-flex; align-items:center; justify-content:center; width:24px; height:24px; padding:0; border:none; background:none; cursor:pointer; color:#666666; /* обычный серый */ -webkit-tap-highlight-color: transparent; outline:none; transition:color .15s ease, transform .12s ease; --vkShareOffsetX: 0px; /* смещение по умолчанию */ } .vkShareIcon{ width:20px; height:20px; display:block; pointer-events:none; transform: translateX(var(--vkShareOffsetX)); } /* hover: делаем обводку темнее */ .vkShareBtn:hover{ color:#222222; /* насыщенный тёмный для контраста */ } /* active (нажатие) */ .vkShareBtn:active{ transform:scale(0.92); } /* focus */ .vkShareBtn:focus-visible{ box-shadow:0 0 0 2px rgba(71,132,255,.35); border-radius:6px; } /* ripple */ .vkShareRipple{ position:absolute; width:6px; height:6px; background:rgba(0,0,0,.15); /* более мягкий ripple */ border-radius:50%; transform:translate(-50%,-50%) scale(0); pointer-events:none; } .vkShareRipple.show{ animation:vkRipple .45s ease-out; } @keyframes vkRipple{ to{ transform:translate(-50%,-50%) scale(8); opacity:0; } } </style> </div> </div> <!-- Контейнер для просмотров --> <a class="vkViewBtn" href="$ENTRY_URL$" title="Перейти к новости"> <!-- Иконка глаза --> <svg viewBox="0 0 24 24" class="vkViewIcon" width="20" height="20"> <path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <circle cx="12" cy="12" r="3" fill="currentColor"/> </svg> <!-- Количество просмотров --> <span class="vkViewCount"> $READS$ </span> </a> <style> .vkViewBtn{ display:inline-flex; align-items:center; gap:5px; /* расстояние между глазиком и числом */ color:#666666; /* цвет иконки и текста */ text-decoration:none; font-size:14px; cursor:pointer; transition:color .15s ease, transform .12s ease; --vkViewOffsetX: -4px; /* смещение по умолчанию */ transform: translateX(var(--vkViewOffsetX)); } .vkViewBtn:hover{ color:#222222; /* при наведении цвет темнее */ } .vkViewIcon{ display:block; width:20px; height:20px; stroke:currentColor; fill:currentColor; } </style> </div> <style> /* Старая ВК форма - компактная */ .vk-add-form { margin: 0px; /* убрали все внешние отступы */ padding: 10px; /* минимальные внутренние отступы */ background: #f0f2f5; border-radius: 3px; font-size: 12px; /* размер шрифта внутри формы */ } /* Текстовое поле */ .vk-textarea { padding: 8px; /* внутренние отступы текста внутри textarea */ margin-bottom: 6px; /* расстояние от текстового поля до кнопки */ border-radius: 6px; min-height: 50px; resize: both; /* уголок для растягивания */ border: 1px solid #ddd; overflow: auto; } /* collapsed вид (форма закрыта) */ .vk-add-form .collapsed { padding: 2px; cursor: text; color: #65676b; } /* раскрытая форма */ .vk-add-form .expanded textarea.vk-textarea { width: 100%; min-height: 50px; border: 0; border-radius: 6px; padding: 4px; resize: none; outline: none; } /* Кнопка отправки - стиль ВК */ .vk-add-form .vkSendBtn { padding: 4px 12px; min-width: 80px; max-width: 150px; border-radius: 4px; background: #4c75a3; color: #fff; border: none; cursor: pointer; font-weight: 500; font-size: 13px; transition: all 0.2s ease; position: relative; overflow: hidden; } /* Hover эффект - чуть светлее и плавное поднятие */ .vk-add-form .vkSendBtn:hover { background: #5a85b3; transform: translateY(0px); box-shadow: 0 4px 8px rgba(0,0,0,0.15); } /* Active / клик - нажатие кнопки */ .vk-add-form .vkSendBtn:active { background: #466d93; transform: translateY(0px); box-shadow: 0 2px 4px rgba(0,0,0,0.2); } /* Ripple эффект при клике (как ВК) */ .vk-add-form .vkSendBtn::after { content: ""; position: absolute; left: 50%; top: 50%; width: 0; height: 0; background: rgba(255,255,255,0.3); border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.4s ease, height 0.4s ease, opacity 0.6s ease; pointer-events: none; opacity: 0; } .vk-add-form .vkSendBtn:active::after { width: 120%; height: 300%; opacity: 1; transition: 0s; } /* статус отправки */ .vk-add-form .vkStatus { margin: 0; color: green; font-size: 11px; } /* уведомление об успешной отправке */ #vkSuccessMsg { position: fixed; top: 80px; right: 20px; background: linear-gradient(135deg, #4a76a8, #5b8bd5); color: #fff; padding: 12px 20px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.25); z-index: 9999; opacity: 0; transition: all 0.5s ease; } #vkSuccessMsg.show { opacity: 1; } </style> <!-- Форма комментариев --> <div class="vk-add-form"> <div class="collapsed">Что у Вас нового?</div> <div class="expanded" style="display:none;"> <!-- Аватар + поле --> <div class="vk-input-row"> <img class="vk-avatar" src="/avatar/00/00/00107456.png"> <textarea class="vk-textarea" placeholder="Напишите комментарий..."></textarea> </div> <!-- Кнопка + статус + анонимность --> <div class="vk-actions-row"> <div class="vk-left-group"> <button class="vkSendBtn">Отправить</button> <span class="vkStatus"></span> </div> <label class="vk-anon-wrapper" title="Анонимно"> <svg class="vk-anon-icon"> <use xlink:href="/.s/t/2301/icons/icons.svg#incognito_icon"></use> </svg> <input type="checkbox" class="vkAnon" hidden> </label> </div> <span class="vkStatus"></span> </div> </div> </div> </div> <iframe id="commentFrame" style="width:0;height:0;border:0;position:absolute;left:-9999px;"></iframe> <!-- Уведомление --> <div id="vkSuccessMsg"> <div class="vk-icon1">✉️</div> <div>Ваш комментарий успешно отправлен! <span class="vk-heart">💙</span></div> </div> <style> /* --- Форма комментариев --- */ .vk-add-form { margin-top: 8px; padding: 6px; background: #f0f2f5; border-radius: 4px; font-size: 12px; } /* Скрытая collapsed форма */ .collapsed { color: #65676b; cursor: text; } /* Ряд с аватаркой и текстовым полем */ .vk-input-row { display: flex; gap: 6px; align-items: flex-start; } .vk-avatar { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; } .vk-textarea { flex: 1; min-height: 50px; border-radius: 6px; padding: 6px; resize: both; /* уголок для растягивания */ border: 1px solid #ddd; overflow: auto; } /* Ряд кнопок */ .vk-actions-row { display: flex; align-items: center; position: relative; margin-top: 4px; } /* Левая кнопка "Отправить" */ .vkSendBtn { padding: 4px 12px; min-width: 80px; max-width: 150px; border-radius: 4px; background: #4c75a3; color: #fff; border: none; cursor: pointer; flex-shrink: 0; /* Пододвигаем вправо */ position: relative; left: 35px; /* меняй это значение чтобы двигать вправо/влево */ } /* Левая группа: кнопка и статус */ .vk-left-group { display: flex; align-items: center; gap: 50px; /* <-- расстояние между кнопкой и текстом */ } /* Статус справа от кнопки */ .vkStatus { font-size: 11px; color: green; white-space: nowrap; margin-left: 50px; /* <-- чтобы сдвигать текст вправо */ } /* Правая кнопка "Анонимно" */ .vk-anon-wrapper { cursor: pointer; display: flex; align-items: center; margin-left: auto; /* прижимаем к правому краю */ } .vk-anon-icon { width: 26px; height: 26px; fill: #ccd0d5; transition: 0.2s; } .vk-anon-wrapper.active .vk-anon-icon { fill: #4a76a8; transform: scale(1.1); } /* Пуш уведомление */ #vkSuccessMsg { position: fixed; top: 90px; right: 20px; width: 300px; background: linear-gradient(135deg,#4a76a8,#5b8bd5); color: #fff; padding: 14px 16px 14px 60px; border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,.25); display: flex; align-items: center; opacity: 0; transform: translateY(-10px); transition: .3s; z-index: 9999; } #vkSuccessMsg.show { opacity: 1; transform: none; } .vk-icon1 { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); } .vk-heart { color: #4595ff; } </style> <script> document.querySelectorAll('.vk-modern-post').forEach(post => { const collapsed = post.querySelector('.vk-add-form .collapsed'); const expanded = post.querySelector('.vk-add-form .expanded'); const textarea = expanded.querySelector('.vk-textarea'); const sendBtn = expanded.querySelector('.vkSendBtn'); const status = expanded.querySelector('.vkStatus'); const anonCheck = expanded.querySelector('.vkAnon'); const anonWrapper = expanded.querySelector('.vk-anon-wrapper'); const iframe = document.getElementById('commentFrame'); const successMsg = document.getElementById('vkSuccessMsg'); // Связь кнопки анонимности с checkbox anonWrapper.addEventListener('click', () => { anonCheck.checked = !anonCheck.checked; anonWrapper.classList.toggle('active', anonCheck.checked); }); // открыть форму collapsed.addEventListener('click', () => { collapsed.style.display = 'none'; expanded.style.display = 'block'; textarea.focus(); }); // закрыть если клик вне document.addEventListener('click', e => { if(!post.contains(e.target)){ collapsed.style.display = 'block'; expanded.style.display = 'none'; } }); // отправка комментария sendBtn.addEventListener('click', () => { const msg = textarea.value.trim(); if(!msg) return; status.textContent = 'Идёт отправка....'; const postId = post.querySelector('.post').dataset.id; iframe.src = `/publ/1-1-0-${postId}`; iframe.onload = () => { try { const doc = iframe.contentDocument; const w = iframe.contentWindow; const form = doc.getElementById('acform'); if(!form){ status.textContent = 'Форма не найдена'; return; } const msgField = form.querySelector('textarea[name="message"]'); if(msgField) msgField.value = msg; if(anonCheck.checked){ const realAnon = form.querySelector('input[name="anonymous"]'); if(realAnon){ realAnon.checked = true; realAnon.dispatchEvent(new Event('change', {bubbles:true})); } const uid = form.querySelector('input[name="user_id"]'); if(uid) uid.value = ''; const email = form.querySelector('input[name="email"]'); if(email) email.value = ''; } if(typeof w.addcom === 'function'){ w.addcom(form); } else { form.submit(); } // Очистка формы status.textContent = ''; textarea.value = ''; collapsed.style.display = 'block'; expanded.style.display = 'none'; // Показ уведомления if(successMsg){ successMsg.classList.add('show'); const heart = successMsg.querySelector('.vk-heart'); if(heart){ heart.style.opacity = 1; heart.style.animation = 'heartPop 0.5s ease forwards'; setTimeout(()=>{ heart.style.animation=''; heart.style.opacity=0; },500); } setTimeout(()=>{ successMsg.classList.remove('show'); },3000); } } catch(e){ console.error(e); status.textContent = 'Ошибка отправки'; } }; }); }); </script>
Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.