2017年1月14日土曜日

ラベルごとの最新記事取得(前編) ~Blogger テンプレートを作るよ! (39)~

こんにちはー!

今まで、フィードガジェットを使って特定のラベルの最新記事を取得していましたが、どうも更新が遅い気がするのでラベルガジェットを使ってみようと思います。

一日では終わらなかったので、前後編に分けてやっていこうと思います。

(前回:『ページの追加とメニューの調整 ~Blogger テンプレートを作るよ! (38)~』)

さっそく作業開始!

ステップ1 HTMLの修正

まず、ラベルガジェットを用意して、中身を適当に書き換えます。

ラベル名とフィードで取得した情報は一対一で対応するので、HTMLのタグは <dl> を使ってみます。<dl> 要素は、タイトル(<dt> 要素)とデータ(<dd> 要素)のペアで使用することを前提としたリストで、タイトルとしてラベル名、データとして最新記事を使うとちょうどペアになります。

というわけで、ガジェットのテンプレートを以下のように変更しました。この <dd> 要素の中にフィードで取得した情報を入れる予定です。
<dl>
  <b:loop values='data:labels' var='label'>
    <dt>
      <a expr:dir='data:blog.languageDirection' expr:href='data:label.url'>
        <span class='label-name' expr:dir='data:blog.languageDirection'>
          <data:label.name/>
        </span>
        <b:if cond='data:showFreqNumbers'>
          <span class='label-count' dir='ltr'>
            (
            <data:label.count/>
            )
          </span>
        </b:if>
      </a>
    </dt>
    <dd>
    </dd>
  </b:loop>
</dl>

STEP2 フィードを取得するプログラム

現在の URL とラベル名を使えばフィードの URL を作ることができます。問題は取得したフィード情報を解析する手段なのですが、もっともシンプルな方法は alt=json-in-script を使用することです。

フィードURLのパラメータとして alt=json-in-script と callback=関数名 を入れると、フィードの情報を callback に指定した関数に渡してくれるスクリプトを生成してくれます。以下のような感じです。

関数名(フィード情報をJSON形式にしたもの);

それを踏まえ、以下のように URL を生成します。

ブログURL/feeds/posts/summary/-/ラベル名?alt=json-in-script&callback=関数名

それを <script src=""></script> の src 属性に入れることで、フィード情報を特定の関数で受け取ることができます。あとは、ラベルごとにその受け取り側の関数を作るだけです。

ラベルごとに受け取る関数を変えますので、どうやってその関数を管理するかを考える必要があります。

そこで、まずは madoug オブジェクトに feedListeners という連想配列を用意しました。この中にフィード情報を受け取る関数を放り込んでいくという寸法です。

連想配列のキーとして、アルファベットと数字とアンダースコアだけで固有IDを付けます。今回はラベルガジェットの利用ということで label_数字 という名前にしてみます。これなら、以下のような形で固有の関数を実行することができます。

madoug.feedListeners.label_0(JSONデータ);

フィードURLに callback=madoug.feedListeners.label_0 と書けばこの関数が実行される、という寸法です。(javascript 上では同じ意味を持つ 「madoug.feedListeners["label_0"]」 ではできませんでした。関数名として正しくないとかエラーが出ました。)

完成した javascript はこちら。ちなみに現状ではフィード情報を受け取れたかどうかを確認するだけで、フィード情報の中身を表示するようにはしていません。

<script>
  // <![CDATA[
  (function() {
    if (madoug == null) window.madoug = {};
    madoug.feedRequest = function (widget_id, label_name, dir) {
      if (madoug == null) madoug = {};
      if (madoug.feedListeners == null) madoug.feedListeners = {};
      var thisUrl = (new RegExp("^([^\\:\\/\\?#@]+\\:)?(?:\\/\\/((?:([^\\/\\?#\\:@]*)(\\:[^\\/\\?#@]*)?@)?" + 
                                "([^\\/\\?#\\:]*)(?:\\:(\\d*))?))?")).exec(document.location.href);
      if (thisUrl == null) return;
      var listener_id = "label_" + Object.keys(madoug.feedListeners).length;
      var feedUrl = thisUrl[0] + "/feeds/posts/summary/-/" + label_name
      + "?alt=json-in-script&callback=" + "madoug.feedListeners." + listener_id;
      madoug.feedListeners[listener_id] = function(json) {
        var listeners = document.querySelectorAll("#" + widget_id + " [data-listener-name=" + label_name + "]");
        for (var i = 0, imax = listeners.length; i < imax; i++) {
          listeners[i].innerHTML = json;
        }
      }
      var elem = document.createElement("script");
      elem.setAttribute("src", feedUrl);
      document.body.appendChild(elem);
    }
  })();
  // ]]>
</script>

データを差し込む先は、「特定のウィジェットID の子要素で、 data-listener-name が指定したラベル名のもの」と指定しました。ということは、HTML 側もそれに対応して data-listener-name にラベル名を指定する必要が出てきましたね。

あとは、この関数を実行する部分もループ処理に入れる必要もあります。なので、一度作った HTML を少し修正しようと思います。

STEP3 HTML部分の修正

実際に追加した箇所は以下です。実は <script> タグの中でも <data:~~/> 要素でデータの差し込みができます。これ、かなり便利です。

<dl>
  <b:loop index='i' values='data:labels' var='label'>
    <dt>
      <a expr:dir='data:blog.languageDirection' expr:href='data:label.url'>
        <span class='label-name' expr:dir='data:blog.languageDirection'>
          <data:label.name/>
        </span>
        <b:if cond='data:showFreqNumbers'>
          <span class='label-count' dir='ltr'>
            (
            <data:label.count/>
            )
          </span>
        </b:if>
      </a>
    </dt>
    <dd expr:data-listener-name="data:label.name">
    </dd>
    <script>
      madoug.feedRequest(&quot;<data:widget.instanceId/>&quot;
                         , &quot;<data:label.name/>&quot;
                         , &quot;<data:blog.languageDirection/>&quot;);
    </script>
  </b:loop>
</dl>

実際に動かしてみよう!

実際に動かすと、以下のようになりました。


製作日誌と雑談ラベルのフィード取得を試したところ。
[object Object] が取得できていれば成功。

とりあえず、何かのオブジェクトが取得できたということはわかりますね。よしよし、順調です!

よーし、この調子で次回は記事の題名を取得して表示できるようにするぞ!

0 件のコメント :

コメントを投稿