vendor/assets/javascripts/webshims/shims/form-shim-extend.js in webshims-rails-1.11.3.1 vs vendor/assets/javascripts/webshims/shims/form-shim-extend.js in webshims-rails-1.11.6
- old
+ new
@@ -2,11 +2,10 @@
"use strict";
webshims.inputTypes = webshims.inputTypes || {};
//some helper-functions
var cfg = webshims.cfg.forms;
var bugs = webshims.bugs;
-var isSubmit;
var isNumber = function(string){
return (typeof string == 'number' || (string && string == string * 1));
},
typeModels = webshims.inputTypes,
@@ -77,10 +76,11 @@
badInput: false,
rangeUnderflow: false,
rangeOverflow: false,
stepMismatch: false,
tooLong: false,
+ tooShort: false,
patternMismatch: false,
valueMissing: false,
valid: true
};
@@ -113,10 +113,13 @@
}
ret = ret.filter('[type="radio"]');
}
return ret;
};
+var patternTypes = {url: 1, email: 1, text: 1, search: 1, tel: 1, password: 1};
+var lengthTypes = $.extend({textarea: 1}, patternTypes);
+
var validityRules = {
valueMissing: function(input, val, cache){
if(!input.prop('required')){return false;}
var ret = false;
if(!('type' in cache)){
@@ -129,15 +132,16 @@
} else {
ret = !(val);
}
return ret;
},
- tooLong: function(){
- return false;
- },
patternMismatch: function(input, val, cache) {
if(val === '' || cache.nodeName == 'select'){return false;}
+ if(!('type' in cache)){
+ cache.type = getType(input[0]);
+ }
+ if(!patternTypes[cache.type]){return false;}
var pattern = input.attr('pattern');
if(!pattern){return false;}
try {
pattern = new RegExp('^(?:' + pattern + ')$');
} catch(er){
@@ -148,10 +152,24 @@
return !(pattern.test(val));
}
}
;
+$.each({tooShort: ['minLength', -1], tooLong: ['maxLength', 1]}, function(name, props){
+ validityRules[name] = function(input, val, cache){
+ //defaultValue is not the same as dirty flag, but very similiar
+ if(cache.nodeName == 'select' || input.prop('defaultValue') == val){return false;}
+ if(!('type' in cache)){
+ cache.type = getType(input[0]);
+ }
+ if(!lengthTypes[cache.type]){return false;}
+ var prop = input.prop(props[0]);
+
+ return ( prop > 0 && prop * props[1] < val.length * props[1] );
+ };
+});
+
$.each({typeMismatch: 'mismatch', badInput: 'bad'}, function(name, fn){
validityRules[name] = function (input, val, cache){
if(val === '' || cache.nodeName == 'select'){return false;}
var ret = false;
if(!('type' in cache)){
@@ -198,19 +216,16 @@
teardown: $.noop,
handler: function(e, d){
if( e.type != 'submit' || e.testedValidity || !e.originalEvent || !$.nodeName(e.target, 'form') || $.prop(e.target, 'noValidate') ){return;}
- isSubmit = true;
e.testedValidity = true;
- var notValid = !($(e.target).checkValidity());
+ var notValid = !($(e.target).callProp('reportValidity'));
if(notValid){
e.stopImmediatePropagation();
- isSubmit = false;
return false;
}
- isSubmit = false;
}
};
$.event.special.submit = $.event.special.submit || {setup: function(){return false;}};
var submitSetup = $.event.special.submit.setup;
@@ -273,10 +288,13 @@
//ToDo: add object to this list
webshims.defineNodeNamesProperties(['button', 'fieldset', 'output'], {
checkValidity: {
value: function(){return true;}
},
+ reportValidity: {
+ value: function(){return true;}
+ },
willValidate: {
value: false
},
setCustomValidity: {
value: $.noop
@@ -287,11 +305,11 @@
return $.extend({}, validityPrototype);
}
}
}, 'prop');
-var baseCheckValidity = function(elem){
+var baseCheckValidity = function(elem, type){
var e,
v = $.prop(elem, 'validity')
;
if(v){
$.data(elem, 'cachedValidity', v);
@@ -299,118 +317,134 @@
return true;
}
if( !v.valid ){
e = $.Event('invalid');
var jElm = $(elem).trigger(e);
- if(isSubmit && !baseCheckValidity.unhandledInvalids && !e.isDefaultPrevented()){
+ if(type == 'reportValidity' && !baseCheckValidity.unhandledInvalids && !e.isDefaultPrevented()){
webshims.validityAlert.showFor(jElm);
baseCheckValidity.unhandledInvalids = true;
}
}
$.removeData(elem, 'cachedValidity');
return v.valid;
};
var rsubmittable = /^(?:select|textarea|input)/i;
-webshims.defineNodeNameProperty('form', 'checkValidity', {
- prop: {
- value: function(){
-
- var ret = true,
- elems = $($.prop(this, 'elements')).filter(function(){
- if(!rsubmittable.test(this.nodeName)){return false;}
- var shadowData = webshims.data(this, 'shadowData');
- return !shadowData || !shadowData.nativeElement || shadowData.nativeElement === this;
- })
- ;
-
- baseCheckValidity.unhandledInvalids = false;
- for(var i = 0, len = elems.length; i < len; i++){
- if( !baseCheckValidity(elems[i]) ){
- ret = false;
+
+['checkValidity', 'reportValidity'].forEach(function(name){
+ webshims.defineNodeNameProperty('form', name, {
+ prop: {
+ value: function(){
+
+ var ret = true,
+ elems = $($.prop(this, 'elements')).filter(function(){
+ if(!rsubmittable.test(this.nodeName)){return false;}
+ var shadowData = webshims.data(this, 'shadowData');
+ return !shadowData || !shadowData.nativeElement || shadowData.nativeElement === this;
+ })
+ ;
+
+ baseCheckValidity.unhandledInvalids = false;
+ for(var i = 0, len = elems.length; i < len; i++){
+ if( !baseCheckValidity(elems[i], name) ){
+ ret = false;
+ }
}
+ return ret;
}
- return ret;
}
- }
+ });
});
-webshims.defineNodeNamesProperties(['input', 'textarea', 'select'], {
- checkValidity: {
- value: function(){
- baseCheckValidity.unhandledInvalids = false;
- return baseCheckValidity($(this).getNativeElement()[0]);
- }
- },
- setCustomValidity: {
- value: function(error){
- $.removeData(this, 'cachedValidity');
- webshims.data(this, 'customvalidationMessage', ''+error);
- }
- },
- willValidate: {
- writeable: false,
- get: (function(){
- var types = {
- button: 1,
- reset: 1,
- hidden: 1,
- image: 1
+
+
+
+['input', 'textarea', 'select'].forEach(function(nodeName){
+ var inputValidationAPI = {
+ setCustomValidity: {
+ value: function(error){
+ $.removeData(this, 'cachedValidity');
+ webshims.data(this, 'customvalidationMessage', ''+error);
+ if(bugs.bustedValidity && inputValidationAPI.setCustomValidity.prop._supvalue){
+ inputValidationAPI.setCustomValidity.prop._supvalue.apply(this, arguments);
}
- ;
- return function(){
- var elem = $(this).getNativeElement()[0];
- //elem.name && <- we don't use to make it easier for developers
- return !!(!elem.disabled && !elem.readOnly && !types[elem.type] );
- };
- })()
- },
- validity: {
- writeable: false,
- get: function(){
- var jElm = $(this).getNativeElement();
- var elem = jElm[0];
- var validityState = $.data(elem, 'cachedValidity');
- if(validityState){
- return validityState;
}
- validityState = $.extend({}, validityPrototype);
-
- if( !$.prop(elem, 'willValidate') || elem.type == 'submit' ){
+ },
+ willValidate: {
+ writeable: false,
+ get: (function(){
+ var types = {
+ button: 1,
+ reset: 1,
+ hidden: 1,
+ image: 1
+ }
+ ;
+ return function(){
+ var elem = $(this).getNativeElement()[0];
+ return !!(!elem.readOnly && !types[elem.type] && !$(elem).is(':disabled') );
+ };
+ })()
+ },
+ validity: {
+ writeable: false,
+ get: function(){
+ var jElm = $(this).getNativeElement();
+ var elem = jElm[0];
+ var validityState = $.data(elem, 'cachedValidity');
+ if(validityState){
+ return validityState;
+ }
+ validityState = $.extend({}, validityPrototype);
+
+ if( !$.prop(elem, 'willValidate') || elem.type == 'submit' ){
+ return validityState;
+ }
+ var val = jElm.val(),
+ cache = {nodeName: elem.nodeName.toLowerCase()}
+ ;
+
+ validityState.customError = !!(webshims.data(elem, 'customvalidationMessage'));
+ if( validityState.customError ){
+ validityState.valid = false;
+ }
+
+ $.each(validityRules, function(rule, fn){
+ if (fn(jElm, val, cache)) {
+ validityState[rule] = true;
+ validityState.valid = false;
+ }
+ });
+ $(this).getShadowFocusElement().attr('aria-invalid', validityState.valid ? 'false' : 'true');
+ jElm = null;
+ elem = null;
return validityState;
}
- var val = jElm.val(),
- cache = {nodeName: elem.nodeName.toLowerCase()}
- ;
-
- validityState.customError = !!(webshims.data(elem, 'customvalidationMessage'));
- if( validityState.customError ){
- validityState.valid = false;
+ }
+ };
+
+ ['checkValidity', 'reportValidity'].forEach(function(name){
+ inputValidationAPI[name] = {
+ value: function(){
+ baseCheckValidity.unhandledInvalids = false;
+ return baseCheckValidity($(this).getNativeElement()[0], name);
}
-
- $.each(validityRules, function(rule, fn){
- if (fn(jElm, val, cache)) {
- validityState[rule] = true;
- validityState.valid = false;
- }
- });
- $(this).getShadowFocusElement().attr('aria-invalid', validityState.valid ? 'false' : 'true');
- jElm = null;
- elem = null;
- return validityState;
}
- }
-}, 'prop');
+ });
+
+ webshims.defineNodeNameProperties(nodeName, inputValidationAPI, 'prop');
+});
+
webshims.defineNodeNamesBooleanProperty(['input', 'textarea', 'select'], 'required', {
set: function(value){
$(this).getShadowFocusElement().attr('aria-required', !!(value)+'');
},
initAttr: Modernizr.localstorage //only if we have aria-support
});
webshims.defineNodeNamesBooleanProperty(['input'], 'multiple');
-if(webshims.bugs.bustedValidity){
+if(bugs.bustedValidity){
webshims.defineNodeNameProperty('form', 'novalidate', {
attr: {
set: function(val){
webshims.data(this, 'bustedNoValidate', ''+val);
@@ -449,10 +483,26 @@
return $.attr(this, 'novalidate') != null;
}
}
});
+webshims.defineNodeNamesProperty(['input', 'textarea'], 'minLength', {
+ prop: {
+ set: function(val){
+ val *= 1;
+ if(val < 0){
+ throw('INDEX_SIZE_ERR');
+ }
+ this.setAttribute('minlength', val || 0);
+ },
+ get: function(){
+ var val = this.getAttribute('minlength');
+ return val == null ? -1 : (val * 1) || 0;
+ }
+ }
+})
+
if(Modernizr.inputtypes.date && /webkit/i.test(navigator.userAgent)){
(function(){
var noInputTriggerEvts = {updateInput: 1, input: 1},
fixInputTypes = {
@@ -503,11 +553,11 @@
setTimeout(function(){
if(e && noFocusEvents[e.type]){
focusedin = false;
}
if(input){
- input.unbind('focusout blur', unbind).unbind('input change updateInput', trigger);
+ input.off('focusout blur', unbind).off('input change updateInput', trigger);
trigger();
}
input = null;
}, 1);
@@ -546,11 +596,11 @@
webshims.addReady(function(context, contextElem){
//start constrain-validation
var focusElem;
$('form', context)
.add(contextElem.filter('form'))
- .bind('invalid', $.noop)
+ .on('invalid', $.noop)
;
try {
if(context == document && !('form' in (document.activeElement || {}))) {
focusElem = $('input[autofocus], select[autofocus], textarea[autofocus]', context).eq(0).getShadowFocusElement()[0];
@@ -722,19 +772,19 @@
formSubmitterDescriptors[attrName] = {};
}
formSubmitterDescriptors[attrName].attr = {
set: function(value){
formSubmitterDescriptors[attrName].attr._supset.call(this, value);
- $(this).unbind(eventName).on(eventName, changeSubmitter);
+ $(this).off(eventName).on(eventName, changeSubmitter);
},
get: function(){
return formSubmitterDescriptors[attrName].attr._supget.call(this);
}
};
formSubmitterDescriptors[attrName].initAttr = true;
formSubmitterDescriptors[attrName].removeAttr = {
value: function(){
- $(this).unbind(eventName);
+ $(this).off(eventName);
formSubmitterDescriptors[attrName].removeAttr._supvalue.call(this);
}
};
});