DOMを利用して追加したエレメントのエラーチェック

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



0   名前: まさこ : 2007/06/26(火) 09:05  ID:q9zQZlGn sub-Cl
初めて質問します。まさこです。

OracleDB+ASP(.netではない。)+IE6のローカル環境のみで開発&テストをしています。
どうしてもうまくいかないので教えて下さい。(DOM初心者ですが、Web+DB開発は経験があります。)

ブラウザで入力したデータをAPサーバを介してDBに登録したいのですが、
その前にエラーチェックをしたいのでJavaScriptでチェックします。
ですが、もともと表示されているデータのチェックはしてくれるのですが、
DOMを使って追加したデータはチェックしてくれないんです。
ソースで言うと、『アノマロカリス』を『アノマロカリス'』にするとチェックにひっかかりますが、
追加ボタンを押してコードが『103』の名称を『'』にしてもチェックに引っかかりません。

何故だか全く分かりません。
誰か教えて下さいませんでしょうか。
宜しくお願いします。

以下ソースです。(TEST用に短く&簡素にしていますが、余計な部分も多少あります。すいません。)
==========================
<html>
<head>
<title>TEST</title>
<script language="JavaScript">
<!--
function chk_kinsoku(str){
//禁則文字チェック
if ((str != "") && (str.match("'"))){
return false;
}
}

function funcCheck(){
for (i=0;i<document.form2.i_theme.length;i++){
if (chk_kinsoku(document.form2.i_theme[i].value) == false){
alert("名称に「'」は入力できません。")
document.form2.i_theme[i].focus();
return false;
}
}
return false; //わざと
}

function add(){
var opt1 = new Array();
table = document.getElementById('AddArea');
row = table.insertRow(table.rows.length);
cell0 = row.insertCell(-1);
cell1 = row.insertCell(-1);

d = table.rows.length - 1;
num = d + 100;
cell0.appendChild(document.createTextNode(num));
cell1_ny = document.form2.appendChild(document.createElement('input'));
cell1.appendChild(cell1_ny);
cell1_ny.type = 'text';
cell1_ny.name = 'i_theme';
cell1_ny.size = '20';
cell2_ny = document.createElement('input');
cell2_ny.type = 'hidden';
cell2_ny.name = 'i_themeC';
cell2_ny.value = num;
document.form2.appendChild(cell2_ny);
}

-->
</script>
</head>

<body bgColor="ffffcc">
<basefont size='2'>

<table border='0' width='100%'>
<tr>
<td width='10%' valign='top'><br></td>
<td width='80%' align='center'>
<h2><font color='#006633'>登録・変更画面</font></h2>
</td>
<td width='10%' valign='top'><br></td>
</tr>
</table>

<center>

<table border='0' width='100%'>
<tr>
<td width='97%' align='center'>
<form name='form2' action='action.asp' method='post'>

<table border='1' cellpadding='2' cellspacing='0' width='100%' id='AddArea'>
<tr bgcolor='#ffcc33'>
<th>コード</th>
<th>名称</th>
</tr>
<tr>
<td>101</td>
<td>
<input type='hidden' value='101' name='i_themeC'>
<input type='text' value='アノマロカリス' size='20' name='i_theme'>
</td>
</tr>
<tr>
<td>102</td>
<td>
<input type='hidden' value='102' name='i_themeC'>
<input type='text' value='オパビニア' size='20' name='i_theme'>
</td>
</tr>
</table>

</td>
<td width='3%' valign='bottom'>
<input type='button' value='追加' onClick='add()'>
</td>
</tr>
</table>

<br>

<input type='submit' value='更新' onClick='return funcCheck()'>
</form>
</center>

</body>
</html>




社内のイントラ環境で使用する予定なので、他のブラウザでのテストは必要ありません。

1   名前: 匿名 : 2007/06/26(火) 09:05  ID:epW2eUw6 sub-8t
function funcCheck(){
    for (i = 0; i < document.getElementsByTagName('input').length; i++) {
        if (document.form2.getElementsByTagName('input')[i].name != 'i_theme') continue;
        if (chk_kinsoku(document.getElementsByTagName('input')[i].value) == false) {
            alert("名称に「'」は入力できません。");
            document.getElementsByTagName('input')[i].focus();
            return false;
        }
    }
    return false; //わざと
}

2   名前: 匿名 : 2007/06/26(火) 09:05  ID:ey/iH1GD sub-Cz
IE は createElement('input') した要素の name 属性を変更することができない。

ではどうすれば良いかと言うと、MSDN にちゃんと書かれている。
var inputElement = document.createElement ('<input type="text" name="i_theme" size="20">');

ここ笑う(しかない)所ね。ブラウザ分けするのが面倒だが、IE6 のみの環境なら大丈夫だろう。



蛇足。

(1). JavaScript では、たとえ関数内であっても、(var|let) 宣言せずに初期化した変数はグローバル変数になります。for ループの i がグローバルスコープなんてのは結構シャレにならないので注意。

(2). 覚えるなら document.forms['フォーム id'].elements['コントロール name'] で。古い省略形は百害あって一利なし。

(3). onclick="return funcCheck(this.form)" のように this.form を渡せば、そのコントロールが属する HTMLFormElement を参照できるので、document.forms を使う必要すらありません。毎回毎回 document から辿るのは無駄だし時間もかかる。

>>1
(4). getElementsByTagName を無駄に実行しすぎ。NodeList は「生きている」のだから、一度 getElementsByTagName('input') すれば十分。また、IE の NodeList は遅いので、(メモリリークさせない範囲で)可能な限り値・参照を保持した方が圧倒的に速い。

3   名前: 匿名 : 2007/06/26(火) 09:05  ID:ey/iH1GD sub-Cz
>>2
> (4). getElementsByTagName を無駄に実行しすぎ。

ごめんなさい、私が >>1 の意図を理解していなかった。

・IE は、createElement('input') してから name プロパティを変更しても、elements、getElementsByName() からは認識されない。最初に生成したときの name 属性値で識別される。
・ただし name 属性の文字列自体は変更されているので、getElementsByTagName('input') してから name 属性を見れば識別は可能。

ということですよねたぶん。失礼しました。
function funcCheck (form){
    var inputs = form.getElementsByTagName ('input');
    for (var i = 0, I = inputs.length; i < I; i++) {
        if (inputs[i].name != 'i_theme') continue;
        if (! chk_kinsoku(inputs[i].value)) {
            alert ("名称に「'」は入力できません。");
            inputs[i].focus();
            return false;
        }
    }
//  return false;
}

ついでに。

>>0
送信するつもりがあるのなら、チェックボックスとラジオボタン以外のコントロールが、同一の name 属性値を持つというのは普通考えられませんが、大丈夫なんでしょうか。

4   名前: まさこ : 2007/06/26(火) 09:05  ID:q9zQZlGn sub-Cl
おはようございます。

返信の数々、ありがとうございます。

>>2
> IE は createElement('input') した要素の name 属性を変更することができない。
>
> ではどうすれば良いかと言うと、MSDN にちゃんと書かれている。

そうなんですか〜!?すいません。
まず確認しなきゃいけないところですね。MSDN。
でもまさかそんな風に書かなきゃいけないなんて・・・。

あと、注意書きは大変参考になりました。
今までのコードも見直します。
ずっと一人でコーディングしているのでこういうご指摘はとてもありがたいです。

>>3
書いて下さったコードもテストで、動く事が確認できました。
ありがとうございました。

> 送信するつもりがあるのなら、チェックボックスとラジオボタン以外のコントロールが、同一の name 属性値を持つというのは普通考えられませんが、大丈夫なんでしょうか。

実際は、DB+ASPという環境なんです。
で、POSTで送った先のASPでテキストボックスの値を配列に入れなおしています。
普通のコーディングではないんでしょうか?
私以外の開発者が近くにいないので、どういうコーディングが普通なのか分からないんです。。



会社で、ここの掲示板を参照する事は出来るんですが、書き込みはできないので
実際どうコーディングしたかは、夕方また書き込みます。

とりあえず、お礼まで。ありがとうございました。

5   名前: NullPo : 2007/06/26(火) 09:05  ID:Z0FHbpib sub-ii
>>3
>送信するつもりがあるのなら、チェックボックスとラジオボタン以外のコントロールが、同一の name 属性値を持つというのは普通考えられませんが、大丈夫なんでしょうか。
ASPだと、同じname属性を持つ値は、
Request.Form("name").Count
Request.Form("name").Item(number)
で取得できるのですが、私はこれ以外の方法を知りません。
参考のために、他にどういった取得方法があるかご教授願えませんか。

6   名前: 匿名 : 2007/06/26(火) 09:05  ID:q9zQZlGn sub-Cl
こんばんは。

さっそく、>>2の方がおっしゃっているMSDNを確認してみました。
多分コレかと思います。
英語苦手ながら、目は通しました。。
http://msdn2.microsoft.com/en-us/library/ms536389.aspx

という訳で、
var inputElement = document.createElement ('<input type="text" name="i_theme" size="20">');
全部↑みたいに書き直して、正常に動作する事を確認しました。
本当に助かりました。
皆さん、ありがとうございました。


>>5
また余談ですが、ASPでPOSTで受け取る時に、私は、
For Each item In Request.Form("i_theme")
 ar[i] = item
 i = i + 1
Next
こんな感じで配列に格納していますよ。
JavaScriptの掲示板なのに、すいませんでした〜。

7   名前: まさこ : 2007/06/26(火) 09:05  ID:q9zQZlGn sub-Cl
すいません。名前を書き忘れました。
>>6は質問主のまさこです。

失礼しました。

8   名前: 匿名 : 2007/06/26(火) 09:05  ID:3p2QJGXn sub-uG
>>4
> > チェックボックスとラジオボタン以外のコントロールが、同一の name 属性値を持つというのは

ごめんなさい、余計なこと言った。これはフォームデザインの問題だから、今回の件とは関係ないや。大変失礼しました。

>>5
ASP はよう知らんのですが、標準入力からクエリ文字列 'name=value1&name=value2&name=value3' を取れるなら、最悪自前でパースすれば何とかなるかと。

# 余談だが、Web Forms 2.0(§7.1)で「HTMLFormElement.コントロール名」が再定義されていること、同一のコントロール名が複数あればそれが NodeList になると定義されていることを、恥ずかしながら今さら知った。何だかなあ。

9   名前: NullPo : 2007/06/26(火) 09:05  ID:Z0FHbpib sub-ii
>>6
ご丁寧にありがとうございます。
for eachもいいですね。

>>8
クエリ文字列は取得できるけど、どうも文字コードがクライアントの実装依存な感じ。あるいはasciiか。
ともかく文字コードの変換がめんどうくさくてやってられなかった。
name属性を重複無しにするなら、後ろに数値をくっつけて順番に回すのかな。
返信ありがとです。

一覧へ戻る