vendor/assets/javascripts/webshims/shims/form-shim-extend.js in webshims-rails-0.4.7 vs vendor/assets/javascripts/webshims/shims/form-shim-extend.js in webshims-rails-1.10.3

- old
+ new

@@ -322,12 +322,12 @@ validityState = $.extend({}, validityPrototype); if( !$.prop(elem, 'willValidate') || elem.type == 'submit' ){ return validityState; } - var val = jElm.val(), - cache = {nodeName: elem.nodeName.toLowerCase()} + var val = jElm.val(), + cache = {nodeName: elem.nodeName.toLowerCase()} ; validityState.customError = !!(webshims.data(elem, 'customvalidationMessage')); if( validityState.customError ){ validityState.valid = false; @@ -349,11 +349,11 @@ webshims.defineNodeNamesBooleanProperty(['input', 'textarea', 'select'], 'required', { set: function(value){ $(this).getShadowFocusElement().attr('aria-required', !!(value)+''); }, - initAttr: (Modernizr.localstorage)//only if we have aria-support + initAttr: Modernizr.localstorage //only if we have aria-support }); webshims.reflectProperties(['input'], ['pattern']); @@ -670,11 +670,12 @@ (function(){ var noInputTriggerEvts = {updateInput: 1, input: 1}, fixInputTypes = { date: 1, - time: 1 + time: 1, + "datetime-local": 1 }, noFocusEvents = { focusout: 1, blur: 1 }, @@ -878,14 +879,12 @@ if(elements){ elements.remove(); $.removeData(form, 'webshimsAddedElements'); } }; - 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; + if(!Modernizr.formattribute){ webshims.defineNodeNamesProperty(['input', 'textarea', 'select', 'button', 'fieldset'], 'form', { prop: { get: function(){ var form = webshims.contentAttr(this, 'form'); @@ -988,40 +987,188 @@ writeable: false } }); } - $.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(); + 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(); + }; + } - 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($('<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 + } + }); + } + + if(!('value' in document.createElement('progress'))){ + (function(){ + + var nan = parseInt('NaN', 10); + + 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){ + delete this.value; + } + 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 + ); + + })(); + } + try { document.querySelector(':checked'); } catch(er){ (function(){ + $('html').addClass('no-csschecked'); var checkInputs = { radio: 1, checkbox: 1 }; var selectChange = function(){ @@ -1123,10 +1270,11 @@ var hidePlaceholder = function(elem, data, value, _onFocus){ if(value === false){ value = $.prop(elem, 'value'); } + if(!isOver && elem.type != 'password'){ if(!value && _onFocus && setSelection(elem)){ var selectTimer = setTimeout(function(){ setSelection(elem); }, 9); @@ -1152,12 +1300,13 @@ $(elem).unbind('.placeholderremove'); } }) ; return; + } else if(!_onFocus && !value && elem.value){ //especially on submit + elem.value = value; } - elem.value = value; } else if(!value && _onFocus){ $(elem) .off('.placeholderremove') .on({ 'keydown.placeholderremove keypress.placeholderremove paste.placeholderremove input.placeholderremove': function(e){ @@ -1188,19 +1337,22 @@ if(!data){ data = $.data(elem, 'placeHolder'); if(!data){return;} } $(elem).unbind('.placeholderremove'); - if(type == 'focus' || (!type && $(elem).is(':focus'))){ + + if(value === false){ + value = $.prop(elem, 'value'); + } + + if(!value && (type == 'focus' || (!type && $(elem).is(':focus')))){ if(elem.type == 'password' || isOver || $(elem).hasClass('placeholder-visible')){ hidePlaceholder(elem, data, '', true); } return; } - if(value === false){ - value = $.prop(elem, 'value'); - } + if(value){ hidePlaceholder(elem, data, value); return; } if(placeholderTxt === false){ @@ -1210,25 +1362,17 @@ showPlaceholder(elem, data, placeholderTxt); } else { hidePlaceholder(elem, data, value); } }, + 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); - var id = elem.prop('id'), - hasLabel = !!(elem.prop('title') || elem.attr('aria-labelledby')) - ; - if(!hasLabel && id){ - hasLabel = !!( $('label[for="'+ id +'"]', elem[0].form)[0] ); - } - if(!hasLabel){ - if(!id){ - id = $.webshims.getID(elem); - } - hasLabel = !!($('label #'+ id)[0]); - } - return $( hasLabel ? '<span class="placeholder-text"></span>' : '<label for="'+ id +'" class="placeholder-text"></label>'); + 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, @@ -1239,10 +1383,14 @@ tel: 1, number: 1 } ; + if(webshims.modules["form-number-date-ui"].loaded){ + delete allowedPlaceholder.number; + } + return { create: function(elem){ var data = $.data(elem, 'placeHolder'); var form; var responsiveElem; @@ -1337,14 +1485,11 @@ return data; }, update: function(elem, val){ var type = ($.attr(elem, 'type') || $.prop(elem, 'type') || '').toLowerCase(); if(!allowedPlaceholder[type] && !$.nodeName(elem, 'textarea')){ - webshims.error('placeholder not allowed on input[type="'+type+'"]'); - if(type == 'date'){ - webshims.error('but you can use data-placeholder for input[type="date"]'); - } + webshims.warn('placeholder not allowed on input[type="'+type+'"], but it is a good fallback :-)'); return; } var data = pHolder.create(elem); @@ -1384,13 +1529,15 @@ var desc; ['attr', 'prop'].forEach(function(propType){ placeholderValueDesc[propType] = { set: function(val){ var elem = this; - var placeholder = webshims.contentAttr(elem, 'placeholder'); - + var placeholder; + 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); } @@ -1437,11 +1584,11 @@ var outputCreate = function(elem){ if(elem.getAttribute('aria-live')){return;} elem = $(elem); var value = (elem.text() || '').trim(); - var id = elem.attr('id'); + 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; @@ -1454,11 +1601,13 @@ webshims.contentAttr(elem[0], 'value', value); elem.attr({'aria-live': 'polite'}); if(id){ shim.attr('id', id); - elem.attr('aria-labelledby', webshims.getID($('label[for="'+id+'"]', form))); + 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); @@ -1501,11 +1650,10 @@ 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'); } @@ -1526,11 +1674,11 @@ } ; clearInterval(timer); - timer = setInterval(trigger, 99); + timer = setInterval(trigger, 200); extraTest(); input.on({ 'keyup keypress keydown paste cut': extraTest, focusout: unbind, 'input updateInput change': trigger @@ -1541,10 +1689,10 @@ $.event.customEvent.updateInput = true; } $(doc) .on('focusin', function(e){ - if( e.target && e.target.type && !e.target.readOnly && !e.target.disabled && (e.target.nodeName || '').toLowerCase() == 'input' && !noInputTypes[e.target.type] ){ + 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)); } }) ; })();