好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

html5教程-Html5用户注册自动校验

小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。

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

以下是效果截图:

1.页面代码:usersRegister.hbs
&nbs p;

 <!DOCTY PE  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>     < ;m eta http-equiv="Content -t ype" content="text/html; charset=utf-8">     <meta http-equiv="X-UA-Compatible" content="IE= Edge " />     <t IT le>用户注册</title>      <!--[if lt IE 9]>     <script src="/assets/scripts/html5shiv.js"></script>     <![endif]-->      <link  hr ef="/assets/styles/ jq uery.idealforms.min.css" rel="stylesheet" media="screen" />      <style type="text/css">         body {             font: normal 15px/1.5 Arial, Helvetica, Free Sans, sans -s erif;             color:  # 222;             overflow-y: scroll;             padding: 60px 0 0 0;         }          .m ai n {             width: 560px;             h ei ght: 480px;             m arg in: -50px auto;         }          #my-form {             width: 560px;             height: 450px;             mar gin : 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 -i mage: url( stat ic/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="usern am e" 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="requi red  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="s ub mit" 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/uimcard PR j/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 + "/ LOG in";                alert("注册成功!");             },             error : function(e) {                 alert("注册失败!" + e);             }         });     });      $('#reset').click(function() {         $myform.reset().fresh().focus First ();     });  </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测试数据/jq-idealforms/   * --------------------------------------------------------------------------*/  ;(function ( $, window, document, un define d ) {    'use strict';    // Global Ideal Forms  names pace   $.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  Store d.    * @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 RegE xp    },   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.')   },   getFields From Array: 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|se Arch |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)     },      p rev Tab: 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  Press ed          */         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.f rom CharCode(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( $ ) {    //  br owser 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 t hat  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测试数据)</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. HdhCmsTest GOOGLE 测试数据)</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/ yy yy', // 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')   },   noval IDC lass: 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 $t abc ontainer = $('<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()      // Auto complete  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 && userOptions.errors[ filter ]         var error = ''          // If field is empty and not required         if ( !value && filter !== 'required' ) {           resetError()           return false         }          if ( theFilter ) {            // Abort and reset ajax if there's a request pending           if ( e.type === 'keyup' && ajaxRequest ) {             ajaxRequest.abort()             $field.removeClass('ajax')           }            // AJAX           if ( filter === 'ajax' ) {             showOrHideError( error, false ) // set invalid till response comes back             $error.hide()             if ( e.type === 'keyup' ) {               theFilter.regex( inputData, value, showOrHideError ) // runs the ajax callback             } else {               var ajaxError = $input.data('ideal-ajax-error')               if ( ajaxError ) {                 showOrHideError( ajaxError, $input.data('ideal-ajax-resp') || false )               }             }           }           // All other filters           else {             var valid = Utils.isRegex( theFilter.regex ) && theFilter.regex.test( value ) ||                         Utils.isFunction( theFilter.regex ) && theFilter.regex( inputData, value )             error = customError || theFilter.error // assign error after calling regex()             showOrHideError( error, valid )             if ( !valid ) { return false }           }         }       })     }     // Reset if there are no filters     else {       resetError()     }      // Flags     var flags = (function(){       var f = userOptions.flags && userOptions.flags.split(' ') || []       if ( o.globalFlags ) {         $.each( o.globalFlags.split(' '), function( i,v ) { f.push(v) })       }       return f     }())     if ( flags.length ) {       $.each(flags, function( i,f ) {         var theFlag = $.idealforms.flags[f]         if ( theFlag ) { theFlag( $input, e.type ) }       })     }      // Update counter     if ( self.$tabs.length ) {       self._updateTabsCounter( self._getCurrentTabIdx() )     }   },    _attachEvents: function() {      var self = this      self._getUserInputs().on('keyup change focus blur', function(e) {        var $this = $(this)       var $field = $this.parents('.ideal-field')       var isFile = $this.is('input[type=file]')        // Trigger on change if type=file cuz custom file       // disables focus on original file input (tabIndex = -1)       if ( e.type === 'focus' || isFile && e.type === 'change' ) {         $field.addClass('ideal-field-focus')       }       if ( e.type === 'blur' ) {         $field.removeClass('ideal-field-focus')       }        self._validate( $this, e )     })    },    _responsive: function() {      var formElements = this._getFormElements()     var maxWidth = LessVars.fieldWidth + formElements.labels.outerWidth()     var $emptyLabel = formElements.labels.filter(function() {       return $(this). html()  === ' '     })     var $customSelect = this.$form.find('.ideal-select')      this.opts.responsiveAt === 'auto'       ? this.$form.toggleClass( 'stack', this.$form.width() < maxWidth )       : this.$form.toggleClass( 'stack', $(window).width() < this.opts.responsiveAt )      var isStack = this.$form.is('.stack')     $emptyLabel.toggle( !isStack )     $customSelect.trigger( isStack ? 'list' : 'menu' )      // Hide datePicker     var $datePicker = this.$form.find('input.hasDatepicker')     if ( $datePicker.length ) { $datePicker.datepicker('hide') }    }  })  /*  * Public Methods  */ $.extend( IdealForms.prototype, {    getInvalid: function() {     return this.$form.find('.ideal-field').filter(function() {       return $(this).data('ideal-isvalid') === false     })   },    getInvalidInTab: function( nameOrIdx ) {     return this._getTab( nameOrIdx ).find('.ideal-field').filter(function() {       return $(this).data('ideal-isvalid') === false     })   },    isValid: function() {     return !this.getInvalid().length   },    isVali DF ield: function( field ) {     var $input = Utils.getByNameOrId( field )     return $input.parents('.ideal-field').data('ideal-isvalid') === true   },    focusFirst: function() {     if ( this.$tabs.length ) {       this.$tabs.filter(':visible')         .find('.ideal-field:first')         .find('input:first, select, textarea').focus()     } else {       this.$form.find('.ideal-field:first')         .find('input:first, select, textarea').focus()     }     return this   },    focusFirstInvalid: function() {     var $first = this.getInvalid().first().find('input:first, select, textarea')     var tabName = $first.parents('.ideal-tabs-content').data('ideal-tabs-content-name')     if ( this.$tabs.length ) {       this.switchTab( tabName )     }     $first.focus()     return this   },    switchTab: function( nameOrIdx ) {     this.$tabs.switchTab( nameOrIdx )     return this   },    nextTab: function() {     this.$tabs.nextTab()     return this   },    prevTab: function() {     this.$tabs.prevTab()     return this   },    firstTab: function() {     this.$tabs.firstTab()     return this   },    lastTab: function() {     this.$tabs.lastTab()     return this   },    fresh: function() {     this._getUserInputs().change().parents('.ideal-field')       .removeClass('valid invalid')     return this   },    freshFields: function( fields ) {     fields = Utils.convertToArray( fields )     $.each( fields, function( i ) {       var $input = Utils.getByNameOrId( fields[ i ] )       $input.change().parents('.ideal-field').removeClass('valid invalid')     })     return this   },    reload: function() {     this._adjust()     this._attachEvents()     return this   },    reset: function() {      var formElements = this._getFormElements()      formElements.text.val('') // text inputs     formElements.radiocheck.removeAttr('checked') // radio & check     // Select and custom select     formElements.select.find('option').first().prop( 'selected', true )     this.$form.find('.ideal-select').trigger('reset')      if ( this.$tabs.length ) { this.firstTab() }      this.focusFirst().fresh()      return this    },    resetFields: function( fields ) {      fields = Utils.convertToArray( fields )     var formElements = this._getFormElements()      $.each( fields, function( i, v ) {       var $input = Utils.getByNameOrId( v )       var type = Utils.getIdealType( $input )       if ( type === 'text' || type === 'file' ) {         $input.val('')       }       if ( type === 'radiocheck' ) {         $input.removeAttr('checked') // radio & check       }       if ( type === 'select' ) {         $input.find('option').first().prop( 'selected', true )         $input.next('.ideal-select').trigger('reset')       }       $input.change()     })      this.freshFields( fields )      return this    },    toggleFields: function( fields ) {      fields = Utils.convertToArray( fields )     var self = this     var $fields = Utils.getFieldsFromArray( fields )      $fields.each(function() {       var $this = $(this)       var name = $this.attr('name') || $this.attr('id')       var input = self.opts.inputs[ name ]       var filters = input && input.filters       var dataFilters = $this.data('ideal-filters') || ''       $this.data( 'ideal-filters', filters )       $this.closest('.ideal-wrap').toggle()       self.setFieldOptions( name, { filters: dataFilters } )     })      return this   },    setOptions: function( options ) {     $.extend( true, this.opts, options )     this.reload().fresh()     return this   },    setFieldOptions: function( name, options ) {     $.extend( true, this.opts.inputs[ name ], options )     this.reload().freshFields([ name ])     return this   },    addFields: function( fields ) {      fields = Utils.convertToArray( fields )      var self = this      // Save names of all inputs  IN ARRAY      // to use methods that take names ie. fresh()     var allNames = []      // Add an input to the DOM     function add( ops ) {        var name = ops.name        var userOptions = {         filters: ops.filters || '',         data: ops.data || {},         errors: ops.errors || {},         flags: ops.flags || ''       }        var label = ops.label || ''       var type = ops.type       var list = ops.list || []       var placeholder = ops.placeholder || ''       var value = ops.value || ''        var $field = $('<p>'+           '<label>'+ label +':</label>'+           Utils.makeInput( name, value, type, list, placeholder ) +         '</p>')       var $input = $field.find('input, select, textarea, :button')        // Add inputs with filters to the list       // of user inputs to validate       if ( userOptions.filters ) { self.opts.inputs[ name ] = userOptions }        self._doMarkup( $input )        // Insert in DOM       if ( ops.addAfter ) {         $field.insertAfter(           $( Utils.getByNameOrId( ops.addAfter ) ).parents('.ideal-wrap')         )       } else if ( ops.addBefore ) {         $field.insertBefore(           $(Utils.getByNameOrId( ops.addBefore ))           .parents('.ideal-wrap')         )       } else if ( ops.appendToTab ) {         $field.insertAfter(           self._getTab( ops.appendToTab ).find('.ideal-wrap:last-child')         )       } else {         $field.insertAfter( self.$form.find('.ideal-wrap').last() )       }        // Add current field name to list of names       allNames.push( name )     }      // Run through each input     $.each( fields, function( i, ops ) { add( ops ) })      self.reload()     self.freshFields( allNames )     self._responsive()      return this    },    removeFields: function( fields ) {     fields = Utils.convertToArray( fields )     var $fields = Utils.getFieldsFromArray( fields )     $fields.parents('.ideal-wrap').remove()     this.reload()     return this   }  })  }( jQuery, window, document ))

 

抽时间写了一个带有自动校验功能的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测试数据) ',   phone: '必须是一个有效的手机号码.  (例: 18723101212) '
以下是整个代码文件:
 /*--------------------------------------------------------------------------    jq-idealforms 2.1    * Author: Cedric Ruiz   * License: GPL or MIT   * Demo: https://elclanrs.github测试数据/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测试数据)</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. HdhCmsTestgoogle测试数据)</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 && userOptions.errors[ filter ]         var error = ''          // If field is empty and not required         if ( !value && filter !== 'required' ) {           resetError()           return false         }          if ( theFilter ) {            // Abort and reset ajax if there's a request pending           if ( e.type === 'keyup' && ajaxRequest ) {             ajaxRequest.abort()             $field.removeClass('ajax')           }            // AJAX           if ( filter === 'ajax' ) {             showOrHideError( error, false ) // set invalid till response comes back             $error.hide()             if ( e.type === 'keyup' ) {               theFilter.regex( inputData, value, showOrHideError ) // runs the ajax callback             } else {               var ajaxError = $input.data('ideal-ajax-error')               if ( ajaxError ) {                 showOrHideError( ajaxError, $input.data('ideal-ajax-resp') || false )               }             }           }           // All other filters           else {             var valid = Utils.isRegex( theFilter.regex ) && theFilter.regex.test( value ) ||                         Utils.isFunction( theFilter.regex ) && theFilter.regex( inputData, value )             error = customError || theFilter.error // assign error after calling regex()             showOrHideError( error, valid )             if ( !valid ) { return false }           }         }       })     }     // Reset if there are no filters     else {       resetError()     }      // Flags     var flags = (function(){       var f = userOptions.flags && userOptions.flags.split(' ') || []       if ( o.globalFlags ) {         $.each( o.globalFlags.split(' '), function( i,v ) { f.push(v) })       }       return f     }())     if ( flags.length ) {       $.each(flags, function( i,f ) {         var theFlag = $.idealforms.flags[f]         if ( theFlag ) { theFlag( $input, e.type ) }       })     }      // Update counter     if ( self.$tabs.length ) {       self._updateTabsCounter( self._getCurrentTabIdx() )     }   },    _attachEvents: function() {      var self = this      self._getUserInputs().on('keyup change focus blur', function(e) {        var $this = $(this)       var $field = $this.parents('.ideal-field')       var isFile = $this.is('input[type=file]')        // Trigger on change if type=file cuz custom file       // disables focus on original file input (tabIndex = -1)       if ( e.type === 'focus' || isFile && e.type === 'change' ) {         $field.addClass('ideal-field-focus')       }       if ( e.type === 'blur' ) {         $field.removeClass('ideal-field-focus')       }        self._validate( $this, e )     })    },    _responsive: function() {      var formElements = this._getFormElements()     var maxWidth = LessVars.fieldWidth + formElements.labels.outerWidth()     var $emptyLabel = formElements.labels.filter(function() {       return $(this).html() === ' '     })     var $customSelect = this.$form.find('.ideal-select')      this.opts.responsiveAt === 'auto'       ? this.$form.toggleClass( 'stack', this.$form.width() < maxWidth )       : this.$form.toggleClass( 'stack', $(window).width() < this.opts.responsiveAt )      var isStack = this.$form.is('.stack')     $emptyLabel.toggle( !isStack )     $customSelect.trigger( isStack ? 'list' : 'menu' )      // Hide datePicker     var $datePicker = this.$form.find('input.hasDatepicker')     if ( $datePicker.length ) { $datePicker.datepicker('hide') }    }  })  /*  * Public Methods  */ $.extend( IdealForms.prototype, {    getInvalid: function() {     return this.$form.find('.ideal-field').filter(function() {       return $(this).data('ideal-isvalid') === false     })   },    getInvalidInTab: function( nameOrIdx ) {     return this._getTab( nameOrIdx ).find('.ideal-field').filter(function() {       return $(this).data('ideal-isvalid') === false     })   },    isValid: function() {     return !this.getInvalid().length   },    isValidField: function( field ) {     var $input = Utils.getByNameOrId( field )     return $input.parents('.ideal-field').data('ideal-isvalid') === true   },    focusFirst: function() {     if ( this.$tabs.length ) {       this.$tabs.filter(':visible')         .find('.ideal-field:first')         .find('input:first, select, textarea').focus()     } else {       this.$form.find('.ideal-field:first')         .find('input:first, select, textarea').focus()     }     return this   },    focusFirstInvalid: function() {     var $first = this.getInvalid().first().find('input:first, select, textarea')     var tabName = $first.parents('.ideal-tabs-content').data('ideal-tabs-content-name')     if ( this.$tabs.length ) {       this.switchTab( tabName )     }     $first.focus()     return this   },    switchTab: function( nameOrIdx ) {     this.$tabs.switchTab( nameOrIdx )     return this   },    nextTab: function() {     this.$tabs.nextTab()     return this   },    prevTab: function() {     this.$tabs.prevTab()     return this   },    firstTab: function() {     this.$tabs.firstTab()     return this   },    lastTab: function() {     this.$tabs.lastTab()     return this   },    fresh: function() {     this._getUserInputs().change().parents('.ideal-field')       .removeClass('valid invalid')     return this   },    freshFields: function( fields ) {     fields = Utils.convertToArray( fields )     $.each( fields, function( i ) {       var $input = Utils.getByNameOrId( fields[ i ] )       $input.change().parents('.ideal-field').removeClass('valid invalid')     })     return this   },    reload: function() {     this._adjust()     this._attachEvents()     return this   },    reset: function() {      var formElements = this._getFormElements()      formElements.text.val('') // text inputs     formElements.radiocheck.removeAttr('checked') // radio & check     // Select and custom select     formElements.select.find('option').first().prop( 'selected', true )     this.$form.find('.ideal-select').trigger('reset')      if ( this.$tabs.length ) { this.firstTab() }      this.focusFirst().fresh()      return this    },    resetFields: function( fields ) {      fields = Utils.convertToArray( fields )     var formElements = this._getFormElements()      $.each( fields, function( i, v ) {       var $input = Utils.getByNameOrId( v )       var type = Utils.getIdealType( $input )       if ( type === 'text' || type === 'file' ) {         $input.val('')       }       if ( type === 'radiocheck' ) {         $input.removeAttr('checked') // radio & check       }       if ( type === 'select' ) {         $input.find('option').first().prop( 'selected', true )         $input.next('.ideal-select').trigger('reset')       }       $input.change()     })      this.freshFields( fields )      return this    },    toggleFields: function( fields ) {      fields = Utils.convertToArray( fields )     var self = this     var $fields = Utils.getFieldsFromArray( fields )      $fields.each(function() {       var $this = $(this)       var name = $this.attr('name') || $this.attr('id')       var input = self.opts.inputs[ name ]       var filters = input && input.filters       var dataFilters = $this.data('ideal-filters') || ''       $this.data( 'ideal-filters', filters )       $this.closest('.ideal-wrap').toggle()       self.setFieldOptions( name, { filters: dataFilters } )     })      return this   },    setOptions: function( options ) {     $.extend( true, this.opts, options )     this.reload().fresh()     return this   },    setFieldOptions: function( name, options ) {     $.extend( true, this.opts.inputs[ name ], options )     this.reload().freshFields([ name ])     return this   },    addFields: function( fields ) {      fields = Utils.convertToArray( fields )      var self = this      // Save names of all inputs in Array     // to use methods that take names ie. fresh()     var allNames = []      // Add an input to the DOM     function add( ops ) {        var name = ops.name        var userOptions = {         filters: ops.filters || '',         data: ops.data || {},         errors: ops.errors || {},         flags: ops.flags || ''       }        var label = ops.label || ''       var type = ops.type       var list = ops.list || []       var placeholder = ops.placeholder || ''       var value = ops.value || ''        var $field = $('<p>'+           '<label>'+ label +':</label>'+           Utils.makeInput( name, value, type, list, placeholder ) +         '</p>')       var $input = $field.find('input, select, textarea, :button')        // Add inputs with filters to the list       // of user inputs to validate       if ( userOptions.filters ) { self.opts.inputs[ name ] = userOptions }        self._doMarkup( $input )        // Insert in DOM       if ( ops.addAfter ) {         $field.insertAfter(           $( Utils.getByNameOrId( ops.addAfter ) ).parents('.ideal-wrap')         )       } else if ( ops.addBefore ) {         $field.insertBefore(           $(Utils.getByNameOrId( ops.addBefore ))           .parents('.ideal-wrap')         )       } else if ( ops.appendToTab ) {         $field.insertAfter(           self._getTab( ops.appendToTab ).find('.ideal-wrap:last-child')         )       } else {         $field.insertAfter( self.$form.find('.ideal-wrap').last() )       }        // Add current field name to list of names       allNames.push( name )     }      // Run through each input     $.each( fields, function( i, ops ) { add( ops ) })      self.reload()     self.freshFields( allNames )     self._responsive()      return this    },    removeFields: function( fields ) {     fields = Utils.convertToArray( fields )     var $fields = Utils.getFieldsFromArray( fields )     $fields.parents('.ideal-wrap').remove()     this.reload()     return this   }  })  }( jQuery, window, document ))

 

觉得 可用,就经常来吧! 欢迎评论哦!  html5教程 ,巧夺天工,精雕玉琢。小宝典献丑了!

总结

以上是 为你收集整理的 html5教程-Html5用户注册自动校验 全部内容,希望文章能够帮你解决 html5教程-Html5用户注册自动校验 所遇到的问题。

如果觉得 网站内容还不错, 推荐好友。

查看更多关于html5教程-Html5用户注册自动校验的详细内容...

  阅读:77次