2014年6月24日火曜日

Blogger(ブロガー) にパンくずリスト

以前、ラベルの AND 検索を調べた時にパンくずリストがあれば良いのにな、と書きました。もしかしてと思い検索してみたらテンプレートの編集で実現している方がいました。その方の参照元の英語ページは 2009/06 と古い記事でしたが、内容は今の Blogger にも通用するものでした。(但し、このパンくずリストは1階層までです)

以下は手順

内容に従いテンプレートの編集で
<b:include data='top' name='status-message'/>
を探します。2箇所見つかった場合は2番目の上に追加、と書いてあるのですが、私のブログの場合は2番目に追加しても何も表示されず、これで数時間悩みました。色々試すうちに1番目に変更したら表示されました。

付近のコードはこの様な感じです。
  <b:if cond='data:mobile == &quot;false&quot;'>

    <!-- posts -->
    <div class='blog-posts hfeed'>

      <b:include data='top' name='status-message'/>
これに
<b:include data='posts' name='breadcrumb'/>
を追加します。
  <b:if cond='data:mobile == &quot;false&quot;'>

    <!-- posts -->
    <div class='blog-posts hfeed'>

      <b:include data='posts' name='breadcrumb'/>
      <b:include data='top' name='status-message'/>
この様になります。

次に
<b:includable id='main' var='top'>
を探します。これはたぶん1箇所だけだと思います。私の場合は1箇所だけでした。

付近のコードはこの様な感じです。
        <div class='column-center-outer'>
        <div class='column-center-inner'>
          <b:section class='main' id='main' showaddelement='no'>
            <b:widget id='Blog1' locked='true' title='ブログの投稿' type='Blog'>
              <b:includable id='main' var='top'>

この上に参照元英語ページに書いてあるコードを追加します。
        <div class='column-center-outer'>
        <div class='column-center-inner'>
          <b:section class='main' id='main' showaddelement='no'>
            <b:widget id='Blog1' locked='true' title='ブログの投稿' type='Blog'>
<b:includable id='breadcrumb' var='posts'>
<b:if cond='data:blog.homepageUrl != data:blog.url'>
<b:if cond='data:blog.pageType == "static_page"'>
<div class='breadcrumbs'><span><a expr:href='data:blog.homepageUrl' rel='tag'>Home</a></span> » <span><data:blog.pageName/></span></div>
<b:else/>
<b:if cond='data:blog.pageType == "item"'>
<!-- breadcrumb for the post page -->
<b:loop values='data:posts' var='post'>
<b:if cond='data:post.labels'>
<div class='breadcrumbs' xmlns:v="http://rdf.data-vocabulary.org/#">
<span typeof="v:Breadcrumb"><a expr:href='data:blog.homepageUrl' rel="v:url" property="v:title">Home</a></span>
<b:loop values='data:post.labels' var='label'>
<b:if cond='data:label.isLast == "true"'>
 » <span typeof="v:Breadcrumb"><a expr:href='data:label.url' rel="v:url" property="v:title"><data:label.name/></a></span>
</b:if>
</b:loop>
 » <span><data:post.title/></span>
</div>
<b:else/>
<div class='breadcrumbs'><span><a expr:href='data:blog.homepageUrl' rel='tag'>Home</a></span> » <span>Unlabelled</span> » <span><data:post.title/></span></div>
</b:if>
</b:loop>
<b:else/>
<b:if cond='data:blog.pageType == "archive"'>
<!-- breadcrumb for the label archive page and search pages.. -->
<div class='breadcrumbs'>
<span><a expr:href='data:blog.homepageUrl'>Home</a></span> » <span>Archives for <data:blog.pageName/></span>
</div>
<b:else/>
<b:if cond='data:blog.pageType == "index"'>
<div class='breadcrumbs'>
<b:if cond='data:blog.pageName == ""'>
<span><a expr:href='data:blog.homepageUrl'>Home</a></span> » <span>All posts</span>
<b:else/>
<span><a expr:href='data:blog.homepageUrl'>Home</a></span> » <span>Posts filed under <data:blog.pageName/></span>
</b:if>
</div>
</b:if>
</b:if>
</b:if>
</b:if>
</b:if>
</b:includable>
              <b:includable id='main' var='top'>
この様になります。

コードを追加し保存すると Blogger のテンプレート編集の仕様が変ったのか、保存されていないとメッセージが出てしまいます。警告を無視して戻ってから再び編集を開くと breadcrumb ブロックは別の場所に移動された状態で保存されていました。また " は &quot; に » は &#187; にエンコードされていました。

これでトップページ以外を開けば投稿上部にパンくずリストが追加されているのが確認できると思います。ただ blogger のラベルには上下関係がない為このパンくずリストの階層は1階層までとなります。

また、複数ラベルがある場合は最後のラベルのみが表示される様で
<b:if cond='data:label.isLast == "true"'>
 » <span typeof="v:Breadcrumb"><a expr:href='data:label.url' rel="v:url" property="v:title"><data:label.name/></a></span>
</b:if>
全てのラベルを表示したい場合は、青文字で書いた部分を削除すると » で繋がれて表示されます。


途中、うまく行かなかった時にテンプレートの仕様を勉強したおかげで、テンプレートのコードが多少読める様になりました。

.net に例えるなら

<b:include data='posts' name='breadcrumb'/>
はメソッド呼び出しに相当し
b:includable
ブロックがメソッドの実装部分に相当
<b:includable id='breadcrumb' var='posts'>
はメソッドのシグネチャに相当します。

コードを読み解いて行くと、実装部分最初の
<b:if cond='data:blog.homepageUrl != data:blog.url'>
はトップページかを判定し、トップページの時はパンくずリストの作成を行わない様にしています。

次の
<b:if cond='data:blog.pageType == "static_page"'>
はページかを判定し、ページの時は Home と現ページタイトルのみを表示しています。私のブログの場合だと ClipTimer などは投稿ではない「ページ」になります。

そして
<b:else/>
<b:if cond='data:blog.pageType == "item"'>
で投稿かを判定し、パンくずリストの作成を行っています。

blogger のテンプレートには switch - case や else if に相当する物がなく、今は b:if をネストで書くしかない様です。コードの可読性以前に、複雑な処理はテンプレートで行うな、という事なのでしょう。

多少理解したついでに複数ラベルが存在した時の処理をカンマ(,)で繋ぐ様に変更して使っています。投稿リストの全ラベルを多い順に取得できれば2階層以上のパンくずリストも可能ですね。

■blogger pageType の種類
  • static_page (ページ)
  • item (投稿)
  • archive (月毎などのアーカイブ)
  • index (ラベルなどでの検索結果)

■参考リンク
Blogger 投稿ページにパンくずリストを表示する方法 - Breadcrumb for Blogger: LAB@Moon
Breadcrumb for Blogger - Blogger Widgets
レイアウト データ タグ - Blogger ヘルプ

■関連投稿
Blogger(ブロガー) 複数ラベルの AND 検索