nanocにJavaScriptで動的ページャ機能を追加する

当サイトはRuby製静的CMSのnanocで構築していますが、これまでトップページ末尾では単純に記事一覧にリンクしていました。

これはjekyllなども含め、静的CMSではページャを設けると生成・転送の必要なHTMLが増えてしまう問題があるためです。

そこで、当サイトではJavaScriptで動的に個別の記事からサマリを読み込み、継ぎ足し表示することでページャ機能を再現することにしました。

nanoc 動的ページャ 実装内容

jQueryを使用するので、ダウンロードしておきます。(content/javascripts/jquery-1.9.1.min.js)

今回動的ページャを実現するために作成したJavaScriptの内容は以下のとおりです。(content/javascripts/ajax_pager.js)

//JavaScriptでのユーザエージェント条件分岐便利スニペット - W3G Blog Tools/Tips
//http://w3g.jp/blog/tools/js_browser_sniffing
var _ua = (function(){
  return {
    ltIE6:typeof window.addEventListener == "undefined" && typeof document.documentElement.style.maxHeight == "undefined",
    ltIE7:typeof window.addEventListener == "undefined" && typeof document.querySelectorAll == "undefined",
    ltIE8:typeof window.addEventListener == "undefined" && typeof document.getElementsByClassName == "undefined",
    IE:document.uniqueID,
    Firefox:window.sidebar,
    Opera:window.opera,
    Webkit:!document.uniqueID && !window.opera && !window.sidebar && window.localStorage && typeof window.orientation == "undefined",
    Mobile:typeof window.orientation != "undefined"
  }
})();

if(_ua.Webkit || _ua.Firefox || _ua.Opera){
  $(function(){
    $.ajaxSetup({async: false});

    var articles = [];
    var current_index = 10; //トップページ表示記事数
    //最大5件のサマリを読み込む関数
    function getSummaries() {
      if (articles.length == 0) {
        //記事一覧を読み込む
        $.ajax({
          url: "/articles/index.html",
          cache: false,
          success: function(html){
            $(html).find("#article a").each(function() {;
              articles.push({'href':$(this).attr("href"), 'text':$(this).text()});
            });
          }
        });
      }
      var summary_htmls = "";
      for (i = 0; (i < 5) && (current_index < articles.length); i++){
        //記事からサマリを読み込む
        $.ajax({
          url: articles[current_index]["href"] + "index.html",
          cache: false,
          success: function(html){
            var summary_html = "";
            summary_html = $(html).find("#article").html().replace(/[\s\S]*?(<h2>[\s\S]*)/, "$1");
            summary_html = summary_html.replace(/([\s\S]*?)<h3>[\s\S]*/, "$1<p class='readmore'><a href='" + articles[current_index]["href"] + "' target='_blank'>記事の続きを読む ≫</a></p>");
            summary_html = summary_html.replace(/([\s\S]*?)<div id="section_bottom_ad">[\s\S]*/, "$1");
            summary_html = summary_html.replace(/<a /, "<a target='_blank' ");
            summary_htmls += summary_html + "\n\n";
            current_index += 1;
          }
        });
      }
      return summary_htmls;
    }

    //ページャボタンを表示する
    var pager_html = "<p id='index_nav'><a id='show_prev_entries' href='#'>次の5件を表示する &raquo;</a><img id='loading_gif' style='display:none;margin-left:10px;vertical-align:bottom;' src='/images/ajax-loader.gif' alt='loading' width='16' height='16' /><img style='display:none;' src='/images/ajax_pager.jpg' width='0' height='0' /></p>";
    $("#index_nav").replaceWith(pager_html);

    //ページャボタンが押されたら処理する
    $("#show_prev_entries").click(function () {
      //ローディング表示(chromeでは動作せず)
      $("#loading_gif").show();

      //サマリを追加表示
      var html = "<hr />" + getSummaries();
      $("#index_nav").before(html);
      $("#loading_gif").hide();
      if (current_index >= articles.length) {
        $("#index_nav").hide();
      }
      return false;
    });
  });
}

これらのJavaScirptファイルをレイアウトファイルでトップページの場合のみ読み込むようにします。(layouts/default.haml)

~中略~
- if @item[:content_filename] == 'content/index.haml'
  %script{:type => "text/javascript", :src => "/javascripts/jquery-1.9.1.min.js"}
  %script{:type => "text/javascript", :src => "/javascripts/ajax_pager.js?201304172335"}
~中略~

トップページ側では表示位置の目印に使われるID(#index_nav)を設定しておきます。(content/index.haml)

~中略~
- if sorted_articles.length > 10
  %p#index_nav
    %a{:href => "/articles/"} 記事一覧へ &raquo;

また、継ぎ足し部分にhrで区切りを入れるため、hr用のスタイルを設定します。(content/stylesheets/screen.sass)

    ~中略~
    hr
      :border none
      :margin-top 15px
      :margin-bottom 0px
      :height 20px
      :background url(/images/ajax_pager.jpg) no-repeat 50% 50%
      :background-color $hr_background_color
    ~中略~

以上で設定は完了です。

nanoc 動的ページャ 動作内容

Chrome(Webkit)、Firefox、Operaと判定されれば、「次の5件を表示する」のリンクが表示されます。これをクリックすることで、以下のように動作します。

  • 1回目のみ過去記事一覧ページから記事のURL情報を取得する
  • 5件の記事ページからサマリ情報を取得してつなげる
  • つなげたサマリ情報をインデックスページに継ぎ足し表示する

上記3種以外のブラウザでは、従来通り記事一覧へのリンクが表示されます。

Chromeではなぜかローディング画像が表示されないようです。原因と対応方法の分かる方がいれば教えて下さい。

参考ページ

おわりに

当サイトのトップページで動作が確認できます。

コード内容はご自由にお使い下さい。jekyll等でも同じように使えるかと思います。

blog comments powered by Disqus