Blog Archive をプルダウン表示にする

<!-- markdown-mode-on --> <img alt="jettheme logo" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEih6tkuCAB6zwNyTYCvTrA07cGstQGH7GBjCipsk3a6HoUiKVea-159v4oK4uq7qhXUjbbnX0Hm5Fds5sw7iiCzhqObJHwcnKQEf9-0iAqgpH6bSzH6FxQCVVBh-XrghyphenhyphenMUwaIjVewBQXI/s1600/jettheme-cover.png" style=" display: none;"/> ## 概要 Jettheme の Blog Archive は、「階層(HIERARCHY)」、「フラット(FLAT)」、「プルダウン(Menu)」の3スタイルある。手抜きかもしれないが、 - 「階層(HIERARCHY)」は、階層が1列縦に並んでいるだけで、見栄え、使い勝手ともに最悪だ。 - それに加えて、「プルダウン(Menu)」と「フラット(FLAT)」はと同じだ。(バグではなく仕様) <img alt="Blog Archive" data-original-height="734" data-original-width="790" height="595" src="https://blogger.googleusercontent.com/img/a/AVvXsEg0dh0ajsTBtM9MpUyIiNLZ9yBekeYj1hc1jKblii4_mf_LYq3-iaejKRiKZehZXL4jy-PXlFLf7O35bapfYvcOiewzVZAwPIyPduOMXU99PnW-A6wstfTrhbVzAUR5VIaopO3mWwPA1bJ3GtpEglX5RAyobmy21NO5z_T5Anu2KyJN2Dgq2levWTLX4p_8=w640-h595" width="640"/> <br/> <br/> 他のデザインテーマで見られるようなプルダウンスタイルのBlog Archive を作ることにした。下記が完成したDIY Blog Archiveだ。 <br/> <div style="text-align: center;"> <img alt="DIY Blog Archive" border="0" data-original-height="238" data-original-width="174" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlSZA_-vD5rtnlRTrek5gSQL1QsjRzDfuFb5Exg7_moEozsNRQKbd4JZqp2iF3qIXV_Tr-KdY738YAKQBW9oNGhtg-uAVdv1840mDFkhyACi4rATK0He6MkVc6kwz9qweBrJljmDck_Z24d8gFVEa-7OQCNOjbyte4gvAlGNQcW2zfXx_eTm3o1utk9Dnz/w468-h640/image.png" width="240"/> </div> <a name="more"></a> ## スクリプト テーマxmlから、` <b:includable id="JetBlogArchiveHierarchy" var="intervals"> `を探し、` </b:includable> ` までを次のスクリプトと入れ替える。 <details> <summary>Archiveスクリプト</summary> ```html <b:includable id="JetBlogArchiveHierarchy" var="intervals"> <ul class="hierarchy list-unstyled border-start border-2 jt-border-light ps-2 mb-0 year-list"> <b:loop values="data:intervals" var="interval"> <li class="mb-2 pe-2 year-item"> <div class="hierarchy-toggle-wrap"> <button aria-expanded="false" class="toggle-button" type="button">▶</button> <a class="text-reset fw-bold hover-text-primary archive-link" expr:href="data:interval.url"> <span class="archive-name"><data:interval.name></data:interval.name></span> <span class="ms-1 fw-light fs-9">[<data:interval.post-count></data:interval.post-count>]</span> </a> </div> <div class="hierarchy-content month-list" style="display: none;"> <b:include cond="data:interval.data" data="interval.data" name="JetBlogArchiveHierarchy"></b:include> <b:if cond="data:interval.posts"> <ul class="hierarchy-posts list-unstyled border-start border-2 jt-border-light ps-2 mb-0 day-list"> <b:loop values="data:interval.posts" var="post"> <li><a class="text-reset fs-7 hover-text-primary" expr:href="data:post.url"><data:post.title></data:post.title></a></li> </b:loop> </ul> </b:if> </div> </li> </b:loop> </ul> <script type="text/javascript"> //<![CDATA[ window.onload = function () { const buttons = document.querySelectorAll('.toggle-button'); buttons.forEach(button => { button.addEventListener('click', function () { const parentItem = this.closest('.year-item'); const monthList = parentItem.querySelector('.month-list'); if (monthList) { const isExpanded = monthList.style.display === 'block'; monthList.style.display = isExpanded ? 'none' : 'block'; button.textContent = isExpanded ? '\u25B6' : '▼'; // Unicodeの右向き三角 button.setAttribute('aria-expanded', !isExpanded); } }); }); }; //]]> </script> <style type="text/css"> .month-list { margin-left: 15px; } .day-list { margin-left: 30px; } .hierarchy-toggle-wrap { display: flex; align-items: center; gap: 0.3em; } .toggle-button { color: inherit; /* 親要素から色を継承 */ background: none; border: none; font-size: 0.5em; cursor: pointer; padding: 0; margin: 0; line-height: 1; } .hierarchy-toggle-wrap:hover .toggle-button { color: var(--jt-primary); } .archive-link { display: inline-block; text-decoration: none; } .archive-name { vertical-align: middle; } </style> </b:includable> ``` </details> ## 使い方(設定) 「管理画面」→「レイアウト」→「Sidebar」→「Blog Archive」→「編集」→「スタイル」→「**階層**」を選択する。 「階層(HIERARCHY)」の仕組み(データ授受、処理など)を使って、表示を変更しているので、「**階層**」を選択すると、この改造スクリプトが動く仕組みだ。 <div style="text-align: center;"> <img alt="Style" border="0" data-original-height="604" data-original-width="403" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0HNHV-8-bGOJx5gDl1QwyjYR6Zj5xa1U2upehAUCWH2fSnK13nBx_q7VEnX26witoXznIvVfwC7VXuEuYK9EtNHMitL5G_bCSvXQ6EYcsVC7GKR32zLcg1sfhevcrYUfhBz5MQ5aIZG3ffKY3w6hXHgf9KhO_zvxCXvd-vW917UalHtQYaqvWosN37e8T/s320/image.png" width="400"/> </div> ## 蛇足 本来なら、「階層(HIERARCHY)」スタイルはそのままにして、オリジナルのコードには記述されていない「プルダウン(Menu)」を使うのがスマートな方法だ。 しかし残念ながら、この方法はうまく動くスクリプトを作ることができなかった。「プルダウン(Menu)」の選択をすると、アーカイブリストは表示されるのだが、プルダウンさせることがどうやってもできなかった。「**階層**」の仕組みをそのままコピーしてあてはめても、「**階層**」では正常に動くスクリプトが「**メニュー**」では動かない。 そこでしかたなく、単独で「**階層**」の仕組みを使うことにした。 ## 十分じゃないけど、これが限界 機能上の不具合がある。 - 当該年(例えば、2025)では、"▶" をクリックすると、月ごとのアーカイブリストにプルダウンする。 - 当該月の"▶" をクリックすると、その月の投稿記事リストにプルダウンする。 - しかし、当該年以外の年で"▶" をクリックしても、なにも起こらない。プルダウンしない不具合がある。 これも対策できなかった。 年/月をクリックすると、その年や月の記事一覧が抽出される。この状態(**抽出された一覧の状態**)では、 - 当該年(例えば、2025)では、"▶" をクリックすると、月ごとのアーカイブリストにプルダウンする。 - 当該月の"▶" をクリックすると、その月の投稿記事リストにプルダウンする。 これらの動作は、 <b> Jettheme 本来の動作(仕様) </b> のようだ。オリジナルの jettheme-v2.xml を一時的に導入して、それを確認した。 ### 問題の根源 <b>1. JetThemeのデータ構造</b> JetThemeが階層化されたアーカイブデータを生成する際に、**現在表示されている期間(年または月)以外の詳細な投稿記事リストを一度にすべて提供しない**ものと思われます。 つまり、**現在の表示とは異なる年や月では、`data:interval.data`や`data:interval.posts`が空、あるいは必要な情報を含んでいないため、HTML自体が生成されていない**のです。 <b>2. スクリプトの実行タイミングと対象 </b> **JavaScriptのwindow.onloadはページが完全に読み込まれたときに一度だけ実行されます**。この時、JavaScriptは現時点(ページの初回読み込み時)でDOMに存在する要素にのみイベントリスナーを割り当てます。 問題の現象は、**現在の表示とは異なる年や月では、**一度クリックして「抽出された一覧の状態」にするまでは、その年/月の内部にある**月ごとのアーカイブリストや記事リストがそもそもHTMLとして存在しない**ため、JavaScriptが「▶」ボタンをクリックしても、表示/非表示を切り替える**対象の要素を見つけられない**ために発生しています。 「その年/月をクリックして、**その年や月の記事一覧が抽出された状態」にするとプルダウン表示できるのは、そのクリックによってJetThemeが必要なアーカイブデータを動的にロードし、DOMに要素が追加される**ためです。その後、JavaScriptがその新しく追加された要素を認識して動作するようになる、という流れです。 <b>3. 動的にデータ取得</b> JetThemeの代わりに、スクリプトで各年や月の投稿リストを動的に取得するためには、「どの種類のデータ(年か月か)」と「どこからデータを取得するか(URL)」をJavaScriptに教える情報が不可欠になります。そのために`data-type`と`data-url`といったデータ属性をHTML要素に埋め込みます。 しかし、これらのデータ属性に埋め込むこと自体が、BloggerのXMLパーサーによってSyntaxErrorを引き起こし、スクリプトが機能しなくなります。 ## 参考:ブログアーカイブ構成/ オリジナルの jettheme-v2.xml 以下は、 <img alt="Google Gemini Logo" height="32" src="https://upload.wikimedia.org/wikipedia/commons/8/8a/Google_Gemini_logo.svg" style="display: inline-block; vertical-align: baseline;" width="75"/> で解析した内容になる。 ご指摘ありがとうございます。おっしゃる通り、オリジナルの Jettheme XML には `<b:includable id="JetBlogArchiveMenu">` は存在しません。私の説明に誤りがありました。深くお詫び申し上げます。 オリジナルの Jettheme XML におけるブログアーカイブの構成を説明します。 **オリジナルの Jettheme XML ブログアーカイブ構成(再説明):** 1. **`<b:widget-settings>`:** ブログアーカイブの表示スタイル (`<b:widget-setting name="showStyle">`) などの設定を格納。`HIERARCHY`(階層)、`FLAT`(フラットリスト)などの値を持ちます。`MENU`(プルダウンメニュー)に対応する `<b:widget-setting>` は通常、デフォルトでは存在しません。 2. **`<b:includable id="main">`:** ウィジェットの主要なレンダリング処理を記述。通常、`<b:include name="JetBlogArchive"></b:include>` を呼び出します。 3. **`<b:includable id="JetBlogArchive" var="this">`:** `showStyle` の値に基づいて、異なる表示形式の includable を条件分岐 (`<b:if>`) で呼び分けます。 * **`HIERARCHY` の場合:** `<b:include data="data" name="JetBlogArchiveHierarchy"></b:include>` を呼び出し、階層的なリストを表示。 * **`FLAT` の場合:** `<b:else></b:else>` ブロック内のコードが実行され、`<b:loop>` を用いて年月をフラットなリストとして表示する HTML 構造を直接記述。 * **`MENU` の場合:** オリジナルには `MENU` スタイルに対する明示的な処理は記述されていません。そのため、デフォルトでは `HIERARCHY` の条件に合致しない場合に実行される `<b:else></b:else>` ブロック(フラットリスト表示)が適用されると考えられます。 4. **`<b:includable id="JetBlogArchiveHierarchy" var="intervals">`:** 年月ごとの階層構造を持つリストを表示する HTML (`<ul>`, `<li>`) と、年月ごとのリンク (`<a>`)、投稿数を記述。必要に応じて、さらに月ごとのリストなどを再帰的に表示 (`<b:include data="interval.data" name="JetBlogArchiveHierarchy"></b:include>`)。 5. **`<b:includable id="JetWidgetTitle">`:** ウィジェットのタイトル部分 (`<h2>` など) を表示する共通 includable。 ## 関連リンク </h2></b:includable></a></li></ul></b:includable></b:loop></b:if></b:includable></b:includable></b:widget-setting></b:widget-setting></b:widget-settings></b:includable>
Next Post Previous Post