2014-07-17 16:45:12 +02:00
webshims . register ( 'form-validation' , function ( $ , webshims , window , document , undefined , options ) {
"use strict" ;
var isWebkit = 'webkitURL' in window ;
var support = webshims . support ;
var hasNative = support . formvalidation && ! webshims . bugs . bustedValidity ;
var chromeBugs = isWebkit && hasNative ;
var ua = navigator . userAgent ;
var isIE = ua . indexOf ( 'MSIE' ) != - 1 ;
var webkitVersion = chromeBugs && parseFloat ( ( ua . match ( /Safari\/([\d\.]+)/ ) || [ '' , '999999' ] ) [ 1 ] , 10 ) ;
var iVal = options . iVal ;
var invalidClass = iVal . errorClass || ( iVal . errorClass = 'user-error' ) ;
var validClass = iVal . successClass || ( iVal . successClass = 'user-success' ) ;
var markedClases = '.' + validClass + ', .' + invalidClass ;
var invalidWrapperClass = iVal . errorWrapperClass || ( iVal . errorWrapperClass = 'ws-invalid' ) ;
var successWrapperClass = iVal . successWrapperClass || ( iVal . successWrapperClass = 'ws-success' ) ;
var errorBoxClass = iVal . errorBoxClass || ( iVal . errorBoxClass = 'ws-errorbox' ) ;
var errorMessageClass = iVal . errorMessageClass || ( iVal . errorMessageClass = 'ws-errormessage' ) ;
var errorBoxWrapper = iVal . errorBoxWrapper || ( iVal . errorBoxWrapper = 'div' ) ;
var errorMessageWrapper = iVal . errorMessageWrapper || ( iVal . errorMessageWrapper = 'p' ) ;
var checkTypes = { checkbox : 1 , radio : 1 } ;
var loader = webshims . loader ;
var addModule = loader . addModule ;
var emptyJ = $ ( [ ] ) ;
var nonFormFilter = function ( ) {
return ! $ . prop ( this , 'form' ) ;
} ;
2014-09-03 00:57:03 +02:00
var modules = webshims . modules ;
var getGroupElements = modules [ "form-core" ] . getGroupElements || function ( elem ) {
2014-07-17 16:45:12 +02:00
elem = $ ( elem ) ;
var name ;
var form ;
var ret = emptyJ ;
if ( elem [ 0 ] . type == 'radio' ) {
form = elem . prop ( 'form' ) ;
name = elem [ 0 ] . name ;
if ( ! name ) {
ret = elem ;
} else if ( form ) {
ret = $ ( form ) . jProp ( name ) ;
} else {
ret = $ ( document . getElementsByName ( name ) ) . filter ( nonFormFilter ) ;
}
ret = ret . filter ( '[type="radio"]' ) ;
}
return ret ;
} ;
var returnValidityCause = function ( validity , elem ) {
var ret ;
$ . each ( validity , function ( name , value ) {
if ( value ) {
ret = name + $ . prop ( elem , 'validationMessage' ) ;
return false ;
}
} ) ;
return ret ;
} ;
var isInGroup = function ( name ) {
var ret ;
try {
ret = document . activeElement . name === name ;
} catch ( e ) { }
return ret ;
} ;
//actually we could always use the change event, but chrome messed it up and does not respect the commit action definition of the html spec
//see: http://code.google.com/p/chromium/issues/detail?id=155747
var changeTypes = {
radio : 1 ,
checkbox : 1 ,
'select-one' : 1 ,
'select-multiple' : 1 ,
file : 1 ,
date : 1 ,
month : 1 ,
week : 1 ,
text : 1
} ;
//see: http://code.google.com/p/chromium/issues/detail?id=179708 and bug above
var noFocusWidgets = {
time : 1 ,
date : 1 ,
month : 1 ,
datetime : 1 ,
week : 1 ,
'datetime-local' : 1
} ;
var updateValidationEvents = {
refreshvalidityui : 1 ,
updatevalidation : 1
} ;
var iValClasses = '.' + iVal . errorClass + ', .' + iVal . successClass ;
var switchValidityClass = function ( e ) {
if ( ! iVal . sel ) { return ; }
var elem , timer , shadowElem , shadowType ;
if ( ! e . target ) { return ; }
elem = $ ( e . target ) . getNativeElement ( ) [ 0 ] ;
shadowElem = $ ( elem ) . getShadowElement ( ) ;
if ( elem . type == 'submit' || ! $ . prop ( elem , 'willValidate' ) || ( e . type == 'change' && ( shadowType = shadowElem . prop ( 'type' ) ) && ! changeTypes [ shadowType ] ) ) { return ; }
timer = $ . data ( elem , 'webshimsswitchvalidityclass' ) ;
var switchClass = function ( ) {
if ( ! shadowType ) {
shadowType = shadowElem . prop ( 'type' ) ;
}
if (
2014-07-20 02:43:13 +02:00
( chromeBugs && ( e . type == 'change' || webkitVersion < 537.36 ) && noFocusWidgets [ shadowType ] && $ . find . matchesSelector ( e . target , ':focus' ) ) ||
2014-07-17 16:45:12 +02:00
( e . type == 'focusout' && elem . type == 'radio' && isInGroup ( elem . name ) )
) {
return ;
}
2014-11-05 21:25:18 +01:00
if ( webshims . refreshCustomValidityRules ( elem ) == 'async' ) {
2014-07-17 16:45:12 +02:00
$ ( elem ) . one ( 'updatevalidation.webshims' , switchValidityClass ) ;
return ;
}
var validity = $ . prop ( elem , 'validity' ) ;
var addClass , removeClass , trigger , generaltrigger , validityCause ;
if ( validity . valid ) {
if ( ! shadowElem . hasClass ( validClass ) ) {
addClass = validClass ;
removeClass = invalidClass ;
generaltrigger = 'changedvaliditystate' ;
trigger = 'changedvalid' ;
if ( checkTypes [ elem . type ] && elem . checked ) {
getGroupElements ( elem ) . not ( elem ) . removeClass ( removeClass ) . addClass ( addClass ) . removeAttr ( 'aria-invalid' ) ;
}
shadowElem . removeAttr ( 'aria-invalid' ) ;
$ . removeData ( elem , 'webshimsinvalidcause' ) ;
}
} else {
validityCause = returnValidityCause ( validity , elem ) ;
if ( $ . data ( elem , 'webshimsinvalidcause' ) != validityCause ) {
$ . data ( elem , 'webshimsinvalidcause' , validityCause ) ;
generaltrigger = 'changedvaliditystate' ;
}
if ( ! shadowElem . hasClass ( invalidClass ) ) {
addClass = invalidClass ;
removeClass = validClass ;
if ( checkTypes [ elem . type ] && ! elem . checked ) {
getGroupElements ( elem ) . not ( elem ) . removeClass ( removeClass ) . addClass ( addClass ) . attr ( 'aria-invalid' , 'true' ) ;
}
shadowElem . attr ( 'aria-invalid' , 'true' ) ;
trigger = 'changedinvalid' ;
}
}
if ( addClass ) {
shadowElem . addClass ( addClass ) . removeClass ( removeClass ) ;
//jQuery 1.6.1 IE9 bug (doubble trigger bug)
setTimeout ( function ( ) {
$ ( elem ) . trigger ( trigger ) ;
} ) ;
}
if ( generaltrigger ) {
setTimeout ( function ( ) {
$ ( elem ) . trigger ( generaltrigger ) ;
} ) ;
}
$ . removeData ( elem , 'webshimsswitchvalidityclass' ) ;
} ;
if ( shadowElem . triggerHandler ( 'wsallowinstantvalidation' , [ e ] ) !== false ) {
if ( timer ) {
clearTimeout ( timer ) ;
}
if ( updateValidationEvents [ e . type ] ) {
if ( e . type == 'refreshvalidityui' ) {
webshims . error ( 'refreshvalidityui was renamed to updatevalidation' ) ;
}
switchClass ( ) ;
} else {
$ . data ( elem , 'webshimsswitchvalidityclass' , setTimeout ( switchClass ) ) ;
}
}
} ;
var eachReset = function ( ) {
webshims . errorbox . reset ( this ) ;
} ;
if ( 'validityUIEvents' in options ) {
webshims . error ( 'validityUIEvents was renamed to iVal.events' ) ;
iVal . events = options . validityUIEvents ;
}
if ( 'events' in iVal ) {
iVal . events = iVal . events || '' ;
} else {
iVal . events = 'focusout change' ;
}
if ( iVal . events ) {
iVal . events += ' ' ;
}
if ( ! iVal . fieldWrapper ) {
iVal . fieldWrapper = ':not(span):not(label):not(em):not(strong):not(p):not(.ws-custom-file)' ;
}
2014-09-03 00:57:03 +02:00
if ( ! modules [ "form-core" ] . getGroupElements ) {
modules [ "form-core" ] . getGroupElements = getGroupElements ;
2014-07-17 16:45:12 +02:00
}
$ ( document . body || 'html' )
. on ( iVal . events + 'refreshvalidityui updatevalidation.webshims invalid' , switchValidityClass )
. on ( 'refreshvalidationui.webshims' , function ( e ) {
if ( $ ( e . target ) . getShadowElement ( ) . is ( markedClases ) ) {
switchValidityClass ( { type : 'updatevalidation' , target : e . target } ) ;
}
} )
. on ( 'reset resetvalidation.webshims resetvalui' , function ( e ) {
var noIValTrigger ;
var elems = $ ( e . target ) ;
if ( e . type == 'resetvalui' ) {
webshims . error ( 'resetvalui was renamed to resetvalidation' ) ;
}
if ( elems . is ( 'form, fieldset' ) ) {
if ( elems [ 0 ] . nodeName . toLowerCase ( ) == 'form' ) {
noIValTrigger = ! elems . is ( iVal . sel ) ;
}
elems = elems . jProp ( 'elements' ) ;
}
elems = elems
. filter ( iValClasses )
. removeAttr ( 'aria-invalid' )
. removeClass ( iVal . errorClass + ' ' + iVal . successClass )
. getNativeElement ( )
. each ( function ( ) {
$ . removeData ( this , 'webshimsinvalidcause' ) ;
} )
;
if ( ! noIValTrigger ) {
if ( noIValTrigger === false ) {
elems . each ( eachReset ) ;
} else {
elems . trigger ( 'resetvalidityui.webshims' ) ;
}
}
} )
;
var setRoot = function ( ) {
webshims . scrollRoot = ( isWebkit || document . compatMode == 'BackCompat' ) ?
$ ( document . body ) :
$ ( document . documentElement )
;
} ;
var hasTransition = ( 'transitionDelay' in document . documentElement . style ) ;
var resetPos = { display : 'inline-block' , left : 0 , top : 0 , marginTop : 0 , marginLeft : 0 , marginRight : 0 , marginBottom : 0 } ;
var fx = {
slide : {
show : 'slideDown' ,
hide : 'slideUp'
} ,
fade : {
show : 'fadeIn' ,
hide : 'fadeOut'
} ,
no : {
show : 'show' ,
hide : 'hide'
}
} ;
setRoot ( ) ;
webshims . ready ( 'DOM' , setRoot ) ;
var rtlReg = /right|left/g ;
var rtlReplace = function ( ret ) {
return ret == 'left' ? 'right' : 'left' ;
} ;
webshims . getRelOffset = function ( posElem , relElem , opts ) {
var offset , bodyOffset , dirs ;
posElem = $ ( posElem ) ;
$ . swap ( posElem [ 0 ] , resetPos , function ( ) {
var isRtl ;
if ( $ . position && opts && $ . position . getScrollInfo ) {
if ( ! opts . of ) {
opts . of = relElem ;
}
isRtl = $ ( opts . of ) . css ( 'direction' ) == 'rtl' ;
if ( ! opts . isRtl ) {
opts . isRtl = false ;
}
if ( opts . isRtl != isRtl ) {
opts . my = ( opts . my || 'center' ) . replace ( rtlReg , rtlReplace ) ;
opts . at = ( opts . at || 'center' ) . replace ( rtlReg , rtlReplace ) ;
opts . isRtl = isRtl ;
}
posElem [ opts . isRtl ? 'addClass' : 'removeClass' ] ( 'ws-is-rtl' ) ;
opts . using = function ( calced , data ) {
posElem . attr ( { 'data-horizontal' : data . horizontal , 'data-vertical' : data . vertical } ) ;
offset = calced ;
} ;
posElem . attr ( {
'data-horizontal' : '' ,
'data-vertical' : '' ,
'data-my' : opts . my ,
'data-at' : opts . at
} ) ;
posElem . position ( opts ) ;
} else {
offset = $ ( relElem ) . offset ( ) ;
bodyOffset = posElem . offset ( ) ;
offset . top -= bodyOffset . top ;
offset . left -= bodyOffset . left ;
offset . top += relElem . outerHeight ( ) ;
}
} ) ;
return offset ;
} ;
$ . extend ( webshims . wsPopover , {
isInElement : function ( containers , contained ) {
if ( ! $ . isArray ( containers ) ) {
containers = [ containers ] ;
}
var i , len , container ;
var ret = false ;
for ( i = 0 , len = containers . length ; i < len ; i ++ ) {
container = containers [ i ] ;
if ( container && container . jquery ) {
container = container [ 0 ] ;
}
if ( container && ( container == contained || $ . contains ( container , contained ) ) ) {
ret = true ;
break ;
}
}
return ret ;
} ,
show : function ( element ) {
var showAction ;
if ( this . isVisible ) { return ; }
var e = $ . Event ( 'wspopoverbeforeshow' ) ;
this . element . trigger ( e ) ;
if ( e . isDefaultPrevented ( ) ) { return ; }
this . isVisible = true ;
if ( ! this . _shadowAdded && webshims . shadowClass ) {
this . element . addClass ( webshims . shadowClass ) ;
this . _shadowAdded = true ;
}
2014-09-03 00:57:03 +02:00
element = $ ( element || this . options . prepareFor ) . getNativeElement ( ) ;
2014-07-17 16:45:12 +02:00
var that = this ;
var closeOnOutSide = function ( e ) {
if ( that . options . hideOnBlur && ! that . stopBlur && ! that . isInElement ( [ that . lastElement [ 0 ] , element [ 0 ] , that . element [ 0 ] ] , e . target ) ) {
that . hide ( ) ;
}
} ;
var visual = $ ( element ) . getShadowElement ( ) ;
var delayedRepos = function ( e ) {
clearTimeout ( that . timers . repos ) ;
that . timers . repos = setTimeout ( function ( ) {
that . position ( visual ) ;
} , e && e . type == 'pospopover' ? 4 : 200 ) ;
} ;
this . clear ( ) ;
this . element . css ( 'display' , 'none' ) ;
this . prepareFor ( element , visual ) ;
this . position ( visual ) ;
if ( this . options . inline ) {
showAction = ( fx [ this . options . inline ] || fx . slide ) . show ;
that . element [ showAction ] ( ) . trigger ( 'wspopovershow' ) ;
} else {
this . element . removeClass ( 'ws-po-visible' ) ;
that . timers . show = setTimeout ( function ( ) {
that . element . css ( 'display' , '' ) ;
that . timers . show = setTimeout ( function ( ) {
that . element . addClass ( 'ws-po-visible' ) . trigger ( 'wspopovershow' ) ;
} , 14 ) ;
} , 4 ) ;
}
$ ( document . body )
. on ( 'focusin' + this . eventns + ' mousedown' + this . eventns , closeOnOutSide )
//http://www.quirksmode.org/m/tests/eventdelegation2.html
. children ( ':not(script), :not(iframe), :not(noscript)' )
. on ( 'mousedown' + this . eventns , closeOnOutSide )
;
this . element . off ( 'pospopover' ) . on ( 'pospopover' , delayedRepos ) ;
$ ( window ) . on ( 'resize' + this . eventns + ' pospopover' + this . eventns , delayedRepos ) ;
} ,
_getAutoAppendElement : ( function ( ) {
var invalidParent = /^(?:span|i|label|b|p|tr|thead|tbody|table|strong|em|ul|ol|dl|html)$/i ;
return function ( element ) {
var appendElement ;
var parent = element [ 0 ] ;
var body = document . body ;
while ( ( parent = parent [ appendElement ? 'offsetParent' : 'parentNode' ] ) && parent . nodeType == 1 && parent != body ) {
if ( ! appendElement && ! invalidParent . test ( parent . nodeName ) ) {
appendElement = parent ;
}
2014-11-05 21:25:18 +01:00
if ( appendElement && $ . css ( parent , 'overflow' ) != 'visible' && $ . css ( parent , 'position' ) != 'static' ) {
2014-07-17 16:45:12 +02:00
appendElement = false ;
}
}
return $ ( appendElement || body ) ;
} ;
} ) ( ) ,
prepareFor : function ( element , visual ) {
var onBlur , parentElem ;
var that = this ;
var css = { } ;
var opts = $ . extend ( true , { } , this . options , element . jProp ( 'form' ) . data ( 'wspopover' ) || { } , element . data ( 'wspopover' ) ) ;
this . lastOpts = opts ;
this . lastElement = $ ( element ) . getShadowFocusElement ( ) ;
if ( ! this . prepared || ! this . options . prepareFor ) {
if ( opts . appendTo == 'element' || ( opts . inline && opts . appendTo == 'auto' ) ) {
2014-07-20 02:43:13 +02:00
parentElem = visual . parent ( ) ;
2014-07-17 16:45:12 +02:00
} else if ( opts . appendTo == 'auto' ) {
2014-07-20 02:43:13 +02:00
parentElem = this . _getAutoAppendElement ( visual ) ;
2014-07-17 16:45:12 +02:00
} else {
parentElem = $ ( opts . appendTo ) ;
}
if ( ! this . prepared || parentElem [ 0 ] != this . element [ 0 ] . parentNode ) {
this . element . appendTo ( parentElem ) ;
}
}
this . element . attr ( {
'data-class' : element . prop ( 'className' ) ,
'data-id' : element . prop ( 'id' )
} ) ;
if ( opts . constrainWidth ) {
this . element . addClass ( 'ws-popover-constrained-width' ) ;
css . minWidth = visual . outerWidth ( ) ;
} else {
this . element . removeClass ( 'ws-popover-constrained-width' ) ;
css . minWidth = '' ;
}
if ( opts . inline ) {
this . element . addClass ( 'ws-popinline ws-po-visible' ) ;
} else {
this . element . removeClass ( 'ws-popinline' ) ;
}
this . element . css ( css ) ;
if ( opts . hideOnBlur ) {
onBlur = function ( e ) {
if ( that . stopBlur ) {
e . stopImmediatePropagation ( ) ;
} else {
that . hide ( ) ;
}
} ;
that . timers . bindBlur = setTimeout ( function ( ) {
that . lastElement . off ( that . eventns ) . on ( 'focusout' + that . eventns + ' blur' + that . eventns , onBlur ) ;
that . lastElement . getNativeElement ( ) . off ( that . eventns ) ;
} , 10 ) ;
}
this . prepared = true ;
} ,
clear : function ( ) {
$ ( window ) . off ( this . eventns ) ;
$ ( document ) . off ( this . eventns ) ;
$ ( document . body )
. off ( this . eventns )
. children ( ':not(script), :not(iframe), :not(noscript)' )
. off ( this . eventns )
;
this . element . off ( 'transitionend' + this . eventns ) ;
this . stopBlur = false ;
this . lastOpts = false ;
$ . each ( this . timers , function ( timerName , val ) {
clearTimeout ( val ) ;
} ) ;
} ,
hide : function ( ) {
var hideAction ;
var e = $ . Event ( 'wspopoverbeforehide' ) ;
this . element . trigger ( e ) ;
if ( e . isDefaultPrevented ( ) || ! this . isVisible ) { return ; }
this . isVisible = false ;
var that = this ;
var forceHide = function ( e ) {
if ( ! ( e && e . type == 'transitionend' && ( e = e . originalEvent ) && e . target == that . element [ 0 ] && that . element . css ( 'visibility' ) == 'hidden' ) ) {
that . element . off ( 'transitionend' + that . eventns ) . css ( 'display' , 'none' ) . attr ( { 'data-id' : '' , 'data-class' : '' , 'hidden' : 'hidden' } ) ;
clearTimeout ( that . timers . forcehide ) ;
$ ( window ) . off ( 'resize' + that . eventns ) ;
}
} ;
this . clear ( ) ;
if ( this . options . inline ) {
hideAction = ( fx [ this . options . inline ] || fx . slide ) . hide ;
this . element [ hideAction ] ( ) ;
} else {
this . element . removeClass ( 'ws-po-visible' ) ;
$ ( window ) . on ( 'resize' + this . eventns , forceHide ) ;
if ( hasTransition ) {
this . element . off ( 'transitionend' + this . eventns ) . on ( 'transitionend' + this . eventns , forceHide ) ;
}
that . timers . forcehide = setTimeout ( forceHide , hasTransition ? 600 : 40 ) ;
}
this . element . trigger ( 'wspopoverhide' ) ;
} ,
position : function ( element ) {
var offset ;
var opts = this . lastOpts || this . options ;
if ( ! opts . inline ) {
offset = webshims . getRelOffset ( this . element . removeAttr ( 'hidden' ) , element , ( this . lastOpts || this . options ) . position ) ;
this . element . css ( offset ) ;
}
}
} ) ;
/* some extra validation UI */
webshims . validityAlert = ( function ( ) {
options . messagePopover . position = $ . extend ( { } , {
at : 'left bottom' ,
my : 'left top' ,
collision : 'none'
} , options . messagePopover . position || { } ) ;
var api = webshims . objectCreate ( webshims . wsPopover , undefined , options . messagePopover ) ;
var boundHide = api . hide . bind ( api ) ;
api . element . addClass ( 'validity-alert' ) . attr ( { role : 'alert' } ) ;
$ . extend ( api , {
hideDelay : 5000 ,
showFor : function ( elem , message , noFocusElem , noBubble ) {
elem = $ ( elem ) . getNativeElement ( ) ;
this . clear ( ) ;
this . hide ( ) ;
if ( ! noBubble ) {
this . getMessage ( elem , message ) ;
this . show ( elem ) ;
if ( this . hideDelay ) {
this . timers . delayedHide = setTimeout ( boundHide , this . hideDelay ) ;
}
}
if ( ! noFocusElem ) {
this . setFocus ( elem ) ;
}
} ,
setFocus : function ( element ) {
var focusElem = $ ( element ) . getShadowFocusElement ( ) ;
var scrollTop = webshims . scrollRoot . scrollTop ( ) + ( options . viewportOffset || 0 ) ;
var elemTop = focusElem . offset ( ) . top - ( options . scrollOffset || 30 ) ;
var focus = function ( ) {
try {
focusElem [ 0 ] . focus ( ) ;
} catch ( e ) { }
if ( ! focusElem [ 0 ] . offsetWidth && ! focusElem [ 0 ] . offsetHeight ) {
webshims . warn ( 'invalid element seems to be hidden. Make element either visible or use disabled/readonly to bar elements from validation. With fieldset[disabled] a group of elements can be ignored! In case of select replacement see shims/form-combat.js to fix issue.' ) ;
}
api . element . triggerHandler ( 'pospopover' ) ;
} ;
if ( scrollTop > elemTop ) {
webshims . scrollRoot . animate (
{ scrollTop : elemTop - 5 - ( options . viewportOffset || 0 ) } ,
{
queue : false ,
duration : Math . max ( Math . min ( 600 , ( scrollTop - elemTop ) * 1.5 ) , 80 ) ,
complete : focus
}
) ;
} else {
focus ( ) ;
}
} ,
getMessage : function ( elem , message ) {
if ( ! message ) {
message = elem . getErrorMessage ( ) ;
}
if ( message ) {
api . contentElement . html ( message ) ;
} else {
this . hide ( ) ;
}
}
} ) ;
return api ;
} ) ( ) ;
if ( ! iVal . fx || ! fx [ iVal . fx ] ) {
iVal . fx = 'slide' ;
}
if ( ! $ . fn [ fx [ iVal . fx ] . show ] ) {
iVal . fx = 'no' ;
}
var errorBoxId = 0 ;
webshims . errorbox = {
create : function ( elem , fieldWrapper ) {
if ( ! fieldWrapper ) {
fieldWrapper = this . getFieldWrapper ( elem ) ;
}
var errorBox = $ ( '.' + errorBoxClass , fieldWrapper ) ;
if ( ! errorBox . length ) {
2015-01-21 16:03:20 +01:00
errorBox = $ ( '<' + errorBoxWrapper + ' class="' + errorBoxClass + '" hidden="hidden" style="display: none;" />' ) ;
2014-07-17 16:45:12 +02:00
fieldWrapper . append ( errorBox ) ;
}
if ( ! errorBox . prop ( 'id' ) ) {
errorBoxId ++ ;
errorBox . prop ( 'id' , 'errorbox-' + errorBoxId ) ;
}
fieldWrapper . data ( 'errorbox' , errorBox ) ;
return errorBox ;
} ,
getFieldWrapper : function ( elem ) {
var fieldWrapper ;
fieldWrapper = ( typeof iVal . fieldWrapper == "function" ) ? iVal . fieldWrapper . apply ( this , arguments ) : $ ( elem ) . parent ( ) . closest ( iVal . fieldWrapper ) ;
if ( ! fieldWrapper . length ) {
webshims . error ( "could not find fieldwrapper: " + iVal . fieldWrapper ) ;
}
return fieldWrapper ;
} ,
_createContentMessage : ( function ( ) {
var noValidate = function ( ) {
return ! noValidate . types [ this . type ] ;
} ;
noValidate . types = {
hidden : 1 ,
image : 1 ,
button : 1 ,
reset : 1 ,
submit : 1
} ;
var fields = { } ;
var deCamelCase = function ( c ) {
return '-' + ( c ) . toLowerCase ( ) ;
} ;
var getErrorName = function ( elem ) {
var ret = $ ( elem ) . data ( 'errortype' ) ;
if ( ! ret ) {
$ . each ( fields , function ( errorName , cNames ) {
2014-07-20 02:43:13 +02:00
if ( $ . find . matchesSelector ( elem , cNames ) ) {
2014-07-17 16:45:12 +02:00
ret = errorName ;
return false ;
}
} ) ;
}
return ret || 'defaultMessage' ;
} ;
$ . each ( [ "customError" , "badInput" , "typeMismatch" , "rangeUnderflow" , "rangeOverflow" , "stepMismatch" , "tooLong" , "tooShort" , "patternMismatch" , "valueMissing" ] , function ( i , name ) {
var cName = name . replace ( /[A-Z]/ , deCamelCase ) ;
fields [ name ] = '.' + cName + ', .' + name + ', .' + ( name ) . toLowerCase ( ) + ', [data-errortype="' + name + '"]' ;
} ) ;
return function ( elem , errorBox , fieldWrapper ) {
var extended = false ;
var descriptiveMessages = { } ;
$ ( errorBox ) . children ( ) . each ( function ( ) {
var name = getErrorName ( this ) ;
descriptiveMessages [ name ] = $ ( this ) . html ( ) ;
} ) ;
$ ( 'input, select, textarea' , fieldWrapper ) . filter ( noValidate ) . each ( function ( i , elem ) {
var errorMessages = $ ( elem ) . data ( 'errormessage' ) || { } ;
if ( typeof errorMessages == 'string' ) {
errorMessages = { defaultMessage : errorMessages } ;
}
$ . each ( descriptiveMessages , function ( name , val ) {
if ( ! errorMessages [ name ] ) {
extended = true ;
errorMessages [ name ] = val ;
}
} ) ;
if ( extended ) {
$ ( elem ) . data ( 'errormessage' , errorMessages ) ;
}
if ( webshims . getOptions ) {
webshims . getOptions ( elem , 'errormessage' , false , true ) ;
}
} ) ;
} ;
} ) ( ) ,
initIvalContentMessage : function ( elem ) {
2014-07-20 02:43:13 +02:00
var form ;
if ( iVal . sel && ( form = $ . prop ( elem , 'form' ) ) && $ . find . matchesSelector ( form , iVal . sel ) ) {
2014-07-17 16:45:12 +02:00
this . get ( elem ) ;
}
} ,
get : function ( elem , fieldWrapper ) {
if ( ! fieldWrapper ) {
fieldWrapper = this . getFieldWrapper ( elem ) ;
}
var type ;
var errorBox = fieldWrapper . data ( 'errorbox' ) ;
if ( ( type = typeof errorBox ) != 'object' ) {
if ( ! errorBox ) {
errorBox = this . create ( elem , fieldWrapper ) ;
} else if ( type == 'string' ) {
errorBox = $ ( '#' + errorBox ) ;
fieldWrapper . data ( 'errorbox' , errorBox , fieldWrapper ) ;
}
this . _createContentMessage ( elem , errorBox , fieldWrapper ) ;
}
return errorBox ;
} ,
addSuccess : function ( elem , fieldWrapper ) {
var type = $ . prop ( elem , 'type' ) ;
var check = function ( ) {
var hasVal = checkTypes [ type ] ? $ . prop ( elem , 'checked' ) : $ ( elem ) . val ( ) ;
fieldWrapper [ hasVal ? 'addClass' : 'removeClass' ] ( successWrapperClass ) ;
} ;
var evt = changeTypes [ type ] ? 'change' : 'blur' ;
$ ( elem ) . off ( '.recheckvalid' ) . on ( evt + '.recheckinvalid' , check ) ;
check ( ) ;
} ,
hideError : function ( elem , reset ) {
var invalid , errorBox , afterHide ;
var fieldWrapper = this . getFieldWrapper ( elem ) ;
2014-11-25 23:27:31 +01:00
if ( ! reset ) {
invalid = $ ( 'input:invalid, select:invalid, textarea:invalid' , fieldWrapper ) ;
}
2014-07-17 16:45:12 +02:00
if ( fieldWrapper . hasClass ( invalidWrapperClass ) ) {
$ ( elem ) . filter ( 'input' ) . off ( '.recheckinvalid' ) ;
2014-11-25 23:27:31 +01:00
if ( ! reset && invalid && invalid [ 0 ] ) {
2014-07-17 16:45:12 +02:00
$ ( invalid ) . trigger ( 'updatevalidation.webshims' ) ;
} else {
errorBox = this . get ( elem , fieldWrapper ) ;
fieldWrapper . removeClass ( invalidWrapperClass ) ;
errorBox . message = '' ;
afterHide = function ( ) {
if ( this . id == elem . getAttribute ( 'aria-describedby' ) ) {
elem . removeAttribute ( 'aria-describedby' ) ;
}
$ ( this ) . attr ( { hidden : 'hidden' } ) ;
} ;
if ( iVal . fx != 'no' ) {
errorBox [ fx [ iVal . fx ] . hide ] ( afterHide ) ;
} else {
errorBox [ fx [ iVal . fx ] . hide ] ( ) . each ( afterHide ) ;
}
}
}
2014-11-25 23:27:31 +01:00
if ( ! reset && ( ! invalid || ! invalid . length ) ) {
2014-07-17 16:45:12 +02:00
this . addSuccess ( elem , fieldWrapper ) ;
}
return fieldWrapper ;
} ,
recheckInvalidInput : function ( input ) {
if ( iVal . recheckDelay && iVal . recheckDelay > 90 ) {
var timer ;
var throttle = function ( ) {
switchValidityClass ( { type : 'input' , target : input } ) ;
} ;
$ ( input )
2014-07-20 02:43:13 +02:00
. filter ( 'input:not([type="checkbox"]):not([type="radio"]), textarea' )
2014-07-17 16:45:12 +02:00
. off ( '.recheckinvalid' )
. on ( 'input.recheckinvalid' , function ( ) {
clearTimeout ( timer ) ;
timer = setTimeout ( throttle , iVal . recheckDelay ) ;
} )
. on ( 'focusout.recheckinvalid' , function ( ) {
clearTimeout ( timer ) ;
} )
;
}
} ,
showError : function ( elem ) {
var fieldWrapper = this . getFieldWrapper ( elem ) ;
var box = this . get ( elem , fieldWrapper ) ;
var message = $ ( elem ) . getErrorMessage ( ) ;
if ( box . message != message ) {
if ( box . stop ) {
box . stop ( true , true ) ;
}
box . html ( '<' + errorMessageWrapper + ' class="' + errorMessageClass + '">' + message + '</' + errorMessageWrapper + '>' ) ;
box . message = message ;
fieldWrapper . addClass ( invalidWrapperClass ) . removeClass ( successWrapperClass ) ;
this . recheckInvalidInput ( elem ) ;
if ( box . is ( '[hidden]' ) || box . css ( 'display' ) == 'none' ) {
if ( ! elem . getAttribute ( 'aria-describedby' ) ) {
elem . setAttribute ( 'aria-describedby' , box . prop ( 'id' ) ) ;
}
box
. css ( { display : 'none' } )
. removeAttr ( 'hidden' )
[ fx [ iVal . fx ] . show ] ( )
;
}
}
fieldWrapper . removeClass ( successWrapperClass ) ;
$ ( elem ) . off ( '.recheckvalid' ) ;
return fieldWrapper ;
} ,
reset : function ( elem ) {
this . hideError ( elem , true ) . removeClass ( successWrapperClass ) ;
} ,
toggle : function ( elem ) {
2014-07-20 02:43:13 +02:00
if ( $ . find . matchesSelector ( elem , ':invalid' ) ) {
2014-07-17 16:45:12 +02:00
this . showError ( elem ) ;
} else {
this . hideError ( elem ) ;
}
}
} ;
$ ( document . body )
. on ( {
'changedvaliditystate' : function ( e ) {
2014-07-20 02:43:13 +02:00
var form ;
if ( iVal . sel && ( form = $ . prop ( e . target , 'form' ) ) && $ . find . matchesSelector ( form , iVal . sel ) ) {
webshims . errorbox . toggle ( e . target ) ;
2014-07-17 16:45:12 +02:00
}
} ,
'resetvalidityui.webshims' : function ( e ) {
2014-07-20 02:43:13 +02:00
var form ;
if ( iVal . sel && ( form = $ . prop ( e . target , 'form' ) ) && $ . find . matchesSelector ( form , iVal . sel ) ) {
webshims . errorbox . reset ( e . target ) ;
2014-07-17 16:45:12 +02:00
}
} ,
firstinvalid : function ( e ) {
2014-07-20 02:43:13 +02:00
var form ;
2014-07-17 16:45:12 +02:00
if ( iVal . sel && iVal . handleBubble ) {
2014-07-20 02:43:13 +02:00
if ( iVal . sel && ( form = $ . prop ( e . target , 'form' ) ) && $ . find . matchesSelector ( form , iVal . sel ) ) {
2014-07-17 16:45:12 +02:00
e . preventDefault ( ) ;
if ( iVal . handleBubble != 'none' ) {
webshims . validityAlert . showFor ( e . target , false , false , iVal . handleBubble == 'hide' ) ;
}
}
}
} ,
submit : function ( e ) {
2014-07-20 02:43:13 +02:00
if ( iVal . sel && iVal . submitCheck && $ . find . matchesSelector ( e . target , iVal . sel ) && $ . prop ( e . target , 'noValidate' ) && ! $ ( e . target ) . checkValidity ( ) ) {
2014-07-17 16:45:12 +02:00
e . stopImmediatePropagation ( ) ;
return false ;
}
}
} )
;
if ( /[\s\:\>\~\+]/ . test ( iVal . sel || '' ) ) {
webshims . error ( 'please use a simple selector for iVal.sel: for example .validate' ) ;
}
if ( options . replaceValidationUI ) {
$ ( document ) . on ( 'firstinvalid' , function ( e ) {
if ( ! e . isDefaultPrevented ( ) ) {
e . preventDefault ( ) ;
setTimeout ( function ( ) {
webshims . validityAlert . showFor ( e . target ) ;
} , 4 ) ;
}
} ) ;
}
/* extension, but also used to fix native implementation workaround/bugfixes */
( function ( ) {
var firstEvent ,
invalids = [ ] ,
stopSubmitTimer ,
stop
;
$ ( document ) . on ( 'invalid' , function ( e ) {
if ( e . wrongWebkitInvalid || stop ) { return ; }
var jElm = $ ( e . target ) ;
if ( ! firstEvent ) {
//trigger firstinvalid
firstEvent = $ . Event ( 'firstinvalid' ) ;
jElm . addClass ( 'first-invalid' ) . trigger ( firstEvent ) ;
}
//if firstinvalid was prevented all invalids will be also prevented
if ( firstEvent && firstEvent . isDefaultPrevented ( ) ) {
e . preventDefault ( ) ;
}
invalids . push ( e . target ) ;
e . extraData = 'fix' ;
clearTimeout ( stopSubmitTimer ) ;
stopSubmitTimer = setTimeout ( function ( ) {
var lastEvent = { type : 'lastinvalid' , cancelable : false , invalidlist : $ ( invalids ) } ;
//reset firstinvalid
invalids = [ ] ;
stop = true ;
$ ( e . target ) . trigger ( lastEvent , [ lastEvent ] ) ;
$ ( firstEvent . target ) . removeClass ( 'first-invalid' ) ;
firstEvent = false ;
/ *
if ( hasNative && ! $ . nodeName ( e . target , 'form' ) ) {
$ ( e . target ) . jProp ( 'form' ) . triggerHandler ( 'invalid' ) ;
}
* /
stop = false ;
} , 9 ) ;
jElm = null ;
} ) ;
} ) ( ) ;
function getFileNames ( file ) {
return file . name ;
}
function customFile ( ) {
if ( $ . data ( this , 'wsCustomFile' ) ) { return ; }
var map = Array . prototype . map ;
var $module = $ ( this ) ;
var $file = $ ( 'input[type="file"]' , $module ) ;
var $valueDisplay = $ ( '.ws-file-value' , $module ) ;
var emptyHtml = $ . trim ( $valueDisplay . html ( ) ) || ' ' ;
var showSelected = function ( ) {
var files = $file . prop ( 'files' ) || [ ] ;
var names = map . call ( files , getFileNames ) . join ( ', ' ) || $file . val ( ) ;
if ( names ) {
$valueDisplay . text ( names ) ;
} else {
$valueDisplay . html ( emptyHtml ) ;
}
} ;
$ . data ( this , 'wsCustomFile' , { showSelected : showSelected } ) ;
2014-09-03 00:57:03 +02:00
$ ( 'button:not(.ws-capture-button)' , $module ) . attr ( 'tabindex' , '-1' ) ;
2014-07-17 16:45:12 +02:00
$file
. on ( 'change.webshim' , showSelected )
. each ( showSelected )
. jProp ( 'form' )
. on ( 'reset' , function ( ) {
setTimeout ( showSelected ) ;
} )
;
if ( isIE ) {
$ ( '<div class="ws-coverfile" />' )
. insertAfter ( $file )
. on ( 'click.webshim' , function ( e ) {
e . stopImmediatePropagation ( ) ;
$file . trigger ( 'click' ) ;
} )
;
}
}
2014-09-03 00:57:03 +02:00
$ ( function ( ) {
var fileReaderReady = ( 'FileReader' in window && 'FormData' in window ) ;
if ( ! fileReaderReady ) {
webshims . addReady ( function ( context ) {
2014-09-05 21:05:17 +02:00
if ( ! fileReaderReady && modules [ 'filereader-xhr' ] && ! modules [ 'filereader-xhr' ] . loaded && context . querySelector ( 'input.ws-filereader' ) ) {
2014-09-03 00:57:03 +02:00
webshims . reTest ( [ 'filereader' ] ) ;
fileReaderReady = true ;
}
} ) ;
}
} ) ;
2014-07-17 16:45:12 +02:00
webshims . addReady ( function ( context , contextElem ) {
$ ( context . querySelectorAll ( '.ws-custom-file' ) ) . add ( $ ( contextElem ) . filter ( '.ws-custom-file' ) ) . each ( customFile ) ;
} ) ;
addModule ( 'form-fixrangechange' , {
test : ! ( ! $ . event . special . change && ! $ . event . special . input && support . inputtypes . range && options . fixRangeChange )
} ) ;
addModule ( 'form-inputmode' , {
test : ! ( ! options . noInputmodeFix && document . addEventListener && support . inputtypes . number && ua . indexOf ( 'Mobile' ) != - 1 && ! ( 'inputMode' in document . createElement ( 'input' ) && ! ( 'inputmode' in document . createElement ( 'input' ) ) ) )
} ) ;
addModule ( 'form-combat' , {
d : [ 'dom-support' ] ,
test : ! ( ( $ . mobile && ( $ . mobile . selectmenu || $ . mobile . checkboxradio ) ) || ( $ . ui && $ . ui . selectmenu ) || $ . fn . select2 || $ . fn . chosen || $ . fn . selectpicker || $ . fn . selectBoxIt )
} ) ;
addModule ( 'position' , {
src : 'plugins/jquery.ui.position.js' ,
test : ! ! ( $ . position && $ . position . getScrollInfo )
} ) ;
loader . loadList ( [ 'form-combat' , 'position' , 'form-fixrangechange' , 'form-inputmode' ] ) ;
} ) ;