いつもフォーラムで的確な回答をありがとうございます。
ブログに目次(TOC)を別のサイトを参考にして導入しています。現状でも充分なのですが、文字数が多く比例して目次が多くなると、少し読みづらい印象のため、目次に開閉ボタンを付けたいと思っています。
調べるとJavaScriptに追加スクリプトを書くまでは理解できましたが、その先に進めません。
解決のお力をお願いしたいです、よろしくお願いします。コードは下記となります。
toc.js
{
const TOC_INSERT_SELECTOR = '#toc';
const HEADING_SELECTOR = 'h1,h2,h3,h4,h5,h6';
const LINK_CLASS_NAME = 'tocLink';
const ID_NAME = 'heading';
const tocInsertElement = document.querySelector(TOC_INSERT_SELECTOR);
const tocTarget = document.querySelector('#toc_target');
const headingElements = tocTarget.querySelectorAll(HEADING_SELECTOR);
const layer = [];
let id = 0;
const uid = () =>`${ID_NAME}${id++}`;
let oldRank = -1;
try {
const createLink = (el) => {
let li = document.createElement('li');
let a = document.createElement('a');
el.id = el.id || uid();
a.href = `#${el.id}`;
a.innerText = el.innerText;
a.className = LINK_CLASS_NAME;
li.appendChild(a);
return li;
};
const findParentElement = (layer, rank, diff) => {
do {
rank += diff;
if (layer[rank]) return layer[rank];
} while (0 < rank && rank < 7);
return false;
};
const appendToc = (el, toc) => {
el.appendChild(toc.cloneNode(true));
};
headingElements.forEach( (el) => {
let rank = Number(el.tagName.substring(1));
let parent = findParentElement(layer, rank, -1);
if (oldRank > rank) layer.length = rank + 1;
if (!layer[rank]) {
layer[rank] = document.createElement('ol');
if (parent.lastChild) parent.lastChild.appendChild(layer[rank]);
}
layer[rank].appendChild(createLink(el));
oldRank = rank;
});
if (layer.length) appendToc(tocInsertElement, findParentElement(layer, 0, 1));
} catch (e) {
//error
}
}
toc.css
html {
scroll-behavior: smooth;
}
#toc {
padding: 1.5em;
margin-bottom: 1em;
border: 1px solid #ccc;
}
#toc ol {
list-style: none;
counter-reset: toc;
padding-left: 2em;
margin: 0;
}
#toc ol li::before {
counter-increment: toc;
content: counters(toc, "-");
display: inline;
padding-right: .5em;
margin-left: -2em;
}
main-article.liquidに下記を追加しています。大幅に省略しています。
{% comment %}上部にcssを追記{% endcomment %}
{{ 'toc.css' | asset_url | stylesheet_tag }}
{% comment %}article.contentに以下を追記{% endcomment %}
〜 省略 〜
<div id="toc_target" class="article-template__content page-width page-width--narrow rte" itemprop="articleBody" {{ block.shopify_attributes }}>
<div id="toc"></div>
{{ article.content }}
</div>
〜 省略 〜
<script src="{{ 'toc.js' | asset_url }}" defer></script>