日々のコンピュータ情報の集積と整理

Dr.ウーパのコンピュータ備忘録

2014年5月14日水曜日

Blogger:「前の投稿」「次の投稿」に記事のタイトルを付与する! - JavaScript: ブログ アーカイブから取得編(前・次の投稿が月を跨ぐ場合は非対応)

イントロダクション

記事「Blogger:レイアウト用ページ要素タグを使用して、「前の投稿」「次の投稿」に記事のタイトルを付与する! - 失敗編」では、Blogger のレイアウト用ページ要素タグを使用すれば、「次の投稿」「前の投稿」ナビゲータに、それぞれの記事のタイトルを付与することができるのはないかという考え、実現可能性を検証しましたが ”実現できない” という結論が得られました。

そこで、今回は JavaScript を使用して、動的に「次の投稿」「前の投稿」ナビゲータに、それぞれの記事のタイトルを付与する方法を検討します。




先行事例調査

先行事例をインターネットで調査したところ、以下の事例が見つかりました。

1.「次の投稿」「前の投稿」に設定された <A>タグのURL を使用して、動的にその URL の HTML ドキュメントを取得し、タイトルを抽出して、「次の投稿」「前の投稿」ナビゲータのタイトルとして設定

Bloggerのページャにリンク先のページタイトルを挿入する : たき備忘録
http://blogger.weblix.net/2011/09/blogger.html


2.「次の投稿」「前の投稿」に設定された <A>タグのURL をもとに、Atom 情報から「次の投稿」「前の投稿」のタイトルを取得して、「次の投稿」「前の投稿」ナビゲータのタイトルとして設定

Bloggerのページ送りをタイトルに変更する方法 | ダーフク.com
http://www.dafuku.com/2014/03/blogger-next-link-title-change.html

「次の投稿」と「前の投稿」を記事タイトルに!blogger | きゃんつくばっと
http://kyantsukubatto.blogspot.jp/2012/11/blogger.html


いずれの方式も、動的に他ページにアクセスして「次の投稿」「前の投稿」のタイトル情報を取得する方式です。

これらの方式で「前の投稿」「次の投稿」に記事のタイトルを付与してもよいのですが、せっかくなので、別の処理方式を考えてみました。

処理方式

概要

Blogger のブログ アーカイブから「前の投稿」「次の投稿」の記事タイトルを取得する

処理詳細

Blogger のブログ アーカイブガジェットには、Blogger に投稿されたすべての投稿と、その URL が HTML として含まれています。(注1)

注1:

初期状態では、現在表示している投稿の投稿日と同じ年月の記事のみ含まれます。
現在表示している投稿の投稿日とは異なる年月の記事は、必要に応じて読み込まれます。この動作については下記記事に詳細をまとめました。

Blogger:「ブログのアーカイブ」ガジェットで階層表示にしているときの投稿一覧のデータ生成・表示動作について - Dr.ウーパのコンピュータ備忘録
http://upa-pc.blogspot.jp/2014/05/bloggerarchive.html


そこで、「前の投稿」「次の投稿」に設定された URL を元に、Blogger のブログ アーカイブガジェットの HTML 解析します。

そして、「前の投稿」「次の投稿」のURLにマッチする要素を探しだし、そのタイトルを取得します。

取得したタイトルを「前の投稿」「次の投稿」へ設定します。


この方式のメリット

  • 他のページへのアクセスが発生しない(注2)


注2:
「前の投稿」「次の投稿」の投稿日が現在の投稿と同じ年月場合のみ、他のページへのアクセスが発生しません。
「前の投稿」「次の投稿」の投稿日が現在の投稿とは違う年月の場合、Blogger のサーバから「前の投稿」「次の投稿」の投稿日の記事一覧を別途取得する必要があります。

この方式のデメリット

  • Blogger のページ内に必ずブログ アーカイブを配置する必要がある。
  • 投稿のタイトルが長い場合には、最後の部分が省略されている。

ソースコード

今回は前・次の投稿が、月を跨ぐ場合は非対応としました。
(前・次の投稿が、月を跨ぐ場合は、ブログアーカイブに対して、月を跨いだ分のタイトルの読み込み指示を与えないといけないため。)

その代り、他のページの読み込みは一切行わない方式です。


以下のソースコードを<body>タグ内の最後に配置します。

    <b:if cond='data:blog.pageType == &quot;item&quot;'>
      <!-- 投稿ページにのみ 前の投稿・次の投稿のタイトル挿入 を適用する -->
      <!-- 前の投稿・次の投稿のタイトル挿入 START -->
      <script type='text/javascript'>
        //<![CDATA[
        <!--
    (function () {

        // --- Util ---

        /*
        タグ名から子要素のみを選択して取得する
        */
        function getChildElementsByTagName(obj, tagName) {
            var items = new Array();

            for (var i = 0; i < obj.childNodes.length; i++) {
                if (obj.childNodes[i].tagName !== void 0)          // undefined でなければ処理
                {
                    if (obj.childNodes[i].tagName.toLowerCase() == tagName.toLowerCase()) {
                        items.push(obj.childNodes[i]);
                    }
                }
            }

            return items;
        }


        // --- Main ---

        /*
        ブログアーカイブから前の投稿・次の投稿のタイトルを取得し、
        前の投稿・次の投稿ナビゲータに設定する
        */
        function setPrevNextTitle() {

            var obj_archive = document.getElementById("BlogArchive1_ArchiveList");                  // ブログアーカイブ取得
            var obj_years = getChildElementsByTagName(obj_archive, "ul");                           // 年毎のアーカイブ

            for (var y = 0; y < obj_years.length; y++) {
                var obj_year_childs = getChildElementsByTagName(obj_years[y], "li");

                var obj_months = getChildElementsByTagName(obj_year_childs[0], "ul");               // 月ごとのアーカイブ
                for (var m = 0; m < obj_months.length; m++) {
                    var obj_month_childs = getChildElementsByTagName(obj_months[m], "li");

                    var obj_posts_tops = getChildElementsByTagName(obj_month_childs[0], "ul");

                    // 投稿データが読み込まれていなかったらスキップする
                    if (obj_posts_tops.length == 0) {
                        continue;
                    }

                    var obj_posts = getChildElementsByTagName(obj_posts_tops[0], "li");             // 月ごとの投稿
                    for (var p = 0; p < obj_posts.length; p++) {

                        // 要素の a タグから href を取得し、現在のページの要素かどうかチェック
                        var obj_a = obj_posts[p].getElementsByTagName("a");
                        var now_href = obj_a[0].getAttribute("href");

                        // 現在のページの要素を発見
                        if (now_href == location.href) {

                            // 次の投稿が同じ月だったら
                            if (p > 0) {
                                setNextTitleFromArchiveElement(obj_posts[p - 1]);
                            }

                            // 前の投稿が同じ月だったら
                            if (p < obj_posts.length - 1) {
                                setPrevTitleFromArchiveElement(obj_posts[p + 1]);
                            }
                        }
                    }
                }
            }
        }

        /*
        次の投稿のタイトルをブログアーカイブの要素より設定する
        */
        function setNextTitleFromArchiveElement(obj_archive_element) {

            // 次の投稿のナビゲータ取得
            var obj = document.getElementById("Blog1_blog-pager-newer-link");
            if (!obj) return;


            var obj_archive_a = obj_archive_element.getElementsByTagName("a");

            // 次の投稿の URL と、ブログアーカイブから取得した URL が異なっていたら対象外
            if (obj.getAttribute("href") != obj_archive_a[0].getAttribute("href")) {
                return;
            }

            obj.innerHTML = obj.innerHTML + "<br /><div id=\"next-title\">" + obj_archive_a[0].innerHTML + "</div>";
        }

        /*
        前の投稿のタイトルをブログアーカイブの要素より設定する
        */
        function setPrevTitleFromArchiveElement(obj_archive_element) {

            // 前の投稿のナビゲータ取得
            var obj = document.getElementById("Blog1_blog-pager-older-link");
            if (!obj) return;


            var obj_archive_a = obj_archive_element.getElementsByTagName("a");

            // 前の投稿の URL と、ブログアーカイブから取得した URL が異なっていたら対象外
            if (obj.getAttribute("href") != obj_archive_a[0].getAttribute("href")) {
                return;
            }

            obj.innerHTML = obj.innerHTML + "<br /><div id=\"prev-title\">" + obj_archive_a[0].innerHTML + "</div>";
        }


        // --- 実行 ---
        setPrevNextTitle();

    })();
        //-->
        //]]>
      </script>
      <!-- 前の投稿・次の投稿のタイトル挿入 END -->
    </b:if>

結果

前の投稿・次の投稿が、現在の投稿と同じ月に投稿された場合

以下のように前の投稿・次の投稿の記事タイトルを下に表示することが出来ました。

前の投稿、次の投稿の記事タイトルを下に表示

前の投稿・次の投稿が、現在の投稿とは異なる月に投稿された場合

前の投稿・次の投稿が、現在の投稿とは異なる月に投稿された場合には、以下のように記事タイトルは表示されません。

前の投稿、次の投稿の記事タイトルは表示されない


まとめ

Bloggerの「前の投稿」「次の投稿」の投稿タイトルを、JavaScriptにてブログ アーカイブから取得することで、付与することが出来ました。

次は、前の投稿・次の投稿が、現在の投稿とは異なる月に投稿された場合にも対応する方法を考えたいと思います。





関連記事

関連記事を読み込み中...

同じラベルの記事を読み込み中...