defunkt/jquery-pjax - GitHub
「次はpjaxですねー」とか書いてから数ヶ月過ぎていたりしますけども、先日jquery-pjaxを用いて当ページのpjax対応をやってみましたよ。ちなみに、上記のリンク先にも書いてありますけども、pjaxはpushStateとajaxを組み合わせた造語で、ajaxを用いて表示内容を書き換え、pushStateを用いてそれに対応するURLへと置き換えhistoryも辿れるようにする技術です。
ajaxによるパフォーマンス改善の期待。#!(shebang、或はhashbang)を用いた場合のURLと表示内容の不一致の改善(permalinkと言えない。ツールにより取得できない)。googlebot用の_escaped_fragment_なURLへの対応が不必要。などがメリットとして上げられます。一方で、pushStateに対応しているブラウザでしか使えない(現状最大勢力であるIEさんでは不可です。モバイル系ブラウザも厳しい)。同一URLでajax用とフルアクセス用で表示内容が変わる(厳密に言って)。などがデメリットして上げられるでしょうか。対応ブラウザが限られる事は結構深刻で、shebangを使う手法ではほぼ全てのブラウザで機能していただけに残念です。でも、時が解決してくれるかもしれないですし、そもそもpjax自体がいつまでも有効な手法であるかもわかりません。
そんなわけで、我らがgithubのdefunktさんが開発しているjquery-pjaxです。もちろんgithubでも使われておりますし、jQueryのplug-inとして作られておりますし、仕様的にもスタンダードになるのではないかと思います。動作的には、pjaxが使えるブラウザどうか確認し、ajaxでHTMLを取得し要素を書き換えるが、ajax時の通信の再にX-PJAXというリクエストヘッダーを付加する。pjaxが使えない場合は普通にリクエストを送信するという感じになっています。特別なリクエストヘッダーを付加してくれるのでサーバ側での対応が可能になります。あればpjax用の、なければ普通のHTMLを返せばいいわけです。
使い方は適用したいaタグの要素にメソッドチェーンでpjax()を実行させるだけです。その際、書き換える要素のセレクタの文字列を引数で渡せます。あらかじめ適用したい要素にData属性でセレクタの文字列を仕込んでおく事もできます。ajaxで取得するURLも要素のhref属性から取得してくれるので手間なしです。しかも、内容を変更する要素にpjax:start、pjax:endという名前で前後に任意の処理を行うカスタムイベントも設定できます。さらに、実際のイベントはjQueryのlive()を用いて登録されるので、最初に実行してしまえば追加で取得したHTMLの中にpjaxを適用できるリンクがあってもそれに勝手にイベントを登録してくれるという便利仕様です。素晴らしい。
data-pjax属性を持ったリンクに全てpjaxを適用するようにして、その際に変更される要素はIDがcontentのものとすると、
$('a[data-pjax]').pjax();
$('#content').bind('pjax:start',function(){
任意の前処理
}).bind('pjax:end',function(){
任意の後処理
});
みたいになりましたよ。
これで基本的には動くのですけど、何だか私の環境ではpjaxになったりならなかったりしました。同じリンクを辿った場合でもなったりならなかったり。おかしいなと思ってソースを眺めてみましたら(読んではいない、なぜなら……)原因発見、timeoutの数値が私の環境では小さ過ぎました。どうやら上手く動いてくれないときは、pjaxで実行し始めているのですけどtimeoutして再度普通のリクエストを投げている、そういった動きだったようです。「なにこのブルジョワ数値。うちのサーバさまはそんなレスポンスで動いてくれないんだよぉ」とガッツリそれなりに大きくしましたら安定動作するように。しょっぱいサーバでごめんなさいねぇ。悲しいです……。
それと、送られてくる内容にhtmlタグを発見するとこれまた読み込み直してくれるので、最初にちょっと動かしてみようみたいなときに手を抜くと上手く動かせないみたいな事にもなります。ええ、なります、なりましたとも。
これでクライアント側は終了ですけど、今度は内容を返すサーバ側の準備が必要になります。当ページではDjangoというPython製のFrameworkを使っていますが、そちらの方でもちょっとだけごにょったのでそれはまた次回。でも、Djangoに限ってしまえば、
jacobian/django-pjax - GitHub
というのが既にあります。大した事ではなかったし私は自前で適当に適当な事にするのが好きなのでやってしまいましたが、こちらを活用するのもいいと思います。
実際に使ってみてかなり気に入っているpjaxですが、個人的にはshebangのやり方も嫌いではなくて、これからも場合によってはそちらを選択すべきだと思います。閉じたWebアプリとかだとそちらの方が対応ブラウザが拡がるし、fragmentURLへの対応も必要ないので手間もあまり変わりません。どちらにせよ、私はこういう風にシームレスに遷移していったり変更していったりするのが好きなんですよね。みんなもやるといいと思うよ。
ジョニー・アイブの追悼スピーチ « maclalala2
スピリチュアル・パートナーとまで言わしめたJonathan Iveのスピーチ。
血を分けた兄の死(1) « maclalala2
血を分けた兄の死(2)— 彼の人生 « maclalala2
血を分けた兄の死(3)— 病い « maclalala2
血を分けた兄の死(4)— 死 « maclalala2
実の妹であるMona Simpsonのスピーチ。
【コラム】新・OS X ハッキング! (20) あなたの知らない「Dock」の横顔 | パソコン | マイコミジャーナル
$ defaults write com.apple.dock itunes-notifications -bool YES
$ defaults write com.apple.dock notification-always-show-image -bool YES
$ killall Dock
これでアプリケーションアイコンと共にアーティスト名と曲名がDockの位置にポップアップ、いつものようにピョコンと心地よい動きで飛び出してきますよ。凄く凄く気に入りました。けど、アプリケーションアイコンをアートワークにもできたらもっといいのになぁ。
先日のpjax話(例のあれ(仮題)- pjaxを導入してみた。)の続きです。
pjaxではページの一部を変更しますから、やり取りするページのデータも一部でいいです。pjaxでないアクセスの場合は全てのページのデータをやり取りする必要があります。問題はそれらが同一URIでリクエストされる事で、サーバ側で判断してそれぞれに合った形でデータを供給しなければなりません。実際にはpjaxである事が確認できたら一部を、そうでない場合はとりあえず全てのデータを送信するようになると思います。
前回触れたようにjquery-pjaxではX-PJAXというヘッダーを付加してアクセスしてくれますので、それを利用して判定します。ビューで受け取ったRequestオブジェクトのMETA辞書の中にHTTP_X_PJAX(X-BenderみたいなヘッダーはHTTP_X_BENDERという風に大文字アンダースコア化されて格納されます)があるかどうかでOKですね。
def spam_view(request):
if 'HTTP_X_PJAX' in request.META:
pjaxの場合の処理
else:
pjaxではない場合の処理
return spam_response
とかが基本的な形になりますでしょうか。
基本がわかったところで、Ajaxのときと同じようにdecoratorにしてしまえばいいかなぁと。これをdecoratorにするのが果たして正解なのかどうかはイマイチ判然としませんけども、私的に便利そうだし書きたかったし。自前アプリで自前アプリ用に実装するので自前仕様上等でありますから、そういうのを幾つか適当に仕込みましたよ。
pjaxかどうか判定し、そうでなければ他のView関数を呼び出して返す。
その場合の呼び出される関数は、元の関数名から_pjaxを削除した名前で同一module内に実装してある。
後付けで、かつ自前だからこそできる規約的仕様。規約より明記とか言いながら規約。いい加減過ぎる。
def pjax_access(func):
def _pjax_access(*args, **kwargs):
if not 'HTTP_X_PJAX' in args[0].META:
module = __import__(func.__module__, globals(), locals(), [func.__name__.replace('_pjax', '')])
function = getattr(module, (func.__name__).replace('_pjax', ''))
return function(*args, **kwargs)
return func(*args, **kwargs)
return _pjax_access
あれこれ試しながら実装したらこうなりました。途中、どうして自分がいるmoduleをすんなりimportできないんだとかなんとか憤ったりしてました。
せめてViewの名前だけでも渡せるようにしたい場合は、もう一つ関数を入れ子にして、
def pjax_access(view_name):
def _pjax_access(func):
def __pjax_access(*args, **kwargs):
if not 'HTTP_X_PJAX' in args[0].META:
module = __import__(func.__module__, globals(), locals(), [view_name])
function = getattr(module, view_name)
return function(*args, **kwargs)
return func(*args, **kwargs)
return __pjax_access
return _pjax_access
とでもするといいと思いますよ。もちろんよくわからないままに書きました、そらそうです。
久しぶりにPythonやったら行末に;付けようとするわ、if (spam !== ham) {とか書きそうになるわで相変わらず頭悪いなって思った。賢くなりたいです。もう遅いですか、そうですね。
11月ともなればすっかり気温も下がって肌寒く……、なってねえ、全くなってねえ、むしろ暑かったわ、たまらなかったわ。すみませんすみません、過ごし難い環境の勉強会ですみません。と冒頭から謝罪で入りましたけども、生憎の雨の中での開催になってしまった八回目のれいかい、無事に終了いたしました。みなさまのお陰ですありがとうございます。

前回と違ってレギュラーな研修室に戻っての開場です。いつものように無線LANをセットアップあっぷあっぷ。

今回のスペシャルゲストはレコロさん(インターバルレコーダー「レコロ」|KING JIM)。ボクが欲しいって言ってるのを何故か買ってしまうナイスガイがいるんだ。

後ろからのご勇姿はこんな感じ。ちゃんと定点観測していただきましたよ。顔バレ過ぎるので公開できるかは微妙ですけど。

久しぶりに再会したボクの(違う)JAMBOXさん。ボクが欲しいって言っているのを(ry 私の旧式iPhone 3GさんとリンクさせてBGM強制再生させられます。本当にこれも欲しいなぁ。貧乏ってヤだなぁ。
そんなJAMBOXさんの操作模様を撮影してみました。

ヤらしく某告知的なのも書いてたりしましたよ。

そうこうしているうちに続々とお集りいただき、最終的に9名の方にご参加いただきました! ありがとうございます!! 前回に引き続きまさかの大人数による開催となりまして驚愕歓喜しております。
こうなりますと私を含めて10人で、椅子自体は14脚あるのですけどちょっと手狭ですね。こんな日が来るなんてっ。まぁ、でも、今だけのバブルです。驕らず地道に参ります、参りますとも。
カメラで撮っている動画の画像認識をして動いているところに泡を合成するとかいうFlashで作られているらしいアプリも見せてもらったよ。おもしろげ。こういうの大好き、もっとやれ!

この日のダブルWiMAXさんは白黒で。このルータ三色とも見た事あるていうか、そのうち三色揃えられそうじゃね。WiMAX tri的な。

そんなわけでお疲れさまでした。是非また遊びに来てくださいね、お待ちしております!
さて、ここからはおじさん達のお楽しみ呑み会タイムと相成りますよ。今回は私が奇跡の最年少でありまして、他の方は昔からコンピュータと戯れていた方々でしたから、新旧ネタを交えて大変濃い大変楽しいお話をたくさん伺えましたよ。こういうのいいです、凄く。

先週末くらいから行きたさマックスだった花山さんへロックイン! 串やで、季節到来の牡蠣さんとかやで!

タイラギさんとかも串でガッと!

チーズさんとか、

トマトさんも巻いて焼いて串ウマっ!

もちろん牛タンさんも欠かせませんし、

もつ鍋さんも頂きますよねー。満たされたわー。

しかしまぁ、止まらずその後立ち飲み屋さんとかへも行っちゃったりするのだけど。あかんあかん、あかんて……。
先月に引き続き、とっても気分のよかったれいかいでありました。本当に皆さまのお陰です。重ね重ね感謝いたします。これからもよろしくお願いします。何かの形で恩を返したいです、仇じゃなくて。
それでは次回は12月の3日。毎月最初の土曜日は「れいかい」で!
もはや恒例の「いきたいけどいきられないからノープランでいきたい、ただし夜になるとそこそこ持ち直す」病が最近また酷いので時期を忘れないためと恥をさらして自戒を込める為に。とかこういうのも何回目だよ。
まぁ、大丈夫です。
ゼルダの伝説トランプ
「グッズかよ、任天堂迷走してるなぁ」と思ったけど、そもそもこっちが本業だった。
お詫びに一つ買っておいたよ。甥っ子とか来たとき遊んでもらおう……。
InfoQ: 追悼:Steve Jobsのソフトウェアエンジニアリングへの貢献
ソフトウェアエンジニアリングの側面から辿る足跡。周りにたくさんのとんでもない天才たちをはべらし、そこから出てくるモノの取捨選択のセンス……。もちろん外したモノをあるけれど、本当に優れていたのだなぁとあらためて。
WebObjectsさんは私にとってもとても重要なモノでしたよ。知ったのはAppleの製品になってからですけど。
WOUnit - Test framework for WebObjects
WebObjectsでUnitTestを行うFramework。例によって試してません。ですよねー。
WebObjectsでJUnitを使うとなれば、以前にもWOUTというのがありました。違いはJUnit 4.7に対応している事、Wonderアプリケーションに対応というか必須という事みたいです。
相変わらずこの界隈の人たちはガッツがあります。少しは見習いなさいよ、おれ……。
ひとつめ(例のあれ(仮題)- 久しぶりにそれっぽい勉強会やりました。)の時は小数に対応していないゆとり風電卓アプリでしたけども、ひとつめ.1へ向けて晴れて対応しましたので脱ゆとり宣言であります。
12月17日のひとつめ.1の開催に向けて小出しにしていくヤらしい戦略ですよ! とか言って多分続かないけど。ネタがないよねー。ですよねー。