JavaScriptを使用してWordPressの投稿に目次を挿入する

最近のWordpressブログには目次を良く見る。確かに目次があればブログの内容がわかりやすい。というわけで導入してみた。

目次

記事に目次をつけよう

目次があれば、結末まですぐに飛ぶことができる。

時間に追われる現代人にはなくてはならない機能である。

そこで本サイトに目次を導入した。

プラグインは使いたくないよう

個人的にプラグインには頼りたくない。

理由はシンプルで楽しくないからである。

どうせ作るなら自分自身の力で作成したい。

なので今回も自作した。

目次を挿入するための考え方

やりたいことはページが開かれた時に記事に目次を挿入する。

で、対象はh2タグとh3タグとする。

つまり、記事内にh2タグとh3タグがあるかを判定し、あればそれに対応する目次を挿入する。

実現コードはこちら

// 目次を生成
let secondIdCount = 1
let ThirdIdCount = 1
const headingSecond = document.querySelector('.article-detail')?.querySelectorAll('h2')
const headingThird = document.querySelector('.article-detail')?.querySelectorAll('h3')
if (headingSecond !== undefined || headingThird !== undefined) {

    headingSecond.forEach(el => {
        el.id = `tocSecond-${secondIdCount}`
        secondIdCount++
    });
    headingThird.forEach(el => {
        el.id = `tocThird-${ThirdIdCount}`
        ThirdIdCount++
    });

    const target = document.querySelectorAll(`[id^='toc']`)

    const insertTarget = document.querySelector('.article-table-of-contents-insert')
    if (target.length === 0) {
        document.querySelector('.article-table-of-contents').style.display = 'none'
    } else {
        target.forEach((el) => {
            if (el.nodeName === 'H2') {
                insertTarget.insertAdjacentHTML('beforeend', `<p class="second" onclick="smoothScroll('${el.id}')">${el.innerText}</p>`)
            } else {
                insertTarget.insertAdjacentHTML('beforeend', `<p class="third" onclick="smoothScroll('${el.id}')">${el.innerText}</p>`)
            }
        });
    }
}

// スムーススクール
const smoothScroll = (el) => {
    const box = document.querySelector('.content')
    const scrollY = box.scrollTop
    const target = document.getElementById(el).getBoundingClientRect().top
    const headerHight = document.getElementById('header').clientHeight
    box.scrollTo({
        top: target - headerHight + scrollY,
        behavior: 'smooth'
    })
}

前提として記事内に、

<div class="article-table-of-contents">
  <p class="title">目次</p>
  <div class="article-table-of-contents-insert">


  </div>
</div>

という要素を書いておく必要がある。

実現コードを書き下してみる

事前に必要な情報を定義する

// 目次を生成
let secondIdCount = 1
let ThirdIdCount = 1
const headingSecond = document.querySelector('.article-detail')?.querySelectorAll('h2')
const headingThird = document.querySelector('.article-detail')?.querySelectorAll('h3')

まずは諸々定義する。

IDに連番を振るので、基準の数字。

記事内にある、h2タグとh3タグ。

連番IDを付与する

headingSecond.forEach(el => {
    el.id = `tocSecond-${secondIdCount}`
    secondIdCount++
});
headingThird.forEach(el => {
    el.id = `tocThird-${ThirdIdCount}`
    ThirdIdCount++
});

const target = document.querySelectorAll(`[id^='toc']`)

事前に定義した情報をもとにh2タグh3タグに連番IDを振る。

IDを振った要素を取得する。

対象を目次に挿入していく

const insertTarget = document.querySelector('.article-table-of-contents-insert')
if (target.length === 0) {
    document.querySelector('.article-table-of-contents').style.display = 'none'
} else {
    target.forEach((el) => {
        if (el.nodeName === 'H2') {
            insertTarget.insertAdjacentHTML('beforeend', `<p class="second" onclick="smoothScroll('${el.id}')">${el.innerText}</p>`)
        } else {
            insertTarget.insertAdjacentHTML('beforeend', `<p class="third" onclick="smoothScroll('${el.id}')">${el.innerText}</p>`)
        }
    });
}

まず、挿入する要素を取得する。

次に先ほど取得したtagertが、H2であればh2に紐づくHTMLを。

H3であればh3に紐づくHTMLをどんどん挿入していく。

クリック時に対象要素にスクールする

// スムーススクール
const smoothScroll = (el) => {
    const box = document.querySelector('.content')
    const scrollY = box.scrollTop
    const target = document.getElementById(el).getBoundingClientRect().top
    const headerHight = document.getElementById('header').clientHeight
    box.scrollTo({
        top: target - headerHight + scrollY,
        behavior: 'smooth'
    })
}

上記はヘッダーの高さを取得しているので、そこは適宜変更してほしい。

技術を書く技術がない

うーん。

色々書いたが、うまく伝えられない。

考え方さえわかれば難しくないと思うので、挑戦してみてほしい。

わからなければコメントを残してもらえれば個人的に解説をするので、どんどんコメントしてください。

次に読むおすすめ記事

今更ながら、即時関数がとでも便利でかっこいい

Vue3のベースプロジェクトを作成したので、仕上げにhuskyを導入する

Javascriptで任意の値を持つn個の配列を作成する

JavaScriptで2つの配列を比較し、一致したものを取り出す方法コード

JavaScriptで文字列falseをBoolean型に変更しようとして沼に落ちた

この記事に対するコメント

サブドメインでアドセンスに申請したので、実況中継する。 | ウェブ制作を手掛ける「nove」のオウンドメディア へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です