Blogger自作ページネーション

一覧の下のページ送りやページャーと呼ばれるページごとのリンクの自作テンプレートのjavascriptです。

初めにfeedで総件数を取得して、10件ごとの件数分のページリンクだけ作って終わります。ページリンクがクリックされると、feedでリンク先のurlを作ってリンク先にジャンプします。

urlに総件数をsumcntとして引き継ぐので1度総件数を取得すると、feedで総件数を取得する処理はやらないので、時間が短縮されます。

検索の場合だけ処理が違います。初めにfeedで101件目があるか取得します。101件目が無ければ、1件目から91件分を検索して、総件数を取得します。91件でも100件でもページリンクが10個必要なのは同じなので最小の91件。101件目があれば10個のページリンクだけ作って終わります。

検索のページリンクの10個目がクリックされたら、feedで201件目があるか取得します。201件目が無ければ、101件目から91件分を検索して、総件数を取得します。201件目があれば10個のページリンクだけ作って終わります。1度総件数を取得すると、feedで総件数を取得する処理はやらないので、時間が短縮されます。

一覧表示を全て10件ごとに表示する変更も必要です。
Bloggerラベル一覧表示を10件にする
Blogger検索結果を公開日順10件にする

ページネーションのjavascriptは以下になります。テンプレートの</body>の前に書きます。
<b:if cond='data:view.isMultipleItems and !data:view.isArchive'>
<script>
/*<![CDATA[*/
const maxResults=10;
const dispPage=3;
const queryMaxResults=maxResults*10;
const textQuery=getUrlParam('q');
const textLabel=location.pathname.split('/search/label/')[1]||'';
const start=parseInt(getUrlParam('start'))||0;
let sumcnt=parseInt(getUrlParam('sumcnt'))||0;
if(start>sumcnt) sumcnt=start+maxResults;
document.addEventListener('DOMContentLoaded',setIndexPager);
function setIndexPager(){
  if(textQuery){
    setIndexPagerQuery();
    return;
  }
  if(sumcnt>0){
    setHtmlPager();
    return;
  }
  let feedUrl='/feeds/posts/summary';
  if(textLabel) feedUrl+='/-/'+textLabel;
  feedUrl+='?alt=json&max-results=1';
  fetch(feedUrl)
  .then(response=>response.json())
  .then(json=>{
    sumcnt=parseInt(json.feed.openSearch$totalResults.$t)||0;
    setHtmlPager();
    return;
  })
  .catch(error=>console.log(error));
}
function setIndexPagerQuery(){
  if(sumcnt>0&&(sumcnt%queryMaxResults)!=0){
    setHtmlPager();
    return;
  }
  let feedUrl='/feeds/posts/summary?alt=json&q='+textQuery+'&max-results=1&start-index='+(sumcnt+queryMaxResults+1);
  fetch(feedUrl)
  .then(response=>response.json())
  .then(json=>{
    let totalResults=parseInt(json.feed.openSearch$totalResults.$t)||0;
    if(totalResults==1){
      sumcnt+=queryMaxResults;
      setHtmlPager();
      return;
    }
    feedUrl='/feeds/posts/summary?alt=json&q='+textQuery+'&max-results='+(queryMaxResults-maxResults+1)+'&start-index='+(sumcnt+1);
    fetch(feedUrl)
    .then(response=>response.json())
    .then(json=>{
      let totalResults=parseInt(json.feed.openSearch$totalResults.$t)||0;
      sumcnt+=totalResults;
      setHtmlPager();
    })
    .catch(error=>console.log(error));
  })
  .catch(error=>console.log(error));
}
function setHtmlPager(){
  let pagerobj=document.getElementById('blog-pager');
  if(!pagerobj) return;
  let currentPage=start/maxResults+1;
  let totalPage=Math.ceil(sumcnt/maxResults);
  let html='';
  for(let i=1;i<=totalPage;i++){
    if(i==currentPage){
      html+='<span id="pager-current">'+i+'</span>';
    }else if(i==1){
      html+='<a href="#" class="pager-a" onclick="return pager('+(currentPage-1)+')"><</a>';
      html+='<a href="#" class="pager-a" onclick="return pager('+i+')">'+i+'</a>';
    }else if(i==totalPage){
      html+='<a href="#" class="pager-a" onclick="return pager('+i+')">'+i+'</a>';
      html+='<a href="#" class="pager-a" onclick="return pager('+(currentPage+1)+')">></a>';
    }else if(Math.abs(i-currentPage)<dispPage){
      html+='<a href="#" class="pager-a" onclick="return pager('+i+')">'+i+'</a>';
    }else if(Math.abs(i-currentPage)==dispPage){
      html+='...';
    }
  }
  pagerobj.innerHTML=html;
}
function pager(targetPage){
  if(textQuery){
    location.href='/search?q='+textQuery+'&max-results='+maxResults+'&by-date=true&start='+(targetPage-1)*maxResults+'&sumcnt='+sumcnt;
  }else if(targetPage==1&&textLabel){
    location.href=location.pathname;
  }else if(targetPage==1){
    location.href='/';
  }else{
    let feedUrl='/feeds/posts/summary';
    if(textLabel) feedUrl+='/-/'+textLabel;
    feedUrl+='?alt=json&max-results=1&start-index='+(targetPage-1)*maxResults;
    fetch(feedUrl)
    .then(response=>response.json())
    .then(json=>{
      let pubDate=json.feed.entry[0].published.$t;
      pubDate=encodeURIComponent(pubDate.substring(0,19)+pubDate.substring(23,29));
      let url='/search';
      if(textLabel) url+='/label/'+textLabel;
      location.href=url+'?updated-max='+pubDate+'&max-results='+maxResults+'&start='+(targetPage-1)*maxResults+'&sumcnt='+sumcnt;
    })
    .catch(error=>console.log(error));
  }
  return false;
}
function getUrlParam(key){
  let searchlist=location.search.substring(1).split('&');
  for(let i=0;i<searchlist.length;i++) if(searchlist[i].split('=')[0]==key) return decodeURI(searchlist[i].split('=')[1]);
  return '';
}
/*]]>*/
</script>
</b:if>
cssは以下のようになります。大きさや色はブログにあうように変えてください。
<style>
#pager-current,.pager-a{
display:inline-block;
padding:.4em .8em;
margin:0 .2em;
border-radius:.5em;
}
#pager-current{
color:#fff;
background:#999;
}
.pager-a{
color:inherit;
background:#fff;
border:1px solid #999;
}
</style>

条件次第で高速化するjavascriptもあります。
Blogger自作ページネーション・高速化
Blogger自作ページネーション・キャッシュ高速化
この記事のタイトルとURLをコピーする blogger
blogger