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

1
Админ
Постов: 288
2
VIP
Постов: 75
3
Элита
Постов: 62
4
Проверенные
Постов: 46
5
Проверенные
Постов: 45
6
Проверенные
Постов: 40
7
VIP
Постов: 36
8
VIP
Постов: 35

  • Страница 1 из 1
  • 1
Новый Модуль Подарков как ВК для Ucoz версия 2.0
Дата: Вторник, 06.01.2026, 04:20 | Сообщение # 1 | | Написал: Известный
Автор темы
Мурчанн не в сети
        Сообщений:288
         Регистрация: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
Поиск: