• 简约的form表单校验插件


    前言

    网上有好多form表单校验插件,包括jquery的表单检验插件,这些中好多插件功能很齐全强大,提示方式很酷,很美观好看。本想拿来用,但是发现几个问题:

      1、使用不方便。校验规则繁多,调用校验函数难记忆。

      2、提示方式固定。一般插件给出固定的几种提示方式,但是实际中,不同系统都有自己的页面风格样式,有自己的提示方式,插件自带的一般用不上。

    因此,我最终没有采用这些插件,以免用后出现难以修改或实现的情况。

    如果一种校验插件能避免以上两个问题最好了,方便使用,提示方式自定义 ,所以自己做了一个简单的校验器,希望能慢慢完善。

    正文

    先来一个DEMO

    1、html:

    <ul id="form">
        <li>
            <span class="name-col">姓名:</span>
            <span class="value-col">
                <input type="text" name="username" minLength="5" maxLength="20" required afterFunc="showTip"></input>
            </span>
        </li>
        <li>
            <span class="name-col">年龄:</span>
            <span class="value-col">
                <input type="text" vtype="number" min="18" max="40" step="1" name="age" onEvent="keyup" beforeFunc="modify" afterFunc="showTip"></input>
            </span>
        </li>
        <li>
            <span class="name-col">电话:</span>
            <span class="value-col">
                <input type="text" name="phone" pattern="^(0[0-9]{2,3}-)?[2-9][0-9]{6,7}(-[0-9]{1,4})?$" afterFunc="showTip"></input>
            </span>
        </li>
        <li>
            <span class="name-col">性别:</span>
            <span class="value-col">
                <input type="radio" name="sex" checked /><input type="radio" name="sex" /></span>
        </li>
        <li>
            <span class="name-col">爱好:</span>
            <span class="value-col">
                <input type="checkbox" name="love" value="1" />爬山
                <input type="checkbox" name="love" value="2" />游泳
                <input type="checkbox" name="love" value="3" />音乐
                <input type="checkbox" name="love" value="4" />读书
            </span>
        </li>
        <li>
            <span class="name-col">自我描述:</span>
            <span class="value-col">
                <textarea name="description"  minLength="10" maxLength="20" afterFunc="showTip"></textarea>
            </span>
        </li>
        <li>
            <button onclick="validate()" >validate</button>
            <button onclick="disabd()">disabled</button>
        </li>
    </ul>

    2、js调用方法:

    $(function(){
        $("#form").validateInit();
    });
    
    var modify = function(source){
        source.val(source.val().replace(/[^0-9]+/g,''));
    };
    
    var validate = function(){
        var res = $("#form").validate();
        alert(res.valid);
    };
    
    var showTip = function(e){
        var res = e.getVresult();
        if(res && res.valid == false){
            e.next().remove();
            e.after('<span>'+res.errorType+'</span>');
        }else{
            e.next().remove();
        }
    };
    
    var disabd = function(){
        $("#form").disableValidate();
    }

     说明:

      1、 校验规则添加到表单元素的属性上,属性使用类似html5的表单校验。

        <input type="text" name="username" minLength="5" maxLength="20" required afterFunc="showTip"></input>

        <input type="text" vtype="number" min="18" max="40" step="1" name="age" onEvent="keyup" beforeFunc="modify" afterFunc="showTip"></input>

      以上input的例子:vtype="number"说明为number类型,min=18,max=40,step=1,这些规则可代码就可以知道是什么意思。

      2、js校验调用:

         页面初始化时:$("#form").validateInit();

         校验时调用:$("#form").validate();

         这里$("#form")可以是单个表单元素(input)可以是容器(form)。

     使用很简单方便吧。

    具体说明:

    1、表单元素上的校验属性:

      pattern:自定义正则表达式,这个很好用,以至于不想写下面的vtype其他种类了。

      vtype:校验类型 有number,email,tel。还有待添加。

      min: vtype为number时的最小值

      max:vtype为number时的最大值

      step: vtype为number时,增加步长。

      minLength:字符串最小长度

      maxLength:字符串最大长度

      required: 必填项

      beforeFunc:校验前调用函数,传递参数为对象本身。

      afterFunc:校验完成后调用函数,传递参数为对象本身。

      onEvent: 将校验函数绑定到的事件。

    2、插件方法:

      validateInit 校验初始化--该方法会根据表单元素的属性,进行相应的校验函数绑定到blur事件上, 
      disableValidate 禁用校验--去掉校验事件,去掉校验结果
      validate 校验--立即校验,结果保存saveVresult(),可以用getVresult().valid查看是否通过校验。
      isFormElement 是否为表单元素--
      vattr 校验属性的获取和设置
      getVresult 获取校验结果
      saveVresult 保存校验结果

      这七个方法都在表单元素上。如$('div[name='form']').validate()则是校验div里面的所有表单元素。$('input[name='username']')则校验本身。

    校验器代码:

    /**
     * form 表单校验器
     * 使用规则仿照html5表单验证情况。
     * @author jokinliu@163.com
     * @date 2014-08-05
     * @version V2.0
     */
    (function($){
        /**
         * 表单校验添加jquery插件方法,方法简介如下:
         * 1、validateInit    校验初始化
         * 2、disableValidate    禁用校验    
         * 3、validate    校验
         * 4、isFormElement    是否为表单元素
         * 5、vattr    校验属性的获取和设置
         * 6、getVresult 获取校验结果
         * 7、saveVresult 保存校验结果
         */
        $.fn.extend({
            /*********************************************************************************
             * 初始化校验 绑定校验事件
             * validityObj: 校验选项,可选,如果设置了该选项,往后的校验就以该选项的值为主
             * validityObj = {
             *         vtype:    校验类型
             *         pattern: 校验正则表达式
             *         max: vtype为number是的最大值
             *         min: vtype为number是的最小值
             *         maxLength:非number是字符串的最大长度
             *         minLength:非number是字符串的最小长度
             *         step:vtype为number是的step
             *         onEvent:
             *         beforeFunc: func1,    //校验前的执行方法,该方法接受对象本身参数$(this)。
             *         afterFunc: func2,    //校验后的执行方法,该方法接受对象本身参数$(this)。
             * }
             *********************************************************************************/
            validateInit: function(validityObj){
                if($(this).isFormElement()){
                    $(this).data('vresult','');
                    event.onEvent($(this), validityObj);
                }
                else{
                    $(this).find(constants.formElements.join(',')).each(function(){
                        $(this).data('vresult','');
                        event.onEvent($(this), validityObj);
                    });
                }
            },
            /******************************************
             * disabled校验功能
             * 取消本对象上的校验相关
             * 1、取消绑定校验事件。
             * 2、取消校验结果,设置不可用标识$(this).data('vresult','disabled');
             ******************************************/
            disableValidate: function(){
                if($(this).isFormElement()){
                    event.offEvent($(this));
                    $(this).data('vresult','disabled');
                }
                else{
                    $(this).find(constants.formElements.join(',')).each(function(){
                        event.offEvent($(this));
                        $(this).data('vresult','disabled');
                    });
                }
                return $(this);
            },
            /*********************************************************************************
             * 校验方法,开始校验
             * validityObj: 校验选项,可选,如果设置了该选项,往后的校验就以该选项的值为主
             * validityObj = {
             *         vtype:    校验类型
             *         pattern: 校验正则表达式
             *         max: vtype为number是的最大值
             *         min: vtype为number是的最小值
             *         maxLength:非number是字符串的最大长度
             *         minLength:非number是字符串的最小长度
             *         step:vtype为number是的step
             *         onEvent:
             *         beforeFunc: func1,    //校验前的执行方法,该方法接受对象本身参数$(this)。
             *         afterFunc: func2,    //校验后的执行方法,该方法接受对象本身参数$(this)。
             * }
             *********************************************************************************/
            validate: function(validityObj){
                if($(this).isFormElement()){
                    if(validityObj){
                        for(var attr in validityObj){
                            validityObj[attr] && source.vattr(attr, validityObj[attr]);
                        }
                    }
                    return event.validate('', $(this));
                }
                else{
                    var result = true;
                    $(this).find(constants.formElements.join(',')).each(function(){
                        var res = event.validate('', $(this));
                        if(res && res.valid == false) result = false;
                    });
                    return {valid:result};
                }
            },
            /*********************************************
             * 是否为表单元素
             * 判断当前对象的tagName是否为INPUT,TEXTEREA等。
             *********************************************/
            isFormElement: function(){
                var tag = $(this)[0].tagName;
                for(var i=0; i<constants.formElements.length; i++){
                    if(tag == constants.formElements[i]){
                        return true;
                    }
                }
                return false;
            },
            /********************************************************************
             * 校验属性的获取和设置
             * 将属性取出放置到data('validator')中
             *******************************************************************/
            vattr: function(attr, val){
                !$(this).data('validator') && $(this).data('validator',{});
                var data = $(this).data('validator');
                if(val && (val+'').trim() != ''){
                    data[attr] = val;
                    return $(this); 
                }
                if(!data[attr]){
                    var attrVal = $(this).attr(attr);
                    if(attrVal && attrVal.trim() != ''){
                        if(attr == 'beforeFunc' || attr == 'afterFunc'){
                            data[attr] = eval("("+attrVal.trim()+")");
                        }else{
                            data[attr] = attrVal.trim();
                        }
                    }
                }
                return data[attr]; 
            },
            /*****************************************************************
             * 获取校验结果,从data('vresult')中
             * 校验完成时,结果存储在当前对象的 $(this).data('vresult')中;
             * 结果对象为htmL5校验结果对象,并添加几个其他
             * result = {
             *    badInput: false,
             *     customError: false,
             *    errorType: "typeMismatch",      //错误类型,记录值为true的属性到这里。
             *    patternMismatch: false,
             *    rangeOverflow: false,
             *    rangeUnderflow: false,
             *    stepMismatch: false,
             *    tooLong: false,
             *    typeMismatch: true,
             *    valid: false,
             *    valueMissing: false
             * }
             *****************************************************************/
            getVresult: function(){
                return $(this).data('vresult');
            },
            /*****************************************************************
             * 保存校验结果,到data('vresult')中
             * 校验完成时,结果存储在当前对象的 $(this).data('vresult')中;
             * 结果对象为htmL5校验结果对象,并添加几个其他
             * result = {
             *    badInput: false,
             *     customError: false,
             *    errorType: "typeMismatch",      //错误类型,记录值为true的属性到这里。
             *    patternMismatch: false,
             *    rangeOverflow: false,
             *    rangeUnderflow: false,
             *    stepMismatch: false,
             *    tooLong: false,
             *    typeMismatch: true,
             *    valid: false,
             *    valueMissing: false
             * }
             *****************************************************************/
            saveVresult: function(result){
                var result = $.extend({},$(this)[0].validity, result);
                for(var attr in result){
                    if(attr != "valid" && result[attr] == true){
                        result.valid = false;
                        result.errorType = attr;
                        break;
                    }
                }
                $(this).data('vresult', result);
                return $(this);
            }
        });
        
        /******************************************
         * jquery对象方法调用的事件函数
         * 主要函数有:
         * 1、validate    校验
         * 2、onEvent    添加事件
         * 3、offEvent    取消事件
         **************************************/
        var event = {
            validate: function(event, source){
                source = !source ? event.data.source : source;
                if(source.data('vresult')=='disabled') return;    //disabed used .disabedvalidate()
                //do beforeFunc
                source.vattr('beforeFunc') instanceof Function && source.vattr('beforeFunc')(source);
                //do validate
                source.saveVresult(validator.validate(source));
                //do afterFunc
                source.vattr('afterFunc') instanceof Function && source.vattr('afterFunc')(source);
                return source.getVresult();
            },
            onEvent: function(source, validityObj){
                if(validityObj){
                    for(var attr in validityObj)
                        validityObj[attr] && source.vattr(attr, validityObj[attr]);
                }
                source.vattr('onEvent') && source.on(source.vattr('onEvent'), {source:source}, this.validate);
                source.on('blur', {source:source}, this.validate);
            },
            offEvent: function(source){
                source.off(event, this.validate);
                source.off('blur', this.validate);
            }
        };
        
        //常量
        var constants = {
            formElements: ['INPUT','TEXTAREA']
        };
        
        var validator = {
            empty: function(value){
                return !value || value.trim() == '';
            },
            number: function(value){
                if(this.empty(value)) return true;
                return /^-?[1-9]d*(.d+)?$/.test(value);
            },
            min: function(value, min){
                if(this.empty(value)) return true;
                return value*1>=min;
            },
            max: function(value, max){
                if(this.empty(value)) return true;
                return value*1<=max;
            },
            step: function(value, step, min){
                if(this.empty(value)) return true;
                min = this.number(min)?min*1:0;
                return (value*1-min)/step*1%1===0;
            },
            tel: function(value){
                if(this.empty(value)) return true;
                var reg = /^(0[0-9]{2,3}-)?[2-9][0-9]{6,7}(-[0-9]{1,4})?$/;
                return reg.test(value.trim());
            },
            mobile: function(value){
                if(this.empty(value)) return true;
                var reg = /^1[3-8]d{9}$/;
                return reg.test(value.trim());
            },
            email: function(value){
                if(this.empty(value)) return true;
                var reg = /^.{2,}@.{2,}$/;
                return reg.test(value.trim());
            },
            pattern: function(value, regExp){
                if(this.empty(value)) return true;
                return RegExp(regExp).test(value);
            },
            validate: function(source){
                if(!source.vattr('vtype')
                        && !source.vattr('pattern')
                        && !source.vattr('minLength')
                        && !source.vattr('maxLength'))
                    return;
                var vtype = source.vattr('vtype')?source.vattr('vtype'):source.vattr('type');
                var val = source.val().trim();
                source.val(val); 
                //required validate
                if(source.vattr("required") == 'required' && validator.empty(val)){
                    return {valueMissing:true};
                }
                //vtype validate
                if(vtype == 'number'){
                    if(!validator.number(val)) return {typeMismatch:true};
                    if(source.vattr('min') && !isNaN(source.vattr('min')*1)){
                        if(!validator.min(val, source.vattr('min')*1)) return {rangeUnderflow:true};
                    }
                    if(source.vattr('max') && !isNaN(source.vattr('max')*1)){
                        if(!validator.max(val, source.vattr('max')*1)) return {rangeOverflow:true};
                    }
                    if(source.vattr('step') && !isNaN(source.vattr('step')*1)){
                        if(!validator.step(val,source.vattr('step'),source.vattr('min'))) return {stepMismatch:true};
                    }
                }else{
                    if(vtype == 'email'){
                        if(!validator.email(val)) return {typeMismatch:true};
                    }else if(vtype == 'tel'){
                        if(!validator.tel(val)) return {typeMismatch:true};
                    }else if(vtype == 'url'){
                        if(!validator.url(val)) return {typeMismatch:true};
                    }
                    if(!validator.empty(val)){
                        if(source.vattr('minLength') && !isNaN(source.vattr('minLength')*1)){
                            if(val.length < source.vattr('minLength')*1) return {tooShort:true};
                        }
                        if(source.vattr('maxLength') && !isNaN(source.vattr('maxLength')*1)){
                            if(val.length > source.vattr('maxLength')*1) return {tooLong:true};
                        }
                    }
                }
                //pattern validate
                if(source.vattr('pattern') && source.vattr('pattern').trim() != ''){
                    if(!validator.pattern(val, source.vattr('pattern'))) return {patternMismatch:true};
                }
            }
        };
        /**
         * String trim
         */
        String.prototype.trim = function(){
            return this.replace(/(^s*)|(s*$)/g, '');
        };
        String.prototype.leftTrim = function(){
            return this.replace(/^s*/g, '');
        };
        String.prototype.rightTrim = function(){
            return this.replace(/s*$/g, '');
        };
    })(jQuery);

      

      

  • 相关阅读:
    leetcode 763 划分字母区间
    leetcode 392 判断子序列
    Leetcode 665 修改一个数成为非递减数组 (Easy)
    leetcode 605 种花问题 贪心算法
    leetcode 452 用最少数量的箭引爆气球 贪心算法
    leetcode 455 分发饼干 贪心算法
    delphi中的 CLX Application
    delphi 之DCOM应用服务器定义函数
    SqlServer 之 sp_executesql系统存储过程的介绍和使用
    delphi 之调用WinSock的API获取本机的机器名称和IP地址
  • 原文地址:https://www.cnblogs.com/liuqingsha3/p/3895803.html
Copyright © 2020-2023  润新知