最近开发一个项目,有一个新闻的模块,用户需要对标题进行控制,希望在输入的时候就不允许超过规定的字数,而不是提交到服务器再判断。
显然,这只能使用javascript来完成这一艰巨的任务了。
首先,既然要限制字数,肯定要想办法实时获取用户在文本框里输入的文字的数量。input控件有个length的属性,可以方便地获取字数。可是,它所返回的字数无论是中文还是英文或者数字,1个字就算1个字。客户要限制字数的原因是为了页面显示的时候排版不会乱,因此一个汉字需要按2个英文字符来计算。这样的话,这个默认的length就无用武之地了。
怎么区分中文和英文呢?查阅了一下资料,string对象有一个叫charCodeAt(index)的方法,可以获取字符串中某一个字符的编码。我们都知道,字母数字的ascii编码都小于255而汉字的编码肯定大于255,因此我们可以使用此方法来判断字符串占用多少英文字符的宽度。
function GetCharLength(str)
{
var iLength = 0;
for(var i = 0;i<str.length;i++)
{
if(str.charCodeAt(i) >255)
{
iLength += 2;
}
else
{
iLength += 1;
}
}
return iLength;
}
字数统计有了,接下去我们需要实时地捕获用户的输入。我们可以采取在input文本框的onkeyup事件中加入字符串检测函数的调用即可。
在检测完字符长度后,对于那些超长的,我们将采用自后往前截断的方法将多余的字符去除。
字符截断代码如下:
function CutStr(Str,Len)
{
var CurStr = "";
for(var i = 0;i<Str.length;i++)
{
CurStr += Str.charAt(i);
if(GetCharLength(CurStr )>Len)
{
return Str.substring(0,i);
}
}
return CurStr ;
}
至此,一个简单的限制用户输入字符数的方案完成了。
接下去,我们考虑一些改进。
1、javascript中,可以使用正则表达式来搜索字符串里的字符并替换,我们可以用此方法来获取字符串占用的宽度,代码如下:
String.prototype.len=function(){
return this.replace(/[^\x00-\xff]/g,"**").length;
}
这段代码为string对象建立了一个len的属性,用户可以直接使用string.len来获取字符串所占用的宽度。在这里,我们使用了一个小技巧,通过正则表达式将编码在255以外的字符换成2个*,这样就可以统计了。
其实这个replace还有其它用法,比如要限制用户只能输入数字,可以使用
<input onChange="value=value.replace(/[^\d]/g,'')" >
只能输入数字和英文 /[\W]/g
只能输入汉字的 /[^\u4E00-\u9FA5]/g
2、微软拼音输入法对keyup事件很敏感,在某些情况下会把文本框里原有的字符全部去除(其实,主要因为用微软拼音输入法,虽然中文字没有上去,但是拼音字母已经作为内容存在文本框内,从而会激发判断函数。而一旦拼音比较长,会使字符超长,产生截断操作。因为是重写了框里的文本,截断操作之后,光标将移到最后一位,从而导致整个输入法的异常)
发现这个问题后,我又测试了其它一些输入法,发现这些输入法输入中文的方式各不一样,微软全拼输入法和智能ABC输入法也不同。考虑到还有其它各种输入法,因此采用在焦点移出的时候onBlur进行判断和截断操作。这样是最安全的。
以下是完整的代码:
<script language="javascript">
<!--
String.prototype.len=function(){
return this.replace(/[^\x00-\xff]/g,"**").length;
}
//Set maxlength for multiline TextBox
function setMaxLength(object,length)
{
var result = true;
var controlid = document.selection.createRange().parentElement().id;
var controlValue = document.selection.createRange().text;
var tempString=object.value;
var tt="";
for(var i=0;i<length;i++)
{
if(tt.len()<length)
tt=tempString.substr(0,i+1);
else
break;
}
if(tt.len()>length)
tt=tt.substr(0,tt.length-1);
object.value=tt;
}
//Check maxlength for multiline TextBox when paste
function limitPaste(object,length)
{
var tempLength = 0;
if(document.selection)
{
if(document.selection.createRange().parentElement().id == object.id)
{
tempLength = document.selection.createRange().text.len();
}
}
var tempValue = window.clipboardData.getData("Text");
tempLength = object.value.len() + tempValue.len() - tempLength;
if (tempLength > length)
{
tempLength -= length;
var tt="";
for(var i=0;i<tempValue.len()-tempLength;i++)
{
if(tt.len()<(tempValue.len()-tempLength))
tt=tempValue.substr(0,i+1);
else
break;
}
if(tt.len()<=0)
{
window.event.returnValue=false;
}
else
{
tempValue=tt;
window.clipboardData.setData("Text", tempValue);
window.event.returnValue = true;
}
}
}
function PressLength()
{
if(event.srcElement.type=="text" || event.srcElement.type=="textarea" )
{
if(event.srcElement.length!=null)
setMaxLength(event.srcElement,event.srcElement.length);
}
}
function LimitLength()
{
if(event.srcElement.type=="text" || event.srcElement.type=="textarea" )
{
if(event.srcElement.length!=null)
limitPaste(event.srcElement,event.srcElement.length);
}
}
document.documentElement.attachEvent('onBlur', PressLength);
document.documentElement.attachEvent('onpaste', LimitLength);
//-->
</script>
From http://www.gaozhe.net/article.asp?id=11