posts - 283, comments - 10329, trackbacks - 112, articles - 5
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

 最经典的实现字符数控制的方案
当我们在ASP.NET开发时,经常会遇到一个头疼的问题:字符数的控制
 由于数据库的字段长度是固定的,因此在进行字符输入时,最关键的就是控制字符的个数不能超过字段的长度,要不然,一个个异常会让人疯掉的。
  对于单行文本框,不管是HTML控件还是Web控件,我们经常会使用MaxLength来控制,但这种控制无法控制到中文字符,即MaxLength=50的控制,可以输入50个英文与50个中文,这样的话,还是会导致中文字符数的溢出。
  对于多行文本框,那就更惨了,使用MaxLenth根本不起作用的。

下面提供的方案优势:
  1)最佳的方法是在文本框中输入时,控制到最大字数,超过时不能进行输入;

  2)对于粘帖的情况也要能兼容,以前网上的方法不能控制到paste的情况;

  3)对于最后的一个中文字符,宁愿舍去也不能多一个字符,比如50的字符数,在第49个时,最后输入一个中文,会导致最终字数为51,而这种情况,推荐是不能输入中文,保证最终的字符数<=50最佳,因为放弃一个中文字符总比数据库报错要好吧。
 4)为了提高开发效率,尽可能的减少代码量,此方案不需要为文本框添加任何事件,而是由脚本块自己解决,因此只需要把脚本块饮包含到页面中就可以了,这应该是相当方便了吧 
 
完善版修改:由于前一个方案中,一些输入法无法激活onpress事件,导致对于中文的不支持,现在采用onkeyup事件处理,在处理方式上也进行了修改,原来的onpress事件是进行输入控制,而onkeyup只能对已经输入后的字数进行字数判断,过长的进行截短处理。

  在原方案中,有位朋友指出:数据采用n(type)系统不会报错,是的,如果采用n(type)的话,是以字符为基础的,可以不考虑数据库出错的可能性,但同样也存在一个界面显示的问题,比如界面上的Address值,希望是100个字符,如果不进行中英文字数区分,最多将输入100个中文,从而占200个字节空间,导致Adress在显示时会超过预料的空间,界面搞得不易控制。因此,此方案还是有可取之处的。
具体新方案实现:
 1)将以下的代码包含到页面中:

<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('onkeyup', PressLength); 
document.documentElement.attachEvent('onpaste', LimitLength);

//--> 
        </script>


2)在需要控制的控件上添加length="n"(n为要控制的字数)即可,如:
 
<INPUT  type="text" length="3">
<TEXTAREA length="20"  rows="2" cols="20"></TEXTAREA>
<asp:TextBox id="TextBox1"  runat="server" length="7"></asp:TextBox>
<asp:TextBox id="TextBox2" runat="server" TextMode="MultiLine" length="10"></asp:TextBox>
上面是HTML控件与Web控件的例子,只要加一个length就可以了。

 好了,大家可以体验一下了哦:http://files.cnblogs.com/tintown/stringLenth3.rar (已经修改复了“没有length无法输入的问题”)

个人建议:1)可以把这个脚本块放在js文件中,进行引用即可
                2)可以把脚本放在BasePage中,这样每个页面都可以使用了
               3)可以使用这些脚本块,开发专门的服务器端控件,我没有时间开发,如果有朋友可以开发了发布一下哦!

Feedback

#1楼   回复  引用  查看    

2005-02-07 13:43 by 灵感之源:PSP团队Guru      
强行去掉最后一个输入的字符似乎有的不大好吧?

#2楼   回复  引用  查看    

2005-02-07 14:18 by -╃小〥斌╄      
试了,可以了。
ps:不是强行去掉最后一个字符而是最后一个汉字 觉得不合适,可以把length加长啊。

#3楼   回复  引用  查看    

2005-02-07 14:42 by 灵感之源:PSP团队Guru      
我表达得不清楚:如果限制为5,输入第6个字符,会发现字符输入了,但又自动去掉,这样给别人看起来不舒服

#4楼   回复  引用  查看    

2005-02-07 16:31 by -╃小〥斌╄      
那是不是可以放在一个隐藏框里 再显示呢?

#5楼   回复  引用  查看    

2005-02-07 16:33 by 轻剑傲风      
3)对于最后的一个中文字符,宁愿舍去也不能多一个字符,比如50的字符数,在第49个时,最后输入一个中文,会导致最终字数为51,而这种情况,推荐是不能输入中文,保证最终的字符数<=50最佳,因为放弃一个中文字符总比数据库报错要好吧。

完全的程序员呆板思维,做出来的东西要的实用,别人最后一个字可能就是最重要的,去掉了,你存下来的资料就完全没有了意义。

所以这种解决方案根本不行哈。完全不从市场解度考虑,失败。

#6楼   回复  引用    

2005-02-08 21:35 by birdshome
@轻剑傲风
莫名其妙的评论,限制成50个字符就是更具用户需求做出的呀。

#7楼[楼主]   回复  引用  查看    

2005-02-09 17:25 by 听棠.NET      
@轻剑傲风
老兄,你不要妄自菲薄,我看你才是不懂的人啊!这是为了防止出错,为了界面,难道你宁愿系统报错,让客户输入过多的字符。
@all:
至于最后一个字符的删除,在控制上可能不太美观,但目前我只能这样控制,不知道有没有其他的好方法。最后一个中文的删除,也是为了保持完整性,因为一个字符容不下一个中文,所以宁愿舍去!

#8楼   回复  引用  查看    

2005-02-16 10:00 by James      
good

#9楼   回复  引用  查看    

2005-02-16 17:23 by BOBO      
GooD

#10楼   回复  引用  查看    

2005-02-17 11:56 by 轻剑傲风      
不好意思,前面言词不太合适
我对技术方面并不太在行,只能说是了解一些吧
我主要负责是客户需求和系统构架,在公司里。
当然,是客户要求限在50字以内,那当然无可非意,在处理时但也不应直接去掉,给出提示,让用户自行把内容改到50字以内,否则不执行后面的,这样会更人性化。
如果自动就这么去掉了,可能是最关键的去掉了,而客户自己也不知情,,,,

#11楼[楼主]   回复  引用  查看    

2005-02-17 12:44 by 听棠.NET      
@轻剑傲风:
我也口气太重了,控制字数的业务情况还是蛮多的,在超过时采用弹出窗口也是可以的,有兴趣的朋友只要修改一下就可以了,不过,我倒是不太喜欢弹出来,因为挺烦人的。输不下去,自然也就知道了。

#12楼   回复  引用  查看    

2005-02-17 15:28 by 轻剑傲风      
嘿嘿,记得以前我在输不下去时就重装过输入法

#13楼   回复  引用    

2005-02-19 18:56 by guest
如果采用sqlserver,将该字段设置为nvarchar(50),不知道可不可以

#14楼   回复  引用    

2005-02-24 21:44 by 头发不能乱[未注册用户]
你这个方法需要改进,我发现了一些问题
1.如果TextBox没有设置length这个属性的话,连值都输入不了
2.假如用户希望TextMode="MultiLine" 输入为NTEXT,请问您怎么实现
3.当length超过1000的时候我发现输入就很明显的慢了下来,5000以上几乎就象是死机,对客户端的影响太大了
4.输入文字后CTRL+A不能全选
总体来说这是个好方法,解决了我不少问题,但是这些方面也应该考虑一下,楼主解决了请给我邮箱发个邮件,谢谢!

#15楼[楼主]   回复  引用  查看    

2005-02-25 09:43 by 听棠.NET      
@头发不能乱 :
首先要感谢你的支持。
1.此问题已经解决,请重新下载即可。
2.NTEXT可以照常输入啊,只要保存时使用nvarchar即可。
3.速度我也测试了一下,是有点慢下来了,不过,还算可以接受,可能是我的机器比较好吧,我是1G内存的。这个问题我也不知道如何解决了。
4.CTRL+A的问题我试了好几次,也不知道如何解决,哪位朋友帮个忙,我用event.keyCode=17还是不行啊。

#16楼   回复  引用    

2005-02-25 14:18 by 头发不能乱 [未注册用户]
我想要的效果就是假如我没有设置length属性的话,就不用调用那个JS函数,js对这个控件无效,也就是说我无论输入多少字符,也不会产生那种反应速度的问题了。楼主,急啊!帮帮忙,谢谢

#17楼   回复  引用    

2005-02-25 14:27 by 头发不能乱[未注册用户]
另外楼主你这个页面上面的原代码我看了一遍,好象一点都没有变啊!!你改过了吗?

#18楼[楼主]   回复  引用  查看    

2005-02-25 14:50 by 听棠.NET      
我现在改过了,你可以直接copy代码或是下载文件即可。

#19楼   回复  引用    

2005-02-25 15:24 by 头发乱了[未注册用户]
楼主,太谢谢你了,你的回复太及时了,.......支持楼主
帮了我大忙了

#20楼   回复  引用  查看    

2005-03-01 16:15 by Freeman      
小弟学习了!

好像 shift + ← 可以全选定,而CTRL+A 不可以!

#21楼   回复  引用  查看    

2005-03-01 16:55 by myrat      
快速输入后快速用鼠标在空白处点一下,多出来的字符就不会被截掉了,hiahia,小bug

#22楼[楼主]   回复  引用  查看    

2005-03-01 17:00 by 听棠.NET      
希望JavaScript高手能进行再次完善啊!其实我对js也不是特熟,象CTRL+A的问题等,我也是搞不定了啊。SOS!!!搞不定我就

#23楼   回复  引用  查看    

2005-03-01 17:10 by mikespook      
[a-zA-Z0-9\u4e00-\uf900] 不是可以匹配一个大小写字母、数字或中文么? 用这个应该可以直接统计吧?

#24楼   回复  引用    

2005-03-04 21:54 by 咖啡猫
我觉得可以从以下几个方面来解决:
1.
在设计数据库的时候已经完全用n(type),
这样直接使length小于数据库中指定的长度就可以了。
毕竟硬件发展了,这点空间还是可以承受的,
而且可以减少很多问题,尤其需要支持多语言的时候更明显。
还有就是nvarchar比varchar的查询速度更快(信不信由你)。

2. 不要在用户输入的时候去检查用户,这样会打扰用户,
尤其很多用户就是一些专门录单子的,输入速度非常快。
建议在form的提交的时候统一检查,
如果有错误的话,将焦点停留在出错的输入框上。

不知大家的意见如何?


#25楼[楼主]   回复  引用  查看    

2005-03-06 10:33 by 听棠.NET      
@咖啡猫 :
你的观点我基本同意:
1.我也是早已采用n(type)了,没有了Length问题,而且支持多语言
2.在输入时控制不控制呢,也要看情况的,如果在输入以后再提示,未必有些麻烦,在输入时他就能注意到就可以在立即修改,因为前面的输入部分可能会影响后面的输入部分。如果不是速度的影响,我还是推荐在输入时就进行控制,把错误扼杀的输入状态。
3.中英文的字符判断是需要的,因为界面控制也是非常重要的,不能因为n(type)的兼容而忽略了界面控制。

#26楼   回复  引用    

2005-03-10 09:25 by cmoremore
想法不错,但看上去确实很不对劲,客户很难同意


不知道又没有更好的办法

#27楼   回复  引用    

2005-05-20 10:13 by 哈哈[未注册用户]
http://www.shanghaiabc.com/
挺好的,我用了!谢谢!!!

#28楼   回复  引用  查看    

2005-05-23 09:09 by 慕晓      
同意使用 n(*) 的解决办法。对于js我觉得尽量少用,因为js很容易出错(个人感觉),有时候还有兼容问题。但是很多友好的界面还是需要js来完成的。我觉得这个矛盾就世为什么flash能够流行的原因。

#29楼   回复  引用    

2005-06-23 10:53 by caibird
楼主能想办法过滤掉成对的<><>吗?
比如说<font color=#ff0000>红色</font>
统计字数的时候只算“红色”,其他的过滤掉

#30楼   回复  引用    

2005-06-29 09:47 by lt
使用n(type)可以解决问题,何必这么麻烦?

#31楼   回复  引用    

2005-10-10 22:26 by 领悟[未注册用户]
比如我输入10个文字以后,想去求改第3,4个字,但是每修改一个光标都会跑到最后!删除中间自己字时,光标也会自动跳到最后!

#32楼   回复  引用    

2005-10-25 17:59 by 崇拜高智商[未注册用户]
有点疑惑, copy 你的code, html control 可以, asp server control (textbox) 好像不可以, 解析成html control 没有length property, code 中event.srcElement.length == undefind, 暂时我没有好办法, 另用个hidden来充当event.srcElement, 来弥补undefind, 你们有什么好办法吗?

#33楼   回复  引用    

2005-11-18 19:29 by fw[未注册用户]
这个js已经很不错了,但是有一点小bug,当我们在TEXTAREA 内容中间部分用键盘输入数据时;光标会自动指向最后一个字符,很不方便!希望能否改进一下!感谢!!

#34楼   回复  引用    

2006-03-24 16:25 by hongyi_crack[未注册用户]
1.关于光标会自动移动到后面的问题,这是因为楼主的代码是每次,不管你这次输入的是不是超出长度,都会用一个暂存的变量向当前选中的textbox里面赋值,所以每次光标自然是移动到最后面了.
2.关于crl+a的问题,开始着实让人找不到出路.因为虽然if ((event.ctrlKey)&&(event.keyCode==65))判断可以判断出当前按的是ctr+a,可问题是,我们松开的时候并不一定是同时松,所以atr按钮和a按钮的放开事件变会又执行一次,于是按以前楼主的代码,用一个暂存的变量向当前选中的textbox里面赋值,所以不但每次光标自然是移动到最后面了.而且ctr+a的全选状态也被取消了.

解决以上问题,我是换了一种思路,就是当用户输入不超长时,就让其保存原来的值.超长再用暂存的变量去覆盖.改了点代码,于是,上面两个问题就解决了

3.觉得每次把用户输入的超出长度的最后部分截掉太不友好了,因此定义了个全局变量来保存上一次存入的合规则的值.这样,当超出长度时,就可以只取消用户当前的输入而不老是去截最后的值.

改动的代码如下:var globalStr="";

//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)
{
alert("输入超出"+length+"个字符");
object.value=globalStr;
//tt=tt.substr(0,tt.length-1);
//object.value=tt;
}
else
{
globalStr= tt;
}


}

最后,非常感谢楼主,从你这里学了很多东西.

#35楼   回复  引用    

2006-03-24 16:47 by hongyi_crack[未注册用户]
第三个问题我的解决方案错了.汗

#36楼   回复  引用  查看    

2006-05-24 15:37 by 徐灿钊Asp.net专栏      
正用上!

#37楼   回复  引用  查看    

2006-07-07 13:55 by BookWorm      
FF下不能正常运行。

#38楼   回复  引用    

2006-08-18 11:07 by 杀猪的[未注册用户]
这有问题啊。。。特别是在用微软拼音输入的时候,当达到maxlength之后然后再用微软输入中文字符会把整个框的内容全部删除的。。

#39楼   回复  引用    

2006-09-13 15:58 by kefan[未注册用户]
这不是最好的方案,用onpropertychange属性就可以控制,我以前的控制方法如下,可以封装一下,做成共用文件的:

<script language="javascript">
<!--
function MaxLength(field,maxlimit){
var j = field.value.replace(/[^\x00-\xff]/g,"**").length;
//alert(j);
var tempString=field.value;
var tt="";
if(j > maxlimit){
for(var i=0;i<maxlimit;i++){
if(tt.replace(/[^\x00-\xff]/g,"**").length < maxlimit)
tt = tempString.substr(0,i+1);
else
break;
}
if(tt.replace(/[^\x00-\xff]/g,"**").length > maxlimit)
tt=tt.substr(0,tt.length-1);
field.value = tt;
}else{
;
}
}
</script>

单行文本框控制<br />
<INPUT type="text" id="Text1" name="Text1" onpropertychange="MaxLength(this, 5)"><br />
多行文本框控制:<br />
<TEXTAREA rows="14"
cols="39" id="Textarea1" name="Textarea1"
onpropertychange="MaxLength(this, 15)"
style="WIDTH: 336px; HEIGHT: 232px"></TEXTAREA><br />

Email:kefanmail@163.com
欢迎沟通
刚刚回复错了,好象回复到了另一篇文章,呵..不好意思.

#40楼   回复  引用    

2006-11-20 15:55 by UFO[匿名][未注册用户]
请问楼主如何解决光标移动的问题?

#41楼   回复  引用    

2007-01-31 12:55 by 菜鸟[未注册用户]
请区别字符长度和字节长度,谢谢!

#42楼   回复  引用    

2007-01-31 13:07 by 菜鸟[未注册用户]
帅哥,你知道什么叫“人性化吗”?

1、你觉得这应该让客户自己去取舍还是让你来强制执行?

2、你那个javascript离开ie就死翘翘了。

3、在客户端代码里加个length是很管用吗?在地址栏里输入一句脚本就可以改掉了。

4、对于包含 Unicode 的内容,本来就应该使用 nvarchar 之类的字段类型,数据库已经给你提供了解决方案,你不用

5、在显示的时候考虑占位长度是应该的,但你的做法貌似本末倒置了,仅仅因为这样你就压缩了用户的输入空间?是不是把你的做法放到显示这个环节比较好?

最终该判断的还判断,规范长度的方法n多,你不但用了最不可取的方式,还是一种多余的方式。

#43楼   回复  引用    

2007-02-27 16:30 by Terry[未注册用户]
两个问题:
1、firefox下不生效
2、用微软拼音输入的时候,当达到maxlength之后然后再用微软输入中文字符会把整个框的内容全部删除的

#44楼   回复  引用    

2007-08-16 09:31 by 路过[未注册用户]
把中英文混编的字段设置成nvarchar或ntext就可以了。

#45楼   回复  引用    

2007-10-14 18:50 by asf[未注册用户]
dsfds

#46楼   回复  引用    

2007-10-29 13:15 by xwl[未注册用户]
你们好,我要设个密码,它说必须是字符数,啥叫字符数

#47楼   回复  引用    

2008-06-02 10:08 by JiangKunJian[未注册用户]
--引用--------------------------------------------------
听棠.NET: @轻剑傲风:
我也口气太重了,控制字数的业务情况还是蛮多的,在超过时采用弹出窗口也是可以的,有兴趣的朋友只要修改一下就可以了,不过,我倒是不太喜欢弹出来,因为挺烦人的。输不下去,自然也就知道了。
--------------------------------------------------------
楼主说得对,又要想我们以最快的速度做出项目,又要求代码质量,还要我们把市场解度完美的考虑进去,还要不要我们活了?

#48楼   回复  引用    

2008-08-01 10:14 by 老破[未注册用户]
--引用--------------------------------------------------
听棠.NET: @轻剑傲风
<br> 老兄,你不要妄自菲薄,我看你才是不懂的人啊!这是为了防止出错,为了界面,难道你宁愿系统报错,让客户输入过多的字符。
<br>@all:
<br> 至于最后一个字符的删除,在控制上可能不太美观,但目前我只能这样控制,不知道有没有其他的好方法。最后一个中文的删除,也是为了保持完整性,因为一个字符容不下一个中文,所以宁愿舍去!
--------------------------------------------------------
妄自菲薄???用错词了吧!

#49楼   回复  引用    

2008-09-22 21:39 by mr.caiqinghua[未注册用户]
@听棠.NET
解决CTRL+A的问题:只要在
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);
if(object.value != tt)//在这个函数添加这一行就可以了
object.value=tt;


}

#50楼   回复  引用    

2008-12-23 11:07 by 想做程序员的菜鸟[未注册用户]
感谢博主~
楼上的太牛B了,解决微软拼音输入法回车时清空textbox的漏洞



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 103088




相关文章:

相关链接: