Bloggerにサムネ画像付きページャーを導入する

2021/01/10
16
サムネイル画像

前後の投稿などを分かりやすく表示してくれるページャーですが、例によってBloggerのページャーは超絶シンプル。

ページャー画像

これではあまりにも味気ないので、少しおしゃれな感じにしてみたいな~と思いサムネ画像付きページャーを作ってみました。WordPressのブログでよくある感じのやつですね。

作成したページャーの特徴や導入方法について、詳しくご紹介していきます。

特徴

主な特徴は以下の通りです。

軽量なJavaScript&CSS

最小限のJavaScriptとCSSのみで実装しており、動作が軽いです。

記事タイトルと画像を表示

前後の投稿のタイトルと画像を表示します。

レスポンシブデザイン

PC/スマホ表示にしっかり対応しています。

今回作成したページャーはjQueryを一切使用せず、JavaScriptのみで実装しているため軽量なのが売りです。コードも必要最小限を心がけ、最適化にこだわりました。

コードについて(1/11情報修正)

投稿当初、YouTubeサムネ画像について言及していたのですが、あれは私の勘違いで今回の場合は特別な処理は必要ありませんでした。そのため、スクリプトの当該部を一部削除しました。

また、最初掲載したスクリプトにはバグが含まれていたため、早い段階で導入された方はお手数ですが新しいスクリプトに入れ替えていただくようお願いいたします。

導入方法

ページャーの導入方法について見ていきます。

テーマのバックアップ

HTMLの編集をするので、テーマのバックアップを取っておきましょう。

バックアップ

管理画面から「テーマ」→「バックアップ」を選択し、ダウンロードしたファイルを保存します。

HTMLの編集

今回のページャーではFont Awesomeを使用するので、まずは<head>~</head>内に次のコードを挿入します。Font Awesomeのバージョンは適宜お好きなものに変えてください。

<link href='https://use.fontawesome.com/releases/v5.13.1/css/all.css' rel='stylesheet'/>

次に、ページャー本体を設置します。「ブログの投稿」セクション内のお好きな場所に以下のコードをコピペしてください。

ページャー(最初と最後の投稿にホーム あり)

<!-- post pager -->
<div id='post-pager'></div>
<script type='text/javascript'>
  var topurl = "<data:blog.homepageUrl/>";
  var currenturl = "<data:post.url/>";

  //<![CDATA[
  var postTitle = new Array();
  var postUrl = new Array();
  var postImg = new Array();

  function loadpager(json) {
    function getPostData() {
      var entry, posttitle, posturl, postimg;
      for (var i = 0; i < json.feed.entry.length; i++) {
        entry = json.feed.entry[i];
        posttitle = entry.title.$t;
        for (var k = 0; k < entry.link.length; k++) {
          if (entry.link[k].rel == 'alternate') {
            posturl = entry.link[k].href;
            break;
          }
        }
        if ("media$thumbnail" in entry) {
          postimg = entry.media$thumbnail.url;
        } else {
          // NoImage画像
          postimg = "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpJms9mnNPfhuWkuWFCoMCTzb9wop7cvTs5LlisKd79TN06TOEHDwmB5mMkes27EY6H9XQpbkqNOCMDA3WoyWJDi8D2C3-SDQCYI3UJzKTE5QG1fdGjSBNC5snDeJmc-x9EggqNenPEmU/s100/"
        }
        postTitle.push(posttitle);
        postUrl.push(posturl);
        postImg.push(postimg);
      }
    }
    getPostData();
    displayPager();
  }

  function displayPager() {
    var current;
    var pagerHTML = '';
    // 現在の投稿を特定
    for (var i = 0; i < postTitle.length; i++) {
      if (postUrl[i] == currenturl) {
        current = i;
      }
    }
    if (current > 0) {
      // 次の投稿へのリンク
      pagerHTML += '<div class="next-post pager-div"><a class="pager-link" href="' + postUrl[current-1] + '">';
      pagerHTML += '<figure class="pager-img"><img loading="lazy" src="' + postImg[current-1] + '"/></figure>';
      pagerHTML += '<span class="pager-title">' + postTitle[current-1] + '</span>';
      pagerHTML += '</a></div>';
    } else {
      // トップへのリンク
      pagerHTML += '<div class="next-post pager-div"><a class="pager-link" href="' + topurl + '">';
      pagerHTML += '<figure class="pager-img"><i class="fas fa-home"></i></figure>';
      pagerHTML += '<span class="pager-title">トップページへ</span>';
      pagerHTML += '</a></div>';
    }
    if (current < postTitle.length - 1) {
      // 前の投稿へのリンク
      pagerHTML += '<div class="prev-post pager-div"><a class="pager-link" href="' + postUrl[current+1] + '">';
      pagerHTML += '<span class="pager-title">' + postTitle[current+1] + '</span>';
      pagerHTML += '<figure class="pager-img"><img loading="lazy" src="' + postImg[current+1] + '"/></figure>';
      pagerHTML += '</a></div>';
    } else {
      // トップへのリンク
      pagerHTML += '<div class="prev-post pager-div"><a class="pager-link" href="' + topurl + '">';
      pagerHTML += '<span class="pager-title">トップページへ</span>';
      pagerHTML += '<figure class="pager-img"><i class="fas fa-home"></i></figure>';
      pagerHTML += '</a></div>';
    }
    document.getElementById("post-pager").innerHTML = pagerHTML;
  }
  //]]>
</script>
<script expr:src='"https://www.blogger.com/feeds/" + data:blog.blogId + "/posts/default?max-results=500&amp;alt=json-in-script&amp;callback=loadpager"' type='text/javascript'/>
<style>
  #post-pager {
    margin-top: 2em;
  }
  .pager-div {
    word-break: break-all;
    margin-bottom: 13px;
  }
  .prev-post {
    text-align: right;
  }
  .pager-link {
    display: table;
    width: 100%;
    font-size: 95%;
    color: #444 !important;
    text-decoration: none;
    transition: 0.3s ease;
  }
  .pager-link:hover {
    opacity: 0.6;
    text-decoration: none;
  }
  .pager-link i {
    font-size: 30px;
    padding: 5px 10px;
  }
  .pager-img {
    position: relative;
    display: table-cell;
    width: 68px;
    vertical-align: middle;
    text-align: center;
    padding: 0 14px;
    box-sizing: border-box;
  }
  .pager-img img {
    width: 100%;
    height: 40px;
    object-fit: cover;
    vertical-align: top;
  }
  .pager-title {
    display: table-cell;
    vertical-align: middle;
  }
  .next-post .pager-img:before {
    position: absolute;
    left: 0;
    content: "\f104";
    font-family: "Font Awesome 5 Free";
    font-weight: 900;
    line-height: 40px;
    padding: 0 3px;
  }
  .prev-post .pager-img:after {
    position: absolute;
    right: 0;
    content: "\f105";
    font-family: "Font Awesome 5 Free";
    font-weight: 900;
    line-height: 40px;
    padding: 0 3px;
  }
</style>

※コードをHTML編集で貼り付ける際、エラーが出ていたスクリプト部分を修正しました。情報をいち早く提供して下さったふじろじっくさんに感謝します。

「ホーム なし」バージョンはこちら↓

コードを確認

設置場所の目安としては、Bloggerもともとのページャーがある<b:include name='nextprev'/>の所が良いと思います。<b:include name='nextprev'/>をコメントアウトし、下の画像の場所に設置してみてください。

※設置場所によっては現在の投稿URLが正しく取得できない場合があります。ご注意ください。

設置場所

コピペしたコードを<b:includable id='post-pager' var='post'>...</b:includable>で囲っておき、<b:include data='post' name='post-pager'/>で好きな場所から呼び出す形にすればよりスマートです。

ちなみに本体に関してですが、ブログのURL等はプログラムが勝手に取得しますので基本的に書き換える必要はありません。安心してコピペしていただいて大丈夫です。

導入は以上で完了です!テーマを保存し、ページャーがちゃんと表示されているか確認してみてください。

注意!

var topurl = "<data:blog.homepageUrl/>";の部分は、必ず//<![CDATA[の前に出すようにしてください。そうしないと、トップページへのリンクを正しく参照することができなくなります。スクリプトを圧縮した際は、コードに変化が生じていないか注意してください。

補足:読み込み速度について

JavaScriptを読み込んでフィードを取得しているため、投稿数が多い方だと読み込みに時間がかかってしまうことがあります。表示の遅れ等が気になる方は、以下のようにscript部分にdefer='defer'を追加してみてください。

<script defer='defer' src='...' type='text/javascript'> 

これによってJavaScriptの実行が後回しになるので、全体の表示への影響は少なくなると思います。

コードの解説

ここからは余談です。コードの中身も知りたい!という方は読んでみてください。

今回のページャー用コードでは、JavaScriptを利用してフィードのjsonデータを取得し、それをもとに前後の記事を表示させるようにしています。

function loadpager(json) {

  function getPostData() {
    // フィードをもとに投稿のタイトル、URL、画像のデータを取得し配列に格納
  }
  getPostData();  // データを取得
  displayPager();  // ページャーHTMLを出力
}

function displayPager() {
  // 取得したデータからページャー部分のHTMLを作成
}

JavaScript部分は上記のような構成になっており、フィードから取得したデータをもとにページャー用のHTMLを作成し、<div id='post-pager'></div>の部分に出力しています。

メインになっているのはloadpager関数で、これはjsonデータを引数(入力)として処理を行います。getPostDataとdisplayPagerはloadpager内で実行されるもので、本体に全部書くと面倒な感じの処理をひとまとめにしたサブルーチンです。

そして、処理のメインになっているloadpager関数を呼び出すのは次の部分。

<script expr:src='"https://www.blogger.com/feeds/" + data:blog.blogId + "/posts/default?max-results=500&amp;alt=json-in-script&amp;callback=loadpager"' type='text/javascript'/>

default?以降でフィードの表示形式を指定し、callback=loadpagerによってloadpager関数を呼び出します。ウィジェットなどを動的に生成する場合、この形で処理を行うことが多いです。

あとがき

前々からやってみたいなぁと思っていて、今回やっとちゃんとした形で作ることができました。やっぱりページャーにタイトルや画像があると分かりやすくて良いですね。

お使いのブログやサイトで利用していただけると嬉しいです。

16件のコメント
こんばんは。
ウチのブログにも導入してみたところ問題なく動作していたのですが、偶然バグを発見してしまいました(^^;

記事URLの末尾にアンカータグやパラメータ(?m=1など)が付いているとページャーのリンクが全てホームになってしまうようです。
例えばこちらのようなコメントパーマリンクとか→
https://itblogger-note.blogspot.com/2017/02/jumpy-star.html?showComment=1512995729336#c7401998235985228755

お手すきの時にでもご確認いただければ幸いです。
ふじやんさん、ご報告ありがとうございます。全く気付かなかったので助かりました。なんとか直せるよう、頑張ってみます!
コード修正できました!どうやら、現在の投稿をlocation.hrefで取得していたのが原因だったようです。を使うことで解決できました。
素早い対応ありがとうございます!
とりあえずテストブログ(プレーンな状態のQooQ)の方では修正されているのを確認できたのですが…肝心のメインブログの方は別の所で何かおかしくなっちゃったみたいでw
たぶん、独自にカスタマイズしたところに原因があると思うので、自力でなんとかしてみます(~_~;)
なるほど、環境によってうまくいく場合といかない場合があるんですね。こちらのほうでもまた実験して試してみます。

また何か問題等ありましたらお気軽にコメントください。できる範囲で対処させていただきます(`・ω・´)
ご心配おかけしましたがどうにか自力で対処できました。完璧に動作してます!

ページャーの位置をQooQのデフォルトの位置から一番下に移動させていたのですが、nextprevタグの挿入位置が適切でなかったのが原因だったようで…慌てて当該記事を修正しました(^^;

こちらもミスに気づくことが出来て助かりました(^^ゞ
無事解決されたようで何よりです。素敵にカスタマイズされてバッチリ決まっていますね!

ふじやんさんのご指摘のおかげでバグを取り除くことができ、こちらとしても一安心です。ありがとうございました(^^)
こんな時間に失礼します。寝る前にまたバグを発見してしまいました(^^;
おそらくウチの環境依存ではないと思うのですが、どうやら記事数が150本以上ある場合、151件目以降機能しなくなる(フィードが取得できない?)ようです。
ちなみにこれがウチの最新から数えて150件目の記事ですが、prevリンクがホームになってしまってます。(これ以降は全てホームリンクに)
https://fujilogic.blogspot.com/2017/04/off-course-song-is-love.html

ウチの古い記事なんてほとんどアクセスはない(笑)ので支障はないですけど、もし可能であれば対応していただければ幸いですm(_ _)m
なるほど、そういう不具合もあったのですね!ご報告ありがとうございます。

詳しく確認させていただきます(`・ω・)ゞ
調べた範囲で申し上げると、151件目以降の投稿フィードが取得できないのは仕様のようです。(もともと一度で500まで取得できたものが現在は150までとのこと)

解決策として、投稿数に応じて分割処理をする方法を考えていますが、少し時間がかかりそうなので実装出来次第こちらで公開することにします。完成までしばしお待ちください<(_ _)>
ちょっと検索をしてみるとfeedを500個まで得ることができる方法が出たりします。下のリンクであるが、
https://www.blogger.com/feeds/Blog-id/posts/default?max-results=500
500個までfeedが出るのか確認お願いしてもなりますか?
こんにちは。
私も150件に仕様変更されたという話は認識していました。しかしまさかこんな影響が出るとは思っても見なかったです(^^;
素晴らしいスクリプトの完成、気長にお待ちしております。

…てコメント書いてたらBINUBALLさんからヒントが!
https://www.blogger.com/feeds/5377390612546612653/posts/default?max-results=500
確かにこれなら当ブログの158件分全て含まれてるようですね。
これで改善できるといいのですが。
> BINUBALLさん、ふじやんさん

対象ブログのURLから直接取得することばかり考えていましたが、ブログIDを使う方法があったんですね!素晴らしい情報をありがとうございます。これなら大丈夫そうなので、早速試してみようと思います。
スクリプトのほう、修正しました。おそらくこれで150件以上でも正しく動くと思います。
早速の対応ありがとうございます。
修正版のコードで問題なく動作しました!
キャッシュの関係か、初回の読み込みだけ多少時間がかかるようですが、記事数が多いとやむを得ないですね(^^;
多少は軽くなるかなと、試しにフィードURLの default を summary に変えてみましたけど、あまり変わりないかな(^^;
良かったです!これでやっと安心できます(笑)

読み込みの遅れは私も感じてました。summaryとの違いはちょっと微妙かもしれませんね・・・
max-resultsをギリギリ(ふじやんさんの場合200ぐらい)で設定したほうが多少早くなるかもしれません(^^;