באתרים אשר מכילים עומדים ארוכים עם הרבה תוכן וכותרות, מומלץ להכניס תוכן עניינים אשר יאפשר לגולש לקפוץ בין חלקים שונים של המאמר. הוספה של תוכן עניינים יכול להקל על הגולש ולשפר את חווית המשתמש שלו באתר שלכם.
את הקוד במאמר הבא אנחנו נעטוף כתוסף אשר נוכל להתקין בכל אתר בקלות ובמהירות. בנוסף, התוסף הזה יודע לבנות את תוכן העניינים של העמוד לפי כותרות ה-<h2>
אשר נמצאות בתוכן.
שלב ראשון – יצירת בסיס תוסף
בתור התחלה, ניצור תיקייה חדשה תחת סביבת הפיתוח שלנו בתוך תיקיית plugins
של וורדפרס בשם table-of-contetns
.
לאחר מכן ניצור קובץ חדש בשם table-of-contents.php
תחת התיקייה שיצרנו ונכניס את הקוד הבא:
<?php
/**
* Plugin Name: Page Table of Contents
* Plugin URI: https://www.dorzki.io
* Description: Add automatically a dynamic table of contents to your page or post.
* Version: 1.0.0
* Author: dorzki
* Author URI: https://www.dorzki.io
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: wp-toc
*
* @package dorzki\TableOfContents
* @subpackage Plugin
* @version 1.0.0
*/
namespace dorzki\TableOfContents;
// Block if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Plugin constants.
define( 'TOC_PATH', plugin_dir_path( __FILE__ ) );
define( 'TOC_URL', plugin_dir_url( __FILE__ ) );
/**
* Class Plugin
*
* @package dorzki\TableOfContents
*/
class Plugin {
/**
* Total headings counter.
*
* @var int
*/
private $counter = 0;
/**
* Article headings.
*
* @var array
*/
private $headings = [];
/* ------------------------------------------ */
/**
* Plugin constructor.
*/
public function __construct() {
add_action( 'init', [ $this, 'register_textdomain' ] );
add_action( 'wp_enqueue_scripts', [ $this, 'load_assets' ] );
add_filter( 'the_content', [ $this, 'build_toc' ] );
add_shortcode( 'disable_toc', '__return_false' );
}
/* ------------------------------------------ */
/**
* Register the plugin's text domain.
*/
public function register_textdomain() {
load_plugin_textdomain( 'wp-toc', false, TOC_PATH . 'languages' );
}
/**
* Load plugin CSS and JS
*/
public function load_assets() {
wp_enqueue_style( 'toc_styles', TOC_URL . 'assets/styles.css' );
wp_enqueue_script( 'toc_scripts', TOC_URL . 'assets/scripts.js', [ 'jquery' ], false, true );
}
/* ------------------------------------------ */
/**
* Extracts and builds TOC.
*
* @param string $content the post content.
*
* @return string
*/
public function build_toc( $content ) {
if ( ! $this->is_disabled( $content ) ) {
$content = preg_replace_callback( '/<(h2)>(.*?)<\/h2>/i', [ $this, 'extract_headings' ], $content );
$toc = $this->generate_toc();
$content = $toc . $content;
}
return $content;
}
/* ------------------------------------------ */
/**
* Adds title id number and saves the heading.
*
* @param array $match regex match array.
*
* @return string
*/
public function extract_headings( $match ) {
$tag = sprintf( '<%1$s id="title_%2$s">%3$s</%1$s>', $match[1], $this->counter, $match[2] );
$this->counter ++;
$this->headings[] = $match[2];
return $tag;
}
/**
* Generates a table of contents from the headings.
*
* @return string|boolean
*/
public function generate_toc() {
if ( empty( $this->headings ) ) {
return false;
}
$html = '';
$html .= '<div class="post_toc">';
$html .= ' <strong>' . esc_html__( 'Table of Contents', 'wp-toc' ) . '</strong>';
$html .= ' <ol>';
foreach ( $this->headings as $id => $text ) {
$html .= "<li><a href='#title_{$id}'>{$text}</a></li>";
}
$html .= ' </ol>';
$html .= '</div>';
return $html;
}
/* ------------------------------------------ */
/**
* Check if the user don't want TOC on this page.
*
* @param string $content the post content.
*
* @return boolean
*/
private function is_disabled( $content ) {
return ( false !== strpos( $content, '[disable_toc]' ) );
}
}
// Initiate the class.
new Plugin();
הסבר
אני לא אסביר את כל הקוד, אך אתייחס לקוד העיקרי של התוסף. בתור התחלה אנו משתמשים בפילטר של וורדפרס the_content
על מנת לקבל את התוכן של המאמר לפני שהוא מודפס, ואז אנחנו מחילים עליו חיפוש אחר כותרות <h2>
ע״י שימוש בביטוי רגולרי.
כאשר הקוד מוצא כותרת הוא קורא לפונקציה extract_headings
אשר שומרת את הכותרת עצמה במשתנה מסוג מערך בזיכרון ונותנת לכל כותרת מזהה רציף (לדוגמא: title_0, title_1 וכד׳) ואז מתבצעת החלפת בתוכן שהכותרת הישנה מתחלפת בחדשה עם המזהה החדש.
לבסוף לאחר שמצאנו את כל הכותרות ונתנו להם מזהה רציף, הקוד קורא לפונקציה generate_toc
אשר תפקידה לקחת את הכותרות ששמרנו בזיכרון, ולבנות תוכן עניינים אשר יוצג לפני התוכן.
שלב שני – הוספת CSS
בשלב זה אנחנו ניצור תיקייה בשם assets
ובתוכה ניצור קובץ בשם styles.css
ונדביק את הקוד הבא:
.post_toc {
display: inline-block;
padding: 15px;
border: 1px solid #ebebeb;
background-color: #f8f8f8;
float: right;
margin: 0 0 15px 30px;
}
.post_toc ol {
padding-right: 0;
list-style-position: inside;
margin: 15px 0 0;
}
שלב שלישי – הוספת JavaScript
בשלב האחרון אנחנו ניצור קובץ בשם scripts.js
תחת התיקייה assets
ונדביק את הקוד הבא:
( function ( $ ) {
$( '.post_toc li a' )
.on( 'click', function ( e ) {
e.preventDefault();
$( 'html, body' ).animate( {
scrollTop : $( $( this ).attr( 'href' ) ).offset().top
} );
} );
} )( jQuery );
שלב רביעי – ביטול תוכן עניינים בעמוד מסויים (אופציונלי)
במידה ואתם מעוניינים שלא יוצג תוכן עניינים בעמוד מסויים, נוסיף לתוכן העמוד את השוטקוד הבא [disable_toc]
והתוסף ידע אוטומטית לא לעבד את התוכן ולהציג את תוכן העניינים.
סיכום להורדת הקוד המלא
בעזרת הקוד הנ״ל תוכלו לקחת לבנות את תוכן עניינים של העמוד שלכם בצורה דינאמית, זהו בהחלט כלי עזר חשוב במידה והעמוד שלכם כולל הרבה תוכן.
רעיון מדליק!
אהבתי את ההתמודדות עם נתינת id לכותרות כדי שאפשר יהיה לקשר אליהן.
היי לאה,
תודה רבה על התגובה, וכן בהחלט פיתרון מגניב 🙂 זה רעיון שעלה לי באחד הפרוייקטים שעשיתי ללקוח שלי.
תודה רבה, עזר לי המון!
היי טל,
שמח לשמוע! תודה רבה על התגובה 🙂
זה אחלה רעיון ואחלה תוסף חביבי!
היי רועי!
תודה רבה! בהחלט משהו שימושי ודי קליל לביצוע 🙂
היי אחלה פוסט, מזכיר את התוכן עיניינים בויקיפדיה.
האם יש דרך לעשות שכברירת מחדל התוכן עיניינים לא יוצג. ואם יוצג, אז רק איפה שנוסיף את סורט-קוד?
היי יוני,
זה הכיוון 🙂
לגבי השאלה שלך, עם טיפה ידע ב-PHP אני בטוח שתסתדר.
אם תרצה מוזמן ליצור קשר לקבלת הצעת מחיר 🙂