Оглавление (содержание) для больших постов
Не редко большие посты мы разделяем логическими подзаголовками. Порой пост несет в себе какую-то собранную информацию, разбитую на части. Для таких постов я предпочитаю создавать "оглавление" — список ссылок с анкорами на подзаголовки в посте. Создавать такое оглавление - занятие до того муторное, что проще обойтись без него (за редким исключение, конечно).
- Код класса Kama_Contents
- Как пользоваться классом Kama_Contents
- #1 Оглавление в тексте (шоткод [contents])
- #2 Оглавление вверху каждого поста
- #3 Оглавление вверху каждого поста, после разделителя
- #4 Оглавление в сайд-баре
- #5 Разные экземпляры
- Настройки Оглавления
- HTML и CSS
- Древовидная нумерация списка
- Плавная прокрутка
- «Cкрыть/Показать» оглавление (jQuery код)
- Плагины для создания оглавления
- Опрос: Что добавить в скрипт "Содержание для больших постов"?
Написал небольшой класс, который позволяет без шума и пыли, а также красиво и главное быстро создавать оглавления почти любой сложности. Для этого нужно использовать шоткод [contents], в том месте, где оно нам нужно. В начале этого поста вы видите то самое оглавление.
Кроме этого написанный мною класс позволяет создавать оглавление для любого текста, без использования шоткода в нем. А затем выводить это оглавление, например, в начале поста или в боковой колонке (сайдбаре).
"Оглавление" можно всячески настроить:
- не показывать заголовок: "Содержание:" - [contents embed];
- не показывать ссылки "К содержанию" в тексте - параметр to_menu;
- настроить под себя CSS стили - параметр css;
- изменить HTML теги по которым будет строиться оглавление. Можно указать любые теги не только
H1
,H2
... но иstrong
,em
и т.д. Или вообще, указать классы html тега, например:.foo
,.bar
- [contents h1 em .foo]; - указать минимальное количество заголовков для того, чтобы оглавление выводилось - параметр min_found.
- указать минимальную длину текста, чтобы оглавление выводилось - параметр min_length.
- указать название шоткода, который будет использоваться в тексте для создания оглавления - параметр shortcode.
- другие параметры, см. в коде класса Kama_Contents.
Код класса Kama_Contents
GitHub менюКак пользоваться классом Kama_Contents
Прежде всего нужно подключить код, можно добавить его в файл темы functions.php или создать плагин. Далее выбирайте подходящий вам код примера и добавьте его рядом с основным (выше или ниже неважно).
#1 Оглавление в тексте (шоткод [contents])
Разместите этот код рядом с основным и при написании поста используйте шоткод [contents] или [contents h3] или [contents h3 h5]. На месте шоткода появится содержание, текста который следует после шоткода:
## Обработка шоткода [contents] в тексте add_filter( 'the_content', 'kama_contents_shortcode', 20 ); function kama_contents_shortcode( $content ){ if( is_singular() ){ $args = array( //'shortcode' => 'list', // [list] вместо [contents] //'margin' => 30, //'page_url' => get_permalink(), 'to_menu' => 'к оглавлению ↑', 'title' => 'Оглавление:', 'min_length' => 300, ); return Kama_Contents::init( $args )->shortcode( $content ); } // вырежем шорткод else return Kama_Contents::init()->strip_shortcode( $content ); }меню
#2 Оглавление вверху каждого поста
Разместите этот код рядом с основным и в начале каждого поста у вас будет выводится содержание, по указанным тегам array('h2','h3'), т.е. если в тексте будут найдены теги h2 или h3, то из них будет собрано содержание:
## Вывод содержания вверху, автоматом для всех постов add_filter( 'the_content', 'contents_on_post_top', 20 ); function contents_on_post_top( $content ){ if( ! is_singular() ) return $content; $args = array( //'margin' => 50, //'to_menu' => false, //'title' => false, 'selectors' => array('h2','h3'), ); $contents = Kama_Contents::init( $args )->make_contents( $content ); return $contents . $content; }
#3 Оглавление вверху каждого поста, после разделителя
Этот код будет вставлять оглавление в начале каждой записи. Но не в самом начале, а после первого параграфа. Номер параграфа (разделителя) и сам разделитель можно изменить в переменных: $_sep_num
и $_sep
соответственно.
## Вывод содержания вверху после указанного параграфа, автоматом для всех записей add_filter( 'the_content', 'contents_at_top_after_nsep', 20 ); function contents_at_top_after_nsep( $text ){ if( ! is_singular() ) return $text; // настройки разделителя $_sep = '</p>'; // разделитель в тексте $_sep_num = 1; // после какого по порядку разделителя вставлять оглавление? // настройки оглавления $args = array( 'min_length' => 4000, 'css' => false, 'markup' => true, 'selectors' => array('h2','h3'), ); // погнали... $ex_text = explode( $_sep, $text, $_sep_num + 1 ); // если подходящий по порядку разделитель найден в тексте if( isset($ex_text[ $_sep_num ]) ){ $contents = Kama_Contents::init( $args )->make_contents( $ex_text[$_sep_num] ); $ex_text[ $_sep_num ] = $contents . $ex_text[$_sep_num]; $text = implode( $_sep, $ex_text ); } // просто в верху текста else { $contents = Kama_Contents::init( $args )->make_contents( $text ); $text = $contents . $text; } return $text; }меню
#4 Оглавление в сайд-баре
Эти примеры похожи на второй - тут также используется метод make_contents(), а не shortcode(), как в первом.
Вариант 1
Добавьте эту функцию рядом с классом и используйте там где нужно вывести оглавление. В функцию нужно передать объект поста (по умолчанию передается global $post) для которого нужно получить оглавление или можно передать сам текст для которого нужно вывести оглавление (текст нужно передавать в переменной, которая потом будет использована для вывода текста, именно эта переменная, потому что в ней по ссылке изменяется текст - к его заголовкам добавляются анкоры).
// для вывода оглавления function get_kama_contents( & $post = false ){ if( ! $post ) $post = & $GLOBALS['post']; if( is_string($post) ) $post_content = & $post; else $post_content = & $post->post_content; $args = array( 'selectors' => array('h2','h3'), 'min_found' => 1, 'margin' => 0, 'to_menu' => false, 'title' => false, ); $contents = Kama_Contents::init( $args )->make_contents( $post_content ); // чтобы правильно работала the_content() которая работатет на основе get_the_content() global $pages; if( $pages && count($pages) == 1 ){ $pages[0] = $post_content; } else{ // об этом варианте молчит наука. Тут надо выдумывать... } return $contents; }
Теперь выводим оглавление, например в сайдбаре:
echo get_kama_contents();
Заметка: get_kama_contents() нужно вызывать раньше чем выводиться контент. Если в HTML содержание нужно вывести ниже чем выводится контент, то вызовите функцию сохраните оглавление и выведите его ниже.
$contents = get_kama_contents(); // код код the_content(); // выводим оглавление echo $contents;
Вариант 2
Разместив этот код рядом с основным классом, оглавление можно вывести в любом месте шаблона, например в сайдбаре. Для этого используйте строку: echo $GLOBALS['kc_contents'];
## вывод содержания в сайдбаре add_action( 'wp_head', 'sidebar_contents' ); function sidebar_contents(){ if( ! is_singular() ) return; global $post; $args = array(); $args['selectors'] = array('h2','h3'); //$args['margin'] = 50; //$args['to_menu'] = false; //$args['title'] = false; $GLOBALS['kc_contents'] = Kama_Contents::init( $args )->make_contents( $post->post_content ); } // затем в сайдбаре выводим: echo $GLOBALS['kc_contents'];меню
#5 Разные экземпляры
Если нужно использовать несколько классов с разными параметрами. Например, чтобы обработать разные тексты. То разные экземпляры класса можно создать так:
// первый текст $text1 = 'текст [contents] текст'; $kcone = new Kama_Contents( array( 'to_menu' = 'к оглавлению ↑', 'title' = 'Оглавление:', //'page_url' = get_permalink(), ) ); echo $kcone->shortcode( $text1 ); // второй текст $text2 = 'текст [list] текст'; $kctwo = new Kama_Contents( array( 'to_menu' = 'к списку ↑', 'title' = 'Навигация:', 'shortcode' = 'list', ) ); echo $kctwo->shortcode( $text2 );
Настройки Оглавления
Вы же заметили закомментированные строки в примерах? Это настройки. В экземпляр класса можно передавать аргументы (настройки): Kama_Contents::init( $args ):
// число. отступ слева у подразделов в пикселях. $args['margin'] = 40; // массив/строка. Теги по умолчанию по котором будет строиться содержание. Порядок имеет значение. // Кроме тегов, можно указать атрибут class: array('h2','.class_name'). Можно указать строкой: 'h2 h3 .class_name' $args['selectors'] = array('h2','h3','h4'); // строка. ссылка на возврат к содержанию. '' - убрать ссылку $args['to_menu'] = 'к содержанию ↑'; // строка. Заголовок содержания. '' - убрать заголовок $args['title'] = 'Содержание:'; // строка. css стили. '' - убрать стили $args['css'] = '.kc-gotop{ display:block; text-align:right; } .kc-title{ text-align:italic; }'; // число. Сколько минимум заголовков должен содержать текст, чтобы оглавление отобразилось. $args['min_found'] = 2; // Минимальная длина (символов) текста, чтобы содержание выводилось. $args['min_length'] = 2000; // Ссылка на страницу для которой собирается содержание. Если содержание выводиться на другой странице... $args['page_url'] = ''; // Название шоткода $args['shortcode'] = 'contents'; // Включение микроразметки. Установите true чтобы включить микроразметку типа http://schema.org/ItemList $args['markup'] = false; // Добавить 'знак' перед под-заголовком статьи со ссылкой на текущий анкор под-заголовка. // Чтобы включить, укажите '#', '&' или что вам нравится :) $args['anchor_link'] = ''; // Какой тип анкора использовать: 'a' - <a name="anchor"></a> или 'id' - $args['anchor_type'] = 'id'; // Название атрибута тега из значения которого будет браться анкор // (если этот атрибут есть у тега). Ставим '', чтобы отключить такую проверку... // пример: у заголовка есть атрибут id="fooo". Анкором станет текст #fooo, а не текст заголовка $args['anchor_attr_name'] = 'id';меню
HTML и CSS
Все содержание идет сплошными <li>, а для уровней указываются CSS классы и левый отступ - margin. С помощью классов можно настроить отображение как угодно...
Вот так выглядит HTML код, который генерирует Kama_Contents:
<div class="kc__wrap"> <div class="kc__title" id="kcmenu">Содержание:</div> <ul class="contents"> <li class="top"><a href="#h2_1">заглавие 2, №1</a></li> <li style="margin-left:40px;" class="sub sub_1"><a href="#h3_2">заглавие 3, №1</a></li> <li style="margin-left:80px;" class="sub sub_2"><a href="#h4_3">заглавие 4, №1</a></li> <li style="margin-left:80px;" class="sub sub_2"><a href="#h4_4">заглавие 4, №2</a></li> <li style="margin-left:80px;" class="sub sub_2"><a href="#h4_5">заглавие 4, №3</a></li> <li style="margin-left:40px;" class="sub sub_1"><a href="#h3_6">заглавие 3, №2</a></li> <li style="margin-left:40px;" class="sub sub_1"><a href="#h3_7">заглавие 3, №3</a></li> <li class="top"><a href="#h2_8">заглавие 2, №2</a></li> <li class="top"><a href="#h2_9">заглавие 2, №3</a></li> <li style="margin-left:40px;" class="sub sub_1"><a href="#h3_10">заглавие 3, №4</a></li> <li style="margin-left:40px;" class="sub sub_1"><a href="#h3_11">заглавие 3, №5</a></li> </ul> </div>
style="margin-left:40px;" добавляется автоматически на основе настройки $args['margin'] = 40;. Нет связи между числами в заголовках (h1, h2), уровни выставляются в зависимости от порядка указного в настройке: $args['def_tags'] = array('h2','h3','h4');. Т.е. если поменять на array('h3','h2','h4');, то h3 будет в содержании верхним уровнем - это нужно, чтобы указывать отличные от h* теги: strong, em.
менюДревовидная нумерация списка
Чтобы сделать древовидную нумерацию списка, как на картинке, установите для списка такие CSS стили:
.contents{ list-style-type:none; counter-reset:list; } /* цвет чисел */ .contents li:before{ color:#555; } /* уровень 0 */ .contents li.top{ counter-increment:list; counter-reset:list1; } .contents li.top:before{ content:counter(list) '. '; } /* уровень 1 */ .contents li.sub_1{ counter-increment:list1; counter-reset:list2; } .contents li.sub_1:before{ content:counter(list) '.' counter(list1) '. '; } /* уровень 2 */ .contents li.sub_2{ counter-increment:list2; } .contents li.sub_2:before{ content:counter(list) '.' counter(list1) '.' counter(list2) '. '; }
Нумерация идет только до 3 уровня: верхний и два под ним. Если нужно больше, то по аналогии допишите стили так:
/* уровень 3 */ .contents li.sub_3{ counter-increment:list3; } .contents li.sub_3:before{ content:counter(list) '.' counter(list1) '.' counter(list2) '.' counter(list3) '.'; }меню
Плавная прокрутка
В целом, можно ставить этот код на любой сайт где подключен jQuery и будет плавная прокрутка к якорям, а в частности, он хорошо сочетается с "содержанием" (см. пример, жмите там на ссылки). А это и js код:
// document.ready jQuery(function($){ // Прокрутка на все якоря (анкоры) (#) и на a[name]. v1.3 $(document).on( 'click.smoothscroll', 'a[href*="#"]', function( e ){ let hash = this.hash let _hash = hash.replace( /#/, '' ) let theHref = $(this).attr('href').replace( /#.*/, '' ) // у кнопки есть атрибут onclick значит у нее другая задача if( this.onclick ) return // не текущая страница if( theHref && location.href.replace( /#.*/, '' ) !== theHref ) return let $target = (_hash === '') ? $(document.body) : $( hash + ', a[name="'+ _hash +'"]').first() if( ! $target.length ) return e.preventDefault() let scrollTo = $target.offset().top - 50 $('html:first, body:first') .stop() .animate( { scrollTop: scrollTo }, 200, 'swing', function(){ window.history.replaceState( null, document.title, hash ) } ) }) })меню
«Cкрыть/Показать» оглавление (jQuery код)
Вариант 1 ("как-в-википедии"):
/** * Показать/скрыть Содержание. Кнопка добавляется после Текста в заголовок - "Содержание: [скрыть]" * v 0.3 */ // document.ready jQuery(function($){ let $title = $('.kc__title') let showtxt = '[показать]' let hidetxt = '[скрыть]' let $but = $('<span class="kc-show-hide" style="cursor:pointer;margin-left:.5em;font-size:80%;">'+ hidetxt +'</span>') $but.on( 'click', function(){ let $the = $(this) let $cont = $the.parent().next('.contents') if( $the.text() === hidetxt ){ $the.text( showtxt ) $cont.slideUp() } else{ $the.text( hidetxt ) $cont.slideDown() } }) $title.append( $but ) });
Вариант 2 (заголовок-кнопка):
/** * Показать/скрыть Содержание. Заголовок является кнопкой и к нему приписывается текст - "Содержание ▴" * v 1.0 */ jQuery(document).ready(function($){ let $title = $('.kc__title').css({ cursor:'pointer' }) let showico = ' ▾' let hideico = ' ▴' let collapsedKey = 'contents_collapse' let setIco = function( $that, type ){ $that.text( type === 'hide' ? $that.text().replace( showico, hideico ) : $that.text().replace( hideico, showico ) ) } $title.each(function(){ let $the = $(this); $the.text( $the.text().replace(':','').trim() + hideico ) $the.on( 'click', function(){ let $cont = $the.next('.contents') if( $cont.is(':visible') ){ $cont.slideUp(function(){ $the.addClass('collapsed') setIco( $the, 'show' ) window.localStorage.setItem( collapsedKey, '1' ) }) } else { $cont.slideDown(function(){ $the.removeClass('collapsed') setIco( $the, 'hide' ) window.localStorage.removeItem( collapsedKey ) }) } }) // свернем/развернем на основе куков if( window.localStorage.getItem(collapsedKey) === '1' ){ setIco( $the, 'show' ) $the.next('.contents').hide() } }) });
Коды нужно добавить к имеющимся js скриптам. Код должен срабатывать после того как подключилась jQuery библиотека.
менюПлагины для создания оглавления
Есть не мало причин использовать готовые плагины, даже для тех кто может использовать материал из этой статьи. Потому что - это удобно! Вот плагины для создания такого же содержания:
-
Easy Table of Contents - удобный и функциональный плагин, который позволяет вам вставлять оглавление в ваши посты, страницы и пользовательские типы постов.
-
Table of Contents Plus - очень гибко настраиваемые плагин содержания в статьях. Также есть кнопка в виз. редакторе.
- LuckyWP Table of Contents — генерирует содержание для записей, страниц и произвольных типов постов. Множество настроек, Gutenbeg-блок, кнопка в классическом редакторе. Поддерживает как ручное, так и автоматическое добавление содержания в посты.
Опрос: Что добавить в скрипт "Содержание для больших постов"?
Что было сделано благодаря опросу:
- Добавить Schema разметку и оптимизировать код для поисковиков (30 голосов)
—
Заказать по очень недорогой цене комментарии в Инстаграм Вы можете на сайте Avi1.ru. При этом Вам не придется тратить свое время на поиск действительно надежного сервиса. Здесь Вы найдете все, что нужно: качественные услуги, приятные цены, гарантии и вежливое обслуживание.
- Блок произвольных полей в админке WordPress своими руками
- Функция вывода всех постов по месяцам написания
- Исполняемый php код в записях Wordpress