2009-06-23

Aptana Jaxer 向けの OS API をベースとした OpenSocial Client Library を作りました

おはようございます。なかじまんです。

Aptana Jaxer のサーバサイド JavaScript 向けの OpenSocial Client Library を作りました。opensocial-jaxer-client と名付け Apache License 2.0 のオープンソースとして Google Code で公開します。



opensocial-jaxer-client は OS API ( Lightweight JavaScript API ともいう) のソースコードをそのままベースとして Aptana Jaxer 向けに手直ししたものです。なので opensocial-jaxer-client を使うと OS API の手軽さそのままで OpenSocial の Server-side integration ができちゃうわけです。

さっそく実例を紹介します。

はじめに opensocial-jaxer-client.js をロードし osapi.init を使って初期化します。rpcUrl は RPC Protocol のエンドポイントです。fcauth は Google FriendConnect の cookie ベースのセキュリティトークンです。現在のリリース 0.1.0 は fcauth のみサポートします。近いうちに consumer key, consumer secret もサポートします。

<script src="opensocial-jaxer-client.js" runat="server"></script>
<script runat="server">

osapi.init({
rpcUrl: 'http://friendconnect.gmodules.com/ps/api',
fcauth: Jaxer.Util.Cookie.get('fcauth03382920006806842951')
});

osiapi.people を使って、プロフィールや友達リストを取得できます。OS API は execute メソッドの引数に与えた関数を非同期でコールバックしますが、opensocial-jaxer-client は同期して結果を戻り値で返します。

var viewer = osapi.people.getViewer().execute();

Jaxer.Log.info('Your name is ' + viewer.displayName);

var viewer = osapi.people.getViewer({
fields: ['profileUrl', 'thumbnailUrl']
}).execute();

Jaxer.Log.info('Your profile URL is ' + viewer.profileUrl);
Jaxer.Log.info('Your thumbnail URL is ' + viewer.thumbnailUrl);

osiapi.appdata を使って、アプリケーションデータの取得、更新、削除ができます。

var r = osapi.appdata.update({
userId: '@viewer', data: { gifts: 'a crazed monkey' }
}).execute();

var data = osapi.appdata.get({
userId: '@viewer', keys: ['gifts']
}).execute();

Jaxer.Log.info('AppData gifts is ' + data[viewer.id].gifts);

var r = osapi.appdata.deleteData({
userId: '@viewer', keys: ['gifts']
}).execute();

osiapi.activities を使って、アクティビティの取得と追加ができます。

var r = osapi.activities.create({
userId: '@viewer', activity: {
title: 'Hello!', url: 'http://example.com/'
}
}).execute();

var list = osapi.activities.get({
userId: '@viewer'
}).execute();

list.forEach(function(data) {
Jaxer.Log.info('Activity title is ' + data.title);
Jaxer.Log.info('Activity URL is ' + data.url);
});

osapi.batch を使って、上記の people, appdata, activities のバッチ操作もできます。

var batch = osapi.newBatch()
.add('viewer', osapi.people.getViewer())
.add('data', osapi.appdata.get({ userId: '@viewer' }))
.execute();

Jaxer.Log.info('Viewer id is ' + batch.viewer.id);
Jaxer.Log.info('Viewer name is ' + batch.viewer.displayName);
Jaxer.Log.info('Viewer thumbnail URL is ' + batch.viewer.thumbnailUrl);
Jaxer.Log.info('AppData gifts is ' + batch.data[batch.viewer.id].gifts);

Aptana Jaxer 向けということで、ほとんどニーズがないかと思いますが、わたし自身、目的があって使えていますので、もしかしたら必要とする人や場面があったりするかも... という願いを込めて、オープンソースとして公開しました。

2009-06-16

jQuery blockUI を使ってガジェットでメッセージや確認のダイアログを表示する

こんばんは。なかじまんです。

OpenSocial ガジェットを開発していると、メッセージボックスを表示して確認や選択を促したくなることが多々あります。が、残念ながら Gadgets API は (minimessage が微妙ですが)適切な手段を提供していません。JavaScript の alert や confirm で役立つこともありますが、それ以上の何かをしたいことが多いです。

そこで opensocial-jqueryjQuery BlockUI Plugin を使って、いろいろなダイアログを表示する実例を紹介します。

ガジェットの動画を用意しましたので、どのようなダイアログが表示できるのか見てください。"読み込み中..." のメッセージを表示するダイアログと、"はい" と "いいえ" を選択するダイアログを盛り込んでみました。



検索フォームの HTML です。

<form id="refresh">
<input type="text" name="vq" value="dog" />
<input type="submit" value="検索" />
</form>
<div id="videos"></div>

"はい" と "いいえ" を選択するダイアログです。

<div id="dialog" style="display:none;">
<div class="message">動画を検索します。よろしいですか?</div>
<input id="yes" type="button" value="はい" />
<input id="no" type="button" value="いいえ" />
</div>

YouTube Data API を使って、指定したキーワードで動画を検索しています。jQuery.getJSON という jQuery.ajax のショートカットを使っています。

function refresh(vq) {
var url = 'http://gdata.youtube.com/feeds/videos';
var data = { vq: vq, 'max-results': 25, alt: 'json' };
$.getJSON(url, data).next(function(json) {
$.each(json.feed.entry, function() {
var img = $('<img width="80" height="60" />')
.attr('src', this.media$group.media$thumbnail[0].url)
.appendTo(videos);
});
$(window).adjustHeight();
});
}

jQuery.ajax を開始したら "読み込み中..." のダイアログを表示して、jQuery.ajax が終了したら、そのダイアログを非表示にしています。

var css = {
border: '0', padding: '10px', '-moz-border-radius': '10px'
};

$('#videos')
.ajaxStart(function() {
$.blockUI({ message: '読み込み中...', css: css });
})
.ajaxStop($.unblockUI);

検索ボタンをクリックしたとき、"はい" と "いいえ" を選択するダイアログを表示しています。"はい" をクリックすると、ダイアログを非表示にして、入力したキーワードを使って、動画を検索します。"いいえ" をクリックすると、ダイアログを非表示にします(するだけ)。

$('#refresh').submit(function() {
var self = this;

$.blockUI({ message: $('#dialog'), css: css });

$('#yes').click(function() {
$.unblockUI(); refresh(self.vq.value);
});

$('#no').click(function() {
$.unblockUI();
});

return false;
});

});

ソースコード を公開しておきます。また gooホームのサンドボックス にインストールして体験できます。スタイルがチョー適当なので Firefox2 以外では、ダサダサかもしれません。

jQuery BlockUI Plugin の デモオプションの品揃え をひととおり見れば、何ができて何ができないかすぐに判断できるでしょう。また、軽量でシンプルなので、ソースコードを解析してしまったほうが早いかもしれません。

jQuery は有益なプラグインがたくさんありますので、何か実現したいことがあれば、まずはプラグインを探してみるとよいです。

2009-06-15

写真で手短に振り返る OpenSocial Hackathon in GDD 2009 Japan

おはようございます。なかじまんです。Google Developer Day 2009 の OpenSocial Hackathon の様子を写真でお伝えします。

6月3日(水) 渋谷の Google オフィスで事前ミーティングがありました。

Google Japan Blog: ハッカソン を 10 倍楽しむための アイデアソン
今回、6 月 9 日に開催が迫った Google Developer Day 2009 Japan に併せて 4 つの ハッカソンを開催することになりましたので、参加者の募集を兼ねてみなさんにお知らせします。また、それに関連して このハッカソン をスムーズに運営するために Google が行っている「アイデアソン」について紹介します。
グループのメンバーで1つのテーブルを囲んで、自己紹介からはじまって、アイディア出しがはじまります。



基調講演と OpenSocial in Japan セッションを担当した田中洋一郎さんが気軽に相談にのってくれます。



基調講演と OpenSocial パネルディスカッションを担当した北村英志さんがアドバイスしてくれます。



グループごとにアイディア出しの結果をプレゼンテーションします。









当日の 6月11日(水) は富士ソフトアキバプラザです。限られた時間の中で、試行錯誤しながら、黙々と真剣に開発していきます。別室では AppEngine Hackathon もやってました。





最後にグループごとに開発したものをプレゼンテーションして、優秀グループを決める投票をします。



OpenSocial Advance セッションを担当したゲストのパトリックシャネゾンさんからメッセージをもらったり、



パトリックシャネゾンさん、北村英志さんと記念撮影したり...。



ごくろうさまでした... と思いきや、解散の時間になってもはなしが尽きない様子です。



来月 7月も OpenSocial Hackathon を開催するとのことです。

天使やカイザーと呼ばれて: OpenSocial Hackathon参加を躊躇されてる方々へ
「Hackathonへの参加資格はありますか?」「どれだけOpenSocialのことを知っていれば、Hackathonに参加できますか?」「自分はHackathonに参加できるレベルではないです」「OpenSocialアプリケーション開発未経験ではだめですか?」など、OpenSocialに興味はあるけどHackathonに参加するのはちょっと・・・、という意見を聞くようになりました。このようなモチベーションの持ち主がHackathonに参加していただけないのは、主催する側からしても非常に残念なことです。
OpenSocial Hackathon の成果はいろいろな人が注目しています。OpenSocial Hackathon のアイディアが基調講演のネタになったりしています。

Tender Surrender » Google Developer Day 2009
基調講演では、先日一般ユーザー向けにも公開したgooホームのOpenSocialを使って、goo地図ガジェットとフォトビューアーガジェットがPhotomemoのガジェットに連動して動く、というソーシャルウェブ・ポータルというコンセプトを打ち出したgooホームならではのデモをお披露目しました。基調講演では言いそびれてしまったのですが、このアイディアは元々、先日行われたHackathonでディベロッパーの1チームが見せてくれたものを元にしています。
Hackathon の成果は hackathon-jp で共有して公開されています。

2009-06-13

Firefox の a.href と a.getAttribute('href') の違い

こんばんは。なかじまんです。Firefox で注意しましょうという小ネタです。

次のソースコードは Firefox3 と Firefox2、その他のブラウザで href 属性を参照した結果が異なります。

<script type="text/javascript">
jQuery(function($) {
console.log($('#a')[0].href);
console.log($('#a')[0].getAttribute('href'));
console.log($('#a').attr('href'));
});
</script>
<a id="a" href="http://example.com/?foo's bar">foo' bar</a>

Firefox3

foo%27s%20bar
foo's bar
foo's bar

Firefox2

foo's%20bar
foo's bar
foo's bar

その他

foo's bar
foo's bar
foo's bar

この事象って多くの人が知っていることでしょうか。JavaScript ライブラリを使わないでコードを書いていてはじめて気がつきました。

bugzilla を検索してみると、次の report がありました。

Bug 405890 – When getting a DOM element's href property, and when the href contains a space, the space is URLencoded as %20
My first search didn't find a bug that this is a direct duplicate of, but in spirit it's a duplicate of all the bugs talking about things like being surprised to get back an absolute URI when the href attribute had a relative URI - the DOM spec says .href is a URI, not the string you put in, and if you want the string you put in, you should .getAttribute("href") instead.
DOM 仕様の解釈の曖昧さから生じているのでしょうかね。間違ってはいないと思いますが、期待どおりではない感じですね。

なので href 属性を参照するときは、クロスブラウザをサポートする JavaScript ライブラリか getAttribute メソッドを使いましょということです。ご参考まで。

2009-06-10

Google I/O 2009 Google Friend Connect 関連セッションのビデオとスライド

おはようございます。なかじまんです。

Google I/O 2009 の Google Friend Connect (GFC) 関連セッションのビデオとスライドが公開されたので、ざっと全体を流し見と読みをしてみました。

Beyond Cut & Paste: Deep integrations with Google Friend Connect

Google Friend Connect を提供する目的や効果が説明されています。ダイアグラムを使ってビジュアルに表現しているので、GFC を使って自分のウェブサイトで何ができるだろうか...といったアイディア出しと関連付けて眺めてみると、有意義かもしれないです。

このセッションは In-page integration と Server-side integration を使ったウェブサイトのデザイン(設計)にフォーカスしたものでした。既存のドキュメント を補足する位置付けだし、インサイド的な話題もあり、発見があるかもしれないです。



Google Friend Connect Gadgets: Best Practices in Code and Interaction Design

このセッションは、ガジェットにフォーカスしたものでした。ガジェットのデザイン(設計)や UI のガイドラインが明示されていたりとか、Blogger をコンテナとしたガジェットの開発とか、あまり公になっていない(と思う)の話題が盛り込まれていました。



Google Friend Connect In The Real World

先日のエントリ Google I/0 2009 Google Friend Connect In The Real World で見つけた各認証プロバイダ画面へショートカットするウラ技 で紹介しました。



Google Friend Connect は Google Developer Day 2009 Japan の基調講演やソーシャルウェブのセッションでも紹介がありました。ソーシャルとは...を考察するネタとして Google Friend Connect をひとつの選択枠としてみると、新しい発見があるかもしれないです。

なんかよいアイディアが浮かびましたら、ぜひ教えてください。(PR) それと、Google Friend Connect を使ったウェブサイトやガジェットを開発するときは opensocial-jquery も試してみてくださいね。

2009-06-08

Google Friend Connect 対応した opensocial-jquery 1.0.3 をリリースしました!

おはようございます。なかじまんです。

opensocial-jquery 1.0.3 をリリースしました。opensocial-jquery は Google Friend Connect JavaScript API (GFC JS API) に対応し、いままでの OpenSocial ガジェットの開発に加えて、ソーシャルなウェブサイトも開発できるようになりました。

ひととおりの機能を盛り込んだデモを用意しましたので、まずは体験してみてください。

Google Friend Connect In-page integration (デモ)



デモのソースコードを抜粋して、使い方を紹介します。

初期化

ウェブサイトで opensocial-jquery を使うときは opensocial-jquery をロードする前に GFC JS API をロードします。

<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">google.load('friendconnect', '0.8');</script>
<script type="text/javascript" src="opensocial-jquery.min.js"></script>

GFC のサイト ID を指定します。必要に応じて canvas.html や rpc_relay.html を配置したディレクトリ、キャッシュの有無を指定します。そして、jQuery.ready を使って、GFC JS API を初期化します。初期化が終わると、jQuery.ready がコールバックします。

jQuery.container.id = '04434253654266747254';
jQuery.container.parentUrl = '/';
jQuery.container.cache = false;
jQuery(function($) {

リンク

サインイン、サインアウト、招待、アカウント設定のリンクを作成できます。

<div id="m1" class="menubar">
<a class="signin anonymous" href="#signin" style="display:none;">Sign in</a>
<a class="signout anonymous" href="#signout">Sign out</a>
<a class="invite anonymous" href="#invite">Invite</a>
<a class="settings anonymous" href="#settings">Settings</a>
</div>

jQuery.anonymous を使って、VIEWER がサインインしているどうかを確認できます。サインインしてないときは、不要なリンクを隠しています。

if ($.anonymous)
$('.anonymous').toggle();

jQuery.signIn を使って、サインインのポップアップを表示します。サインインするとコールバックします。ここではページをリロードしています。

$('#m1 .signin').click(function() {
$.signIn(function() {
location.reload();
});
return false;
});

jQuery.signOut を使って、サインアウトします。サインアウトとコールバックします。ここではページをリロードしています。

$('#m1 .signout').click(function() {
$.signOut(function() {
location.reload();
});
return false;
});

jQuery.invite を使って、招待のポップアップを表示します。

$('#m1 .invite').click(function() {
$.invite();
return false;
});

jQuery.settings を使って、アカウント設定のポップアップを表示します。アカウント設定を変更するとコールバックします。ここではページをリロードしています。

$('#m1 .settings').click(function() {
$.settings(function() {
location.reload();
});
return false;
});

認証プロバイダ

jQuery.signIn は、認証プロバイダを指定して、サインインのポップアップを表示できます。

<script type="text/javascript">
$('#f1').submit(function() {
$.signIn(this.provider.value, function() {
location.reload();
});
return false;
});
</script>
<form id="f1">
<select name="provider">
<option value="google">Google</option>
<option value="yahoo">Yahoo!</option>
<option value="aim">AIM</option>
<option value="openid">OpenID</option>
</select>
<input type="submit" value="Sign in" />
</form>

招待

jQuery.invite は、メッセージを指定して、招待のポップアップを表示できます。

<script type="text/javascript">
$('#f2').submit(function() {
$.invite(this.message.value);
return false;
});
</script>
<form id="f2">
<textarea name="message" rows="3" cols="40"></textarea><br/>
<input type="submit" value="Invite" />
</form>

ボタン

jQuery.fn.signIn を使って、サインインのボタンを表示できます。要素のテキストがボタンのテキストになります。また long や text の CSS で ボタンのスタイル を変更できます。

<script type="text/javascript">
$('#m2 .button').signIn(function() {
location.reload();
});
</script>
<div id="m2" class="menubar">
<div class="button"></div>
<div class="button long"></div>
<div class="button">Click here to join</div>
<div class="button text">Click here to sign in:</div>
</div>

ガジェット

jQuery.fn.gadget を使って、ウェブサイトにガジェットを追加できます。ここでは Google が開発した Members ガジェットを追加しています。このとき、ガジェットのスキンを VIEW パラメータとして引き渡しています。

<script type="text/javascript">
var skin = {};
skin['BORDER_COLOR'] = '#cccccc';
skin['ENDCAP_BG_COLOR'] = '#e0ecff';
skin['ENDCAP_TEXT_COLOR'] = '#333333';
skin['ENDCAP_LINK_COLOR'] = '#0000cc';
skin['ALTERNATE_BG_COLOR'] = '#ffffff';
skin['CONTENT_BG_COLOR'] = '#ffffff';
skin['CONTENT_LINK_COLOR'] = '#0000cc';
skin['CONTENT_TEXT_COLOR'] = '#333333';
skin['CONTENT_SECONDARY_LINK_COLOR'] = '#7777cc';
skin['CONTENT_SECONDARY_TEXT_COLOR'] = '#666666';
skin['CONTENT_HEADLINE_COLOR'] = '#333333';
skin['NUMBER_ROWS'] = '4';

$('#g1').gadget(
'http://www.google.com/friendconnect/gadgets/members.xml',
{ skin: skin }
);
</script>
<div id="g1" class="gadget"></div>

jQuery.fn.gadget を使って、指定したガジェット URL からウェブサイトにガジェットを追加しています。ここでは @agektmr さんが開発したあしあとガジェット を追加しています。

<script type="text/javascript">
$('#f3').submit(function() {
$('<div class="gadget" />')
.appendTo('#g2')
.gadget(this.url.value);
return false;
});
</script>
<form id="f3">
<input type="text" name="url" value="http://gadgets.agektmr.com/Footprints/friendconnect.xml" size="50" />
<input type="submit" value="Add gadget" />
</form>
<div id="g2"></div>

OpenSocial

jQuery.ajax と OpenSocial API を使って、ウェブサイトでプロフィールや友達リスト、アプリケーションデータ、アクティビティといったソーシャルデータを操作できます。ガジェットを開発するときと同じインタフェースを保っていますので、ガジェットを開発したときの経験や資産をそのまま活用できます。

<script type="text/javascript">
var url = '/people/@viewer/@self';
$.ajax({
url: url, dataType: 'data',
success: function(data) {
var person = data[0];
if (person.thumbnailUrl)
$('#person .thumbnail img')
.attr('src', person.thumbnailUrl)
.show();
$('#person .id')
.text(person.id);
$('#person .displayName')
.text(person.displayName);
},
error: function(xhr, status, e) {
$('#person').text(e || status);
}
});
</script>
<dl id="person">
<dt class="thumbnail"><img style="display:none;" /></dt>
<dd class="id"></dd>
<dd class="displayName"></dd>
</dl>

以上です。

Google Friend Connect API の initOpenSocialApi をもっとよく知る
initOpenSocialApi メソッドのコールバックは、何が引き金となって呼び出されたのか、判断することができません。ですが、何回目のコールバックか、cookie の有無とその変化を見て判断できそうな気もします。もうしばらく検討します。何かよい方法があったらお伝えします。
なお、見てのとおり、上記の不都合をうまく解決することができました。ここでは技術的な解説はしませんが、イベント発火元の要素やメソッドを特定できるインタフェースとし、最後の操作のみを有効とすることで解決しています。

2009-06-01

Google I/0 2009 Google Friend Connect In The Real World で見つけた各認証プロバイダ画面へショートカットするウラ技

こんばんは。なかじまんです。

Google I/0 2009 の Google Friend Connect In The Real World というセッションのスライドが公開されました。
Time.com social lists とか、



HuffingtonPost social slideshows とか、



ウェブサイトに Google Friend Connect (GFC) を統合する(した)実例を紹介するセッションだったようです。高度に統合するという視点では不十分な印象はありますが、自ウェブサイトで GFC JS API を使うと、どんなことができそうか実感からヒントを得られるかもしれないです。

Time.com social lists のソースコードから GFC JS API のアンドキュメントなウラ技を発見しました。ドキュメントで GFC にサインインは、次の引数なしのメソッドとなっていて、

google.friendconnect.requestSignIn();

そのメソッドを呼び出すと、次のような認証プロバイダを選択するポップアップが開くことになっています。



が、このとき、引数に認証プロバイダの識別子(だろうか?)を指定すると、プロバイダを選択するポップアップをスキップして、そのプロバイダの認証画面を直接ポップアップすることができるようです。ただ、なぜか NETLOG だけ期待どおり反応しませんでした。この引数はドキュメントに記載はありません。

google.friendconnect.requestSignIn('GOOGLE'); // OK
google.friendconnect.requestSignIn('YAHOO'); // OK
google.friendconnect.requestSignIn('AIM'); // OK
google.friendconnect.requestSignIn('NETLOG'); // NG
google.friendconnect.requestSignIn('OPENID'); // OK

Time.com social lists は Google や Yahoo!、AOL、OpenID のボタンを設置し、上のコードを使って、認証プロバイダのポップアップを直接開いています。これは Google Friend Connect を使う感覚が希薄な印象なので、これでいいのか? ... と思うところもありますが、このようなサインインボタンの選択もありうるってことですね。