vendor/assets/javascripts/webshims/shims/combos/24.js in webshims-rails-1.11.1 vs vendor/assets/javascripts/webshims/shims/combos/24.js in webshims-rails-1.11.2
- old
+ new
@@ -1,1129 +1,1821 @@
-webshims.register('form-validation', function($, webshims, window, document, undefined, options){
- 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;
- };
-
- var nonFormFilter = function(){
- return !$.prop(this, 'form');
- };
- var getGroupElements = function(elem){
- 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 = {
+webshims.register('form-shim-extend', function($, webshims, window, document, undefined, options){
+"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,
+ checkTypes = {
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 switchValidityClass = function(e){
- if(!options.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(
- (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(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');
+ checkbox: 1
+ },
+ getType = function(elem){
+ return (elem.getAttribute('type') || elem.type || '').toLowerCase();
+ }
+;
+
+(function(){
+ if('querySelector' in document){
+ try {
+ bugs.findRequired = !($('<form action="#" style="width: 1px; height: 1px; overflow: hidden;"><select name="b" required="" /></form>')[0].querySelector('select:required'));
+ } catch(er){
+ bugs.findRequired = false;
+ }
+
+ if (bugs.bustedValidity || bugs.findRequired) {
+ (function(){
+ var find = $.find;
+ var matchesSelector = $.find.matchesSelector;
+
+ var regExp = /(\:valid|\:invalid|\:optional|\:required|\:in-range|\:out-of-range)(?=[\s\[\~\.\+\>\:\#*]|$)/ig;
+ var regFn = function(sel){
+ return sel + '-element';
+ };
+
+ $.find = (function(){
+ var slice = Array.prototype.slice;
+ var fn = function(sel){
+ var ar = arguments;
+ ar = slice.call(ar, 1, ar.length);
+ ar.unshift(sel.replace(regExp, regFn));
+ return find.apply(this, ar);
+ };
+ for (var i in find) {
+ if(find.hasOwnProperty(i)){
+ fn[i] = find[i];
+ }
}
- shadowElem.removeAttr('aria-invalid');
- $.removeData(elem, 'webshimsinvalidcause');
+ return fn;
+ })();
+ if(!Modernizr.prefixed || Modernizr.prefixed("matchesSelector", document.documentElement)){
+ $.find.matchesSelector = function(node, expr){
+ expr = expr.replace(regExp, regFn);
+ return matchesSelector.call(this, node, expr);
+ };
}
- } 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);
- }, 0);
- }
- if(generaltrigger){
- setTimeout(function(){
- $(elem).trigger(generaltrigger);
- }, 0);
- }
-
- $.removeData(elem, 'webshimsswitchvalidityclass');
- };
-
- if(timer){
- clearTimeout(timer);
+
+ })();
}
- if(e.type == 'refreshvalidityui'){
- switchClass();
+ }
+})();
+
+//API to add new input types
+webshims.addInputType = function(type, obj){
+ typeModels[type] = obj;
+};
+
+//contsrain-validation-api
+var validityPrototype = {
+ customError: false,
+
+ typeMismatch: false,
+ badInput: false,
+ rangeUnderflow: false,
+ rangeOverflow: false,
+ stepMismatch: false,
+ tooLong: false,
+ patternMismatch: false,
+ valueMissing: false,
+
+ valid: true
+};
+
+var isPlaceholderOptionSelected = function(select){
+ if(select.type == 'select-one' && select.size < 2){
+ var option = $('> option:first-child', select);
+ return !!option.prop('selected');
+ }
+ return false;
+};
+
+var emptyJ = $([]);
+var getGroupElements = function(elem){
+ 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[name]);
} else {
- $.data(elem, 'webshimsswitchvalidityclass', setTimeout(switchClass, 9));
+ ret = $(document.getElementsByName(name)).filter(function(){
+ return !$.prop(this, 'form');
+ });
}
- };
-
- $(document.body || 'html')
- .on(options.validityUIEvents || 'focusout change refreshvalidityui invalid', switchValidityClass)
- .on('reset resetvalui', function(e){
- var elems = $(e.target);
- if(e.type == 'reset'){
- elems = elems.filter('form').jProp('elements');
+ ret = ret.filter('[type="radio"]');
+ }
+ return ret;
+};
+var validityRules = {
+ valueMissing: function(input, val, cache){
+ if(!input.prop('required')){return false;}
+ var ret = false;
+ if(!('type' in cache)){
+ cache.type = getType(input[0]);
}
- elems
- .filter('.user-error, .user-success')
- .removeAttr('aria-invalid')
- .removeClass('user-error')
- .removeClass('user-success')
- .getNativeElement()
- .each(function(){
- $.removeData(this, 'webshimsinvalidcause');
- })
- .trigger('resetvalidityui')
- ;
- })
- ;
-
- var setRoot = function(){
- webshims.scrollRoot = (isWebkit || document.compatMode == 'BackCompat') ?
- $(document.body) :
- $(document.documentElement)
- ;
- };
- var minWidth = (Modernizr.boxSizing || Modernizr['display-table'] || $.support.getSetAttribute || $.support.boxSizing) ?
- 'minWidth' :
- 'width'
- ;
- var hasTransition = ('transitionDelay' in document.documentElement.style);
- var resetPos = {display: 'inline-block', left: 0, top: 0, marginTop: 0, marginLeft: 0, marginRight: 0, marginBottom: 0};
-
- setRoot();
- webshims.ready('DOM', setRoot);
-
-
- webshims.getRelOffset = function(posElem, relElem, opts){
- var offset, bodyOffset, dirs;
- posElem = $(posElem);
- $.swap($(posElem)[0], resetPos, function(){
- if($.position && opts && $.position.getScrollInfo){
- if(!opts.of){
- opts.of = relElem;
- }
-
- 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 || 'center',
- 'data-at': opts.at || 'center'
- });
- posElem.position(opts);
-
+ if(cache.nodeName == 'select'){
+ ret = (!val && (input[0].selectedIndex < 0 || isPlaceholderOptionSelected(input[0]) ));
+ } else if(checkTypes[cache.type]){
+ ret = (cache.type == 'checkbox') ? !input.is(':checked') : !getGroupElements(input).filter(':checked')[0];
} else {
- offset = $(relElem).offset();
- bodyOffset = posElem.offset();
- offset.top -= bodyOffset.top;
- offset.left -= bodyOffset.left;
-
- offset.top += relElem.outerHeight();
+ ret = !(val);
}
-
- });
+ return ret;
+ },
+ tooLong: function(){
+ return false;
+ },
+ patternMismatch: function(input, val, cache) {
+ if(val === '' || cache.nodeName == 'select'){return false;}
+ var pattern = input.attr('pattern');
+ if(!pattern){return false;}
+ try {
+ pattern = new RegExp('^(?:' + pattern + ')$');
+ } catch(er){
+ webshims.error('invalid pattern value: "'+ pattern +'" | '+ er);
+ pattern = false;
+ }
+ if(!pattern){return false;}
+ return !(pattern.test(val));
+ }
+ }
+;
+
+$.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)){
+ cache.type = getType(input[0]);
+ }
- return offset;
+ if(typeModels[cache.type] && typeModels[cache.type][fn]){
+ ret = typeModels[cache.type][fn](val, input);
+ } else if('validity' in input[0] && ('name' in input[0].validity)){
+ ret = input[0].validity[name] || false;
+ }
+ return ret;
};
-
- $.extend(webshims.wsPopover, {
+});
+
+webshims.addValidityRule = function(type, fn){
+ validityRules[type] = fn;
+};
+
+$.event.special.invalid = {
+ add: function(){
+ $.event.special.invalid.setup.call(this.form || this);
+ },
+ setup: function(){
+ var form = this.form || this;
+ if( $.data(form, 'invalidEventShim') ){
+ form = null;
+ return;
+ }
+ $(form)
+ .data('invalidEventShim', true)
+ .on('submit', $.event.special.invalid.handler)
+ ;
+ webshims.moveToFirstEvent(form, 'submit');
+ if(webshims.bugs.bustedValidity && $.nodeName(form, 'form')){
+ (function(){
+ var noValidate = form.getAttribute('novalidate');
+ form.setAttribute('novalidate', 'novalidate');
+ webshims.data(form, 'bustedNoValidate', (noValidate == null) ? null : noValidate);
+ })();
+ }
+ form = null;
+ },
+ teardown: $.noop,
+ handler: function(e, d){
+ if( e.type != 'submit' || e.testedValidity || !e.originalEvent || !$.nodeName(e.target, 'form') || $.prop(e.target, 'noValidate') ){return;}
- isInElement: function(container, contained){
- return container == contained || $.contains(container, contained);
- },
- show: function(element){
- if(this.isVisible){return;}
- var e = $.Event('wspopoverbeforeshow');
- this.element.trigger(e);
- if(e.isDefaultPrevented()){return;}
- this.isVisible = true;
- element = $(element || this.options.prepareFor).getNativeElement() ;
+ isSubmit = true;
+ e.testedValidity = true;
+ var notValid = !($(e.target).checkValidity());
+ 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;
+$.extend($.event.special.submit, {
+ setup: function(){
+ if($.nodeName(this, 'form')){
+ $(this).on('invalid', $.noop);
+ } else {
+ $('form', this).on('invalid', $.noop);
+ }
+ return submitSetup.apply(this, arguments);
+ }
+});
+webshims.ready('form-shim-extend2 WINDOWLOAD', function(){
+ $(window).on('invalid', $.noop);
+});
+
+
+webshims.addInputType('email', {
+ mismatch: (function(){
+ //taken from http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
+ var test = cfg.emailReg || /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
+ var splitReg = /\s*,\s*/g;
+ return function(val, input){
+ var ret = false;
+ val = $(input).prop('multiple') ? val.split(splitReg) : [val];
- var that = this;
- 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);
- };
+ for(var i = 0; i < val.length; i++){
+ if(!test.test(val[i])){
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+ };
+ })()
+});
- this.clear();
- this.element.removeClass('ws-po-visible').css('display', 'none');
+webshims.addInputType('url', {
+ mismatch: (function(){
+ //taken from scott gonzales
+ var test = cfg.urlReg || /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i;
+ return function(val){
+ return !test.test(val);
+ };
+ })()
+});
+
+webshims.defineNodeNameProperty('input', 'type', {
+ prop: {
+ get: function(){
+ var elem = this;
+ var type = (elem.getAttribute('type') || '').toLowerCase();
+ return (webshims.inputTypes[type]) ? type : elem.type;
+ }
+ }
+});
+
+// IDLs for constrain validation API
+//ToDo: add object to this list
+webshims.defineNodeNamesProperties(['button', 'fieldset', 'output'], {
+ checkValidity: {
+ value: function(){return true;}
+ },
+ willValidate: {
+ value: false
+ },
+ setCustomValidity: {
+ value: $.noop
+ },
+ validity: {
+ writeable: false,
+ get: function(){
+ return $.extend({}, validityPrototype);
+ }
+ }
+}, 'prop');
+
+var baseCheckValidity = function(elem){
+ var e,
+ v = $.prop(elem, 'validity')
+ ;
+ if(v){
+ $.data(elem, 'cachedValidity', v);
+ } else {
+ return true;
+ }
+ if( !v.valid ){
+ e = $.Event('invalid');
+ var jElm = $(elem).trigger(e);
+ if(isSubmit && !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(){
- this.prepareFor(element, visual);
+ 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;
+ })
+ ;
- this.position(visual);
- that.timers.show = setTimeout(function(){
- that.element.css('display', '');
- that.timers.show = setTimeout(function(){
- that.element.addClass('ws-po-visible').trigger('wspopovershow');
- }, 9);
- }, 9);
-
- $(document).on('focusin'+this.eventns+' mousedown'+this.eventns, function(e){
- if(that.options.hideOnBlur && !that.stopBlur && !that.isInElement(that.lastElement[0] || document.body, e.target) && !that.isInElement(element[0] || document.body, e.target) && !that.isInElement(that.element[0], e.target)){
- that.hide();
+ baseCheckValidity.unhandledInvalids = false;
+ for(var i = 0, len = elems.length; i < len; i++){
+ if( !baseCheckValidity(elems[i]) ){
+ ret = false;
}
- });
-
- this.element.off('pospopover').on('pospopover', delayedRepos);
- $(window).on('resize'+this.eventns + ' pospopover'+this.eventns, delayedRepos);
- },
- prepareFor: function(element, visual){
- var onBlur;
- var that = this;
- var css = {};
- var opts = $.extend(true, {}, this.options, $(element.prop('form') || []).data('wspopover') || {}, element.data('wspopover'));
- this.lastOpts = opts;
- this.lastElement = $(element).getShadowFocusElement();
- if(!this.prepared || !this.options.prepareFor){
- if(opts.appendTo == 'element'){
- this.element.insertAfter(element);
- } else {
- this.element.appendTo(opts.appendTo);
+ }
+ 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
}
+ ;
+ 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);
- this.element.attr({
- 'data-class': element.prop('className'),
- 'data-id': element.prop('id')
- });
-
- css[minWidth] = opts.constrainWidth ? visual.outerWidth() : '';
-
- 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);
-
-
+ if( !$.prop(elem, 'willValidate') || elem.type == 'submit' ){
+ return validityState;
}
+ var val = jElm.val(),
+ cache = {nodeName: elem.nodeName.toLowerCase()}
+ ;
- if(!this.prepared && $.fn.bgIframe){
- this.element.bgIframe();
+ validityState.customError = !!(webshims.data(elem, 'customvalidationMessage'));
+ if( validityState.customError ){
+ validityState.valid = false;
}
- this.prepared = true;
- },
- clear: function(){
- $(window).off(this.eventns);
- $(document).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 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);
+
+ $.each(validityRules, function(rule, fn){
+ if (fn(jElm, val, cache)) {
+ validityState[rule] = true;
+ validityState.valid = false;
}
- };
- this.clear();
- this.element.removeClass('ws-po-visible').trigger('wspopoverhide');
- $(window).on('resize'+this.eventns, forceHide);
- if(hasTransition){
- this.element.off('transitionend'+this.eventns).on('transitionend'+this.eventns, forceHide);
+ });
+ $(this).getShadowFocusElement().attr('aria-invalid', validityState.valid ? 'false' : 'true');
+ jElm = null;
+ elem = null;
+ return validityState;
+ }
+ }
+}, '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){
+
+ webshims.defineNodeNameProperty('form', 'novalidate', {
+ attr: {
+ set: function(val){
+ webshims.data(this, 'bustedNoValidate', ''+val);
+ },
+ get: function(){
+ var ret = webshims.data(this, 'bustedNoValidate');
+ return ret == null ? undefined : ret;
}
-
- that.timers.forcehide = setTimeout(forceHide, hasTransition ? 600 : 40);
},
- position: function(element){
- var offset = webshims.getRelOffset(this.element.removeAttr('hidden'), element, (this.lastOpts || this.options).position);
-
- this.element.css(offset);
+ removeAttr: {
+ value: function(){
+ webshims.data(this, 'bustedNoValidate', null);
+ }
}
});
+ $.each(['rangeUnderflow', 'rangeOverflow', 'stepMismatch'], function(i, name){
+ validityRules[name] = function(elem){
+ return (elem[0].validity || {})[name] || false;
+ };
+ });
-
- /* some extra validation UI */
- webshims.validityAlert = (function(){
+}
+
+webshims.defineNodeNameProperty('form', 'noValidate', {
+ prop: {
+ set: function(val){
+ val = !!val;
+ if(val){
+ $.attr(this, 'novalidate', 'novalidate');
+ } else {
+ $(this).removeAttr('novalidate');
+ }
+ },
+ get: function(){
+ return $.attr(this, 'novalidate') != null;
+ }
+ }
+});
+
+if(Modernizr.inputtypes.date && /webkit/i.test(navigator.userAgent)){
+ (function(){
- options.messagePopover.position = $.extend({}, {
- at: 'left bottom',
- my: 'left top',
- collision: 'none'
- }, options.messagePopover.position || {});
-
- var focusTimer = false;
-
- var api = webshims.objectCreate(webshims.wsPopover, {}, 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);
- }
+ var noInputTriggerEvts = {updateInput: 1, input: 1},
+ fixInputTypes = {
+ date: 1,
+ time: 1,
+ month: 1,
+ week: 1,
+ "datetime-local": 1
},
- setFocus: function(element){
- var focusElem = $(element).getShadowFocusElement();
- var scrollTop = webshims.scrollRoot.scrollTop();
- var elemTop = focusElem.offset().top - 30;
- var focus = function(){
- try {
- focusElem[0].focus();
- } catch(e){}
- $(window).triggerHandler('pospopover'+this.eventns);
- };
-
- if(scrollTop > elemTop){
- webshims.scrollRoot.animate(
- {scrollTop: elemTop - 5},
- {
- queue: false,
- duration: Math.max( Math.min( 600, (scrollTop - elemTop) * 1.5 ), 80 ),
- complete: focus
+ noFocusEvents = {
+ focusout: 1,
+ blur: 1
+ },
+ changeEvts = {
+ updateInput: 1,
+ change: 1
+ },
+ observe = function(input){
+ var timer,
+ focusedin = true,
+ lastInputVal = input.prop('value'),
+ lastChangeVal = lastInputVal,
+ trigger = function(e){
+ //input === null
+ if(!input){return;}
+ var newVal = input.prop('value');
+
+ if(newVal !== lastInputVal){
+ lastInputVal = newVal;
+ if(!e || !noInputTriggerEvts[e.type]){
+ input.trigger('input');
+ }
}
- );
-
- } else {
- focus();
- }
+ if(e && changeEvts[e.type]){
+ lastChangeVal = newVal;
+ }
+ if(!focusedin && newVal !== lastChangeVal){
+ input.trigger('change');
+ }
+ },
+ extraTimer,
+ extraTest = function(){
+ clearTimeout(extraTimer);
+ extraTimer = setTimeout(trigger, 9);
+ },
+ unbind = function(e){
+ clearInterval(timer);
+ setTimeout(function(){
+ if(e && noFocusEvents[e.type]){
+ focusedin = false;
+ }
+ if(input){
+ input.unbind('focusout blur', unbind).unbind('input change updateInput', trigger);
+ trigger();
+ }
+ input = null;
+ }, 1);
+
+ }
+ ;
- },
- getMessage: function(elem, message){
- if (!message) {
- message = elem.getErrorMessage();
- }
- if (message) {
- api.contentElement.text(message);
- } else {
- this.hide();
- }
+ clearInterval(timer);
+ timer = setInterval(trigger, 160);
+ extraTest();
+ input
+ .off({
+ 'focusout blur': unbind,
+ 'input change updateInput': trigger
+ })
+ .on({
+ 'focusout blur': unbind,
+ 'input updateInput change': trigger
+ })
+ ;
}
- });
+ ;
- return api;
+ $(document)
+ .on('focusin', function(e){
+ if( e.target && fixInputTypes[e.target.type] && !e.target.readOnly && !e.target.disabled ){
+ observe($(e.target));
+ }
+ })
+ ;
+
+
})();
+}
+
+webshims.addReady(function(context, contextElem){
+ //start constrain-validation
+ var focusElem;
+ $('form', context)
+ .add(contextElem.filter('form'))
+ .bind('invalid', $.noop)
+ ;
- var fx = {
- slide: {
- show: 'slideDown',
- hide: 'slideUp'
- },
- fade: {
- show: 'fadeIn',
- hide: 'fadeOut'
+ try {
+ if(context == document && !('form' in (document.activeElement || {}))) {
+ focusElem = $('input[autofocus], select[autofocus], textarea[autofocus]', context).eq(0).getShadowFocusElement()[0];
+ if (focusElem && focusElem.offsetHeight && focusElem.offsetWidth) {
+ focusElem.focus();
+ }
}
- };
- if(!fx[options.iVal.fx]){
- options.iVal.fx = 'slide';
- }
- webshims.errorbox = {
- create: function(elem, fieldWrapper){
- if(!fieldWrapper){
- fieldWrapper = this.getFieldWrapper(elem);
+ }
+ catch (er) {}
+
+});
+
+if(!Modernizr.input.list){
+ webshims.defineNodeNameProperty('datalist', 'options', {
+ prop: {
+ writeable: false,
+ get: function(){
+ var elem = this;
+ var select = $('select', elem);
+ var options;
+ if(select[0]){
+ options = $.makeArray(select[0].options || []);
+ } else {
+ options = $('option', elem).get();
+ if(options.length){
+ webshims.warn('you should wrap your option-elements for a datalist in a select element to support IE and other old browsers.');
+ }
+ }
+ return options;
}
- var errorBox = $('div.'+errorBoxClass, fieldWrapper);
+ }
+ });
+}
+
+
+
+var submitterTypes = {submit: 1, button: 1, image: 1};
+var formSubmitterDescriptors = {};
+[
+ {
+ name: "enctype",
+ limitedTo: {
+ "application/x-www-form-urlencoded": 1,
+ "multipart/form-data": 1,
+ "text/plain": 1
+ },
+ defaultProp: "application/x-www-form-urlencoded",
+ proptype: "enum"
+ },
+ {
+ name: "method",
+ limitedTo: {
+ "get": 1,
+ "post": 1
+ },
+ defaultProp: "get",
+ proptype: "enum"
+ },
+ {
+ name: "action",
+ proptype: "url"
+ },
+ {
+ name: "target"
+ },
+ {
+ name: "novalidate",
+ propName: "noValidate",
+ proptype: "boolean"
+ }
+].forEach(function(desc){
+ var propName = 'form'+ (desc.propName || desc.name).replace(/^[a-z]/, function(f){
+ return f.toUpperCase();
+ });
+ var attrName = 'form'+ desc.name;
+ var formName = desc.name;
+ var eventName = 'click.webshimssubmittermutate'+formName;
+
+ var changeSubmitter = function(){
+ var elem = this;
+ if( !('form' in elem) || !submitterTypes[elem.type] ){return;}
+ var form = $.prop(elem, 'form');
+ if(!form){return;}
+ var attr = $.attr(elem, attrName);
+ if(attr != null && ( !desc.limitedTo || attr.toLowerCase() === $.prop(elem, propName))){
- if(!errorBox.length){
- errorBox = $('<div class="'+ errorBoxClass +'" hidden="hidden">');
- fieldWrapper.append(errorBox);
- }
+ var oldAttr = $.attr(form, formName);
- fieldWrapper.data('errorbox', errorBox);
- return errorBox;
- },
- getFieldWrapper: function(elem){
- var fieldWrapper;
- if(options.iVal.fieldWrapper){
- fieldWrapper = (typeof options.iVal.fieldWrapper == "function") ? options.iVal.fieldWrapper.apply(this, arguments) : $(elem).parent().closest(options.iVal.fieldWrapper);
- if(!fieldWrapper.length){
- fieldWrapper = false;
- webshims.error("could not find fieldwrapper: "+ options.iVal.fieldWrapper);
+ $.attr(form, formName, attr);
+ setTimeout(function(){
+ if(oldAttr != null){
+ $.attr(form, formName, oldAttr);
+ } else {
+ try {
+ $(form).removeAttr(formName);
+ } catch(er){
+ form.removeAttribute(formName);
+ }
}
- }
- 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;
+ }, 9);
+ }
+ };
+
+
+
+switch(desc.proptype) {
+ case "url":
+ var urlForm = document.createElement('form');
+ formSubmitterDescriptors[propName] = {
+ prop: {
+ set: function(value){
+ $.attr(this, attrName, value);
+ },
+ get: function(){
+ var value = $.attr(this, attrName);
+ if(value == null){return '';}
+ urlForm.setAttribute('action', value);
+ return urlForm.action;
+ }
+ }
+ };
+ break;
+ case "boolean":
+ formSubmitterDescriptors[propName] = {
+ prop: {
+ set: function(val){
+ val = !!val;
+ if(val){
+ $.attr(this, 'formnovalidate', 'formnovalidate');
+ } else {
+ $(this).removeAttr('formnovalidate');
}
- });
+ },
+ get: function(){
+ return $.attr(this, 'formnovalidate') != null;
+ }
}
- 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 +'"]';
+ break;
+ case "enum":
+ formSubmitterDescriptors[propName] = {
+ prop: {
+ set: function(value){
+ $.attr(this, attrName, value);
+ },
+ get: function(){
+ var value = $.attr(this, attrName);
+ return (!value || ( (value = value.toLowerCase()) && !desc.limitedTo[value] )) ? desc.defaultProp : value;
}
- });
- });
- 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();
+ };
+ break;
+ default:
+ formSubmitterDescriptors[propName] = {
+ prop: {
+ set: function(value){
+ $.attr(this, attrName, value);
+ },
+ get: function(){
+ var value = $.attr(this, attrName);
+ return (value != null) ? value : "";
}
- });
- 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;
+ }
+
+
+ if(!formSubmitterDescriptors[attrName]){
+ formSubmitterDescriptors[attrName] = {};
+ }
+ formSubmitterDescriptors[attrName].attr = {
+ set: function(value){
+ formSubmitterDescriptors[attrName].attr._supset.call(this, value);
+ $(this).unbind(eventName).on(eventName, changeSubmitter);
},
- 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';
+ get: function(){
+ return formSubmitterDescriptors[attrName].attr._supget.call(this);
+ }
+ };
+ formSubmitterDescriptors[attrName].initAttr = true;
+ formSubmitterDescriptors[attrName].removeAttr = {
+ value: function(){
+ $(this).unbind(eventName);
+ formSubmitterDescriptors[attrName].removeAttr._supvalue.call(this);
+ }
+ };
+});
+
+webshims.defineNodeNamesProperties(['input', 'button'], formSubmitterDescriptors);
+
+}); //webshims.ready end
+
+webshims.register('form-shim-extend2', function($, webshims, window, document, undefined, options){
+"use strict";
+var emptyJ = $([]);
+var getGroupElements = function(elem){
+ 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[name]);
+ } else {
+ ret = $(document.getElementsByName(name)).filter(function(){
+ return !$.prop(this, 'form');
+ });
+ }
+ ret = ret.filter('[type="radio"]');
+ }
+ return ret;
+};
+//submitbubbles for IE6-IE8
+var supportSubmitBubbles = !('submitBubbles' in $.support) || $.support.submitBubbles;
+var addSubmitBubbles = function(form){
+ if (!supportSubmitBubbles && form && typeof form == 'object' && !form._submit_attached ) {
+
+ $.event.add( form, 'submit._submit', function( event ) {
+ event._submit_bubble = true;
+ });
+
+ form._submit_attached = true;
+ }
+};
+if(!supportSubmitBubbles && $.event.special.submit){
+
+ $.event.special.submit.setup = function() {
+ // Only need this for delegated form submit events
+ if ( $.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ $.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = $.nodeName( elem, 'input' ) || $.nodeName( elem, 'button' ) ? $.prop(elem, 'form') : undefined;
+ addSubmitBubbles(form);
- $(elem).off('.recheckvalid').on(evt+'.recheckinvalid', check);
- check();
- },
- hideError: function(elem, reset){
- var fieldWrapper = this.getFieldWrapper(elem);
- var errorBox = fieldWrapper.hasClass(invalidWrapperClass) ? this.get(elem, fieldWrapper) : fieldWrapper.data('errorbox');
-
- if(errorBox && errorBox.jquery){
- fieldWrapper.removeClass(invalidWrapperClass);
- errorBox.message = '';
- $(elem).filter('input').off('.recheckinvalid');
- errorBox[fx[options.iVal.fx].hide](function(){
- $(this).attr({hidden: 'hidden'});
+ });
+ // return undefined since we don't need an event listener
+ };
+}
+
+
+
+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.reflectProperties(['input'], ['pattern']);
+
+
+if( !('maxLength' in document.createElement('textarea')) ){
+ var constrainMaxLength = (function(){
+ var timer;
+ var curLength = 0;
+ var lastElement = $([]);
+ var max = 1e9;
+ var constrainLength = function(){
+ var nowValue = lastElement.prop('value');
+ var nowLen = nowValue.length;
+ if(nowLen > curLength && nowLen > max){
+ nowLen = Math.max(curLength, max);
+ lastElement.prop('value', nowValue.substr(0, nowLen ));
+ }
+ curLength = nowLen;
+ };
+ var remove = function(){
+ clearTimeout(timer);
+ lastElement.unbind('.maxlengthconstraint');
+ };
+ return function(element, maxLength){
+ remove();
+ if(maxLength > -1){
+ max = maxLength;
+ curLength = $.prop(element, 'value').length;
+ lastElement = $(element);
+ lastElement.on({
+ 'keydown.maxlengthconstraint keypress.maxlengthconstraint paste.maxlengthconstraint cut.maxlengthconstraint': function(e){
+ setTimeout(constrainLength, 0);
+ },
+ 'keyup.maxlengthconstraint': constrainLength,
+ 'blur.maxlengthconstraint': remove
});
+ timer = setInterval(constrainLength, 200);
}
- if(!reset){
- this.addSuccess(elem, fieldWrapper);
+ };
+ })();
+
+ constrainMaxLength.update = function(element, maxLength){
+ if($(element).is(':focus')){
+ if(!maxLength){
+ maxLength = $.prop(element, 'maxlength');
}
- return fieldWrapper;
- },
- recheckInvalidInput: function(input){
- 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);
- })
- .on('focusout.recheckinvalid', function(){
- clearTimeout(timer);
- })
- ;
+ constrainMaxLength(element, maxLength);
+ }
+ };
+
+ $(document).on('focusin', function(e){
+ var maxLength;
+ if(e.target.nodeName == "TEXTAREA" && (maxLength = $.prop(e.target, 'maxlength')) > -1){
+ constrainMaxLength(e.target, maxLength);
+ }
+ });
+
+ webshims.defineNodeNameProperty('textarea', 'maxlength', {
+ attr: {
+ set: function(val){
+ this.setAttribute('maxlength', ''+val);
+ constrainMaxLength.update(this);
+ },
+ get: function(){
+ var ret = this.getAttribute('maxlength');
+ return ret == null ? undefined : ret;
}
},
- 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(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]()
- ;
+ prop: {
+ set: function(val){
+ if(isNumber(val)){
+ if(val < 0){
+ throw('INDEX_SIZE_ERR');
+ }
+ val = parseInt(val, 10);
+ this.setAttribute('maxlength', val);
+ constrainMaxLength.update(this, val);
+ return;
}
+ this.setAttribute('maxlength', '0');
+ constrainMaxLength.update(this, 0);
+ },
+ get: function(){
+ var val = this.getAttribute('maxlength');
+ return (isNumber(val) && val >= 0) ? parseInt(val, 10) : -1;
+
}
- fieldWrapper.removeClass(successWrapperClass);
- $(elem).off('.recheckvalid');
-
- return fieldWrapper;
- },
- reset: function(elem){
- this.hideError(elem, true).removeClass(successWrapperClass);
- },
- toggle: function(elem){
- if($(elem).is(':invalid')){
- this.showError(elem);
- } else {
- this.hideError(elem);
+ }
+ });
+ webshims.defineNodeNameProperty('textarea', 'maxLength', {
+ prop: {
+ set: function(val){
+ $.prop(this, 'maxlength', val);
+ },
+ get: function(){
+ return $.prop(this, 'maxlength');
}
}
- };
-
- $(document.body)
- .on({
- 'changedvaliditystate': function(e){
- if(options.iVal.sel){
- var form = $(e.target).jProp('form');
- if(form.is(options.iVal.sel)){
- webshims.errorbox.toggle(e.target);
- }
- }
+ });
+}
+
+if(!$.support.getSetAttribute && $('<form novalidate></form>').attr('novalidate') == null){
+ webshims.defineNodeNameProperty('form', 'novalidate', {
+ attr: {
+ set: function(val){
+ this.setAttribute('novalidate', ''+val);
},
- resetvalidityui: function(e){
- if (options.iVal.sel) {
- var form = $(e.target).jProp('form');
- if (form.is(options.iVal.sel)) {
- webshims.errorbox.reset(e.target);
+ get: function(){
+ var ret = this.getAttribute('novalidate');
+ return ret == null ? undefined : ret;
+ }
+ }
+ });
+}
+
+
+if(Modernizr.formattribute === false || !Modernizr.fieldsetdisabled){
+ (function(){
+
+ (function(prop, undefined){
+ $.prop = function(elem, name, value){
+ var ret;
+ if(elem && elem.nodeType == 1 && value === undefined && $.nodeName(elem, 'form') && elem.id){
+ ret = document.getElementsByName(name);
+ if(!ret || !ret.length){
+ ret = document.getElementById(name);
}
- }
- },
- firstinvalid: function(e){
- if(options.iVal.sel && options.iVal.handleBubble){
- var form = $(e.target).jProp('form');
- if(form.is(options.iVal.sel)){
- e.preventDefault();
- if(options.iVal.handleBubble != 'none'){
- webshims.validityAlert.showFor( e.target, false, false, options.iVal.handleBubble == 'hide' );
+ if(ret){
+ ret = $(ret).filter(function(){
+ return $.prop(this, 'form') == elem;
+ }).get();
+ if(ret.length){
+ return ret.length == 1 ? ret[0] : ret;
}
}
}
- },
- submit: function(e){
- if(options.iVal.sel && !options.iVal.noSubmitCheck &&$(e.target).is(options.iVal.sel) && $.prop(e.target, 'noValidate') && !$(e.target).checkValidity()){
- e.stopImmediatePropagation();
- return false;
- }
+ return prop.apply(this, arguments);
+ };
+ })($.prop, undefined);
+
+ var removeAddedElements = function(form){
+ var elements = $.data(form, 'webshimsAddedElements');
+ if(elements){
+ elements.remove();
+ $.removeData(form, 'webshimsAddedElements');
}
- })
- ;
-
- 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 );
+ };
+
+
+ if(!Modernizr.formattribute){
+ webshims.defineNodeNamesProperty(['input', 'textarea', 'select', 'button', 'fieldset'], 'form', {
+ prop: {
+ get: function(){
+ var form = webshims.contentAttr(this, 'form');
+ if(form){
+ form = document.getElementById(form);
+ if(form && !$.nodeName(form, 'form')){
+ form = null;
+ }
+ }
+ return form || this.form;
+ },
+ writeable: false
}
});
- });
- }
-
- /* 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);
- }
+ webshims.defineNodeNamesProperty(['form'], 'elements', {
+ prop: {
+ get: function(){
+ var id = this.id;
+ var elements = $.makeArray(this.elements);
+ if(id){
+ elements = $(elements).add('input[form="'+ id +'"], select[form="'+ id +'"], textarea[form="'+ id +'"], button[form="'+ id +'"], fieldset[form="'+ id +'"]').not('.webshims-visual-hide > *').get();
+ }
+ return elements;
+ },
+ writeable: false
+ }
+ });
+
+
+
+ $(function(){
+ var stopPropagation = function(e){
+ e.stopPropagation();
+ };
+ var submitters = {
+ image: 1,
+ submit: 1
+ };
+ $(document).on('submit', function(e){
+
+ if(!e.isDefaultPrevented()){
+ var form = e.target;
+ var id = form.id;
+ var elements;
+
+
+ if(id){
+ removeAddedElements(form);
+
+ elements = $('input[form="'+ id +'"], select[form="'+ id +'"], textarea[form="'+ id +'"]')
+ .filter(function(){
+ return !this.disabled && this.name && this.form != form;
+ })
+ .clone()
+ ;
+ if(elements.length){
+ $.data(form, 'webshimsAddedElements', $('<div class="webshims-visual-hide" />').append(elements).appendTo(form));
+ setTimeout(function(){
+ removeAddedElements(form);
+ }, 9);
+ }
+ elements = null;
+ }
+ }
+ });
+
+
+ $(document).on('click', function(e){
+ if(submitters[e.target.type] && !e.isDefaultPrevented() && $(e.target).is('input[form], button[form]')){
+ var trueForm = $.prop(e.target, 'form');
+ var formIn = e.target.form;
+ var clone;
+ if(trueForm && trueForm != formIn){
+ clone = $(e.target)
+ .clone()
+ .removeAttr('form')
+ .addClass('webshims-visual-hide')
+ .on('click', stopPropagation)
+ .appendTo(trueForm)
+ ;
+ if(formIn){
+ e.preventDefault();
+ }
+ addSubmitBubbles(trueForm);
+ clone.trigger('click');
+ setTimeout(function(){
+ clone.remove();
+ clone = null;
+ }, 9);
+ }
+ }
+ });
+ });
+ }
+
+ if(!Modernizr.fieldsetdisabled){
+ webshims.defineNodeNamesProperty(['fieldset'], 'elements', {
+ prop: {
+ get: function(){
+ //add listed elements without keygen, object, output
+ return $('input, select, textarea, button, fieldset', this).get() || [];
+ },
+ writeable: false
+ }
+ });
+ }
+
+ if(!$.fn.finish && parseFloat($.fn.jquery, 10) < 1.9){
+ var rCRLF = /\r?\n/g,
+ rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+ rselectTextarea = /^(?:select|textarea)/i;
+ $.fn.serializeArray = function() {
+ return this.map(function(){
+ var elements = $.prop(this, 'elements');
+ return elements ? $.makeArray( elements ) : this;
+ })
+ .filter(function(){
+ return this.name && !this.disabled &&
+ ( this.checked || rselectTextarea.test( this.nodeName ) ||
+ rinput.test( this.type ) );
+ })
+ .map(function( i, elem ){
+ var val = $( this ).val();
+
+ return val == null ?
+ null :
+ $.isArray( val ) ?
+ $.map( val, function( val, i ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ };
+ }
+
+ })();
+}
- //if firstinvalid was prevented all invalids will be also prevented
- if( firstEvent && firstEvent.isDefaultPrevented() ){
- e.preventDefault();
+ if($('<input />').prop('labels') == null){
+ webshims.defineNodeNamesProperty('button, input, keygen, meter, output, progress, select, textarea', 'labels', {
+ prop: {
+ get: function(){
+ if(this.type == 'hidden'){return null;}
+ var id = this.id;
+ var labels = $(this)
+ .closest('label')
+ .filter(function(){
+ var hFor = (this.attributes['for'] || {});
+ return (!hFor.specified || hFor.value == id);
+ })
+ ;
+
+ if(id) {
+ labels = labels.add('label[for="'+ id +'"]');
+ }
+ return labels.get();
+ },
+ writeable: false
}
- 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) {
+ if(!('value' in document.createElement('progress'))){
(function(){
- var elems = /^(?:textarea|input)$/i;
- var form = false;
- document.addEventListener('contextmenu', function(e){
- if (elems.test(e.target.nodeName || '') && (form = e.target.form)) {
- setTimeout(function(){
- form = false;
- }, 1);
- }
- }, false);
+ var nan = parseInt('NaN', 10);
- $(window).on('invalid', function(e){
- if (e.originalEvent && form && form == e.target.form) {
- e.wrongWebkitInvalid = true;
- e.stopImmediatePropagation();
+ var updateProgress = function(progress){
+ var position;
+
+
+ position = $.prop(progress, 'position');
+
+ $.attr(progress, 'data-position', position);
+ $('> span', progress).css({width: (position < 0 ? 100 : position * 100) +'%'});
+ };
+ var desc = {
+ position: {
+ prop: {
+ get: function(){
+ var max;
+ //jQuery 1.8.x try's to normalize "0" to 0
+ var val = this.getAttribute('value');
+ var ret = -1;
+
+ val = val ? (val * 1) : nan;
+ if(!isNaN(val)){
+ max = $.prop(this, 'max');
+ ret = Math.max(Math.min(val / max, 1), 0);
+ if(updateProgress.isInChange){
+ $.attr(this, 'aria-valuenow', ret * 100);
+ if(updateProgress.isInChange == 'max'){
+ $.attr(this, 'aria-valuemax', max);
+ }
+ }
+ } else if(updateProgress.isInChange) {
+ $(this).removeAttr('aria-valuenow');
+ }
+ return ret;
+ },
+ writeable: false
+ }
}
+ };
+
+ $.each({value: 0, max: 1}, function(name, defValue){
+ var removeProp = (name == 'value' && !$.fn.finish);
+ desc[name] = {
+ attr: {
+ set: function(value){
+ var ret = desc[name].attr._supset.call(this, value);
+ updateProgress.isInChange = name;
+ updateProgress(this);
+ updateProgress.isInChange = false;
+ return ret;
+ }
+ },
+ removeAttr: {
+ value: function(){
+ this.removeAttribute(name);
+ if(removeProp){
+ try {
+ delete this.value;
+ } catch(er){}
+ }
+ updateProgress.isInChange = name;
+ updateProgress(this);
+ updateProgress.isInChange = false;
+ }
+ },
+ prop: {
+ get: function(){
+ var max;
+ var ret = (desc[name].attr.get.call(this) * 1);
+ if(ret < 0 || isNaN(ret)){
+ ret = defValue;
+ } else if(name == 'value'){
+ ret = Math.min(ret, $.prop(this, 'max'));
+ } else if(ret === 0){
+ ret = defValue;
+ }
+ return ret;
+ },
+ set: function(value){
+ value = value * 1;
+ if(isNaN(value)){
+ webshims.error('Floating-point value is not finite.');
+ }
+ return desc[name].attr.set.call(this, value);
+ }
+ }
+ };
});
+ webshims.createElement(
+ 'progress',
+ function(){
+ var labels = $(this)
+ .attr({role: 'progressbar', 'aria-valuemin': '0'})
+ .html('<span class="progress-value" />')
+ .jProp('labels')
+ .map(function(){
+ return webshims.getID(this);
+ })
+ .get()
+ ;
+ if(labels.length){
+ $.attr(this, 'aria-labelledby', labels.join(' '));
+ } else {
+ webshims.info("you should use label elements for your prgogress elements");
+ }
+
+ updateProgress.isInChange = 'max';
+ updateProgress(this);
+ updateProgress.isInChange = false;
+ },
+ desc
+ );
+
})();
}
-});
-webshims.register('form-validators', function($, webshims, window, document, undefined, options){
-"use strict";
-
-(function(){
- if(webshims.refreshCustomValidityRules){
- webshims.error("form-validators already included. please remove custom-validity.js");
- }
-
- var customValidityRules = {};
- var formReady = false;
- 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(formReady){
- $('input, select, textarea')
- .filter(noValidate)
- .each(function(){
- testValidityRules(this);
- })
- ;
- }
- };
- webshims.refreshCustomValidityRules = function(elem){
- if(!initTest){return;}
-
- var data = $(elem).data() || $.data(elem, {});
- var customMismatchedRule = data.customMismatchedRule;
- var validity = $.prop(elem, 'validity') || {};
- var message = '';
- 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][''];
+try {
+ document.querySelector(':checked');
+} catch(er){
+ (function(){
+ $('html').addClass('no-csschecked');
+ var checkInputs = {
+ radio: 1,
+ checkbox: 1
+ };
+ var selectChange = function(){
+ var options = this.options || [];
+ var i, len, option;
+ for(i = 0, len = options.length; i < len; i++){
+ option = $(options[i]);
+ option[$.prop(options[i], 'selected') ? 'addClass' : 'removeClass']('prop-checked');
}
+ };
+ var checkChange = function(){
+ var fn = $.prop(this, 'checked') ? 'addClass' : 'removeClass';
+ var className = this.className || '';
+ var parent;
- if(typeof message == 'object'){
- message = message[errorType] || message.customError || message.defaultMessage;
+ //IE8- has problems to update styles, we help
+ if( (className.indexOf('prop-checked') == -1) == (fn == 'addClass')){
+ $(this)[fn]('prop-checked');
+ if((parent = this.parentNode)){
+ parent.className = parent.className;
+ }
}
- $(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, data, setMessage) || '';
- customMismatchedRule = name;
- if(message){
- return false;
- }
- });
- if(message != 'async'){
- setMessage(message, customMismatchedRule);
+
+
+ webshims.onNodeNamesPropertyModify('select', 'value', selectChange);
+ webshims.onNodeNamesPropertyModify('select', 'selectedIndex', selectChange);
+ webshims.onNodeNamesPropertyModify('option', 'selected', function(){
+ $(this).closest('select').each(selectChange);
+ });
+ webshims.onNodeNamesPropertyModify('input', 'checked', function(value, boolVal){
+ var type = this.type;
+ if(type == 'radio' && boolVal){
+ getGroupElements(this).each(checkChange);
+ } else if(checkInputs[type]) {
+ $(this).each(checkChange);
}
- }
- return message;
- };
- var testValidityRules = webshims.refreshCustomValidityRules;
-
- webshims.ready('forms form-validation', function(){
+ });
- $.propHooks.setCustomValidity = {
- get: function(elem){
- if(!blockCustom){
- $.data(elem, 'customMismatchedRule', '');
+ $(document).on('change', function(e){
+
+ if(checkInputs[e.target.type]){
+ if(e.target.type == 'radio'){
+ getGroupElements(e.target).each(checkChange);
+ } else {
+ $(e.target)[$.prop(e.target, 'checked') ? 'addClass' : 'removeClass']('prop-checked');
}
- return null;
+ } else if(e.target.nodeName.toLowerCase() == 'select'){
+ $(e.target).each(selectChange);
}
- };
+ });
-
- setTimeout(function(){
- webshims.addReady(function(context, selfElement){
- initTest = true;
- $('input, select, textarea', context).add(selfElement.filter('input, select, textarea'))
- .filter(noValidate)
- .each(function(){
- testValidityRules(this);
- })
- ;
-
- formReady = true;
- });
- $(document).on('refreshCustomValidityRules', onEventTest);
- }, 9);
-
- });
-
-})();
-
-/*
- * adds support for HTML5 constraint validation
- * - partial pattern: <input data-partial-pattern="RegExp" />
- * - creditcard-validation: <input class="creditcard-input" />
- * - several dependent-validation patterns (examples):
- * - <input type="email" id="mail" /> <input data-dependent-validation='mail' />
- * - <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;
- 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, 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;
- if(!name || elem.type !== 'checkbox' || !$(elem).hasClass('group-required')){return;}
- var checkboxes = $( (elem.form && elem.form[name]) || document.getElementsByName(name));
- var isValid = checkboxes.filter(':checked:enabled');
- if(groupTimer[name]){
- clearTimeout(groupTimer[name]);
- }
- groupTimer[name] = setTimeout(function(){
- checkboxes
- .addClass('group-required')
- .unbind('click.groupRequired')
- .bind('click.groupRequired', function(){
- checkboxes.filter('.group-required').each(function(){
- webshims.refreshCustomValidityRules(this);
- });
+ webshims.addReady(function(context, contextElem){
+ $('option, input', context)
+ .add(contextElem.filter('option, input'))
+ .each(function(){
+ var prop;
+ if(checkInputs[this.type]){
+ prop = 'checked';
+ } else if(this.nodeName.toLowerCase() == 'option'){
+ prop = 'selected';
+ }
+ if(prop){
+ $(this)[$.prop(this, prop) ? 'addClass' : 'removeClass']('prop-checked');
+ }
+
})
;
- }, 9);
+ });
+ })();
+}
+
+(function(){
+ var bustedPlaceholder;
+ Modernizr.textareaPlaceholder = !!('placeholder' in $('<textarea />')[0]);
+ if(Modernizr.input.placeholder && options.overridePlaceholder){
+ bustedPlaceholder = true;
+ }
+ if(Modernizr.input.placeholder && Modernizr.textareaPlaceholder && !bustedPlaceholder){
+ (function(){
+ var ua = navigator.userAgent;
+
+ if(ua.indexOf('Mobile') != -1 && ua.indexOf('Safari') != -1){
+ $(window).on('orientationchange', (function(){
+ var timer;
+ var retVal = function(i, value){
+ return value;
+ };
+
+ var set = function(){
+ $('input[placeholder], textarea[placeholder]').attr('placeholder', retVal);
+ };
+ return function(e){
+ clearTimeout(timer);
+ timer = setTimeout(set, 9);
+ };
+ })());
+ }
+ })();
- return !(isValid[0]);
- }, 'Please check one of these checkboxes.');
+ //abort
+ return;
+ }
- // based on https://sites.google.com/site/abapexamples/javascript/luhn-validation
- addCustomValidityRule('creditcard', function(elem, value){
- if(!value || !$(elem).hasClass('creditcard-input')){return;}
- value = value.replace(/\-/g, "");
- //if it's not numeric return true >- for invalid
- if(value != value * 1){return true;}
- var len = value.length;
- var sum = 0;
- var mul = 1;
- var ca;
+ var isOver = (webshims.cfg.forms.placeholderType == 'over');
+ var isResponsive = (webshims.cfg.forms.responsivePlaceholder);
+ var polyfillElements = ['textarea'];
+ var debug = webshims.debug !== false;
+ if(!Modernizr.input.placeholder || bustedPlaceholder){
+ polyfillElements.push('input');
+ }
- while (len--) {
- ca = parseInt(value.charAt(len),10) * mul;
- sum += ca - (ca>9)*9;// sum += ca - (-(ca>9))|9
- // 1 <--> 2 toggle.
- mul ^= 3; // (mul = 3 - mul);
- }
- return !((sum%10 === 0) && (sum > 0));
- }, 'Please enter a valid credit card number');
-
- var dependentDefaults = {
- //"from": "IDREF || UniqueNAMEREF", //required property: element
- "prop": "value", //default: value||disabled (last if "from-prop" is checked)
- "from-prop": "value", //default: value||checked (last if element checkbox or radio)
- "toggle": false
+ var setSelection = function(elem){
+ try {
+ if(elem.setSelectionRange){
+ elem.setSelectionRange(0, 0);
+ return true;
+ } else if(elem.createTextRange){
+ var range = elem.createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', 0);
+ range.moveStart('character', 0);
+ range.select();
+ return true;
+ }
+ } catch(er){}
};
- 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;
- }
- });
-
- addCustomValidityRule('dependent', function(elem, val, data){
- data = data.dependentValidation;
- if( !data ){return;}
- var specialVal;
- var depFn = function(e){
- var val = $.prop(data.masterElement, data["from-prop"]);
- if(specialVal){
- val = $.inArray(val, specialVal) !== -1;
+ var hidePlaceholder = function(elem, data, value, _onFocus){
+ if(value === false){
+ value = $.prop(elem, 'value');
}
- if(data.toggle){
- val = !val;
+
+ if(!isOver && elem.type != 'password'){
+ if(!value && _onFocus && setSelection(elem)){
+ var selectTimer = setTimeout(function(){
+ setSelection(elem);
+ }, 9);
+ $(elem)
+ .off('.placeholderremove')
+ .on({
+ 'keydown.placeholderremove keypress.placeholderremove paste.placeholderremove input.placeholderremove': function(e){
+ if(e && (e.keyCode == 17 || e.keyCode == 16)){return;}
+ elem.value = $.prop(elem, 'value');
+ data.box.removeClass('placeholder-visible');
+ clearTimeout(selectTimer);
+ $(elem).unbind('.placeholderremove');
+ },
+ 'mousedown.placeholderremove drag.placeholderremove select.placeholderremove': function(e){
+ setSelection(elem);
+ clearTimeout(selectTimer);
+ selectTimer = setTimeout(function(){
+ setSelection(elem);
+ }, 9);
+ },
+ 'blur.placeholderremove': function(){
+ clearTimeout(selectTimer);
+ $(elem).unbind('.placeholderremove');
+ }
+ })
+ ;
+ return;
+ } else if(!_onFocus && !value && elem.value){ //especially on submit
+ elem.value = value;
+ }
+ } else if(!value && _onFocus){
+ $(elem)
+ .off('.placeholderremove')
+ .on({
+ 'keydown.placeholderremove keypress.placeholderremove paste.placeholderremove input.placeholderremove': function(e){
+ if(e && (e.keyCode == 17 || e.keyCode == 16)){return;}
+ data.box.removeClass('placeholder-visible');
+ $(elem).unbind('.placeholderremove');
+ },
+ 'blur.placeholderremove': function(){
+ $(elem).unbind('.placeholderremove');
+ }
+ })
+ ;
+ return;
}
- $.prop( elem, data.prop, val);
- if(e){
- $(elem).getShadowElement().filter('.user-error, .user-success').trigger('refreshvalidityui');
+ data.box.removeClass('placeholder-visible');
+ },
+ showPlaceholder = function(elem, data, placeholderTxt){
+ if(placeholderTxt === false){
+ placeholderTxt = $.prop(elem, 'placeholder');
}
- };
-
- if(!data._init || !data.masterElement){
- if(typeof data == 'string'){
- data = {"from": data};
+ if(!isOver && elem.type != 'password'){
+ elem.value = placeholderTxt;
}
+ data.box.addClass('placeholder-visible');
+ },
+ changePlaceholderVisibility = function(elem, value, placeholderTxt, data, type){
+ if(!data){
+ data = $.data(elem, 'placeHolder');
+ if(!data){return;}
+ }
+ var isVisible = $(elem).hasClass('placeholder-visible');
+ if(placeholderTxt === false){
+ placeholderTxt = $.attr(elem, 'placeholder') || '';
+ }
+ $(elem).unbind('.placeholderremove');
- data.masterElement = document.getElementById(data["from"]) || (document.getElementsByName(data["from"] || [])[0]);
+ if(value === false){
+ value = $.prop(elem, 'value');
+ }
- if (!data.masterElement || !data.masterElement.form) {return;}
-
- if(/radio|checkbox/i.test(data.masterElement.type)){
- if(!data["from-prop"]){
- data["from-prop"] = 'checked';
+ if(!value && (type == 'focus' || (!type && $(elem).is(':focus')))){
+ if(elem.type == 'password' || isOver || isVisible){
+ hidePlaceholder(elem, data, '', true);
}
- if(!data.prop && data["from-prop"] == 'checked'){
- data.prop = 'disabled';
- }
- } else if(!data["from-prop"]){
- data["from-prop"] = 'value';
+ return;
}
- if(data["from-prop"].indexOf('value:') === 0){
- specialVal = data["from-prop"].replace('value:', '').split('||');
- data["from-prop"] = 'value';
-
+ if(value){
+ hidePlaceholder(elem, data, value);
+ return;
}
- data = $.data(elem, 'dependentValidation', $.extend({_init: true}, dependentDefaults, data));
-
- if(data.prop !== "value" || specialVal){
- $(data.masterElement.type === 'radio' && getGroupElements(data.masterElement) || data.masterElement).bind('change', depFn);
+ if(placeholderTxt && !value){
+ showPlaceholder(elem, data, placeholderTxt);
} else {
- $(data.masterElement).bind('change', function(){
- webshims.refreshCustomValidityRules(elem);
- $(elem).getShadowElement().filter('.user-error, .user-success').trigger('refreshvalidityui');
- });
+ hidePlaceholder(elem, data, value);
}
- }
-
- if(data.prop == "value" && !specialVal){
- return ($.prop(data.masterElement, 'value') != val);
- } else {
- 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) : $([]);
+ },
+ hasLabel = function(elem){
+ elem = $(elem);
+ return !!(elem.prop('title') || elem.attr('aria-labelledby') || elem.attr('aria-label') || elem.jProp('labels').length);
+ },
+ createPlaceholder = function(elem){
+ elem = $(elem);
+ return $( hasLabel(elem) ? '<span class="placeholder-text"></span>' : '<label for="'+ elem.prop('id') +'" class="placeholder-text"></label>');
+ },
+ pHolder = (function(){
+ var delReg = /\n|\r|\f|\t/g,
+ allowedPlaceholder = {
+ text: 1,
+ search: 1,
+ url: 1,
+ email: 1,
+ password: 1,
+ tel: 1,
+ number: 1
}
-
- 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;
+ ;
+ if(webshims.modules["form-number-date-ui"].loaded){
+ delete allowedPlaceholder.number;
+ }
+
+ return {
+ create: function(elem){
+ var data = $.data(elem, 'placeHolder');
+ var form;
+ var responsiveElem;
+ if(data){return data;}
+ data = $.data(elem, 'placeHolder', {});
+
+ $(elem).on('focus.placeholder blur.placeholder', function(e){
+ changePlaceholderVisibility(this, false, false, data, e.type );
+ data.box[e.type == 'focus' ? 'addClass' : 'removeClass']('placeholder-focused');
+ });
+
+ if((form = $.prop(elem, 'form'))){
+ $(elem).onWSOff('reset.placeholder', function(e){
+ setTimeout(function(){
+ changePlaceholderVisibility(elem, false, false, data, e.type );
+ }, 0);
+ }, false, form);
+ }
+
+ if(elem.type == 'password' || isOver){
+ data.text = createPlaceholder(elem);
+ if(isResponsive || $(elem).is('.responsive-width') || (elem.currentStyle || {width: ''}).width.indexOf('%') != -1){
+ responsiveElem = true;
+ data.box = data.text;
} 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
- })
- );
+ data.box = $(elem)
+ .wrap('<span class="placeholder-box placeholder-box-'+ (elem.nodeName || '').toLowerCase() +' placeholder-box-'+$.css(elem, 'float')+'" />')
+ .parent()
+ ;
}
- },
- _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;
+ data.text
+ .insertAfter(elem)
+ .on('mousedown.placeholder', function(){
+ changePlaceholderVisibility(this, false, false, data, 'focus');
+ try {
+ setTimeout(function(){
+ elem.focus();
+ }, 0);
+ } catch(e){}
return false;
+ })
+ ;
+
+
+ $.each(['lineHeight', 'fontSize', 'fontFamily', 'fontWeight'], function(i, style){
+ var prop = $.css(elem, style);
+ if(data.text.css(style) != prop){
+ data.text.css(style, prop);
}
- 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);
+ $.each(['Left', 'Top'], function(i, side){
+ var size = (parseInt($.css(elem, 'padding'+ side), 10) || 0) + Math.max((parseInt($.css(elem, 'margin'+ side), 10) || 0), 0) + (parseInt($.css(elem, 'border'+ side +'Width'), 10) || 0);
+ data.text.css('padding'+ side, size);
+ });
+
+ $(elem)
+ .onWSOff('updateshadowdom', function(){
+ var height, width;
+ if((width = elem.offsetWidth) || (height = elem.offsetHeight)){
+ data.text
+ .css({
+ width: width,
+ height: height
+ })
+ .css($(elem).position())
+ ;
}
+ }, true)
+ ;
+
+ } else {
+ var reset = function(e){
+ if($(elem).hasClass('placeholder-visible')){
+ hidePlaceholder(elem, data, '');
+ setTimeout(function(){
+ if(!e || e.type != 'submit' || e.isDefaultPrevented()){
+ changePlaceholderVisibility(elem, false, false, data );
+ }
+ }, 9);
}
- } else {
- message = remoteValidate.message;
+ };
+
+ $(elem).onWSOff('beforeunload', reset, false, window);
+ data.box = $(elem);
+ if(form){
+ $(elem).onWSOff('submit', reset, false, form);
}
- return message;
}
- };
- data.remoteValidate = remoteValidate;
+
+ return data;
+ },
+ update: function(elem, val){
+ var type = ($.attr(elem, 'type') || $.prop(elem, 'type') || '').toLowerCase();
+ if(!allowedPlaceholder[type] && !$.nodeName(elem, 'textarea')){
+ webshims.warn('placeholder not allowed on input[type="'+type+'"], but it is a good fallback :-)');
+ return;
+ }
+
+
+ var data = pHolder.create(elem);
+ if(data.text){
+ data.text.text(val);
+ }
+
+ changePlaceholderVisibility(elem, false, val, data);
+ }
+ };
+ })()
+ ;
+
+ $.webshims.publicMethods = {
+ pHolder: pHolder
+ };
+ polyfillElements.forEach(function(nodeName){
+ var desc = webshims.defineNodeNameProperty(nodeName, 'placeholder', {
+ attr: {
+ set: function(val){
+ var elem = this;
+ if(bustedPlaceholder){
+ webshims.data(elem, 'bustedPlaceholder', val);
+ elem.placeholder = '';
+ } else {
+ webshims.contentAttr(elem, 'placeholder', val);
+ }
+ pHolder.update(elem, val);
+ },
+ get: function(){
+ var placeholder;
+ if(bustedPlaceholder){
+ placeholder = webshims.data(this, 'bustedPlaceholder');
+ }
+ return placeholder || webshims.contentAttr(this, 'placeholder');
+ }
+ },
+ reflect: true,
+ initAttr: true
+ });
+ });
+
+
+ polyfillElements.forEach(function(name){
+ var placeholderValueDesc = {};
+ var desc;
+ ['attr', 'prop'].forEach(function(propType){
+ placeholderValueDesc[propType] = {
+ set: function(val){
+ var elem = this;
+ var placeholder;
+ if(bustedPlaceholder){
+ placeholder = webshims.data(elem, 'bustedPlaceholder');
+ }
+ if(!placeholder){
+ placeholder = webshims.contentAttr(elem, 'placeholder');
+ }
+ $.removeData(elem, 'cachedValidity');
+ var ret = desc[propType]._supset.call(elem, val);
+ if(placeholder && 'value' in elem){
+ changePlaceholderVisibility(elem, val, placeholder);
+ }
+ return ret;
+ },
+ get: function(){
+ var elem = this;
+ return $(elem).hasClass('placeholder-visible') ? '' : desc[propType]._supget.call(elem);
+ }
+ };
+ });
+ desc = webshims.defineNodeNameProperty(name, 'value', placeholderValueDesc);
+ });
+
+})();
+
+ (function(){
+ var doc = document;
+ if( 'value' in document.createElement('output') ){return;}
+
+ webshims.defineNodeNameProperty('output', 'value', {
+ prop: {
+ set: function(value){
+ var setVal = $.data(this, 'outputShim');
+ if(!setVal){
+ setVal = outputCreate(this);
+ }
+ setVal(value);
+ },
+ get: function(){
+ return webshims.contentAttr(this, 'value') || $(this).text() || '';
+ }
}
+ });
+
+
+ webshims.onNodeNamesPropertyModify('input', 'value', function(value, boolVal, type){
+ if(type == 'removeAttr'){return;}
+ var setVal = $.data(this, 'outputShim');
+ if(setVal){
+ setVal(value);
+ }
+ });
+
+ var outputCreate = function(elem){
+ if(elem.getAttribute('aria-live')){return;}
+ elem = $(elem);
+ var value = (elem.text() || '').trim();
+ var id = elem.prop('id');
+ var htmlFor = elem.attr('for');
+ var shim = $('<input class="output-shim" type="text" disabled name="'+ (elem.attr('name') || '')+'" value="'+value+'" style="display: none !important;" />').insertAfter(elem);
+ var form = shim[0].form || doc;
+ var setValue = function(val){
+ shim[0].value = val;
+ val = shim[0].value;
+ elem.text(val);
+ webshims.contentAttr(elem[0], 'value', val);
+ };
- return data.remoteValidate.getTempMessage();
- }, 'remote error');
- }
-})();
+ elem[0].defaultValue = value;
+ webshims.contentAttr(elem[0], 'value', value);
+
+ elem.attr({'aria-live': 'polite'});
+ if(id){
+ shim.attr('id', id);
+ elem.attr('aria-labelledby', elem.jProp('labels').map(function(){
+ return webshims.getID(this);
+ }).get().join(' '));
+ }
+ if(htmlFor){
+ id = webshims.getID(elem);
+ htmlFor.split(' ').forEach(function(control){
+ control = document.getElementById(control);
+ if(control){
+ control.setAttribute('aria-controls', id);
+ }
+ });
+ }
+ elem.data('outputShim', setValue );
+ shim.data('outputShim', setValue );
+ return setValue;
+ };
+
+ webshims.addReady(function(context, contextElem){
+ $('output', context).add(contextElem.filter('output')).each(function(){
+ outputCreate(this);
+ });
+ });
+
+ /*
+ * Implements input event in all browsers
+ */
+ (function(){
+ var noInputTriggerEvts = {updateInput: 1, input: 1},
+ noInputTypes = {
+ radio: 1,
+ checkbox: 1,
+ submit: 1,
+ button: 1,
+ image: 1,
+ reset: 1,
+ file: 1
+
+ //pro forma
+ ,color: 1
+ //,range: 1
+ },
+ observe = function(input){
+ var timer,
+ lastVal = input.prop('value'),
+ trigger = function(e){
+ //input === null
+ if(!input){return;}
+ var newVal = input.prop('value');
+ if(newVal !== lastVal){
+ lastVal = newVal;
+ if(!e || !noInputTriggerEvts[e.type]){
+ webshims.triggerInlineForm && webshims.triggerInlineForm(input[0], 'input');
+ }
+ }
+ },
+ extraTimer,
+ extraTest = function(){
+ clearTimeout(extraTimer);
+ extraTimer = setTimeout(trigger, 9);
+ },
+ unbind = function(){
+ input.unbind('focusout', unbind).unbind('keyup keypress keydown paste cut', extraTest).unbind('input change updateInput', trigger);
+ clearInterval(timer);
+ setTimeout(function(){
+ trigger();
+ input = null;
+ }, 1);
+
+ }
+ ;
+
+ clearInterval(timer);
+ timer = setInterval(trigger, 200);
+ extraTest();
+ input.on({
+ 'keyup keypress keydown paste cut': extraTest,
+ focusout: unbind,
+ 'input updateInput change': trigger
+ });
+ }
+ ;
+
+ $(doc)
+ .on('focusin', function(e){
+ if( e.target && !e.target.readOnly && !e.target.disabled && (e.target.nodeName || '').toLowerCase() == 'input' && !noInputTypes[e.target.type] && !(webshims.data(e.target, 'implemented') || {}).inputwidgets){
+ observe($(e.target));
+ }
+ })
+ ;
+ })();
+ })();
-});
+
+});
\ No newline at end of file