jQuery + Google AJAX Feed API

以前にも何度かここでGoogle AJAX Feed APIについて書いてたのだが、JQuery HowTo: Google Feeds API - jQuery pluginを見て、もっとシンプルな使用方法があったことを知った。

クラス リファレンス - Google AJAX Feed API - Google Codeを再度確認して今一度。

上記で挙げたpluginでは渡す引数の順番に気をつけなければならないのが不満なので、使いやすいように書き直してみる。

Code

$.gFeed = function(options, callback){
  var opt = $.extend({
    v: '1.0',
    num: 10
  }, options);
  
  if (!opt.q) 
    return false;
  
  $.getJSON(
    'http://ajax.googleapis.com/ajax/services/feed/load?callback=?',
    opt,
    function(data){
      if (data) 
        callback.call(this, data.responseData.feed);
    });
}

使用できる引数の種類は「q, v, hl, key, context, num, scoring, output」
引数の説明はURL 引数で確認できます。

Usage

$.gFeed({
  'q': 'http://yas-hummingbird.blogspot.com/rss.xml'
  }, function(feed){
    var lst = [];
    for(var i=0; i<feed.entries.length; i++){
      var entry = feed.entries[i];
      lst.push(
        '<span><a href=' + entry.link + ' >' + entry.title + '</a></span>' + 
        '<span> - ' + 
        (function (date) {
          return (date.getFullYear() + '/' + (date.getMonth() + 1) + '/' + date.getDate());
        })(new Date(entry.publishedDate)) + 
        '</span>');
    }
    
    $(document.body).append('<ul><li>' + lst.join('</li><li>') + '</li></ul>');
});



iTunes Feed

このgFeedを利用して、さらに特定のFeedを取得するメソッドを作成する方が使いやすいだろうということで、iTunesのFeedを取得するメソッドを作成してみる。

Code

(function($){
$.iTunes = {
  categories: {
    Top_Albums: 'topalbums',
    Top_Songs: 'topsongs',
    New_Releases: 'newreleases',
    Just_Added: 'justadded',
    Featured_Albums: 'featuredalbums',
    _default: 'topalbums'
  },
  genre: {
    all: 0,
    country:6,
    electronic: 7,
    folk: 10,
    jazz:11,
    newAge: 13,
    pop: 14,
    rb_Soul: 15,
    dance:17,
    hiphop_Rap: 18,
    world: 19,
    rock: 21,
    vocal:23,
    reggae:24,
    jPop: 27
    // etc ...
  },
  feed: function( params, options, callback){
    var prms = $.extend({
      category:'topalbums',
      country:143462,
      limit:10,
      genre:0
    }, params);
    
    var countries = {
      usa: 143441,
      france: 143442,
      germany: 143443,
      uk: 143444,
      italy: 143450,
      canada:143455,
      australia: 143460,
      japan: 143462,
      // etc ...
      _default: 143462
    };
    
    prms.country = (function(c){
      return (+c == c) ? c : countries[c.toLowerCase()] || countries._default;
    })(prms.country);
    
    callback = $.isFunction(options) ? options : callback || function(){};
    options = ( !options || $.isFunction(options) ) ? {} : options;
    options.q = 
      'http://ax.itunes.apple.com/WebObjects/MZStore.woa/wpa/MRSS/' + 
      prms.category +
      '/sf=' + prms.country +
      '/limit=' + prms.limit +
      '/genre=' + prms.genre + '/rss.xml';
    
    $.gFeed(options, callback);
  }
}
})(jQuery);

Usage

$.iTunes.feed({
    category:$.iTunes.categories.Top_Albums,
    country:'japan',
    limit:10,
    genre:$.iTunes.genre.dance
  },
  function(feed){
    var $div = $('<div>').append($('<h3>').text(feed.description));
      $.each(feed.entries, function(i, entry){
      $div.append(entry.content);
      });
    $(document.body).append($div);
});


実際に使用して気付いたのだが、iTunesのFeedは応答が少々遅いのか、たまにではあるが初回読み込み時にタイムアウトしてしまい、Feedを表示できないことがある。
こういう場合、やはりgetJSONを使用するよりajaxメソッド使用してタイムアウトの時間を設定した方が良いかもしれない。

Google Web Elementsで唯一目新しいのはYouTube News Elementだけだ

Google Web Elements なるものを見かけチェックしたのだが、実際に目新しいのは「YouTube News Element」だけで、他は既に存在していたものを集めてきたにすぎない。

例えば、Custom Search ElementはCustomSearchControlを使用しているが、これは以前から存在し、既にネタとしては古い部類と言える。何ならGoogle AJAX Search API - Google Codeに行けば他にも色々あるので試してみるとイイ。

Google NewsのNews Elementはガジェットとしては新しい部類だが、Google AJAX Search API - AJAX News Barに行けばあるものであって、特に目新しくもない。

Conversation ElementはGoogle Friend Connectに行けば他にも様々なガジェットがあるので、そちらで選んだほうが良いだろう。

その他に関しても、ソースを見れば分かるが、APIで情報を取得してiframe内に表示しているだけで、それらのAPIは既に多くで使われているモノであり、何ら難しいことはしていない。Calendar Element, Spreadsheets Element, Presentations Elementは、あまりネタの古さを気にしない私でさえネタにするには躊躇するほど以前からあるもので、決してAPI自体目新しいものではない。

唯一、目新しい「YouTube News Element」に関しては、YoutubeのAPIは既にかなり前からあったのだが、このようなガジェットとして公開するのはGoogle Web Elementsがお初のはず。

よって、「Googleが"YouTube News Element"など言うYoutubeの指定したチャンネルの動画を表示、スライドさせるガジェットを公開した。」が正しい反応である。

何処かで「...パワーアップさせてかなりすごい!」などと言っているのを目にしたら突っ込んであげて下さい。

今ホントに目新しいものと言えば Google Wave だろうね。

Google Page CreatorからGoogle CodeのProject Hostingにお引っ越し

Google Page Creator もそろそろ閉鎖されると思われ、引っ越し先を探していたのだが、結局Google Code の Project Hosting に落ち着いたのだが、使ってみるとこれが案外便利。

Project Hosting では、プロジェクトを作成したらファイルをアップロードするのに Subversion を使うのだが、最初は TortoiseSVN を使ってみて、その後 aptana からも plugin をインストールすれば管理できることを知り、Subclipse を入れた。他にも Subversive というのもあるのだが、正直どちらがイイのか分らない。

使い方は簡単で分かりづらいことと言えば、MIME-TYPEの設定だろう。
TortoiseSVNなら適当なファイルを右クリックして[TortoiseSVN] - [設定]をクリックして表示されるダイアログの[一般]の編集ボタンを押すと表示されるテキストに使いそうなファイルのMIME-TYPEを設定する。

設定例:

  • *.png = svn:mime-type=image/png
  • *.jpg = svn:mime-type=image/jpeg
  • *.jpeg = svn:mime-type=image/jpeg
  • *.gif = svn:mime-type=image/gif
  • *.html = svn:mime-type=text/html
  • *.xml = svn:mime-type=text/xml
  • *.css = svn:mime-type=text/css
  • *.js = svn:mime-type=application/javascript
  • *.txt = svn:mime-type=text/plain
  • *.zip = svn:mime-type=application/zip

これらをテキストファイルの一番下辺りに追加すれば良かったはず。

aptana だと設定ダイアログの[チーム] - [ファイルコンテンツ]になるのかな?(単なる勘)

よく分らなくても、インポート/エクスポート、チェックアウト、コミットと他にはフォルダを作成することぐらいが出来ればとりあえず不自由はない。


Project Hostingは便利なサービス


リポジトリの管理をするつもりがない人でも単に便利なツールとしてProject Hostingを利用する価値はある。

例えばこのご時世、Javascriptを使用したWebページを公開するのも場所を選ぶ。ブログの投稿内のデモとしてちょっとしたページをアップしたいことがある。
そのようなページをWeb上にアップしておくにはちょうどイイ場所だ。

また、見方をかえればファイルのバックアップにもなる。たとえPCがブッ飛んでもファイルはWeb上にあるので安心。

画像もアップできるのでブログの背景などに使用するテクスチャ画像等をこちらにアップして使うのも良いのでは。

私はこのブログで使用するjsファイルはすべてこちらに移動して管理することにした。

そして何より、Webにアップする手間が少ない労力で行えるということ魅力。
手順としては、最初に作成したファイルをフォルダごとインポート、それをチェックアウトして aptana のプロジェクトとしてローカルに配置すれば、後は管理する者が自分一人ならロックの必要もなく、ファイルを編集したらコミットすればアップロード完了となる。コミットするのも aptana ならたった3クリックでおk。

私は手放せなくなりそうだ。

Google Data API を利用してRecent Postsの数を増やしてみた

前回、Google Feed APIを利用してRecent Postsの数を増やしてみたのだが、Google Data APIの方が簡単にできることが分かった。

Google Data APIなら、クロスドメイン制限を気にせず簡単にフィードを取得できるので、以下のコード以外に他に必要なものはない。

Code

<ul id='recentPosts'></ul>

<script type="text/javascript">
function getFeedList(data){
  var entries = data.feed.entry, alink = '', list = [];
  
  for(var i = 0, j = entries.length; i < j ; i++ ){
    var entry = entries[i];
    for (var k = 0; k < entry.link.length; k++) {
      if (entry.link[k].rel == 'alternate') {
        alink = entry.link[k].href;
        break;
      }
    }
    list.push('<li><span class="item-title"><a href="' + alink + '">' + entry.title.$t + '</a></span></li>');
  }
  
  document.getElementById('recentPosts').innerHTML = list.join('');
}

(function(domain, maxResults, order, redirect){
  var script = document.createElement('script');
  script.setAttribute('src',
    'http://' + encodeURIComponent(domain) +
    '.blogspot.com/feeds/' + order +
    '/default?redirect=' + redirect +
    '&max-results=' + (maxResults > 0 ? maxResults : 10) +
    '&alt=json-in-script&callback=getFeedList');
  script.setAttribute('type', 'text/javascript');
  document.documentElement.firstChild.appendChild(script);
}
)('yas-hummingbird', 10, 'posts', false);
</script>

Usage

  1. 上記匿名メソッドに渡している引数を適宜書き換える。
  2. レイアウトの変更でHTMLウィジェットを追加する。
  3. 追加したHTMLウィジェットに上記のulタグとJavascriptコードを貼りつける。

引数:
  1. ブログ ドメイン
    • 例: 'yas-hummingbird'
  2. 取得する投稿数
    • 0以上の数値で
  3. 取得するフィードの種類
    • 'posts' or 'comments'
  4. リダイレクト
    • リダイレクトの設定をされている方用に。


フィードの種類を'comments'にするとコメントフィードを取得することもできます。


Otherwise

<script src="http://yas-hummingbird.blogspot.com/feeds/posts/default?max-results=10&redirect=false&alt=json-in-script&callback=getFeedList"></script>

もし、上記のscriptタグの内容が理解できるなら、上記の匿名メソッドを削除して、このスクリプトタグを追加する方が簡潔になる。

要するに、上記の匿名メソッドはこのスクリプトタグを生成しているわけで、どちらかを選んで使ってね、ということです。


スクリプトタグに差し替えた場合の例

<ul id='recentPosts'></ul>
<script type="text/javascript">
function getFeedList(data){
  var entries = data.feed.entry, alink = '', list = [];
  
  for(var i = 0, j = entries.length; i < j ; i++ ){
    var entry = entries[i];
    for (var k = 0; k < entry.link.length; k++) {
      if (entry.link[k].rel == 'alternate') {
        alink = entry.link[k].href;
        break;
      }
    }
    list.push('<li><span class="item-title"><a href="' + alink + '">' + entry.title.$t + '</a></span></li>');
  }
  
  document.getElementById('recentPosts').innerHTML = list.join('');
}
</script>
<script src="http://yas-hummingbird.blogspot.com/feeds/posts/default?max-results=10&redirect=false&alt=json-in-script&callback=getFeedList"></script>


jQueryで書いてみる

<ul id='recentPosts'></ul>

<script type="text/javascript">
(function($){$.extend({
  // domain : blog domain
  bloggerFeed: function(domain, options, callback){
    var opt = $.extend({
      'max-results': 10,
      'redirect': false,
      'alt': 'json-in-script'
    }, options);
    
    callback = $.isFunction(options) ? options : callback || function(){};
    
    $.getJSON('http://' + domain + '.blogspot.com/feeds/posts/default?callback=?', opt,
      function(data){
        if(data)
          callback.call(this, data.feed);
      });
  }
})})(jQuery);

$(function(){
  $.bloggerFeed('yas-hummingbird', {'max-results': 15},
    function(feed){
      $('#recentPosts').append(
        '<li>' + 
        $.map(feed.entry, function(entry, i){
          return '<span class="item-title"><a href=\'' + 
            (function(links){
              for (var k = 0; k < links.length; k++) {
                if (links[k].rel == 'alternate') {
                  return links[k].href;
                }
              }
              return '';
            })(entry.link) + 
            '\'>' + entry.title.$t + '</a></span>';
        }).join('</li><li>') +
        '</li>');
  });
});
</script>

Google Feed APIを利用してRecent Postsの数を増やしてみた

Bloggerで用意されたFeedウィジェットは投稿数が5つまでしか取得できない。
このFeedウィジェットをちょっと調べてみるとどうもGoogle Feed APIを使用してるっぽい。
そうだとしてもBloggerはGoogleのサービスなのだから不思議ではない。

で、どうせGoogle Feed APIを使用するのなら自分でやれば投稿数も自由に変えられるので、ウィジェットに頼らず、Google Feed APIを使用して自力でFeedを取得するコードを書いてみた。

jQueryを使用したものとそうでないものの二種類。

ページ下部にzipファイルのテキストリンクがあります。

Usage

HTMLの編集からテンプレートのheadタグ内に以下のタグを挿入します。
<script src='http://www.google.com/jsapi' type='text/javascript'></script>
自身で試しましたが、APIキーは必要ないはずです。これは自身のフィードを取得しているのでクロスドメインではないからかな?

取得したフィードを表示するためにターゲットとなる要素が必要になるので、レイアウト画面で空のHTMLウィジェットを追加します。

追加した空のHTMLウィジェットのIDが分らなければならないので以下の3つの内のどれかの方法で対応してください。
  • 追加した空のHTMLウィジェットのIDを引数として渡す。
  • HTMLの編集でID自体を'HTML99'に変更する。
  • ソースを書き換える。

Feedを追加する対象の要素は以下のような階層になっている必要があります。(タイトルは無くても良い)
<div id="HTML99" class="widget HTML">
  <h2 class="title">Recent Posts</h2>
  <div class="widget-content"></div>
</div>


ソース下部で実行しているので、引数で渡すフィードのURLを適宜書き換えて下さい。
Code:
bloggerGoogleFeed('http://yas-hummingbird.blogspot.com/feeds/posts/default?redirect=false');


Default Option Value:
  • targetID:'HTML99' … コンテンツを追加する要素
  • numEntries:10 …取得する投稿数
  • pubDate:true … 投稿日を表示するか否か
  • author:false … 投稿者を表示するか否か
  • delimiter:' - ' … 投稿日、投稿者の区切り文字
  • dateFormat: … 投稿日のフォーマットを操作するメソッド
「dateFormat」は投稿日のフォーマットを自由に操作できるようにオプションで渡すことができるようにした。

Example:
bloggerGoogleFeed({
  targetID:'HTML2',
  numEntries:15
},'http://yas-hummingbird.blogspot.com/feeds/posts/default?redirect=false');

jsファイルの中に実行するコードは書かない方が良かったかな?

ブラウザ間によるborderのopacityの違い

親子関係にある要素にopacityを適用した場合のブラウザ間による動作の違いについて。
この違いはbackground-colorではなく、border-colorのopacityの差異についてまとめたものです。

以下のような階層構造の要素があるとします。

<div class="test outer">
 <div class="test inner">
  <div class="test core"></div>
 </div>
</div>

これに以下のCSSを適用します。
*{margin:0;padding:0;}
body{background-color:#fff}

.test{
 background-color:blue;
 border: 10px solid red;
 filter: alpha(opacity=50);
 -moz-opacity:0.5;
 opacity:0.5;
}

.test.outer{
 margin:10px;
 width:60px;
 height:60px;
}
.test.inner{
 width:40px;
 height:40px;
}
.test.core{
 width:20px;
 height:20px;
}


上記の表示結果:




要素の background-color を transparent にしてみる

例)
.test{background-color:transparent}

上記CSSで設定した要素のbackground-colorを透明にするか、あるいは削除すると以下のような表示になります。

要素のbackground-colorを指定しない場合の表示結果:


IEでは個々に設定されたopacityで表示される。
つまり、親子関係はopacityに反映されない




bodyのbackground-colorを変えてみる

body{background-color:#000}

bodyのbackground-colorを黒色に設定すると以下のような表示になります。

bodyのbackground-colorに黒色を指定した場合の表示結果:

図を見て分るとおり、Chromeでは明らかに色がおかしくなる。

このような違いがあることを知っておかないとJavascriptやCSSでborderとopacityが関係したトリックを行う際にハマるので注意。



IEも他のブラウザと同じように見せる方法はないか試してみた

CSSで行うのは面倒なのでjQueryを使用して以下のように処理してみた。
var $w = $(document.body),
opacity = 0.8,
bw = 10,
hw = 100;

for(var i = 0; i < 5;i++){
 var $x = $('<div>').css({
   opacity:opacity,
   border:'10px solid #ff0000',
   height:hw,
   width:hw
  }).appendTo($w);
 
 hw -= bw*2;
 $w = $x;
 
 if($.browser.msie) opacity *= opacity;
}

表示結果:


IEの場合だけ以下のように処理する。
if($.browser.msie) opacity *= opacity;

上記でopacityを「0.8」としたのはサンプルを多くしたかったため。

「恐らくこれでいけるだろう」と安易に考えたが...
どうもIEでは端数を切り捨てているっぽい。
同じように表示させるのは無理かもしれない。

私はここで挫折。

border-width を取得/設定するときに気をつけること

以下のような a要素に囲まれたimg要素はスタイル(CSS)を指定しないとブラウザによっては 2px の border が付けられることがある。

例)

<a href="#"><img src="image.jpg"/></a>

この img 要素の border-width を jQuery で取得し、違いを見てみる。

スタイル(CSS)での border 指定がない場合(defaultの状態)

img 要素の border-width を取得する
alert($('a > img').css('border-width'));
取得結果
IE82px
Firefox3空文字
Chrome空文字


img 要素の border-top-width を取得する
alert($('a > img').css('border-top-width'));
取得結果
IE82px
Firefox32px
Chrome0px

Chrome では default のままでは border は付かない。


CSSで「border:none」指定した場合

img{
  border:none;
}
img要素のborder-widthを取得する
取得結果
IE8medium
Firefox3空文字
Chrome空文字


img要素のborder-top-widthを取得する
取得結果
IE8medium
Firefox30px
Chrome0px


default との違い
  • IE8 で「medium」が返ってくる。
IE Testerというソフトで調べた限りでは medium を返すのは IE8 のみだった。



CSSで「border-width:0」指定した場合

img{
  border-width:0;
}

img要素のborder-widthを取得する
取得結果
IE80px
Firefox3空文字
Chrome空文字


img要素のborder-top-widthを取得する
取得結果
IE80px
Firefox30px
Chrome0px



結論

以上のことから、
  • CSS で border をなくす場合、jQuery で border-width を取得する際のことを考慮するなら、「border:none」ではなく「border-width:0」とするべき。
  • jQuery で border-width を取得する場合、
    「border-(top|right|bottom|left)-width」から値を得ること。

Sony Style(ソニースタイル)
デル株式会社

Recent Posts