Oleksii Panchenko
Посетитель
- Регистрация
- 18 Фев 2024
- Сообщения
- 34
- Реакции
- 8
Стили были адаптированы для шаблона Green (стандартный)
Инструкция:
Green/navigation.tpl добавить сюда после всех ваших кодов.
Вверху JS меняешь одну строку:
Опционально можно добавить:
1) Автоподгрузка (Infinite Scroll)
Варианты UX
Pure Infinite — грузим автоматически, кнопки нет.
Hybrid — первые N страниц грузим автоматически, дальше показываем кнопку (контроль + меньше нагрузки).
Infinite + “стоп” — автоподгрузка, но с переключателем “Авто/Ручной”.
Рекомендуемая реализация (не scroll, а IntersectionObserver)
Почему: меньше лагов, меньше событий, лучше на мобилках.
Логика
наблюдаем за #btn (или “sentinel” div)
когда он попадает в viewport → триггерим тот же loadNext()
Опции
rootMargin: "300px" — начинать загрузку заранее (не в самый низ).
защита от повторных запросов: флаг isLoading.
лимит авто-страниц: AUTO_PAGES_LIMIT = 3 (гибрид).
2) Счётчик “показано N из M”
Что реально возможно
В DLE “из коробки” нет универсальной переменной “всего постов” на страницу/категорию в DOM (зависит от шаблона). Поэтому 2 стратегии:
Стратегия A (быстро, без бэка): “Показано N”
N считаем просто: document.querySelectorAll(ITEM_SEL).length
показываем “Показано: N”
Плюсы: всегда работает, везде.
Минусы: нет “из M”.
Стратегия B (точно “N из M”): нужен источник M

M можно взять из:
заголовка категории/страницы, если там есть “(123)” или “найдено 123”
скрытого тега в шаблоне (лучший вариант):
добавить в шаблон один <meta>/data-total="123" (если DLE предоставляет число)
отдельного эндпоинта/хелпера (серверная доработка)
Итоговый UX
Показано 40 (минимум)
либо Показано 40 из 123 (если есть total)
Инструкция:
Green/navigation.tpl добавить сюда после всех ваших кодов.
Код:
<div class="nav-load" id="btn">[next-link]Загрузить еще[/next-link]</div>
<style>
#btn{
display:flex;
justify-content:center;
align-items:center;
margin:18px 0;
text-align:center;
}
#btn a{ text-decoration:none; }
#btn a.is-loading{
pointer-events:none;
opacity:.75;
cursor:default;
}
#btn.is-empty{ opacity:.75; }
#btn .nav-load-text{ display:inline-block; }
</style>
<script>
$(function () {
const ITEM_SEL = 'article.block.story.shortstory';
// ✅ ОПЦИЯ: что делать на последней странице
// 'hide' -> полностью убрать блок (самый чистый UX)
// 'message' -> показать текст
// 'disabled'-> оставить “задизейбленную” кнопку
const END_BEHAVIOR = 'hide';
const END_MESSAGE = 'Больше нечего загружать';
const DISABLED_TEXT = 'Нет новых записей';
function parseDoc(html) {
return $('<div>').append($.parseHTML(html));
}
function hasNextLink($wrap) {
const $a = $wrap.find('a').first();
return !!($a.length && $a.attr('href'));
}
function applyEndBehavior($wrap) {
if (END_BEHAVIOR === 'hide') {
$wrap.remove();
return;
}
if (END_BEHAVIOR === 'message') {
$wrap.addClass('is-empty').html('<span class="nav-load-text">' + END_MESSAGE + '</span>');
return;
}
if (END_BEHAVIOR === 'disabled') {
// оставляем кнопку, но делаем “неактивной”
let $a = $wrap.find('a').first();
if (!$a.length) {
$wrap.html('<a href="#" class="btn nav-load-btn is-loading" aria-disabled="true"></a>');
$a = $wrap.find('a').first();
}
$wrap.addClass('is-empty');
$a.addClass('btn nav-load-btn is-loading')
.attr('aria-disabled','true')
.text(DISABLED_TEXT);
return;
}
// fallback -> hide
$wrap.remove();
}
function skinLoadMoreBtn() {
const $wrap = $('#btn');
if (!$wrap.length) return;
const $a = $wrap.find('a').first();
// Последняя страница: next-link отсутствует
if (!$a.length || !$a.attr('href')) {
applyEndBehavior($wrap);
return;
}
// Есть next-link
$wrap.removeClass('is-empty');
if (!$a.hasClass('nav-load-btn')) $a.addClass('btn nav-load-btn');
$a.text('Загрузить еще');
}
function setBtnLoading(isLoading) {
const $a = $('#btn a').first();
if (!$a.length) return;
if (isLoading) {
if (!$a.data('old-text')) $a.data('old-text', $a.text());
$a.text('Загрузка...').addClass('is-loading');
} else {
$a.text($a.data('old-text') || 'Загрузить еще').removeClass('is-loading');
skinLoadMoreBtn();
}
}
// init
skinLoadMoreBtn();
$('body').on('click', '#btn a', function (e) {
e.preventDefault();
// если режим disabled/message и ссылки нет — просто выходим
const urlNext = $(this).attr('href');
if (!urlNext || urlNext === '#') return false;
const $firstItem = $(ITEM_SEL).first();
if (!$firstItem.length) return false;
const $list = $firstItem.parent();
$.ajax({
url: urlNext,
beforeSend: function () {
setBtnLoading(true);
if (typeof ShowLoading === 'function') ShowLoading('');
},
success: function (data) {
const $doc = parseDoc(data);
// 1) Подгружаем ниже только карточки новостей
const $newItems = $doc.find(ITEM_SEL);
if ($newItems.length) $list.append($newItems);
// 2) Обновляем навигацию/кнопку
$('.navigation').remove();
$('#btn').remove();
const $newNav = $doc.find('.navigation').first();
const $newLoad = $doc.find('#btn').first();
if ($newNav.length) $list.after($newNav);
if ($newLoad.length) $list.after($newLoad);
// 3) Применяем поведение кнопки (в т.ч. конец)
skinLoadMoreBtn();
// 4) URL (опционально)
if (history.pushState) history.pushState({}, '', urlNext);
},
error: function () {
alert('что-то пошло не так');
},
complete: function () {
if (typeof HideLoading === 'function') HideLoading('');
setBtnLoading(false);
}
});
return false;
});
});
</script>
Как переключать “что делать в конце”
Вверху JS меняешь одну строку:
Код:
const END_BEHAVIOR = 'hide'; // убрать полностью
// const END_BEHAVIOR = 'message'; // показать текст
// const END_BEHAVIOR = 'disabled'; // оставить неактивную кнопку
1) Автоподгрузка (Infinite Scroll)
Варианты UX
Pure Infinite — грузим автоматически, кнопки нет.
Hybrid — первые N страниц грузим автоматически, дальше показываем кнопку (контроль + меньше нагрузки).
Infinite + “стоп” — автоподгрузка, но с переключателем “Авто/Ручной”.
Рекомендуемая реализация (не scroll, а IntersectionObserver)
Почему: меньше лагов, меньше событий, лучше на мобилках.
Логика
наблюдаем за #btn (или “sentinel” div)
когда он попадает в viewport → триггерим тот же loadNext()
Опции
rootMargin: "300px" — начинать загрузку заранее (не в самый низ).
защита от повторных запросов: флаг isLoading.
лимит авто-страниц: AUTO_PAGES_LIMIT = 3 (гибрид).
2) Счётчик “показано N из M”
Что реально возможно
В DLE “из коробки” нет универсальной переменной “всего постов” на страницу/категорию в DOM (зависит от шаблона). Поэтому 2 стратегии:
Стратегия A (быстро, без бэка): “Показано N”
N считаем просто: document.querySelectorAll(ITEM_SEL).length
показываем “Показано: N”
Плюсы: всегда работает, везде.
Минусы: нет “из M”.
Стратегия B (точно “N из M”): нужен источник M
M можно взять из:
заголовка категории/страницы, если там есть “(123)” или “найдено 123”
скрытого тега в шаблоне (лучший вариант):
добавить в шаблон один <meta>/data-total="123" (если DLE предоставляет число)
отдельного эндпоинта/хелпера (серверная доработка)
Итоговый UX
Показано 40 (минимум)
либо Показано 40 из 123 (если есть total)