Скрипт был переработан, частично изменена логика работы.
Это вторая версия скрипта: первая отображала только превью-изображения видео, тогда как текущая версия имеет некоторые отличия и улучшения.
Код
<!-- ======= Моё видео ======= -->
<div class="videos-block">
<div class="videos-header">Видео</div>
<div class="videos-footer" id="videos-count">Загрузка…</div>
<div class="videos-container" id="videos-container"></div>
</div>
<style>
/* ---------- Основной блок видео ---------- */
.videos-block {
background: #fff;
border: 1px solid #d1d5da;
font-family: Tahoma, Arial, sans-serif;
font-size: 13px;
color: #000;
max-width: 520px;
margin: 10px auto; /* ↑ отступ сверху и снизу */
padding: 0;
border-radius: 6px;
overflow: hidden;
}
/* Заголовок блока */
.videos-header {
background: #f0f2f5;
padding: 8px 10px; /* ↑ больше внутреннего отступа */
border-bottom: 1px solid #d1d5da;
color: #45688e;
font-weight: bold;
font-size: 13px;
}
/* Футер блока */
.videos-footer {
background: #f7f7f7;
border-top: 0px solid #d1d5da;
padding: 8px 16px; /* ↑ внутренний отступ */
color: #666;
font-size: 11px;
}
/* Контейнер для карточек видео */
.videos-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
padding: 10px;
justify-items: center;
align-items: center;
}
/* Карточка видео */
.video-card {
width: 100%;
height: 90px; /* ↑ чуть выше для красивого вида */
cursor: pointer;
border-radius: 5px;
overflow: hidden;
border: 0px solid #d1d5da;
position: relative;
transition: transform 0.25s, box-shadow 0.25s;
background: #f9f9f9; /* мягкий фон */
display: flex;
align-items: center;
justify-content: center;
}
/* Изображение видео */
.video-card img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 0px;
display: block;
transition: transform 0.25s ease, filter 0.25s ease;
}
/* Эффект при наведении */
.video-card:hover img {
transform: scale(1.05);
filter: brightness(1.1);
}
/* Тёмная накладка с текстом */
.video-overlay {
position: absolute;
inset: 0;
background: rgba(0,0,0,0);
color: #fff;
font-weight: bold;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: background 0.25s, opacity 0.25s;
border-radius: 0px;
}
/* При наведении на карточку показываем накладку */
.video-card:hover .video-overlay {
background: rgba(0,0,0,0.3);
opacity: 1;
}
/* === СЕТКА 2x2 === */
#videos-container{
display:grid;
grid-template-columns:1fr 1fr;
gap:10px;
}
/* === КАРТОЧКА (ВЕРТИКАЛЬНАЯ) === */
.video-card{
display:flex;
flex-direction:column; /* ВАЖНО: заголовок всегда снизу */
cursor:pointer;
}
/* === ПРЕВЬЮ === */
.video-thumb{
position:relative;
width:100%;
overflow:hidden;
}
.video-thumb img{
width:100%;
display:block;
border-radius:0px;
}
/* === PLAY OVERLAY === */
.video-overlay{
position:absolute;
inset:0;
display:flex;
align-items:center;
justify-content:center;
font-size:18px;
color:#fff;
background:rgba(0,0,0,0.25);
opacity:0;
transition:.15s;
}
.video-card:hover .video-overlay{
opacity:1;
}
/* === ЗАГОЛОВОК СНИЗУ ПОД КАРТОЧКОЙ === */
.video-title{
margin-top:5px;
font-size:10px;
line-height:1.25;
color:#2a5885;
display:block;
}
.video-card:hover .video-title{
text-decoration:underline;
}
/* === СЧЁТЧИК === */
#videos-count{
font-size:12px;
color:#656565;
margin-top:6px;
}
</style>
<script>
(async function() {
const container = document.getElementById('videos-container');
const counter = document.getElementById('videos-count');
const userId = <?$JSENCODE$($USER_ID$)?>;
if (!userId || userId == 0) {
container.innerHTML = '';
counter.textContent = '0 видео';
return;
}
const STORAGE_KEY = `user_videos_${userId}`;
const COUNT_KEY = `user_videos_count_${userId}`;
// ================= FETCH =================
async function fetchVideos() {
const res = await fetch(`/video/viusr/${userId}/`);
const html = await res.text();
const doc = new DOMParser().parseFromString(html, 'text/html');
return [...doc.querySelectorAll('li.entTd.uEntryWrap')]
.map(e => {
const img = e.querySelector('img.video-card-preview-img');
const link = e.querySelector('a.video-card-preview-link');
const titleEl = e.querySelector('a.video-card-title');
if (!img || !link) return null;
const title = titleEl
? titleEl.textContent.trim()
: 'Без названия';
return {
img: img.src,
title,
link: link.href
};
})
.filter(Boolean);
}
// ================= CACHE =================
function loadCache() {
const data = localStorage.getItem(STORAGE_KEY);
const count = localStorage.getItem(COUNT_KEY);
if (!data || !count) return null;
return { videos: JSON.parse(data), count: Number(count) };
}
function saveCache(videos) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(videos));
localStorage.setItem(COUNT_KEY, videos.length);
}
// ================= RENDER =================
function renderVideos(videos) {
container.innerHTML = '';
if (!videos.length) {
counter.textContent = '0 видео';
return;
}
videos.slice(-4).forEach(v => {
const div = document.createElement('div');
div.className = 'video-card';
const shortTitle = v.title.length > 55
? v.title.slice(0, 55) + '…'
: v.title;
div.innerHTML = `
<div class="video-thumb">
<img src="${v.img}" alt="${v.title}">
<div class="video-overlay">▶</div>
</div>
<div class="video-title" title="${v.title}">
${shortTitle}
</div>
`;
div.onclick = () => location.href = v.link;
container.appendChild(div);
});
counter.innerHTML =
`${videos.length} <a href="/video/viusr/${userId}/" style="color:#4a76a8;font-weight:bold;text-decoration:none;">видео ▶</a>`;
}
// ================= INIT =================
const cached = loadCache();
if (cached) renderVideos(cached.videos);
const fresh = await fetchVideos();
if (!cached || fresh.length !== cached.count) {
saveCache(fresh);
renderVideos(fresh);
}
})();
</script>
