Opera で onChangeが利かない

[新着] Webテンプレートを仮オープンしました



0   名前: RIO : 2006/10/16(月) 12:01  ID:QPvimfmS
計算をするJavacriptを作っています。XP(SP2)環境です。

IE,Firefoxは大丈夫なのですが、Opera(9.02)の動作がおかしいのです。
以下は、私が作っているものではありませんが、他で紹介されていた
基本的なスクリプト例です。

<HTML>
<HEAD>
<TITLE></TITLE>
<SCRIPT language="JavaScript">
<!--
// テキスト領域の合計を計算
function ttlValue() {
txt = 6; // テキスト領域の総数
ttl = 0;
for(i=0; i<txt; i++) {
if(document.nForm.elements[i].value != "") {
ttl += eval(document.nForm.elements[i].value);
}
}
document.nForm.result.value = ttl;
}

//-->
</SCRIPT>
</HEAD>
<BODY bgcolor="#ffffff">
<FORM name="nForm">
数値を入力してください。合計値を表示します。<BR>
<INPUT type="text" name="t1" onChange="ttlValue()"><BR>
<INPUT type="text" name="t2" onChange="ttlValue()"><BR>
<INPUT type="text" name="t3" onChange="ttlValue()"><BR>
<INPUT type="text" name="t4" onChange="ttlValue()"><BR>
<INPUT type="text" name="t5" onChange="ttlValue()"><BR>
<INPUT type="text" name="t6" onChange="ttlValue()"><BR>

<BR>
合計<INPUT type="text" name="result" size="10">
</FORM>
</BODY>
</HTML>

数値を入力して、クリックすると入力した数値も消えてしまい、
URLの後ろにjavascriptの項目が出てきます。

どのようにすれば、きちんと動作するのかご教示いただきたく、
どなたか宜しくお願いします。

1   名前: miz : 2006/10/16(月) 12:01  ID:87gt8cMr
operaは、以下のmetaタグがないと、各種タグ内のイベント属性値を解釈しないようです。
<meta http-equiv="Content-Script-Type" content="text/javascript">

他にも、そういうブラウザは存在しますので、省略しないようにしましょう。

2   名前: 匿名 : 2006/10/16(月) 12:01  ID:L0mFLTIe
HTTPヘッダでContent-Script-Type: text/javascriptを送出してもいい。

HTML 4.0の仕様書によれば、デフォルトのスクリプト言語を指定せずに組み込みイベントを使用した文書は不正であるから
ブラウザはスクリプトの解釈を中断してよい。だからOperaの動作は妥当。

他にもいろんな意味で、>>0のサンプルは参考にしないよう忠告しておく。

3   名前: RIO : 2006/10/16(月) 12:01  ID:/MCzeMr0
早速のコメントありがとうございます。
しかしながら、
<meta http-equiv="Content-Script-Type" content="text/javascript">
を書いても書かなくても、動作は一緒です。
さらに分かったことです。
数字を入力して、カーソルを次の欄に移行すると、きちんと作動します。
数字を入力後、クリックすると入力した数字が全て消えます。
IE,Firefoxとも、クリックしても数字は残っています。
計算するタイミングは異なるようですが。

宜しくお願いします。

4   名前: 匿名 : 2006/10/16(月) 12:01  ID:K326bbkp
ごめん、>>2を言う前に試すべきだった。
とりあえず、当方のOpera 9.0/Macでは現象を確認できない。

で、>>2でごちゃごちゃ言った手前修正しておく。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<title>Sample</title>
<script type="text/javascript">

function ttlValue(form) {
	var elm = form.elements;
	var ttl = 0;
	for (var i = 1; i <= 6; i++) {
		var input = elm['t' + i];
		if (input.value != '') {
			if (isNaN(input.value)) {
				input.value += ' (invalid value)'
			} else {
				ttl += parseFloat(input.value);
			}
		}
	}
	elm['result'].value = ttl;
}

</script>
<form action="#">
<p>数値を入力してください。合計値を表示します。
<ul>
<li><input type="text" name="t1" onchange="ttlValue(this.form)">
<li><input type="text" name="t2" onchange="ttlValue(this.form)">
<li><input type="text" name="t3" onchange="ttlValue(this.form)">
<li><input type="text" name="t4" onchange="ttlValue(this.form)">
<li><input type="text" name="t5" onchange="ttlValue(this.form)">
<li><input type="text" name="t6" onchange="ttlValue(this.form)">
</ul>
<p>合計<input type="text" name="result" size="10">
</form>


まぁこれも全然よくないのだけど、少なくとも>>0のサンプルに関する限り、
今どきscript要素にlanguage属性が必要なケースなどほとんど皆無だし、
form要素にname属性を付ける必要などJavaScript1.1の時代から既に無いのだし、
変数はvar宣言しておくべきだし、evalなんてそうそう使う関数ではないし
とにかく、真似してはいけないことのオンパレードだ。

5   名前: RIO : 2006/10/16(月) 12:01  ID:lfl5Ybr9
訂正ありがとうございます。
最初のスクリプトは、とあるところのほとんどまんまコピーです。
と言っても、私がそれ以上のスクリプトを書けるわけではないのですが。

申し訳ありません、馬鹿やってました。

>数字を入力して、カーソルを次の欄に移行すると、きちんと作動します。
>数字を入力後、クリックすると入力した数字が全て消えます。

は、間違いです。正しくは、

数字を入力して、カーソルを次の欄に移行すると、きちんと作動します。
数字を入力後、エンターキーを押すと入力した数字が全て消えます。

やっと自分自身でわかったことは、エンターキーがsubmitになっていることですね。
それが、
Firefox では、計算をする、
IE6では、計算しないが、入力データを保持して、他の項目に移ったときに計算する、
Opera9は、入力データをクリアーしてしまう、
という違いになっているようです。

仕様を読むと、input項目におけるonChangeは、
項目からカーソルが出たときに機能するようですから、IE6が正しいのかな?

いずれにせよ、Opera9でデータがクリアーされない方法があれば、教えていただきたく、
宜しくお願いします。

6   名前: RIO : 2006/10/16(月) 12:01  ID:lfl5Ybr9
わかりました。

<form action="#" onSubmit="return(false);">

で、エンターキーがsubmitになるのを抑止できました。

お世話になりました。
ありがとうございます。

7   名前: 匿名 : 2006/10/16(月) 12:01  ID:L0mFLTIe
> エンターキーがsubmitになっていることですね。

ああ、そういうことだったのね。
submitボタンが無いときに、リターンキーで次の項目に移るのはIEとFirefoxくらいだったはず。
Opera、Safariはリターンキーでsubmitと見なす。
これは実装次第だから、どの動作が正しいとは判断できない。

あと>>4の訂正。

> form要素にname属性を付ける必要などJavaScript1.1の時代から既に無いのだし、
JavaScript 1.0からの間違い。

> 変数はvar宣言しておくべきだし
補足しておくと、var宣言しないと大域変数になる。
>>0はiが大域変数だから、万が一ループ中に呼んだ関数内にもiループがあったら悲惨な目に遭う。

> evalなんてそうそう使う関数ではないし
補足しておくと、>>0は任意のコードを実行できる脆弱性がある。
まぁ、危険度はbookmarkletと大差ないけど、フォームデータのチェックとしては致命的。

一覧へ戻る