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

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

  • Страница 1 из 1
  • 1
Отображения фотографий пользователя на главной странице uCoz
Дата: Суббота, 10.01.2026, 17:24 | Сообщение # 1 | | Написал: Узнаваемый
Автор темы
Мурчанн не в сети
        Сообщений:162
         Регистрация:20.10.2016

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

Структура подключения

Код
<div id="user-photos"></div>


Контейнер, в который динамически подгружаются фотографии либо сообщение «фото отсутствуют».



Общий принцип работы

1. Скрипт выполняется сразу после загрузки страницы и работает по следующей логике:

2. Определяет ID пользователя и ссылку на его профиль

3. Проверяет наличие актуального кэша в localStorage

4. Если кэш свежий — мгновенно отображает данные

5. Если кэша нет или он устарел:

6. загружает страницу профиля

7. находит ссылку на фотоальбом

8. получает превью фотографий

9. сохраняет данные в кэш

10. отображает результат

Определение пользователя

Код
const userId = "$USER_ID$" || '0';
const profileUrl = "$PERSONAL_PAGE_LINK$";


$USER_ID$ — ID текущего пользователя

$PERSONAL_PAGE_LINK$ — ссылка на страницу профиля

Если пользователь не авторизован — скрипт не выполняется.

Кэширование (LocalStorage)

Используются ключи:

Код
user_photos_v3_<userId>
user_photos_v3_<userId>_time


Срок жизни кэша: 24 часа

Код
const CACHE_DURATION_MS = 24 * 60 * 60 * 1000;


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

Мгновенный показ кэша

1. Сначала скрипт пытается показать сохранённые данные:

2. если кэш существует

3. если он не старше 24 часов

Запросы к серверу не выполняются

Код
renderPhotos(photos);
return;


Это даёт:

1. быстрый рендер

2. отсутствие «миганий»

3. экономию ресурсов

Загрузка данных с профиля

Если кэш отсутствует или устарел:

1. Загружается HTML страницы профиля

2. Ищется ссылка вида:

Код
Фото (12)


Извлекается:

1. ссылка на альбом

2. общее количество фото

Количество фото сразу сохраняется и отображается в счётчике.

Загрузка фотографий из альбома

Из страницы альбома:

1. выбираются карточки .photo-entry-card

2. берутся изображения / _ph /

3. сохраняются:

JS
Код
{ src, link }


Максимум выводится 4 фотографии.

Отрисовка фотографий

Если фото есть:

1. создаётся сетка карточек

2. плавная загрузка изображений

3. hover-эффект (scale)

4. клик ведёт на оригинальную запись / тему

Если фото нет:

1. Отображается аккуратный блок:

2. «Пока здесь нет фотографий»
с предложением добавить их в фотоальбом

Детали

1. Удаление hash и query из URL
2. Защита от ошибок старого кэша
3. Плавное появление изображений
4. Корректная работа при 0 фото
5. Отсутствие лишних запросов

Скрипт:

автоматически показывает последние фото пользователя

работает быстро за счёт кэша

не ломается при пустых альбомах

минимально нагружает сервер

визуально выглядит аккуратно и современно

Код
<div id="user-photos"></div>

<script>
(function($) {
    $(function() {

        if (typeof $ === 'undefined') return;

        const userId = "$USER_ID$" || '0';
        const profileUrl = "$PERSONAL_PAGE_LINK$";

        if (!userId || userId === '0') return;

        const maxPhotos = 4;
        const container = $("#user-photos");
        const counter = $("#vkPhotosCount");

        const LS_KEY_PHOTOS = 'user_photos_v3_' + userId;
        const LS_KEY_COUNT = 'user_photos_count_v3_' + userId;
        const CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // 24 часа

        function normalizeUrl(url) {
            try {
                const u = new URL(url, location.origin);
                u.search = '';
                u.hash = '';
                return u.toString().replace(/\/$/, '');
            } catch (e) {
                return url;
            }
        }

        function renderPhotos(items) {
            // Нет фотографий — показываем сообщение
            if (!items?.length) {
                container.empty().html(`
                    <div style="
                        padding: 24px 16px;
                        text-align: center;
                        color: #666;
                        font-size: 15px;
                        background: #fafafa;
                        border-radius: 10px;
                        min-height: 100px;
                        display: flex;
                        flex-direction: column;
                        justify-content: center;
                        gap: 10px;
                    ">
                        <div style="font-size: 1.1em; color: #555; font-weight: 500;">
                            Пока здесь нет фотографий
                        </div>
                        <div style="font-size: 0.93em; color: #777; line-height: 1.45;">
                            Добавьте свои снимки в<br>
                            <a href="/photo/0-0-0-1-2" style="
                    color: #3b82f6;
                    text-decoration: none;
                    font-weight: 500;
                            ">Фотоальбом</a>
                            <br>и они красиво отобразятся в профиле
                        </div>
                    </div>
                `);

                if (counter.length) counter.text('0');
                return;
            }

            // Есть фото — отрисовка карточек
            const grid = $('<div class="profile-photo-grid"></div>').css({
                display: 'flex',
                gap: '12px',
                flexWrap: 'wrap'
            });

            items.slice(0, maxPhotos).forEach(item => {
                const card = $('<div class="photo-card"></div>').css({
                    width: '129px',
                    height: '125px',
                    overflow: 'hidden',
                    borderRadius: '2px',
                    cursor: 'pointer',
                    background: '#f0f0f0',
                    boxShadow: '0 2px 6px rgba(0,0,0,0.08)',
                    transition: 'transform 0.15s ease'
                });

                card.hover(function() {
                    $(this).css('transform', 'scale(1.03)');
                }, function() {
                    $(this).css('transform', 'scale(1)');
                });

                const img = $('<img alt="Фото пользователя">').css({
                    width: '100%',
                    height: '100%',
                    objectFit: 'cover',
                    opacity: 0,
                    transition: 'opacity 0.35s ease'
                });

                card.on('click', () => {
                    if (item.link) window.location.href = item.link;
                });

                const loader = new Image();
                loader.onload = () => {
                    img.attr('src', item.src);
                    requestAnimationFrame(() => img.css('opacity', '1'));
                };
                loader.src = item.src;

                card.append(img);
                grid.append(card);
            });

            container.empty().append(grid);

            if (counter.length) {
                counter.text(items.length);
            }
        }

        // 1. Показываем кэш сразу (даже если пустой!)
        try {
            const cached = localStorage.getItem(LS_KEY_PHOTOS);
            const cachedTime = localStorage.getItem(LS_KEY_PHOTOS + '_time');

            if (cached && cachedTime) {
                const age = Date.now() - Number(cachedTime);
                if (age < CACHE_DURATION_MS) {
                    const photos = JSON.parse(cached);
                    if (Array.isArray(photos)) {
                        renderPhotos(photos); // показываем даже если []
                        return; // кэш свежий — выходим, запрос не нужен!
                    }
                }
            }
        } catch (e) {
            // игнорируем ошибки старого кэша
        }

        // 2. Только если кэш устарел или отсутствует — делаем запрос
        $.get(profileUrl)
            .done(function(html) {
                const $profile = $(html);
                let albumLink = null;
                let photoCount = 0;

                $profile.find('a').each(function() {
                    const text = $(this).text().trim();
                    const match = text.match(/^Фото\s*\((\d+)\)$/i);
                    if (match) {
                        albumLink = this.href;
                        photoCount = parseInt(match[1], 10) || 0;
                        return false;
                    }
                });

                // Сохраняем количество сразу
                localStorage.setItem(LS_KEY_COUNT, photoCount.toString());
                if (counter.length) counter.text(photoCount);

                if (!albumLink || photoCount === 0) {
                    // Нет альбома или 0 фото — кэшируем пустое состояние
                    localStorage.setItem(LS_KEY_PHOTOS, JSON.stringify([]));
                    localStorage.setItem(LS_KEY_PHOTOS + '_time', Date.now());
                    renderPhotos([]); // сразу показываем сообщение
                    return;
                }

                // Загружаем альбом
                $.get(albumLink)
                    .done(function(albumHtml) {
                        const $page = $(albumHtml);
                        const items = [];

                        $page.find("div.entry-card.photo-entry-card").each(function() {
                            if (items.length >= maxPhotos) return false;

                            const $img = $(this).find("img[src*='/_ph/']");
                            if (!$img.length) return;

                            const src = normalizeUrl($img.attr("src"));

                            const linkEl = $(this).find(
                    "a.photo-card-title, a[href*='/topic/'], a[href*='/post/'], a[href*='/entry/']"
                            );

                            let link = linkEl.first().attr("href") || '';
                            if (link) {
                    link = normalizeUrl(link.startsWith('/') ? location.origin + link : link);
                            }

                            if (src && link) {
                    items.push({ src, link });
                            }
                        });

                        // Всегда сохраняем в кэш (даже если items пустой)
                        localStorage.setItem(LS_KEY_PHOTOS, JSON.stringify(items));
                        localStorage.setItem(LS_KEY_PHOTOS + '_time', Date.now());

                        renderPhotos(items);
                    });
            })
            .fail(function() {
                // Если профиль не загрузился — оставляем старый кэш
            });

    });
})(jQuery);
</script>


Мурчанн

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