イントロダクション
記事「Blogger:投稿一覧をdocument.writelnではなく、要素のinnerHTMLに挿入することでページの表示を軽くする」では、記事一覧の作成をdocument.writelnではなく、要素のinnerHTMLに挿入することでページの表示を軽くしました。今回は、document.writeln から innerHTML へ切り替えたことで、JavaScript の実行タイミングがページ表示中だけではなく、ページ表示後でも動作できるようになったため、投稿の数が500件を超えていても、意識しないで投稿一覧を作成出来るようにしてみます。
2014/6/5 追記:
ラベルの URL 生成部にバグがあったため修正しました。誤:
var labelLink = location.protocol + "//" + location.host + "/" + label;
正:
var labelLink = location.protocol + "//" + location.host + "/search/label/" + encodeURIComponent(label);
何故、投稿の数が 500件を超えると問題があるかというと、フィードの読み込みで一回に取得できる投稿の数の上限が 500件のため、分割してフードを読みに行かなくてはならないからです。
そのため、記事が 500件の倍数を超えるごとに、フィードの読み込みの script タグを増やすというのが従来良く行われている方式でした。
そこで、わざわざ 記事が 500件の倍数を超えるごとに、フィードの読み込みの script タグを増やさなくてもいいように、コードを記載します。
コード
以下のコードを Blogger のページへ張り付けます。なお、
var blogger_url = "http://upa-pc.blogspot.com";
となっている箇所を各自の Blogger の URL へ差し替えてください。
<div id="post-list-container"> 記事一覧生成中... </div> <div id="post-list-gen-time"> </div> <script type="text/javascript"> <!-- // --- Util --- // JavaScript動的挿入 function addScript(src) { var script = document.createElement('script'); script.setAttribute("type", "text/javascript"); script.setAttribute("src", src); header_setChild(script); } // <head>取得 function getHeader() { return document.getElementsByTagName("head")[0]; } // <head>に子要素を追加 function header_setChild(child) { var head = getHeader(); head.appendChild(child); } // --- Main --- var feedDataArray = []; // フィードのデータ var max_results = 500; // フィード取得件数(最大500) var blogger_url = "http://upa-pc.blogspot.com"; // 記事一覧作成のトリガー (function () { loadFeed(); })(); // Feed の読み込み function loadFeed() { addScript(blogger_url + "/feeds/posts/summary?alt=json-in-script&callback=loadtoc&max-results=" + max_results + "&start-index=" + (max_results * feedDataArray.length + 1) + "&redirect=false"); } function loadtoc(data) { // エントリーがある場合は、エントリーをストックし、次の記事の読み込み処理を実行 if (data.feed.entry) { if (data.feed.entry.length > 0) { feedDataArray.push(data); // フィードの上限件数取得できていた場合、まだ投稿が残っている可能性があるので次のフィードを取得する if (data.feed.entry.length == max_results) { // 次の feed の読み込み loadFeed(); return; } } } // エントリーが無い・最後のエントリーまで読み込んだ場合 // 全てのデータを読み込み終わったので、記事一覧を作成 createPostsIndex(); } function createPostsIndex() { // 処理時間計測 var start_time = new Date(); var html = ""; html += "<ol>"; for (var feedCount = 0; feedCount < feedDataArray.length; feedCount++) { var data = feedDataArray[feedCount]; // 処理対象のフィードの取り出し for (var i = 0; i < data.feed.entry.length; i++) { // リンク先の探索 var href = "javascript:void(0);"; for (var j = 0; j < data.feed.entry[i].link.length; j++) { if (data.feed.entry[i].link[j].title == data.feed.entry[i].title.$t) { href = data.feed.entry[i].link[j].href; } } // ラベル一覧作成 var labels = ""; if (data.feed.entry[i].category) { for (var j = 0; j < data.feed.entry[i].category.length; j++) { var label = data.feed.entry[i].category[j].term; var labelLink = location.protocol + "//" + location.host + "/search/label/" + encodeURIComponent(label); labels += "<span><a href=\"" + labelLink + "\">" + label + "</a><span>"; if (j < data.feed.entry[i].category.length - 1) { labels += ","; } } } html += "<li><a href=\"" + href + "\" title=\"" + fixForAttributeTitle(escapeForAttributeText(data.feed.entry[i].summary.$t)) + "\">" + escapeHTML(data.feed.entry[i].title.$t) + "</a><br />ラベル:" + labels + "<br /><br /></li>"; // 記事のまとまりごとにラインを引く if ((i % 10) == 9) { html += "<hr />"; } } } html += "</ol>"; var obj_output = document.getElementById("post-list-container"); obj_output.innerHTML = html; // 処理時間計測 var end_time = new Date(); var process_span = end_time - start_time; // 処理時間(ms) document.getElementById("post-list-gen-time").innerHTML = "<br />記事一覧の作成にかかった時間は " + process_span + " ms です。<br />"; // テキストをエスケープ処理する function escapeHTML(html) { var div = document.createElement("div"); if (div.innerText !== void 0) div.innerText = html; // innerText が定義されていれば innerText へ設定 else div.textContent = html; // Firefox のように innerText がないブラウザ向け return div.innerHTML; } // 属性用にテキストをエスケープ処理する function escapeForAttributeText(html) { // " をエスケープ html = html.replace(/\&/g, "&"); html = html.replace(/\</g, "<"); html = html.replace(/\>/g, ">"); html = html.replace(/\"/g, """); html = html.replace(/\'/g, "'"); return html; } // 属性の title 用にテキストを整理する function fixForAttributeTitle(text) { text = text.replace(/(\r\n){2,}/g, "$1$1"); text = text.replace(/(\r){2,}/g, "$1$1"); text = text.replace(/(\n){2,}/g, "$1$1"); return text; } } //--> </script>
動作としては、500件ごとにフィードを取得し、取得できた投稿の数が取得上限であれば、まだ取得できていない投稿があると判断し、次のフィードを取得しに行っています。
取得したフィードに投稿が含まれていない場合や、取得上限よりも投稿が少ない場合には最後のフィードと判断し、投稿一覧の作成を実行しています。
現在私のブログは投稿の数が 500件に満たないため、上限でのテストはできませんが、フィードの取得件数を 100 件に設定し、上記コードを実行したところ、分割してフィードを取得して、投稿一覧を作成できることを確認しました。
これで、このコードを張り付けておけば、Blogger の投稿の数がどんどん増えて行ったとしても、そのままのコードで全投稿を含んだ投稿一覧が作成できます。
次の改良
→ 新しい改良したコードがあります。Blogger:JavaScript:大量の投稿があるブログでも、ページ表示時の負荷を抑えて投稿一覧(目次)を作成
コメントを投稿
コメント投稿機能について