vendor/assets/javascripts/webshims/shims/form-shim-extend2.js in webshims-rails-1.11.3.1 vs vendor/assets/javascripts/webshims/shims/form-shim-extend2.js in webshims-rails-1.11.6

- old
+ new

@@ -1,8 +1,11 @@ webshims.register('form-shim-extend2', function($, webshims, window, document, undefined, options){ "use strict"; var emptyJ = $([]); +var isNumber = function(string){ + return (typeof string == 'number' || (string && string == string * 1)); +}; var getGroupElements = function(elem){ elem = $(elem); var name; var form; var ret = emptyJ; @@ -81,11 +84,11 @@ } curLength = nowLen; }; var remove = function(){ clearTimeout(timer); - lastElement.unbind('.maxlengthconstraint'); + lastElement.off('.maxlengthconstraint'); }; return function(element, maxLength){ remove(); if(maxLength > -1){ max = maxLength; @@ -161,11 +164,11 @@ } } }); } -if(!$.support.getSetAttribute && $('<form novalidate></form>').attr('novalidate') == null){ +if(('getSetAttribute' in $.support) && !$.support.getSetAttribute && $('<form novalidate></form>').attr('novalidate') == null){ webshims.defineNodeNameProperty('form', 'novalidate', { attr: { set: function(val){ this.setAttribute('novalidate', ''+val); }, @@ -176,44 +179,128 @@ } }); } -if(Modernizr.formattribute === false || !Modernizr.fieldsetdisabled){ +if(!Modernizr.formattribute || !Modernizr.fieldsetdisabled || !Modernizr.fieldsetelements){ (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); + if(!Modernizr.fieldsetdisabled){ + var isFieldsetGroup = /^(?:fieldset)$/i; + $.extend($.expr[":"], { + "enabled": function( elem ) { + return elem.disabled === false || (isFieldsetGroup.test(elem.nodeName) && elem.getAttribute('disabled') == null && !$(elem).is('fieldset[disabled] *')) ; + }, + + "disabled": function( elem ) { + return elem.disabled === true || (isFieldsetGroup.test(elem.nodeName) && (elem.getAttribute('disabled') != null || $(elem).is('fieldset[disabled] *'))); + } + }); + + + var groupControl = { + getElements: function(group){ + $('input, textarea, select, button', group).each(groupControl.disable); + }, + disable: function(){ + if(!this.disabled){ + webshims.data(this, 'groupedisabled', true); + this.disabled = true; } - if(ret){ - ret = $(ret).filter(function(){ - return $.prop(this, 'form') == elem; - }).get(); - if(ret.length){ - return ret.length == 1 ? ret[0] : ret; - } + }, + enable: function(){ + if(this.disabled && webshims.data(this, 'groupedisabled')){ + webshims.data(this, 'groupedisabled', false); + this.disabled = false; } } - return prop.apply(this, arguments); }; - })($.prop, undefined); + + $(window).on('unload', function(){ + $('input, textarea, select, button').each(groupControl.enable); + }); + + webshims.defineNodeNamesBooleanProperty(['fieldset'], 'disabled', { + set: function(value){ + + if(value){ + $('input, textarea, select, button', this).each(groupControl.disable); + } else if(!$(this).is('fieldset[disabled] *')){ + var nested = $('fieldset[disabled]', this); + var elements = $('input, textarea, select, button', this); + if(nested.length){ + elements = elements.filter(':not(fieldset[disabled] *'); + } + elements.each(groupControl.enable); + } + }, + initAttr: true + }); + + ['input', 'textarea', 'select', 'button'].forEach(function(nodeName){ + var desc = webshims.defineNodeNameProperty(nodeName, 'disabled', { + prop: { + set: function(value){ + if(value){ + webshims.data(this, 'groupedisabled', false); + desc.prop._supset.call(this, value); + } else if($(this).is('fieldset[disabled] *')){ + webshims.data(this, 'groupedisabled', true); + desc.prop._supset.call(this, true); + } else { + webshims.data(this, 'groupedisabled', false); + desc.prop._supset.call(this, value); + } + }, + get: function(){ + var ret = desc.prop._supget.call(this); + return ret ? !webshims.data(this, 'groupedisabled') : ret; + } + }, + removeAttr: { + value: function(){ + desc.set.call(this, false); + } + } + }); + }); + + webshims.addReady(function(context){ + $(context).filter('fieldset[disabled], fieldset[disabled] *').each(groupControl.disable); + }); + } - var removeAddedElements = function(form){ - var elements = $.data(form, 'webshimsAddedElements'); - if(elements){ - elements.remove(); - $.removeData(form, 'webshimsAddedElements'); - } - }; - if(!Modernizr.formattribute){ + (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); + } + if(ret){ + ret = $(ret).filter(function(){ + return $.prop(this, 'form') == elem; + }).get(); + if(ret.length){ + return ret.length == 1 ? ret[0] : ret; + } + } + } + return prop.apply(this, arguments); + }; + })($.prop, undefined); + + var removeAddedElements = function(form){ + var elements = $.data(form, 'webshimsAddedElements'); + if(elements){ + elements.remove(); + $.removeData(form, 'webshimsAddedElements'); + } + }; + webshims.defineNodeNamesProperty(['input', 'textarea', 'select', 'button', 'fieldset'], 'form', { prop: { get: function(){ var form = webshims.contentAttr(this, 'form'); if(form){ @@ -306,13 +393,41 @@ }, 9); } } }); }); + + 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).is(':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(!Modernizr.fieldsetdisabled){ + if(!Modernizr.fieldsetelements){ webshims.defineNodeNamesProperty(['fieldset'], 'elements', { prop: { get: function(){ //add listed elements without keygen, object, output return $('input, select, textarea, button, fieldset', this).get() || []; @@ -320,38 +435,10 @@ 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($('<input />').prop('labels') == null){ webshims.defineNodeNamesProperty('button, input, keygen, meter, output, progress, select, textarea', 'labels', { @@ -574,10 +661,122 @@ ; }); })(); } +if(!('setSelectionRange' in document.createElement('input'))){ + (function(){ + var getSelection = function(elem, getStart){ + var range, value, normalizedValue, textInputRange, len, endRange; + var start = 0; + var end = 0; + if (document.selection && (range = document.selection.createRange()) && range.parentElement() == elem) { + value = $.prop(elem, 'value'); + len = value.length; + normalizedValue = value.replace(/\r\n/g, "\n"); + + textInputRange = elem.createTextRange(); + textInputRange.moveToBookmark(range.getBookmark()); + + + endRange = elem.createTextRange(); + endRange.collapse(false); + + if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { + start = end = len; + } else { + if(getStart){ + start = -textInputRange.moveStart("character", -len); + start += normalizedValue.slice(0, start).split("\n").length - 1; + } else { + if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { + end = len; + } else { + end = -textInputRange.moveEnd("character", -len); + end += normalizedValue.slice(0, end).split("\n").length - 1; + } + } + + } + } + return { + start: start, + end: end + }; + }; + + ['input', 'textarea'].forEach(function(name){ + var isTextarea = name == 'textarea'; + //email? + var allowedTypes = {text: 1, search: 1, url: 1, tel: 1, password: 1, email: 1}; + var error = 'InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable. selection not allowed on this type'; + webshims.defineNodeNameProperties(name, { + selectionStart: { + get: function(){ + if(isTextarea || allowedTypes[$.prop(this, 'type')]){ + return getSelection(this, true).start; + } + webshims.error(error); + }, + set: function(v){ + if(this.createTextRange && (isTextarea || allowedTypes[$.prop(this, 'type')])){ + var range = this.createTextRange(); + range.collapse(true); + range.moveStart('character', v); + range.moveEnd('character', $.prop(this, 'selectionEnd')); + if($(this).is(':focus')){ + range.select(); + } + } else { + webshims.error(error); + } + } + }, + selectionEnd: { + get: function(){ + if(isTextarea || allowedTypes[$.prop(this, 'type')]){ + return getSelection(this).end; + } + webshims.error(error); + }, + set: function(v){ + if(this.createTextRange && (isTextarea || allowedTypes[$.prop(this, 'type')])){ + var range = this.createTextRange(); + var start; + range.collapse(true); + start = getSelection(this, true).start; + range.moveStart('character', start); + range.moveEnd('character', v - start); + if($(this).is(':focus')){ + range.select(); + } + } else { + webshims.error(error); + } + } + }, + setSelectionRange: { + value: function(start, end, dir){ + if(this.createTextRange && (isTextarea || allowedTypes[$.prop(this, 'type')])){ + var range = this.createTextRange(); + range.collapse(true); + range.moveStart('character', start); + range.moveEnd('character', end - start); + if($(this).is(':focus')){ + range.select(); + } + } else { + webshims.error(error); + } + } + } + }, 'prop'); + }); + + })(); +} + (function(){ if(options.noPlaceholderPolyfill){return;} var bustedPlaceholder; Modernizr.textareaPlaceholder = !!('placeholder' in $('<textarea />')[0]); if(Modernizr.input.placeholder && options.overridePlaceholder){ @@ -610,28 +809,18 @@ } 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'); } 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; - } + $(elem).setSelectionRange(0,0); + return true; } catch(er){} }; var hidePlaceholder = function(elem, data, value, _onFocus){ if(value === false){ @@ -649,22 +838,22 @@ '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'); + $(elem).off('.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'); + $(elem).off('.placeholderremove'); } }) ; return; } else if(!_onFocus && !value && elem.value){ //especially on submit @@ -675,14 +864,14 @@ .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'); + $(elem).off('.placeholderremove'); }, 'blur.placeholderremove': function(){ - $(elem).unbind('.placeholderremove'); + $(elem).off('.placeholderremove'); } }) ; return; } @@ -706,11 +895,11 @@ var isVisible = $(elem).hasClass('placeholder-visible'); if(placeholderTxt === false){ placeholderTxt = $.attr(elem, 'placeholder') || ''; } - $(elem).unbind('.placeholderremove'); + $(elem).off('.placeholderremove'); if(value === false){ value = $.prop(elem, 'value'); } @@ -779,14 +968,14 @@ if(elem.type == 'password' || isOver){ data.text = createPlaceholder(elem); if(isResponsive || $(elem).is('.responsive-width') || (elem.currentStyle || {width: ''}).width.indexOf('%') != -1){ data.box = data.text; } else { - data.box = $(elem) - .wrap('<span class="placeholder-box placeholder-box-'+ (elem.nodeName || '').toLowerCase() +' placeholder-box-'+$.css(elem, 'float')+'" />') - .parent() + data.box = $('<span class="placeholder-box placeholder-box-'+ (elem.nodeName || '').toLowerCase() +' placeholder-box-'+$.css(elem, 'float')+'" />') + .insertAfter(elem) ; + data.box.append(elem); } data.text .insertAfter(elem) .on('mousedown.placeholder', function(){ changePlaceholderVisibility(this, false, false, data, 'focus'); @@ -1037,11 +1226,11 @@ 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 triggerinput', trigger); + input.off('focusout', unbind).off('keyup keypress keydown paste cut', extraTest).off('input change updateInput triggerinput', trigger); clearInterval(timer); setTimeout(function(){ trigger(); input = null; }, 1); @@ -1069,6 +1258,6 @@ ; })(); })(); -}); \ No newline at end of file +});