vendor/assets/javascripts/webshims/shims/combos/24.js in webshims-rails-1.10.11 vs vendor/assets/javascripts/webshims/shims/combos/24.js in webshims-rails-1.11.1
- old
+ new
@@ -2,10 +2,14 @@
var isWebkit = 'webkitURL' in window;
var chromeBugs = isWebkit && Modernizr.formvalidation && !webshims.bugs.bustedValidity;
var webkitVersion = chromeBugs && parseFloat((navigator.userAgent.match(/Safari\/([\d\.]+)/) || ['', '999999'])[1], 10);
var invalidClass = options.iVal.errorClass || 'user-error';
var validClass = options.iVal.successClass || 'user-success';
+
+ var invalidWrapperClass = options.iVal.errorWrapperClass || 'ws-invalid';
+ var successWrapperClass = options.iVal.successWrapperClass || 'ws-success';
+ var errorBoxClass = options.iVal.errorBoxClass || 'ws-errorbox';
var checkTypes = {checkbox: 1, radio: 1};
var emptyJ = $([]);
var isValid = function(elem){
return ($.prop(elem, 'validity') || {valid: 1}).valid;
@@ -91,18 +95,23 @@
(chromeBugs && (e.type == 'change' || webkitVersion < 537.36) && noFocusWidgets[shadowType] && $(e.target).is(':focus')) ||
(e.type == 'focusout' && elem.type == 'radio' && isInGroup(elem.name))
){
return;
}
+ if(webshims.refreshCustomValidityRules){
+ if(webshims.refreshCustomValidityRules(elem) == 'async'){
+ $(elem).one('refreshvalidityui', switchValidityClass);
+ return;
+ }
+ }
+
var validity = $.prop(elem, 'validity');
var addClass, removeClass, trigger, generaltrigger, validityCause;
- if(webshims.refreshCustomValidityRules){
- webshims.refreshCustomValidityRules(elem);
- }
+
if(validity.valid){
if(!shadowElem.hasClass(validClass)){
addClass = validClass;
removeClass = invalidClass;
generaltrigger = 'changedvaliditystate';
@@ -455,14 +464,14 @@
webshims.errorbox = {
create: function(elem, fieldWrapper){
if(!fieldWrapper){
fieldWrapper = this.getFieldWrapper(elem);
}
- var errorBox = $('div.ws-errorbox', fieldWrapper);
+ var errorBox = $('div.'+errorBoxClass, fieldWrapper);
if(!errorBox.length){
- errorBox = $('<div class="ws-errorbox" hidden="hidden">');
+ errorBox = $('<div class="'+ errorBoxClass +'" hidden="hidden">');
fieldWrapper.append(errorBox);
}
fieldWrapper.data('errorbox', errorBox);
return errorBox;
@@ -479,43 +488,87 @@
if(!fieldWrapper){
fieldWrapper = $(elem).parent().closest(':not(span, label, em, strong, b, i, mark, p)');
}
return fieldWrapper;
},
+ _createContentMessage: (function(){
+ var fields = {};
+ var getErrorName = function(elem){
+ var ret = $(elem).data('errortype');
+ if(!ret){
+ $.each(fields, function(errorName, cNames){
+ if($(elem).is(cNames)){
+ ret = errorName;
+ return false;
+ }
+ });
+ }
+ return ret || 'defaultMessage';
+ };
+ $(function(){
+ $.each($('<input />').prop('validity'), function(name){
+ if(name != 'valid'){
+ var cName = name.replace(/[A-Z]/, function(c){
+ return '-'+(c).toLowerCase();
+ });
+ fields[name] = '.'+cName+', .'+name+', .'+(name).toLowerCase()+', [data-errortype="'+ name +'"]';
+ }
+ });
+ });
+ return function(elem, errorBox){
+ var extended = false;
+ var errorMessages = $(elem).data('errormessage') || {};
+ if(typeof errorMessages == 'string'){
+ errorMessages = {defaultMessage: errorMessages};
+ }
+ $('> *', errorBox).each(function(){
+ var name = getErrorName(this);
+ if(!errorMessages[name]){
+ extended = true;
+ errorMessages[name] = $(this).html();
+ }
+ });
+ if(extended){
+ $(elem).data('errormessage', errorMessages);
+ }
+ };
+ })(),
get: function(elem, fieldWrapper){
if(!fieldWrapper){
fieldWrapper = this.getFieldWrapper(elem);
}
var errorBox = fieldWrapper.data('errorbox');
if(!errorBox){
errorBox = this.create(elem, fieldWrapper);
+ this._createContentMessage(elem, errorBox);
} else if(typeof errorBox == 'string'){
errorBox = $('#'+errorBox);
fieldWrapper.data('errorbox', errorBox);
+ this._createContentMessage(elem, errorBox);
}
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']('ws-success');
+ fieldWrapper[hasVal ? 'addClass' : 'removeClass'](successWrapperClass);
};
var evt = changeTypes[type] ? 'change' : 'blur';
$(elem).off('.recheckvalid').on(evt+'.recheckinvalid', check);
check();
},
hideError: function(elem, reset){
var fieldWrapper = this.getFieldWrapper(elem);
- var errorBox = fieldWrapper.data('errorbox');
+ var errorBox = fieldWrapper.hasClass(invalidWrapperClass) ? this.get(elem, fieldWrapper) : fieldWrapper.data('errorbox');
if(errorBox && errorBox.jquery){
- fieldWrapper.removeClass('ws-invalid');
+ fieldWrapper.removeClass(invalidWrapperClass);
errorBox.message = '';
$(elem).filter('input').off('.recheckinvalid');
- errorBox.slideUp(function(){
+ errorBox[fx[options.iVal.fx].hide](function(){
$(this).attr({hidden: 'hidden'});
});
}
if(!reset){
this.addSuccess(elem, fieldWrapper);
@@ -526,47 +579,53 @@
if(options.iVal.recheckDelay && options.iVal.recheckDelay > 90){
var timer;
var throttle = function(){
switchValidityClass({type: 'input', target: input});
};
- $(input).filter('input:not([type="checkbox"], [type="radio"])').off('.recheckinvalid').on('input.recheckinvalid', function(){
- clearTimeout(timer);
- timer = setTimeout(throttle, options.iVal.recheckDelay);
- });
+ $(input)
+ .filter('input:not([type="checkbox"], [type="radio"])')
+ .off('.recheckinvalid')
+ .on('input.recheckinvalid', function(){
+ clearTimeout(timer);
+ timer = setTimeout(throttle, options.iVal.recheckDelay);
+ })
+ .on('focusout.recheckinvalid', function(){
+ clearTimeout(timer);
+ })
+ ;
}
},
- showError: function(elem, message){
+ showError: function(elem){
var fieldWrapper = this.getFieldWrapper(elem);
var box = this.get(elem, fieldWrapper);
-
+ var message = $(elem).getErrorMessage();
if(box.message != message){
box.stop(true, true).html('<p>'+ message +'</p>');
box.message = message;
- fieldWrapper.addClass('ws-invalid').removeClass('ws-success');
- if(box.is('[hidden]')){
+ fieldWrapper.addClass(invalidWrapperClass).removeClass(successWrapperClass);
+ if(box.is('[hidden]') || box.css('display') == 'none'){
this.recheckInvalidInput(elem);
box
.css({display: 'none'})
.removeAttr('hidden')
[fx[options.iVal.fx].show]()
;
}
}
- fieldWrapper.removeClass('ws-success');
+ fieldWrapper.removeClass(successWrapperClass);
$(elem).off('.recheckvalid');
return fieldWrapper;
},
reset: function(elem){
- this.hideError(elem, true).removeClass('ws-success');
+ this.hideError(elem, true).removeClass(successWrapperClass);
},
toggle: function(elem){
- var message = $(elem).getErrorMessage();
- if(message){
- this.showError(elem, message);
+ if($(elem).is(':invalid')){
+ this.showError(elem);
} else {
- this.hideError(elem, message);
+ this.hideError(elem);
}
}
};
$(document.body)
@@ -597,20 +656,72 @@
}
}
}
},
submit: function(e){
- if(options.iVal.sel && $(e.target).is(options.iVal.sel) && $.prop(e.target, 'noValidate') && !$(e.target).checkValidity()){
+ if(options.iVal.sel && !options.iVal.noSubmitCheck &&$(e.target).is(options.iVal.sel) && $.prop(e.target, 'noValidate') && !$(e.target).checkValidity()){
e.stopImmediatePropagation();
return false;
}
}
})
;
webshims.modules["form-core"].getGroupElements = getGroupElements;
+
+ if(options.replaceValidationUI){
+ webshims.ready('DOM forms', function(){
+ $(document).on('firstinvalid', function(e){
+ if(!e.isInvalidUIPrevented()){
+ e.preventDefault();
+ webshims.validityAlert.showFor( e.target );
+ }
+ });
+ });
+ }
+
+ /* extension, but also used to fix native implementation workaround/bugfixes */
+ (function(){
+ var firstEvent,
+ invalids = [],
+ stopSubmitTimer,
+ form
+ ;
+
+ $(document).on('invalid', function(e){
+ if(e.wrongWebkitInvalid){return;}
+ var jElm = $(e.target);
+
+
+ if(!firstEvent){
+ //trigger firstinvalid
+ firstEvent = $.Event('firstinvalid');
+ firstEvent.isInvalidUIPrevented = e.isDefaultPrevented;
+ var firstSystemInvalid = $.Event('firstinvalidsystem');
+ $(document).triggerHandler(firstSystemInvalid, {element: e.target, form: e.target.form, isInvalidUIPrevented: e.isDefaultPrevented});
+ jElm.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
+ firstEvent = false;
+ invalids = [];
+ $(e.target).trigger(lastEvent, [lastEvent]);
+ }, 9);
+ jElm = null;
+ });
+ })();
+
//see: https://bugs.webkit.org/show_bug.cgi?id=113377
if (chromeBugs && webkitVersion < 540) {
(function(){
var elems = /^(?:textarea|input)$/i;
var form = false;
@@ -647,81 +758,100 @@
var blockCustom;
var initTest;
var onEventTest = function(e){
webshims.refreshCustomValidityRules(e.target);
};
+ var noValidate = function(){
+ return !noValidate.types[this.type];
+ };
+ noValidate.types = {
+ hidden: 1,
+ image: 1,
+ button: 1,
+ reset: 1,
+ submit: 1
+ };
-
webshims.customErrorMessages = {};
webshims.addCustomValidityRule = function(name, test, defaultMessage){
customValidityRules[name] = test;
if(!webshims.customErrorMessages[name]){
webshims.customErrorMessages[name] = [];
webshims.customErrorMessages[name][''] = defaultMessage || name;
}
- if($.isReady && formReady){
- $('input, select, textarea').each(function(){
- testValidityRules(this);
- });
+ if(formReady){
+ $('input, select, textarea')
+ .filter(noValidate)
+ .each(function(){
+ testValidityRules(this);
+ })
+ ;
}
};
webshims.refreshCustomValidityRules = function(elem){
- if(!elem.form || (!initTest && !$.prop(elem, 'willValidate')) ){return;}
- blockCustom = true;
- var customMismatchedRule = $.data(elem, 'customMismatchedRule');
+ if(!initTest){return;}
+
+ var data = $(elem).data() || $.data(elem, {});
+ var customMismatchedRule = data.customMismatchedRule;
var validity = $.prop(elem, 'validity') || {};
var message = '';
- if(customMismatchedRule || !validity.customError){
+ var setMessage = function(message, errorType){
+ blockCustom = true;
+ data.customMismatchedRule = message ? errorType : '';
+
+ if(typeof message != 'string'){
+ message = $(elem).data('errormessage') || elem.getAttribute('x-moz-errormessage') || webshims.customErrorMessages[errorType][webshims.activeLang()] || webshims.customErrorMessages[errorType][''];
+ }
+
+ if(typeof message == 'object'){
+ message = message[errorType] || message.customError || message.defaultMessage;
+ }
+ $(elem).setCustomValidity(message);
+ blockCustom = false;
+ };
+ if(customMismatchedRule || validity.valid || (data.dependentValidation && !data.dependentValidation._init)){
var val = $(elem).val();
$.each(customValidityRules, function(name, test){
- message = test(elem, val) || '';
+ message = test(elem, val, data, setMessage) || '';
customMismatchedRule = name;
if(message){
-
- if(typeof message != 'string'){
- message = $(elem).data('errormessage') || elem.getAttribute('x-moz-errormessage') || webshims.customErrorMessages[name][webshims.activeLang()] || webshims.customErrorMessages[name][''];
- }
-
- if(typeof message == 'object'){
- message = message[name] || message.customError || message.defaultMessage;
- }
return false;
}
});
-
- if(message){
- $.data(elem, 'customMismatchedRule', customMismatchedRule);
+ if(message != 'async'){
+ setMessage(message, customMismatchedRule);
}
- $(elem).setCustomValidity(message);
}
- blockCustom = false;
+ return message;
};
var testValidityRules = webshims.refreshCustomValidityRules;
webshims.ready('forms form-validation', function(){
-
- var oldCustomValidity = $.fn.setCustomValidity;
-
-
- $.fn.setCustomValidity = function(message){
- if(!blockCustom){
- this.data('customMismatchedRule', '');
+ $.propHooks.setCustomValidity = {
+ get: function(elem){
+ if(!blockCustom){
+ $.data(elem, 'customMismatchedRule', '');
+ }
+ return null;
}
- return oldCustomValidity.apply(this, arguments);
};
+
setTimeout(function(){
webshims.addReady(function(context, selfElement){
initTest = true;
- $('input, select, textarea', context).add(selfElement.filter('input, select, textarea')).each(function(){
- testValidityRules(this);
- });
- initTest = false;
+ $('input, select, textarea', context).add(selfElement.filter('input, select, textarea'))
+ .filter(noValidate)
+ .each(function(){
+ testValidityRules(this);
+ })
+ ;
+
formReady = true;
});
- $(document).on('refreshCustomValidityRules change', onEventTest);
+ $(document).on('refreshCustomValidityRules', onEventTest);
}, 9);
});
})();
@@ -735,21 +865,24 @@
* - <input type="date" id="start" data-dependent-validation='{"from": "end", "prop": "max"}' /> <input type="date" id="end" data-dependent-validation='{"from": "start", "prop": "min"}' />
* - <input type="checkbox" id="check" /> <input data-dependent-validation='checkbox' />
*/
(function(){
- var addCustomValidityRule = $.webshims.addCustomValidityRule;
- addCustomValidityRule('partialPattern', function(elem, val){
- if(!val || !elem.getAttribute('data-partial-pattern')){return;}
- var pattern = $(elem).data('partial-pattern');
- if(!pattern){return;}
+ var addCustomValidityRule = webshims.addCustomValidityRule;
+ var getId = function(name){
+ return document.getElementById(name);
+ };
+ addCustomValidityRule('partialPattern', function(elem, val, pattern){
+ pattern = pattern.partialPattern;
+ if(!val || !pattern){return;}
return !(new RegExp('(' + pattern + ')', 'i').test(val));
}, 'This format is not allowed here.');
- addCustomValidityRule('tooShort', function(elem, val){
- if(!val || !elem.getAttribute('data-minlength')){return;}
- return $(elem).data('minlength') > val.length;
+
+ addCustomValidityRule('tooShort', function(elem, val, data){
+ if(!val || !data.minlength){return;}
+ return data.minlength > val.length;
}, 'Entered value is too short.');
var groupTimer = {};
addCustomValidityRule('group-required', function(elem, val){
var name = elem.name;
@@ -763,11 +896,11 @@
checkboxes
.addClass('group-required')
.unbind('click.groupRequired')
.bind('click.groupRequired', function(){
checkboxes.filter('.group-required').each(function(){
- $.webshims.refreshCustomValidityRules(this);
+ webshims.refreshCustomValidityRules(this);
});
})
;
}, 9);
@@ -802,23 +935,20 @@
};
var getGroupElements = function(elem) {
return $(elem.form[elem.name]).filter('[type="radio"]');
};
- $.webshims.ready('form-validation', function(){
- if($.webshims.modules){
- getGroupElements = $.webshims.modules["form-core"].getGroupElements || getGroupElements;
+ webshims.ready('form-validation', function(){
+ if(webshims.modules){
+ getGroupElements = webshims.modules["form-core"].getGroupElements || getGroupElements;
}
});
- addCustomValidityRule('dependent', function(elem, val){
-
- if( !elem.getAttribute('data-dependent-validation') ){return;}
-
- var data = $(elem).data('dependentValidation');
+ addCustomValidityRule('dependent', function(elem, val, data){
+ data = data.dependentValidation;
+ if( !data ){return;}
var specialVal;
- if(!data){return;}
var depFn = function(e){
var val = $.prop(data.masterElement, data["from-prop"]);
if(specialVal){
val = $.inArray(val, specialVal) !== -1;
}
@@ -863,11 +993,11 @@
if(data.prop !== "value" || specialVal){
$(data.masterElement.type === 'radio' && getGroupElements(data.masterElement) || data.masterElement).bind('change', depFn);
} else {
$(data.masterElement).bind('change', function(){
- $.webshims.refreshCustomValidityRules(elem);
+ webshims.refreshCustomValidityRules(elem);
$(elem).getShadowElement().filter('.user-error, .user-success').trigger('refreshvalidityui');
});
}
}
@@ -877,8 +1007,123 @@
depFn();
return '';
}
}, 'The value of this field does not repeat the value of the other field');
+
+
+ if(window.JSON){
+ addCustomValidityRule('ajaxvalidate', function(elem, val, data){
+ if(!val || !data.ajaxvalidate){return;}
+ var opts;
+ if(!data.remoteValidate){
+ if(typeof data.ajaxvalidate == 'string'){
+ data.ajaxvalidate = {url: data.ajaxvalidate, depends: $([])};
+ } else {
+ data.ajaxvalidate.depends = data.ajaxvalidate.depends ? $(data.ajaxvalidate.depends).map(getId) : $([]);
+ }
+
+ data.ajaxvalidate.depends.on('refreshCustomValidityRules', function(){
+ webshims.refreshCustomValidityRules(elem);
+ });
+
+ opts = data.ajaxvalidate;
+
+ var remoteValidate = {
+ ajaxLoading: false,
+ restartAjax: false,
+ message: 'async',
+ cache: {},
+ update: function(remoteData){
+ if(this.ajaxLoading){
+ this.restartAjax = remoteData;
+ } else {
+ this.restartAjax = false;
+ this.ajaxLoading = true;
+ $.ajax(
+ $.extend({}, opts, {
+ url: opts.url,
+ dataType: 'json',
+ depData: remoteData,
+ data: opts.fullForm ?
+ $(elem).jProp('form').serializeArray() :
+ remoteData,
+ success: this.getResponse,
+ complete: this._complete
+ })
+ );
+ }
+ },
+ _complete: function(){
+ remoteValidate.ajaxLoading = false;
+ if(remoteValidate.restartAjax){
+ this.update(remoteValidate.restartAjax);
+ }
+ remoteValidate.restartAjax = false;
+ },
+ getResponse: function(data){
+ var old = webshims.refreshCustomValidityRules;
+ if(!data){
+ data = {message: '', valid: true};
+ } else if(typeof data == 'string'){
+ data = JSON.parse(data);
+ }
+
+ remoteValidate.message = ('message' in data) ? data.message : !data.valid;
+ remoteValidate.lastMessage = remoteValidate.message;
+ remoteValidate.blockUpdate = true;
+ $(elem).triggerHandler('refreshvalidityui');
+ remoteValidate.message = 'async';
+ remoteValidate.blockUpdate = false;
+ },
+ getData: function(){
+ var data;
+ data = {};
+ data[$.prop(elem, 'name') || $.prop(elem, 'id')] = $(elem).val();
+ opts.depends.each(function(){
+ if($(this).is(':invalid')){
+ data = false;
+ return false;
+ }
+ data[$.prop(this, 'name') || $.prop(this, 'id')] = $(this).val();
+ });
+ return data;
+ },
+ getTempMessage: function(){
+ var message = 'async';
+ var remoteData, dataStr;
+ if(!data.remoteValidate.blockUpdate){
+ remoteData = this.getData();
+ if(!remoteData){
+ message = '';
+ } else {
+ try {
+ dataStr = JSON.stringify(remoteData);
+ } catch(er){}
+
+ if(dataStr === this.lastString){
+ message = this.ajaxLoading ? 'async' : this.lastMessage;
+ } else {
+ this.lastString = dataStr;
+ this.lastMessage = 'async';
+ clearTimeout(data.remoteValidate.timer);
+ data.remoteValidate.timer = setTimeout(function(){
+ data.remoteValidate.update(remoteData);
+ }, 9);
+ }
+
+ }
+ } else {
+ message = remoteValidate.message;
+ }
+ return message;
+ }
+ };
+ data.remoteValidate = remoteValidate;
+ }
+
+ return data.remoteValidate.getTempMessage();
+ }, 'remote error');
+ }
})();
});