H5完成用户注册自动校验的实例详解
Html5实现用户注册自动校验功能实例代码
05-24 10:49:46作者:
抽时间写了一个带有自动校验功能的Html5用户注册Demo。使用到Handlebars模板技术和手机验证码校验。
以下是效果截图:
1.页面代码:usersRegister.hbs
XML/HTML Code 复制内容到剪贴板
-
<!DOCTYPE html>
-
<!–[if IE 8 ]> <html lang=”en” class=”ie8″> <![endif]–>
-
<!–[if IE 9 ]> <html lang=”en” class=”ie9″> <![endif]–>
-
<!–[if (gt IE 9)|!(IE)]><!–>
-
<html lang=“en”>
-
<!–<![endif]–>
-
<head>
-
<meta http-equiv=“Content-Type” content=“text/html; charset=utf-8”>
-
<meta http-equiv=“X-UA-Compatible” content=“IE=edge” />
-
<title>用户注册</title>
-
<!–[if lt IE 9]>
-
<script src=“/assets/scripts/html5shiv.js”></script>
-
<![endif]–>
-
<link href=“/assets/styles/jquery.idealforms.min.css” rel=“stylesheet” media=“screen” />
-
<style type=“text/css”>
-
body {
-
font: normal 15px/1.5 Arial, Helvetica, Free Sans, sans-serif;
-
color: #222;
-
overflow-y: scroll;
-
padding: 60px 0 0 0;
-
}
-
.main {
-
width: 560px;
-
height: 480px;
-
margin: -50px auto;
-
}
-
#my-form {
-
width: 560px;
-
height: 450px;
-
margin: 0 auto;
-
border: 1px solid #ccc;
-
padding: 3em;
-
border-radius: 3px;
-
box-shadow: 0 0 2px rgba(0, 0, 0, .2);
-
}
-
</style>
-
<script type=“text/javascript” src=“/assets/scripts/jquery-1.8.2.min.js”></script>
-
<script type=“text/javascript” src=“/assets/scripts/jquery.idealforms.js”></script>
-
</head>
-
<body>
-
<!– style=”background-image: url(static/image/bg.jpg) –>
-
<div class=“main” >
-
<div style=“height:5px;text-align:center;font-size:25px”> 欢迎您注册!</div>
-
<!– Begin Form –>
-
<form id=“my-form” class=“myform”>
-
<div>
-
<label>用户名:</label><input id=“username” name=“username” type=“text” />
-
</div>
-
<div>
-
<!– <label>密码:</label><input id=”pass” name=”password” type=”password” /> –>
-
<label>密码:</label><input id=“pass” name=“password” type=“text” />
-
</div>
-
<div>
-
<label>邮箱:</label><input id=“email” name=“email”
-
data-ideal=“required email” type=“email” />
-
</div>
-
<div>
-
<label>电话:</label><input id=“telephone” type=“text” name=“phone” data-ideal=“phone” />
-
</div>
-
<div>
-
<label>供应商V码:</label><input id=“vCode” type=“text” name=“vCode” data-ideal=“vCode” />
-
</div>
-
<div>
-
<label>真实姓名:</label><input id=“trueName” type=“text” name=“trueName” data-ideal=“trueName” />
-
</div>
-
<div>
-
<label>手机验证码:</label><input id=“telCode” type=“text” name=“telCode” data-ideal=“telCode” />
-
</div>
-
<div style=“margin-bottom:5px;”>
-
<button id=“getTelCode” type=“button” style=“margin-left:160px; margin-right:auto;” >获取手机校验码</button>
-
<hr style=“margin-top:5px; margin-bottom:5px;” />
-
</div>
-
<!–<div>
-
<label>性别:</label>
-
<select id=“sex” name=“sex”>
-
<option value=“男”>男</option>
-
<option value=“女”>女</option>
-
</select>
-
</div>
-
<div>
-
<label>昵称:</label><input id=“nickName” type=“text” name=“nickName” data-ideal=“nickName” />
-
</div>
-
<div>
-
nbsp; <label>年龄:</label><input id=“age” type=“text” name=“age” data-ideal=“age” />
-
</div>—>
-
<!– <div>
-
<label>地址:</label><input type=“text” name=“address” data-ideal=“address” />
-
</div>
-
<div>
-
<label>QQ:</label><input type=“text” name=“qq” data-ideal=“qq” />
-
</div>
-
<div>
-
<label>邮编:</label><input type=“text” name=“zip” data-ideal=“zip” />
-
</div>
-
<div>
-
<label>传真:</label><input type=“text” name=“fax” data-ideal=“fax” />
-
</div>
-
<div>
-
<label>身份证:</label><input type=“text” name=“creditID” data-ideal=“creditID” />
-
</div>
-
<div>
-
<label>出生日期:</label><input name=“date” class=“datepicker”
-
data-ideal=“date” type=“text” placeholder=“月/日/年” />
-
</div>
-
<div>
-
<label>上传头像:</label><input id=“file” name=“file” multiple
-
type=“file” />
-
</div>
-
<div>
-
<label>个人主页:</label><input name=“website” data-ideal=“url”
-
type=“text” />
-
</div>
-
<div>
-
<label>备注:</label>
-
<textarea id=“comments” name=“comments”></textarea>
-
</div>
-
—>
-
<!– <div id=“languages”>
-
<label>语言:</label> <label><input type=“checkbox”
-
name=“langs[]” value=“English” />英文</label> <label><input
-
type=“checkbox” name=“langs[]” value=“Chinese” />中文</label> <label><input
-
type=“checkbox” name=“langs[]” value=“Spanish” />西班牙文</label> <label><input
-
type=“checkbox” name=“langs[]” value=“French” />法文</label>
-
</div>
-
<div>
-
<label>精通几门:</label> <label><input type=“radio”
-
name=“radio” checked />1</label> <label><input type=“radio”
-
name=“radio” />2</label> <label><input type=“radio” name=“radio” />3</label>
-
<label><input type=“radio” name=“radio” />4</label>
-
</div>
-
<div>
-
<label>国籍:</label> <select id=“states” name=“states”>
-
<option value=“default”>– 选择国籍 –</option>
-
<option value=“AL”>阿拉伯</option>
-
<option value=“AK”>中国</option>
-
<option value=“AZ”>美国</option>
-
<option value=“AR”>法国</option>
-
<option value=“CA”>英国</option>
-
<option value=“CO”>德国</option>
-
<option value=“CT”>西班牙</option>
-
<option value=“DE”>俄罗斯</option>
-
</select>
-
</div> —>
-
<div style=“margin-top:10px; margin-left:100px;margin-right:100px;”>
-
<button type=“button” id=“submit” class=“submit”>提交</button>
-
<button id=“reset” type=“button” >重置</button>
-
</div>
-
</form>
-
<!– End Form –>
-
</div>
-
<script type=“text/javascript”>
-
var options = {
-
onFail : function() {
-
alert($myform.getInvalid().length + ‘ invalid fields.’)
-
},
-
inputs : {
-
‘password’ : {
-
filters : ‘required pass’
-
},
-
‘username’ : {
-
filters : ‘required username’
-
},
-
’email’ : {
-
filters : ‘required email’
-
},
-
‘phone’ : {
-
filters : ‘required phone’
-
},
-
‘trueName’ : {
-
filters : ‘required’
-
},
-
‘vCode’ : {
-
filters : ‘required’
-
},
-
‘telCode’ : {
-
filters : ‘required’
-
}
-
/*
-
‘age’ : {
-
filters : ‘required digits’,
-
data : {
-
min : 16,
-
max : 70
-
}
-
},
-
‘file’ : {
-
filters : ‘extension’,
-
data : {
-
extension : [ ‘jpg’ ]
-
}
-
},
-
‘comments’ : {
-
filters : ‘min max’,
-
data : {
-
min : 50,
-
max : 200
-
}
-
},
-
‘states’ : {
-
filters : ‘exclude’,
-
data : {
-
exclude : [ ‘default’ ]
-
},
-
errors : {
-
exclude : ‘选择国籍.’
-
}
-
},
-
‘langs[]’ : {
-
filters : ‘min max’,
-
data : {
-
min : 2,
-
max : 3
-
},
-
errors : {
-
min : ‘Check at least <strong>2</strong> options.’,
-
max : ‘No more than <strong>3</strong> options allowed.’
-
}
-
}
-
*/
-
}
-
};
-
$(‘#getTelCode’).click(function() {
-
var telephone = document.getElementById(“telephone”).value; //手机号码
-
if (telephone == null || telephone == “”){
-
alert(“手机号码不能为空!”);
-
}
-
else{
-
$.ajax({
-
type : “GET”,
-
dataType : “json”,
-
url : “../api/getTelCode?telephone=”+ telephone,
-
success : function(msg) {
-
},
-
error : function(e) {
-
alert(“获取手机校验码失败!” + e);
-
}
-
});
-
}
-
});
-
var $myform = $(‘#my-form’).idealforms(options).data(‘idealforms’);
-
$(‘#submit’).click(function() {
-
var username = document.getElementById(“username”).value; //用户名
-
var password = document.getElementById(“pass”).value; //密码
-
var email = document.getElementById(“email”).value; //邮箱
-
var telephone = document.getElementById(“telephone”).value; //手机号码
-
var vCode = document.getElementById(“vCode”).value; //公司V码
-
var telCode = document.getElementById(“telCode”).value; //手机校验码
-
var trueName = document.getElementById(“trueName”).value; //真实姓名
-
$.ajax({
-
type : “GET”,
-
url : “../api/usersRegister?username=“+ username +”password=“+ password +”email=“+ email +”telephone=“+ telephone +”vCode=“+ vCode +”telCode=“+ telCode +”trueName=”+ trueName,
-
success : function(msg) {
-
//获取当前网址,如: http://localhost:8083/uimcardprj/share/meun.jsp
-
var curWwwPath = window.document.location.href;
-
//获取主机地址之后的目录,如: uimcardprj/share/meun.jsp
-
var pathName = window.document.location.pathname;
-
var pos = curWwwPath.indexOf(pathName);
-
//获取主机地址,如: http://localhost:8083
-
var localhostPaht = curWwwPath.substring(0, pos);
-
//获取带”/”的项目名,如:/uimcardprj
-
var projectName = pathName.substring(0, pathName.substr(1).indexOf(‘/’) + 1);
-
window.location.href = projectName + “/login”;
-
alert(“注册成功!”);
-
},
-
error : function(e) {
-
alert(“注册失败!” + e);
-
}
-
});
-
});
-
$(‘#reset’).click(function() {
-
$myform.reset().fresh().focusFirst();
-
});
-
</script>
-
</body>
-
</html>
2.jq输入校验:jquery.idealforms.js
该js校验初始版本来自Cedric Ruiz,我略有修改。
部分校验的规则如下:
required: ‘此处是必填的.’
number: ‘必须是数字.’,
digits: ‘必须是唯一的数字.’
name: ‘必须至少有3个字符长,并且只能包含字母.’
username: ‘用户名最短5位,最长30位,请使用英文字母、数字、中文和下划线. 用户名首字符必须为字母、数字、中文,不能为全数字.中文最长21个字.’
pass: ‘密码的位数必须的在6-15位之间,并且至少包含一个数字,一个大写字母和一个小写字母.’
strongpass: ‘必须至少为8个字符长,至少包含一个大写字母和一个小写字母和一个数字或特殊字符.’
email: ‘必须是一个有效的email地址. <em>(例: user@gmail.com)</em>’
phone: ‘必须是一个有效的手机号码. <em>(例: 18723101212)</em>’
以下是整个代码文件:
XML/HTML Code 复制内容到剪贴板
-
/*————————————————————————–
-
jq-idealforms 2.1
-
* Author: Cedric Ruiz
-
* License: GPL or MIT
-
* Demo: http://elclanrs.github.com/jq-idealforms/
-
*
-
————————————————————————–*/
-
;(function ( $, window, document, undefined ) {
-
‘use strict’;
-
// Global Ideal Forms namespace
-
$.idealforms = {}
-
$.idealforms.filters = {}
-
$.idealforms.errors = {}
-
$.idealforms.flags = {}
-
$.idealforms.ajaxRequests = {}
-
/*————————————————————————–*/
-
/**
-
* @namespace A chest for various Utils
-
*/
-
var Utils = {
-
/**
-
* Get width of widest element in the collection.
-
* @memberOf Utils
-
* @param {jQuery object} $elms
-
* @returns {number}
-
*/
-
getMaxWidth: function( $elms ) {
-
var maxWidth = 0
-
$elms.each(function() {
-
var width = $(this).outerWidth()
-
if ( width > maxWidth ) {
-
maxWidth = width
-
}
-
})
-
return maxWidth
-
},
-
/**
-
* Hacky way of getting LESS variables
-
* @memberOf Utils
-
* @param {string} name The name of the LESS class.
-
* @param {string} prop The css property where the data is stored.
-
* @returns {number, string}
-
*/
-
getLessVar: function( name, prop ) {
-
var value = $(‘<p class=“‘ + name + ‘”></p>‘).hide().appendTo(‘body’).css( prop )
-
$(‘.’ + name).remove()
-
return ( /^\d+/.test( value ) ? parseInt( value, 10 ) : value )
-
},
-
/**
-
* Like ES5 Object.keys
-
*/
-
getKeys: function( obj ) {
-
var keys = []
-
for(var key in obj) {
-
if ( obj.hasOwnProperty( key ) ) {
-
keys.push( key )
-
}
-
}
-
return keys
-
},
-
// Get lenght of an object
-
getObjSize: function( obj ) {
-
var size = 0, key;
-
for ( key in obj ) {
-
if ( obj.hasOwnProperty( key ) ) {
-
size++;
-
}
-
}
-
return size;
-
},
-
isFunction: function( obj ) {
-
return typeof obj === nbsp;’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,
-
$containercontainer = 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&nbnbsp;= $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 {
-
&nnbsp;idealSelect.select.data(‘counter’, 0)
-
newIdx = $matches.eq(0).index()
-
}
-
if (isOpen)
-
Actions.select(newIdx)
-
else
-
Actions.change(newIdx)
-
idealSelect.select.data(‘key’, key)
-
Actions.scrollToItem()
-
Actions.focusHack()
-
}
-
}
-
keys[key]
-
? keys[key]()
-
: keys[‘default’]()
-
}
-
}
-
/**
-
* @namespace Holds all events of custom select for “menu mode” and “list mode”
-
* @memberOf $.fn.toCustomSelect
-
*/
-
var events = {
-
focus: Actions.focus,
-
‘blur.menu’: function () {
-
Actions.blur()
-
Actions.hideMenu()
-
},
-
‘blur.list’: function () {
-
Actions.blur()
-
},
-
keydown: function (e) {
-
Actions.keydown(e.which)
-
},
-
‘clickItem.menu’: function () {
-
Actions.change($(this).index())
-
Actions.hideMenu()
-
},
-
‘clickItem.list’: function () {
-
Actions.change($(this).index())
-
},
-
‘clickTitle.menu’: function () {
-
Actions.focus()
-
Actions.showMenu()
-
$select.trigger(‘focus’)
-
},
-
‘hideOutside.menu’: function () {
-
$select.off(‘blur.menu’)
-
$(document).on(‘mousedown.ideal’, function (evt) {
-
if (!$(evt.target).closest(idealSelect.select).length) {
-
$(document).off(‘mousedown.ideal’)
-
$select.on(‘blur.menu’, events[‘blur.menu’])
-
} else {
-
Actions.focusHack()
-
}
-
})
-
},
-
‘mousedown.list’: function () {
-
Actions.focusHack()
-
}
-
}
-
// Reset events
-
var disableEvents = function () {
-
idealSelect.select.removeClass(‘ideal-select-menu ideal-select-list’)
-
$select.off(‘.menu .list’)
-
idealSelect.items.off(‘.menu .list’)
-
idealSelect.select.off(‘.menu .list’)
-
idealSelect.title.off(‘.menu .list’)
-
}
-
// Menu mode
-
idealSelect.select.on(‘menu’, function () {
-
disableEvents()
-
idealSelect.select.addClass(‘ideal-select-menu’)
-
Actions.hideMenu()
-
$select.on({
-
‘blur.menu’: events[‘blur.menu’],
-
‘focus.menu’: events.focus,
-
‘keydown.menu’: events.keydown
-
})
-
idealSelect.select.on(‘mousedown.menu’, events[‘hideOutside.menu’])
-
idealSelect.items.on(‘click.menu’, events[‘clickItem.menu’])
-
idealSelect.title.on(‘click.menu’, events[‘clickTitle.menu’])
-
})
-
// List mode
-
idealSelect.select.on(‘list’, function () {
-
disableEvents()
-
idealSelect.select.addClass(‘ideal-select-list’)
-
Actions.showMenu()
-
$select.on({
-
‘blur.list’: events[‘blur.list’],
-
‘focus.list’: events.focus,
-
‘keydown.list’: events.keydown
-
})
-
idealSelect.select.on(‘mousedown.list’, events[‘mousedown.list’])
-
idealSelect.items.on(‘mousedown.list’, events[‘clickItem.list’])
-
})
-
$select.keydown(function (e) {
-
// Prevent default keydown event
-
// to avoid bugs with Ideal Select events
-
if (e.which !== 9) e.preventDefault()
-
})
-
// Reset
-
idealSelect.select.on(‘reset’, function(){
-
Actions.change(0)
-
})
-
idealSelect.select.trigger(‘menu’) // Default to “menu mode”
-
})
-
}
-
/*
-
* idealRadioCheck: jQuery plguin for checkbox and radio replacement
-
* Usage: $(‘input[type=checkbox], input[type=radio]’).idealRadioCheck()
-
*/
-
$.fn.idealRadioCheck = function() {
-
return this.each(function() {
-
var $this = $(this)
-
var $span = $(‘<span/>‘)
-
$span.addClass( ‘ideal-‘+ ( $this.is(‘:checkbox’) ? ‘check’ : ‘radio’ ) )
-
$this.is(‘:checked’) && $span.addClass(‘checked’) // init
-
$span.insertAfter( $this )
-
$this.parent(‘label’).addClass(‘ideal-radiocheck-label’)
-
.attr(‘onclick’, ”) // Fix clicking label in iOS
-
$this.css({ position: ‘absolute’, left: ‘-9999px’ }) // hide by shifting left
-
// Events
-
$this.on({
-
change: function() {
-
var $this = $(this)
-
if ( $this.is(‘input[type=“radio”]’) ) {
-
$this.parent().siblings(‘label’).find(‘.ideal-radio’).removeClass(‘checked’)
-
}
-
$span.toggleClass( ‘checked’, $this.is(‘:checked’) )
-
},
-
focus: function() { $span.addClass(‘focus’) },
-
blur: function() { $span.removeClass(‘focus’) },
-
click: function() { $(this).trigger(‘focus’) }
-
})
-
})
-
}
-
;(function( $ ) {
-
// Browser supports HTML5 multiple file?
-
var multipleSupport = typeof $(‘<input/>‘)[0].multiple !== ‘undefined’,
-
isIE = /msie/i.test( navigator.userAgent )
-
$.fn.idealFile = function() {
-
return this.each(function() {
-
var $file = $(this).addClass(‘ideal-file’), // the original file input
-
// label that will be used for IE hack
-
$wrap = $(‘<div class=“ideal-file-wrap”>‘),
-
$input = $(‘<input type=“text” class=“ideal-file-filename” />‘),
-
// Button that will be used in non-IE browsers
-
$button = $(‘<button type=“button” class=“ideal-file-upload”>Open</button>‘),
-
// Hack for IE
-
$label = $(‘<label class=“ideal-file-upload” for=“‘+ $file[0].id +'”>Open</label>‘)
-
// Hide by shifting to the left so we
-
// can still trigger events
-
$file.css({
-
position: ‘absolute’,
-
left: ‘-9999px’
-
})
-
$wrap.append( $input, ( isIE ? $label : $button ) ).insertAfter( $file )
-
// Prevent focus
-
$file.attr(‘tabIndex’, -1)
-
$button.attr(‘tabIndex’, -1)
-
$button.click(function () {
-
$file.focus().click() // Open dialog
-
})
-
$file.change(function() {
-
var files = [], fileArr, filename
-
// If multiple is supported then extract
-
// all filenames from the file array
-
if ( multipleSupport ) {
-
fileArr = $file[0].files
-
for ( var i = 0, len = fileArr.length; i < len; i++ ) {
-
files.push( fileArr[i].name )
-
}
-
filename = files.join(‘, ‘)
-
// If not supported then just take the value
-
// and remove the path to just show the filename
-
} else {
-
filename = $file.val().split(‘\\’).pop()
-
}
-
$input.val( filename ) // Set the value
-
.attr( ‘title’, filename ) // Show filename in title tootlip
-
})
-
$input.on({
-
focus: function () { $file.trigger(‘change’) },
-
blur: function () { $file.trigger(‘blur’) },
-
keydown: function( e ) {
-
if ( e.which === 13 ) { // Enter
-
if ( !isIE ) { $file.trigger(‘click’) }
-
} else if ( e.which === 8 || e.which === 46 ) { // Backspace & Del
-
// On some browsers the value is read-only
-
// with this trick we remove the old input and add
-
// a clean clone with all the original events attached
-
$file.replaceWith( $file = $file.val(”).clone( true ) )
-
$file.trigger(‘change’)
-
$input.val(”)
-
} else if ( e.which === 9 ){ // TAB
-
return
-
} else { // All other keys
-
return false
-
}
-
}
-
})
-
})
-
}
-
}( jQuery ))
-
/**
-
* @namespace Errors
-
* @locale en
-
*/
-
$.idealforms.errors = {
-
required: ‘此处是必填的.’,
-
number: ‘必须是数字.’,
-
digits: ‘必须是唯一的数字.’,
-
name: ‘必须至少有3个字符长,并且只能包含字母.’,
-
username: ‘用户名最短5位,最长30位,请使用英文字母、数字、中文和下划线.用户名首字符必须为字母、数字、中文,不能为全数字.中文最长21个字.’,
-
pass: ‘密码的位数必须的在6-15位之间,并且至少包含一个数字,一个大写字母和一个小写字母.’,
-
strongpass: ‘必须至少为8个字符长,至少包含一个大写字母和一个小写字母和一个数字或特殊字符.’,
-
email: ‘必须是一个有效的email地址. <em>(例: user@gmail.com)</em>‘,
-
phone: ‘必须是一个有效的手机号码. <em>(例: 18723101212)</em>‘,
-
zip: ‘Must be a valid US zip code. <em>(e.g. 33245 or 33245-0003)</em>‘,
-
url: ‘Must be a valid URL. <em>(e.g. www.google.com)</em>‘,
-
minChar: ‘Must be at least <strong>{0}</strong> characters long.’,
-
minOption: ‘Check at least <strong>{0}</strong> options.’,
-
maxChar: ‘No more than <strong>{0}</strong> characters long.’,
-
maxOption: ‘No more than <strong>{0}</strong> options allowed.’,
-
range: ‘Must be a number between {0} and {1}.’,
-
date: ‘Must be a valid date. <em>(e.g. {0})</em>‘,
-
dob: ‘Must be a valid date of birth.’,
-
exclude: ‘”{0}” is not available.’,
-
excludeOption: ‘{0}’,
-
equalto: ‘Must be the same value as <strong>“{0}”</strong>‘,
-
extension: ‘File(s) must have a valid extension. <em>(e.g. “{0}”)</em>‘,
-
ajaxSuccess: ‘<strong>{0}</strong> is not available.’,
-
ajaxError: ‘Server error…’
-
}
-
/**
-
* Get all default filters
-
* @returns object
-
*/
-
var getFilters = function() {
-
var filters = {
-
required: {
-
regex: /.+/,
-
error: $.idealforms.errors.required
-
},
-
number: {
-
regex: function( i, v ) { return !isNaN(v) },
-
error: $.idealforms.errors.number
-
},
-
digits: {
-
regex: /^\d+$/,
-
error: $.idealforms.errors.digits
-
},
-
name: {
-
regex: /^[A-Za-z]{3,}$/,
-
error: $.idealforms.errors.name
-
},
-
username: {
-
regex: /^[a-z](?=[\w.]{4,30}$)\w*\.?\w*$/i,
-
error: $.idealforms.errors.username
-
},
-
pass: {
-
regex: /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/,
-
error: $.idealforms.errors.pass
-
},
-
strongpass: {
-
regex: /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/,
-
error: $.idealforms.errors.strongpass
-
},
-
email: {
-
regex: /^([a-zA-Z0-9]*[-_.]?[a-zA-Z0-9]+)*@([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)+[\\.][A-Za-z]{2,3}([\\.][A-Za-z]{2})?$/,
-
error: $.idealforms.errors.email
-
},
-
phone: {
-
//regex: /^((13[0-9])|(15[0-9])|(17[0-9])|(18[0-9]))\\d{8}$/,
-
regex: /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/,
-
error: $.idealforms.errors.phone
-
},
-
zip: {
-
regex: /^\d{5}$|^\d{5}-\d{4}$/,
-
error: $.idealforms.errors.zip
-
},
-
url: {
-
regex: /^(?:(ftp|http|https):\/\/)?(?:[\w\-]+\.)+[a-z]{2,6}([\:\/?#].*)?$/i,
-
error: $.idealforms.errors.url
-
},
-
min: {
-
regex: function( input, value ) {
-
var $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 ) {
-
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 $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 })
-
.length
-
if ( !isValid ) { return false }
-
this.error = $.idealforms.errors.equalto.replace( ‘{0}’, name )
-
return $input.val() === $equals.val()
-
}
-
},
-
extension: {
-
regex: function( input, value ) {
-
nbsp;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 $inputinput = input.input
-
var userOptions = input.userOptions
-
var name = $input.attr(‘name’)
-
var $field = $input.parents(‘.ideal-field’)
-
var valid = false
-
var customErrors = userOptions.errors && userOptions.errors.ajax
-
self.error = {}
-
self.error.success = customErrors && customErrors.success
-
? customErrors.success
-
: $.idealforms.errors.ajaxSuccess.replace( ‘{0}’, value )
-
self.error.fail = customErrors && customErrors.error
-
? customErrors.error
-
: $.idealforms.errors.ajaxError
-
// Send input name as $_POST[name]
-
var data = {}
-
data[ name ] = $.trim( value )
-
// Ajax options defined by the user
-
var userAjaxOps = input.userOptions.data.ajax
-
var ajaxOps = {
-
type: ‘post’,
-
dataType: ‘json’,
-
data: data,
-
success: function( resp, text, xhr ) {
-
console.log(resp)
-
showOrHideError( self.error.success, true )
-
$input.data({
-
‘ideal-ajax-resp’: resp,
-
‘ideal-ajax-error’: self.error.success
-
})
-
$input.trigger(‘change’) // to update counter
-
$field.removeClass(‘ajax’)
-
// Run custom success callback
-
if( userAjaxOps._success ) {
-
userAjaxOps._success( resp, text, xhr )
-
}
-
},
-
error: function( xhr, text, error ) {
-
if ( text !== ‘abort’ ) {
-
showOrHideError( self.error.fail, false )
-
$input.data( ‘ideal-ajax-error’, self.error.fail )
-
$field.removeClass(‘ajax’)
-
// Run custom error callback
-
if ( userAjaxOps._error ) {
-
userAjaxOps._error( xhr, text, error )
-
}
-
}
-
}
-
}
-
$.extend( ajaxOps, userAjaxOps )
-
// Init
-
$input.removeData(‘ideal-ajax-error’)
-
$input.removeData(‘ideal-ajax-resp’)
-
$field.addClass(‘ajax’)
-
// Run request and save it to be able to abort it
-
// so requests don’t bubble
-
$.idealforms.ajaxRequests[ name ] = $.ajax( ajaxOps )
-
}
-
}
-
}
-
return filters
-
}
-
$.idealforms.flags = {
-
noerror: function (i) {
-
i.parent().siblings(‘.ideal-error’).hide()
-
},
-
noicons: function (i) {
-
i.siblings(‘.ideal-icon-valid, .ideal-icon-invalid’).hide()
-
},
-
novalidicon: function (i) {
-
i.siblings(‘.ideal-icon-valid’).hide()
-
},
-
noinvalidicon: function (i) {
-
i.siblings(‘.ideal-icon-invalid’).hide()
-
},
-
noclass: function (i) {
-
i.parents(‘.ideal-field’).removeClass(‘valid invalid’)
-
},
-
novalidclass: function (i) {
-
i.parents(‘.ideal-field’).removeClass(‘valid’)
-
},
-
noinvalidclass: function (i) {
-
i.parents(‘.ideal-field’).removeClass(‘invalid’)
-
}
-
}
-
/*
-
* Ideal Forms plugin
-
*/
-
var _defaults = {
-
inputs: {},
-
customFilters: {},
-
customFlags: {},
-
globalFlags: ”,
-
onSuccess: function(e) { alert(‘Thank you…’) },
-
onFail: function() { alert(‘Invalid!’) },
-
responsiveAt: ‘auto’,
-
disableCustom: ”
-
}
-
// Constructor
-
var IdealForms = function( element, options ) {
-
var self = this
-
self.$form = $( element )
-
self.opts = $.extend( {}, _defaults, options )
-
self.$tabs = self.$form.find(‘section’)
-
// Set localized filters
-
$.extend( $.idealforms.filters, getFilters() )
-
self._init()
-
}
-
// Plugin
-
$.fn.idealforms = function( options ) {
-
return this.each(function() {
-
if ( !$.data( this, ‘idealforms’ ) ) {
-
$.data( this, ‘idealforms’, new IdealForms( this, options ) )
-
}
-
})
-
}
-
// Get LESS variables
-
var LessVars = {
-
fieldWidth: Utils.getLessVar( ‘ideal-field-width’, ‘width’ )
-
}
-
/*
-
* Private Methods
-
*/
-
$.extend( IdealForms.prototype, {
-
_init: function() {
-
var self = this
-
var o = self.opts
-
var formElements = self._getFormElements()
-
self.$form.css( ‘visibility’, ‘visible’ )
-
.addClass(‘ideal-form’)
-
.attr( ‘novalidate’, ‘novalidate’ ) // disable HTML5 validation
-
// Do markup
-
formElements.inputs
-
.add( formElements.headings )
-
.add( formElements.separators )
-
.each(function(){ self._doMarkup( $(this) ) })
-
// Generate tabs
-
if ( self.$tabs.length ) {
-
var $tabContainer = $(‘<div class=“ideal-wrap ideal-tabs ideal-full-width”/>‘)
-
self.$form.prepend( $tabContainer )
-
self.$tabs.idealTabs( $tabContainer )
-
}
-
// Always show datepicker below the input
-
if ( jQuery.ui ) {
-
$.datepicker._checkOffset = function( a,b,c ) { return b }
-
}
-
// Add inputs specified by data-ideal
-
// to the list of user inputs
-
self.$form.find(‘[data-ideal]’).each(function() {
-
var userInput = o.inputs[ this.name ]
-
o.inputs[ this.name ] = userInput || { filters: $(this).data(‘ideal’) }
-
})
-
// Responsive
-
if ( o.responsiveAt ) {
-
$(window).resize(function(){ self._responsive() })
-
self._responsive()
-
}
-
// Form events
-
self.$form.on({
-
keydown: function( e ) {
-
// Prevent submit when pressing enter
-
// but exclude textareas
-
if ( e.which === 13 && e.target.nodeName !== ‘TEXTAREA’ ) {
-
e.preventDefault()
-
}
-
},
-
submit: function( e ) {
-
if ( !self.isValid() ) {
-
e.preventDefault()
-
o.onFail()
-
self.focusFirstInvalid()
-
} else {
-
o.onSuccess( e )
-
}
-
}
-
})
-
self._adjust()
-
self._attachEvents()
-
self.fresh() // Start fresh
-
},
-
_getFormElements: function() {
-
return {
-
inputs: this.$form.find(‘input, select, textarea, :button’),
-
labels: this.$form.find(‘div > label:first-child’),
-
text: this.$form.find(‘input:not([type=“checkbox”], [type=“radio”], [type=“submit”]), textarea’),
-
select: this.$form.find(‘select’),
-
radiocheck: this.$form.find(‘input[type=“radio”], input[type=“checkbox”]’),
-
buttons: this.$form.find(‘:button’),
-
file: this.$form.find(‘input[type=“file”]’),
-
headings: this.$form.find(‘h1, h2, h3, h4, h5, h6’),
-
separators: this.$form.find(‘hr’),
-
hidden: this.$form.find(‘input:hidden’)
-
}
-
},
-
_getUserInputs: function() {
-
return this.$form.find(‘[name=“‘+ Utils.getKeys( this.opts.inputs ).join(‘”], [name=“‘) +'”]’)
-
},
-
_getTab: function( nameOrIdx ) {
-
var self = this
-
var isNumber = !isNaN( nameOrIdx )
-
if ( isNumber ) {
-
return self.$tabs.eq( nameOrIdx )
-
}
-
return self.$tabs.filter(function() {
-
var re = new RegExp( nameOrIdx, ‘i’ )
-
return re.test( nbsp;$(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(‘div’).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(‘div’).addClass(‘ideal-hidden’)
-
},
-
heading: function() {
-
$element.closest(‘div’).addClass(‘ideal-full-width’)
-
$element.parent().children().wrapAll(‘<span class=“ideal-heading”/>‘)
-
},
-
separator: function() {
-
$element.closest(‘div’).addClass(‘ideal-full-width’)
-
$element.wrapAll(‘<div 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’ ) {
-
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 {
-
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
-
 nbsp; 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 = $(‘<div>‘+
-
‘<label>‘+ label +’:</label>‘+
-
Utils.makeInput( name, value, type, list, placeholder ) +
-
‘</div>‘)
-
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 ))
【相关推荐】
1. Html5免费视频教程
2. HTML5本地数据库实例详解
3. 教你如何实现一个H5微场景
4. 详解H5的自定义属性data-*
5. h5实现文本框提示语的代码实例
以上就是H5完成用户注册自动校验的实例详解的详细内容,更多请关注其它相关文章!
- h5实现文本框提示语的代码实例
- 用H5实现手机摇一摇的实例详解