7-4 簡

在網際網路上,表單是和使用者互動的最常用方式。但使用者填入的資料可能不符合要求(例如將姓名欄位填成電子郵件、電子郵件不全、身份證字號或信用卡號碼有誤等),這些都可以在伺服器端的程式碼進行檢測,並將錯誤訊息回傳使用者。但這種方式不但增加了伺服器的負擔,也加重了網路資料的傳輸量。一個簡單的解決方案就是在客戶端以 JavaScript 來對表單的輸入進行驗證的工作,以確保表單數據在送至伺服器前都是正確無誤,這個檢核表單資料是否正確的過程,就稱為「表單資料驗證」(Form Data Validation),簡稱「表單驗證」(Form Validation)。

表單驗證可用 JavaScript 的各種字串與數值的函式來達成,並配合滑鼠事件,在適當的時機來提醒使用者可能發生的錯誤。以 JavaScript 在客戶端進行表單驗證的主要好處可摘要如下::

但是,若僅僅使用客戶端的程式碼來進行表單驗證,只能排除無心的錯誤,對於有心要從事破壞工作的惡意使用者,表單驗證是無法做到滴水不漏的。換句話說,對於重要的資料,除了在用戶端進行表端驗證外,最好也在伺服器進行相關資料的檢查。

此外,Netscape 及 IE 在第四版後都支援 JavaScript 的「通用表示法」(Regular Expressions),這是一套功能非常強大的字串比對方法,這使得表單驗證的程式碼益形簡潔。有關通用表示法,會在本書後續章節有詳細的介紹。但本節的重點則是以簡潔的範例來說明表單驗證的概念,不會使用通用表示法,以便讓讀者能夠進入情況。

首先我們來看一個簡單的範例,此範例檢查使用者輸入的電子郵件,讀者可以自行輸入電子郵件帳號來試試看:

Example(formValidation01.htm):

在上述範例中,我們檢驗電子郵件的規則很簡單,列舉如下:

此範例的原始檔如下:

原始檔(formValidation01.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>簡易表單資料驗證:電子郵件</h2>
<hr>

<script>
function validateForm(form){
	if (!checkEmail(form.email.value)){
		alert("Email 資料有誤,表單將不送出!");
		return(false);	
	}
	alert("資料正確無誤,立刻送出表單!");
	form.submit();
	return(true);
}

function checkEmail(email){
	index = email.indexOf ('@', 0);		// 尋找 @ 的位置,0 代表開始尋找的起始位置
	if (email.length==0) {
		alert("請輸入電子郵件地址!");
		return (false);
	} else if (index==-1) {
		alert("錯誤:必須包含「@」。");
		return (false);
	} else if (index==0) {
		alert("錯誤:「@」之前不可為空字串。");
		return (false);
	} else if (index==email.length-1) {
		alert("錯誤:「@」之後不可為空字串。");
		return (false);
	} else
		return (true);
}
</script>

請輸入您個人的電子郵件:<p>
<form>
電子郵件:
<input type="text" name=email size=20 value="xxxx"><br>
<p><input type=button VALUE="查核" onClick="validateForm(this.form)">
</form>

<hr>
</body>
</html>

嚴格來說,這些驗證規則是過於簡單,當我們學到通用表示法時,就可以對電子郵件進行較複雜完整的驗證。

在下面的範例,我們對信用卡號碼進行驗證:

Example(formValidation02.htm):

在上述範例中,我們假設信用卡卡號的格式是「xxxx-xxxx-xxxx-xxxx」,其中的每一個 x 都是代表一個數字,我們的驗證規則是:

上述範例的原始檔如下:

原始檔(formValidation02.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>表單資料驗證:信用卡號碼</h2>
<hr>

<script>
function validateForm(form){
	if (checkCreditCardNumber(form.cardNumber)){
		alert("資料正確無誤,立刻送出表單!");
		form.submit();
		return(true);
	}
	alert("資料有誤,表單將不送出!");
	form.cardNumber.focus();
	return(false);
}

function checkCreditCardNumber(control){
	var number=control.value;
	var character;
	var digit;
	if (number.length!=19){
		alert("<"+number+">:卡號長度有誤,請查核!");
		return false;
	}
	for (i=0; i<19; i++){
		character=number.charAt(i);
		if ((i==4)||(i==9)||(i==14)){	// 檢查是否是 "-"
			if (character!="-"){
				alert("<"+number+">:卡號輸入有誤(請以「-」分開四碼),請查核!");
				return false;
			}
		} else {	// 檢查是否是數字
			if (isNaN(parseInt(character))){
				alert("<"+number+">:卡號輸入有誤,請查核!");
				return false;
			}
		}
	}
	return true;
}
</script>

請輸入您個人的信用卡資料: <p>
<form>
卡號:
<input type="text" name=cardNumber size=20 value="xxxx-xxxx-xxxx-xxxx"><br>
<p><input type=button VALUE="查核" onClick="validateForm(this.form)">
</form>

<hr>
</body>
</html>

事實上上述驗證規則過於粗糙,真正的信用卡號碼還要符合一些內訂的編碼規則,詳見本書後續有關於「通用表示法」之章節的說明。

在下列的範例中,我們對各類表單控制項進行資料驗證,相關規則都可以由程式碼看出,請各位讀者親自試看看這個範例:

Example(formValidation03.htm):

上述範例的原始檔如下:

原始檔(formValidation03.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>表單資料驗證:驗證各類控制項的資料</h2>
<hr>

<script>
function checkName(control) {
	if (control.value == "") {
		validatePrompt(control, "請輸入大名!");
		return (false);
	}
	return (true);
}

function checkPassword(control) {
	if (control.value.length != 5) {
		validatePrompt(control, "請輸入長度為 5 的密碼!");
		return (false);
	}
	return (true);
}

function checkGender(control) {
	for (i=0; i<control.length; i++)
		if (control[i].checked)
			return(true);
	alert ("請輸入性別!");
	return (false);
}

function checkNationality(control) {
	for (i=1; i<control.length; i++)
		if (control[i].selected)
			return(true);
	alert ("請輸入國籍!");
	return (false);
}

function checkHobbies(control) {
	var count=0;
	for (i=0; i<control.length; i++)
		if (control[i].selected)
			count++;
	if (count>=2)
		return(true);
	alert ("請輸入至少兩樣興趣!");
	return (false);
}

function checkComment(control) {
	if (control.value == "") {
		validatePrompt(control, "請輸入您的寶貴意見!");
		return (false);
	}
	return (true);
}

function validateForm(form) {
	if (!checkName(form.realname)) return;
	if (!checkPassword(form.password)) return;
	if (!checkGender(form.gender)) return;
	if (!checkNationality(form.nationality)) return;
	if (!checkHobbies(form.hobbies)) return;
	if (!checkComment(form.comments)) return;
	alert ("你終於聽我的話了!\n全部資料通過驗證!\n表單即將送出!!!");
	document.testform.submit();	// Submit form
}

function validatePrompt(control, promptStr) {
	alert(promptStr);
	control.focus();
	return;
}
</script>

<form name=testform>
<P>貴性大名:<input type="text" name="realname" value="xxx">
<P>個人密碼:<input type="password" name="password">
<P>您的性別:<input type="radio" name="gender" value="male"> male
	<input type="radio" name="gender" value="female"> female
<P>您的國籍:<select name="nationality">
	<option>----<option>台灣<option>日本<option>韓國
	</select>
<P>您的興趣:<select multiple name="hobbies">
	<option>打球<option>下棋<option selected>聽音樂<option>閱讀<option>上網
	</select>
<p>寶貴意見:<textarea name=comments cols=40 rows=3></textarea>
<P><input type="button" value="送出" onClick="validateForm(this.form)"><input type="reset">
</form>

<hr>
</body>
</html>


JavaScript 程式設計與應用:用於網頁用戶端