From d0388e9e806ca3b30e7bbaaa1c336b7c98dc5f88 Mon Sep 17 00:00:00 2001 From: Gilad Peleg Date: Tue, 23 Jun 2015 07:01:06 +0300 Subject: [PATCH] Core: organize prop & attr code to be similar Ref 5153b5334eb2c8317372b46209bd9d092a91afdc Closes gh-2426 --- src/attributes/attr.js | 156 +++++++++++++---------------------------- src/attributes/prop.js | 79 ++++++++------------- 2 files changed, 81 insertions(+), 154 deletions(-) diff --git a/src/attributes/attr.js b/src/attributes/attr.js index da0ae24d9..07576738a 100644 --- a/src/attributes/attr.js +++ b/src/attributes/attr.js @@ -1,16 +1,13 @@ define([ "../core", - "../var/rnotwhite", "../core/access", "./support", - "./val", + "../var/rnotwhite", "../selector" -], function( jQuery, rnotwhite, access, support ) { +], function( jQuery, access, support, rnotwhite ) { var boolHook, - attrHandle = jQuery.expr.attrHandle, - ruseDefault = /^(?:checked|selected)$/i, - getSetInput = support.input; + attrHandle = jQuery.expr.attrHandle; jQuery.fn.extend({ attr: function( name, value ) { @@ -26,10 +23,10 @@ jQuery.fn.extend({ jQuery.extend({ attr: function( elem, name, value ) { - var hooks, ret, + var ret, hooks, nType = elem.nodeType; - // don't get/set attributes on text, comment and attribute nodes + // Don't get/set attributes on text, comment and attribute nodes if ( nType === 3 || nType === 8 || nType === 2 ) { return; } @@ -48,30 +45,43 @@ jQuery.extend({ } if ( value !== undefined ) { - if ( value === null ) { jQuery.removeAttr( elem, name ); + return; + } - } else if ( hooks && "set" in hooks && - (ret = hooks.set( elem, value, name )) !== undefined ) { - + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { return ret; - - } else { - elem.setAttribute( name, value + "" ); - return value; } - } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { return ret; + } - } else { - ret = jQuery.find.attr( elem, name ); + ret = jQuery.find.attr( elem, name ); - // Non-existent attributes return null, we normalize to undefined - return ret == null ? - undefined : - ret; + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + jQuery.nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } } }, @@ -81,116 +91,50 @@ jQuery.extend({ attrNames = value && value.match( rnotwhite ); if ( attrNames && elem.nodeType === 1 ) { - while ( (name = attrNames[i++]) ) { + while ( ( name = attrNames[i++] ) ) { propName = jQuery.propFix[ name ] || name; // Boolean attributes get special treatment (#10870) if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false - if ( getSetInput || !ruseDefault.test( name ) ) { - elem[ propName ] = false; - // Support: IE<9 - // Also clear defaultChecked/defaultSelected (if appropriate) - } else { - elem[ jQuery.camelCase( "default-" + name ) ] = - elem[ propName ] = false; - } + elem[ propName ] = false; } elem.removeAttribute( name ); } } - }, - - attrHooks: { - type: { - set: function( elem, value ) { - if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { - // Setting the type on a radio button after the value resets the value in IE8-9 - // Reset value to default in case type is set after value during creation - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - } } }); -// Hook for boolean attributes +// Hooks for boolean attributes boolHook = { set: function( elem, value, name ) { if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); - } else if ( getSetInput || !ruseDefault.test( name ) ) { - elem.setAttribute( jQuery.propFix[ name ] || name, name ); - } else { - // Support: IE<9 - // Use defaultChecked and defaultSelected for oldIE - elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + elem.setAttribute( name, name ); } - return name; } }; - -// Retrieve booleans specially jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { - var getter = attrHandle[ name ] || jQuery.find.attr; - attrHandle[ name ] = getSetInput || !ruseDefault.test( name ) ? - function( elem, name, isXML ) { - var ret, handle; - if ( !isXML ) { - // Avoid an infinite loop by temporarily removing this function from the getter - handle = attrHandle[ name ]; - attrHandle[ name ] = ret; - ret = getter( elem, name, isXML ) != null ? - name.toLowerCase() : - null; - attrHandle[ name ] = handle; - } - return ret; - } : - function( elem, name, isXML ) { - if ( !isXML ) { - return elem[ jQuery.camelCase( "default-" + name ) ] ? - name.toLowerCase() : - null; - } - }; -}); - -// fix oldIE attroperties -if ( !getSetInput ) { - jQuery.attrHooks.value = { - set: function( elem, value ) { - if ( jQuery.nodeName( elem, "input" ) ) { - // Does not return so that setAttribute is also used - elem.defaultValue = value; - } + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle; + if ( !isXML ) { + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ name ]; + attrHandle[ name ] = ret; + ret = getter( elem, name, isXML ) != null ? + name.toLowerCase() : + null; + attrHandle[ name ] = handle; } + return ret; }; -} - -if ( !support.style ) { - jQuery.attrHooks.style = { - get: function( elem ) { - // Return undefined in the case of empty string - // Note: IE uppercases css property names, but if we were to .toLowerCase() - // .cssText, that would destroy case senstitivity in URL's, like in "background" - return elem.style.cssText || undefined; - }, - set: function( elem, value ) { - return ( elem.style.cssText = value + "" ); - } - }; -} +}); }); diff --git a/src/attributes/prop.js b/src/attributes/prop.js index 991e509c2..4c7b51e8c 100644 --- a/src/attributes/prop.js +++ b/src/attributes/prop.js @@ -1,11 +1,11 @@ define([ "../core", "../core/access", - "./support" + "./support", + "../selector" ], function( jQuery, access, support ) { -var rfocusable = /^(?:input|select|textarea|button|object)$/i, - rclickable = /^(?:a|area)$/i; +var rfocusable = /^(?:input|select|textarea|button)$/i; jQuery.fn.extend({ prop: function( name, value ) { @@ -13,70 +13,59 @@ jQuery.fn.extend({ }, removeProp: function( name ) { - name = jQuery.propFix[ name ] || name; return this.each(function() { - // try/catch handles cases where IE balks (such as removing a property on window) - try { - this[ name ] = undefined; - delete this[ name ]; - } catch ( e ) {} + delete this[ jQuery.propFix[ name ] || name ]; }); } }); jQuery.extend({ - propFix: { - "for": "htmlFor", - "class": "className" - }, - prop: function( elem, name, value ) { - var ret, hooks, notxml, + var ret, hooks, nType = elem.nodeType; - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { return; } - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - if ( notxml ) { // Fix name and attach hooks name = jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; } if ( value !== undefined ) { - return hooks && "set" in hooks && - (ret = hooks.set( elem, value, name )) !== undefined ? - ret : - ( elem[ name ] = value ); - - } else { - return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? - ret : - elem[ name ]; + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; } + + return elem[ name ]; }, propHooks: { tabIndex: { get: function( elem ) { - // elem.tabIndex doesn't always return the - // correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - // Use proper attribute retrieval(#12072) - var tabindex = jQuery.find.attr( elem, "tabindex" ); - - return tabindex ? - parseInt( tabindex, 10 ) : - rfocusable.test( elem.nodeName ) || - rclickable.test( elem.nodeName ) && elem.href ? - 0 : - -1; + return elem.hasAttribute( "tabindex" ) || + rfocusable.test( elem.nodeName ) || elem.href ? + elem.tabIndex : + -1; } } + }, + + propFix: { + "for": "htmlFor", + "class": "className" } }); @@ -84,14 +73,8 @@ if ( !support.optSelected ) { jQuery.propHooks.selected = { get: function( elem ) { var parent = elem.parentNode; - - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; } return null; } -- 2.39.5