JavaScriptで記事の目次を生成する方法

schedule Published
Category folderJumble
format_list_bulleted Contents

このブログで実装したJavaScriptで記事の目次を作る方法を紹介。
JSファイルだけなので、CMSやプラグインなどの影響がなく、一番手軽な実装じゃないかと思う。

JavaScriptを調べる準備

非エンジニアがコードをいきなり書きだすのは無理なので、JSにやってほしいことを整理する。

JSに自動でやってほしいこと

h2タグを目次にする前提とする。

  • ページ内のh2を全て取得
  • 取得したh2の数に応じて実行
    • 目次にするli要素を生成
    • 生成した目次のli要素に、h2から取得したテキストを追加する
    • h2に重複しないid属性を追加
    • 目次のli要素の子となるa要素を生成
    • 生成したa要素のhref属性に、h2要素に追加したid属性を追加
    • li要素の子要素にa要素を挿入
    • ページ内のul要素に生成したli要素を挿入

必要なコードを調べる

今のところエンジニアを目指してはいないので、必要そうなものだけを調べる。

ページ内のh2を取得

document.querySelectorAll()を使う。
該当する要素を全て取得して、配列っぽいオブジェクトを返す。ここで注意なのは配列ではないということ。 console.logをみるとNodeListと出力される。

また、document.getElementsByTagName()を使っても取得できる。
こちらも配列っぽいオブジェクトを返すが、こちらはHTMLCollectionとなっている。

NodeListとHTMLCollectionの違い

ドキュメントを見ると、document.querySelectorAll()で取得したNodeListは静的 (ライブではない) 、HTMLCollectionは動的(生きたもの)とある。

取得したh2の数だけ繰り返す

ページ内のh2の取得方法によって少し変わる部分もある。

NodeListもHTMLCollectionも配列風のオブジェクトだが、「NodeListはArrayとは異なりますが、forEach() メソッドで処理を反復適用することは可能」とのこと。
HTMLCollectionの方はforEach() メソッドを使えない。
NodelistはforEach() が使えるが、IE11でサポートされていないので、使われることが少なかったかもしれない。今はIE11に配慮する必要がなくなったので、今は気にする必要はなさそう。

NodeListにもHTMLCollectionにもプロパティにlengthがあるので、数を取得してfor文で処理を繰り返せば配列風なのにどっちが配列のfor each。

またArray.prototype.forEach.call(obj, …)を使えば、どちらでも使え、IE11でも動作する。

目次のli要素の生成

document.createElement()を使って生成する。

h2にid属性を設定する

element.idelement.setAttributeを使って、h2にidを設定する。
今回はelement.idを使った。

h2のテキストを取得して・目次のli要素に追加する

NodeのプロパティtextContentを使って取得・追加する。

混同しやすいプロパティにinnerTextinnerHTMLがあるらしいので、それぞれのプロパティを見ておく。

また、そもそものHTMLのDOMを理解するために、The HTML DOM APIopen_in_newのプロパティやメソッドの継承などを見ながら調べた。

親要素に子要素を挿入する

今回は繰り返し処理で順番に追加するので、末尾に追加するNode.appendChild()メソッドを使った。

繰り返し処理でリアルDOMに要素を1つずつ挿入すると、都度ブラウザの再フローが起きるので、いったんDocumentFragmentに挿入して、すべて完了したらDocumentFragmentをリアルDOMに挿入する。DocumentFragmentは、document.createDocumentFragment()メソッドを使って生成する。

コードを書く(サンプルコード紹介)

調べた内容で書いたサンプルコードです。

外部JSの場合はdefer属性を使って読み込むなどで、実行タイミングを調整してください。

おわりに

このブログでは目次を固定表示しているので、カレント機能やスクロール率の表示なども追加した。

まずやりたいことの整理ができれば、非エンジニアでも調べるのは簡単だった。
ドキュメントを読んでおくと、ちょっとずつできることが増えて応用がきくので、ソースをコピーするよりオススメです。