Html5用户注册自动校验

Posted 火雨_Nick

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Html5用户注册自动校验相关的知识,希望对你有一定的参考价值。

        抽时间写了一个带有自动校验功能的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) -->
    <div class="main" >
        <div style="height:5px;text-align:center;font-size:25px"> 欢迎您注册!</div>
        <!-- Begin Form -->
        <form id="my-form" class="myform">
            <div>
                <label>用户名:</label><input id="username" name="username" type="text" />
            </div>
            <div>
                <!-- <label>密码:</label><input id="pass" name="password" type="password" /> -->
                <label>密码:</label><input id="pass" name="password" type="text" />
            </div>
            <div>
                <label>邮箱:</label><input id="email" name="email"
                                         data-ideal="required email" type="email" />
            </div>
            <div>
                <label>电话:</label><input id="telephone" type="text" name="phone" data-ideal="phone" />
            </div>
            <div>
                <label>供应商V码:</label><input id="vCode" type="text" name="vCode" data-ideal="vCode" />
            </div>
            <div>
                <label>真实姓名:</label><input id="trueName" type="text" name="trueName" data-ideal="trueName" />
            </div>
            <div>
                <label>手机验证码:</label><input id="telCode" type="text" name="telCode" data-ideal="telCode" />
            </div>
            <div 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;" />
            </div>
            <!--<div>
                <label>性别:</label>
                <select id="sex" name="sex">
                    <option value="男">男</option>
                    <option value="女">女</option>
                </select>
            </div>
            <div>
                <label>昵称:</label><input id="nickName" type="text" name="nickName" data-ideal="nickName" />
            </div>
            <div>
                <label>年龄:</label><input id="age" type="text" name="age" data-ideal="age" />
            </div>-->
            <!-- <div>
                <label>地址:</label><input type="text" name="address" data-ideal="address" />
            </div>
            <div>
                <label>QQ:</label><input type="text" name="qq" data-ideal="qq" />
            </div>
            <div>
                <label>邮编:</label><input type="text" name="zip" data-ideal="zip" />
            </div>
            <div>
                <label>传真:</label><input type="text" name="fax" data-ideal="fax" />
            </div>
            <div>
                <label>身份证:</label><input type="text" name="creditID" data-ideal="creditID" />
            </div>
            <div>
                <label>出生日期:</label><input name="date" class="datepicker"
                    data-ideal="date" type="text" placeholder="月/日/年" />
            </div>
            <div>
                <label>上传头像:</label><input id="file" name="file" multiple
                    type="file" />
            </div>
            <div>
                <label>个人主页:</label><input name="website" data-ideal="url"
                    type="text" />
            </div>
            <div>
                <label>备注:</label>
                <textarea id="comments" name="comments"></textarea>
            </div>
            -->
            <!-- <div 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>
            </div>
            <div>
                <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>
            </div>
            <div>
                <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>
            </div> -->
            <div style="margin-top:10px; margin-left:100px;margin-right:100px;">
                <button type="button" id="submit" class="submit">提交</button>
                <button id="reset" type="button" >重置</button>
            </div>

        </form>
        <!-- End Form -->
    </div>

<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) {
               //获取当前网址,如: http://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);
               //获取主机地址,如: http://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地址. <em>(: user@gmail.com)</em>',
  phone: '必须是一个有效的手机号码. <em>(: 18723101212)</em>'
  以下是整个代码文件:

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

  jq-idealforms 2.1

  * Author: Cedric Ruiz
  * License: GPL or MIT
  * Demo: http://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 = $('<div 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 = $('<div 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('div > 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 clas

以上是关于Html5用户注册自动校验的主要内容,如果未能解决你的问题,请参考以下文章

十个html5代码片段,超实用,一定要收藏

html5中啥方法是用于网页传参的

常用HTML5代码片段

VSCode 配置 用户自定义代码片段 自定义自动代码补充

如何在 Vs Code 中更改默认自动选择的用户片段行为

在 HTML5 Video 中,如何播放长视频中的小片段?