2017年1月22日日曜日

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

こんにちはー!

前回の続きで、ラベルごとの最新記事を取得するラベルガジェットを作っていきます。



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




作業再開!

前回はフィードを取得したところまでを作りました。今回は、その中から必要な情報を抜き出して表示する部分を作っていきます。

STEP1 JSONの中身を調べる

JSONの中身がどんな構造になっているのかわからなければ、JSONから情報を取り出すことは出来ません。まずは、JSONの中身がどうなっているのかを調べてみます。

実際に取得したファイルの中身を確認すると以下のようになっていました。


feed.entry の中に記事が格納されていることがわかります。

そして、feed.entry[0].link の5つあるデータのうち、 rel が alternate で type が text/html のものの中に実際のブログの URL が入っていることがわかりました。javascript でその情報を取得して表示させてみようと思います。

STEP2 プログラムを書いてみる

プログラムを以下のように変えてみます。

<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 + "&max-results=1";
      madoug.feedListeners[listener_id] = function(json) {
        var listeners = document.querySelectorAll("#" + widget_id + " [data-listener-name=" + label_name + "]");
        var html = "<ul>", entries = json.feed.entry;
        for (var i = 0, imax = entries.length, entry = entries[0]; i < imax; entry = entries[++i]) {
          for (var j = 0, jmax = entry.link.length, link = entry.link[0]; j < jmax; link = entry.link[++j]) {
            if (link.rel == "alternate" && link.type == "text/html") {
              html += "<li>"
                + "<a href=\"" + link.href + "\">"
                + "<span dir=\"" + dir + "\">"
                + link.title
                + "</span>"
                + "</a>"
                + "</li>";
              break;
            }
          }
        }
        html += "</ul>";
        for (var i = 0, imax = listeners.length; i < imax; i++) {
          listeners[i].innerHTML = html;
        }
      }
      var elem = document.createElement("script");
      elem.setAttribute("src", feedUrl);
      document.body.appendChild(elem);
    }
  })();
  // ]]>
</script>

こっそりフィードURLに max-results=1 というパラメータも追加しました。何も指定しない場合は最大で25件取得しますが、今回は1件だけでいいので少しでもデータ量を減らすためにこのようにしました。

さて、これで実際に表示させてみると以下のようになります!


いいですね~。きちんと取得できています。これで完成です!

……が、よく見るとサムネイル画像のURLとかも JSON に載っているみたいですね。うむ。ちょっと弄ってみよう。

STEPα 大改造

数日後、 Javascript の大改造、および CSS の追加により以下のようなものが完成しました。



カードのような形でカテゴリ別の最新記事を表示するようになりました。半透明と影の実験の結果です。背景が単色だとわかりにくいので、 Blogger テンプレートデザイナーで最初から選択できる画像を使ってみました。

現段階のプログラムは以下のようになっています。

<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("^([^\\:\\/\\?#@]+\\:)?\\/\\/[^\\/\\?#]+")).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 + "&max-results=1";
      madoug.feedListeners[listener_id] = function(json) {
        var listeners = document.querySelectorAll("#" + widget_id + " [data-listener-name=" + label_name + "]");
        var html = "<ul class=\"feed-added\">", entries = json.feed.entry;
        for (var i = 0, imax = entries.length, entry = entries[0]; i < imax; entry = entries[++i]) {
          var time, time_type, time_str;
          if (entry.published.$t != null && entry.updated.$t != null) {
            var published_time = new Date(entry.published.$t);
            var updated_time = new Date(entry.updated.$t);
            time = published_time >= updated_time ? published_time : updated_time;
            time_type = published_time > updated_time ? "published-time" : "updated-time";
          }
          else if (entry.published.$t != null || entry.updated.$t != null) {
            time = entry.published.$t != null ? new Date(entry.published.$t) : new Date(entry.updated.$t);
            time_type = entry.published.$t != null ? "published-time" : "updated-time";
          }
          if (time != null) time_str = time.getFullYear() + "年" + (time.getMonth() + 1) + "月" + time.getDate() + "日";
          for (var j = 0, jmax = entry.link.length, link = entry.link[0]; j < jmax; link = entry.link[++j]) {
            if (link.rel == "alternate" && link.type == "text/html") {
              html += "<li>"
              + "<a href=\"" + link.href + "\">"
              + (entry.media$thumbnail != null ? "<img src=\"" + entry.media$thumbnail.url + "\"/>" : "")
              + (time_type != null ? "<span class=\"" + time_type + "\">" + time_str + "</span>" : "")
              + "<span class=\"title\" dir=\"" + dir + "\">" + link.title + "</span>"
              + "</a>"
              + "</li>";
              break;
            }
          }
        }
        html += "</ul>";
        for (var i = 0, imax = listeners.length; i < imax; i++) {
          listeners[i].innerHTML = html;
        }
      }
      var elem = document.createElement("script");
      elem.setAttribute("src", feedUrl);
      document.body.appendChild(elem);
    }
  })();
  // ]]>
</script>

そして、css はこんな感じです。試行錯誤の名残でごちゃごちゃしていますが、今のところ問題なく動作しています。

#Label3 a {
text-decoration: none;
}
#Label3 dl {
margin: 0;
padding: 0;
}
#Label3 dt {
margin-top: 16px;
margin-bottom: 8px;
}
#Label3 dt:first-child {
margin-top: 0;
}
#Label3 dt a {
display: block;
padding: 0.2em 0.5em;
background: rgba(221, 153, 68, 0.8);
color: #ffffff;
font-weight: normal;
border: 2px outset rgba(204, 136, 68, 0.8);
}
#Label3 dt a:hover {
background: rgba(221, 153, 68, 1);
border: 2px outset rgba(204, 136, 68, 1);
}
#Label3 dt a:active {
border: 2px inset rgba(204, 136, 68, 1);
}
#Label3 dt .label-name:after{
content:">>もっと見る";
font-weight: normal;
color: #cccccc;
font-size: 12px;
}
#Label3 dd {
clear: both;
display:block;
margin: 0;
padding: 0;
max-height: 98px;
min-height: 98px;
}
#Label3 dd ul {
list-style: none;
margin: 0;
padding: 0;
}
#Label3 dd li {
margin: 8px;
}
#Label3 dd li a {
display: block;
padding: 8px;
height: 72px;
background: rgba(255,255,255,0.8);
box-shadow: 1px 1px 3px rgba(0,0,0,0.5);
color: #666666;
}
#Label3 dd li a:hover {
background: rgba(255,255,255,1);
box-shadow: 1px 3px 6px rgba(0,0,0,0.5);
color: #888844;
}
#Label3 dd li img {
float: left;
margin: 0 8px 0 0;
}
#Label3 dd li span.published-time, #Label3 dd li span.updated-time {
display: block;
line-height: 1;
height: 11px;
font-size: 11px;
overflow: hidden;
color: #888888;
margin-bottom: 7px;
}
#Label3 dd li span.published-time:after {
content: " 公開";
}
#Label3 dd li span.updated-time:after {
content: " 更新";
}
#Label3 dd li span.title {
display: block;
line-height: 1.3;
font-size: 15px;
height: 54px;
overflow: hidden;
}
#Label3 dd li span.title:after {
display: block;
content: "";
clear: both;
}

良いものが出来た! よくがんばった! さっそくブログに反映だ!

まとめ

無事、ラベルごとの最新記事を表示するラベルガジェットを作成することが出来ました。問題は、テンプレートの書き換えなしに javascript だけでラベルガジェットをこんな風に改造することが出来ないということです。

ラベルガジェットについては、_WidgetManager というオブジェクトからラベル名や URL を取得することが出来ないので、javascript でラベル情報を取得する方法が乏しいのです。出力された標準のラベルガジェットの文書構造から推察するという曖昧な手段を使用するほかありません。

今後のために対策を立てたいところです。

以上、今回はここまでとさせていただきマス!

0 件のコメント :

コメントを投稿