一、准确获取文本框数据的字节长度
也许你要问,在Javascript中,利用form.textfield.value.length就可以得到form表单的textfield文本框中输入数据的长度了,难道这个长度不是以字节计的吗?
在详细说明之前,读者不妨先测试如下网页:
<!DOCTYPE HTML PUBLIC "-//W 3C //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="测试" οnclick="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 "-//W 3C //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="" οnsubmit="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事件进行了捕获:οnsubmit="return verifyAll(this);"。在用户提交表单时,用verifyAll对此表单的元素的值统一进行检测,验证其合法性,保证存入数据库时不出现异常。
上述网页引用的Javascript函数库univerify.js内容如下:
/******************************************************/ /* 文件名:univerify.js */ /* 功 能:基于自定义属性的统一检测用Javascript函数库 */ /* 作 者:纵横软件制作中心雨亦奇(zhsoft88@sohu.com) */ /******************************************************/ /* 取得字符串的字节长度 */ 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网页的画面:
下面是浏览 univerify_test.html 网页的画面:
使用基于自定义属性的客户端统一检测方法,需要做的工作很简单:
1、在网页文件中嵌入统一检测用Javascript函数库:<script language="javascript" src="univerify.js"></script>
2、对所用表单添加onsubmit事件处理程序:οnsubmit="return verifyAll(this);"。其中的this指定为当前表单对象,勿需提供表单具体名字,极具通用性。
3、对每个需要检测的文本框添加chname,maxsize,nullable和datatype四个自定义属性。如果想在文本框失去焦点时对数据进行一下校验,请添加事件处理程序:onBlur="verifyInput(this);"。
怎么样?使用基于自定义属性的客户端统一检测方法后,不用再为每个表单写类似的检测代码了吧,统一检测足够了。
小结:自定义属性是非常有用的属性,基于自定义属性的客户端数据统一检测方法,在B/S开发中极其有用,使用方便,可扩充性强。相信读者经过实践,自能体会到个中妙处。