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件を表示する »</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/"} 記事一覧へ »
また、継ぎ足し部分に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ではなぜかローディング画像が表示されないようです。原因と対応方法の分かる方がいれば教えて下さい。
参考ページ
- JavaScriptでのユーザエージェント条件分岐便利スニペット - W3G Blog Tools/Tips
ブラウザ判定にはこちらを使用させていただいています。
おわりに
当サイトのトップページで動作が確認できます。
コード内容はご自由にお使い下さい。jekyll等でも同じように使えるかと思います。