H5完成用户注册自动校验的实例详解

Y2J
풀어 주다: 2017-05-24 13:27:07
원래의
2406명이 탐색했습니다.

Html5实现用户注册自动校验功能实例代码

05-24 10:49:46作者:php中文网

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

以下是效果截图:

1.页面代码:usersRegister.hbs

XML/HTMLCode 复制内容到剪贴板
  1. >

  2. <htmllang="en">

  3. <head>

  4. <metahttp-equiv="Content-Type"content="text/html; charset=utf-8">

  5. <metahttp-equiv="X-UA-Compatible"content="IE=edge"/>

  6. <title>用户注册 title>

  7. <divclass="main">

  8. <divstyle="height:5px;text-align:center;font-size:25px">欢迎您注册! div>

  9. <formid="my-form"class="myform">

  10. <div>

  11. <label>用户名: label><inputid="username"name="username"type="text"/>

  12. div>

  13. <div>

  14. <label>密码: label><inputid="pass"name="password"type="text"/>

  15. div>

  16. <div>

  17. <label>邮箱: label><inputid="email"name="email"

  18. data-ideal="required email"type="email"/>

  19. div>

  20. <div>

  21. <label>电话: label><inputid="telephone"type="text"name="phone"data-ideal="phone"/>

  22. div>

  23. <div>

  24. <label>供应商V码: label><inputid="vCode"type="text"name="vCode"data-ideal="vCode"/>

  25. div>

  26. <div>

  27. <label>真实姓名: label><inputid="trueName"type="text"name="trueName"data-ideal="trueName"/>

  28. div>

  29. <div>

  30. <label>手机验证码: label><inputid="telCode"type="text"name="telCode"data-ideal="telCode"/>

  31. div>

  32. <divstyle="margin-bottom:5px;">

  33. <buttonid="getTelCode"type="button"style="margin-left:160px;margin-right:auto;">获取手机校验码 button>

  34. <hrstyle="margin-top:5px; margin-bottom:5px;"/>

  35. div>

  36. div>

  37. <scripttype="text/javascript">

  38. varoptions= {

  39. onFail : function() {

  40. alert($myform.getInvalid().length + ' invalid fields.')

  41. },

  42. inputs : {

  43. 'password' : {

  44. filters : 'required pass'

  45. },

  46. 'username' : {

  47. filters : 'required username'

  48. },

  49. 'email' : {

  50. filters : 'required email'

  51. },

  52. 'phone' : {

  53. filters : 'required phone'

  54. },

  55. 'trueName' : {

  56. filters : 'required'

  57. },

  58. 'vCode' : {

  59. filters : 'required'

  60. },

  61. 'telCode' : {

  62. filters : 'required'

  63. }

  64. /*

  65. 'age' : {

  66. filters : 'required digits',

  67. data : {

  68. min : 16,

  69. max : 70

  70. }

  71. },

  72. 'file' : {

  73. filters : 'extension',

  74. data : {

  75. extension : [ 'jpg' ]

  76. }

  77. },

  78. 'comments' : {

  79. filters : 'min max',

  80. data : {

  81. min : 50,

  82. max : 200

  83. }

  84. },

  85. 'states' : {

  86. filters : 'exclude',

  87. data : {

  88. exclude : [ 'default' ]

  89. },

  90. errors: {

  91. exclude : '选择国籍.'

  92. }

  93. },

  94. 'langs[]' : {

  95. filters : 'min max',

  96. data : {

  97. min : 2,

  98. max : 3

  99. },

  100. errors : {

  101. min : 'Check at least<strong>2 strong>options.',

  102. max : 'No more than<strong>3 strong>optionsallowed.'

  103. }

  104. }

  105. */

  106. }

  107. };

  108. $('#getTelCode').click(function() {

  109. vartelephone=document.getElementById("telephone").value; //手机号码

  110. if (telephone==null||telephone== ""){

  111. alert("手机号码不能为空!");

  112. }

  113. else{

  114. $.ajax({

  115. type : "GET",

  116. dataType : "json",

  117. url : "../api/getTelCode?telephone="+ telephone,

  118. success : function(msg) {

  119. },

  120. error : function(e) {

  121. alert("获取手机校验码失败!" + e);

  122. }

  123. });

  124. }

  125. });

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

  127. $('#submit').click(function() {

  128. varusername=document.getElementById("username").value; //用户名

  129. varpassword=document.getElementById("pass").value; //密码

  130. varemail=document.getElementById("email").value; //邮箱

  131. vartelephone=document.getElementById("telephone").value; //手机号码

  132. varvCode=document.getElementById("vCode").value; //公司V码

  133. vartelCode=document.getElementById("telCode").value; //手机校验码

  134. vartrueName=document.getElementById("trueName").value; //真实姓名

  135. $.ajax({

  136. type : "GET",

  137. url : "../api/usersRegister?username="+ username +"password="+ password +"email="+ email +"telephone="+ telephone +"vCode="+ vCode +"telCode="+ telCode +"trueName="+ trueName,

  138. success : function(msg) {

  139. //获取当前网址,如: http://localhost:8083/uimcardprj/share/meun.jsp

  140. varcurWwwPath=window.document.location.href;

  141. //获取主机地址之后的目录,如: uimcardprj/share/meun.jsp

  142. varpathName=window.document.location.pathname;

  143. varpos=curWwwPath.indexOf(pathName);

  144. //获取主机地址,如: http://localhost:8083

  145. varlocalhostPaht=curWwwPath.substring(0, pos);

  146. //获取带"/"的项目名,如:/uimcardprj

  147. varprojectName=pathName.substring(0, pathName.substr(1).indexOf('/') + 1);

  148. window.location.href=projectName+ "/login";

  149. alert("注册成功!");

  150. },

  151. error : function(e) {

  152. alert("注册失败!" + e);

  153. }

  154. });

  155. });

  156. $('#reset').click(function() {

  157. $myform.reset().fresh().focusFirst();

  158. });

  159. script>

  160. body>

  161. 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)'

以下是整个代码文件:

XML/HTML Code 复制内容到剪贴板
  1. /*--------------------------------------------------------------------------

  2. jq-idealforms 2.1

  3. * Author: Cedric Ruiz

  4. * License: GPL or MIT

  5. * Demo: http://elclanrs.github.com/jq-idealforms/

  6. *

  7. --------------------------------------------------------------------------*/

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

  9. 'use strict';

  10. // Global Ideal Forms namespace

  11. $.idealforms= {}

  12. $.idealforms.filters= {}

  13. $.idealforms.errors= {}

  14. $.idealforms.flags= {}

  15. $.idealforms.ajaxRequests= {}

  16. /*--------------------------------------------------------------------------*/

  17. /**

  18. * @namespace A chest for various Utils

  19. */

  20. varUtils= {

  21. /**

  22. * Get width of widest element in the collection.

  23. * @memberOf Utils

  24. * @param {jQueryobject} $elms

  25. * @returns {number}

  26. */

  27. getMaxWidth: function( $elms ) {

  28. varmaxWidth=0

  29. $elms.each(function() {

  30. varwidth= $(this).outerWidth()

  31. if ( width>maxWidth ) {

  32. maxWidth=width

  33. }

  34. })

  35. return maxWidth

  36. },

  37. /**

  38. * Hacky way of getting LESS variables

  39. * @memberOf Utils

  40. * @param {string} name The name of the LESS class.

  41. * @param {string} prop The css property where the data is stored.

  42. * @returns {number, string}

  43. */

  44. getLessVar: function( name, prop ) {

  45. varvalue= $('<pclass="' + name + '"> p>').hide().appendTo('body').css( prop )

  46. $('.' + name).remove()

  47. return ( /^\d+/.test( value ) ? parseInt( value, 10 ) : value )

  48. },

  49. /**

  50. * Like ES5 Object.keys

  51. */

  52. getKeys: function( obj ) {

  53. varkeys= []

  54. for(var key in obj) {

  55. if ( obj.hasOwnProperty( key ) ) {

  56. keys.push( key )

  57. }

  58. }

  59. return keys

  60. },

  61. // Get lenght of an object

  62. getObjSize: function( obj ) {

  63. varsize=0, key;

  64. for ( key in obj ) {

  65. if ( obj.hasOwnProperty( key ) ) {

  66. size++;

  67. }

  68. }

  69. return size;

  70. },

  71. isFunction: function( obj ) {

  72. return typeofobj=== nbsp;'function'

  73. },

  74. isRegex: function( obj ) {

  75. return obj instanceof RegExp

  76. },

  77. isString: function( obj ) {

  78. return typeofobj=== 'string'

  79. },

  80. getByNameOrId: function( str ) {

  81. var $el= $('[name="'+ str +'"]').length

  82. ? $('[name="'+ str +'"]') // by name

  83. : $('#'+ str) // by id

  84. return $el.length

  85. ? $el

  86. : $.error('The field "'+ str + '" doesn\'t exist.')

  87. },

  88. getFieldsFromArray: function( fields ) {

  89. varf= []

  90. for ( vari=0,l=fields.length; i<l; i++ ) {

  91. f.push( Utils.getByNameOrId( fields[i] ).get(0) )

  92. }

  93. return $( f )

  94. },

  95. convertToArray: function( obj ) {

  96. return Object.prototype.toString.call( obj ) === '[object Array]'

  97. ? obj : [ obj ]

  98. },

  99. /**

  100. * Determine type of any Ideal Forms element

  101. * @param $input jQuery $input object

  102. */

  103. getIdealType: function( $el ) {

  104. vartype= $el.attr('type') || $el[0].tagName.toLowerCase()

  105. return (

  106. /(text|password|email|number|search|url|tel|textarea)/.test( type ) && 'text' ||

  107. /file/.test( type ) && 'file' ||

  108. /select/.test( type ) && 'select' ||

  109. /(radio|checkbox)/.test( type ) && 'radiocheck' ||

  110. /(button|submit|reset)/.test( type ) && 'button' ||

  111. /h\d/.test( type ) && 'heading' ||

  112. /hr/.test( type ) && 'separator' ||

  113. /hidden/.test( type ) && 'hidden'

  114. )

  115. },

  116. /**

  117. * Generates an input

  118. * @param name `name` attribute of the input

  119. * @param type `type` or `tagName` of the input

  120. */

  121. makeInput: function( name, value, type, list, placeholder ) {

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

  123. function splitValue( str ) {

  124. var item, value, arr

  125. if ( /::/.test( str ) ) {

  126. arr=str.split('::')

  127. item=arr[ 0 ]

  128. value=arr[ 1 ]

  129. } else {

  130. item=value= str

  131. }

  132. return { item: item, value: value }

  133. }

  134. // Text & file

  135. if ( /^(text|password|email|number|search|url|tel|file|hidden)$/.test(type) )

  136. markup='+

  137. 'type="'+ type +'"'+

  138. 'id="'+ name +'"'+

  139. 'name="'+ name +'"'+

  140. 'value="'+ value +'"'+

  141. (placeholder && 'placeholder="'+ placeholder +'"') +

  142. '/>'

  143. // Textarea

  144. if ( /textarea/.test( type ) ) {

  145. markup='"'+ name +'"value="'+ value +'"> textarea>'

  146. }

  147. // Select

  148. if ( /select/.test( type ) ) {

  149. items= []

  150. for (i=0,len=list.length; i<len; i++ ) {

  151. item=splitValue( list[ i ] ).item

  152. value=splitValue( list[ i ] ).value

  153. items.push('<optionvalue="'+ value +'">'+ item +' option>')

  154. }

  155. markup=

  156. 'menu jQuery plugin* @example `$('select').idealSelect()`*/$.fn.idealSelect=function() {return this.each(function () {var$select= $(this),$options&nbnbsp;= $select.find('option')/*** Generate markup and return elements of custom select* @memberOf $.fn.toCustomSelect* @returns {object} All elements of the new select replacement*/varidealSelect= (function () {var$wrap= $(''),$menu= $('

  157. ' +$options.filter(':selected').text() +' span> li>'),items= (function () {varitems= []$options.each(function () {var $this= $(this)items.push('' + $this.text() + ' li>')})return items}())$menu.append('' + 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*/varActions= {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 keyboardfocusHack: 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 submenuvarelPos= $selected.position().top + itemHeightreturndir=== 'down'? elPos<= menuHeight: elPos>0}())if (!isInView) {itemHeight= (dir=== 'down')? itemHeight // go down: -itemHeight // go upidealSelect.sub.scrollTop(idealSelect.sub.scrollTop() + itemHeight)}},scrollToItem: function () {varidx=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) {vartext=idealSelect.items.eq(idx).text()Actions.select(idx)idealSelect.title.text(text)$options.eq(idx).prop('selected', true)$select.trigger('change')},keydown: function (key) {varidx=Actions.getSelectedIdx(),isMenu=idealSelect.select.is('.ideal-select-menu'),isOpen=idealSelect.select.is('.ideal-select-open')/*** @namespace Key pressed*/varkeys= {9: function () { // TABif (isMenu) {Actions.blur()Actions.hideMenu()}},13: function () { // ENTERif (isMenu)isOpen? Actions.hideMenu(): Actions.showMenu()Actions.change(idx)},27: function () { // ESCif (isMenu) Actions.hideMenu()},40: function () { // DOWNif (idx<$options.length - 1) {isOpen? Actions.select(idx + 1): Actions.change(idx + 1)}Actions.scrollIntoView('down')},38: function () { // UPif (idx>0) {isOpen? Actions.select(idx - 1): Actions.change(idx - 1)}Actions.scrollIntoView('up')},'default': function () { // Lettervarletter=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 matchesreturn false// If more matches with same letterif (curKey=== key) {if (counter')$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?varmultipleSupport=typeof$('')[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= $(''),$input= $(''),// Button that will be used in non-IE browsers$button= $('Open button>'),// Hack for IE$label= $('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() {varfiles= [], fileArr, filename// If multiple is supported thenextract// all filenames from the file arrayif ( multipleSupport ) {fileArr= $file[0].filesfor ( vari=0,len=fileArr.length; i(例: user@gmail.com) em>',phone: '必须是一个有效的手机号码.(例: 18723101212) em>',zip: 'Must be a valid US zip code.(e.g. 33245 or 33245-0003) em>',url: 'Must be a valid URL.(e.g. www.google.com) em>',minChar: 'Must be at least{0} strong>characters long.',minOption: 'Check at least{0} strong>options.',maxChar: 'No more than{0} strong>characters long.',maxOption: 'No more than{0} strong>options allowed.',range: 'Must be a number between {0} and {1}.',date: 'Must be a valid date.(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"{0}" strong>',extension: 'File(s) must have a valid extension.(e.g. "{0}") em>',ajaxSuccess: '{0} strong>is not available.',ajaxError: 'Server error...'}/*** Get all default filters* @returns object*/vargetFilters=function() {varfilters= {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 $inputinput= 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 $inputinput= 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 ) {varrange=input.userOptions.data.range,val= +valuethis.error= $.idealforms.errors.range.replace( '{0}', range[0] ).replace( '{1}', range[1] )return val>= range[0] && val<= range[1]}},date: {regex: function( input, value ) {varuserFormat=input.userOptions.data && input.userOptions.data.date? input.userOptions.data.date: 'mm/dd/yyyy', // default formatdelimiter= /[^mdy]/.exec( userFormat )[0],theFormat=userFormat.split(delimiter),theDate=value.split(delimiter),isDate=function( date, format ) {var m, d, yfor ( vari=0,len=format.length; i0 && 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 ) {varuserFormat=input.userOptions.data && input.userOptions.data.dob? input.userOptions.data.dob: 'mm/dd/yyyy', // default format// Simulate a date inputdateInput= {input: input.input,userOptions: {data: { date: userFormat }}},// Use internal date filter to validatethe dateisDate=filters.date.regex( dateInput, value ),// DOBtheYear= /\d{4}/.exec( value ),maxYear=newDate().getFullYear(), //CurrentyearminYear=maxYear- 100this.error= $.idealforms.errors.dobreturn isDate && theYear>= minYear && theYear<= maxYear}},exclude: {regex: function( input, value ) {var $inputinput= 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 ),$inputinput= input.input,name= $equals.attr('name') || $equals.attr('id'),isValid= $equals.parents('.ideal-field').filter(function(){ return $(this).data('ideal-isvalid') === true }).lengthif ( !isValid ) { return false }this.error= $.idealforms.errors.equalto.replace( '{0}', name )return $input.val() === $equals.val()}},extension: {regex: function( input, value ) {nbsp;varfiles=input.input[0].files || [{ name: value }],extensions=input.userOptions.data.extension,re=newRegExp( '\\.'+ extensions.join('|') +'$', 'i' ),valid=falsefor ( vari=0,len=files.length; i')self.$form.prepend( $tabContainer )self.$tabs.idealTabs( $tabContainer )}// Always show datepicker below the inputif ( jQuery.ui ) {$.datepicker._checkOffset=function( a,b,c ) { return b }}// Add inputs specified by data-ideal// to the list of user inputsself.$form.find('[data-ideal]').each(function() {varuserInput=o.inputs[ this.name ]o.inputs[ this.name ] = userInput || { filters: $(this).data('ideal') }})// Responsiveif ( o.responsiveAt ) {$(window).resize(function(){ self._responsive() })self._responsive()}// Form eventsself.$form.on({keydown: function( e ) {// Prevent submit when pressing enter// but exclude textareasif (e.which=== 13 && e.target.nodeName !== 'TEXTAREA' ) {e.preventDefault()}},submit: function( e ) {if ( !self.isValid() ) {e.preventDefault()o.onFail()self.focusFirstInvalid()} else {o.onSuccess( e )}}})self._adjust()self._attachEvents()self.fresh() // Start fresh},_getFormElements: function() {return {inputs: this.$form.find('input, select, textarea, :button'),labels: this.$form.find('div>label:first-child'),text: this.$form.find('input:not([type="checkbox"], [type="radio"], [type="submit"]), textarea'),select: this.$form.find('select'),radiocheck: this.$form.find('input[type="radio"], input[type="checkbox"]'),buttons: this.$form.find(':button'),file: this.$form.find('input[type="file"]'),headings: this.$form.find('h1, h2, h3, h4, h5, h6'),separators: this.$form.find('hr'),hidden: this.$form.find('input:hidden')}},_getUserInputs: function() {return this.$form.find('[name="'+ Utils.getKeys( this.opts.inputs ).join('"], [name="') +'"]')},_getTab: function( nameOrIdx ) {varself=thisvarisNumber= !isNaN( nameOrIdx )if ( isNumber ) {return self.$tabs.eq( nameOrIdx )}return self.$tabs.filter(function() {varre=newRegExp( nameOrIdx, 'i' )return re.test( nbsp;$(this).data('ideal-tabs-content-name') )})},_getCurrentTabIdx: function() {return this.$tabs.index( this.$form.find('.ideal-tabs-content:visible') )},_updateTabsCounter: function() {varself=thisself.$tabs.each(function( i ) {varinvalid=self.getInvalidInTab( i ).lengthself.$tabs.updateCounter( i, invalid )})},_adjust: function() {varself=thisvaro=self.optsvarformElements=self._getFormElements()varcurTab=self._getCurrentTabIdx()// Autocomplete causes some problems...formElements.inputs.attr('autocomplete', 'off')// Show tabs to calculate dimensionsif ( self.$tabs.length ) { self.$tabs.show() }// Adjust labelsvarlabels=formElements.labelslabels.removeAttr('style').width( Utils.getMaxWidth( labels ) )// Adjust headings and separatorsif ( 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 tabsif ( self.$tabs.length ) {self.$tabs.hide()self.switchTab( curTab )}},_setDatepicker: function() {varo=this.optsvar $datepicker=this.$form.find('input.datepicker')if ( jQuery.ui && $datepicker.length ) {$datepicker.each(function() {varuserInput=o.inputs[ this.name ]vardata=userInput&& userInput.data && userInput.data.datevarformat=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 resizingvar $this= $(this)varw= $this.outerWidth() //cachefirst!setTimeout(function() {$this.datepicker('widget').css( 'width', w )}, 1)},onClose: function() { $(this).removeClass('open') }})})// Adjust width$datepicker.on('focus keyup', function() {vart= $(this),w=t.outerWidth()t.datepicker('widget').css( 'width', w )})$datepicker.parent().siblings('.ideal-error').addClass('hidden')}},_doMarkup: function( $element ) {varo=this.optsvarelementType=Utils.getIdealType( $element )// Validation elementsvar $field= $('')var $error= $('')var $valid= $('')var $invalid= $('').click(function(){$(this).parent().find('input:first, textarea, select').focus()})// Basic markup$element.closest('div').addClass('ideal-wrap').children('label:first-child').addClass('ideal-label')varidealElements= {_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 oncevarisWrapped= $element.parents('.ideal-field').lengthif ( !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('div').addClass('ideal-hidden')},heading: function() {$element.closest('div').addClass('ideal-full-width')$element.parent().children().wrapAll('')},separator: function() {$element.closest('div').addClass('ideal-full-width')$element.wrapAll('')}}// Generate markup for current element typeidealElements[ 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 ) {varself=thisvaro=this.optsvaruserOptions= o.inputs[ $input.attr('name') ]varuserFilters=userOptions.filters && userOptions.filters.split(/\s/)varname= $input.attr('name')varvalue= $input.val()varajaxRequest= $.idealforms.ajaxRequests[ name ]varisRadioCheck= $input.is('[type="checkbox"], [type="radio"]')varinputData= {// If is radio or check validate all inputs related by nameinput: isRadioCheck ? self.$form.find('[name="' + name + '"]') : $input,userOptions: userOptions}// Validation elementsvar $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 requestsvaroldValue= $input.data('ideal-value') || 0$input.data( 'ideal-value', value )if (e.type=== 'keyup' &&value=== oldValue ) { return false }// Validateif ( userFilters ) {$.each( userFilters, function( i, filter ) {vartheFilter= $.idealforms.filters[ filter ]varcustomError=userOptions.errors && userOptions.errors[ filter ]varerror=''// If field is empty and not requiredif ( !value && filter !== 'required' ) {resetError()return false}if ( theFilter ) {// Abort and reset ajax if there's a request pendingif (e.type=== 'keyup' && ajaxRequest ) {ajaxRequest.abort()$field.removeClass('ajax')}// AJAXif (filter=== 'ajax' ) {nbsp; 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 {varajaxError= $input.data('ideal-ajax-error')if ( ajaxError ) {showOrHideError( ajaxError, $input.data('ideal-ajax-resp') || false )}}}// All other filterselse {varvalid=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 filterselse {resetError()}// Flagsvarflags= (function(){varf=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 ) {vartheFlag= $.idealforms.flags[f]if ( theFlag ) { theFlag( $input, e.type ) }})}// Update counterif ( self.$tabs.length ) {self._updateTabsCounter( self._getCurrentTabIdx() )}},_attachEvents: function() {varself=thisself._getUserInputs().on('keyup change focus blur', function(e) {var $this= $(this)var $field= $this.parents('.ideal-field')varisFile= $this.is('input[type=file]')// Trigger on change iftype=filecuz 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() {varformElements=this._getFormElements()varmaxWidth=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()'+'