用Javascript校驗客戶端資料(1)
作者: 雨亦奇
一、準確獲取文字框資料的位元組長度
也許你要問,在javascript中,利用form.textfield.value.length就可以得到form表單的textfield文字框中輸入資料的長度了,難道這個長度不是以位元組計的嗎?
在詳細說明之前,讀者不妨先測試如下網頁:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML4.01Transitional//EN">
<html>
<head>
<title>長度測試</title>
<meta http-equiv="Content-Type"
content="text/html; charset=gb2312">
</head>
<script>
function strlen(str)
{
return str.length;
}
function test()
{
alert("'"+form1.textfield.value+"'的長度等於"
+strlen(form1.textfield.value));
}
</script>
<body>
<form name="form1" method="post" action="">
<p>輸入字串:
<input name="textfield" type="text" value="china中國">
</p>
<p>
<input type="button" name="Button" value="測試" onclick="test();">
</p>
</form>
</body>
</html>
測試的結果如下:
怎麼樣?“china中國”的長度是7,而不是9(按位元組算的話,它的長度應該是9)。為什麼會這樣?答案是這個長度是以Unicode字元計的長度,一個英文字母是一個Unicode字元,一個漢字也是一個Unicode字元。
實際上我們經常用的並不是這個長度,而是以位元組為單位計算的長度。在B/S開發中,我們所用的後臺資料庫,其欄位寬度就是以節字計算的。以位元組為單位時,一個英文字母是一個位元組,而一個漢字則是兩個位元組了,二者長度不一樣。
由於資料校驗不宜在資料庫伺服器端進行(這樣做效率很低),所以在客戶端(瀏覽器端)進行資料校驗時,就必須以位元組為單位,以避免輸入的資料超出欄位寬度。為此,必須能獲取輸入資料的準確的位元組長度。
筆者經過一番研究,寫了如下javascript函式:
function strlen(str)
{
var len;
var i;
len = 0;
for (i=0;i<str.length;i++)
{
if (str.charCodeAt(i)>255) len+=2; else len++;
}
return len;
}
在這個javascript指令碼中,strlen函式逐個取str字串中的Unicode字元,利用charCodeAt獲取指定位置的字元的值(為數字形式,可和數字進行比較),因為英文字元的值總在0到255之間,所以我們可以認定,如果該值大於255,就表示是漢字,長度加2,否則長度加1,這樣最終可得到這個字串以位元組計的長度,滿足了我們的要求。
下面是將原取字串長度的函式strlen替換為新的strlen後的結果:
二、客戶端資料校驗的通用解決之道----妙用自定義屬性
我們知道,HTML的文字框元素可以使用type,name,value,size,maxlength,style,id等固有屬性,但你可曾想到,我們還可以自定義一些屬性呢。筆者是在一個極其偶然的機會裡發現這個小祕密的,並且沒有想到的是,這個小祕密竟然可以幫我們很大的忙----實現客戶端資料的通用校驗,自此客戶端校驗工作容易做了,不用再為每個FORM表單勞神又費力地寫javascript校驗程式碼了。
請看下面的測試網頁univerify_test.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>基於自定義屬性的客戶端統一檢測方法</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<script language="javascript" src="univerify.js"></script>
<body>
<br>
<br>
<center>基於自定義屬性的客戶端統一檢測方法</center>
<form name="form1" method="post" action=""
onsubmit="return verifyAll(form1);">
<center>
<TABLE align="center" border="1" borderColor="#aaeeff"
cellPadding="1" cellSpacing="0" width="580">
<tr>
<td><img id=img_NAME src="img/space.gif"></td>
<td>姓名:</td>
<td><input type="text" name="NAME" chname="姓名"
size="10" maxlength="10" maxsize="10" nullable="no"
datatype="text" onBlur="verifyInput(this);">
<font color="red">*</font></td>
</tr>
<td><img id=img_AGE src="img/space.gif"></td>
<td>年齡:</td>
<td><input type="text" name="AGE" chname="年齡"
size="3" maxlength="3" maxsize="3" nullable="no"
datatype="number" onBlur="verifyInput(this);">
<font color="red">*</font></td>
<tr>
<td><img id=img_ADDRESS src="img/space.gif"></td>
<td>住址:</td>
<td><input type="text" name="ADDRESS" chname="住址"
size="40" maxlength="100" maxsize="100" nullable="yes"
datatype="text" onBlur="verifyInput(this);"></td>
</tr>
<tr height=48px>
<td colspan=3 align=center><input type="submit"
name="Button" value="檢測全部輸入並提交" ></td>
</tr>
</table>
</center>
</form>
</html>
上述網頁的表單form1中有三個文字框,姓名(NAME)、年齡(AGE)和住址(ADDRESS)。筆者為這三個文字框中自行定義了四個新屬性,分別是:
1、chname:表示該資料的中文名稱,用於校驗出錯時顯示用。
2、maxsize:表示允許輸入的最大長度,這個長度是以節字計算的。
3、nullable:表示輸入值是否允許為空。為yes時允許為空。
4、datatype:表示輸入值的資料型別。這個資料型別使用者可以根據需要自行定義,需要注意的是,對於每一個新的資料型別,均需要在下面將要講述的javascript檔案univerify.js中新增相應的校驗函式,從而實現統一校驗。
三個文字框都對失去焦點事件進行捕獲:onBlur="verifyInput(this);"。在失去焦點時用verifyInput校驗一下此文字框的值是否合法。
form1表單對onsubmit事件進行了捕獲:onsubmit="return verifyAll(this);"。在使用者提交表單時,用verifyAll對此表單的元素的值統一進行檢測,驗證其合法性,保證存入資料庫時不出現異常。
上述網頁引用的javascript函式庫univerify.js內容如下:
/******************************************************/
/* 檔名:univerify.js */
/* 功 能:基於自定義屬性的統一檢測用javascript函式庫 */
/* 作 者:縱橫軟體製作中心雨亦奇([email protected]) */
/******************************************************/
/* 取得字串的位元組長度 */
function strlen(str)
{var i;
var len;
len = 0;
for (i=0;i<str.length;i++)
{
if (str.charCodeAt(i)>255) len+=2; else len++;
}
return len;
}
/* 檢測字串是否為空 */
function isnull(str)
{
var i;
for (i=0;i<str.length;i++)
{
if (str.charAt(i)!=' ') return false;
}
return true;
}
/* 檢測字串是否全為數字 */
function isnumber(str)
{
var number_chars = "1234567890";
var i;
for (i=0;i<str.length;i++)
{
if (number_chars.indexOf(str.charAt(i))==-1) return false;
}
return true;
}
/* 檢測指定文字框輸入是否合法 */
function verifyInput(input)
{
var image;
var i;
var error = false;
/* 長度校驗 */
if (strlen(input.value)>parseInt(input.maxsize))
{
alert(input.chname+"超出最大長度"+input.maxsize);
error = true;
}
else
/* 非空校驗 */
if (input.nullable=="no"&&isnull(input.value))
{
alert(input.chname+"不能為空");
error = true;
}
else
{
/* 資料型別校驗 */
switch(input.datatype)
{
case "number": if (isnumber(input.value)==false)
{
alert(input.chname+"值應該全為數字");
error = true;
}
break;
/* 在這裡可以新增多個自定義資料型別的校驗判斷 */
/* case datatype1: ... ; break; */
/* case datatype2: ... ; break; */
/* ....................................*/
default : break;
}
}
/* 根據有無錯誤設定或取消警示標誌 */
if (error)
{
image = document.getElementById("img_"+input.name);
image.src="img/warning.gif";
return false;
}
else
{
image = document.getElementById("img_"+input.name);
image.src="img/space.gif";
return true;
}
}
/* 檢測指定FORM表單所有應被檢測的元素
(那些具有自定義屬性的元素)是否合法,此函式用於表單的onsubmit事件 */
function verifyAll(myform)
{
var i;
for (i=0;i<myform.elements.length;i++)
{
/* 非自定義屬性的元素不予理睬 */
if (myform.elements[i].chname+""=="undefined") continue;
/* 校驗當前元素 */
if (verifyInput(myform.elements[i])==false)
{
myform.elements[i].focus();
return false;
}
}
return true;
}
在univerify.js中,verifyAll用來校驗指定表單的資料,它是逐個提取表單中的元素的,不用特別指定表單元素的名字,所以具有通用性。verifyInput是用來實際執行資料校驗的函式,如果有新的資料型別datatype需要檢測,使用者可在此函式中新增,可擴充性好。
下面是瀏覽univerify_test.html網頁的畫面:
使用基於自定義屬性的客戶端統一檢測方法,需要做的工作很簡單:
1、在網頁檔案中嵌入統一檢測用javascript函式庫:<script language="javascript" src="univerify.js"></script>
2、對所用表單新增onsubmit事件處理程式:onsubmit="return verifyAll(this);"。其中的this指定為當前表單物件,勿需提供表單具體名字,極具通用性。
3、對每個需要檢測的文字框新增chname,maxsize,nullable和datatype四個自定義屬性。如果想在文字框失去焦點時對資料進行一下校驗,請新增事件處理程式:onBlur="verifyInput(this);"。
怎麼樣?使用基於自定義屬性的客戶端統一檢測方法後,不用再為每個表單寫類似的檢測程式碼了吧,統一檢測足夠了。
小結:自定義屬性是非常有用的屬性,基於自定義屬性的客戶端資料統一檢測方法,在B/S開發中極其有用,使用方便,可擴充性強。相信讀者經過實踐,自能體會到箇中妙處。