Html5实现用户注册自动校验功能实例代码
程序员文章站
2023-11-28 22:28:58
这篇文章主要介绍了 Html5实现用户注册自动校验功能实例代码的相关资料,需要的朋友可以参考下... 16-05-24...
抽时间写了一个带有自动校验功能的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>
- <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>(例:
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 === '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 = $select.find('option')
- /**
- * generate markup and return elements of custom select
- * @memberof $.fn.tocustomselect
- * @returns {object} all elements of the new select replacement
- */
- var idealselect = (function () {
- var
- $wrap = $('<ul class="ideal-select '+ $select.attr('name') +'"/>'),
- $menu = $(
- '<li><span class="ideal-select-title">' +
- $options.filter(':selected').text() +
- '</span></li>'
- ),
- items = (function () {
- var items = []
- $options.each(function () {
- var $this = $(this)
- items.push('<li class="ideal-select-item">' + $this.text() + '</li>')
- })
- return items
- }())
- $menu.append('<ul class="ideal-select-sub">' + items.join('') + '</ul>')
- $wrap.append($menu)
- return {
- select: $wrap,
- title: $menu.find('.ideal-select-title'),
- sub: $menu.find('.ideal-select-sub'),
- items: $menu.find('.ideal-select-item')
- }
- }())
- /**
- * @namespace methods of custom select
- * @memberof $.fn.tocustomselect
- */
- var actions = {
- getselectedidx: function () {
- return idealselect.items
- .filter('.ideal-select-item-selected').index()
- },
- /**
- * @private
- */
- init: (function () {
- $select.css({
- position: 'absolute',
- left: '-9999px'
- })
- idealselect.sub.hide()
- idealselect.select.insertafter($select)
- idealselect.select.css(
- 'min-width',
- utils.getmaxwidth(idealselect.items)
- )
- idealselect.items
- .eq($options.filter(':selected').index())
- .addclass('ideal-select-item-selected')
- }()),
- nowindowscroll: function (e) {
- if (e.which === 40 || e.which === 38 || e.which === 13) {
- e.preventdefault()
- }
- },
- // fix loosing focus when scrolling
- // and selecting item with keyboard
- focushack: function () {
- settimeout(function () {
- $select.trigger('focus')
- }, 1)
- },
- focus: function () {
- idealselect.select.addclass('ideal-select-focus')
- $(document).on('keydown.noscroll', actions.nowindowscroll)
- },
- blur: function () {
- idealselect.select
- .removeclass('ideal-select-open ideal-select-focus')
- $(document).off('.noscroll')
- },
- scrollintoview: function (dir) {
- var
- $selected = idealselect.items.filter('.ideal-select-item-selected'),
- itemheight = idealselect.items.outerheight(),
- menuheight = idealselect.sub.outerheight(),
- isinview = (function () {
- // relative position to the submenu
- var elpos = $selected.position().top + itemheight
- return dir === 'down'
- ? elpos <= menuheight
- : elpos > 0
- }())
- if (!isinview) {
- itemheight = (dir === 'down')
- ? itemheight // go down
- : -itemheight // go up
- idealselect.sub
- .scrolltop(idealselect.sub.scrolltop() + itemheight)
- }
- },
- scrolltoitem: function () {
- var idx = actions.getselectedidx(),
- height = idealselect.items.outerheight(),
- nitems = idealselect.items.length,
- allheight = height * nitems,
- curheight = height * (nitems - idx)
- idealselect.sub.scrolltop(allheight - curheight)
- },
- showmenu: function () {
- idealselect.sub.fadein('fast')
- idealselect.select.addclass('ideal-select-open')
- actions.select(actions.getselectedidx())
- actions.scrolltoitem()
- },
- hidemenu: function () {
- idealselect.sub.hide()
- idealselect.select.removeclass('ideal-select-open')
- },
- select: function (idx) {
- idealselect.items
- .removeclass('ideal-select-item-selected')
- idealselect.items
- .eq(idx).addclass('ideal-select-item-selected')
- },
- change: function (idx) {
- var text = idealselect.items.eq(idx).text()
- actions.select(idx)
- idealselect.title.text(text)
- $options.eq(idx).prop('selected', true)
- $select.trigger('change')
- },
- keydown: function (key) {
- var
- idx = actions.getselectedidx(),
- ismenu = idealselect.select.is('.ideal-select-menu'),
- isopen = idealselect.select.is('.ideal-select-open')
- /**
- * @namespace key pressed
- */
- var keys = {
- 9: function () { // tab
- if (ismenu) {
- actions.blur()
- actions.hidemenu()
- }
- },
- 13: function () { // enter
- if (ismenu)
- isopen
- ? actions.hidemenu()
- : actions.showmenu()
- actions.change(idx)
- },
- 27: function () { // esc
- if (ismenu) actions.hidemenu()
- },
- 40: function () { // down
- if (idx < $options.length - 1) {
- isopen
- ? actions.select(idx + 1)
- : actions.change(idx + 1)
- }
- actions.scrollintoview('down')
- },
- 38: function () { // up
- if (idx > 0) {
- isopen
- ? actions.select(idx - 1)
- : actions.change(idx - 1)
- }
- actions.scrollintoview('up')
- },
- 'default': function () { // letter
- var
- letter = string.fromcharcode(key),
- $matches = idealselect.items
- .filter(function () {
- return /^\w+$/i.test( letter ) && // not allow modifier keys ( ctrl, cmd, meta, super... )
- new regexp('^' + letter, 'i').test( $(this).text() ) // find first match
- }),
- nmatches = $matches.length,
- counter = idealselect.select.data('counter') + 1 || 0,
- curkey = idealselect.select.data('key') || key,
- newidx = $matches.eq(counter).index()
- if (!nmatches) // no matches
- return false
- // if more matches with same letter
- if (curkey === key) {
- if (counter < nmatches) {
- idealselect.select.data('counter', counter)
- }
- else {
- idealselect.select.data('counter', 0)
- newidx = $matches.eq(0).index()
- }
- }
- // if new letter
- else {
- idealselect.select.data('counter', 0)
- newidx = $matches.eq(0).index()
- }
- if (isopen)
- actions.select(newidx)
- else
- actions.change(newidx)
- idealselect.select.data('key', key)
- actions.scrolltoitem()
- actions.focushack()
- }
- }
- keys[key]
- ? keys[key]()
- : keys['default']()
- }
- }
- /**
- * @namespace holds all events of custom select for "menu mode" and "list mode"
- * @memberof $.fn.tocustomselect
- */
- var events = {
- focus: actions.focus,
- 'blur.menu': function () {
- actions.blur()
- actions.hidemenu()
- },
- 'blur.list': function () {
- actions.blur()
- },
- keydown: function (e) {
- actions.keydown(e.which)
- },
- 'clickitem.menu': function () {
- actions.change($(this).index())
- actions.hidemenu()
- },
- 'clickitem.list': function () {
- actions.change($(this).index())
- },
- 'clicktitle.menu': function () {
- actions.focus()
- actions.showmenu()
- $select.trigger('focus')
- },
- 'hideoutside.menu': function () {
- $select.off('blur.menu')
- $(document).on('mousedown.ideal', function (evt) {
- if (!$(evt.target).closest(idealselect.select).length) {
- $(document).off('mousedown.ideal')
- $select.on('blur.menu', events['blur.menu'])
- } else {
- actions.focushack()
- }
- })
- },
- 'mousedown.list': function () {
- actions.focushack()
- }
- }
- // reset events
- var disableevents = function () {
- idealselect.select.removeclass('ideal-select-menu ideal-select-list')
- $select.off('.menu .list')
- idealselect.items.off('.menu .list')
- idealselect.select.off('.menu .list')
- idealselect.title.off('.menu .list')
- }
- // menu mode
- idealselect.select.on('menu', function () {
- disableevents()
- idealselect.select.addclass('ideal-select-menu')
- actions.hidemenu()
- $select.on({
- 'blur.menu': events['blur.menu'],
- 'focus.menu': events.focus,
- 'keydown.menu': events.keydown
- })
- idealselect.select.on('mousedown.menu', events['hideoutside.menu'])
- idealselect.items.on('click.menu', events['clickitem.menu'])
- idealselect.title.on('click.menu', events['clicktitle.menu'])
- })
- // list mode
- idealselect.select.on('list', function () {
- disableevents()
- idealselect.select.addclass('ideal-select-list')
- actions.showmenu()
- $select.on({
- 'blur.list': events['blur.list'],
- 'focus.list': events.focus,
- 'keydown.list': events.keydown
- })
- idealselect.select.on('mousedown.list', events['mousedown.list'])
- idealselect.items.on('mousedown.list', events['clickitem.list'])
- })
- $select.keydown(function (e) {
- // prevent default keydown event
- // to avoid bugs with ideal select events
- if (e.which !== 9) e.preventdefault()
- })
- // reset
- idealselect.select.on('reset', function(){
- actions.change(0)
- })
- idealselect.select.trigger('menu') // default to "menu mode"
- })
- }
- /*
- * idealradiocheck: jquery plguin for checkbox and radio replacement
- * usage: $('input[type=checkbox], input[type=radio]').idealradiocheck()
- */
- $.fn.idealradiocheck = function() {
- return this.each(function() {
- var $this = $(this)
- var $span = $('<span/>')
- $span.addclass( 'ideal-'+ ( $this.is(':checkbox') ? 'check' : 'radio' ) )
- $this.is(':checked') && $span.addclass('checked') // init
- $span.insertafter( $this )
- $this.parent('label').addclass('ideal-radiocheck-label')
- .attr('onclick', '') // fix clicking label in ios
- $this.css({ position: 'absolute', left: '-9999px' }) // hide by shifting left
- // events
- $this.on({
- change: function() {
- var $this = $(this)
- if ( $this.is('input[type="radio"]') ) {
- $this.parent().siblings('label').find('.ideal-radio').removeclass('checked')
- }
- $span.toggleclass( 'checked', $this.is(':checked') )
- },
- focus: function() { $span.addclass('focus') },
- blur: function() { $span.removeclass('focus') },
- click: function() { $(this).trigger('focus') }
- })
- })
- }
- ;(function( $ ) {
- // browser supports html5 multiple file?
- var multiplesupport = typeof $('<input/>')[0].multiple !== 'undefined',
- isie = /msie/i.test( navigator.useragent )
- $.fn.idealfile = function() {
- return this.each(function() {
- var $file = $(this).addclass('ideal-file'), // the original file input
- // label that will be used for ie hack
- $wrap = $('<div class="ideal-file-wrap">'),
- $input = $('<input type="text" class="ideal-file-filename" />'),
- // button that will be used in non-ie browsers
- $button = $('<button type="button" class="ideal-file-upload">open</button>'),
- // hack for ie
- $label = $('<label class="ideal-file-upload" for="'+ $file[0].id +'">open</label>')
- // hide by shifting to the left so we
- // can still trigger events
- $file.css({
- position: 'absolute',
- left: '-9999px'
- })
- $wrap.append( $input, ( isie ? $label : $button ) ).insertafter( $file )
- // prevent focus
- $file.attr('tabindex', -1)
- $button.attr('tabindex', -1)
- $button.click(function () {
- $file.focus().click() // open dialog
- })
- $file.change(function() {
- var files = [], filearr, filename
- // if multiple is supported then extract
- // all filenames from the file array
- if ( multiplesupport ) {
- filearr = $file[0].files
- for ( var i = 0, len = filearr.length; i < len; i++ ) {
- files.push( filearr[i].name )
- }
- filename = files.join(', ')
- // if not supported then just take the value
- // and remove the path to just show the filename
- } else {
- filename = $file.val().split('\\').pop()
- }
- $input.val( filename ) // set the value
- .attr( 'title', filename ) // show filename in title tootlip
- })
- $input.on({
- focus: function () { $file.trigger('change') },
- blur: function () { $file.trigger('blur') },
- keydown: function( e ) {
- if ( e.which === 13 ) { // enter
- if ( !isie ) { $file.trigger('click') }
- } else if ( e.which === 8 || e.which === 46 ) { // backspace & del
- // on some browsers the value is read-only
- // with this trick we remove the old input and add
- // a clean clone with all the original events attached
- $file.replacewith( $file = $file.val('').clone( true ) )
- $file.trigger('change')
- $input.val('')
- } else if ( e.which === 9 ){ // tab
- return
- } else { // all other keys
- return false
- }
- }
- })
- })
- }
- }( jquery ))
- /**
- * @namespace errors
- * @locale en
- */
- $.idealforms.errors = {
- required: '此处是必填的.',
- number: '必须是数字.',
- digits: '必须是唯一的数字.',
- name: '必须至少有3个字符长,并且只能包含字母.',
- username: '用户名最短5位,最长30位,请使用英文字母、数字、中文和下划线.用户名首字符必须为字母、数字、中文,不能为全数字.中文最长21个字.',
- pass: '密码的位数必须的在6-15位之间,并且至少包含一个数字,一个大写字母和一个小写字母.',
- strongpass: '必须至少为8个字符长,至少包含一个大写字母和一个小写字母和一个数字或特殊字符.',
- email: '必须是一个有效的email地址. <em>(例: user@gmail.com)</em>',
- phone: '必须是一个有效的手机号码. <em>(例: 18723101212)</em>',
- zip: 'must be a valid us zip code. <em>(e.g. 33245 or 33245-0003)</em>',
- url: 'must be a valid url. <em>(e.g. www.google.com)</em>',
- minchar: 'must be at least <strong>{0}</strong> characters long.',
- minoption: 'check at least <strong>{0}</strong> options.',
- maxchar: 'no more than <strong>{0}</strong> characters long.',
- maxoption: 'no more than <strong>{0}</strong> options allowed.',
- range: 'must be a number between {0} and {1}.',
- date: 'must be a valid date. <em>(e.g. {0})</em>',
- dob: 'must be a valid date of birth.',
- exclude: '"{0}" is not available.',
- excludeoption: '{0}',
- equalto: 'must be the same value as <strong>"{0}"</strong>',
- extension: 'file(s) must have a valid extension. <em>(e.g. "{0}")</em>',
- ajaxsuccess: '<strong>{0}</strong> is not available.',
- ajaxerror: 'server error...'
- }
- /**
- * get all default filters
- * @returns object
- */
- var getfilters = function() {
- var filters = {
- required: {
- regex: /.+/,
- error: $.idealforms.errors.required
- },
- number: {
- regex: function( i, v ) { return !isnan(v) },
- error: $.idealforms.errors.number
- },
- digits: {
- regex: /^\d+$/,
- error: $.idealforms.errors.digits
- },
- name: {
- regex: /^[a-za-z]{3,}$/,
- error: $.idealforms.errors.name
- },
- username: {
- regex: /^[a-z](?=[\w.]{4,30}$)\w*\.?\w*$/i,
- error: $.idealforms.errors.username
- },
- pass: {
- regex: /(?=.*\d)(?=.*[a-z])(?=.*[a-z]).{6,}/,
- error: $.idealforms.errors.pass
- },
- strongpass: {
- regex: /(?=^.{8,}$)((?=.*\d)|(?=.*\w+))(?![.\n])(?=.*[a-z])(?=.*[a-z]).*$/,
- error: $.idealforms.errors.strongpass
- },
- email: {
- regex: /^([a-za-z0-9]*[-_.]?[a-za-z0-9]+)*@([a-za-z0-9]*[-_]?[a-za-z0-9]+)+[\\.][a-za-z]{2,3}([\\.][a-za-z]{2})?$/,
- error: $.idealforms.errors.email
- },
- phone: {
- //regex: /^((13[0-9])|(15[0-9])|(17[0-9])|(18[0-9]))\\d{8}$/,
- regex: /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/,
- error: $.idealforms.errors.phone
- },
- zip: {
- regex: /^\d{5}$|^\d{5}-\d{4}$/,
- error: $.idealforms.errors.zip
- },
- url: {
- regex: /^(?:(ftp|http|https):\/\/)?(?:[\w\-]+\.)+[a-z]{2,6}([\:\/?#].*)?$/i,
- error: $.idealforms.errors.url
- },
- min: {
- regex: function( input, value ) {
- var $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 ) {
- 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( $(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' ) {
- 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 = $('<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 ))
以上所述是本文的全部内容希望对大家有所帮助!
上一篇: HTML5 Canvas实现烟花绽放特效
下一篇: 10个最常见的HTML5面试题 附答案