zoukankan      html  css  js  c++  java
  • 经验总结:应对中文输入法的字符串截断方案(带代码示例)

    遇到这么个需求,允许用户修改自己的名片,名片最大长度支持8个汉字(24个字节),当用户输入超过8个字节,则不允许用户继续输入

    最初的思路:oninput你好

    很常见的需求,觉得驾轻就熟,监听input事件,当输入内容发生变化的时候,获得用户输入内容,并进行截断操作(如果超出的话)。主要代码如下。一切显得那么美好,直到中文输入法出现。

    ps:本文用例均在 chrome 版本 33.0.1750.146下测试

    $('#text').on('input', function() {
        var value = $(this).val();
        if(Str.byteLen(value, 3)>24){
            $(this).val(Str.getMaxlen(value, 24));
        }
    });

    完整代码如下,有兴趣可以看下:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>demo</title>
    
    </head>
    <body>
        <input id="text" placeHolder="最大支持24个字节" />
        <script type="text/javascript" src="jquery.js"></script>
        <script type="text/javascript">
         var Str = {
             byteLen : function (str, len){
                //正则取到中文的个数,然后len*count+原来的长度。不用replace
                var factor = len || 2;
                str += '';
                var tmp = str.match(/[^x00-xff]/g) || [];
    
                var count = tmp.length;
                return str.length + (factor-1)*count;
            },
            getMaxlen : function(str,maxlen){
                var sResult = '', L=0, i=0, stop = false, sChar;
                if(str.replace(/[^x00-xff]/g,'xxx').length <= maxlen){
                    return str;
                }
                while(!stop){
                    sChar = str.charAt(i);
                    //sResult+=sChar;
                    L+= sChar.match(/[^x00-xff]/) !== null ? 3 : 1;
    
                    if(L > maxlen){
                        stop = true;
                    }else{
                        sResult+=sChar;
                        i++;
                    }
                }
                return sResult;
            }
        };
        $('#text').on('input', function() {
            var value = $(this).val();
            if(Str.byteLen(value, 3)>24){
                $(this).val(Str.getMaxlen(value, 24));
            }
        });
        </script>
    </body>
    </html>
    完整代码

    oninput的局限:中文输入法带来的难题

    上面的解决方案对于普通的文本输入,如英文字母、数字等的输入是ok的。但当用户通过中文输入法(比如QQ拼音)时,就会遇到一些问题,我们简单改下上面的代码,看看究竟会有什么问题。就加多了个log打印。

        $('#text').on('input', function() {
            var value = $(this).val();
            console.log('当前输入:'+value);  // 打印当前输入的值
            if(Str.byteLen(value, 3)>24){
                $(this).val(Str.getMaxlen(value, 24));
            }
        });

    下面是输入过程中的截图。可以看到,用户使用中文输入法输入的过程中,“input”事件被不断地触发着,这会带来什么问题呢?相信你已经想到了——会导致程序对当前用户输入字符实际长度的误判。比如用户输入“程序猿”三个汉子,实际占用9个字节,但对上面的程序来说,取到的字节数为"chengxuyuan".length == 11。在用户输入达到边界值时,就会莫名其妙地将用户的输入截断,导致中文输入无法接续(感兴趣的同学可以自己试下)

    解决思路一:compositionstart、compositionend

    在万能的幼稚园群里抛出问题后,有个兄弟提出了个方案:可以采用compositionstart、compositionend来捕获IME(input method editor)的启动和关闭事件。说实话,这两事件听都没听过,但既然有这么个解决方案,暂且试一下,再次修改代码

    $('#text').on('input', function() {
        if($(this).prop('comStart')) return;    // 中文输入过程中不截断
    
        var value = $(this).val();
        console.log('当前输入:'+value);
        if(Str.byteLen(value, 3)>24){
            $(this).val(Str.getMaxlen(value, 24));
        }
    }).on('compositionstart', function(){
        $(this).prop('comStart', true);
        console.log('中文输入:开始');
    }).on('compositionend', function(){
        $(this).prop('comStart', false);
        console.log('中文输入:结束');
    });

    输入过程截图如下,可以看到,当compositionstart事件触发,就停止对输入字符的截断操作,而是耐心等待用户输入的结束

    按下空格键,中文输入结束,此时再去进行字符长度的判读和截断

    未完的探索

    正如正文最前面强调的,本文的用例都是在chrome特定版本下进行测试,显然compositionstart、compositionend并不是一个兼容所有浏览器的方案。包括jQuery的“input”事件都是内部做了一堆兼容性处理的。假如这个需求是要兼容所有主流浏览器的话就真跪了,虽然这个迟早有一天会变成残酷的现实。

    所以呢,探索还将继续:是否有兼容所有主流浏览器的方案,求路过的兄弟们支招。

    本文代码示例参见附件

  • 相关阅读:
    CSS3—— 2D转换 3D转换 过渡 动画
    CSS3——边框 圆角 背景 渐变 文本效果
    CSS3——表单 计数器 网页布局 应用实例
    CSS3——提示工具 图片廓 图像透明 图像拼接技术 媒体类型 属性选择器
    CSS3——对齐 组合选择符 伪类 伪元素 导航栏 下拉菜单
    CSS3——分组和嵌套 尺寸 display显示 position定位 overflow float浮动
    CSS3——盒子模型 border(边框) 轮廓(outline)属性 margin外边距 padding填充
    Eclipse连接数据库报错Local variable passwd defined in an enclosing scope must be final or effectively final
    数据库——单表查询
    数据库——添加,修改,删除
  • 原文地址:https://www.cnblogs.com/chyingp/p/3599641.html
Copyright © 2011-2022 走看看