easyform表单校验插件改版源码

改动特性:

   1.支持回调,可用于ajax提交

   2.提示框样式修改,原版太丑,修改成bootstrap的popover  样式

原版还存在缺陷:被校验的表单元素设置不灵活,还得加上id、name 什么的,建议设置个data-id等属性,有时间再改,效果和jquery-validate差不多,气泡效果提示

效果图:

具体代码作用不做阐述,如有类似需求,请私信。主要源码如下:

(1)easyform.css文件

.easy-black{color:rgba(238,238,238,1);background-color:rgba(75,75,75,0.8);}
.easy-blue{color:rgba(255,255,255,1);background-color:rgba(51,153,204,0.8);}
.easy-red{color:rgba(255,255,255,1);background-color:rgba(255,102,102,0.9);}

.easy-white{color:#ff3636;background-color:rgba(255,255,255,0.9)}

.popover {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1060;
    display: none;
    max-width: 276px;
    padding: 1px;
    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
    font-size: 14px;
    font-style: normal;
    font-weight: 400;
    line-height: 1.42857143;
    text-align: left;
    text-align: start;
    text-decoration: none;
    text-shadow: none;
    text-transform: none;
    letter-spacing: normal;
    word-break: normal;
    word-spacing: normal;
    word-wrap: normal;
    white-space: normal;
    background-color: #fff;
    -webkit-background-clip: padding-box;
    background-clip: padding-box;
    border: 1px solid #ccc;
    border: 1px solid rgba(0,0,0,.2);
    border-radius: 6px;
    -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
    box-shadow: 0 5px 10px rgba(0,0,0,.2);
    line-break: auto;
}
/***提示框***/
.popover>.arrow {
    border-width: 11px;
}
.popover>.arrow, .popover>.arrow:after {
    position: absolute;
    display: block;
    width: 0;
    height: 0;
    border-color: transparent;
    border-style: solid;
}
.popover>.arrow:after {
    content: "";
    border-width: 10px;
}
.popover-content {
    padding: 9px 14px;
}
.fade.in {
    opacity: 1;
}
.fade {
    opacity: 0;
    -webkit-transition: opacity .15s linear;
    -o-transition: opacity .15s linear;
    transition: opacity .15s linear;
}
/**右边位置的提示框**/
.popover.right {
    margin-left: 10px;
}
.popover.right>.arrow {
    top: 50%;
    left: -11px;
    margin-top: -11px;
    border-right-color: #999;
    border-right-color: rgba(0,0,0,.25);
    border-left-width: 0;
}
.popover.right>.arrow:after {
    bottom: -10px;
    left: 1px;
    content: " ";
    border-right-color: #fff;
    border-left-width: 0;
}
/***********TODO://下面三个位置的样式需要结合easyform脚本文件调一下******************/
/**左边位置的提示框**/
.popover.left {
    margin-left: -10px;
}
.popover.left>.arrow {
    top: 50%;
    right: -11px;
    margin-top: -11px;
    border-right-width: 0;
    border-left-color: #999;
    border-left-color: rgba(0,0,0,.25);
}
.popover.left>.arrow:after {
    right: 1px;
    bottom: -10px;
    content: " ";
    border-right-width: 0;
    border-left-color: #fff;
}
/**上边位置的提示框**/
.popover.top {
    margin-top: -10px;
}
.popover.top>.arrow {
    bottom: -11px;
    left: 50%;
    margin-left: -11px;
    border-top-color: #999;
    border-top-color: rgba(0,0,0,.25);
    border-bottom-width: 0;
}
.popover.top>.arrow:after {
    bottom: 1px;
    margin-left: -10px;
    content: " ";
    border-top-color: #fff;
    border-bottom-width: 0;
}
/**下边位置的提示框**/
.popover.bottom {
    margin-top: 10px;
}
.popover.bottom>.arrow {
    top: -11px;
    left: 50%;
    margin-left: -11px;
    border-top-width: 0;
    border-bottom-color: #999;
    border-bottom-color: rgba(0,0,0,.25);
}
.popover.bottom>.arrow:after {
    top: 1px;
    margin-left: -10px;
    content: " ";
    border-top-width: 0;
    border-bottom-color: #fff;
}

(2)easyform.js 脚本文件

/*
 * 表单验证插件 easyform
 * 2014-11-5
 * 用于表单验证
 * 只要在需要验证的控件上添加easyform属性即可,多个属性用[;]连接,语法类似css
 * 属性列表:
 *      null
 *      email
 *      char-normal         英文、数字、下划线
 *      char-chinese        中文、英文、数字、下划线、中文标点符号
 *      char-english        英文、数字、下划线、英文标点符号
 *      length:1 10 / length:4      能够识别汉字等宽字符长度
 *      equal:xxx                               等于某个对象的值,冒号后是jq选择器语法
 *      ajax:fun()
 *      real-time                               实时检查
 *      date                    2014-10-31
 *      time                    10:30:00
 *      datetime            2014-10-31 10:30:00
 *      money               正数,两位小数
 *      uint :1 100                 正整数 , 参数为起始值和最大值
 *      number              不限长度的数字字符串
 *      float:7 2
 *      regex:"^(\\d{4})-(\\d{2})-(\\d{2})$"
 *      mobile              手机
 * */
/**
 * 读取一个控件的指定data属性,并通过:和;来分割成key/value值对
 * @id string 控件id
 * @name string 属性名称
 **/
if (typeof(easy_load_options) == "undefined") {
    // function easy_load_options(id, name) // # by galandeo, fix bug
    function easy_load_options(obj, name)
    {
        var options = $(obj).data(name);
        // var options = $("#" + id).data(name);

        //将字符串用;分割
        options = (!!options ? options.split(";") : undefined);

        var data = Object();

        if (!!options) {
            var index;
            for (index in options) {
                var temps = options[index];
                var p = temps.indexOf(":");

                var temp = [];
                if (-1 == p) {
                    temp[0] = temps;
                    temp[1] = "";
                }
                else {
                    temp[0] = temps.substring(0, p);
                    temp[1] = temps.substring(p + 1);
                }

                if (temp[0].length > 0) {
                    data[temp[0]] = temp[1];
                }
            }
        }

        return data;
    }
}

//easyform
(function ($, window, document, undefined)
{
    /*
     构造函数
     **/
    var _easyform = function (ele, opt)
    {
        this.form = ele;

        this.id = Math.random();

        if (0 == this.form.length && "form" != this.form[0].localName) {
            throw new Error("easyform need a form !");
        }

        this.defaults = {
            easytip: true,   //是否显示easytip,可以关闭后,使用自定义的提示信息
            success: null,
            error: null,
            complete: null,
            per_validation: null
        };

        this.options = $.extend({}, this.defaults, opt);


        this.is_submit = true;  //是否提交,如果为false,即使验证成功也不会执行提交

        //事件定义
        this.success = this.options.success;
        this.error = this.options.error;
        this.complete = this.options.complete;
        this.callback = this.options.callback;//所有验证成功的回调 用于ajax提交,默认表单提交
        this.per_validation = this.options.per_validation;     //在所有验证之前执行

        this._check_back = null;
    };

    //方法
    _easyform.prototype = {

        init: function ()
        {
            this.inputs = [];
            this.counter_success = [];   //已经判断成功的input计数
            this.counter = [];                   //已经判断的input计数

            var $this = this;
            $this._load();

            //改写 submit 的属性,便于控制
            this.submit_button = this.form.find("input:submit");
            this.submit_button.each(function ()
                {
                    var button = $(this);
                    button.attr("type", "button");

                    //提交前判断
                    button.click(function ()
                        {
                            $this.submit(true);
                        }
                    );
                }
            );

            return this;
        },

        _load: function (iterator)
        {
            if (!iterator) {
                iterator = "input:visible, textarea:visible";
            }

            for (var i in this.inputs) {
                this.inputs[i].destructor();
            }

            //析构旧的easyinput,防止real-time条件下的重复验证。
            this._array_empty(this.inputs);

            var $this = this;

            this.form.find(iterator).each(function (index, input)
                {
                    //排除 hidden、button、submit、file
                    if (input.type != "hidden" && input.type != "button" && input.type != "submit"
                        && input.type != "file") {
                        if (input.type == "radio" || input.type == "checkbox") {
                            var name = input.name;

                            for (index in  $this.inputs) {
                                if (name == $this.inputs[index].input[0].name) {
                                    return;
                                }
                            }
                        }

                        var checker = $(input).easyinput({easytip: $this.options.easytip});

                        checker.error = function (e, r)
                        {
                            $this.is_submit = false;
                            //$this.result.push(e);

                            if (!!$this.error)    //失败事件
                            {
                                $this.error($this, e, r);
                            }
                        };

                        checker.complete = function (e)
                        {
                            //记录已经完成检查的input
                            $this._array_add_unique($this.counter, (!!e.id ? e.id : e.name));

                            if ($this.counter.length == $this.inputs.length) {
                                //$this._array_empty($this.counter_success);
                                //$this._array_empty($this.counter);

                                if (!!$this.complete)    //结束事件
                                {
                                    $this.complete($this);
                                }

                                if (!!$this._check_back) {
                                    $this._check_back($this._is_success());
                                    $this._check_back = null;
                                }
                            }
                        };

                        checker.success = function (e)
                        {
                            //记录检查成功的控件
                            $this._array_add_unique($this.counter_success, (!!e.id ? e.id : e.name));

                            if ($this._is_success()) {
                                //$this._array_empty($this.counter_success);
                                //$this._array_empty($this.counter);

                                if (!!$this.success)    //成功事件
                                {
                                    $this.success($this);
                                }

                                if (!!$this.is_submit) {
                                     if($this.callback && $.isFunction($this.callback)){
                                        $this.callback();
                                        return false;
                                    }
                                    $this.form.submit()
                                }
                            }
                        };

                        $this.inputs.push(checker);
                    }
                }
            );
        },

        _is_success: function ()
        {
            return this.inputs.length == this.counter_success.length;
        },

        _array_empty: function (arr)
        {
            arr.splice(0, arr.length);
        },

        _array_add_unique: function (arr, value)
        {
            if (-1 == arr.indexOf(value)) {
                arr.push(value);
            }
        },

        _check: function (submit)
        {
            this._array_empty(this.counter_success);
            this._array_empty(this.counter);

            this.is_submit = submit;

            //执行per_validation事件
            if (!!this.per_validation) {
                this.is_submit = this.per_validation(this);
            }

            //如果没有需要判断的控件
            if (this.inputs.length == 0) {
                if (!!this.success)    //成功事件
                {
                    this.success(this);
                }

                if (!!this.complete)    //结束事件
                {
                    this.complete(this);
                }

                if (this.is_submit) {
                     if(this.callback && $.isFunction(this.callback)){
                        this.callback();
                        return false;
                    }
                    this.form.submit()
                }
            }

            var index;
            for (index in this.inputs) {
                this.inputs[index].validation(false);
            }
        },

        /*
         * 表单提交函数
         * @submit:bool值,用于定义是否真的提交表单
         * */
        submit: function (submit)
        {
            this._load();           //重新载入控件

            this._check(submit);        //验证并提交
        },

        check: function (iterator, fun)
        {
            this._check_back = fun;

            this._load(iterator);       //重新载入控件

            this._check(false);        //验证不提交
        },

        show: function (iterator, msg)
        {
            if (!iterator) {
                iterator = "input:visible, textarea:visible";
            }

            this.form.find(iterator).each(function (index, input)
                {
                    if (input.type != "hidden" && input.type != "button" && input.type != "submit"
                        && input.type != "file") {
                        $(this).easytip().show(msg);
                    }
                }
            );
        }
    };

    //添加到jquery
    $.fn.easyform = function (options)
    {
        var validation = new _easyform(this, options);

        return validation.init();
    };

})(jQuery, window, document);

//easyinput
(function ($, window, document, undefined)
{
    //单个input的检查器构造函数
    var _easyinput = function (input, opt)
    {
        if (0 == input.length) {
            throw new Error("easyform need a input object !");
        }

        this.input = input;     //绑定的控件
        this.rules = [];            //规则

        //事件
        this.error = null;
        this.success = null;
        this.complete = null;

        this.defaults = {
            "easytip": true,   //是否显示easytip
            "real-time": false
        };

        this.tip = null;    //关联的tip

        //读取 data-easyform属性
        // this.rules = easy_load_options(input[0].id, "easyform"); // # by galandeo, fix bug
        this.rules = easy_load_options(input[0], "easyform");

        //处理data-easyform中的配置属性
        var o = Object();
        for (var index in this.rules) {
            if (index == "easytip") {
                o["easytip"] = this.rules[index];
            }
            else if (index == "real-time") {
                o["real-time"] = true;
            }
        }

        delete this.rules["easytip"];
        delete this.rules["real-time"];

        this.options = $.extend({}, this.defaults, opt, o);

        this.counter_success = 0;   //计数器,记录已经有多少个条件成功
        this.counter = 0;                   //计数器,记录已经验证了多少条件

        this.is_error = false;      //错误标志
    };

    //单个input的检查器
    _easyinput.prototype = {

        init: function ()
        {
            //初始化easytip
            if (true === this.options.easytip) {
                this.tip = $(this.input).easytip();
            }

            var $this = this;

            //是否实时检查
            if (!!this.rules && this.options["real-time"]) {
                this.input.on("blur", function ()
                    {
                        $this.validation(true);
                    }
                );
            }

            return this;
        },

        /**
         * 规则判断
         * */
        validation: function (real_time)
        {
            this.value = this.input.val();
            this.counter_success = 0;   //计数器清零
            this.counter = 0;
            this.is_error = false;

            if (this.input.attr("type") == "radio" || this.input.attr("type") == "checkbox") {
                var name = this.input.attr("name");

                var v = $('input[name="' + name + '"]:checked').val();

                if (false == this._null(this, v, this.rules, {"realtime": real_time})) {
                    if (false == this.is_error) {
                        this._success({"realtime": real_time});
                    }
                }
            }
            else if (false == this._null(this, this.value, this.rules, {"realtime": real_time})) {
                delete this.rules.null;

                for (var index in this.rules) {
                    if (index == undefined) {
                        continue;
                    }
                    //调用条件函数
                    if (!!this.judge[index]) {
                        this.judge[index](this, this.value, this.rules[index], {"realtime": real_time});
                    }
                }
            }
        },

        show: function (msg)
        {
            this.tip.show(msg);
        },

        _error: function (rule, option)
        {
            this.counter++;

            if (!!this.error) {
                this.error(this.input[0], rule);
            }

            $(this.input).trigger("easyform-error", [this.input, rule]);

            if (!option.realtime && !!this.complete && this.counter == Object.keys(this.rules).length) {
                this.complete(this.input[0]);
            }

            if (false == this.is_error) {
                var msg = $(this.input).data("message-" + rule);

                if (!msg) {
                    msg = $(this.input).data("message");
                }

                msg = !msg ? "格式错误" : msg;

                if (true === this.options.easytip) {
                    this.tip.show(msg);
                }

                this.is_error = true;
            }

            return false;
        },

        _success: function (option)
        {
            if (!!this.success) {
                $(this.input).trigger("easyform-success", [this.input]);
                this.success(this.input[0]);
            }

            if (!option.realtime && !!this.complete) {
                this.complete(this.input[0]);
            }

            return true;
        },

        _success_rule: function (rule, option)
        {
            this.counter++;
            this.counter_success++;

            $(this.input).trigger("easyform-success-" + rule, [this.input]);

            if (!option.realtime && this.counter_success == Object.keys(this.rules).length) {
                this._success(option);
            }

            return true;
        },

        _null: function (ei, v, r, o)
        {
            if (!v) {
                //rule不为空并且含有null
                if (!!r && typeof(r["null"]) != "undefined") {
                    if (false == o.realtime) {
                        return ei._success(o);
                    }
                    else {
                        return true;
                    }
                }
                else {
                    return ei._error("null", o);
                }
            }
            //当控件没有规则,或者只有一个null规则
            else if (Object.keys(r).length == 0 || (Object.keys(r).length == 1 && typeof(r["null"]) != "undefined")) {
                if (!o.realtime && !!this.complete) {
                    this.complete(this.input[0]);
                }

                if (!!v) {
                    return ei._success(o);
                }

                return false;
            }
            else {
                return false;
            }
        },

        /*
         * 按照各种rule进行判断的函数数组
         * 通过对judge添加成员函数,可以扩充规则
         * */
        judge: {
            "char-normal": function (ei, v, p, o)
            {
                if (false == /^\w+$/.test(v)) {
                    return ei._error("char-normal", o);
                }
                else {
                    return ei._success_rule("char-normal", o);
                }
            },

            "char-chinese": function (ei, v, p, o)
            {
                if (false == /^([\w]|[\u4e00-\u9fa5]|[ 。,、?¥“”‘’!:【】《》()——.,?!$'":+-])+$/.test(v)) {
                    return ei._error("char-chinese", o);
                }
                else {
                    return ei._success_rule("char-chinese", o);
                }
            },

            "char-english": function (ei, v, p, o)
            {
                if (false == /^([\w]|[ .,?!$'":+-])+$/.test(v)) {
                    return ei._error("char-english", o);
                }
                else {
                    return ei._success_rule("char-english", o);
                }
            },

            "email": function (ei, v, p, o)
            {
                if (false == /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(v)) {
                    return ei._error("email", o);
                }
                else {
                    return ei._success_rule("email", o);
                }
            },

            "mobile": function (ei, v, p, o)
            {
                if (false == /^(0|86|17951)?(1)(3[0-9]|4[0-9]|5[0-9]|7[0-9]|8[0-9])[0-9]{8}$/.test(v)) {
                    return ei._error("mobile", o);
                }
                else {
                    return ei._success_rule("mobile", o);
                }
            },

            "length": function (ei, v, p, o)
            {
                var range = p.split(" ");

                //如果长度设置为 length:6 这样的格式
                if (range.length == 1) {
                    range[1] = range[0];
                }

                var len = v.replace(/[^\x00-\xff]/g, "aa").length;

                if (len < range[0] || len > range[1]) {
                    return ei._error("length", o);
                }
                else {
                    return ei._success_rule("length", o);
                }
            },

            "idcard": function (ei, v, p, o)
            {
                /*
                 * 身份证15位编码规则:dddddd yymmdd xx p
                 * dddddd:6位地区编码
                 * yymmdd: 出生年(两位年)月日,如:910215
                 * xx: 顺序编码,系统产生,无法确定
                 * p: 性别,奇数为男,偶数为女
                 *
                 * 身份证18位编码规则:dddddd yyyymmdd xxx y
                 * dddddd:6位地区编码
                 * yyyymmdd: 出生年(四位年)月日,如:19910215
                 * xxx:顺序编码,系统产生,无法确定,奇数为男,偶数为女
                 * y: 校验码,该位数值可通过前17位计算获得
                 *
                 * 前17位号码加权因子为 Wi = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ]
                 * 验证位 Y = [ 1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2 ]
                 * 如果验证码恰好是10,为了保证身份证是十八位,那么第十八位将用X来代替
                 * 校验位计算公式:Y_P = mod( ∑(Ai×Wi),11 )
                 * i为身份证号码1...17 位; Y_P为校验码Y所在校验码数组位置
                 */

                //15位和18位身份证号码的正则表达式
                var reg = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/;

                //如果通过该验证,说明身份证格式正确,但准确性还需计算
                if (reg.test(v)) {
                    if (v.length == 18) {
                        var idCardWi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; //将前17位加权因子保存在数组里
                        var idCardY = [1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2]; //这是除以11后,可能产生的11位余数、验证码,也保存成数组
                        var idCardWiSum = 0; //用来保存前17位各自乖以加权因子后的总和
                        for (var i = 0; i < 17; i++) {
                            idCardWiSum += v.substring(i, i + 1) * idCardWi[i];
                        }

                        var idCardMod = idCardWiSum % 11;//计算出校验码所在数组的位置
                        var idCardLast = v.substring(17);//得到最后一位身份证号码

                        //如果等于2,则说明校验码是10,身份证号码最后一位应该是X
                        if (idCardMod == 2) {
                            if (idCardLast == "X" || idCardLast == "x") {
                                return ei._success_rule("idcard", o);
                            }
                            else {
                                return ei._error("idcard", o);
                            }
                        }
                        else {
                            //用计算出的验证码与最后一位身份证号码匹配,如果一致,说明通过,否则是无效的身份证号码
                            if (idCardLast == idCardY[idCardMod]) {
                                return ei._success_rule("idcard", o);
                            }
                            else {
                                return ei._error("idcard", o);
                            }
                        }
                    }
                }
                else {
                    return ei._error("idcard", o);
                }
            },

            "equal": function (ei, v, p, o)
            {
                var pair = $(p);
                if (0 == pair.length || pair.val() != v) {
                    return ei._error("equal", o);
                }
                else {
                    return ei._success_rule("equal", o);
                }
            },

            "ajax": function (ei, v, p, o)
            {
                // 为ajax处理注册自定义事件
                // HTML中执行相关的AJAX时,需要发送事件 easyform-ajax 来通知 easyinput
                // 该事件只有一个bool参数,easyinput 会根据这个值判断ajax验证是否成功
                ei.input.delegate("", "easyform-ajax", function (e, p)
                    {
                        ei.input.unbind("easyform-ajax");

                        if (false == p) {
                            return ei._error("ajax", o);
                        }
                        else {
                            return ei._success_rule("ajax", o);
                        }
                    }
                );

                eval(p);
            },

            "date": function (ei, v, p, o)
            {
                if (false == /^(\d{4})-(\d{2})-(\d{2})$/.test(v)) {
                    return ei._error("date", o);
                }
                else {
                    //Modify by Martin 2016/06/13
                    return ei._success_rule("date", o);
                    //Modify end

                    //return ei._success_rule("date");
                }
            },

            "time": function (ei, v, p, o)
            {
                if (false == /^(\d{2}):(\d{2}):(\d{2})$/.test(v)) {
                    return ei._error("time", o);
                }
                else {
                    return ei._success_rule("time", o);
                }
            },

            "datetime": function (ei, v, p, o)
            {
                if (false == /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/.test(v)) {
                    return ei._error("datetime", o);
                }
                else {
                    return ei._success_rule("datetime", o);
                }
            },

            "money": function (ei, v, p, o)
            {
                if (false == /^([1-9][\d]{0,10}|0)(\.[\d]{1,2})?$/.test(v)) {
                    return ei._error("money", o);
                }
                else {
                    return ei._success_rule("money", o);
                }
            },

            "number": function (ei, v, p, o)
            {
                if (false == /^\d{1,}$/.test(v)) {
                    return ei._error("number", o);
                }
                else {
                    return ei._success_rule("number", o);
                }
            },

            "float": function (ei, v, p, o)
            {
                var range = p.split(" ");

                //如果长度设置为 float:6 这样的格式
                //必须定义整数和小数的位数
                if (range.length != 2) {
                    return ei._error("float", o);
                }
                else if (range[0] + range[1] > 16) {
                    console.warn("您的" + ei.input.id + "float规则配置可能不正确!请保证整数位数+小数位数 < 16");
                }

                var pattern = new RegExp("^([1-9][\\d]{0," + range[0] + "}|0)(\\.[\\d]{1," + range[1] + "})?$");

                if (false == pattern.test(v)) {
                    return ei._error("float", o);
                }
                else {
                    return ei._success_rule("float", o);
                }
            },

            "uint": function (ei, v, p, o)
            {
                v = parseInt(v);

                var range = p.trim().split(" ");

                if ("" == p.trim()) {
                    console.warn("您的" + ei.input.id + "uint规则,没有设置值域!");
                    range[0] = 0;
                }

                if (range.length == 1) {
                    range[1] = 999999999999999;
                }

                range[0] = parseInt(range[0]);
                range[1] = parseInt(range[1]);

                if (isNaN(v) || isNaN(range[0]) || isNaN(range[1]) || v < range[0] || v > range[1] || v < 0) {
                    return ei._error("uint", o);
                }
                else {
                    return ei._success_rule("uint", o);
                }
            },

            "regex": function (ei, v, p, o)
            {
                var pattern = new RegExp(p);

                if (false == pattern.test(v)) {
                    return ei._error("regex", o);
                }
                else {
                    return ei._success_rule("regex", o);
                }
            },
             "empty": function (ei, v, p, o)
            {
                if (v.length == 0) {
                    return ei._error("empty", o);
                }
                else {
                    return ei._success_rule("empty", o);
                }
            }
        },

        destructor: function ()
        {
            //重置事件
            this.error = null;
            this.success = null;

            //解除实时验证
            this.input.off("blur");

            delete this;
        }
    };

    $.fn.easyinput = function (options)
    {
        var check = new _easyinput(this, options);

        return check.init();
    };

})(jQuery, window, document);

//easytip
(function ($, window, document, undefined)
{
    var _easytip = function (ele, opt)
    {
        this.parent = ele;
        this.is_show = false;

        if (0 == this.parent.length) {
            throw new Error("easytip's is null !");
        }

        this.defaults = {
            left: 0,
            top: 0,
            position: "right",          //top, left, bottom, right
            disappear: "other",           //self, other, lost-focus, none, N seconds, out
            speed: "fast",
            class: "easy-white",
            arrow: "bottom",              //top, left, bottom, right 自动,手动配置无效
            onshow: null,               //事件
            onclose: null,               //事件
            hover_show: "false"            //鼠标移动到绑定目标时,是否自动出现
        };

        this._fun_cache = Object();    //响应函数缓存,用来保存show里面自动添加的click函数,以便于后面的unbind针对性的一个一个删除

        //从控件的 data-easytip中读取配置信息
        // var data = easy_load_options(ele[0].id, "easytip"); // # by galandeo, fix bug
        var data = easy_load_options(ele[0], "easytip");

        this.options = $.extend({}, this.defaults, opt, data);

        this.id = "easytip-div-main-" + ele[0].id;
    };

    _easytip.prototype = {

        init: function ()
        {
            var tip = $("#" + this.id);

            var $this = this;

            //同一个控件不会多次初始化。
            if (tip.length == 0) {
                $(document.body).append("<div class='popover fade in' id=\"" + this.id + "\"><div class=\"popover-content\"></div></div>");

                tip = $("#" + this.id);
                var text = $("#" + this.id + " .popover-content");

                tip.css({
                        "text-align": "left",
                        "display": "none",
                        "position": "absolute",
                        "z-index": 9000
                    }
                );

                tip.append("<div class=\"arrow\"></div>");
                var arrow = $("#" + this.id + " .arrow");
//              arrow.css({
//                      "padding": "0",
//                      "margin": "0",
//                      "width": "0",
//                      "height": "0",
//                      "position": "absolute",
//                      "border": "10px solid"
//                  }
//              );

                if (this.options.hover_show == "true") {
                    this.options.disappear = "none";
                    this.options.speed = 1;
                    this.parent.hover(function ()
                        {
                            $this.show();
                        }, function ()
                        {
                            $this.close();
                        }
                    );
                }
            }

            return this;
        },

        _size: function ()
        {
            var parent = this.parent;
            var tip = $("#" + this.id);

            if (tip.width() > 300) {
                tip.width(300);
            }
        },

        _css: function ()
        {
            var tip = $("#" + this.id);
            var text = $("#" + this.id + " .popover-content");
            var arrow = $("#" + this.id + " .arrow");

            text.addClass(this.options.class);

            //arrow.css("border-color", "transparent transparent transparent transparent");
            //tip.css("box-sizing", "content-box");
        },

        _arrow: function ()
        {
            var tip = $("#" + this.id);
            var text = $("#" + this.id + " .popover-content");
            var arrow = $("#" + this.id + " .arrow");

            switch (this.options.arrow) {
                case "top":
                    arrow.css({
                            "left": "25px",
                            "top": -arrow.outerHeight(),
                            "border-bottom-color": '#999'
                        }
                    );
                    break;

                case "left":
                    arrow.css({
                            "left": -arrow.outerWidth(),
                            "top":"50%",
                            //"top": tip.innerHeight() / 2 - arrow.outerHeight() / 2
                            "border-right-color": '#999'
                        }
                    );
                    break;

                case "bottom":
                    arrow.css({
                            "left": "25px",
                            "top": tip.innerHeight(),
                            "border-top-color":  '#999'
                        }
                    );
                    break;

                case "right":
                    arrow.css({
                            "left": tip.outerWidth(),
                            "top":"50%",
//                          "top": tip.innerHeight() / 2 - arrow.outerHeight() / 2,
                            "border-left-color": '#999'
                        }
                    );
                    break;
            }
        },

        _position: function ()
        {
            var tip = $("#" + this.id);
            var text = $("#" + this.id + " .popover-content");
            var arrow = $("#" + this.id + " .arrow");
            var offset = $(this.parent).offset();
            var size = {
                width: $(this.parent).outerWidth(),
                height: $(this.parent).outerHeight()
            };

            switch (this.options.position) {
                case "top":

                    //tip.css("left", offset.left - this.padding);
                    tip.addClass('top');
                    tip.css("left", offset.left);
                    tip.css("top", offset.top - tip.outerHeight() - arrow.outerHeight() / 2);
                    this.options.arrow = "bottom";

                    break;

                case "left":
                    tip.addClass('left');
                    tip.css("left", offset.left - tip.outerWidth() - arrow.outerWidth() / 2);
                    tip.css("top", offset.top - (tip.outerHeight() - size.height) / 2);
                    this.options.arrow = "right";

                    break;

                case "bottom":
                    tip.addClass('bottom');
                    //tip.css("left", offset.left - this.padding);
                    tip.css("left", offset.left);
                    tip.css("top", offset.top + size.height + arrow.outerHeight() / 2);
                    this.options.arrow = "top";

                    break;

                case "right":
                    tip.addClass('right');
                    tip.css("left", offset.left + size.width + arrow.outerWidth() / 2);
                    tip.css("top", offset.top - (tip.outerHeight() - size.height) / 2);
                    this.options.arrow = "left";

                    break;
            }

            var left = parseInt(tip.css("left"));
            var top = parseInt(tip.css("top"));

            tip.css("left", parseInt(this.options.left) + left);
            tip.css("top", parseInt(this.options.top) + top);
        },

        close: function (fn)
        {
            var tip = $("#" + this.id);
            var parent = this.parent;
            var onclose = this.options.onclose;
            this.is_show = false;

            //onclose事件
            if (!!onclose) {
                onclose(parent, tip[0]);
            }

            tip.fadeOut(this.options.speed, fn);
        },

        _show: function ()
        {
            var tip = $("#" + this.id);
            var text = $("#" + this.id + " .popover-content");
            var arrow = $("#" + this.id + " .arrow");
            var speed = this.options.speed;
            var disappear = this.options.disappear;
            var parent = this.parent;
            var $this = this;
            this.is_show = true;

            if (this.options.hover_show == "true") {
                tip.show();
                return;
            }

            tip.fadeIn(speed, function ()
                {
                    if (!isNaN(disappear)) {
                        //如果disappear是数字,则倒计时disappear毫秒后消失
                        setTimeout(function ()
                            {
                                $this.close();

                            }, disappear
                        );
                    }
                    else if (disappear == "self" || disappear == "other") {
                        $(document).bind('click', $this._fun_cache[tip[0].id] = function (e)
                            {
                                if (disappear == "self" && e.target == text[0]) {
                                    $this.close(function ()
                                        {
                                            $(document).unbind("click", $this._fun_cache[tip[0].id]);
                                        }
                                    );

                                }
                                else if (disappear == "other" && e.target != tip[0]) {
                                    $this.close(function ()
                                        {
                                            $(document).unbind("click", $this._fun_cache[tip[0].id]);
                                        }
                                    );
                                }
                            }
                        );
                    }
                    else if (disappear == "lost-focus") {
                        $(parent).focusout(function ()
                            {
                                $this.close(function ()
                                    {
                                        $(parent).unbind("focusout");
                                    }
                                );
                            }
                        );
                    }

                }
            );
        },

        show: function (msg)
        {
            var tip = $("#" + this.id);
            var text = $("#" + this.id + " .popover-content");
            var arrow = $("#" + this.id + " .arrow");
            var speed = this.options.speed;
            var disappear = this.options.disappear;
            var parent = this.parent;
            var $this = this;
            var onshow = this.options.onshow;

            if (!msg) {
                msg = parent.data("easytip-message");
            }

            text.html(msg);

            this._size();
            this._css();
            this._position();
            this._arrow();

            if ("none" == tip.css("display")) {
                //onshow事件
                if (!!onshow) {
                    onshow(parent, tip[0]);
                }
                $this._show();
            }
            else {
                tip.hide(1, function ()
                    {
                        if (!!onshow) {
                            onshow(parent, tip[0]);
                        }

                        $this._show();
                    }
                );
            }
        }
    };

    $.fn.easytip = function (options)
    {
        var tip = new _easytip(this, options);

        return tip.init();
    };

})(jQuery, window, document);

 

posted @ 2017-09-20 13:58  创业男生  阅读(665)  评论(0编辑  收藏  举报