[Ha-Basic] How to automatically display a table of contents on the theme text or anywhere

【ha-Basic】テーマの本文上や任意の場所へ自動で目次を表示させる方法

公開日: カスタマイズ 制作備忘録
Knowledge Base Wordpress ha-Basic テーマ
☆☆ この機能は【ha-Basic】テーマ バージョン1.1で実装(対応)済みです ☆☆
最近のテーマでよく見かける記事本文上の目次表示機能。個人的には

  • 必要な部分だけ斜め読みされてしまうのでは??(ページ閲覧時間の低下を招くかも)
  • いきなりバーンと目次が表示されるのはどうか?(構造の複雑な記事はもくじも複雑になる)

という懸念からあまり進んで表示はさせていませんでしたが、このページのように最初は非表示(目次を閉じた状態)にしておいて必要な人は開くという風にしたらあまり邪魔にもならないでしょうということで設置してみました。

この機能の設置については有名なプラグイン

を使えば一発なのですが、一度設置してしまえばプラグインにあるような設定ページは不要ですからわざわざ使わなくても・・ということでテーマ内へコードを追加する方法にしました。

とかっこいいこと言ってますけど、私の能力では一からコードが書けるはずもないので、基本となるコードは

に掲載されているものを使わせていただきました。

分かりやすい記事を公開していただいてありがとうございます

プラグインなしで目次を自動表示させる方法については本当にたくさんの記事が検索すると出てきますが、今回は任意の場所にショートコードで挿入できるという点から上記のサイトを参考にさせていただきました。

※【ha-Basic】テーマテーマを使われている方がカスタマイズできるよう、このサイトで表示している目次についての最終形のコードは文中に掲載させていただいております

☆☆ この機能は【ha-Basic】テーマ バージョン1.1で実装(対応)済みです ☆☆

【ha-Basic】テーマの本文上や任意の場所へ自動で目次を表示させる方法

今回のカスタマイズをした後の完成形

何はともあれどんな風になるのかを紹介しないといけないですね。

まずこの記事の上の方にあるSNSシェアボタン下に1つ目次を設置しています。

また、任意の場所に設置できるようになっていますので

[toc]
というショートコードを入れると↓のように思った場所へも表示できるようになっています。

テーマフォルダ内へ「toc.php」をアップロードする

同じ機能を追加するための記事によってはテーマのfunctions.phpへ直接追記する方法が紹介されていますが、結構コードが長いので、今回はテーマフォルダ内へ新たに目次用のファイルを設置して、functions.phpでそのファイルを読み込ませる方法を紹介します。

まずはこちらから「toc.zip」というファイルをダウンロードし、解凍してください

解凍した「toc.php」というファイルだけをテーマフォルダ内へアップロードしてください。

※一応PHPコードの内容を掲載しておきます

コードを表示する
class Toc_Shortcode {
	private $add_script = false;
	private $atts = array();
	public function __construct() {
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
		add_shortcode( 'toc', array( $this, 'shortcode_content' ) );
		add_action( 'wp_footer', array( $this, 'add_script' ) );
	}
	function enqueue_scripts() {
		if ( !wp_script_is( 'jquery', 'done' ) ) {
			wp_enqueue_script( 'jquery' );
		}
	}
	public function shortcode_content( $atts ) {
		$this->atts = shortcode_atts( array(
			'id' => '',
			'class' => 'toc',
			'title' => '<span class="icon-info"></span> 【目次】 ',
			'toggle' => 'true',
			'opentext' => '表示する',
			'closetext' => '閉じる',
			'showcount' => 2,
			'depth' => 0,
			'toplevel' => 2,
			'targetclass' => 'kiji',
			'offset' => '',
			'duration' => 'normal'
		), $atts );
		$content = get_the_content();
		$headers = array();
		preg_match_all( '/<([hH][1-6]).*?>(.*?)<\/[hH][1-6].*?>/u', $content, $headers );
		$header_count = count( $headers[0] );
		$counter = 0;
		$counters = array( 0, 0, 0, 0, 0, 0 );
		$current_depth = 0;
		$prev_depth = 0;
		$top_level = intval( $this->atts['toplevel'] );
		if ( $top_level < 1 ) $top_level = 1;
		if ( $top_level > 6 ) $top_level = 6;
		$this->atts['toplevel'] = $top_level;
		// 表示する階層数
		$max_depth = ( ( $this->atts['depth'] == 0 ) ? 6 : intval( $this->atts['depth'] ) );
		$toc_list = '';
		for ( $i = 0; $i < $header_count; $i++ ) {
			$depth = 0;
			switch ( strtolower( $headers[1][$i] ) ) {
				case 'h1': $depth = 1 – $top_level + 1; break;
				case 'h2': $depth = 2 – $top_level + 1; break;
				case 'h3': $depth = 3 – $top_level + 1; break;
				case 'h4': $depth = 4 – $top_level + 1; break;
				case 'h5': $depth = 5 – $top_level + 1; break;
				case 'h6': $depth = 6 – $top_level + 1; break;
			}
			if ( $depth >= 1 && $depth <= $max_depth ) {
				if ( $current_depth == $depth ) {
					$toc_list .= '</li>';
				}
				while ( $current_depth > $depth ) {
					$toc_list .= '</li></ul>';
					$current_depth–;
					$counters[$current_depth] = 0;
				}
				if ( $current_depth != $prev_depth ) {
					$toc_list .= '</li>';
				}
				if ( $current_depth < $depth ) {
					$toc_list .= '<ul' . ( ( $current_depth == 0 ) ? ' class="toc-list"' : '' ) . '>';
					$current_depth++;
				}
				$counters[$current_depth – 1]++;
				$number = $counters[0];
				for ( $j = 1; $j < $current_depth; $j++ ) {
					$number .= '.' . $counters[$j];
				}
				$counter++;
				$toc_list .= '<li><a href="#toc' . ($i + 1) . '"><span class="contentstable-number">' . $number . '</span> ' . $headers[2][$i] . '</a>';
				$prev_depth = $depth;
			}
		}
		while ( $current_depth >= 1 ) {
			$toc_list .= '</li></ul>';
			$current_depth–;
		}
		$html = '';
		if ( $counter >= $this->atts['showcount'] ) {
			$this->add_script = true;
			$toggle = '';
			if ( strtolower( $this->atts['toggle'] ) == 'true' ) {
				$toggle = ' <span class="toc-toggle">[<a class="internal" href="javascript:void(0);">' . $this->atts['closetext'] . '</a>]</span>';
			}
			$html .= '<div' . ( $this->atts['id'] != '' ? ' id="' . $this->atts['id'] . '"' : '' ) . ' class="' . $this->atts['class'] . '">';
			$html .= '<p class="toc-title">' . $this->atts['title'] . $toggle . '</p>';
			$html .= $toc_list;
			$html .= '</div>' . "\n";
		}
		return $html;
	}
	public function add_script() {
		if ( !$this->add_script ) {
			return false;
		}
		$class = $this->atts['class'];
		$offset = is_numeric( $this->atts['offset'] ) ? (int)$this->atts['offset'] : – 1;
		$duration = is_numeric( $this->atts['duration'] ) ? (int)$this->atts['duration'] : '"' . $this->atts['duration'] . '"';
		$targetclass = trim( $this->atts['targetclass'] );
		if ( $targetclass == '' ) {
			$targetclass = get_post_type();
		}
		$targetclass = ".$targetclass :header";
		$opentext = $this->atts['opentext'];
		$closetext = $this->atts['closetext'];
		?>
<script type="text/javascript">
(function ($) {
  var offset = <?php echo $offset; ?>;
  var idCounter = 0;
  $("<?php echo $targetclass; ?>").each(function () {
    idCounter++;
    this.id = "toc" + idCounter;
  });
  $(".<?php echo $class; ?> a[href^='#']").click(function () {
    var href = $(this).attr("href");
    var target = $(href === "#" || href === "" ? "html" : href);
    var h = (offset === -1 ? $("#wpadminbar").height() + $(".navbar-fixed-top").height() : offset);
    var position = target.offset().top – h – 4;
    $("html, body").animate({scrollTop: position}, <?php echo $duration; ?>, "swing");
    return false;
  });
  $(".toc-toggle a").click(function () {
    var tocList = $(".toc-list");
    if (tocList.is(":hidden")) {
      tocList.show();
      $(this).text("<?php echo $closetext; ?>");
    } else {
      tocList.hide();
      $(this).text("<?php echo $opentext; ?>");
    }
  });
})(jQuery);
</script>
		<?php
	}
}
new Toc_Shortcode();

テーマの「a-insert-functions.php」へ追記する

「toc.php」のアップロードが終わったら、テーマ編集から「a-insert-functions.php」を開き、一番下の行へ以下のコードを追加して保存してください。

include 'toc.php';// もくじ出力
【注意】コードをコピーして使用する前に必ずお読みください

この記事内にコードが記載されている場合、コードはそのままコピー(いわゆるコピペ)してお使いいただいても構いませんが、以下の件にご留意ください。

使用については自己責任でお願いします

コードの確認は私の管理するサイト、またはテスト環境で問題が起こらなかったものですので、お使いの環境での動作等を保証するものではありません。

万が一このコードを使用してサイトに重篤なトラブルが生じても当サイト、当サイト管理者は一切責任を負いません

コードの変換エラーなどにより動作しない場合、更新エラーが出る場合があります

コードをそのままコピーしても問題なく使えるよう文字列変換を行った上で掲載しておりますが、希に変換できていない場合があり、コードエラーとなることがあります

その場合には以下の方法で修正を行ってみてください

  1. コードの中に全角の記号が入っていませんか?
  2. 半角にすることで解消できます
  3. コードの中に全角の空白(スペース)がありませんか?
  4. 半角にすることで解決できます
  5. コードは合っているはずなのに更新できないときは
  6. 特にエラーの出た行内に日本語での文字列が入っている場合には全角での文字列があるということでエラーになる場合があり、Wordpressのエディタチェックではこれを「’」や「)」など閉じ子のエラーとして認識され更新できないことがあります。エラーとして返される行の先頭に空白がある場合には空白をなくすことできちんと認識され更新されるようになることが多いです。
  7. 「何かが間違っています...」と表示され、更新できないときは
  8. このエラーは本当に何がエラーなのかをWordpressのチェックが判断できない場合に発生します。解決策としてはその画面を開き直すことなのですが、その際希に元のコードがすべて削除されてしまう場合がありますので、今表示されているコードを一旦どこかへコピーしてからページの再読み込みをするようにしてやり直します。
    ※このエラーは不明なエラーなので予期せぬ動きをする可能性がありますので特に慎重な対処が必要です
これらのエラー対処については以下のページが参考になるかも知れません

コードを転載する場合には

ご自身のサイトで当ページで紹介しているコードを転載される場合には当ページへのリンクを入れていただきますようお願いいたします

テーマの「a-insert-css.css」へ追記する

そのままの画面から今度は「a-insert-css.css」を開き、以下を追加後保存してください。

/* 以下、目次自動生成のデザインです。 */
.toc {
	width: 100%;
    display: table;
    margin: 15px 0px 15px 0px;
    padding: 10px 10px 10px 10px;
    color: #333;
    word-break: break-all;
    word-wrap: break-word;
    border: #ccc double 1px;
    background: linear-gradient(#fff, #777777);
	border-radius:5px;
}
.toc .toc-title {
    margin: 0;
    padding: 0;
    text-align: center;
    font-weight: bold;
}
.toc .toc-title a{
	text-decoration:none;
	color:#333;
}
.toc .toc-title a:hover{
	color:#fff;
	background-color:#777777;
}
.toc .toc-toggle {
    font-weight: normal;
    font-size: 90%;
    text-decoration:none;
}
.toc ul{
    list-style: none;
    margin-left:-25px;
}
.toc li a{
	text-decoration:none;
	color:#333;
}
.toc li a:hover{
	color:#fff;
	background-color:#777777;
}
.toc .toc-list {
    margin: 0;
    margin-left:0px;
    padding: 0;
	display:none;
	-webkit-animation: fadeIn 1.5s ease 0s 1 normal;animation: fadeIn 1.5s ease 0s 1 normal;}
	@keyframes fadeIn {
		0% {opacity: 0}
		100% {opacity: 1}
	}
	@-webkit-keyframes fadeIn {
		0% {opacity: 0}
		100% {opacity: 1}
}
/* 以上、目次自動生成のデザインでした。 */

これで目次を自動表示させるための前準備が完了しました。では実際に表示させる方法を紹介していきます

【ha-Basic】見ている記事と同一カテゴリーの人気記事一覧をサイドバーへ表示する方法

【ha-Basic】テーマでカスタム投稿タイプを使う場合の設定いろいろ

【ha-Basic】OGPタグの出力方法見直し


もくじを表示させる(機能を使用する)方法

任意の場所へもくじを表示させるには

冒頭のほうでちらっと紹介しましたが、表示させたい場所に

[toc]
というショートコードを入れるだけです。

この方法はいつもは目次などいらないけどhタグで読みやすくした長い記事のみ目次表示をしたい場合に有効です。

もくじを記事本文前へ自動表示させるには

どの記事にも共通して表示させる方法です。

テーマ編集から「single.php」を開き、36行目付近にある

<?php get_template_part('sns' ); //シェアボタンの読み込み ?>
<!–本文取得–>
という2行の間に
<!–もくじの表示–>
<?php echo do_shortcode('[toc]'); ?>
を挿入し、
<?php get_template_part('sns' ); //シェアボタンの読み込み ?>
<!–もくじの表示–>
<?php echo do_shortcode('[toc]'); ?>
<!–本文取得–>
という形にします(これでシェアボタンと本文の間に目次が表示されるようになります)。

※このサイトのように本文の上下に入れたい場合は

<?php get_template_part('sns' ); //シェアボタンの読み込み ?>
<!–もくじの表示–>
	<?php echo do_shortcode('[toc]'); ?>
<!–本文取得–>
	<?php if( !is_user_logged_in() && !is_bot() ) { set_post_views( get_the_ID() ); } ?>
	<?php the_content(); ?>
<!–もくじの表示–>
	<?php echo do_shortcode('[toc]'); ?>
という形にすればいいでしょう。

ひまあーと(管理人)
  • 記事の作者: ひまあーと(管理人)

  • ☆最後までお読みいただきありがとうございました。記事作者のひまあーとです。
    ☆Wordpressでサイトをカスタマイズしていく上で有用な情報を配信しつつ、「ココナラ」でサイトカスタマイズのお手伝い、不具合の修復、サイト引っ越し代行などをさせていただいております。
    ☆Wordpressネタが多いですが、趣味の「園芸」「卓球」などの情報や日々の出来事などもどんどん増やしていきますのでよろしくお願いいたします。


いつでもご相談・サイトカスタマイズの依頼を受け付けています

Wordpressのカスタマイズ、不具合解消のご相談はすべてココナラのダイレクトメッセージからお受けしております。まずはこちらのバナーからお気軽にお問い合わせください。

※一度もココナラを使ったことがない方はココナラへの無料登録が必要です。こちらから登録後、上のリンクをクリックする、またはココナラトップページから「ひまあーと」を検索してお問い合わせください。


【スポンサーリンク】


記事の拡散にご協力をお願いします

閲覧いただきありがとうございました。役に立つ情報でしたら是非SNSでシェアをお願いします

関連情報