【Blogger】JavaScript を使わない年別・月別アーカイブ用ページャー

以前、Blogger の月別アーカイブページのページャー(ページネーション)の作成方法を書いた。

上の記事では、アーカイブウィジェットを利用して、元からブログにあるページャーの a タグの href 属性と内部テキストの文字を JavaScript で書き換えることで月別ページャーを作成している。

しかしながら、投稿してから数ヶ月も経たないうちに以下の JS 不要のアーカイブ用ページャーの記事を見つけたので、光の速さでこちらに乗り換えた。

だから本来ならこの記事は必要ないはずなのだが、今後のカスタマイズのためにも自力でアーカイブページャーを作ってみようと思い立った。その結果を記事にする。

年月・月別アーカイブ用ページャーの導入方法

本カスタマイズでは、階層(hierarchy)型のブログアーカイブガジェットを利用してページャーを導入する。

アーカイブガジェットは 1 ブログにつき 2 個しか設置できず、3 個目を設置しようとするとエラーが出てしまう。すでに 2 つも設置しているブログは稀有だろうけれど、念のため注意。

また、投稿頻度が多いブログだと特に年別アーカイブでは投稿が 1 ページに納まらない可能性がある。その場合、その月の残りの投稿を表示する方法がなくなってしまう。

最後に、このページャーは日別アーカイブ data:view.arichive.day には対応していない。ひとえにめんどくさかったからです。冒頭で紹介したクラウド番外地さんのページャーなら日別アーカイブにも対応しているので、そちらを使うのがおすすめ。

既存のページャーを非表示にする

ブログアーカイブウィジェット内にページャーを表示するため、年別・月別アーカイブページでは既存のページャーを非表示にする必要がある。

テーマによって差があるため一概には言えないが、バージョン 1 のブログ投稿ウィジェットなら記事一覧ブロックに以下のコードがあるはずなので、

<b:inculude name='nextprev'/>

それをこちらのコードに変更する。

<b:inculude cond='!data:view.archive.year and !data:view.archive.month' name='nextprev'/>

ページャーのコードを設置する

上の項の操作ができたら、以下のコードをブログの投稿ウィジェットの </b:widget> の直後に貼り付けて保存する。

<b:widget cond='data:view.archive.year or data:view.archive.month' id='BlogArchive0' locked='true' title='アーカイブページャー' type='BlogArchive' version='1'>
  <b:widget-settings>
    <b:widget-setting name='showStyle'>HIERARCHY</b:widget-setting>
    <b:widget-setting name='yearPattern'>yyyy</b:widget-setting>
    <b:widget-setting name='showWeekEnd'>true</b:widget-setting>
    <b:widget-setting name='monthPattern'>M</b:widget-setting>
    <b:widget-setting name='dayPattern'>MMM dd</b:widget-setting>
    <b:widget-setting name='weekPattern'>MM/dd</b:widget-setting>
    <b:widget-setting name='chronological'>false</b:widget-setting>
    <b:widget-setting name='showPosts'>false</b:widget-setting>
    <b:widget-setting name='frequency'>MONTHLY</b:widget-setting>
  </b:widget-settings>
  <b:includable id='main'>
    <b:attr name='class' value='blog-pager'/>
    <b:attr name='id' value='blog-pager'/>
    <b:attr name='data-version' value=''/>
    <b:loop index='i' values='data:data' var='year'>
      <b:comment>年別アーカイブ</b:comment>
      <b:include cond='data:blog.url == data:year.url' name='archive_year'/>
      <b:comment>月別アーカイブ</b:comment>
      <b:loop index='j' values='data:year.data' var='month'>
        <b:include cond='data:blog.url == data:month.url' name='archive_month'/>
      </b:loop>
    </b:loop>
  </b:includable>
  <b:includable id='archive_month'>
    <b:comment>翌月</b:comment>
    <b:if cond='data:j gt 0'>
      <b:with value='data:year' var='y'>
        <b:with value='data:y.data[data:j - 1]' var='m'>
          <b:include name='archive_month_next'/>
        </b:with>
      </b:with>
    <b:elseif cond='data:i gt 0 and data:j == 0'/>
      <b:with value='data:data[data:i - 1]' var='y'>
        <b:with value='data:y.data[data:data[data:i - 1].data.length - 1]' var='m'>
          <b:include name='archive_month_next'/>
        </b:with>
      </b:with>
    </b:if>
    <b:comment>前月</b:comment>
    <b:if cond='data:j lt data:data[i].data.length - 1'>
      <b:with value='data:year' var='y'>
        <b:with value='data:y.data[data:j + 1]' var='m'>
          <b:include name='archive_month_prev'/>
        </b:with>
      </b:with>
    <b:elseif cond='data:i lt data:data.length - 1 and data:j == data:data[i].data.length - 1'/>
      <b:with value='data:data[data:i + 1]' var='y'>
        <b:with value='data:y.data[0]' var='m'>
          <b:include name='archive_month_prev'/>
        </b:with>
      </b:with>
    </b:if>
  </b:includable>
  <b:includable id='archive_month_next'>
    <b:comment>翌月</b:comment>
    <span id='blog-pager-newer-link'>
      <a class='blog-pager-newer-link' expr:href='data:m.url' expr:title='data:y.name + &quot;年&quot; + data:m.name + &quot;月の投稿&quot;'><data:y.name/>/<b:eval expr='data:m.name.length == 1 ? &quot;0&quot; + data:m.name : data:m.name'/> [<data:m.post-count/>]</a>
    </span>
  </b:includable>
  <b:includable id='archive_month_prev'>
    <b:comment>前月</b:comment>
    <span id='blog-pager-older-link'>
      <a class='blog-pager-older-link' expr:href='data:m.url' expr:title='data:y.name + &quot;年&quot; + data:m.name + &quot;月の投稿&quot;'><data:y.name/>/<b:eval expr='data:m.name.length == 1 ? &quot;0&quot; + data:m.name : data:m.name'/> [<data:m.post-count/>]</a>
    </span>
  </b:includable>
  <b:includable id='archive_year'>
    <b:comment>翌年</b:comment>
    <b:if cond='data:i - 1 gte 0'>
      <b:with value='data:data[data:i - 1]' var='y'>
        <span id='blog-pager-newer-link'>
          <a class='blog-pager-newer-link' expr:href='data:y.url' expr:title='data:y.name + &quot;年の投稿&quot;'><data:y.name/> [<data:y.post-count/>]</a>
        </span>
      </b:with>
    </b:if>
    <b:comment>前年</b:comment>
    <b:if cond='data:i + 1 lt data:data.length'>
      <b:with value='data:data[data:i + 1]' var='y'>
        <span id='blog-pager-older-link'>
          <a class='blog-pager-older-link' expr:href='data:y.url' expr:title='data:y.name + &quot;年の投稿&quot;'><data:y.name/> [<data:y.post-count/>]</a>
        </span>
      </b:with>
    </b:if>
  </b:includable>
  <b:includable id='flat'/>
  <b:includable id='interval'/>
  <b:includable id='menu'/>
  <b:includable id='posts'/>
  <b:includable id='toggle'/>
</b:widget>

テーマ編集上の b:widget タグは実際の HTML 上では div タグへと変化する。例えばブログアーカイブウィジェットを普通に設置した場合は以下のようになる。

<div class="widget BlogArchive" data-version="1" id="BlogArchive0">
  ...
</div>

ここで以下の記事の方法を応用し、Blogger の 独自タグ b:attrclass 属性と id 属性の属性値を blog-pager に置換し、使用しない data-version 属性を削除した。

この操作により、b:widget の部分が HTML 上でこのように出力されるため、ウィジェットのいちばん外側の div をページャーのリンクを囲む枠として利用できる。

<div class="blog-pager" id="blog-pager">
 ...
</div>

肝心のページャー部分については、基本的には以下の 3 つの b:includable タグの中身をいじれば見た目を変えられる。

  • archive_month_next:月別アーカイブの翌月リンク
  • archive_month_prev:月別アーカイブの前月リンク
  • archive_year:年別アーカイブの翌年・前年リンク

年に関するデータは data:y.[...]、月に関するデータは data:m.[...] で取得できる。[...] には以下のようなアイテム名が入る。

  • url:URL
  • name:年月表記
  • post-count:投稿数

デフォルトの月表記 data:m.name は、1~9月が 1 桁で表示される。01 のような 2 桁にしたい場合は <data:m.name/> を以下のように書き換える。

<b:eval expr='data:m.name.length == 1 ? &quot;0&quot; + data:m.name : data:m.name'/>

または、一括で月表記の桁数を変えるためにコードの 6 行目の以下の部分を

<b:widget-setting name='monthPattern'>M</b:widget-setting>

このようにすればオッケー。

<b:widget-setting name='monthPattern'>MM</b:widget-setting>

【おまけ】JS を少しだけ使う月別アーカイブ用ページャー

フラット(flat)型ブログアーカイブウィジェットを利用し、翌月・前月のリンク表示自体は Blogger の独自タグで行い、年月表記のみ JavaScript で変更するページャーを作成した。

しかしこれまで述べてきた通り、JS を使わずともアーカイブページャーを表示する方法がわかったためお役御免になってしまった。とはいえせっかく考えたのだからここで成仏させておく。

このページャーの場合も、前述の「既存のページャーを非表示にする」に倣い、以下のコードを

<b:inculude name='nextprev'/>

こちらに変更する。

<b:inculude cond='!data:view.archive.month' name='nextprev'/>

そしたら以下のコードをブログの投稿ウィジェットの </b:widget> の直後に貼り付けて保存すればオッケー。

<b:widget cond='data:view.archive.month' id='BlogArchive0' locked='true' title='アーカイブページャー' type='BlogArchive' version='1'>
  <b:widget-settings>
    <b:widget-setting name='showStyle'>FLAT</b:widget-setting>
    <b:widget-setting name='yearPattern'>yyyy</b:widget-setting>
    <b:widget-setting name='showWeekEnd'>true</b:widget-setting>
    <b:widget-setting name='monthPattern'>MMMM yyyy</b:widget-setting>
    <b:widget-setting name='dayPattern'>MMM dd</b:widget-setting>
    <b:widget-setting name='weekPattern'>MM/dd</b:widget-setting>
    <b:widget-setting name='chronological'>false</b:widget-setting>
    <b:widget-setting name='showPosts'>false</b:widget-setting>
    <b:widget-setting name='frequency'>MONTHLY</b:widget-setting>
  </b:widget-settings>
  <b:includable id='main'>
    <b:attr name='class' value=''/>
    <b:attr name='id' value=''/>
    <b:attr name='data-version' value=''/>
    <b:if cond='data:data.length gte 2'>
      <b:attr name='class' value='blog-pager'/>
      <b:attr name='id' value='blog-pager'/>
<script>//<![CDATA[
function archivePager(name, elem){
  const link = document.querySelector(elem);
  const regex = /(\d{1,2})月\s(\d{4})/;
  const year = regex.exec(name)[2];
  const month = regex.exec(name)[1];
  const date = year + '/' + (month.length == 1 ? '0' + month : month);
  link.textContent = link.textContent.replace(name, date);
}
//]]></script>
      <b:loop index='i' values='data:data' var='month'>
        <b:if cond='data:blog.url == data:month.url'>
          <b:comment>翌月</b:comment>
          <b:if cond='data:i - 1 gte 0'>
            <b:with value='data:data[data:i - 1]' var='m'>
              <span id='blog-pager-newer-link'>
                <a class='blog-pager-newer-link' expr:href='data:m.url' title='翌月の投稿'><data:m.name/> [<data:m.post-count/>]</a>
                <script>archivePager(&#39;<data:m.name/>&#39;, &#39;a.blog-pager-newer-link&#39;)</script>
              </span>
            </b:with>
          </b:if>
          <b:comment>前月</b:comment>
          <b:if cond='data:i + 1 lt data:data.length'>
            <b:with value='data:data[data:i + 1]' var='m'>
              <span id='blog-pager-older-link'>
                <a class='blog-pager-older-link' expr:href='data:m.url' title='前月の投稿'><data:m.name/> [<data:m.post-count/>]</a>
                <script>archivePager(&#39;<data:m.name/>&#39;, &#39;a.blog-pager-older-link&#39;)</script>
              </span>
            </b:with>
          </b:if>
        </b:if>
      </b:loop>
    </b:if>
  </b:includable>
  <b:includable id='flat'/>
  <b:includable id='interval'/>
  <b:includable id='menu'/>
  <b:includable id='posts'/>
  <b:includable id='toggle'/>
</b:widget>

関数 archivePager に翌月・前月リンクの年月表記と a 要素の class 名を引数として渡している。そこから年月表記を exec() で年と月に分解して組み直し、置換することで、リンクの内部テキストを yyyy/MM 表記に変えている。

あとがき

Blogger 上で使える、JavaScript 不要の年別・月別アーカイブ用ページャーを自力で作成した。

2022 年 12 月から 2023 年 1 月(あるいはその逆)のような、年をまたぐページャーの処理が本当に難しくて、ああでもないこうでもないと条件式を書いてはエラーを頻発させていた。なんとか完成したけれど、未だにどこかで不具合が起きるんじゃないかとひやひやしてる。

そんな不安がありつつも、b:widget 由来の div タグをページャーのリンクを囲む枠として利用したり、デザイン変更の際に編集すべき b:includable タグを 1 箇所に固めたり、自分のこだわりは反映できたと思う。確実に成長している!

編集
ホーム