当前位置: 移动技术网 > IT编程>网页制作>Html5 > Html5用户注册自动校验

Html5用户注册自动校验

2018年11月01日  | 移动技术网IT编程  | 我要评论

566665小游戏,搜狗音乐mp3,医学导航

抽时间写了一个带有自动校验功能的html5用户注册demo。使用到handlebars模板技术和手机验证码校验。

以下是效果截图:

\

1.页面代码:usersregister.hbs
 

<!doctype html>
<!--[if ie 8 ]> <html lang="en" class="ie8"> <![endif]-->
<!--[if ie 9 ]> <html lang="en" class="ie9"> <![endif]-->
<!--[if (gt ie 9)|!(ie)]><!-->
<html lang="en">
<!--<![endif]-->
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge" />
    <title>用户注册</title>

    <!--[if lt ie 9]>
    <script src="/assets/scripts/html5shiv.js"></script>
    <![endif]-->

    <link href="/assets/styles/jquery.idealforms.min.css" rel="stylesheet" media="screen" />

    <style type="text/css">
        body {
            font: normal 15px/1.5 arial, helvetica, free sans, sans-serif;
            color: #222;
            overflow-y: scroll;
            padding: 60px 0 0 0;
        }

        .main {
            width: 560px;
            height: 480px;
            margin: -50px auto;
        }

        #my-form {
            width: 560px;
            height: 450px;
            margin: 0 auto;
            border: 1px solid #ccc;
            padding: 3em;
            border-radius: 3px;
            box-shadow: 0 0 2px rgba(0, 0, 0, .2);
        }
    </style>

    <script type="text/javascript" src="/assets/scripts/jquery-1.8.2.min.js"></script>
    <script type="text/javascript" src="/assets/scripts/jquery.idealforms.js"></script>
</head>

<body>
<!-- style="background-image: url(static/image/bg.jpg) -->
    <p class="main" >
        <p style="height:5px;text-align:center;font-size:25px"> 欢迎您注册!</p>
        <!-- begin form -->
        <form id="my-form" class="myform">
            <p>
                <label>用户名:</label><input id="username" name="username" type="text" />
            </p>
            <p>
                <!-- <label>密码:</label><input id="pass" name="password" type="password" /> -->
                <label>密码:</label><input id="pass" name="password" type="text" />
            </p>
            <p>
                <label>邮箱:</label><input id="email" name="email"
                                         data-ideal="required email" type="email" />
            </p>
            <p>
                <label>电话:</label><input id="telephone" type="text" name="phone" data-ideal="phone" />
            </p>
            <p>
                <label>供应商v码:</label><input id="vcode" type="text" name="vcode" data-ideal="vcode" />
            </p>
            <p>
                <label>真实姓名:</label><input id="truename" type="text" name="truename" data-ideal="truename" />
            </p>
            <p>
                <label>手机验证码:</label><input id="telcode" type="text" name="telcode" data-ideal="telcode" />
            </p>
            <p style="margin-bottom:5px;">
                <button id="gettelcode" type="button" style="margin-left:160px; margin-right:auto;" >获取手机校验码</button>
                <hr style="margin-top:5px; margin-bottom:5px;" />
            </p>
            <!--<p>
                <label>性别:</label>
                <select id="sex" name="sex">
                    <option value="男">男</option>
                    <option value="女">女</option>
                </select>
            </p>
            <p>
                <label>昵称:</label><input id="nickname" type="text" name="nickname" data-ideal="nickname" />
            </p>
            <p>
                <label>年龄:</label><input id="age" type="text" name="age" data-ideal="age" />
            </p>-->
            <!-- <p>
                <label>地址:</label><input type="text" name="address" data-ideal="address" />
            </p>
            <p>
                <label>qq:</label><input type="text" name="qq" data-ideal="qq" />
            </p>
            <p>
                <label>邮编:</label><input type="text" name="zip" data-ideal="zip" />
            </p>
            <p>
                <label>传真:</label><input type="text" name="fax" data-ideal="fax" />
            </p>
            <p>
                <label>身份证:</label><input type="text" name="creditid" data-ideal="creditid" />
            </p>
            <p>
                <label>出生日期:</label><input name="date" class="datepicker"
                    data-ideal="date" type="text" placeholder="月/日/年" />
            </p>
            <p>
                <label>上传头像:</label><input id="file" name="file" multiple
                    type="file" />
            </p>
            <p>
                <label>个人主页:</label><input name="website" data-ideal="url"
                    type="text" />
            </p>
            <p>
                <label>备注:</label>
                <textarea id="comments" name="comments"></textarea>
            </p>
            -->
            <!-- <p id="languages">
                <label>语言:</label> <label><input type="checkbox"
                    name="langs[]" value="english" />英文</label> <label><input
                    type="checkbox" name="langs[]" value="chinese" />中文</label> <label><input
                    type="checkbox" name="langs[]" value="spanish" />西班牙文</label> <label><input
                    type="checkbox" name="langs[]" value="french" />法文</label>
            </p>
            <p>
                <label>精通几门:</label> <label><input type="radio"
                    name="radio" checked />1</label> <label><input type="radio"
                    name="radio" />2</label> <label><input type="radio" name="radio" />3</label>
                <label><input type="radio" name="radio" />4</label>
            </p>
            <p>
                <label>国籍:</label> <select id="states" name="states">
                    <option value="default">– 选择国籍 –</option>
                    <option value="al">阿拉伯</option>
                    <option value="ak">中国</option>
                    <option value="az">美国</option>
                    <option value="ar">法国</option>
                    <option value="ca">英国</option>
                    <option value="co">德国</option>
                    <option value="ct">西班牙</option>
                    <option value="de">俄罗斯</option>
                </select>
            </p> -->
            <p style="margin-top:10px; margin-left:100px;margin-right:100px;">
                <button type="button" id="submit" class="submit">提交</button>
                <button id="reset" type="button" >重置</button>
            </p>

        </form>
        <!-- end form -->
    </p>

<script type="text/javascript">
    var options = {

        onfail : function() {
            alert($myform.getinvalid().length + ' invalid fields.')
        },

        inputs : {
            'password' : {
                filters : 'required pass'
            },
            'username' : {
                filters : 'required username'
            },
            'email' : {
                filters : 'required email'
            },
            'phone' : {
                filters : 'required phone'
            },
            'truename' : {
                filters : 'required'
            },
            'vcode' : {
                filters : 'required'
            },
            'telcode' : {
                filters : 'required'
            }

            /*
            'age' : {
                filters : 'required digits',
                data : {
                   min : 16,
                   max : 70
                }
            },
            'file' : {
                filters : 'extension',
                data : {
                    extension : [ 'jpg' ]
                }
            },
            'comments' : {
                filters : 'min max',
                data : {
                    min : 50,
                    max : 200
                }
            },
            'states' : {
                filters : 'exclude',
                data : {
                    exclude : [ 'default' ]
                },
                errors : {
                    exclude : '选择国籍.'
                }
            },
            'langs[]' : {
                filters : 'min max',
                data : {
                    min : 2,
                    max : 3
                },
                errors : {
                    min : 'check at least <strong>2</strong> options.',
                    max : 'no more than <strong>3</strong> options allowed.'
                }
            }
            */
        }
    };

    $('#gettelcode').click(function() {
        var telephone = document.getelementbyid("telephone").value;   //手机号码
        if (telephone == null || telephone == ""){
            alert("手机号码不能为空!");
        }
        else{
            $.ajax({
                type : "get",
                datatype : "json",
                url : "../api/gettelcode?telephone="+ telephone,
                success : function(msg) {
                },
                error : function(e) {
                    alert("获取手机校验码失败!" + e);
                }
            });
        }
    });

    var $myform = $('#my-form').idealforms(options).data('idealforms');

    $('#submit').click(function() {
        var username = document.getelementbyid("username").value; //用户名
        var password = document.getelementbyid("pass").value;    //密码
        var email = document.getelementbyid("email").value;     //邮箱
        var telephone = document.getelementbyid("telephone").value;     //手机号码
        var vcode = document.getelementbyid("vcode").value;     //公司v码
        var telcode = document.getelementbyid("telcode").value;     //手机校验码
        var truename = document.getelementbyid("truename").value;     //真实姓名

        $.ajax({
            type : "get",
            url : "../api/usersregister?username="+ username +"&password="+ password +"&email="+ email +"&telephone="+ telephone +"&vcode="+ vcode +"&telcode="+ telcode +"&truename="+ truename,

            success : function(msg) {
               //获取当前网址,如: https://localhost:8083/uimcardprj/share/meun.jsp
               var curwwwpath = window.document.location.href;
               //获取主机地址之后的目录,如: uimcardprj/share/meun.jsp
               var pathname = window.document.location.pathname;
               var pos = curwwwpath.indexof(pathname);
               //获取主机地址,如: https://localhost:8083
               var localhostpaht = curwwwpath.substring(0, pos);
               //获取带"/"的项目名,如:/uimcardprj
               var projectname = pathname.substring(0, pathname.substr(1).indexof('/') + 1);
               window.location.href = projectname + "/login";
               alert("注册成功!");
            },
            error : function(e) {
                alert("注册失败!" + e);
            }
        });
    });

    $('#reset').click(function() {
        $myform.reset().fresh().focusfirst();
    });

</script>

</body>
</html>

 

2.jq输入校验:jquery.idealforms.js

 

该js校验初始版本来自cedric ruiz,我略有修改。

部分校验的规则如下:

  required: '此处是必填的.',
  number: '必须是数字.',
  digits: '必须是唯一的数字.',
  name: '必须至少有3个字符长,并且只能包含字母.',
  username: '用户名最短5位,最长30位,请使用英文字母、数字、中文和下划线. 用户名首字符必须为字母、数字、中文,不能为全数字.中文最长21个字.',
  pass: '密码的位数必须的在6-15位之间,并且至少包含一个数字,一个大写字母和一个小写字母.',
  strongpass: '必须至少为8个字符长,至少包含一个大写字母和一个小写字母和一个数字或特殊字符.',
  email: '必须是一个有效的email地址. (例: user@gmail.com)',
  phone: '必须是一个有效的手机号码. (例: 18723101212)'
以下是整个代码文件:
/*--------------------------------------------------------------------------

  jq-idealforms 2.1

  * author: cedric ruiz
  * license: gpl or mit
  * demo: https://elclanrs.github.com/jq-idealforms/
  *
--------------------------------------------------------------------------*/

;(function ( $, window, document, undefined ) {

  'use strict';

  // global ideal forms namespace
  $.idealforms = {}
  $.idealforms.filters = {}
  $.idealforms.errors = {}
  $.idealforms.flags = {}
  $.idealforms.ajaxrequests = {}

/*--------------------------------------------------------------------------*/

/**
 * @namespace a chest for various utils
 */
var utils = {
  /**
   * get width of widest element in the collection.
   * @memberof utils
   * @param {jquery object} $elms
   * @returns {number}
   */
  getmaxwidth: function( $elms ) {
    var maxwidth = 0
    $elms.each(function() {
      var width = $(this).outerwidth()
      if ( width > maxwidth ) {
        maxwidth = width
      }
    })
    return maxwidth
  },
  /**
   * hacky way of getting less variables
   * @memberof utils
   * @param {string} name the name of the less class.
   * @param {string} prop the css property where the data is stored.
   * @returns {number, string}
   */
  getlessvar: function( name, prop ) {
    var value = $('<p class="' + name + '"></p>').hide().appendto('body').css( prop )
    $('.' + name).remove()
    return ( /^\d+/.test( value ) ? parseint( value, 10 ) : value )
  },
  /**
   * like es5 object.keys
   */
  getkeys: function( obj ) {
    var keys = []
    for(var key in obj) {
      if ( obj.hasownproperty( key ) ) {
        keys.push( key )
      }
    }
    return keys
  },
  // get lenght of an object
  getobjsize: function( obj ) {
    var size = 0, key;
    for ( key in obj ) {
      if ( obj.hasownproperty( key ) ) {
        size++;
      }
    }
    return size;
  },
  isfunction: function( obj ) {
    return typeof obj === 'function'
  },
  isregex: function( obj ) {
    return obj instanceof regexp
  },
  isstring: function( obj ) {
    return typeof obj === 'string'
  },
  getbynameorid: function( str ) {
    var $el = $('[name="'+ str +'"]').length
      ? $('[name="'+ str +'"]') // by name
      : $('#'+ str) // by id
    return $el.length
      ? $el
      : $.error('the field "'+ str + '" doesn\'t exist.')
  },
  getfieldsfromarray: function( fields ) {
    var f = []
    for ( var i = 0, l = fields.length; i < l; i++ ) {
      f.push( utils.getbynameorid( fields[i] ).get(0) )
    }
    return $( f )
  },
  converttoarray: function( obj ) {
    return object.prototype.tostring.call( obj ) === '[object array]'
      ? obj : [ obj ]
  },
  /**
   * determine type of any ideal forms element
   * @param $input jquery $input object
   */
  getidealtype: function( $el ) {
    var type = $el.attr('type') || $el[0].tagname.tolowercase()
    return (
      /(text|password|email|number|search|url|tel|textarea)/.test( type ) && 'text' ||
      /file/.test( type ) && 'file' ||
      /select/.test( type ) && 'select' ||
      /(radio|checkbox)/.test( type ) && 'radiocheck' ||
      /(button|submit|reset)/.test( type ) && 'button' ||
      /h\d/.test( type ) && 'heading' ||
      /hr/.test( type ) && 'separator' ||
      /hidden/.test( type ) && 'hidden'
    )
  },
  /**
   * generates an input
   * @param name `name` attribute of the input
   * @param type `type` or `tagname` of the input
   */
  makeinput: function( name, value, type, list, placeholder ) {

    var markup, items = [], item, i, len

    function splitvalue( str ) {
      var item, value, arr
      if ( /::/.test( str ) ) {
        arr = str.split('::')
        item = arr[ 0 ]
        value = arr[ 1 ]
      } else {
        item = value = str
      }
      return { item: item, value: value }
    }

    // text & file
    if ( /^(text|password|email|number|search|url|tel|file|hidden)$/.test(type) )
      markup = '<input '+
        'type="'+ type +'" '+
        'id="'+ name +'" '+
        'name="'+ name +'" '+
        'value="'+ value +'" '+
        (placeholder && 'placeholder="'+ placeholder +'"') +
        '/>'

    // textarea
    if ( /textarea/.test( type ) ) {
      markup = '<textarea id="'+ name +'" name="'+ name +'" value="'+ value +'"></textarea>'
    }

    // select
    if ( /select/.test( type ) ) {
      items = []
      for ( i = 0, len = list.length; i < len; i++ ) {
        item = splitvalue( list[ i ] ).item
        value = splitvalue( list[ i ] ).value
        items.push('<option value="'+ value +'">'+ item +'</option>')
      }
      markup =
        '<select id="'+ name +'" name="'+ name +'">'+
          items.join('') +
        '</select>'
    }

    // radiocheck
    if ( /(radio|checkbox)/.test( type ) ) {
      items = []
      for ( i = 0, len = list.length; i < len; i++ ) {
        item = splitvalue( list[ i ] ).item
        value = splitvalue( list[ i ] ).value
        items.push(
          '<label>'+
            '<input type="'+ type +'" name="'+ name +'" value="'+ value +'" />'+
            item +
          '</label>'
        )
      }
      markup = items.join('')
    }

    return markup
  }
}

/**
 * custom tabs for ideal forms
 */
$.fn.idealtabs = function (container) {

  var

  // elements
  $contents = this,
  $container = container,
  $wrapper = $('<ul class="ideal-tabs-wrap"/>'),
  $tabs = (function () {
    var tabs = []
    $contents.each(function () {
      var name = $(this).attr('name')
      var html =
        '<li class="ideal-tabs-tab">'+
          '<span>' + name + '</span>'+
          '<i class="ideal-tabs-tab-counter ideal-tabs-tab-counter-zero">0</i>'+
        '</li>'
      tabs.push(html)
    })
    return $(tabs.join(''))
  }()),

  actions = {
    getcuridx: function () {
      return $tabs
        .filter('.ideal-tabs-tab-active')
        .index()
    },
    gettabidxbyname: function (name) {
      var re = new regexp(name, 'i')
      var $tab = $tabs.filter(function () {
        return re.test($(this).text())
      })
      return $tab.index()
    }
  },

  /**
   * public methods
   */
  methods = {
    /**
     * switch tab
     */
    switchtab: function (nameoridx) {

      var idx = utils.isstring(nameoridx)
        ? actions.gettabidxbyname(nameoridx)
        : nameoridx

      $tabs.removeclass('ideal-tabs-tab-active')
      $tabs.eq(idx).addclass('ideal-tabs-tab-active')
      $contents.hide().eq(idx).show()
    },

    nexttab: function () {
      var idx = actions.getcuridx() + 1
      idx > $tabs.length - 1
        ? methods.firsttab()
        : methods.switchtab(idx)
    },

    prevtab: function () {
      methods.switchtab(actions.getcuridx() - 1)
    },

    firsttab: function () {
      methods.switchtab(0)
    },

    lasttab: function () {
      methods.switchtab($tabs.length - 1)
    },

    updatecounter: function (nameoridx, text) {
      var idx = !isnan(nameoridx) ? nameoridx : actions.gettabidxbyname(name),
          $counter = $tabs.eq(idx).find('.ideal-tabs-tab-counter')
      $counter.removeclass('ideal-tabs-tab-counter-zero')
      if (!text) {
        $counter.addclass('ideal-tabs-tab-counter-zero')
      }
      $counter.html(text)
    }
  }

  // attach methods
  for (var m in methods)
    $contents[m] = methods[m]

  // init
  $tabs.first()
    .addclass('ideal-tabs-tab-active')
    .end()
    .click(function () {
      var name = $(this).text()
      $contents.switchtab(name)
    })

  // insert in dom & events
  $wrapper.append($tabs).appendto($container)

  $contents.addclass('ideal-tabs-content')
  $contents.each(function () {
    var $this = $(this), name = $(this).attr('name')
    $this.data('ideal-tabs-content-name', name)
      .removeattr('name')
  })
  $contents.hide().first().show() // start fresh

  return $contents

}

/**
 * a custom <select> menu jquery plugin
 * @example `$('select').idealselect()`
 */
$.fn.idealselect = function () {

  return this.each(function () {

    var

    $select = $(this),
    $options = $select.find('option')

    /**
     * generate markup and return elements of custom select
     * @memberof $.fn.tocustomselect
     * @returns {object} all elements of the new select replacement
     */
    var idealselect = (function () {
      var
      $wrap = $('<ul class="ideal-select '+ $select.attr('name') +'"/>'),
      $menu = $(
        '<li><span class="ideal-select-title">' +
          $options.filter(':selected').text() +
        '</span></li>'
      ),
      items = (function () {
        var items = []
        $options.each(function () {
          var $this = $(this)
          items.push('<li class="ideal-select-item">' + $this.text() + '</li>')
        })
        return items
      }())

      $menu.append('<ul class="ideal-select-sub">' + items.join('') + '</ul>')
      $wrap.append($menu)

      return {
        select: $wrap,
        title: $menu.find('.ideal-select-title'),
        sub: $menu.find('.ideal-select-sub'),
        items: $menu.find('.ideal-select-item')
      }
    }())

    /**
     * @namespace methods of custom select
     * @memberof $.fn.tocustomselect
     */
    var actions = {

      getselectedidx: function () {
        return idealselect.items
          .filter('.ideal-select-item-selected').index()
      },

      /**
       * @private
       */
      init: (function () {
        $select.css({
          position: 'absolute',
          left: '-9999px'
        })
        idealselect.sub.hide()
        idealselect.select.insertafter($select)
        idealselect.select.css(
          'min-width',
          utils.getmaxwidth(idealselect.items)
        )
        idealselect.items
          .eq($options.filter(':selected').index())
          .addclass('ideal-select-item-selected')
      }()),

      nowindowscroll: function (e) {
        if (e.which === 40 || e.which === 38 || e.which === 13) {
          e.preventdefault()
        }
      },

      // fix loosing focus when scrolling
      // and selecting item with keyboard
      focushack: function () {
        settimeout(function () {
          $select.trigger('focus')
        }, 1)
      },

      focus: function () {
        idealselect.select.addclass('ideal-select-focus')
        $(document).on('keydown.noscroll', actions.nowindowscroll)
      },

      blur: function () {
        idealselect.select
          .removeclass('ideal-select-open ideal-select-focus')
        $(document).off('.noscroll')
      },

      scrollintoview: function (dir) {
        var
        $selected = idealselect.items.filter('.ideal-select-item-selected'),
        itemheight = idealselect.items.outerheight(),
        menuheight = idealselect.sub.outerheight(),

        isinview = (function () {
          // relative position to the submenu
          var elpos = $selected.position().top + itemheight
          return dir === 'down'
            ? elpos <= menuheight
            : elpos > 0
        }())

        if (!isinview) {
          itemheight = (dir === 'down')
            ? itemheight // go down
            : -itemheight // go up

          idealselect.sub
            .scrolltop(idealselect.sub.scrolltop() + itemheight)
        }
      },

      scrolltoitem: function () {
        var idx = actions.getselectedidx(),
            height = idealselect.items.outerheight(),
            nitems = idealselect.items.length,
            allheight = height * nitems,
            curheight = height * (nitems - idx)

        idealselect.sub.scrolltop(allheight - curheight)
      },

      showmenu: function () {
        idealselect.sub.fadein('fast')
        idealselect.select.addclass('ideal-select-open')
        actions.select(actions.getselectedidx())
        actions.scrolltoitem()
      },

      hidemenu: function () {
        idealselect.sub.hide()
        idealselect.select.removeclass('ideal-select-open')
      },

      select: function (idx) {
        idealselect.items
          .removeclass('ideal-select-item-selected')
        idealselect.items
          .eq(idx).addclass('ideal-select-item-selected')
      },

      change: function (idx) {
        var text = idealselect.items.eq(idx).text()
        actions.select(idx)
        idealselect.title.text(text)
        $options.eq(idx).prop('selected', true)
        $select.trigger('change')
      },

      keydown: function (key) {
        var

        idx = actions.getselectedidx(),
        ismenu = idealselect.select.is('.ideal-select-menu'),
        isopen = idealselect.select.is('.ideal-select-open')

        /**
         * @namespace key pressed
         */
        var keys = {

          9: function () { // tab
            if (ismenu) {
              actions.blur()
              actions.hidemenu()
            }
          },

          13: function () { // enter
            if (ismenu)
              isopen
                ? actions.hidemenu()
                : actions.showmenu()
            actions.change(idx)
          },

          27: function () { // esc
            if (ismenu) actions.hidemenu()
          },

          40: function () { // down
            if (idx < $options.length - 1) {
              isopen
                ? actions.select(idx + 1)
                : actions.change(idx + 1)
            }
            actions.scrollintoview('down')
          },

          38: function () { // up
            if (idx > 0) {
              isopen
                ? actions.select(idx - 1)
                : actions.change(idx - 1)
            }
            actions.scrollintoview('up')
          },

          'default': function () { // letter
            var

            letter = string.fromcharcode(key),

            $matches = idealselect.items
              .filter(function () {
                return /^\w+$/i.test( letter ) && // not allow modifier keys ( ctrl, cmd, meta, super... )
                  new regexp('^' + letter, 'i').test( $(this).text() ) // find first match
              }),
            nmatches = $matches.length,

            counter = idealselect.select.data('counter') + 1 || 0,
            curkey = idealselect.select.data('key') || key,

            newidx = $matches.eq(counter).index()

            if (!nmatches) // no matches
              return false

            // if more matches with same letter
            if (curkey === key) {
              if (counter < nmatches) {
                idealselect.select.data('counter', counter)
              }
              else {
                idealselect.select.data('counter', 0)
                newidx = $matches.eq(0).index()
              }
            }
            // if new letter
            else {
              idealselect.select.data('counter', 0)
              newidx = $matches.eq(0).index()
            }

            if (isopen)
              actions.select(newidx)
            else
              actions.change(newidx)

            idealselect.select.data('key', key)

            actions.scrolltoitem()
            actions.focushack()
          }
        }

        keys[key]
          ? keys[key]()
          : keys['default']()
      }
    }

    /**
     * @namespace holds all events of custom select for "menu mode" and "list mode"
     * @memberof $.fn.tocustomselect
     */
    var events = {
      focus: actions.focus,
      'blur.menu': function () {
        actions.blur()
        actions.hidemenu()
      },
      'blur.list': function () {
        actions.blur()
      },
      keydown: function (e) {
        actions.keydown(e.which)
      },
      'clickitem.menu': function () {
        actions.change($(this).index())
        actions.hidemenu()
      },
      'clickitem.list': function () {
        actions.change($(this).index())
      },
      'clicktitle.menu': function () {
        actions.focus()
        actions.showmenu()
        $select.trigger('focus')
      },
      'hideoutside.menu': function () {
        $select.off('blur.menu')
        $(document).on('mousedown.ideal', function (evt) {
          if (!$(evt.target).closest(idealselect.select).length) {
            $(document).off('mousedown.ideal')
            $select.on('blur.menu', events['blur.menu'])
          } else {
            actions.focushack()
          }
        })
      },
      'mousedown.list': function () {
        actions.focushack()
      }
    }

    // reset events
    var disableevents = function () {
      idealselect.select.removeclass('ideal-select-menu ideal-select-list')
      $select.off('.menu .list')
      idealselect.items.off('.menu .list')
      idealselect.select.off('.menu .list')
      idealselect.title.off('.menu .list')
    }

    // menu mode
    idealselect.select.on('menu', function () {
      disableevents()
      idealselect.select.addclass('ideal-select-menu')
      actions.hidemenu()
      $select.on({
        'blur.menu': events['blur.menu'],
        'focus.menu': events.focus,
        'keydown.menu': events.keydown
      })
      idealselect.select.on('mousedown.menu', events['hideoutside.menu'])
      idealselect.items.on('click.menu', events['clickitem.menu'])
      idealselect.title.on('click.menu', events['clicktitle.menu'])
    })

    // list mode
    idealselect.select.on('list', function () {
      disableevents()
      idealselect.select.addclass('ideal-select-list')
      actions.showmenu()
      $select.on({
        'blur.list': events['blur.list'],
        'focus.list': events.focus,
        'keydown.list': events.keydown
      })
      idealselect.select.on('mousedown.list', events['mousedown.list'])
      idealselect.items.on('mousedown.list', events['clickitem.list'])
    })

    $select.keydown(function (e) {
      // prevent default keydown event
      // to avoid bugs with ideal select events
      if (e.which !== 9) e.preventdefault()
    })

    // reset
    idealselect.select.on('reset', function(){
      actions.change(0)
    })

    idealselect.select.trigger('menu') // default to "menu mode"
  })
}

/*
 * idealradiocheck: jquery plguin for checkbox and radio replacement
 * usage: $('input[type=checkbox], input[type=radio]').idealradiocheck()
 */
$.fn.idealradiocheck = function() {

  return this.each(function() {

    var $this = $(this)
    var $span = $('<span/>')

    $span.addclass( 'ideal-'+ ( $this.is(':checkbox') ? 'check' : 'radio' ) )
    $this.is(':checked') && $span.addclass('checked') // init
    $span.insertafter( $this )

    $this.parent('label').addclass('ideal-radiocheck-label')
      .attr('onclick', '') // fix clicking label in ios
    $this.css({ position: 'absolute', left: '-9999px' }) // hide by shifting left

    // events
    $this.on({
      change: function() {
        var $this = $(this)
        if ( $this.is('input[type="radio"]') ) {
          $this.parent().siblings('label').find('.ideal-radio').removeclass('checked')
        }
        $span.toggleclass( 'checked', $this.is(':checked') )
      },
      focus: function() { $span.addclass('focus') },
      blur: function() { $span.removeclass('focus') },
      click: function() { $(this).trigger('focus') }
    })
  })
}

;(function( $ ) {

  // browser supports html5 multiple file?
  var multiplesupport = typeof $('<input/>')[0].multiple !== 'undefined',
      isie = /msie/i.test( navigator.useragent )

  $.fn.idealfile = function() {

    return this.each(function() {

      var $file = $(this).addclass('ideal-file'), // the original file input
          // label that will be used for ie hack
          $wrap = $('<p class="ideal-file-wrap">'),
          $input = $('<input type="text" class="ideal-file-filename" />'),
          // button that will be used in non-ie browsers
          $button = $('<button type="button" class="ideal-file-upload">open</button>'),
          // hack for ie
          $label = $('<label class="ideal-file-upload" for="'+ $file[0].id +'">open</label>')

      // hide by shifting to the left so we
      // can still trigger events
      $file.css({
        position: 'absolute',
        left: '-9999px'
      })

      $wrap.append( $input, ( isie ? $label : $button ) ).insertafter( $file )

      // prevent focus
      $file.attr('tabindex', -1)
      $button.attr('tabindex', -1)

      $button.click(function () {
        $file.focus().click() // open dialog
      })

      $file.change(function() {

        var files = [], filearr, filename

        // if multiple is supported then extract
        // all filenames from the file array
        if ( multiplesupport ) {
          filearr = $file[0].files
          for ( var i = 0, len = filearr.length; i < len; i++ ) {
            files.push( filearr[i].name )
          }
          filename = files.join(', ')

        // if not supported then just take the value
        // and remove the path to just show the filename
        } else {
          filename = $file.val().split('\\').pop()
        }

        $input.val( filename ) // set the value
          .attr( 'title', filename ) // show filename in title tootlip

      })

      $input.on({
        focus: function () { $file.trigger('change') },
        blur: function () { $file.trigger('blur') },
        keydown: function( e ) {
          if ( e.which === 13 ) { // enter
            if ( !isie ) { $file.trigger('click') }
          } else if ( e.which === 8 || e.which === 46 ) { // backspace & del
            // on some browsers the value is read-only
            // with this trick we remove the old input and add
            // a clean clone with all the original events attached
            $file.replacewith( $file = $file.val('').clone( true ) )
            $file.trigger('change')
            $input.val('')
          } else if ( e.which === 9 ){ // tab
            return
          } else { // all other keys
            return false
          }
        }
      })

    })

  }

}( jquery ))


/**
 * @namespace errors
 * @locale en
 */
$.idealforms.errors = {
		
  required: '此处是必填的.',
  number: '必须是数字.',
  digits: '必须是唯一的数字.',
  name: '必须至少有3个字符长,并且只能包含字母.',
  username: '用户名最短5位,最长30位,请使用英文字母、数字、中文和下划线.用户名首字符必须为字母、数字、中文,不能为全数字.中文最长21个字.',
  pass: '密码的位数必须的在6-15位之间,并且至少包含一个数字,一个大写字母和一个小写字母.',
  strongpass: '必须至少为8个字符长,至少包含一个大写字母和一个小写字母和一个数字或特殊字符.',
  email: '必须是一个有效的email地址. <em>(例: user@gmail.com)</em>',
  phone: '必须是一个有效的手机号码. <em>(例: 18723101212)</em>',

  zip: 'must be a valid us zip code. <em>(e.g. 33245 or 33245-0003)</em>',
  url: 'must be a valid url. <em>(e.g. www.google.com)</em>',
  minchar: 'must be at least <strong>{0}</strong> characters long.',
  minoption: 'check at least <strong>{0}</strong> options.',
  maxchar: 'no more than <strong>{0}</strong> characters long.',
  maxoption: 'no more than <strong>{0}</strong> options allowed.',
  range: 'must be a number between {0} and {1}.',
  date: 'must be a valid date. <em>(e.g. {0})</em>',
  dob: 'must be a valid date of birth.',
  exclude: '"{0}" is not available.',
  excludeoption: '{0}',
  equalto: 'must be the same value as <strong>"{0}"</strong>',
  extension: 'file(s) must have a valid extension. <em>(e.g. "{0}")</em>',
  ajaxsuccess: '<strong>{0}</strong> is not available.',
  ajaxerror: 'server error...'

}

/**
 * get all default filters
 * @returns object
 */
var getfilters = function() {

  var filters = {

    required: {
      regex: /.+/,
      error: $.idealforms.errors.required
    },

    number: {
      regex: function( i, v ) { return !isnan(v) },
      error: $.idealforms.errors.number
    },

    digits: {
      regex: /^\d+$/,
      error: $.idealforms.errors.digits
    },

    name: {
      regex: /^[a-za-z]{3,}$/,
      error: $.idealforms.errors.name
    },

    username: {
      regex: /^[a-z](?=[\w.]{4,30}$)\w*\.?\w*$/i,
      error: $.idealforms.errors.username
    },

    pass: {
      regex: /(?=.*\d)(?=.*[a-z])(?=.*[a-z]).{6,}/,
      error: $.idealforms.errors.pass
    },

    strongpass: {
      regex: /(?=^.{8,}$)((?=.*\d)|(?=.*\w+))(?![.\n])(?=.*[a-z])(?=.*[a-z]).*$/,
      error: $.idealforms.errors.strongpass
    },

    email: {
      regex: /^([a-za-z0-9]*[-_.]?[a-za-z0-9]+)*@([a-za-z0-9]*[-_]?[a-za-z0-9]+)+[\\.][a-za-z]{2,3}([\\.][a-za-z]{2})?$/,
      error: $.idealforms.errors.email
    },

    phone: {
      //regex: /^((13[0-9])|(15[0-9])|(17[0-9])|(18[0-9]))\\d{8}$/,
      regex: /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/,
      error: $.idealforms.errors.phone
    },

    zip: {
      regex: /^\d{5}$|^\d{5}-\d{4}$/,
      error: $.idealforms.errors.zip
    },

    url: {
      regex: /^(?:(ftp|http|https):\/\/)?(?:[\w\-]+\.)+[a-z]{2,6}([\:\/?#].*)?$/i,
      error: $.idealforms.errors.url
    },

    min: {
      regex: function( input, value ) {
        var $input = input.input,
            min = input.useroptions.data.min,
            isradiocheck = $input.is('[type="checkbox"], [type="radio"]')
        if ( isradiocheck ) {
          this.error = $.idealforms.errors.minoption.replace( '{0}', min )
          return $input.filter(':checked').length >= min
        }
        this.error = $.idealforms.errors.minchar.replace( '{0}', min )
        return value.length >= min
      }
    },

    max: {
      regex: function( input, value ) {
        var $input = input.input,
            max = input.useroptions.data.max,
            isradiocheck = $input.is('[type="checkbox"], [type="radio"]')
        if ( isradiocheck ) {
          this.error = $.idealforms.errors.maxoption.replace( '{0}', max )
          return $input.filter(':checked').length <= max
        }
        this.error = $.idealforms.errors.maxchar.replace( '{0}', max )
        return value.length <= max
      }
    },

    range: {
      regex: function( input, value ) {
        var range = input.useroptions.data.range,
            val = +value
        this.error = $.idealforms.errors.range
          .replace( '{0}', range[0] )
          .replace( '{1}', range[1] )
        return val >= range[0] && val <= range[1]
      }
    },

    date: {
      regex: function( input, value ) {
        var

        userformat =
          input.useroptions.data && input.useroptions.data.date
            ? input.useroptions.data.date
            : 'mm/dd/yyyy', // default format

        delimiter = /[^mdy]/.exec( userformat )[0],
        theformat = userformat.split(delimiter),
        thedate = value.split(delimiter),

        isdate = function( date, format ) {
          var m, d, y
          for ( var i = 0, len = format.length; i < len; i++ ) {
            if ( /m/.test( format[i]) ) m = date[i]
            if ( /d/.test( format[i]) ) d = date[i]
            if ( /y/.test( format[i]) ) y = date[i]
          }
          return (
            m > 0 && m < 13 &&
            y && y.length === 4 &&
            d > 0 && d <= ( new date( y, m, 0 ) ).getdate()
          )
        }

        this.error = $.idealforms.errors.date.replace( '{0}', userformat )

        return isdate( thedate, theformat )
      }
    },

    dob: {
      regex: function( input, value ) {
        var

        userformat =
          input.useroptions.data && input.useroptions.data.dob
            ? input.useroptions.data.dob
            : 'mm/dd/yyyy', // default format

        // simulate a date input
        dateinput = {
          input: input.input,
          useroptions: {
            data: { date: userformat }
          }
        },

        // use internal date filter to validate the date
        isdate = filters.date.regex( dateinput, value ),

        // dob
        theyear = /\d{4}/.exec( value ),
        maxyear = new date().getfullyear(), // current year
        minyear = maxyear - 100

        this.error = $.idealforms.errors.dob

        return isdate && theyear >= minyear && theyear <= maxyear
      }
    },

    exclude: {
      regex: function( input, value ) {
        var $input = input.input,
            exclude = input.useroptions.data.exclude,
            isoption = $input.is('[type="checkbox"], [type="radio"], select')
        this.error = isoption
          ? $.idealforms.errors.excludeoption.replace( '{0}', value )
          : this.error = $.idealforms.errors.exclude.replace( '{0}', value )
        return $.inarray( value, exclude ) === -1
      }
    },

    equalto: {
      regex: function( input, value ) {
        var $equals = $( input.useroptions.data.equalto ),
            $input = input.input,
            name = $equals.attr('name') || $equals.attr('id'),
            isvalid = $equals.parents('.ideal-field')
              .filter(function(){ return $(this).data('ideal-isvalid') === true })
              .length
        if ( !isvalid ) { return false }
        this.error = $.idealforms.errors.equalto.replace( '{0}', name )
        return $input.val() === $equals.val()
      }
    },

    extension: {
      regex: function( input, value ) {
        var files = input.input[0].files || [{ name: value }],
            extensions = input.useroptions.data.extension,
            re = new regexp( '\\.'+ extensions.join('|') +'$', 'i' ),
            valid = false
        for ( var i = 0, len = files.length; i < len; i++ ) {
          valid = re.test( files[i].name );
        }
        this.error = $.idealforms.errors.extension.replace( '{0}', extensions.join('", "') )
        return valid
      }
    },

    ajax: {
      regex: function( input, value, showorhideerror ) {

        var self = this
        var $input = input.input
        var useroptions = input.useroptions
        var name = $input.attr('name')
        var $field = $input.parents('.ideal-field')
        var valid = false

        var customerrors = useroptions.errors && useroptions.errors.ajax
        self.error = {}
        self.error.success = customerrors && customerrors.success
          ? customerrors.success
          : $.idealforms.errors.ajaxsuccess.replace( '{0}', value )
        self.error.fail = customerrors && customerrors.error
          ? customerrors.error
          : $.idealforms.errors.ajaxerror

        // send input name as $_post[name]
        var data = {}
        data[ name ] = $.trim( value )

        // ajax options defined by the user
        var userajaxops = input.useroptions.data.ajax

        var ajaxops = {
          type: 'post',
          datatype: 'json',
          data: data,
          success: function( resp, text, xhr ) {
          console.log(resp)
            showorhideerror( self.error.success, true )
            $input.data({
              'ideal-ajax-resp': resp,
              'ideal-ajax-error': self.error.success
            })
            $input.trigger('change') // to update counter
            $field.removeclass('ajax')
            // run custom success callback
            if( userajaxops._success ) {
              userajaxops._success( resp, text, xhr )
            }
          },
          error: function( xhr, text, error ) {
            if ( text !== 'abort' ) {
              showorhideerror( self.error.fail, false )
              $input.data( 'ideal-ajax-error', self.error.fail )
              $field.removeclass('ajax')
              // run custom error callback
              if ( userajaxops._error ) {
                userajaxops._error( xhr, text, error )
              }
            }
          }
        }
        $.extend( ajaxops, userajaxops )

        // init
        $input.removedata('ideal-ajax-error')
        $input.removedata('ideal-ajax-resp')
        $field.addclass('ajax')

        // run request and save it to be able to abort it
        // so requests don't bubble
        $.idealforms.ajaxrequests[ name ] = $.ajax( ajaxops )
      }
    }

  }

  return filters

}

$.idealforms.flags = {
  noerror: function (i) {
    i.parent().siblings('.ideal-error').hide()
  },
  noicons: function (i) {
    i.siblings('.ideal-icon-valid, .ideal-icon-invalid').hide()
  },
  novalidicon: function (i) {
    i.siblings('.ideal-icon-valid').hide()
  },
  noinvalidicon: function (i) {
    i.siblings('.ideal-icon-invalid').hide()
  },
  noclass: function (i) {
    i.parents('.ideal-field').removeclass('valid invalid')
  },
  novalidclass: function (i) {
    i.parents('.ideal-field').removeclass('valid')
  },
  noinvalidclass: function (i) {
    i.parents('.ideal-field').removeclass('invalid')
  }
}

/*
 * ideal forms plugin
 */
var _defaults = {
  inputs: {},
  customfilters: {},
  customflags: {},
  globalflags: '',
  onsuccess: function(e) { alert('thank you...') },
  onfail: function() { alert('invalid!') },
  responsiveat: 'auto',
  disablecustom: ''
}

// constructor
var idealforms = function( element, options ) {

  var self = this

  self.$form = $( element )
  self.opts = $.extend( {}, _defaults, options )

  self.$tabs = self.$form.find('section')

  // set localized filters
  $.extend( $.idealforms.filters, getfilters() )

  self._init()

}

// plugin
$.fn.idealforms = function( options ) {
  return this.each(function() {
    if ( !$.data( this, 'idealforms' ) ) {
      $.data( this, 'idealforms', new idealforms( this, options ) )
    }
  })
}

// get less variables
var lessvars = {
  fieldwidth: utils.getlessvar( 'ideal-field-width', 'width' )
}

/*
 * private methods
 */
$.extend( idealforms.prototype, {

  _init: function() {

    var self = this
    var o = self.opts
    var formelements = self._getformelements()

    self.$form.css( 'visibility', 'visible' )
      .addclass('ideal-form')
      .attr( 'novalidate', 'novalidate' ) // disable html5 validation

    // do markup
    formelements.inputs
      .add( formelements.headings )
      .add( formelements.separators )
      .each(function(){ self._domarkup( $(this) ) })

    // generate tabs
    if ( self.$tabs.length ) {
      var $tabcontainer = $('<p class="ideal-wrap ideal-tabs ideal-full-width"/>')
      self.$form.prepend( $tabcontainer )
      self.$tabs.idealtabs( $tabcontainer )
    }

    // always show datepicker below the input
    if ( jquery.ui ) {
      $.datepicker._checkoffset = function( a,b,c ) { return b }
    }

    // add inputs specified by data-ideal
    // to the list of user inputs
    self.$form.find('[data-ideal]').each(function() {
      var userinput = o.inputs[ this.name ]
      o.inputs[ this.name ] = userinput || { filters: $(this).data('ideal') }
    })

   // responsive
    if ( o.responsiveat ) {
      $(window).resize(function(){ self._responsive() })
      self._responsive()
    }

    // form events
    self.$form.on({
      keydown: function( e ) {
        // prevent submit when pressing enter
        // but exclude textareas
        if ( e.which === 13 && e.target.nodename !== 'textarea' ) {
          e.preventdefault()
        }
      },
      submit: function( e ) {
        if ( !self.isvalid() ) {
          e.preventdefault()
          o.onfail()
          self.focusfirstinvalid()
        } else {
          o.onsuccess( e )
        }
      }
    })

    self._adjust()
    self._attachevents()
    self.fresh() // start fresh

  },

  _getformelements: function() {
    return {
      inputs: this.$form.find('input, select, textarea, :button'),
      labels: this.$form.find('p > label:first-child'),
      text: this.$form.find('input:not([type="checkbox"], [type="radio"], [type="submit"]), textarea'),
      select: this.$form.find('select'),
      radiocheck: this.$form.find('input[type="radio"], input[type="checkbox"]'),
      buttons: this.$form.find(':button'),
      file: this.$form.find('input[type="file"]'),
      headings: this.$form.find('h1, h2, h3, h4, h5, h6'),
      separators: this.$form.find('hr'),
      hidden: this.$form.find('input:hidden')
    }
  },

  _getuserinputs: function() {
    return this.$form.find('[name="'+ utils.getkeys( this.opts.inputs ).join('"], [name="') +'"]')
  },

  _gettab: function( nameoridx ) {
    var self = this
    var isnumber = !isnan( nameoridx )
    if ( isnumber ) {
      return self.$tabs.eq( nameoridx )
    }
    return self.$tabs.filter(function() {
      var re = new regexp( nameoridx, 'i' )
      return re.test( $(this).data('ideal-tabs-content-name') )
    })
  },

  _getcurrenttabidx: function() {
    return this.$tabs.index( this.$form.find('.ideal-tabs-content:visible') )
  },

  _updatetabscounter: function() {
    var self = this
    self.$tabs.each(function( i ) {
      var invalid = self.getinvalidintab( i ).length
      self.$tabs.updatecounter( i, invalid )
    })
  },

  _adjust: function() {

    var self = this
    var o = self.opts
    var formelements = self._getformelements()
    var curtab = self._getcurrenttabidx()

    // autocomplete causes some problems...
    formelements.inputs.attr('autocomplete', 'off')

    // show tabs to calculate dimensions
    if ( self.$tabs.length ) { self.$tabs.show() }

    // adjust labels
    var labels = formelements.labels
    labels.removeattr('style').width( utils.getmaxwidth( labels ) )

    // adjust headings and separators
    if ( self.$tabs.length ) {
      this.$tabs.each(function(){
        $( this ).find('.ideal-heading:first').addclass('first-child')
      })
    } else {
      self.$form.find('.ideal-heading:first').addclass('first-child')
    }

    self._setdatepicker()

    // done calculating hide tabs
    if ( self.$tabs.length ) {
      self.$tabs.hide()
      self.switchtab( curtab )
    }

  },

  _setdatepicker: function() {

    var o = this.opts
    var $datepicker = this.$form.find('input.datepicker')

    if ( jquery.ui && $datepicker.length ) {

      $datepicker.each(function() {
        var userinput = o.inputs[ this.name ]
        var data = userinput && userinput.data && userinput.data.date
        var format = data ? data.replace( 'yyyy', 'yy' ) : 'mm/dd/yy'

        $(this).datepicker({
          dateformat: format,
          beforeshow: function( input ) {
            $( input ).addclass('open')
          },
          onchangemonthyear: function() {
            // hack to fix ie9 not resizing
            var $this = $(this)
            var w = $this.outerwidth() // cache first!
            settimeout(function() {
              $this.datepicker('widget').css( 'width', w )
            }, 1)
          },
          onclose: function() { $(this).removeclass('open') }
        })
      })

      // adjust width
      $datepicker.on('focus keyup', function() {
        var t = $(this), w = t.outerwidth()
        t.datepicker('widget').css( 'width', w )
      })

      $datepicker.parent().siblings('.ideal-error').addclass('hidden')
    }
  },

  _domarkup: function( $element ) {

    var o = this.opts
    var elementtype = utils.getidealtype( $element )

    // validation elements
    var $field = $('<span class="ideal-field"/>')
    var $error = $('<span class="ideal-error" />')
    var $valid = $('<i class="ideal-icon ideal-icon-valid" />')
    var $invalid = $('<i class="ideal-icon ideal-icon-invalid"/>')
      .click(function(){
        $(this).parent().find('input:first, textarea, select').focus()
      })

    // basic markup
    $element.closest('p').addclass('ideal-wrap')
      .children('label:first-child').addclass('ideal-label')

    var idealelements = {

      _defaultinput: function() {
        $element.wrapall( $field ).after( $valid, $invalid )
          .parent().after( $error )
      },

      text: function() { idealelements._defaultinput() },

      radiocheck: function() {
        // check if input is already wrapped so we don't
        // wrap radios and checks more than once
        var iswrapped = $element.parents('.ideal-field').length
        if ( !iswrapped ) {
          $element.parent().nextall().andself().wrapall( $field.addclass('ideal-radiocheck') )
          $element.parents('.ideal-field').append( $valid, $invalid ).after( $error )
        }
        if ( !/radiocheck/.test( o.disablecustom ) ) {
          $element.idealradiocheck()
        }
      },

      select: function() {
        idealelements._defaultinput()
        if ( !/select/.test( o.disablecustom ) ) {
          $element.idealselect()
        }
      },

      file: function() {
        idealelements._defaultinput()
        if ( !/file/.test( o.disablecustom ) ) {
          $element.idealfile()
        }
      },

      button: function() {
        if ( !/button/.test( o.disablecustom ) ) {
          $element.addclass('ideal-button')
        }
      },

      hidden: function() {
        $element.closest('p').addclass('ideal-hidden')
      },

      heading: function() {
        $element.closest('p').addclass('ideal-full-width')
        $element.parent().children().wrapall('<span class="ideal-heading"/>')
      },

      separator: function() {
        $element.closest('p').addclass('ideal-full-width')
        $element.wrapall('<p class="ideal-separator"/>')
      }

    }

    // generate markup for current element type
    idealelements[ elementtype ] ? idealelements[ elementtype ]() : $.noop()

    $error.add( $valid ).add( $invalid ).hide() // start fresh

  },


  /** validates an input and shows or hides error and icon
   * @memberof actions
   * @param {object} $input jquery object
   * @param {string} e the javascript event
   */
  _validate: function( $input, e ) {

    var self = this
    var o = this.opts

    var useroptions = o.inputs[ $input.attr('name') ]
    var userfilters = useroptions.filters && useroptions.filters.split(/\s/)
    var name = $input.attr('name')
    var value = $input.val()

    var ajaxrequest = $.idealforms.ajaxrequests[ name ]

    var isradiocheck = $input.is('[type="checkbox"], [type="radio"]')

    var inputdata = {
      // if is radio or check validate all inputs related by name
      input: isradiocheck ? self.$form.find('[name="' + name + '"]') : $input,
      useroptions: useroptions
    }

    // validation elements
    var $field = $input.parents('.ideal-field')
    var $error = $field.siblings('.ideal-error')
    var $invalid = isradiocheck
      ? $input.parent().siblings('.ideal-icon-invalid')
      : $input.siblings('.ideal-icon-invalid')
    var $valid = isradiocheck
      ? $input.parent().siblings('.ideal-icon-valid')
      : $input.siblings('.ideal-icon-valid')

    function reseterror() {
      $field.removeclass('valid invalid').removedata('ideal-isvalid')
      $error.add( $invalid ).add( $valid ).hide()
    }

    function showorhideerror( error, valid ) {
      reseterror()
      valid ? $valid.show() : $invalid.show()
      $field.addclass( valid ? 'valid' : 'invalid' )
      $field.data( 'ideal-isvalid', valid )
      if ( !valid ) {
        $error.html( error ).toggle( $field.is('.ideal-field-focus') )
      }
    }

    // prevent validation when typing but not introducing any new characters
    // this is mainly to prevent multiple ajax requests
    var oldvalue = $input.data('ideal-value') || 0
    $input.data( 'ideal-value', value )
    if ( e.type === 'keyup' && value === oldvalue ) { return false }

    // validate
    if ( userfilters ) {

      $.each( userfilters, function( i, filter ) {

        var thefilter = $.idealforms.filters[ filter ]
        var customerror = useroptions.errors && useroption

                    

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网