javaScriptでBloggerにページネーションを実装する

Bloggerにページネーション機能をつけたい。ページネーションとは記事下部にあって、次の記事、前の記事へのリンクを紹介するというブログパーツ。Bloggerのデフォルトのページネーション機能には、以下の画像のように、次の記事・前の記事のリンクのみで記事のタイトルを表示することはできない。

ページネーションで記事タイトルを取得するようにしたい。当記事では、ざっくりログさまの情報120%全面参考にさせていただいています。ざっくりログさま本当にありがとうございます。Display Post Titles in Blogger Page Navigation



<b:> Bloggerのネイティブ文法では、記事タイトルを取得できない

olderPageUrl: 過去の投稿がある場合、その投稿の URL。ページの種類に応じて表示されます(このリンクはすべてのページにあるとは限りません)。
olderPageTitle: 過去の投稿ページへのリンクのタイトル。
newerPageUrl: 新しい投稿がある場合、その投稿の URL。
newerPageTitle: 新しい投稿ページへのリンクのタイトル。
参考元URL:レイアウト用のデータタグ - Blogger ヘルプ

公式ヘルプを見ると、Bloggerの文法には、
  • olderPageTitle
  • newerPageTitle
といったちゃんとこのようなそれっぽい文法がある



よし!と思ってテーマのHTMLに記載するとこの通り

次の記事、前の記事として表示してくれない。なんだよもう。olderPageTitle = 前の記事、newerPageTitle = 次の記事 ということ。


ちょっとまぎらわしい。記事URLは取得できているので、タイトルを取得するJSコードを書く必要があります。




アクセスカウントされないページネーションコード

ざっくりログさまが上記リンク先の記事で問題があると言っているようにJSでタイトルを取得すると、Bloggerのアクセスカウンターに計上され、次・前のタイトルを取得する度に1PVとしてカウントされてしまいます。

アクセス数を水増ししたいならJSのコードでもいいけどね、そんな不正確なPVデータなんて意味ないしね。アクセスにカウントされないようにするために、ざっくりログさまが書いているようなBloggerAPIを利用したjsonファイルを利用するのがとっても良い方法だと思われます。ざっくりログさま本当にありがとうございます。
<script type='text/javascript'>
//<![CDATA[
// except root, labels, search and mobile pages
if (/.+\.html(\?m=0)?$/.test(location.href)) {
  var olderLink = document.getElementById('Blog1_blog-pager-older-link');
  if (olderLink) {
    getPageTitle(olderLink, setOlderPageTitle);
    function setOlderPageTitle(data){
      setPageTitle(data, olderLink, '', ' &#187;')
    };
  }
  var newerLink = document.getElementById('Blog1_blog-pager-newer-link');
  if (newerLink) {
    getPageTitle(newerLink, setNewerPageTitle);
    function setNewerPageTitle(data){
      setPageTitle(data, newerLink, '&#171; ', '')
    };
  }
  // set the page title from feed data
  function setPageTitle(data, pageLink, prefix, suffix) {
    if (data.feed.entry) {
      if (data.feed.entry.length > 0) {
        var title = data.feed.entry[0].title.$t;
      }
    }
    if (title) {
      pageLink.innerHTML = prefix + title + suffix;
    }
  }
  // get entry data from the feed
  function getPageTitle(pageLink, callback) {
      var pathname = pageLink.getAttribute('href').replace(location.protocol + '//' + location.hostname, '');
      var script = document.createElement('script');
      script.src = '/feeds/posts/summary?alt=json-in-script&max-results=1&redirect=false&path='+pathname+'&callback='+callback.name+'';
      document.body.appendChild(script);
  }
}
//]]>
</script>


コード(自分なり)解説

人様のコードをまるまる転載しておいて解説もクソもないんだけど、自分なりに注釈を入れてみた。
 <script type='text/javascript'>
if (/.+\.html(\?m=0)?$/.test(location.href)) {
  // ※1location.hrefの末尾にhtmlかhtml?m=0か調べる。末尾がhtmlかチェックする。

  var olderLink = document.getElementById('Blog1_blog-pager-older-link');
  if (olderLink) {  // olderLinkが存在するなら。ショートハンド記法
    getPageTitle(olderLink, setOlderPageTitle);
    //※2関数getPageTitleへ第一引数olderLink, 第2引数へ定義した関数setOlderPageTitleを渡す。

    function (data){
      // getPageTitle() で、feed.jsonを渡される。dataへ格納。
      setPageTitle(data, olderLink, '', ' &#187;') // ^#187; = »
    };
  }

  var newerLink = document.getElementById('Blog1_blog-pager-newer-link');
  if (newerLink) {
    // newerLinkが存在するなら
    getPageTitle(newerLink, setNewerPageTitle);
    //関数getPageTitleへ、第一引数newerLink, 第2引数へ定義した関数setNewerPageTitleを渡す。

    function setNewerPageTitle(data){
      // getPageTitle() で、feed.jsonを渡される。dataへ格納。
      setPageTitle(data, newerLink, '&#171; ', '')
    };
  }
  // set the page title from feed data // dataはjsonファイル。$tは添字の名前。
  function setPageTitle(data, pageLink, prefix, suffix) {
    if (data.feed.entry) {
      if (data.feed.entry.length > 0) {
        var title = data.feed.entry[0].title.$t;
      // jsonファイルの項目、feedの添字entry配列[0]のtitle.$tを取得して、変数titleへ格納
      }
    }
    if (title) {
      // 変数titleが存在するなら、
      pageLink.innerHTML = prefix + title + suffix;
      // suffixは "»" 。 pageLink.innerHTML = ''記事タイトル » となる。
    }
  }
  // get entry data from the feed
  function getPageTitle(pageLink, callback) {
      var pathname = pageLink.getAttribute('href').replace(location.protocol + '//' + location.hostname, '');
      // location.protocol = https: location.hostname = あなたのブログ.blogspot.com
      var script = document.createElement('script');
      script.src = '/feeds/posts/summary?alt=json-in-script&max-results=1&redirect=false&path='+pathname+'&callback='+callback.name+'';
      // ※3 記事pathnameで、その記事のjsonファイルを取得することができる。最後の&callback=あとの関数にjsonデータが渡されることになる。
      document.body.appendChild(script);
  }
}
//]]>
</script>

※1 Bloggerは、URLに注目すると現在表示している記事の種類を掴める
URLの末尾が.html: 個別記事、pageTypeはItem
URLに label を含む: ラベル一覧ページ pageTypeはIndex
URLに search を含む: 検索結果表示ページ pageTypeはIndex
URLに 2で始まる4桁の数字を含む(ex: 2020): アーカイブページ pageTypeはarchive


※2
 getPageTitle(olderLink, setOlderPageTitle)の、
  • 第一引数:olderLinkはdomオブジェクト(#Blog1_blog-pager-older-link)
  • 第二引数: 関数setOlderPageTitle
これわかりづらかったのが第二引数だけど、関数をsetPageTitleへ渡している。渡した先のgetPageTitleでは、GoogleBloggerAPIから取得したfeed.jsonデータを受け取るコルバック関数として指定される処理になっている。つまり、

「setOlderPageTitleにjsonを渡してね!だから、jsonを受けてほしい関数を渡すからさ!」
という感じ


※3
  • script.src = '/feeds/posts/summary?alt=json-in-script&max-results=1&redirect=false&path='+pathname+'&callback='+callback.name+'';
で、なんで<script>のsrc属性を記述しているかというと、BloggerFeedAPIを取得するためには<script>をhtmlに作成せよと書いてあるから。
Blogger Data APIが提供するJSON出力形式を使用して、Bloggerベータでホストされているブログからの最近の投稿のリストを表示する方法を示しています。これにより、ブログのパブリックフィードをクエリして、結果のエントリをJSONオブジェクトとして返すことができます。新しいJSONフィードを使用するには、src値が次のスクリプト要素を作成します 
https://blogname.blogspot.com/feeds/posts/default?alt=json-in-script&callback=myFunc
どこblognameあなたが取得したいブログで、 myFuncJSONオブジェクトが渡されるコールバック関数の名前です。<Google翻訳>
参考URL: Simple example of retrieving JSON feeds from Blogger Data API
この引用先の情報ってBloggerAPIのものではなくて、GoogleデータAPIのものなんだよね。なんで、BloggerAPIのセクションにない情報なのだろうか(こんらん)。

  • '/feeds/posts/summary?alt=json-in-script&max-results=1&redirect=false&path='+pathname+'&callback='+callback.name+'';
は、以下と同義。
  • https://www.themetrial.blogspot.com/feeds/posts/summary?alt=json-in-script&max-results=1&redirect=false&path=/2020/05/blogger.html =

つまり、
https://www.themetrial.blogspot.com + /feeds/posts/summary?alt=json-in-script&max-results=1&redirect=false&path=/2020/05/blogger.html 
 ということ。最後のcallback関数へjsonデータを渡す。ここでjsonファイルを受け取るデータを、引数で渡された関数へ渡している。
https://www.themetrial.blogspot.com/feeds/posts/summary?alt=json-in-script&max-results=1&redirect=false&path=/2020/05/blogger.html&callback=callback.name (=関数setOlderPageTitle) ,
callback関数= setOlderPageTitleや setNewerPageTitleとなる。だからjsonを受け取れる。



受け取っているJsonの内容はどうなっているの?

末尾の&callback=callback.nameを消去して、BloggerのURLの部分(以下太字)を調節以下のように調節し、URLを打ち込むとJsonファイルを受け取ることができる。
https://blogname.blogspot.com/feeds/posts/default?alt=json-in-script&max-results=1&redirect=false&path=特定記事のパス.html 

私の場合、一つ前の記事の場合だと以下のようにするとjsonデータをブラウザに表示することができる
https://www.themetrial.blogspot.com/feeds/posts/summary?alt=json-in-script&max-results=1&redirect=false&path=/2020/05/blogger.html

当該部分はこんな感じのデータになる。
"feed": {
       "entry": [
               "title": {
                      "type": "text",
         "$t": "Blogger文法<b:loop>でラベルを呼び出す処理はこれを読めばわかる"
        },
         ]
}

 jsonデータを受け取り、当該箇所の値を取得して、関数に渡せているのがわかりました。

0 コメント: コメントを投稿