はまりどころあれこれ。

JavaScriptを使った仕事をしていた訳ですが、そんな中ではまっちゃった事をあげておきます。JavaScriptを使い慣れている人には常識的なことが有るかも知れませんが、メモ程度ですので受け流すかアドバイスをくれるかしてやってください。

Firefoxの標準エラーコンソールがAjaxイベントハンドラ内のエラーを記録しない

タイトルに全て書いてしまいましたが、firefoxの標準エラーコンソール(ツルール→エラーコンソール)では、prototype.jsAjax.Requestで言うところのonCompleteやonSuccessハンドラ内で起こったエラーを記録してくれません。実際にはエラーでこけているのに見た目ではエラーもなくはまりました。Ajaxで呼び出しているスクリプトを直接叩いたらきちんと返ってくるので気がつきました。
これらのハンドラは事前にしっかりテストしておくのが良いようです。*1

DOMを使って動的に生成したフォームでのファイルアップロード

IE6とfirefox2では出来ませんでした。セキュリティ対策でこういう仕様になっているのだと思いますが。
仕方がないのでインラインフレームに静的な(((サーバサイドでは動的))フォームを読み込んで処理を行うことにしました。iframeのonLoadイベントで更新を検出できるのでiframeの外側にあるファイル一覧を更新することが出来ました。
ほかの方法があるのなら教えてください。

prototype.jsの継承はイマイチ

Object.extendはイマイチです。

IEでテキストボックスの選択範囲が忘れられる。

IE6でテキストボックス内の選択範囲を取得する際、いったん別のフォームコントロールにフォーカスが移ると範囲を取得できなくなることがあるようです。事前に選択範囲をgetBookmarkしておけば回復可能です。

IEでは*.jsファイルが読み込み終わる前にHTML内のスクリプトが実行される事がある

IEでは大きな外部ファイルをscript要素のsrc属性に指定した場合、外部ファイルの読み込みよりも先にインラインのスクリプトが実行されてしまうことがある。したがって、外部ファイルで定義してあるコントロール生成用関数をインラインで呼び出すとエラーになることがある。

// in external.js
function doSomething () {
    // do something creative!
}
<script type="text/javascript" src="external.js"></script>
<script type="text/javascript">
<!--
doSomething();  // "doSomething is not a function" とか言われる
//-->
</script>

回避策は2通り。

1つ目はwindow.onLoadイベントハンドラにやりたいことを登録する。

Event.observe('window', 'load', function (event) {
    doSomething(); // 大丈夫。
});

もうひとつはscript要素のdefer属性を指定する。*2defer属性を指定するとスクリプトの実行が描画の後となる。ただし、内容にdocument.write関数の呼び出しがあってはならない。

<script type="text/javascript" src="external.js"></script>
<script type="text/javascript" defer="defer" >
<!--
doSomething();  // 安心して実行できる。
//-->
</script>

その場所に何かを生成したい場合は、どちらの方法もwriteできないのでDOMを使ってscript要素と置き換えるとかしてやるといい。

*1:当たり前ですね

*2:馬鹿でかいファイルで実際に試したわけではないが・・・