ここまで大まかにフォームを作りましたが、実際に使ってみるとエラーが発生したり、使いにくい部分が出て来ます。
わざと間違った操作をしてみたり、何度も繰り返しテストをする中で問題点を発見します。
実例(p7-6.html)
個数のデータを入力後、削除して空にすると合計金額に「NaN円」と表示されます。「NaN」は計算できないという意味のエラーで、文字を数値にしようとしたときに発生します。
エラーがでる原因はユーザー関数calc_number()の中にあります。ここでは確認だけで作業はしません。
function calc_number(s) {
var t;
t = document.getElementById(s).value;
if (t.match(/[^0-9]/g)) {
alert("半角数字だけを入力してください。");
document.getElementById(s).value = "";
} else {
snumber[s] = eval(t);
calc_price();
}
//注文確認を空欄にする
document.order.order_text.value = "";
}
関数eval()は文字列を数値に変換します。変数tは個数のデータですので、計算用に数値化しています。
JavaScriptでは、文字列のままでも計算は可能です。eval()がないと空欄の場合、計算式では0と同じ扱いとなります。
このエラーを解決するには変数tが空欄の場合、0であることをハッキリと明示します。
} else { if (t == "") t = "0";
snumber[s] = eval(t);
calc_price();
}
if文で判定して強制的に「0」とします。
しかし、これは別の方法でも解決させることができます。また、その方が利便性も向上します。
個数の入力を手入力ではなく、<select>を使ってプルダウンメニューにしてしまいましょう。
フォームにある個数の<input>タグを<select>タグに作り替えます。
0~10個まで個数を選べるようにしましょう。
<tr>
<td>S001</td>
<td><a href="s001.html" class="t_name" target="_blank">サクラソフトクリーム</a></td>
<td><input type="text" class="price" id="s001" value="200" size="10" maxlength="5" onChange="reprice(this.id)"></td>
<td><select class="number" onChange="calc_number(this.id)"> <option>-<option>1<option>2<option>3<option>4<option>5<option>6<option>7<option>8<option>9<option>10 </select></td>
</tr>
<tr>
<td>S002</td>
<td><a href="s002.html" class="t_name" target="_blank">さくらかき氷</a></td>
<td><input type="text" class="price" id="s002" value="350" size="10" maxlength="5" onChange="reprice(this.id)"></td>
<td><select class="number" onChange="calc_number(this.id)"> <option>-<option>1<option>2<option>3<option>4<option>5<option>6<option>7<option>8<option>9<option>10 </select></td>
</tr>
<tr>
<td>W001</td>
<td><a href="w001.html" class="t_name" target="_blank">あんこぼたもち</a></td>
<td><input type="text" class="price" id="w001" value="180" size="10" maxlength="5" onChange="reprice(this.id)"></td>
<td><select class="number" onChange="calc_number(this.id)"> <option>-<option>1<option>2<option>3<option>4<option>5<option>6<option>7<option>8<option>9<option>10 </select></td>
</tr>
<option>タグについては、終了タグを省略しています。
クラス名とイベント処理はそのまま引き継いでいます。
個数に「0」を使わず「-」を使っているのは、数字でないことをハッキリと認識できるようにするためです。「0」だと「6」や「8」と見分けるのにしっかりと確認が必要になりますが、「-」だと全体を見渡しただけで数字が入っていないことが分かります。
このままでは個数を「-」に戻したときにエラーが発生します。これは、個数に半角数字のみ入力されるように制限を付けたからです。
プルダウンメニューにしたため、入力のミスはなくなりますので、このチェック機能も不要になります。
function calc_number(s) {
var t;
t = document.getElementById(s).value;
if (t.match(/[^0-9]/g)) {
alert("半角数字だけを入力してください。");
document.getElementById(s).value = "";
} else {
if (t == "-") snumber[s] = 0;
else snumber[s] = eval(t);
calc_price();
}
//注文確認を空欄にする
document.order.order_text.value = "";
}
念のため、eval()でのエラーが発生しないようにif文で個数が「-」の場合は配列変数snumberに「0」を入れておきます。
<option>タグを10個くらいなら手作業でも作れますが、これを100個作るとなると面倒でソースも見にくくなります。また、それらを全商品に修正しなければなりません。
そこで、この作業をすべてスクリプトに任せるようにすると変更も容易ですし、データベースと連動して在庫数を上限にすることも可能になります。
実例(p7-6-2.html)
今回は余裕を持って、一律に100個まで入力できるようにしてみましょう。
まずは、不要になる<option>タグを全て削除します。
<tr>
<td>S001</td>
<td><a href="s001.html" class="t_name" target="_blank">サクラソフトクリーム</a></td>
<td><input type="text" class="price" id="s001" value="200" size="10" maxlength="5" onChange="reprice(this.id)"></td>
<td><select class="number" onChange="calc_number(this.id)"> <option>-<option>1<option>2<option>3<option>4<option>5<option>6<option>7<option>8<option>9<option>10 </select></td>
</tr>
<tr>
<td>S002</td>
<td><a href="s002.html" class="t_name" target="_blank">さくらかき氷</a></td>
<td><input type="text" class="price" id="s002" value="350" size="10" maxlength="5" onChange="reprice(this.id)"></td>
<td><select class="number" onChange="calc_number(this.id)"> <option>-<option>1<option>2<option>3<option>4<option>5<option>6<option>7<option>8<option>9<option>10 </select></td>
</tr>
<tr>
<td>W001</td>
<td><a href="w001.html" class="t_name" target="_blank">あんこぼたもち</a></td>
<td><input type="text" class="price" id="w001" value="180" size="10" maxlength="5" onChange="reprice(this.id)"></td>
<td><select class="number" onChange="calc_number(this.id)"> <option>-<option>1<option>2<option>3<option>4<option>5<option>6<option>7<option>8<option>9<option>10 </select></td>
</tr>
次にスクリプトの初期設定で、<select>タグに対して<option>タグを追加します。
下記の赤い部分を追加します。
//メニューの最大値
menu_max = 100;
(省略) //個数にIDを割り当てる
obj = document.getElementsByClassName("number");
for(n=0;n<obj.length;n++) {
obj[n].id = sid[n] + "n";
//option追加
obj[n].length = menu_max + 1;
obj[n][0].text = "-";
for(var m=1;m<=menu_max;m++) {
obj[n][m].text = m;
}
}
まず、初期値として変数menu_maxを準備します。これが商品個数の上限となります。
ここを変更するだけで<option>タグの数が全商品で変わります。
次に<select>タグはnumber(クラス)で呼び出して変数objで処理していますので、ここで同時に<option>タグの設定も行います。
「obj[n].length」に必要なメニューの個数を代入すると、<option>タグがその数用意されます。この時点ではまだ表示は空です。ここでの代入値は変数menu_maxに「+1」をして、101個のメニューを追加し、0~100に対応させます。
次の「obj[n][0].text」は、追加したメニューの1番目(要素番号は0)に「0」の代わりに「-」を表示させます。
for文では、2番目の<option>タグから101番目までに1~100の数字を入れて行きます。
ここではfor文が二重になっていますので、それぞれ別の変数を使っています。変数nで外のループ、変数mが内のループで、外が1回ループする間に内は100回ループします。
これで、メール送信フォームは完成とします。