В начале статьи хочу признаться, что я не верстальщик и не владею PHP, JavaScript или CSS на должном уровне, поэтому всё, что написано ниже, используйте на свой страх и риск. Возможно, это неправильно и надо делать не так. Я не знаю, как надо правильно, учусь самостоятельно, поэтому пишу, как умею хрум-хрум-хрум.
Решил привести в порядок свою главную страницу блога. Не нравятся мне длинные посты, которые нужно долго листать, чтобы перейти к следующему. Изначально рассматривал два варианта:
- Кнопка
[Пропустить пост]для быстрой перемотки к следующему посту и возвращению к предыдущему - Кнопка
[Развернуть]для динамической загрузки остальной части поста после тега<!--more-->.
В итоге выбрал третий путь: весь пост загружается сразу, но часть после тега <!--more--> показывается или скрывается по клику на кнопку [развернуть/свернуть].
Я выбрал этот вариант по двум причинам:
- Скрытая часть поста должна корректно обрабатываться скриптами по событию
onload/onready. - Размер постов у меня небольшой.
Реализация
Для начала нужно выбрать способ обработки поста. Если вызвать get_the_content(), то возвращается только часть до тега. Можно обойти это поведение, используя глобальную переменную $more, но такое решение выглядит как костыль:
function my_the_content() {
global $more;
$prev_more = $more;
$more = 1;
$content = apply_filters('the_content', get_the_content());
$more = $prev_more;
}
Я решил брать текст поста из поля post_content объекта $post и делить его с помощью функции get_extended().
В итоге, я заменил вызов the_content() в своей теме на my_the_content($post) такого вида (код нужно добавить в functions.php вашей темы WordPress):
function my_the_content($post) {
// На странице поста стандартное поведение
if (is_singular()) {
the_content();
return;
}
// Получаем текст целиком из поля post_content и применяем фильтры
$content = apply_filters('the_content', $post->post_content);
// Разбиваем на несколько частей по тегу <!--more-->
$parts = get_extended($content);
// Часть после тега
$extended = $parts['extended'];
// После тега ничего нет, заканчиваем работу
if (empty($extended)) {
return;
}
// Поддержка роботов и тех, кому отключили JavaScript за неуплату
echo '<noscript>';
echo '<div>'.$extended.'</div>';
echo '<style>.post-body {display: none; }</style>';
echo '</noscript>';
// Храним всю дополнительную часть в секции post-body,
// классы expanded/collapsed используются для регулировки видимости элементов
echo '<div class="post-body">';
// Прячем кнопки в отдельном контейнере для удобства
echo '<div class="toggle-buttons">';
// Две кнопки, одна видна, другая спрятана
echo '<div class="toggle-post-body expanded">';
echo '<div class="label expand">развернуть</div>';
echo '</div>';
echo '<div class="toggle-post-body collapsed">';
echo '<div class="label collapse">свернуть</div>';
echo '</div>';
echo '</div>';
// Тело поста спрятано по умолчанию
echo '<div class="post-body-content collapsed">'.$extended.'</div>';
echo '</div>';
}
Стилизация
Теперь стили для блока .post-body. Все изменения затрагивают только элементы внутри него:
/* Элементы с классом collapsed внутри post-body скрыты */
.post-body .collapsed {
display: none;
}
/* Элементы с классом expanded внутри post-body видны */
.post-body .expanded {
display: block;
}
/* Общие настройки для кнопок-переключателей */
.post-body .toggle-post-body .label {
color: #cc6633;
cursor: pointer;
margin-bottom: 0.5em;
border-bottom: 1px dashed;
font-size: 90%;
}
/* Треугольник для кнопки "свернуть" */
.post-body .toggle-post-body .label.collapse:before {
content: '\25BC';/* ▼ */
margin-right: 5px;
}
/* Треугольник для кнопки "развернуть" */
.post-body .toggle-post-body .label.expand:before {
content: '\25B6'; /* ▶ */
margin-right: 5px;
}
Логика на JavaScript:
И, наконец, скрипт, который переключает видимость:
// Добавляем обработку клику по элементам с классом "toggle-post-body"
jQuery('.toggle-post-body').click(function(event){
var nextButton = jQuery(this)
.toggleClass('expanded')
.toggleClass('collapsed')
.siblings('.toggle-post-body');
nextButton
.toggleClass("expanded")
.toggleClass("collapsed");
var contentBlock = nextButton
.closest(".toggle-buttons")
.next('.post-body-content');
contentBlock
.toggleClass("expanded")
.toggleClass("collapsed");
});
Заключение
Подводя итог, логика работы выглядит следующим образом:
- Расширенная часть поста по умолчанию скрыта (класс .collapsed).
- При клике на видимую кнопку (например, «развернуть») запускается скрипт.
- Скрипт переключает видимость у нажатой кнопки (скрывая её) и у соседней (показывая её).
- Одновременно скрипт меняет видимость у блока с контентом.
Недостатки
- Пользователь не может перейти на страницу с самим постом, кроме как кликнув на заголовок.
- Пришлось убрать блок кнопки Social Likes с главной страницы для того, чтобы люди могли делиться контентом в социальных сетях. Но они этого и так не делают, так что невелика потеря.
- Некоторые мои записи используют канвас для рисования с помощью WebGL или JavaScript. Для них пришлось делать уникальный идентификатор канвасов для каждого поста.
- Страница грузит содержимое всех постов, что может быть накладно, если все посты на странице рисуют графику, например.
- Пришлось переписать каждый пост с меткой «Интерактив», чтобы каждый скрипт писал в свой уникальный canvas плюс немного исправить вызов
requestAnimationFrame. Зато выложил все скрипты на GitHub и добавил каждому демонстрационныйindex.html.
UPD: Немного упростил логику. Теперь у меня два элемента типа toggle-post-body. По кнопке их видимость меняется местами. Можете посмотреть исходники плагина b2k-tools с актуальной версией на GitHub.
Раз вы дочитали до конца, как считаете: нужно ли добавить кнопку «свернуть» в конец поста для быстрой навигации?