window.onhashchangeが便利すぎる

昨日の記事
http://d.hatena.ne.jp/da-yoshi/20100722/1279811055
に対してコメントいただきました。
http://d.hatena.ne.jp/da-yoshi/20100722/1279811055#c1279857804
window.onhashchangeというそのものズバリのイベントハンドラがあるのですね。
IE8については、HTML5だけではなく、XHTML1.0やHTML4.01の標準モードでも動作しました。Firefox3.6でもChrome5でもSafariでも動作しますね。これなら十分採用できます。ちょっと簡単なHTML書いてみました。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
  $(window).bind("hashchange", function() {
    $("#p1").text(this.location.hash);
  });
  if (window.location.hash) {
    window.onhashchange();
  }
});
</script>
</head>
<body>
<p id="p1">test</p>
<a href="#link1">link1</a>
<a href="#link2">link2</a>
</body>
</html>

業務系アプリでよくある一覧画面の検索やページング、詳細画面への遷移などは、このハッシュとhashchangeハンドラを使えばかなり楽に構築可能ですね。リンクに対して個別にイベントを定義する必要も無ければ、動的に作成される一覧内のリンクに対して、jQueryのlive等を使う必要も無くなります。そしてURL直接アクセスや戻るボタン対応もこれで出来てしまうという、良いこと尽くめな機能です。
IE7以下への対応が必要なときはsetInterval等で代用すれば、ほぼ同じ手法で開発できます。このハンドラはHTML5で正式に仕様化されるみたいですが、XHRと同じく主要ブラウザが対応しているので、実質デファクトとして使っていけそうです。

Gmailを手本にフルAjaxアプリ

最近、初期画面からの遷移を全てAjaxで行うアプリを作る機会がありました。こういうアプリの標準的な構築手法を調べてみたところ、どうやらGmailがいちばんの手本のようです。
最近のRoR系FWだと、アプリのURLは

コントローラ名/メソッド名/ID

または

コントローラ名/メソッド名/key1/value1/key2/value2

となるのが殆どだと思います。GETのパラメータをURLに置き換えて、URLで状態を定義するという手法です。これは通常のWebアプリの場合は有効ですが、Ajaxアプリはサーバに対してURL遷移を行わないので、この手法は使えません。
Gmailの場合、画面ごとに画面名やパラメータをリンクのハッシュに付加していました。

受信トレイ
https://mail.google.com/mail/?hl=ja&shva=1#inbox

全てのメールの2ページめ
https://mail.google.com/mail/?hl=ja&shva=1#all/p2

変更するのはハッシュのみですので、サーバへの画面遷移は行われませんが、URLの履歴は残ります。表示されているURLをコピーして、別タブで直接アクセスしても、画面は再現されます。
これを自前アプリでやろうと思ったら

コントローラ名/初期画面メソッド名#key1/value1/key2/value2

とか

コントローラ名/初期画面メソッド名#value1/value2

のようなかたちでURLを定義して、クリック時にハッシュ値から送信パラメータを生成し、Ajaxで更新を行えばいいことになります。ロード時にハッシュの値がURLに含まれていた場合は自動的に更新するようにすれば、URLの直接アクセスにも対応できます。
ただし、これだけでは戻るボタンには対応できません。URLの履歴は残っていますが、locationのハッシュだけが変更されたときに画面を更新するような仕組みが必要です。Ajaxアプリは戻るボタンが効かない・・・とよく言われる(サイ本もそう書いてる)けど・・・でもGmailはちゃんと戻るボタンが効きます。
ググってみたところ、どうやらsetIntervalで定期的にlocation.hashをチェックして、変更されていたら更新する・・・という仕組みで、戻るボタンの挙動を再現するのが一般的のようですね。locationの変更を監視するようなイベントがあればもっと楽なんでしょうけど。
上記を踏まえて・・・

  • Ajaxで遷移するリンクに、変更するパラメータのハッシュを記述
  • クリックしてlocationのハッシュを更新
  • setIntervalでセットした関数内で、ハッシュが変更されたかチェックし、変更されていた場合ハッシュからパラメータ生成してAjax送信実行。現在のハッシュを保持しておく

こんな形で、汎用的なAjax用画面遷移が定義できるのかなと。setIntervalは戻るボタン用だけにして、通常のクリック時はclearIntervalして普通にAjaxイベントを実行して終了後にまたsetInterval・・・とかした方がいいかな?
そういやIEだとiframeが必要とかどうとからしいです。IE8だと普通に動いたのですが、更に古いブラウザ対応が必要なときは調査した方がよさそうです。

Google Contacts APIでフリガナ取得する方法

ここ数日、Google Contacts APIObjective-Cライブラリを触っていたのですが、取得した連絡先一覧をフリガナでソートしようとして、そのフリガナを取得する方法が見つからず悩んでいました。
ググっても見つからなかったので、元データのXMLをベタ出力したところ、

<gd:name xmlns:gd='http://schemas.google.com/g/2005'>
  <gd:fullName>泉新一</gd:fullName>
  <gd:givenName yomi='シンイチ'>新一</gd:givenName>
  <gd:familyName yomi='イズミ'></gd:familyName>
</gd:name>

こんな感じで属性「yomi」と定義されてあるのを発見・・・「yomi」って・・・
まぁ取り敢えず、ここに定義されてあるということは・・・

- (void)setYomi(NSString *)str;
- (NSString *)yomi;

GDataNameElementにありました。
これ使ってAPIでソートできたら完璧だったんですけど、Google Contacts APIは更新日でしかソート出来ない模様。

Web上のGoogle連絡先のカスタマフィールドにフリガナを登録してもiPhoneと同期できなかったのは、そもそもフリガナはカスタマフィールドでは無いからなんですね。Web上は読み取り専用で表示だけしているということか。
iPhoneGoogle Contactsを同期して使うなら、入力は必ずiPhone側でということですね。CSVで同期するときは、Google側でフリガナも対応できるみたいなんですけど

iOS4でGmailのExchange連携が不安定な件

http://www.google.com/support/forum/p/gmail/thread?tid=0aea7857b25a174f&hl=en
Google側も認識していて修正中らしい。自分の環境(iPhone3G)では一応現時点でGmail、Calendar、Contactsどれも連携は取れているのだけど。
取り敢えず、Gmailがプッシュ含め遅いのを我慢して使うしかないか・・・
(追記)どうやらGoogleのサーバが原因だったみたいで、現在は異常ないみたいです。着信即プッシュしてくれるようになったし、これで問題なくiPhone4へ・・・と思っていたけどどうやら二次出荷に回されたみたい(泣)

シュタインズ・ゲート

ネットで話題になっていた頃に買ったのですが、TOVやったりP3PやったりFF13やったりまたP4始めたりしていて、今年に入ってからは仕事も忙しくなって積んでしまっていました。4月に入って暇になったので、ようやく手を付けたらやめられなくなって、ここ数日ハマってました。
ADVにはよくあるタイムトラベルもので、主人公は超厨二病ネットスラングがこれでもかというくらい飛び交い、舞台は秋葉。もう狙いすぎだろってくらいの設定なんですが、しかしまたこれが実に面白かった。自分はジョン・タイターについて全然知らなかったのですが、ゲームクリア後にググってみると、ゲームの設定そのままの内容が書いてあって、これ知ってる人がプレイしたらそうとうニヤニヤ出来る設定だったんだな・・・と、自分の無知を少々呪ってみたり。
個人的に気に入ったのはダル。とある重要シーンでのツンデレセリフが最高でしたw P4の完二と中の人が同じとはとても思えない・・・後は、キャラというより展開が面白かったフェイリスかな? 電気街時代の秋葉に少々思い入れがあるので・・・
昨年10月に発売されたゲームですが、ネットスラングを使いまくってるというのもあって、賞味期限は少々短めなのかな・・・という気がします。勿論それだけが魅力のゲームではないのですが、100%楽しめる時期はそんなに長くないのかも。

Steins;Gate (シュタインズ・ゲート) (通常版) - Xbox360

Steins;Gate (シュタインズ・ゲート) (通常版) - Xbox360

iPhone2年使ってみて

2ヶ月程炎上現場にいたこともあって、またここ放置してました。
さて、iPhone OS4.0のニュースを色々読んでいて、そういや「これ」買ってもう2年になるんだなぁとしみじみ実感する今日この頃です。
使い始めた頃は、PCと同期してメールやカレンダーや連絡先等を簡単に共有出来るのが新鮮でした。携帯使ってた頃は、バックアップがめんどくさくて携帯の中に情報入れっぱなしにして、水没させて全部パーにして・・・みたいなことを繰り返していたのですが、iPhoneに変えてからそういうことは無くなりました。毎日のようにPCと同期させて、それまで面倒でやっていなかったスケジュール管理、連絡先管理とかを真面目にやるようになりました。
でも、ある時期からPCと同期する必要がほとんど無くなってしまいました。その理由はGoogleです。Google Syncを使ってGmailGoogle CalendarGoogle Contactsと直接同期するようにしてから、iPhoneだろうがPCだろうが全ての情報は一元化することになり、そして全ての情報がリアルタイムで更新されることになり、わざわざPCと同期する必要が無くなってきたからです。音楽も最近はiTunesでしか買わないので、これもPC使う必要無いし、正直言って同期はOSアップデートのときぐらいしか必要性を感じません。
正直自分はiPhoneそれほど使い込んでいるわけじゃないし、アプリもあんまし買わないし、それ程熱を上げているわけでもなんでもないのですが、そんな自分でも、この2年でこの端末の使い方が劇的に変わり、その影響でPCの使い方まで変わっていることを今更ながら実感しました。なんというか、iPhoneだろうがAndroidだろうがガラケーだろうがPCだろうが、自分の「情報」に触ることさえ出来れば後はどうでもいいわけで、PCが廃れるとかガラケーが廃れるとかスマートフォンはまだまだとか、そんなのどうでもいいかなというか。普段のシステム開発と同じで、日常生活レベルでも如何に情報を集約して一元化するかが便利さの鍵になってきているんだなぁ・・・と。
今は売れてないけど、ゲーム機とかもゆくゆくはPSP goみたいな形態で「購入履歴」をネット上で一元管理して、後は好きなハードにダウンロードして遊べばいい・・・みたいな形になっていくんだろうな・・・とか、映画とかドラマとかも近いうちにそうなっていくのかな・・・とか、なんかそんなことを考えてます。
4.0の新機能に全く触れてない内容で済みません(汗)