文本框背景分段显示

文本框背景分段显示功能在web开发中用得不是很多。我见过的只是在部分网上银行输入银行卡号的时候,有过这个效果。输入4位数字后,后面4位数字的背景变成灰色,接着又回到前面4位数字的背景,以此类推。主要是帮助用户快速区分连串的字符,从而核对输入的信息是否正确。当然这类功能应用范围就比较窄了,一般来说,输入的信息需要具备一定的统一格式(字符类型)和长度的情况下使用会起到提供用户体验的效果,反之则有点画蛇添足了。比如银行卡号,和身份证号就是比较常见的适合这一要求的字段。



刚刚上线的项目中正好需要实现这样的功能。并且有两种情况,一个是身份证号代表出生日期的部分需要显示不同的背景颜色,另一个是车架号,发动机号每4位背景颜色改变。为了代码重用和扩展性,决定开发一个插件,通过config来实现类似的个性化功能。

    目前,我所见过的类似功能都是使用背景图片来实现的。使用背景图片有几个不足的地方,比如针对每个特定的案例需要制作特定的图片、当文本框中有中文,英文数字甚至特殊符号的时候,这个方案就失效了。既然使用图片达不到要求,就得换一种思路。

    经过一番思考后,我终于找到了一种可行的方案:在文本框的底层添加几个span标签来充当分段背景的容器,文本框的分段背景转化为span标签的背景。通过js获取用户输入字符,并且按配置取得每段的字符,将他们写入每段对应的span,并将span里的文本颜色设置为span的背景色,从而隐藏文本。这样就能实现用户输入字符,实时显示背景。有了方案当然就开始实现,由于项目中使用了jQuery控件库,自然这个文本框分段背景就是基于jQuery的,也可以说是jQuery的一个插件。下面贴出代码,由于项目匆忙,没有优化代码,代码中较详细的注释,不再多说。



/*
 * 文本框分段显示背景功能插件
 * write by wangtao719@2009-12-16:基本实现功能
 * update by wangtao719@2009-12-28:增加还原文本框到原生状态功能,修复重复设置导致的问题
 * TODO:优化插件代码结构
 * 
 * 都是可选参数,默认配置是按照pa18直通车项目的文本框来设置
 * options={
 *      length : number,--文本框允许的输入长度,默认24
 *      step : number,--每段的个数,默认4
 *      firstIndex : number,--设定某段背景不同的开始元素的索引,默认0
 *      lastIndex : number,--设定某段背景不同的结束元素的索引,默认0,
 *                           如果firstIndex和lastIndex都为0,则采用length和step,
 *                           否则采用firstIndex和lastIndex
 *      oddColor : "#ffffff",--奇数段的背景颜色,默认#ffffff
 *      evenColor : "#dddddd",--偶数段的背景颜色,默认#dddddd
 *      fontSize : "0px",--文本框里的字体大小,默认12px
 *      height : "0px",--背景整体高度,默认24px
 *      width : "0px",--背景整体宽度,默认130px
 *      padding : "0px 0px 0px 0px", --背景整体的padding,默认0px 0px 0px 0px
 *      expandStyle : ""--背景整体的其它样式,用来跨浏览器
 *      revert : true|false--true时,还原设置的文本框恢复到原生状态
 * }
 * example:$(obj).partition(options);--to use 
 *         $(obj).partition({revert:true});-- revert input to native status
 */
(function($){
    $.fn.partition = function(options){
        var defaults = {//默认参数,根据pa18直通项目配置
            length : 24,
            step : 4,
            firstIndex : 0,
            lastIndex : 0,
            oddColor : "#fff",
            evenColor : "#ddd",
            fontSize : "12px",
            height : "24px",
            width : "129px",
            padding : "0px 0px 0px 0px",
            expandStyle : "",
            revert : false
        };
        this.opts = $.extend(defaults,options);
        if(this.opts.revert == true){//增加还原文本框到原生状态
            return this.each(function(){
                $this = $(this);
                $this.replaceAll('#partition_'+$this[0].id);//还原文本框就是删除生成的dom
                $this.css("position","static");
            });
        }
        var _opts = this.opts;
        var type = _opts.firstIndex+_opts.lastIndex>0?1:2;//判断是根据步长显示背景还是设定index显示背景
        
        //构建必须的dom,设置文本框和相应dom的样式
        function render(o,opts){
            var _opts = opts;
            o.css({
                position : "absolute",
                top : "1px",
                left : 0,
                "font-size" : _opts.fontSize,
                background : "none",
                //"z-index" : 1,
                "font-family":"Arial"
            });

            o.wrap('<div class="partition-background" id="partition_'+o[0].id+'" style="position:relative;padding:'+_opts.padding+';overflow:hidden;width:'+_opts.width+';border:0;height:'+_opts.height+';'+_opts.expandStyle+'"></div>');

            var _new = $("#partition_"+o[0].id);
            //创建span的个数
            var num = type==1 ? 3 : Math.ceil(_opts.length/_opts.step);
            var c = [];
            var color = '';
            for(var i=0;num>i;num--){//循环创建span标签,设置背景色,和span里文本颜色
                color = num%2==0?_opts.evenColor:_opts.oddColor;
                _new.prepend('<span class="partitions" wrapper="partition_'+o[0].id+'" index="'+num+'" style="font-size:'+_opts.fontSize+';font-family:Arial;background:'+color+';color:'+color+';height:'+_opts.height+';line-height:'+_opts.height+';border:0;"></span>');
            }
        }
        //输入框文本发生变化时触发的回调函数
        function bindFn(events){
            _this = events.target?events.target:window.event.srcElement;//获取事件发生的对象,即文本框

            var _opts = events.data;//获取传递进来的参数
            
            var w = [];//存放准备放入span标签的文本的数组
            var v = _this.value.length==0?[]:_this.value.split('');//文本框的值
            var type = _opts.firstIndex+_opts.lastIndex>0 ? 1 : 2;
            //根据类型来获得分段数量,type==1时,固定为3段,否则通过计算得出
            var n = type == 2 ? Math.ceil(_this.value.length/_opts.step) : 3;
            //type==1时,存放准备放入span标签的文本数组
            var temp = [v.slice(0,_opts.firstIndex).join(''),v.slice(_opts.firstIndex,_opts.lastIndex).join(''),v.slice(_opts.lastIndex).join('')];
            //首先清空所有span里的文本
            $("#partition_"+_this.id).find("span").each(function(){this.innerHTML = '';});
            //循环放入分段文本
            for(var i=0;i<n;i++){
                if(type == 2){
                    $($("#partition_"+_this.id).find("span").get(i)).html(v.slice(i*_opts.step,(i+1)*_opts.step).join(''));
                }else{
                    $($("#partition_"+_this.id).find("span").get(i)).html(temp[i]);
                }
            }
        }

        return this.each(function(event){
            $this = $(this);
            $this.replaceAll('#partition_'+$this[0].id);//先移除上次生成的dom,解决重复设置引起的bug
            render($this,_opts);//构建必须的标签
            if($.browser.msie){//通过浏览器绑定事件
                $this.bind("propertychange",_opts,bindFn);
            }else{
                $this.bind("input",_opts,bindFn);
            }
            $this.bind("blur",_opts,bindFn);//因为pa18项目的车架号等离开焦点会将文本内容转换为大写,宽度需要重新改变
            $this.blur();//动态为文本框添加partition功能时,自动显示出效果
        });
    }
    
})(jQuery);

你可能感兴趣的:(jquery,css,浏览器)