zoukankan      html  css  js  c++  java
  • jquery plugin 之 form表单验证插件

    基于h5表单验证系统、扩展了对easyui组件的支持

    先上图:

      提示样式用到了伪对象的 {content: attr(xxx)}函数方法,实现提示信息能动态切换。

    1、关键属性说明:

      type: 表单元素类型(h5的input类型:number、email等),
      max: type为number、range时可用的属性,
      min: type为number、range时可用的属性,
      pattern: 正则表达式,
      maxLength: 元素最大长度,
      placeholder: 输入域的填写提示,
      required: 必填
      required-msg: 为空时的校验提示,
      invalid-msg: 正则校验不通过的提示(对应pattern的校验规则)

    2、demo - html:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="UTF-8">
        <title>javascript test</title>
        <link rel="stylesheet" type="text/css" href="css/metro/easyui.css">
        <link rel="stylesheet" type="text/css" href="css/icon.css">
        <link rel="stylesheet" type="text/css" href="css/demo.css">
        <script type="text/javascript" src="js/jquery.min.js"></script>
        <script type="text/javascript" src="js/valid.js"></script>
        <script type="text/javascript" src="js/jquery.easyui.min.js"></script>
        <style>
        .hidden{
          display: none;
        }
    
        /* 表单校验样式 */
        .valid-item {
          display: inline-block;
          position: relative;
        }
        .valid-item:after {
          content: attr(data-msg);
          position: absolute;
          top: calc(100% + 2px);
          left: 0;
          color: #cc0066;
          font-size: 10px;
          opacity: 0;
          transition: opacity 0.5s ease;
          text-shadow: 1px 1px 5px silver;
          z-index: -1;
        }
        .valid-item.invalid:after {
          opacity: 1;
          z-index: 100;
        }
        </style>
    </head>
    
    <body>
      <div class="middle">
        <h5>
          <pre>
            表单校验:$(form).cform('valid');
          </pre>
          <pre>
            表单提交:$(form).cform('submit',fn);
          </pre>
        </h5>
    
        <form class="easyui-cform" action="index.do" method="post">
          <h5>第一种纯容器模式:根据type生成对应的表单元素</h5>
          <span class="valid-item" name="name" invalid-msg="字母、数字,以字母开头且最少3位" type="text" maxLength="4"
                value="sr" required pattern="^[a-zA-Z_][a-zA-Z0-9_@.]{2,16}$" placeholder="字母、数字">
            <!-- <input id="name" type="text" name="name" value="sc" required pattern="^[a-zA-Z_][a-zA-Z0-9_]{2,16}$" placeholder="字母、数字" class="ignore"/> -->
          </span>
          <br>
          <br>
          <h5>第二种非纯容器模式:子节点已经包含表单元素,将不再生成新的表单元素,子节点按h5的表单属性配置</h5>
          <span class="valid-item" required-msg="必填项">
            <select name="sex" required style=" 170px;">
              <option value="">--select--</option>
              <option value="1">man</option>
              <option value="2">women</option>
            </select>
          </span>
          <h5>非纯容器模式:easyui-numberbox组件解析</h5>
          <span class="valid-item" required-msg="数字必填项">
            <input class="easyui-numberbox" name="phone" required style=" 170px;">
          </span>
          <h5>非纯容器模式:easyui-combobox组件解析</h5>
          <span class="valid-item" name="country" required-msg="必填项">
            <input id="cc" class="easyui-combobox" required data-options="
                                                              valueField: 'label',
                                                              textField: 'value',
                                                              data: [{
                                                                  label: '',
                                                                  value: 'select'
                                                              },{
                                                                  label: 'java',
                                                                  value: 'Java'
                                                              },{
                                                                  label: 'perl',
                                                                  value: 'Perl'
                                                              },{
                                                                  label: 'ruby',
                                                                  value: 'Ruby'
                                                              }
                                                          ]" />
          </span>
          <input type="submit" value="submit">
        </form>
      </div>
    </body>
    </html>
    View Code

    3、valid.js:

    function easyuiInvalidProcess(item, value) {
      item.parentNode.classList.add('invalid');
      var $pnode = $(item.parentNode),
        requiredMsg = $pnode.attr('required-msg') || $.fn.cform.defaults.required,
        invalidMsg = $pnode.attr('invalid-msg') || $.fn.cform.defaults.invalid;
      if (value) {
        item.parentNode.classList.remove('invalid');
        $pnode.attr('data-msg', '');
      } else $pnode.attr('data-msg', requiredMsg);
    }
    (function($) {
      function _initItem(form) { /* 初始化校验容器 */
        var ctns = $('.valid-item', form).not('.hasparsed');
        ctns.each(function(index, item) {
          var $item = $(item),
            props = {
              id: $item.prop('id') ? $item.prop('id') + '_input' : undefined,
              name: $item.attr('name'),
              value: $item.attr('value'),
              type: $item.attr('type') || 'text',
              max: $item.attr('max'),
              min: $item.attr('min'),
              pattern: $item.attr('pattern'),
              maxLength: $item.attr('maxLength'),
              placeholder: $item.attr('placeholder'),
              required: $item.attr('required') || $item.attr('required')
            },
            propstr = ' ';
          $.each(props, function(key, value) {
            if (value) propstr += key + '=' + value + ' ';
          });
          var itemChilds = $item.children(),
            noChild = itemChilds.length == 0;
          if (noChild) { /* 校验容器如果没有子节点则生成type对应的表单元素 */
            var $input = $('<input ' + propstr + '/>');
            $(this).append($input);
            item.removeAttribute('name');
          } else {
            itemChilds.each(function(n, child) {
              var isEasyui = $(child).prop('class').indexOf('easyui-') >=
                0;
              if (isEasyui) { /* easyui组件初始化 */
                $.each(props, function(key, value) {
                  if (value) $(child).attr(key, value);
                });
                $(child).addClass('ignore');
                item.removeAttribute('name');
                var options = $(child).data('options') || '';
                if (options) {
                  options +=
                    ',onChange:function(val,oval){ easyuiInvalidProcess(this, val); }';
                } else {
                  options +=
                    'onChange:function(val,oval){ easyuiInvalidProcess(this, val); }';
                }
                $(child).attr('data-options', options);
                /* 解决报错:An invalid form control with name='' is not focusable */
                $(child).removeAttr('required');
              }
            });
          }
          ctns.addClass('hasparsed');
        });
      }
    
      function itemInvalidProcess(item) {
        item.setCustomValidity(' ');
        item.parentNode.classList.add('invalid');
        var $pnode = $(item.parentNode),
          requiredMsg = $pnode.attr('required-msg') || $.fn.cform.defaults.required,
          invalidMsg = $pnode.attr('invalid-msg') || $.fn.cform.defaults.invalid;
        if (item.validity.valueMissing) $pnode.attr('data-msg', requiredMsg);
        else $pnode.attr('data-msg', invalidMsg);
      }
    
      function _initValid(form, op) { /* 初始化form及表单元素 */
        if (form) {
          bindEvent(form);
          _initItem(form);
          var inputs = $(':input', form).not('.ignore');
          inputs.map(function(index, item) {
            var $input = $(item);
            item.addEventListener('invalid', function() {
              itemInvalidProcess(this);
            });
            item.addEventListener('input', function() {
              this.setCustomValidity('');
              this.parentNode.classList.remove('invalid');
              if (!this.validity.valid) { /* this.validity h5表单元素的校验结果对象 */
                itemInvalidProcess(this);
              }
            });
          });
    
          form.addEventListener('submit', function() { /* 校验通过时执行 */
            console.log(123);
          });
        };
      }
    
      function bindEvent(form) { /* 关掉浏览器默认行为 */
        var $form = $(form);
        $form.data('submit', form.submit);
        form.submit = function(event) {
          var valid = validCheck(form);
          if (valid) $form.data('submit').call(form);
        };
        $form.on("invalid", "form", function(event) {
          event.preventDefault();
        });
        $form.on("click", "input[type=submit]", function(event) {
          var valid = validCheck(form);
          if (!valid) event.preventDefault();
        });
      }
    
      function validCheck(form) { /* 检查校验是否通过 */
        var inputs = $(':input', form),
          valid = true;
        inputs.map(function(index, item) {
          var iCls = $(item).prop('class');
          if (item.type != "submit" && !item.checkValidity() && iCls.indexOf(
              'ignore') < 0) {
            valid = false;
          } else if (iCls.indexOf('textbox-value') >= 0) {
            /* 扩展easyui组件支持 */
            var domCtn = $('[textboxname="' + $(item).attr('name') + '"]'),
              clist = domCtn[0].classList;
            $.each(clist, function(n, cls) {
              try {
                var pName = cls.replace('easyui-', ''),
                  value = domCtn[pName]('getValue');
                if (value) {
    
                } else valid = false;
                easyuiInvalidProcess(domCtn[0], value);
              } catch (e) {}
            });
          }
        });
        return valid;
      }
    
      $.fn.cform = function(options, param) {
        /* 判断是否为对外调用API */
        if (typeof options == 'string') {
          return $.fn.cform.methods[options](this, param);
        }
        /* 初始化组件 */
        var op = $.extend({}, $.fn.cform.defaults, options);
        return this.each(function() {
          _initValid(this, op)
        });
      }
      $.fn.cform.methods = {
        valid: function(form, param) {
          var $inputs = $(':input', form) || [];
          for (var i = 0; i < $inputs.length; i++) {
            var input = $inputs[i];
            if (input.type != "submit" && !input.validity.valid) {
              input.checkValidity();
              return false;
            }
          }
          return true;
        },
        submit: function(form, fn) {
          return form.each(function() {
            var url = form.prop('action'),
              dataType = 'json';
            var valid = validCheck(form);
            if (valid) {
              try {
                var param = $(form).serializeJson();
                $.post(url, param, function(data) {
                  try {
                    if (typeof fn == 'function') fn(data);
                  } catch (e) {}
                }, dataType);
              } catch (e) {}
            }
          });
        }
      }
      $.fn.cform.defaults = {
        required: 'field required !',
        invalid: 'field invalid !'
      }
    })(jQuery)
    View Code

    4、easyui-parser改动处:

    $.parser = {
        auto: true,
        onComplete: function(_1) {},
        plugins: ["draggable", "droppable", "resizable", "pagination",
          "tooltip", "linkbutton", "menu", "menubutton", "splitbutton",
          "cform", /* 为了让组件自动解析 */
          "switchbutton", "progressbar", "tree", "textbox", "filebox",
          "combo", "combobox", "combotree", "combogrid", "numberbox",
          "validatebox", "searchbox", "spinner", "numberspinner",
          "timespinner", "datetimespinner", "calendar", "datebox",
          "datetimebox", "slider", "layout", "panel", "datagrid",
          "propertygrid", "treegrid", "datalist", "tabs", "accordion",
          "window", "dialog", "form"
        ],
  • 相关阅读:
    实践是检验真理的唯一标准——《精益创业实战》让你的成功飞起来
    蛇年谈程序员发展之路
    蛇年,你使用Python语言编程了吗?
    由《30天自制操作系统》引发的漫画创作
    《七周七语言:理解多种编程范型》书评整理
    精益创业实战
    一本为程序员量身打造的面试逻辑题宝典——《程序员面试逻辑题解析》
    从1.5k到18k, 一个程序员的5年成长之路
    Comparator and Comparable及Collections and Collection的用法和区别
    线程同步
  • 原文地址:https://www.cnblogs.com/xtreme/p/8442257.html
Copyright © 2011-2022 走看看