Список пользователей

1
Админ
Постов: 162
2
Элита
Постов: 45
3
VIP
Постов: 35
4
Проверенные
Постов: 31
5
Проверенные
Постов: 30
6
Пользователи
Постов: 27
7
VIP
Постов: 26
8
Пользователи
Постов: 24

  • Страница 1 из 1
  • 1
Новый Модуль Подарков как ВК для Ucoz версия 2.0
Дата: Вторник, 06.01.2026, 04:20 | Сообщение # 1 | | Написал: Узнаваемый
Автор темы
Мурчанн не в сети
        Сообщений:162
         Регистрация:20.10.2016

Создал метод получения новых данных для всплывающего окна, аналогичный тому, как это реализовано во ВКонтакте.

Суть в том, что для корректной работы скрипта необходимо заранее продумать пошаговую логику: куда скрипт должен заходить, какие данные извлекать, где и как их сохранять, куда отправлять, что запоминать, какие действия перенаправлять или выполнять с задержкой.

По сути, это почти умный алгоритм , он работает автономно, принимает решения и выполняет задачи последовательно.

Исходя из этой логики, я создал чёткую пошаговую схему, которая позволяет аккуратно извлекать данные и помещать их в наше всплывающее окно, чтобы оно выглядело аккуратно, привлекательно и органично в интерфейсе.



Этот скрипт реализует гибкую систему отображения подарков пользователя с возможностью интерактивного всплывающего окна (popup) и сохранения данных для последующего использования. Логика его работы строится на нескольких ключевых этапах:

Инициализация и глобальные переменные

Код
Скрипт создаёт ссылки на контейнеры на странице (#gifts-container и #gifts-count) и формирует уникальный ключ для локального хранилища (localStorage) на основе ID пользователя.


Код
Все подарки хранятся в массиве allGifts, что позволяет работать с ними централизованно.


Подключение стилей для всплывающего окна

Код
В скрипт динамически вставляется <style> с CSS для popup’а, списка подарков, карточек пользователей, кнопок и изображений.


Это позволяет сделать окно самодостаточным, чтобы оно выглядело аккуратно и единообразно без зависимости от внешних стилей.

Загрузка подарков (loadGifts)

Скрипт делает асинхронный запрос к серверу, получает XML-данные о подарках пользователя.

Из XML вытаскиваются все элементы, содержащие подарки, их изображения и количество.

Для каждого подарка создаются объекты с начальными данными (img, onclick, nick, avatar, date) и добавляются в массив allGifts.

Счётчик подарков (#gifts-count) обновляется динамически, показывая количество подарков.

На страницу выводятся первые 3 подарка в мини-версии.

Создание и отображение всплывающего окна (showPopup)

При клике на счётчик открывается overlay, который затем добавляет в DOM полноценное окно со списком всех подарков.

Каждому подарку соответствует карточка пользователя, включающая аватар, имя, дату и изображение подарка, а также кнопку «Отправить подарок в ответ».

Если данные уже есть в localStorage, они загружаются из кэша, что ускоряет отображение.

Динамическое обновление данных

Через setTimeout (100 мс) скрипт проходит по всем подаркам и асинхронно получает актуальные данные о пользователях, которым они были отправлены:

Извлекается имя пользователя, ссылка на профиль, дата отправки.

Дополнительно загружается аватар из профиля, если он существует.

Все обновлённые данные сохраняются в localStorage для последующего быстрого отображения без повторных запросов.

Интерактивность

Клик по счётчику открывает popup, клик по overlay или кнопке закрытия — закрывает его.

Кнопка «Отправить подарок в ответ» получает динамическую ссылку на профиль пользователя.

Универсальная логика

Скрипт построен модульно и универсально:

Можно менять контейнер, стили, URL-запросы.

Логика асинхронного получения данных и кэширования работает с любыми объектами, подобными подаркам.

Это позволяет создавать свои модели, визуальные интерфейсы или popup’ы, используя ту же основу.

Скрипт это не просто отображение подарков, а полностью автономная система, которая:

1. загружает данные асинхронно,

2. кэширует их для ускорения,

3. динамически обновляет информацию о пользователях,

4. создаёт интерактивный интерфейс,

5. остаётся универсальной основой для расширений.

По сути, это умная методика по извлечению и визуализации данных, которую можно использовать как шаблон для любых интерактивных модулей на странице.

Блок подарков

Код
<!-- ======= Блок подарков ======= -->
<div class="gifts-block">
<div class="gifts-header">Подарки</div>
<div class="gifts-footer" id="gifts-count">Загрузка…</div>
<div class="gifts-container" id="gifts-container"></div>
</div>

<style>
.gifts-block {
background: #fff;
border: 1px solid #d1d5da;
font-family: Tahoma, Arial, sans-serif;
font-size: 13px;
color: #000;
max-width: 600px;
}

.gifts-header {
background: #f0f2f5;
padding: 6px 8px;
border-bottom: 1px solid #d1d5da;
color: #45688e;
font-weight: bold;
}

.gifts-footer {
background: #f7f7f7;
border-top: 1px solid #d1d5da;
padding: 5px 8px;
color: #666;
}

.gifts-container {
display: flex;
gap: 10px;
padding: 10px 8px;
flex-direction: row-reverse; /* последние подарки справа налево */
}

.gift-card {
width: 140px;
text-align: center;
position: relative;
cursor: pointer;
}

.gift-card img {
width: 90px;
height: 90px;
border-radius: 0%;
object-fit: cover;
margin: 0 auto;
transition: .25s ease;
}

.gift-card::after {
content: '';
position: absolute;
inset: 0;
border-radius: 5%;
background: rgba(0,0,0,.25);
opacity: 0;
transition: .25s ease;
}

.gift-card:hover::after {
opacity: 0.1;
}

.vk-reply a {
    display: inline-block;
    text-decoration: none;
    color: #fff; /* белый текст */
    background: linear-gradient(
        145deg,
        #4a76a8,  /* светлый синий */
        #3f6aa0,
        #365d8c,  /* основной синий */
        #2d4b70,
        #25395a   /* темный синий */
    ); /* плавный градиент в стиле современного ВК */

    border: 1px solid #2e4a6b;
    padding: 10px 20px; /* чуть больше паддинга */
    border-radius: 50px; /* супер скругление */
    cursor: pointer;
    font-weight: 600;
    font-size: 13px;
    transition: all 0.3s ease; /* плавная анимация */
    box-shadow: 0 2px 6px rgba(0,0,0,0.2);
}

/* Hover эффект */
.vk-reply a:hover {
    background: linear-gradient(
        145deg,
        #5a88b5,
        #4d79a7,
        #3f6aa0,
        #365d8c,
        #2d4b70
    );
    box-shadow: 0 6px 12px rgba(0,0,0,0.3);
    transform: translateY(0px); /* эффект поднятия */
}

</style>

<script>
(async function(){

const container = document.getElementById('gifts-container');
const counter = document.getElementById('gifts-count');
const userId = <?$JSENCODE$($USER_ID$)?>;
const STORAGE_KEY = `giftsData_${userId}`;

let allGifts = [];

/* =======================
СТИЛИ POPUP
======================== */
const style = document.createElement('style');
style.innerHTML = `
.gifts-popup-overlay{position:fixed; inset:0; background:rgba(0,0,0,.45); display:flex; align-items:center; justify-content:center; z-index:9999;}
.gifts-popup{background:#fff; width:520px; max-height:75vh; border-radius:6px; overflow:hidden; display:flex; flex-direction:column; box-shadow:0 10px 40px rgba(0,0,0,.35); font-family:Tahoma,Arial,sans-serif;}
.gifts-popup-header{background:#f0f2f5; padding:10px 14px; font-weight:bold; color:#2a5885; border-bottom:1px solid #dce1e6; display:flex; justify-content:space-between;}
.gifts-popup-header span{cursor:pointer; font-size:18px; color:#666;}
.gifts-popup-list{padding:14px; overflow-y:auto;}
.vk-gift{padding-bottom:20px; margin-bottom:20px; border-bottom:1px solid #eee;}
.vk-user{display:flex; gap:10px; align-items:center; margin-bottom:10px;}
.vk-user img{width:40px; height:40px; border-radius:50%;}
.vk-user .name{font-weight:bold; color:#2a5885; font-size:13px;}
.vk-user .date{font-size:11px; color:#777;}
.vk-gift-img{text-align:center; margin:10px 0;}
.vk-gift-img img{max-width:240px;}
.vk-reply{text-align:center;}
.vk-reply a{
display:inline-block;
text-decoration:none;
color:#2a5885;
background:#e9eff6;
border:1px solid #c5d0db;
padding:6px 14px;
border-radius:4px;
cursor:pointer;
}
`;
document.head.appendChild(style);

/* =======================
ЗАГРУЗКА ПОДАРКОВ
======================== */
async function loadGifts(){
allGifts = [];
container.innerHTML = '';
try {
const res = await fetch(`/index/54-${userId}-`);
const text = await res.text();
const xml = new DOMParser().parseFromString(text,'application/xml');
const cmd = xml.querySelector('cmd[p="content"]');
if(!cmd){ counter.textContent='0 подарков'; return; }

const temp = document.createElement('div');
temp.innerHTML = cmd.textContent;
const tds = [...temp.querySelectorAll('td[onclick*="_uWnd.reload"]')];
if(!tds.length){ counter.textContent='0 подарков'; return; }

let total = 0;
for(const td of tds){
const img = td.querySelector('img');
if(!img) continue;

const count = td.querySelector('b') ? +td.querySelector('b').textContent || 1 : 1;
total += count;
const onclick = td.getAttribute('onclick');

for(let i=0;i<count;i++){
allGifts.push({
img: img.src,
onclick,
nick: 'Загрузка...',
avatar: '/.s/src/profile/img/profile_photo_thumbnail.png',
date: ''
});
}
}

counter.textContent = total + (total===1 ? ' подарок' : total<5 ? ' подарка' : ' подарков');

// первые 3 подарка на странице
allGifts.slice(0,3).forEach(g=>{
const div = document.createElement('div');
div.className = 'gift-card';
div.innerHTML = `<img src="${g.img}" alt="">`;
container.appendChild(div);
});

} catch(e){
console.error(e);
counter.textContent = 'Ошибка загрузки';
}
}

/* =======================
POPUP
======================== */
async function showPopup(){
if(!allGifts.length) return;

const overlay = document.createElement('div');
overlay.className = 'gifts-popup-overlay';

const popup = document.createElement('div');
popup.className = 'gifts-popup';
popup.innerHTML = `
<div class="gifts-popup-header">
Мои подарки
<span>×</span>
</div>
<div class="gifts-popup-list"></div>
`;
popup.querySelector('span').onclick = ()=>overlay.remove();
overlay.appendChild(popup);
document.body.appendChild(overlay);
overlay.onclick = e=>{ if(e.target===overlay) overlay.remove(); };

const list = popup.querySelector('.gifts-popup-list');

let cached = localStorage.getItem(STORAGE_KEY);
cached = cached ? JSON.parse(cached) : [];

allGifts.forEach((g, idx)=>{
const saved = cached[idx];
if(saved){
g.nick = saved.nick;
g.avatar = saved.avatar;
g.date = saved.date;
}
const div = document.createElement('div');
div.className = 'vk-gift';
div.innerHTML = `
<div class="vk-user">
<img src="${g.avatar}">
<div>
<div class="name">${g.nick}</div>
<div class="date">${g.date}</div>
</div>
</div>
<div class="vk-gift-img">
<img src="${g.img}">
</div>
<div class="vk-reply">
<a href="#">🎁 Отправить подарок в ответ</a>
</div>
`;
list.appendChild(div);
});

setTimeout(async ()=>{
const newData = [];
for(const [idx,g] of allGifts.entries()){
try{
const urlMatch = g.onclick.match(/url:'([^']+)'/);
if(!urlMatch) continue;
const giftPage = await fetch(urlMatch[1]).then(r=>r.text());
const giftDoc = new DOMParser().parseFromString(giftPage,'text/html');
const legend = giftDoc.querySelector('legend a');
const nick = legend ? legend.textContent.trim() : 'Пользователь';
const profile = legend ? legend.href : '#';
const date = giftDoc.querySelector('div[style*="text-align:right"]')?.textContent.trim() || '';
let avatar = '/.s/src/profile/img/profile_photo_thumbnail.png';
if(profile!=='#'){
try{
const prof = await fetch(profile).then(r=>r.text());
const pdoc = new DOMParser().parseFromString(prof,'text/html');
const photoDiv = pdoc.querySelector('.profile-photo');
if(photoDiv){
const bg = photoDiv.style.backgroundImage;
if(bg && bg!=='none'){
avatar = bg.replace(/^url\(["']?|["']?\)$/g,'');
}
}
}catch(e){}
}

newData.push({nick, avatar, date});
const giftDiv = list.children[idx];
giftDiv.querySelector('.name').textContent = nick;
giftDiv.querySelector('.date').textContent = date;
giftDiv.querySelector('.vk-user img').src = avatar;
giftDiv.querySelector('.vk-reply a').href = profile;

}catch(e){}
}
localStorage.setItem(STORAGE_KEY, JSON.stringify(newData));
}, 100);
}

counter.style.cursor='pointer';
counter.onclick = showPopup;

loadGifts();

})();
</script>


Основная ценность заключается не просто в коде, а в методике и продуманной логике.

Именно она позволяет создавать гибкие и масштабируемые решения. Возможно, именно вы сможете развить этот подход и сделать его ещё более эффективным.

Моя задача заложить фундамент и показать направление, от которого можно отталкиваться при дальнейшей разработке.

Совершенствуйте... 2

Мурчанн

Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.
  • Страница 1 из 1
  • 1
Поиск: