LoginSignup
1

More than 3 years have passed since last update.

タグひとつで記事のサブタイトルを抽出して目次を自動生成する

Last updated at Posted at 2020-03-08

雑ですけど覚え書きです。yurubo.orgで書きました。

概要

任意のクラス要素(entryClassName)の中にあるh3要素の値を指定したクラス要素(toClassNmae) に吐き出して目次を作る機能です。Wordpressのプラグインに頼らずJavaScriptのみの実装です。

/** 記事から目次を作成する。
 *  @tocClassName 目次生成先のclass名
 *  @entryClassName 目次追加元のクラス名
 *  @addClass 見出しに追加したいclass名
 */
function makeTableOfContents(tocClassName, entryClassName, addClass='') {
  /** 対象classを全て格納 */
  let contentsList = document.getElementsByClassName(tocClassName);
  //配列に変換
  contentsList = Array.from(contentsList);
  /** 記事内のh3要素を全て格納 */
  const sectionList = document.querySelectorAll('.' + entryClassName + ' h3');

  //ulを生成
  let ol = document.createElement('ol');

  //取得した見出しタグ要素の数だけ繰り返す
  sectionList.forEach(function (value, i) {
    //idが空の場合はsection番号を追加
    if (value.id == '') {
      value.id = i+1;
    }
    //要素を生成
    let li = document.createElement('li');
    let a = document.createElement('a');

    //<a>見出し</a>
    a.innerHTML = value.textContent;
    //a要素にid追加
    a.href = '#' + value.id;
    //a要素にclass追加
    if (addClass != '') {
      a.classList.add(addClass);
    }
    //li要素にa要素を追加
    li.appendChild(a);
    //ol要素にli要素を追加
    ol.appendChild(li);
  });

  //tocClassNameのclassをもつ要素にすべて適用する
  contentsList.forEach(function (index){
    index.appendChild(ol.cloneNode(true));
  }); 
}

少しつまづいたところ

DOMの生成(ol要素)

上記のコードでは目次の要素となるolを生成し、最後の

contentsList.forEach()

で全部反映だ!って考えで書いたんですけども、ひとつの要素にしか反映されませんでした。

生成したDOMは複製してやらないといけない

はじめは

間違い
  contentsList.forEach(function (index){
    index.appendChild(ol);
  }); 

だったんですけど

正しい
  contentsList.forEach(function (index){
    //cloneNodeでクローン生成
    index.appendChild(ol.cloneNode(true));
  }); 

ってな感じでDOMを複製(クローン生成)してやらないといけないみたいです。参照の考えがへっぽこだったのでやられました。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1