プロが教えるわが家の防犯対策術!

JavaScriptを勉強し始めたばかりの者です。

submitボタンがonClickされたときにcheckという関数を呼び出しているのですが、
フォーム名とJavaScriptの関数名を同じものにすると、その関数が呼び出されなくなっているようなのです。

------------------ form.html -----------------------------------------------------
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=euc-jp">
<script type="text/javascript" src="test.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<title>フォーム</title>
</head>
<body class="blue" marginwidth="100" topmargin="40" bottommargin="80">
<form name="check" method="post" action="form2.cgi">
<table border="1" cellpadding="7">
<caption>フォーム</caption>
<tr>
<td>※ID</td>
<td><input type="text" name="id"></td>
<td>テキストボックス</td>
</tr>
</table>
<br>
<input type="submit" name="send" value="送信" onClick="check()">
<input type="reset" name="clear" value="リセット"></td>
</form>
</body>
</html>

------------------ test.js -------------------------------------------------------
<!--
function check()
{
if( document.check.id.value == "" ){
alert( "※のついている項目は入力必須項目です!" );
}
return;
}
-->
-------------------------------------------------------------------------------

上記のソースで、テキストボックスに何も入力せずに送信ボタンを押してもalertは表示されませんが、
フォーム名あるいは関数名のどちらかをcheck1やcheck_1にすると表示されるようになります。
フォーム名と関数名を同じものにするとalertは表示されません。

フォーム名と関数名の関係はこのようなものなのでしょうか?
また上記のソースに原因があるようでしたらお教えください。

A 回答 (8件)

#3です。



>HTMLのフォーム名とJavaScriptの関数名が同じではいけない
#5でわかりやすい解説があるのでその通りで。
JavascriptではHTMの要素や属性、関数、変数その他諸々を全て「オブジェクト」として持っています。なので同じ名前のモノが存在するときに省略表記すると思った動作をしなくなります。

なお、#4さんのおっしゃる通り、getElementsByTagNameやgetElementByIdの利用を勧めるべきでした。
>JScript対応ブラウザ~では動かない
document.forms等のいわゆるコレクションの出現経緯などはわかりませんが、古くから存在するのでブラウザが互換性を捨てない限り利用できるし、動いてしまうんですけど。
(Jscript以前にNetscape2あたりが勝手に作って他が対応している??)
    • good
    • 0
この回答へのお礼

>JavascriptではHTMの要素や属性、関数、変数その他諸々を全て「オブジェクト」として持っています。

この一文でピンときました。

・JavaScriptがフォーム内容を受け取るとき、それはJavaScriptのオブジェクトとして扱われるから、関数名と同じnameを指定するとJavaScriptが混乱してしまう。
・できるだけその環境に応じた正式な形で記述することでその混乱は解消される。

という理解で大丈夫だと思うのですが…。
感覚的に、JavaScriptはフォーム内容を「参照」することで値をとっていると思っていたみたいです。
というか書いたソースが省略表記であることすら知らなくて…もっと学習しなくちゃいけませんね(汗)。

HTMLのバージョンやJavaScriptの種類、ブラウザなどによって様々なところで微妙に書き方を変えなければいけないこと。
このことは何となく分かっていましたが、改めて思い知らされた感じです。
「仕事でwebをやっている人はどうやって折り合いをつけているのだろう」と疑問と感心でいっぱいです。

他の皆さんの書き込みも勉強になります。分からない部分もあるので、自分で調べてみようと思います。
本当にありがとうございました。

お礼日時:2009/03/26 11:07

あまり難しい事を言っても質問者さんに理解してもらえないと意味がないので、簡単に。

。。

仕様です。
同じ名前は使ってはダメです。
    • good
    • 0

ブラウザ上における HTML のイベント属性内のスコープチェーンは通常とは異なります。

下記の場合、

・<input onsubmit="check();">

スクリプトエンジンは以下の順序で check を探し、最初に見つかったものを返します(HTML5: 5.5.6.1)。

(1). onsubmit 属性内の局所変数(var check)。
(2). input 要素の check プロパティ(this.check)
(3). form 要素の check プロパティ(this.form.check)
(4). document の check プロパティ(this.form.ownerDocument.check)
(5). window の check プロパティ(this.form.ownerDocument.defaultView.check)

ここでややこしいのは、HTML の name 属性、id 属性などで名前を付けられた要素が、オブジェクトのプロパティとして「勝手に」露出することがあることです。

・DOM1-HTML における正式な形は document.forms.namedItem('check').elements.namedItem('send') ですが、
・ECMAScript では document.forms['check'].elements['send'] と省略することが許されています(DOM2-HTML: D)。
・さらに、JavaScript 1.0 からの伝統で document['check']['send'] のように書くこともでき(HTML5: 4.10.1)、
・これは ECMAScript 的に document.check.send と等価です(ECMA262: 11.2.1)。
・その上、IE は伝統的に名前を持つ要素を window.id のようにグローバル参照でき、
・それ以外にも非常にややこしいスコープ規則を持っています(参考 URL)。

そういうわけで、私は <input name="input.name"> のようにプロパティとして露出できないような名前を付けておき(よく誤解されていますが、input 要素の name 属性値は CDATA ですから、原則としてどんな文字でも使用できます)、elements['input.name'] を一貫して用いるようにしています。気休め程度ですし、できの悪い IDE なんかでは通用しませんが。

※なお、IE6 は form 要素に id 属性を付けても document.id の省略形では拾えません。window.id か document.forms['id'] ならば拾えます。いずれにせよ、HTML4 の form 要素には互換性のために name 属性と id 属性を並記することが望ましい(HTML4: 17.3)。XHTML1 では form 要素の name 属性は非推奨です(XHTML1: 4.10)。未だに使う人が後を絶たないので HTML5 では復活します(HTML5: 4.10.1)が、使用を控えることをお勧めします。
※コア言語としての ECMAScript・JScript と、ホストオブジェクトは区別して下さい。

参考URL:http://msdn2.microsoft.com/en-us/library/ms53302 …
    • good
    • 0

同じ名称を使うとこういうことが起きるのよ。



山に住んでいるcheckさんと
里に住んでいるcheckさんがいるの。

役場で名前を呼ばれるのよ。
checkさーんって。

どっちを呼んでいるか判らないでしょ?

本来なら
○○に住んでいるcheckさん
と呼ばないといけないんだけど
それは長いから
checkさん
と呼ぶだけでブラウザが勝手に解釈してくれるんだけど
○○に住んでいるcheckさん
が2つ以上あるとブラウザがどっちを呼んでいいのかわからないから
発生してしまう現象なのよ。
    • good
    • 0

同じ名前はダメです、、、というとほかの方の意見と同じになるので割愛するとして。



> 規則というか、それは仕様的なものとしてそうなっているのでしょうか?
HTMLやJavaScriptではなく、JScript(いわゆるIE専用)の仕様です。

もともとのJavaScriptはHTMLドキュメントを操作するために作られた言語ですので、
簡単に要素を示す事ができるように、nameを書くだけでdocument.checkと指定できるようになっています。

JScriptはこれを拡張し、document.all.checkやwindow.checkでもアクセスできるようになっています。

そしてJavaScriptの仕様として、window.checkとグローバル変数のcheckは同じものです。

現在はJScriptがさらに拡張され、<div id="check">にもdocument.all.checkやwindow.checkでアクセスできます。

No.3でwindow.checkとdocument.forms['check']を使い分ければよいと書かれていますが、
JScript対応ブラウザ(IE、Safari3.2以上(3.0以上?)、Opera9.5以上など)では動かないと思います。


ちなみにECMAScriptはdocument.forms['']というものはありませんので
DOMのdocument.getElementsByTagName('form')、
上記のはdocument.getElementById('check')を使う事になります。


この問題はHTMLだけでなく、他人が作ったライブラリなども影響します。
<script src="utils.js"></script>
などとして、utils.jsの中でfunction check(){}という同じ名前が使われていたら、test.jsのcheck()が使えなくなるかもしれません。
これはルールとして気をつけなければならない事ですね。
    • good
    • 0

関数呼び出しは window.check() 、


フォームの部品は document.forms['check'].elements['id'].value と、
省略せずに表記すればいいです。

ただし、後者はともかく、前者は普通やらないですし、やはり紛らわしい名前は付けるべきではないかと思います。
name="id" みたいなのも同じ、頻繁に出てくる単語を付けているとわかりずらいバグを産みやすいです。

ついでに、フォームの入力チェックをするときは、submitボタンのonclickは使わないで、formのonsubmitを使ったほうがいいです。
onsubmitで呼び出す関数でfalseを返せば(return false;)、submit動作を止められます。

また、通常のテキスト入力フィールドでEnterキーで送信もできるのでonclickでは入力チェックが動かずに送信されてしまうこともあります。


<form method="post" action="form2.cgi" onsubmit="return myformCheck(this)">
formにnameは要らない
onsubmitで入力チェック関数を呼び出す。
 引数thisはformオブジェクト。
 関数の返値がfalseならsubmit中止


test.js ※ 外部ファイル化しているなら前後のHTMLコメント表現(<!-- -->)は不要

function myformCheck(F)
{
if( F.elements['id'].value == "" ){
alert( "※のついている項目は入力必須項目です!" );
return false;
}
return true;
}

この回答への補足

回答ありがとうございます。
「onClick」や外部ファイルのコメントもソースを書きながら引っかかっていたのですが、そういうことだったのですね。
「this」でフォーム内容を渡せるというのも初めて知りました。勉強になります。

ただ、HTMLのフォーム名とJavaScriptの関数名が同じではいけないというのがどうしても不思議なんですが、やはり仕様なのでしょうか?

補足日時:2009/03/25 16:36
    • good
    • 0

そもそもの運用方法がよくない。


formにnameをつけるという時点で今風ではない。
idで管理しましょう。

また、inputのnameに制限はないとはいえ、「id」のような一般的な
予約語を使うのはトラブルの元です。できればやめた方がよいでしょう。
(一応以下のような方法で動きますが・・・)

それとバリデートしたあとに、falseを返さないとそのまま進んじゃい
ますので、フローに注意したほうがよいです

<script>
function check(){
if( document.getElementById("check").elements["id"].value == "" ){
alert( "※のついている項目は入力必須項目です!" );
return false;
}
return true;
}
</script>
<form id="check" method="post" action="form2.cgi">
<p>
<input type="text" name="id">
<input type="submit" name="send" value="送信" onClick="return check()">
<input type="reset" name="clear" value="リセット">
</p>
</form>

この回答への補足

回答ありがとうございます。
JavaScriptに関しては独学で始めたばかりなので、yambejpさんのご指摘は勉強になることが多くて本当にありがたいです。
idはHTMLの予約語なのですね。こちらも久しぶりに触っているので忘れてしまっているようです。

書いてくださったソースコードで私のやりたいことはほとんど説明されているのですが、
それとは別に、なぜ同じ名前では関数が呼び出せないのか気になっているのです。
ご存知であればお教えください。

補足日時:2009/03/25 16:23
    • good
    • 0

その通り。


JavaScriptの関数・変数を含めて
同じnameやidをつけてダメよ。

この回答への補足

回答ありがとうございます。
フォームのidやnameについてはまだよく分かっていないので、
もう少しwebを利用して違いなどを勉強したいと思います。

関数名、変数名、id、nameが重複するものを使用してはいけないというのはわかるのですが、
HTMLのフォーム名とJavaScriptの関数名は関係ないもののように思えたので
同じ名前を使用しても問題ないのではと考えました。
しかしそうではないみたいで…。

規則というか、それは仕様的なものとしてそうなっているのでしょうか?

補足日時:2009/03/25 15:45
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!