今保守してるサイトの要件が IE5.0/NN4.7 以上での閲覧を保証しないといけないとかで、NN4.78 で動作検証してたんですが、JavaScript が動作しないことが判明。
ちょっと手が空いたので原因を調べたところ、今回の問題は 2 点。
(1) フォーム名等を参照する場合、普通 frmHoge とだけ書けばいいところも document.frmHoge として記述する必要がある
(2) input type="image" では onClick イベントが動作しない。A タグ+IMG タグに置き換えて、A タグの onClick で処理してやる必要がある。
NN4.x なんて Web 黎明期のブラウザだから、今検索しても情報少ないから困った。(1) に関しては言及されているサイトも多いけど、(2) に関しては情報が少なすぎ。
input type=image onClick doesn't work in Netscape - Dev Shed
Input Type = "Image" - JavaScript
このあたりに載ってたけど、確かに
Netscape 4 DOM Reference(Internet Archive)によると onClick の説明に
Event handler for
Button, document, Checkbox, Link, Radio, Reset, Submit
とか書いてある。IE の仕様書と厳密に比較したら面白そうだけど、今度サイトのリニューアルで NN4.7 のサポートが必要なる予定だからやらなくていいか。
で、動かない原因を調べたのはいいけど、結局デザインにも関わる部分だとわかったので、今回は変更を保留。会員向けサイト(みたいなもの)だけどクレームが入ってないってことは、NN4.7 使ってる人いないってことでしょ。
ちょっと前の話。
今やってる案件で、「Web フォームで submit ボタンをダブルクリックしても、2 回 submit されないようにしてください」との要望(実際には不具合呼ばわりされた)がありまして。
先日読んだ
CSSクックブックにもそういうレシピ「5.5 1回限り有効な送信ボタンの設定」があったけど、これは onSubmit 時にボタンに display: none なスタイルを適用する強引な方法。これだとキャンセルボタンとか押されたときにどうしようもなくなるでしょ・・・。
もっとまともな方法がありそうなのでググってみると、やっぱりありました。
onsubmit で disable にするやつ
へー。共通の .js に入れるだけで自動的に使えるようになるわけか。
ということで、お客さんに「1 時間くらいで対応できると思いますよ」と伝えたんだけど、これがまずかった。実際組み込んでみるとちゃんと動作しない。
原因は 2 点。
・<body> で onLoad イベントを指定していた。<script>→<body> の順で記述してたから、イベントが上書きされちゃったみたい。
・submit 動作を行うのが <input type="image"> なボタンだったんだけど、type="image" な要素は form.elements として取得できない。
前者の問題は、とりあえず <body> の onLoad イベントにも DisableSubmit.set(); を追記することで対応。
後者の問題は、this.elements の代わりに document.getElementsByTagName('input') を渡すことで対応、と。
ちなみに、setTimeout(〜, 1) を使っているので通常のダブルクリックには対応できるけど、「クリックと同時に Enter」みたいな意地悪をすると二回 submit されるみたい。まあ、
naoyaのはてなダイアリー - submit ボタン disable 技の罠
の対策だろうし、目的は「ついうっかりダブルクリック」を防ぐことだからこれで十分か。
あと、setTimeout(〜, 1000) だと 1 秒後に復活しちゃうけど onStop で実装したほうがしっかり作れるんじゃ?とか思って調べてみたら onStop って IE 特有のイベントみたいで納得。
(追記)
そういえばもう一点変更してたんでした。
if ((elm.type == 'submit' || elm.type == 'image') && !elm.disabled) {
...
}
・・・でしたっけ?なんかすでに変更していただいているような。
とりあえずこれだと引っかからないものが出てくるので、
if (elm.type.match(/^(submit|image|file|button)$/i)) {
if (!elm.disabled) {
...
}
}
こんな感じに。
正規表現で条件判定するのは Perl 厨の悪い癖かもしれないけど、こっちのほうが楽に拡張できるから好きだったり。