トップ «前の日(05-03) 最新 次の日(05-05)» 追記

2006-05-04

_ prototype.js で Ajax してみた

※ このエントリはすぐ使えるサンプルを提供することを目的としていません。自分の試行錯誤を記録しているだけです。PHP と JavaScript をまーだいたい分かっている人間が実際に Ajax を書く際にうまくいかなかった点の実例としてご覧下さい。

まとまった情報を紙でほしかったので WEB+DB Press Vol.31 を Amazon のマーケットプレイスで購入して GW の宿題としてチャレンジ。とは言っても事前に @IT とかあれこれ情報は手に入れてるのでこの特集だけの知識で書いたわけじゃない。

しかし、思ったより難しいなっていうのが感想。

まず XMLHttpRequest そのものの理解がいまいち足りてない。つかいつも思うが JavaScript って調べにくいったらありゃしない。Ecma262 の部分はよくまとまってるんだけどな。どうにか作ったあとにつらつら見てたら

Dynamic HTML and XML: The XMLHttpRequest Object

これはコンパクトで見やすかった。こういう概観できるページってなんであんまないんだろ。

あとやっぱ prototype.js ドキュメント足りなすぎ。ほんとに便利な機能が入ってるのに、いちいち中身見なきゃ存在が分からないのはちょっと勘弁してほしい。

で、何を作ったかっていうと

24 ways: Edit-in-Place with Ajax

こんなやつ。イメージとしては del.icio.us の編集部分。

  1. サーバ上に一つファイルを用意して、onLoad でその内容を受け取る*1
  2. その部分をダブルクリックしたらそのテキストを編集する画面を出す
  3. 編集結果を save ボタンで送信してそのファイルに保存する
  4. cancel したら編集内容をすべて破棄して元に戻す

ま、これ作るだけならトライ&エラーでなんとかなる。escape() 使わないで encodeURI() にしてくれってところさえ気をつければほとんどコピペだし。*2

もともと JavaScript が HTTP クライアントになるだけっていうのはイメージついてたので、やっぱり気になるのは

JavaScript からのアクセスでない場合の対処が必要じゃん?

ってところ。prototype.js は HTTP リクエストヘッダにサインを入れてくれるけど、同じものを入れた普通のブラウザからのリクエストとはもう区別つかないわけでしょ? JavaScript からのリクエストに対して XML や JSON やプレーンテキストなどの断片の情報が返るのはアリだけど、普通にブラウザでアクセスした場合どうする、ってのを考えなきゃまずいんじゃないかなぁ。誰もいたずらしないならいいけど。

そうすっとやっぱ session とか URL の設計とかって話になると思うんだけど、そういう参考になる記事って全然見ない。まぁあんまり現実に即しすぎてても面白くはないんだろうけど。あと、

「アプリケーション」じゃなくて「サイト」には適用しにくい

これ、実は最近ずっと感じていることなんだけど、世のフレームワークってほぼ全部「アプリケーション」を指向している。当然「プログラマ」から見ると Web というプラットフォームで動くアプリケーションなんだろうけど、その考え方だけではサイトとしてイマイチ。

JavaScript は geek の間では復権しているかもしれないが、セキュリティ上の問題で普段 off にしてるって人も一定程度いるだろうし、何より 「JavaScript が使えないと情報が手に入らない」という状況はユーザビリティ的にも SEO 的にもまずい。そうするとどこでどう使うかをよく考える必要がある。ま、楽しみを残してもらってるとも言えるけど。

リクエストヘッダの Accept に JavaScript 関係の情報が載れば便利なのになぁ。JavaScript が有効だったら JavaScript 用の情報を返す、そうでない場合は HTML を返すってのをクライアントサイドの JavaScript を使わずに判別できれば、JavaScript 用の分と <noscript> の分と両方返す必要がなくなる。どーーーにかうまいこといかんかなぁ、この辺。

今度は MochiKit 使ってみるかな。prototype.js だけだとバグ見つけにくい気がする。あと、当たり前だけどいくら prototype.js 使ってもイベントハンドラをセットする際の制限とか超えることはできない。prototype.js 使えば楽ちん!て思えるのは prototype.js 以前の苦労を知ってこそだなと思った。

成否の判定と PHP の error_reporting()

[2006-05-05 追記]

読み出し、更新についてわざと失敗させ*3、それへの対応を作り込んでみた。ちなみに今回はライブラリは prototype.js のみ利用し、PHP 側は何も利用せずに全部手で書いて済ませた。便利なフレームワークを使えば PHP 側と JavaScript 側、という風に分けて考える必要はないかもしれないのだけれど、とりあえず練習ってことで。

で、失敗させてるんだけど、いつまで経っても失敗したときの status が返ってこない。*4ブラウザ上では何が起きているのかさっぱり分からないのでサーバ側で簡単なログを吐く仕組みを用意し、狙ったメソッドに処理が移っているのかどうかを確認。うむ、確かに失敗している。でも livehttpheaders で確認すると 200 OK が返ってきている。あ、そうか。error が 200 OK の HTML で返っちゃってるんだ。うーむさすが PHP. てことは Ajax 作り込むときはテスト環境であっても PHP の error は全部 log に吐くようにしないとダメなんだな。

で、実際に読み出しに失敗させてみると、読み込む領域に「最初からは」編集可能ですよと目で分かるスタイルは設定しない方がよいことに気づいた。

どういうことかというと、

.editable {
  border: 1px solid #fefefe;
}
.editable:hover {
  border: 1px solid yellow;
}

こんな風に編集可能な領域はマウスカーソルを合わせると border に色がつくようにしておいたんだけど、このままだと内容がなくてもこの上をマウスが通過すると色が変わる。これはまずいので、読み出しのリクエストのときにこうしてみた。

$('box').setAttribute( 'class', 'editable' );
Event.observe( 'box',
               'dblclick',
               function() { make_editable($('box')) },
               false );

これを request の option の onSuccess にセットする*5。つまり

  1. 読み出しが成功したら
  2. 編集可能な領域であることを示すスタイルを追加し、
  3. 編集モードにスイッチするためのイベントをセットする

box ってのは今回試しに用意しておいた、ここに編集可能な内容が入りますよっていう目印の div 要素。これはついでに

$('box').setAttribute( 'title', 'ダブルクリックすると編集できます。' );

こんな風にしておくと親切かなと思った。マウスが合ったときにここは編集できますよと教えてくれる。色が変わるだけだと意味が分からないもんね。

次、書き込みの失敗。書き込み時は

  1. 内容を送る前に見た目上は編集結果が反映される
  2. 成功したら黙ってそれが定着する
  3. 失敗したら
    1. 「失敗した!」ってメッセージを出して
    2. 送信前の編集状態に戻す

という処理にしてみた。このためには

  • 編集用の textarea
  • 通常の HTML として内容を表示
  • 更新に失敗した!ってメッセージ

の3つの表示を切り替える必要がある*6。ここで上の edit-in-place のサンプルを読みながら感心したことは、

JavaScript で HTML を書き換えるときは DOM を変数として扱っちゃえばいいんだ

ってこと。生の JavaScript で書いていたときはこの感覚に至ることはできなかったけど、prototype.js のおかげで

Element.show( ID )
Element.hide( ID )
Element.remove( ID )
new Insertion.After( ID, 内容 )

などの超便利な書き方ができると、内容を変数に持つんじゃなくて、DOM そのものが変数なのねという心境になってくる。あーこれはものすごい楽だ。面白いぞ JavaScript.

ちなみに今回

  1. 編集に失敗した!ってメッセージを出し、
  2. ちょっと経ってから
  3. 編集画面に戻る

という処理をするためにどうしても sleep() がほしくなり、あちこち探しまわったが汎用の sleep() で使いたくなるものがなかったんだけど、これは

var failure_notice = '<div id="' + obj.id + '-failure">失敗しますた!</div>';
Element.hide( obj );
new Insertion.After( obj.id, failure_notice ); // メッセージを表示
setTimeout( function() {
  Element.show( obj.id + '-edit' );            // 編集画面を表示
  Element.hide( obj.id + '-failure' );         // メッセージを消去
}, 1500 );

こんな書き方ができることに気がついた。更新に失敗したら

  1. 今まで表示してた内容を消して
  2. 失敗しましたってメッセージを Insertion.After で作り、
  3. 1.5秒後に編集画面を on にしてメッセージを消す

sleep() 要らない。無名関数最強すぎ。

参考

*1 ファイル直読みじゃなくて PHP で開いて返す

*2 PHP のマルチバイト関数がなんかどうも腐ってて変なハマり方したけど。

*3 ファイルの permission をちょちょいといじるだけ

*4 今回は試しに 406 Not Acceptable を返すようにしてみた。500 Internal Server Error とかの方がいいのかな?

*5 onSuccess ってのは prototype.js 依存なので他のライブラリを使う、あるいは生書きのときには通じないイディオム。

*6 実際には更新を諦めて cancel したときに元に戻せるようにしなくちゃいけないので4つの切り替えが必要。

_ FreeBSD(98) 2.1.0R 入門キット

CD を整理してたら FreeBSD入門キットが出てきた。中身は FreeBSD(98) 2.1.0R. たぶんこれが初めてのやつだな。

でも捨てちまおう(酷

Amazon で調べると 2.1.0 が入ってるのは恐らく 95年か 96年のもの。でも自分が初めて入れたのはたぶん 97年なんだよな。まだのんびりしてた時代なのね。

※ CPAN の CD とか Prime Time Freeware の CD とか出てくるなぁ…。「筆入れのバックアップ」が出てきたよ。すごいぞ、昔のおれ。

Tags: 日々 Unix
本日のツッコミ(全1件) [ツッコミを入れる]

_ TrackBack [http://aligach.net/diary/20060508.html あーありがち [Web][Ecma..]


2007-05-04

_ irc とか im とか

※ 相変わらず完全には休まない日々。

OSX の irc 環境を調査。以前 Classic 用のものを調べてファイル転送が死ぬほど遅くて実運用を諦めた経緯があるので、もう一度その辺を知っときたかったから。

結果。面白いことが分かった。

アプリ Win アプリ Mac 転送速度
IPmsg IPmsg 900KB/s
LimeChat X-Chat Aqua 600KB/s
LimeChat Conversation 850KB/s

※ サーバは irc-hybrid 7.2.1 で、無線 LAN 経由なのでそれほど速くない。

予想通りアプリによって違うんだけど、LimeChat - Conversation 間では瞬間最大で IP messenger 同士の通信より速くなった。おやおやおや。これはいいかもしれんぞ。

ついでに使い勝手的な部分でいくと、

X-Chat Aqua
日本語インターフェイスがないし、文字エンコーディングを GUI から選択できない。
Colloguy
エンコーディングの選択はその場でできるけど日本語インターフェイスがない。
Conversation
エンコーディングは環境設定からの変更になるけど日本語インターフェイスがある。全体に質素で、分かりやすいと言えば分かりやすい。サーバやチャンネル情報を明示的に設定、保存するインターフェイスがなく、手で入れた情報が自動的に XML で保存される。削除はこれを手でいじるしかなさそうに見える。

てな感じ。自分がいじるならどれでもいいけど他人に使わせるとなると日本語インターフェイスの有無はでかい。Conversation はファイル転送も速いのでかなりよさげに見える。あ、日本語ファイル名については試してないな。テストしなきゃ。

Jabber

サーバのある Messenger ということで名前だけ知ってた Jabber も興味出てきた。が、これはさすがに今回は時間切れだろな。(と言いつつとりあえず FreeBSD にサーバをインストールし始める。)

Jabber についてよく分からないのは

  • irc の channel のように一部のユーザーだけに注視できるか
  • 逆に IP messenger のように他のグループとやりとりしやすいか
    • irc では通常、メッセージをやりとりする channel にはすべて入っておく形になる
  • IP messenger のように必要なときだけメッセージのやりとりをしやすいか
    • チャットだとどうしてもウィンドウを出しっぱなしにしたくなる
  • IP messenger や irc クライアントのように動作は軽いのか
    • 特にプロプラな囲い込み系 IM のように重いのは勘弁してほしい

矛盾しているんだけど、要するにこっちの希望というか注文としては以下のような辺り。

  • irc は 1対1 の瞬間的なやりとりが中心の場合にあまり嬉しくない
  • IP messenger は 1ウィンドウ : 1メッセージなので(つまり履歴を活かせないので)込み入った話に不向き*1
  • IP messenger はログを各自で保存するしかなく、サーバに保存して誰でも検索できるようにするなどの工夫はできない。またログはデフォルトで保存されない。*2
    • これと 1ウィンドウ : 1メッセージな点と絡んで、必要なウィンドウをうっかり閉じて「黒やぎさん状態」になることもある。
  • 必要なユーザーだけに素早く送信したい
    • IP messenger はユーザーが多くなると非常に使いにくい。フィルタリングや優先度などの工夫は認めるけど、どうしてユーザー名検索にみんな注目しないんだろうか。
  • クロスプラットフォームで動くこと
  • 日本語インターフェイスがあり、多くの人に薦めやすいこと
    • とりあえず OSX なら問題ないけど、あとはどうなんだろ
  • 動作が軽いこと

相変わらず注文が多いけど、満たす注文の数が多ければ多いほど嬉しいわけ。Classic Mac が入っている場合は Jabber は自動的に排除されるわけだけど、とりあえず今回それは抜きにして考える。個人的には irc も IP messenger も一長一短だと感じているところ。

Jabber はサーバがあるので リアルタイム性と記録性、閲覧性、検索性の間 で書いたような工夫のしがいがあるのもいいな。何をどう仕込んでいくかはなんにも考えてないけど。

*1 電話か対面の方が向いているという正論はとりあえず置いておく

*2 サーバ動作する互換クライアントがあればブロードキャストしたメッセージについてはなんとかなるかもしんない。

_ めがね買った

今のめがねは5年になる。長いか短いかは人によって判断が変わると思うんだけど、正直コレ自分の顔に合ってないのね。舶来だもんで。やっぱねぇ、日本人の顔には合ってないの*1。デザインは気に入ってるんだけどさ。部品がないからメンテにもえらい時間掛かるしね*2

つーことで実は数年前から変えたくてしょうがなかったんだけど、それなりに値段するものだから(自分の場合はレンズがどうしても高めなので)我慢してたの。

今回は、生まれて初めてセルフレームにしてみた。と言っても普通のセルフレームとはかなり違います。今回は見た目だけでなく機能性にもこだわったのですよ。えーとどこのだっけ。Eye'DC ってとこ。

……。

また舶来だorz

いや、掛け心地は今よりずっといいよ。マジで。

Tags: 日々

*1 スキルのある技師が気合い入れて調整すればなんとかなるんだけど、そこまでやってくれる人はあんまりいません。あちこち行きましたけど。

*2 このめがねはつるの部分がワイヤーで繋がってるタイプなんだけど、以前これが切れたときは修理に 3週間掛かった。


2011-05-04

_ Mac + EvoでUSBテザリング = EasyTether

Evo は一応 au で初めてテザリングを公言できる端末で、USB テザリングも WiFi テザリングもできて、3G でも 4G(WiMAX) でもテザリングできる。

WiFi テザリングについては特に難しいところがなかったのだけど、問題は USB テザリング。というのも、USB テザリングするためには HTC 純正の HTC Sync を使うんだけど、これが Mac で動かない。ということに気づくまでしばらく時間が掛かってしまった。そうか、まさか Mac に対応してなくて Linux に対応してるとは。

ということで結局どうしたかというと従来からみんな黙って使ってた EasyTether を使う。

  • EasyTether Lite を Evo にインストール
  • Mac に EasyTether 用 NIC ドライバをインストール
  • Evo を USB デバッグ ON で Mac に接続
  • EasyTether NIC の DHCP を使うように Mac を設定

これをネットワーク環境設定で保存しておく。

うむ。便利になった。まぁ USB テザリングでなきゃダメなことってどんだけあるの?って聞かれると想像がつかなくて、だったら WiFi でいんじゃね?とも思うんだけど、

できるはずなのに方法が分からないってなんかシャク

なので調べてやってみた。以上。

[2011-05-28 追記] EasyTether は free version では https が block されてしまうので Twitter にも Gmail にも Evernote にも github にも支障が出る。気づいてなかった。

また、NIC をソフトウェアで再現しているせいなのか、WiFi テザリングよりも上りが遅くて PC 全体の性能も落ちるような感じがした。WiFi テザリングのできる Evo では素直に WiFi テザリングするのが正解なんだろう。

Tags: Net Android