すたすた式
Blogger QooQ
目次が開閉可能な場合、初期値で開く設定にするのか、閉じる設定にするのか、それぞれ好みがあると思います。
自分は開く派ですが、見出しの多い記事だと、目次が長くなりすぎるので気になっていました。
そこで、「初期値は閉じた状態だけど、見出しの数が一定以下の場合は開く機能」を追加してみました。
以前書いたJavaScriptに3行追加、タグ2か所変更+CSSでなんとかなりました。
別の解決策もありましたが、自分の実力だと実装までに時間がかかりそうだったので、とりあえず既存の知識でやってみました。
HTMLを編集します。必ずバックアップを取ってから作業してください。
まず、以前書いたJavaScriptの該当部分のdivをdetailsとsummaryにそれぞれ変更。
div
details
summary
変更後
// 目次が入るdiv要素を作成 const tocWrapper = document.createElement("details"); // id="toc-wrapper"を追加 tocWrapper.id = "toc-wrapper"; // class="toc-wrapper"を追加 tocWrapper.className = "toc-wrapper";
// タイトルが入るdiv要素を作成 const tocTitle = document.createElement("summary"); // id="toc-title"を追加 tocTitle.id = "toc-title"; // class="toc-title"を追加 tocTitle.className = "toc-title"; // テキストを追加 tocTitle.textContent = "目次"; // 目次が入るdiv要素に出力 tocWrapper.appendChild(tocTitle);
次に、
const tocElements = parentElement.querySelectorAll("h2:not(details h2), h3:not(details h3)");
の下に
if (tocElements.length <= 6) { tocWrapper.open = true; }
を追加。
tocElements.length <= 6で見出しの数を指定します。この場合は見出しの数が6個以下で開く。
tocElements.length <= 6
追加後
// .post-body以下の(details要素内のh2, h3要素を除く)h2,h3要素を全て取得 const tocElements = parentElement.querySelectorAll( "h2:not(details h2), h3:not(details h3)" ); if (tocElements.length <= 6) { tocWrapper.open = true; }
上記変更済みのJavaScriptです。
<script> // Reference /*! 目次 toc: https://www.marorika.com/entry/create-toc */ // Blogger用 //<![CDATA[ (() => { // 見出しの取得先と目次の出力先親要素を取得 const parentElement = document.querySelector(".post-body"); /*------------------------------ ここから目次を作成しない条件 ------------------------------*/ // id名no-tocがあったら目次を作成しない const noToc = document.getElementById("no-toc"); if (noToc !== null) return; // .post-body以下の(details要素内のh2要素を除く)h2要素を全て取得 const findHeadings = parentElement.querySelectorAll("h2:not(details h2)"); // h2要素が2個以下だったら作成しない if (findHeadings.length <= 2) return; /*------------------------------ ここまで目次を作成しない条件 ------------------------------*/ // 目次が入るdiv要素を作成 const tocWrapper = document.createElement("details"); // id="toc-wrapper"を追加 tocWrapper.id = "toc-wrapper"; // class="toc-wrapper"を追加 tocWrapper.className = "toc-wrapper"; /*------------------------------ ここから目次のタイトル作成 ------------------------------*/ // タイトルが入るdiv要素を作成 const tocTitle = document.createElement("summary"); // id="toc-title"を追加 tocTitle.id = "toc-title"; // class="toc-title"を追加 tocTitle.className = "toc-title"; // テキストを追加 tocTitle.textContent = "目次"; // 目次が入るdiv要素に出力 tocWrapper.appendChild(tocTitle); /*------------------------------ ここまで目次のタイトル作成 ------------------------------*/ // 目次コンテナ用にul要素を作成 const tocContainer = document.createElement("ul"); // id="toc-container"を追加 tocContainer.id = "toc-container"; // class="toc-container"を追加 tocContainer.className = "toc-container"; /*------------------------------ ここから目次を出力する場所を取得 ------------------------------*/ // .post-body以下の(details要素内のh2要素を除く)1個目のh2要素を取得 const target = parentElement.querySelectorAll("h2:not(details h2)")[0]; // .post-body以下の1個目のh2要素を取得 //const target = parentElement.querySelectorAll("h2")[0]; /*------------------------------ ここまで目次を出力する場所を取得 ------------------------------*/ // .post-body以下の(details要素内のh2, h3要素を除く)h2,h3要素を全て取得 const tocElements = parentElement.querySelectorAll( "h2:not(details h2), h3:not(details h3)" ); if (tocElements.length <= 6) { tocWrapper.open = true; } // 取得した見出しタグ要素の数だけ以下の操作を繰り返す tocElements.forEach((value, i) => { // 見出しタグ要素のidを取得。空の場合は"見出しタイトル" + "_TOC-No." + "数字"をidにする let id = value.id; if (id === "") { id = value.textContent + "_TOC-No." + i; //id = i; // 数字のみ value.id = id; } // 要素が h2 タグの場合 if (value.tagName === "H2") { const li = document.createElement("li"); const a = document.createElement("a"); a.textContent = value.textContent; a.href = "#" + value.id; li.appendChild(a); tocContainer.appendChild(li); } // 目次コンテナ用 ul 要素の最後の子要素を取得 const lastElement = tocContainer.lastElementChild; // 要素が h3 タグかつ目次コンテナ用 ul 要素の最後の子要素が li 要素の場合 if (value.tagName === "H3" && lastElement.tagName === "LI") { const ul = document.createElement("ul"); const li = document.createElement("li"); const a = document.createElement("a"); a.textContent = value.textContent; a.href = "#" + value.id; ul.appendChild(li); li.appendChild(a); lastElement.appendChild(ul); } // 要素が h3 タグかつ目次コンテナ用 ul 要素の最後の子要素が ul 要素の場合 if (value.tagName === "H3" && lastElement.tagName === "UL") { const li = document.createElement("li"); const a = document.createElement("a"); a.textContent = value.textContent; a.href = "#" + value.id; li.appendChild(a); lastElement.appendChild(li); } }); // 目次コンテナ用ul要素を目次が入るdiv要素に出力 tocWrapper.appendChild(tocContainer); // .post-body以下にある1個目のh2要素の上に目次を出力 target.before(tocWrapper); // .post-body以下にある1個目のh2要素の下に目次を出力 //target.after(tocWrapper); // .post-body 以下の最初の要素として目次を出力(記事・ページのトップに出力される) // parentElement.prepend(tocWrapper); // ここからスムーススクロール // ここにスムーススクロールのコードを貼り付ける // ここまでスムーススクロール })(); //]]>
#toc-wrapper { margin: 0.5em 0; } #toc-title { font-weight: bold; color: #fff; padding: 0 1em; background: #464555; list-style: none; cursor: pointer; border-radius: 30px; text-align: center; } #toc-title::-webkit-#toc-wrapper-marker { display: none; } #toc-title:hover { background: #383744; } #toc-wrapper[open] * { animation: fadein 0.4s ease; } @keyframes fadein { 0% { opacity: 0; } 100% { opacity: 1; } } #toc-wrapper #toc-title::before { margin-right: 0.25em; color: #fff; font-weight: bold; font-size: 1.5em; font-family: SFMono-Regular, Consolas, "Courier New", "BIZ UDGothic", Meiryo, monospace; content: "+"; } #toc-wrapper[open] #toc-title::before { content: "-"; } #toc-wrapper #toc-title::after { content: "[*ひらく]"; font-size: 0.9em; font-weight: normal; margin-left: 0.75em; } #toc-wrapper[open] #toc-title::after { content: "[*とじる]"; } #toc-container { border-bottom: solid 1px #464555; } #toc-container li { line-height: 2; }
サイト内検索に使ってください 🐤
© 2015 すたすた式
Enjoy!👍
QooQ
コメントなし:
コメントを投稿