Blogger 目次を自動生成するスクリプト
Blogger には、デフォルトで目次を表示する機能がありません。
そこで自分好みの目次を目指し、アイデアやスクリプトをいろいろ探しつつ試行錯誤しながら目次の自動生成スクリプトを作成しました。
目次を表示したい箇所に特定のコードを設置すると、そこに目次が自動で生成されるという仕様です。
素人なので参考サイトのつぎはぎコードなんですが、使い方とあわせて紹介します。
出来上がりイメージはこの下に表示されている目次で、折りたたみ式になっています。
目次
目次の表示方法
今回作成した目次の自動生成スクリプトは、次のようなものです。
- h2 タグと h3 タグをピックアップして、階層にしてリスト化する
- details タグと summary タグを使って折りたたみ式にする
- 目次を表示したい箇所に、生成先を設置しておく
- 生成先が設置されていない場合は、目次表示されない
1. 以下のスクリプトを </body> タグの直前に設置します。
.post-body h2,.post-body h3
の部分は、目次生成の対象となる本文、タグを指定している箇所です。
<!-- TOC -->
<b:if cond='data:blog.pageType == "item"'>
<script>//<![CDATA[
var contentsList=document.getElementById('toc');if(contentsList){var tocContainer=document.createElement('ul');tocContainer.className="toc-container";let table_of_contents_counter=1;var matches=document.querySelectorAll('.post-body h2,.post-body h3');matches.forEach(function(value,i){var id=value.id;if(id===''){const id=`toc_${table_of_contents_counter++}`;value.id=id} if(value.tagName==='H2'){var li=document.createElement('li');var a=document.createElement('a');a.innerHTML=value.textContent;a.href='#'+value.id;li.appendChild(a);li.className="toc-list";tocContainer.appendChild(li)} if(value.tagName==='H3'){var ul=document.createElement('ul');var li=document.createElement('li');var a=document.createElement('a');a.innerHTML=value.textContent;a.href='#'+value.id;li.appendChild(a);li.className="toc-sublist";var lastLi=tocContainer.lastElementChild,lastUl;if(lastLi.getElementsByTagName("UL").length>0) lastLi.getElementsByTagName("UL")[0].appendChild(li);else ul.appendChild(li),lastLi.appendChild(ul)}});contentsList.appendChild(tocContainer)}
//]]></script>
</b:if>
2. 目次を表示したい記事に、生成先として以下を投稿内の HTML に設置します。このコードがある場所に目次が生成されます。
<details id="toc" open>
<summary class="toc-title">目次</summary>
</details>
3. CSS を追記します。以下はシンプルな CSS の例です。
#toc {
margin: 1em auto;
max-width: 600px;
border: solid 1px silver;
}
.toc-title {
background: silver;
padding: .5em;
}
.toc-container {
list-style: decimal;
}
#toc .toc-title:after {
content: '[ひらく]';
margin-left:.5em;
}
#toc[open] .toc-title:after {
content: '[とじる]';
}
目次のイメージ。
開いた状態 |
閉じた状態 |
スクリプトについての補足
toc
という ID の要素に目次を生成します。- .post-body 内にある h2, h3 をピックアップします。テンプレートに応じて、本文のクラス名(.post-body の部分)は修正する必要があります。
- h2 見出しのリストには
toc-list
というクラス名、h3 見出しのリストにはtoc-sublist
というクラス名をつけています。 - h2 見出しと h3 見出しが階層構造になります。
- 目次のリストには上から順に #toc_1, #toc_2 ... というリンクがつき、クリックすると各見出しに飛びます。
- h タグにすでに ID が振られている場合は、その ID がリンク先として用いられます。
- 生成先の details タグに
open
を入れておくと目次が開いた状態で表示され、open がないと閉じた状態で表示されます。open の記述の有無で、記事ごとに目次を開いた状態で表示するか閉じた状態で表示するかを指定できます。 - 折りたたみ式にしない場合は、次のような生成先コードにします。
<div id="toc"> <p class="toc-title">目次</p> </div>
- 生成先を設置しなければ目次は表示されないので、記事ごとに目次の表示・非表示を指定したい場合に有効なスクリプトです。全記事に一括・自動で目次を表示したい場合は、別のスクリプトが良いと思います。
参考サイト
- 見出しタグから入れ子の目次を自動作成するJavaScriptを作りました【コピペOK】 | まろりか
↑こちらのサイトのスクリプトをベースに修正を加えていきました。スクリプトの説明もこちらにあります。 - neputa note
↑上記参考サイトのスクリプトで、h3 見出しの ul と li の配置が理想形にならなかったときに、こちらのブログで使用されているコードを参考にさせていただきました。当ブログのスクリプトも neputa さんに見ていただけたので、私は素人ですが問題なく使えるコードだと思います - 【JavaScript】動的に目次を作成する - Qiita
↑ details タグと summary タグの構造にするときに参考にしたサイト - 【jQuery不要】JS で章番号 & リンク付きの目次を自動生成する - Hood
↑h2 〜 h6 まで目次の対象にしたい場合は、この参考サイトのスクリプトのほうが使いやすいと思います
今回の自動目次生成に至るまで
もともとは、Blogger 用として紹介されている別の目次生成スクリプトを利用していたのですが、当ブログの表示速度の問題なのか目次表示までにけっこう時差が感じられていました。
時差が気になっていたためその後目次は手動で作っていたのですが、やっぱり手動は大変で...。
やっぱり自動生成をしたくなったのですが、すでに多くの記事には手動で目次をつけてしまっていて、全記事に自動生成されるタイプのスクリプトはできれば使いたくない。これまで手動で作成した目次はそのままで、今後の記事にのみ自動反映させたい。
そこで調べていると、指定した div 要素等がある場合のみそこに目次を生成するタイプのスクリプトがあることを知り、表示記事、表示箇所を選べるならちょうど良い! ってことでその仕様にすることにしました。
手動目次では ul タグを使って h2 見出しと h3 見出しを階層にして囲んでいたので、スクリプトもできるだけその構造に近づけるようにしたかった。
また、li タグにはそれぞれクラス名をつけてすでに CSS を設定していたので、自動生成されるものも同じような出力になるようスクリプトの修正を試みました。
(いくつかのスクリプトを試してみて、クラス名がつけられないものは使用を断念)
目次表示までの時差に関しては、DOMContentLoaded っていうので遅くなってたのかも? と思い、そうしない書き方に変更。
details タグと summary タグを使ったのは、たまたまそういう仕組みで目次をつくっているサイトを見つけて、良さそうかなーと。折りたたみ式(表示・非表示切り替え式)の是非については正直わかりません。個人的には、非表示の目次をわざわざクリックして開くことはほとんどないし、表示されている目次をわざわざ閉じることもないんですよね。
ただまぁ、コードの参考サイトもあったので、どうせ新しくつくるなら折りたたみ式にしてみようかなと思いました。このタグたち、簡単に折りたたみ式にできて優秀ですね。ただ、手動目次は折りたたみになってないので、ブログ全体としては統一感に欠けることになりますが。
素人だしぜんぜんわかってないから試行錯誤してスクリプトを修正していったので、1つ修正しては動作を試し、また修正しては試し、うまくいかなかったら直し、、、で、完成したときはだいぶうれしかった。それに既存の CSS をほとんど修正しなくてよかったのもよかった。
わりとすばやく表示されるのも満足です。
目次をつくらなくて良いって、ほんとーに楽!