PHPでComet:フォーカスの当たっていないウィンドウが更新されない

この記事は次のブログに引っ越しました。

PHPprototype.jsを使ってAjaxでCometなチャットを作ろうとした。FireFoxで動作検証していたのだが、ブラウザの複数ウィンドウを立ち上げ、別マシンでもウィンドウを立ち上げて検証していたところ、フォーカスの当たっていない(アクティブでない)ウィンドウでは、TextAreaが更新されないことに気づいた。結論
更新する直前に"$(targetID).focus();"でフォーカスを当ててあげる。
script //要prototype.js function fAjaxUpdate(){ var sUrl = './upload.php'; var sPars = Form.serialize("idFormInput"); $('idTextArea').focus(); //←ここ ここ ここ var oAjax = new Ajax.Updater( "idTextArea", sUrl,{ method: 'post', parameters: sPars, });} /script Cometの仕組み チャットなど、タイマーで定期的にリクエストして更新する通信アプリ、つまりPULL式(データを引っ張ってくるタイプ)のアプリの場合、更新時間が来るまで待つ必要がありタイムライグが発生するため、即時反応という体感がいまいちありません。(このクライアントからサーバーに定期的にリクエストを送信する方法をポーリングとも言います) CometとはPUSH式、つまりサーバ側がクライアント側にデータを届ける仕組みを、アイデアと工夫で「擬似的にPUSH式を実装する仕組み」です。イメージとしては、メーラーがメールを一定置きにチェックしに行く(PULL式である)のに対し、携帯のショートメールなどのようにサーバーからメールが送られてくるタイプ(PUSH式)との違いみたいなものです。一般的なWEBの仕組みとして、サーバは、クライアント(ブラウザやJavascriptなど)がアクセスしてきた場合、リクエストされたWEBページ・スクリプト・画像・データなどを表示して終了します。(プル式。クライアントが情報を引き出すタイプ)しかし、クライアントがアクセスしてきても即座に表示せず、サーバ側で変更があるまで掴んだまま離さない・反応しない、つまり即座にリクエスト結果を返さないのがCometの大きな特徴です。当然サーバは反応しないので、しばらく経つとクライアント側はタイム・アウトでセッションを切るのですが、クライアントのJavascriptが即座に接続を繰り返すことで、サーバ側のリアルタイムな変更を得ることができるので、あたかもサーバから配信された(プッシュされた)ように見えるわけです。これが擬似的なプッシュ式と言われるゆえんです。経緯 海外やネットカフェにいてもオンラインでPHPCSSJavascript、HTMLソースをメンテナンスできる、いちいち保存したりアップロードしなくても紙copiのように即時更新されるオンライン・テキストエディタなるものが欲しかった。となると、FormのTextAreaを"onClick()"とか"onKeyDown()"で更新できたらいいじゃんと思って、ググッてみたら"Nob Funaki"さんが作られたmemooという、まさにドンピシャなのがあった。が、FireFox非対応とのこと。OperaSafariでの作業もあるため、ここはひとつ車輪の再発明かもしれないが、ブラウザ互換といえば、"prototype.js"!
いや、"jQuery"とかもあるんだけど…。で、作ってみて、サーバ負荷を減らすためにキー押下処理ごとにリクエストしないようバッファ処理したりとか、色んな処理に悩まされながら、なんとかできたんです。(セキュリティ処理したら公開したいな。)一人で作業する分には超便利なんですが、複数人作業だと更新のタイミング確認が面倒なこと面倒なこと。やはりここはメンバーとSkypeで話しながら仲良くペア・プログラミングとかクールにやってみたいのが、合理の非合理というもの。となると、一昔のチャットの悩みと同じで、METARefreshなAjaxで困った時のcometさん。とはいえ、cometの実績はなし。そこで、実装の前にテストをしたい。上記のCometの仕組みだけだと問題もあるんだけど、まずはこんなところからはじめた。すると上記現象が発生したんですよ。アクティブなウィンドウで一生懸命更新しているのに、昔のデータ(更新されない非アクティブなウィンドウのデータ)がちょくちょく送られてきて、いささかイラッとくる。「実際の利用時には複数ウィンドウなんて立ち上げないから」と割り切ってしまえば、そこまで気にしなくてもいいのかも、とも思ったが検証中はやはり複数ウィンドウを立ち上げるので、やはり現象がイラッとくる。最初は、非アクティブなウィンドウがサーバからレスポンスが返ってきた際に、ウィンドウを前面に持ってくるなり、アクティブ化させるのかとも思ったが、それだと作業中のウィンドウのフォーカスを持っていかれて、ウィンドウ同士が必死にアクティブ化のピンポンをはじめるのは必死で、またイラッとしそうだったので、どうしようかと悩んだ。ん?もしかして、フォーム(TextArea)にフォーカスを当てればいいとか?で、Ajax.Updater()がレスポンスをエレメントのinnerHTMLに書き込む前にフォーカスを当ててみたら動いた。あちょんぶりけとりあえず、このイライラを記録に残したかったの。