掲示板
知り合いが自分のwebページでhttp://www.ize-design.com/visualize/にあるize-Say! ver1.0を使っていて、ある日相談を受けた。ページを見に行くたびに名前が消えてしまって、毎回入力するのが面倒くさいということだった。
もともとこのCGIというのは掲示板と言うよりも一行チャットに近く、しかも手軽に既存のページ内に埋め込めると言うのがウリで、iframeを使って表示する物だった。iframeと、その下にFORMを配置すれば設置が完了する。
そのころはJavaScriptに関してあまりよく分かって無くて(今でもそんな詳しい訳ではないが)かなり苦労した。特に設置するサーバーがhtml類とcgiを別の場所に置くタイプだったため余計に苦労した。
JavaScriptに関しては初めてではなかったし、HTML内の要素を操作するのもそれ以前にしたことがあったはず。ただ、暫く間が空いていたし、同一平面上ではなくて、別のフレームを操作する必要があったため、以前やっていたことよりは多少難しくなっていた。実のところ、今でもよく分かっていない。それらしいことをごそごそやっていたらなんだかうまく行ったねえ、って、そんな感じ。
まあそれに関しては試行錯誤しながらもなんとか改造を済ませ、やれやれと思っていると暫くして、今度は二重投稿をなんとか出来ないかと言われた。なんでも、リロードすると今書いた物がもう一度投稿されてしまうらしい。
試してみると、確かに毎回ではないものの、条件はよく分からないがそういう現象が起こっているようだった。CGIを使って動的にHTMLを生成しているため、リロードするとそうなってしまうのはやむを得ない。ブラウザにとってみればそのFORMの内容が、CGIでHTMLを生成するのに毎回必要なデータなのかどうかの判断がつかないんだから当然だ。
暫く考えていたが、CGIで動的にHTMLを生成するのがダメなら、HTMLファイルをCGIで作り、それを表示するようにすればいいというのを思いついた。リロードするだけでパラメーターが必要ないため、二重投稿は起こらないはずだ。しかも、ページを表示するたびにCGIを実行しなくても良いため、サーバーへの負荷を軽減することも出来る。掲示板などでもけっこう使われている手法だろう。
まず、iframeを二つに分けた。発言表示用とフォーム表示用の二つだ。両方とも普通のHTMLファイル。下のフレームに発言内容を入れてエンターかsubmitボタンを押すとCGIが実行され、同じ下のフレームに実行結果を表示…とはせず、Locationヘッダを出力してフォーム表示用のHTMLに飛ばす。
このHTMLには仕掛けがしてあって、上のフレームをリロードしなさい、と、JavaScriptで書いてある。これで発言内容が更新され、二つのフレームはどちらも普通のHTMLになる。これをリロードしたところで再び発言してしまうことはない。Locationヘッダで飛ばしてやると、「戻る」ボタンを押してもcgiに戻ってしまうことはない。JavaScriptのreplaceメソッドでも同じだ。
そのときはそれで解決し、しばらくそれで動かしていた。
そして昨日。新しいサーバーに設置したいんだけど、なんかややこしいねえ、あれ、と言ってきた。実は先日、プロバイダを乗り換えたってんで移転するって話は聞いていた。と言うか既に三ヶ月前の話なんだけど…。忙しいのは分かるが、いくらなんでも放置しすぎじゃなかろうか。
普通にアップロードすればいいだけなのになあと思いつつ、久しぶりだからソースを眺めてみた。特別変な感じもなかったけど、なんとなくJavaScriptじゃなくてCGIの方でクッキーを作成しようと思い、やってみたら何故か動かない。と言うかエラーさえ出ない。なんでだろう。
IEではエラーが出ても表示がよくわからないうえ、jsファイルを分離してるとどの行がエラーを出しているか、行数がきちんと表示されない。これじゃあデバッグにならない。そこでFireFoxの登場。確かNetscapeにもあったと思うんだけど、これにはJavaScriptコンソールというものがある。こいつは便利だ。ちゃんと別ファイルのjsファイルにあるエラーの行数も出てくれるし、エラーの内容もわかりよい。
とりあえずそれで表示してみると、エラーだかなんだかよく分からないのが出ていた。document.allはもう古いからdocument.getElementByIdを使えよなって怒られてしまった。動かないこととは関係なさそうだったけど、そこらへんを修正したりごちゃごちゃしてるといつの間にか動くように。いつもこんなだ。
まあ動くようになったから送って、組み込んだらちゃんと動作してるようだ。
で、今日。よく考えたらiframeは二つも要らないんじゃないか。やはり発言内容を表示する部分だけをiframeで作り、フォームは普通にHTMLに書けばいいだろう。
ってことでやってみた。まあやり方としては普通のフレームと同じように、FORMのTARGET属性でiframeのNAMEを指定するだけだ。初め、CGIを書き換えるのを忘れていて、発言内容が表示される部分に、下フレーム用だったフォームが表示されてしまった。画面がフォームだらけだ。
それは飛ばすアドレスを変えればすぐに解決。問題は、フォームに名前と共に発言内容がそのまま残ってしまっている。名前が残っているのは問題ないが、発言内容が残ってしまっては困る。二重発言のもとになってしまう。
しかし、submitボタンにonclickを付けて発言内容を空にするようにしたら、発言内容が空になって送信されてしまった。submit押す->フォームが送信される->空にする のつもりが、submit押す->空にする->フォームが送信される という動作になってしまった。そしてFORMタグにonsubmitを付けてみたら、なぜか今度はイベント自体が発生しなかった。
仕方がないからイベントはonclickにし、その中身はsetTimeoutを置くだけにした。そしてそこで呼び出される関数で発言内容を消すようにした。これで狙い通りの動作となり、iframeを一個にすることができた。FireFoxでも動作を確認している。