FROM CACHE - jp_header
このコミュニティはピアツーピアサポートに移行しました。Shopify サポートは今後、このコミュニティへのサービスを提供いたしません。これからもぜひ、他のマーチャントやパートナーとつながり、サポートし合い、経験を共有してください。 当社の行動規範に違反する行動や削除を希望するコンテンツがありましたら、引き続きご報告ください
現在コミュニティを移動しています!7月7日以降、現在のコミュニティは約2週間読み取り専用となります。期間中はコンテンツの閲覧は可能ですが、一時的に新規投稿や返信はできなくなります。詳しくはこちら

ブログの目次で開閉ボタンを実装したい

ブログの目次で開閉ボタンを実装したい

watanabe1
観光客
10 1 5

いつもフォーラムで的確な回答をありがとうございます。

 

ブログに目次(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>

 

 

 

1件の返信1

Qcoltd
Shopify Partner
1426 549 529

@watanabe1 様

 

開閉についてですが、htmlで開閉部分の記述を<details>にし、

JavaScripやCSSでdetailsの見た目を調整することで、実現できるのではと思われます。

https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/details

 

ご参考まで。

(キュー小坂)

株式会社Q (キュー)
グラフィックデザイン、アパレル事業、Web制作など色々やっている渋谷区代々木の会社です。ShopifyでのECサイトの運営・開発も行なっています。
私たちについて: https://web.q-co.jp/ テックブログ: https://techlab.q-co.jp/