雑ですけど覚え書きです。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を複製(クローン生成)してやらないといけないみたいです。参照の考えがへっぽこだったのでやられました。