システムを利用する人と作った人が同じなら、エラーが出るような操作を避けることもできますが、通常は入力されたデータをチェックします。
【1】「sample010.js」を以下のように更新してください。コピーして貼り付けてもかまいません。
var database;
var txtPrefCd;
var txtPrefName;
onload = init;
onunload = dbClose;
function init() {
//初期設定をする関数
txtPrefCd = document.getElementById("txtPrefCd");
txtPrefName = document.getElementById("txtPrefName");
txtPrefCd.onblur = function (){blur(this);}
txtPrefCd.onfocus = function (){focus(this);}
txtPrefName.onblur = function (){blur(this);}
txtPrefName.onfocus = function (){focus(this);}
document.getElementById("btnInsert").onclick = function (){dataInsert();}
document.getElementById("btnUpdate").onclick = function (){dataUpdate();}
document.getElementById("btnDelete").onclick = function (){dataDelete();}
dbConnect();
dataDisplay();
}
function dbConnect() {
//データベースに接続する関数
database = new ActiveXObject("ADODB.Connection");
database.Open("Driver={Microsoft Access Driver (*.mdb)}; DBQ=c:\\SampleDB010.mdb;");
alert("データベースに接続しました。");
}
function dbClose() {
//データベースを切断する関数
database.Close();
database = null;
alert("データベースを切断しました。");
}
function focus(obj){
obj.style.backgroundColor = "#ffff00";
}
function blur(obj){
obj.style.backgroundColor = "#ffffff";
}
function dataDisplay() {
//データを表示する関数
var mySql = "select * from T01Prefecture order by PREF_CD";
var recordSet = database.Execute(mySql);
var tempText = "";
document.getElementById("dataDisplay").value = "";
while (!recordSet.EOF){
tempText = tempText + recordSet(0) + ":" + recordSet(1) + "\n";
recordSet.MoveNext();
}
document.getElementById("dataDisplay").value = tempText;
recordSet.Close();
recordSet = null;
}
function dataInsert() {
//データを追加する関数
if(dataCheck(txtPrefCd,"PREF_CD") && dataCheck(txtPrefName,"PREF_NAME")){
var mySql = "insert into T01Prefecture values(" + Number(txtPrefCd.value) + ",'" + txtPrefName.value + "')";
sqlDisplay(mySql);
database.Execute(mySql);
dataDisplay();
alert("追加しました。");
}
}
function dataUpdate() {
//データを更新する関数
if(dataCheck(txtPrefCd,"PREF_CD") && dataCheck(txtPrefName,"PREF_NAME")){
var mySql = "update T01Prefecture set PREF_NAME ='" + txtPrefName.value + "' where PREF_CD = " + Number(txtPrefCd.value);
sqlDisplay(mySql);
database.Execute(mySql);
dataDisplay();
alert("更新しました。");
}
}
function dataDelete() {
//データを削除する関数
if(dataCheck(txtPrefCd,"PREF_CD")){
var mySql = "delete from T01Prefecture where PREF_CD = " + Number(txtPrefCd.value);
sqlDisplay(mySql);
database.Execute(mySql);
dataDisplay();
alert("削除しました。");
}
}
function sqlDisplay(_mySql) {
//SQLを表示する関数
document.getElementById("sqlDisplay").innerHTML = "<p>" + _mySql + "</p>";
}
function dataCheck(obj,myStr){
//データをチェックする関数
if (obj.value == "") {
alert(myStr + "は必ず入力してください。");
return false;
}else{
return true;
}
}
【2】保存したら sample010.html をダブルクリックしてWebブラウザで開きます。
★sample010.htmlとsample010.jsは必ず同じフォルダ内に置いてください。
【3】まずテキストボックスは未入力のまま、「追加」ボタンをクリックしてみます。
【4】「PREF_CDは必ず入力してください。」というメッセージが表示されました。「OK」をクリックします。
【5】今度はPREF_CDに「99」と入力し、「追加」ボタンをクリックします。
【6】「PREF_NAMEは必ず入力してください。」というメッセージが表示されました。「OK」をクリックします。
【7】PREF_CDに「99」、PREF_NAMEに「ハワイ」と入力し、「追加」ボタンをクリックします。
【8】未入力がない場合はちゃんと追加されました。
【9】更新や削除の場合でも未入力がある時には、メッセージが表示されることを確認してください。削除の場合はPREF_CDの未入力だけチェックしています。
【解説】
まず、プログラムの先頭で新しく変数を宣言しています。この変数は複数の関数内で共通して使いますので、関数の外で宣言する必要があります。
var txtPrefCd;
var txtPrefName;
次に関数init()の中で2行追加しました。テキストボックスをそれぞれの変数で扱えるようにしています。
txtPrefCd = document.getElementById("txtPrefCd");
txtPrefName = document.getElementById("txtPrefName");
細かいことを言うとinit()はonloadのイベントで呼び出している関数です。onloadはブラウザ上のコントロール(入力部品)がすべて読み込まれた後に起こります。プログラムで操作する時はコントロールが読み込まれた後でなくてはなりませんので、init()の中に書いているわけです。
せっかくテキストボックスが変数で扱えるようになったので、イベント設定の書き方を変えてみました。前より少しシンプルになりましたね。
txtPrefCd.onblur = function (){blur(this);}
txtPrefCd.onfocus = function (){focus(this);}
txtPrefName.onblur = function (){blur(this);}
txtPrefName.onfocus = function (){focus(this);}
ここから先の説明は少し難しいですが、何度も読み返して関数の使い方のコツをつかんでください。理解できればきっと実力がアップしますよ。
それではdataInsert()を見てみましょう。更新や削除も考え方は同じです。
前に述べた通りinit()でテキストボックスを変数として扱えるようになったので、with(){}は不要になりました。コントロールをdocumentから指定する必要がなくなったからです。
そのかわり新しくif(){}でプログラムを囲んでいます。これはif()の条件式が満たされる場合のみ{}カッコ内の処理を行うようにしています。つまり2つのテキストボックスが共に未入力ではない時に、データの追加処理を行うということです。
もっと詳しく見てみましょう。if文の条件式の中で関数dataCheck()を呼び出していますが、この関数は戻り値として、trueかfalseを返すようにしています。
if(dataCheck(txtPrefCd,"PREF_CD") && dataCheck(txtPrefName,"PREF_NAME")){
省略
}
dataCheck(txtPrefCd,"PREF_CD")やdataCheck(txtPrefName,"PREF_NAME")の部分が、trueかfalseに置き換わるとイメージしてください。
if文の条件が満たされプログラムが実行されるのは、
if(true && true){
省略
}
となった時だけです。
「true && false」でも「false && true」または「false && false」でもダメです。PREF_CDかPREF_NAMEのどちらか一つでも未入力の場合は{}カッコ内は実行されません。正確には&&は前の条件がfalseなら後ろは判定されません。「false && ...」の形は全体として結局falseだからです。
次に関数を呼び出す側を詳しく見てみましょう。引数としてテキストボックスを意味する変数と文字列を渡しています。"PREF_CD"はメッセージを表示する時に使う文字なので何でもかまいません。
dataCheck(txtPrefCd,"PREF_CD")
呼び出された関数側は変数objでテキストボックスを、変数myStrで文字列を受け取っています。この関数はコントロールが未入力の場合は受け取った文字列を使ってメッセージを表示して、returnでfalseを返します。入力されている場合はtrueを返しているだけです。
function dataCheck(obj,myStr){
//データをチェックする関数
if (obj.value == "") {
alert(myStr + "は必ず入力してください。");
return false;
}else{
return true;
}
}
obj.value == "" は txtPrefCd.value == "" と同じ意味と考えてください。""は文字が入力されていない状態を表します。
データが未入力の場合はif()の条件式が満たされるのでtrueとなり{}カッコ内の処理が実行されます。満たされない場合は、else{}の処理が実行されます。
PREF_CDのチェックでfalseが返った場合は「false && ...」の形になるのでPREF_NAMEはチェックされません。なのでPREF_CDが未入力の場合表示されるメッセージは1回だけでしたね。PREF_NAMEについては未入力でも表示されません。もう一度動作確認してみてください。プログラムの働きがわかってから見ると「そうか!」という気付きがあると思います。削除の場合はSQL文でPREF_CDしか使っていませんのでチェックもPREF_CDだけです。
ちなみに関数になぜコントロールを引数として渡すかというと、PREF_CDとPREF_NAMEで同じ関数を共通して使いたかったからです。メリットは関数を呼び出す時の引数によって、関数内の処理を変えることができることです。
今はコントロール数が2つと少ないのでメリットがあまり感じないかもしれませんね。しかし例えば100個のコントロールの未入力をチェックしなければならないとしたらどうでしょう?1つの関数でチェックできる効果は大きいです。
余談ですがプログラムにはいろんな書き方があるので、コントロールではなくテキストボックスの値を渡すこともできます。もちろんdataCheck()は変更が必要ですが。
dataCheck(txtPrefCd.value,"PREF_CD")
またPREF_CDとPREF_NAMEを同時にチェックする書き方もできるでしょう。余裕がある人はいろいろ考えてみてください。
実はこのデータチェックではまだまだ不十分です。なぜならPREF_CDに半角数字以外の文字が入った場合や、PREF_NAMEにSQL文のエラー原因となる文字が入力され場合など予想外の使われ方が考えられるからです。もちろん作った本人が使う場合は、データの未入力や予想外の入力は少ないので、最小限のプログラムで済みます。