באתרים אשר מכילים עומדים ארוכים עם הרבה תוכן וכותרות, מומלץ להכניס תוכן עניינים אשר יאפשר לגולש לקפוץ בין חלקים שונים של המאמר. הוספה של תוכן עניינים יכול להקל על הגולש ולשפר את חווית המשתמש שלו באתר שלכם.

את הקוד במאמר הבא אנחנו נעטוף כתוסף אשר נוכל להתקין בכל אתר בקלות ובמהירות. בנוסף, התוסף הזה יודע לבנות את תוכן העניינים של העמוד לפי כותרות ה-<h2> אשר נמצאות בתוכן.

לוגו של טלגרם הצטרפו לערוץ הטלגרם וקבלו עדכון כאשר מאמר חדש מתפרסם!

שלב ראשון – יצירת בסיס תוסף

בתור התחלה, ניצור תיקייה חדשה תחת סביבת הפיתוח שלנו בתוך תיקיית plugins של וורדפרס בשם table-of-contetns.

לאחר מכן ניצור קובץ חדש בשם table-of-contents.php תחת התיקייה שיצרנו ונכניס את הקוד הבא:

<?php
/**
 * Plugin Name: Page Table of Contents
 * Plugin URI: https://www.dorzki.co.il
 * Description: Add automatically a dynamic table of contents to your page or post.
 * Version: 1.0.0
 * Author: dorzki
 * Author URI: https://www.dorzki.co.il
 * 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] והתוסף ידע אוטומטית לא לעבד את התוכן ולהציג את תוכן העניינים.

סיכום

בעזרת הקוד הנ״ל תוכלו לקחת לבנות את תוכן העניינים של העמוד שלכם בצורה דינאמית, זהו בהחלט כלי עזר חשוב במידה והעמוד שלכם כולל הרבה תוכן.

דור צוברי

מתכנת מגיל 13, ומתעסק עם וורדפרס מגיל 18, אוהב לפצח אתגרים ולפתח דברים מורכבים על בסיס וורדפרס. עצמאי מגיל 16, מרצה ובלוגר. בזמן הפנוי שלי אוהב מאוד לקרוא קומיקס של MARVEL.

דור צוברי

תגובות לפוסט

כתיבת תגובה

תגובה אחת

  1. רועי יוסף

    זה אחלה רעיון ואחלה תוסף חביבי!

    1. מחבר
      דור צוברי

      היי רועי!
      תודה רבה! בהחלט משהו שימושי ודי קליל לביצוע 🙂

  2. טל יערי

    תודה רבה, עזר לי המון!

    1. מחבר
      דור צוברי

      היי טל,
      שמח לשמוע! תודה רבה על התגובה 🙂

  3. לאה כהן

    רעיון מדליק!
    אהבתי את ההתמודדות עם נתינת id לכותרות כדי שאפשר יהיה לקשר אליהן.

    1. מחבר
      דור צוברי

      היי לאה,
      תודה רבה על התגובה, וכן בהחלט פיתרון מגניב 🙂 זה רעיון שעלה לי באחד הפרוייקטים שעשיתי ללקוח שלי.