diff --git a/src/attributes.js b/src/attributes.js index 4193bbffb..a9a016eb8 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -3,10 +3,7 @@ var nodeHook, boolHook, rreturn = /\r/g, rfocusable = /^(?:input|select|textarea|button|object)$/i, rclickable = /^(?:a|area)$/i, - rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i, - ruseDefault = /^(?:checked|selected)$/i, - getSetAttribute = jQuery.support.getSetAttribute, - getSetInput = jQuery.support.input; + rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i; jQuery.fn.extend({ attr: function( name, value ) { @@ -349,22 +346,12 @@ jQuery.extend({ propName = jQuery.propFix[ name ] || name; // Boolean attributes get special treatment (#10870) + // Set corresponding property to false for boolean attributes if ( rboolean.test( name ) ) { - // Set corresponding property to false for boolean attributes - // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8 - if ( !getSetAttribute && ruseDefault.test( name ) ) { - elem[ jQuery.camelCase( "default-" + name ) ] = - elem[ propName ] = false; - } else { - elem[ propName ] = false; - } - - // See #9699 for explanation of this approach (setting first, then removal) - } else { - jQuery.attr( elem, name, "" ); + elem[ propName ] = false; } - elem.removeAttribute( getSetAttribute ? name : propName ); + elem.removeAttribute( name ); } } }, @@ -456,26 +443,7 @@ jQuery.extend({ // Hook for boolean attributes boolHook = { get: function( elem, name ) { - var - // Use .prop to determine if this attribute is understood as boolean - prop = jQuery.prop( elem, name ), - - // Fetch it accordingly - attr = typeof prop === "boolean" && elem.getAttribute( name ), - detail = typeof prop === "boolean" ? - - getSetInput && getSetAttribute ? - attr != null : - // oldIE fabricates an empty string for missing boolean attributes - // and conflates checked/selected into attroperties - ruseDefault.test( name ) ? - elem[ jQuery.camelCase( "default-" + name ) ] : - !!attr : - - // fetch an attribute node for properties not recognized as boolean - elem.getAttributeNode( name ); - - return detail && detail.value !== false ? + return elem.getAttribute( name ) !== null ? name.toLowerCase() : undefined; }, @@ -483,158 +451,13 @@ boolHook = { if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); - } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { - // IE<8 needs the *property* name - elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); - - // Use defaultChecked and defaultSelected for oldIE } else { - elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + elem.setAttribute( name, name ); } - return name; } }; -// fix oldIE value attroperty -if ( !getSetInput || !getSetAttribute ) { - jQuery.attrHooks.value = { - get: function( elem, name ) { - var ret = elem.getAttributeNode( name ); - return jQuery.nodeName( elem, "input" ) ? - - // Ignore the value *property* by using defaultValue - elem.defaultValue : - - ret && ret.specified ? ret.value : undefined; - }, - set: function( elem, value, name ) { - if ( jQuery.nodeName( elem, "input" ) ) { - // Does not return so that setAttribute is also used - elem.defaultValue = value; - } else { - // Use nodeHook if defined (#1954); otherwise setAttribute is fine - return nodeHook && nodeHook.set( elem, value, name ); - } - } - }; -} - -// IE6/7 do not support getting/setting some attributes with get/setAttribute -if ( !getSetAttribute ) { - - // Use this for any attribute in IE6/7 - // This fixes almost every IE6/7 issue - nodeHook = jQuery.valHooks.button = { - get: function( elem, name ) { - var ret = elem.getAttributeNode( name ); - return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ? - ret.value : - undefined; - }, - set: function( elem, value, name ) { - // Set the existing or create a new attribute node - var ret = elem.getAttributeNode( name ); - if ( !ret ) { - elem.setAttributeNode( - (ret = elem.ownerDocument.createAttribute( name )) - ); - } - - ret.value = value += ""; - - // Break association with cloned elements by also using setAttribute (#9646) - return name === "value" || value === elem.getAttribute( name ) ? - value : - undefined; - } - }; - - // Set contenteditable to false on removals(#10429) - // Setting to empty string throws an error as an invalid value - jQuery.attrHooks.contenteditable = { - get: nodeHook.get, - set: function( elem, value, name ) { - nodeHook.set( elem, value === "" ? false : value, name ); - } - }; - - // Set width and height to auto instead of 0 on empty string( Bug #8150 ) - // This is for removals - jQuery.each([ "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - set: function( elem, value ) { - if ( value === "" ) { - elem.setAttribute( name, "auto" ); - return value; - } - } - }); - }); -} - - -// Some attributes require a special call on IE -// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !jQuery.support.hrefNormalized ) { - jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - get: function( elem ) { - var ret = elem.getAttribute( name, 2 ); - return ret == null ? undefined : ret; - } - }); - }); - - // href/src property should get the full normalized URL (#10299/#12915) - jQuery.each([ "href", "src" ], function( i, name ) { - jQuery.propHooks[ name ] = { - get: function( elem ) { - return elem.getAttribute( name, 4 ); - } - }; - }); -} - -if ( !jQuery.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 + "" ); - } - }; -} - -// Safari mis-reports the default selected property of an option -// Accessing the parent's selectedIndex property fixes it -if ( !jQuery.support.optSelected ) { - jQuery.propHooks.selected = jQuery.extend( 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; - } - } - return null; - } - }); -} - -// IE6/7 call enctype encoding -if ( !jQuery.support.enctype ) { - jQuery.propFix.enctype = "encoding"; -} - // Radios and checkboxes getter/setter if ( !jQuery.support.checkOn ) { jQuery.each([ "radio", "checkbox" ], function() { diff --git a/src/support.js b/src/support.js index c99bb3922..5e3a7f4ba 100644 --- a/src/support.js +++ b/src/support.js @@ -5,7 +5,7 @@ jQuery.support = (function() { // Setup div.setAttribute( "className", "t" ); - div.innerHTML = "
a"; + div.innerHTML = "
a"; // Support tests won't run in some limited or non-browser environments all = div.getElementsByTagName("*"); @@ -19,7 +19,7 @@ jQuery.support = (function() { opt = select.appendChild( document.createElement("option") ); input = div.getElementsByTagName("input")[ 0 ]; - a.style.cssText = "top:1px;float:left;opacity:.5"; + a.style.cssText = "float:left;opacity:.5"; support = { // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) getSetAttribute: div.className !== "t", @@ -35,14 +35,6 @@ jQuery.support = (function() { // This requires a wrapper element in IE htmlSerialize: !!div.getElementsByTagName("link").length, - // Get the style information from getAttribute - // (IE uses .cssText instead) - style: /top/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: a.getAttribute("href") === "/a", - // Make sure that element opacity exists // (IE uses filter instead) // Use a regex to work around a WebKit issue. See #5145 @@ -55,13 +47,6 @@ jQuery.support = (function() { // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) checkOn: !!input.value, - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Tests for enctype support on a form (#6743) - enctype: !!document.createElement("form").enctype, - // Makes sure cloning an html5 element does not cause problems // Where outerHTML is undefined, this still works html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", @@ -95,11 +80,6 @@ jQuery.support = (function() { support.deleteExpando = false; } - // Check if we can trust getAttribute("value") - input = document.createElement("input"); - input.setAttribute( "value", "" ); - support.input = input.getAttribute( "value" ) === ""; - // Check if an input maintains its value after becoming a radio input.value = "t"; input.setAttribute( "type", "radio" ); diff --git a/test/unit/attributes.js b/test/unit/attributes.js index 072240049..883ba50ef 100644 --- a/test/unit/attributes.js +++ b/test/unit/attributes.js @@ -46,10 +46,6 @@ test( "jQuery.propFix integrity test", function() { "contenteditable": "contentEditable" }; - if ( !jQuery.support.enctype ) { - props.enctype = "encoding"; - } - deepEqual( props, jQuery.propFix, "jQuery.propFix passes integrity check" ); }); diff --git a/test/unit/support.js b/test/unit/support.js index 76a0af7b7..09c6ad1a5 100644 --- a/test/unit/support.js +++ b/test/unit/support.js @@ -43,324 +43,3 @@ testIframeWithCallback( "box-sizing does not affect jQuery.support.shrinkWrapBlo expect( 1 ); strictEqual( shrinkWrapBlocks, jQuery.support.shrinkWrapBlocks, "jQuery.support.shrinkWrapBlocks properties are the same" ); }); - -(function() { - var expected, - userAgent = window.navigator.userAgent; - - // These tests do not have to stay - // They are here to help with upcoming support changes for 1.8 - if ( /chrome/i.test( userAgent ) ) { - expected = { - "leadingWhitespace":true, - "tbody":true, - "htmlSerialize":true, - "style":true, - "hrefNormalized":true, - "opacity":true, - "cssFloat":true, - "checkOn":true, - "optSelected":true, - "getSetAttribute":true, - "enctype":true, - "html5Clone":true, - "submitBubbles":true, - "changeBubbles":true, - "focusinBubbles":false, - "deleteExpando":true, - "noCloneEvent":true, - "inlineBlockNeedsLayout":false, - "shrinkWrapBlocks":false, - "reliableMarginRight":true, - "noCloneChecked":true, - "optDisabled":true, - "radioValue":true, - "checkClone":true, - "appendChecked":true, - "boxModel":true, - "reliableHiddenOffsets":true, - "ajax":true, - "cors":true, - "doesNotIncludeMarginInBodyOffset":true - }; - } else if ( /opera.*version\/12\.1/i.test( userAgent ) ) { - expected = { - "leadingWhitespace":true, - "tbody":true, - "htmlSerialize":true, - "style":true, - "hrefNormalized":true, - "opacity":true, - "cssFloat":true, - "checkOn":true, - "optSelected":true, - "getSetAttribute":true, - "enctype":true, - "html5Clone":true, - "submitBubbles":true, - "changeBubbles":true, - "focusinBubbles":false, - "deleteExpando":true, - "noCloneEvent":true, - "inlineBlockNeedsLayout":false, - "shrinkWrapBlocks":false, - "reliableMarginRight":true, - "noCloneChecked":true, - "optDisabled":true, - "radioValue":false, - "checkClone":true, - "appendChecked":true, - "boxModel":true, - "reliableHiddenOffsets":true, - "ajax":true, - "cors":true, - "doesNotIncludeMarginInBodyOffset":true - }; - } else if ( /msie 10\.0/i.test( userAgent ) ) { - expected = { - "leadingWhitespace":true, - "tbody":true, - "htmlSerialize":true, - "style":true, - "hrefNormalized":true, - "opacity":true, - "cssFloat":true, - "checkOn":true, - "optSelected":false, - "getSetAttribute":true, - "enctype":true, - "html5Clone":true, - "submitBubbles":true, - "changeBubbles":true, - "focusinBubbles":true, - "deleteExpando":true, - "noCloneEvent":true, - "inlineBlockNeedsLayout":false, - "shrinkWrapBlocks":false, - "reliableMarginRight":true, - "noCloneChecked":false, - "optDisabled":true, - "radioValue":false, - "checkClone":true, - "appendChecked":true, - "boxModel":true, - "reliableHiddenOffsets":true, - "ajax":true, - "cors":true, - "doesNotIncludeMarginInBodyOffset":true - }; - } else if ( /msie 9\.0/i.test( userAgent ) ) { - expected = { - "leadingWhitespace":true, - "tbody":true, - "htmlSerialize":true, - "style":true, - "hrefNormalized":true, - "opacity":true, - "cssFloat":true, - "checkOn":true, - "optSelected":false, - "getSetAttribute":true, - "enctype":true, - "html5Clone":true, - "submitBubbles":true, - "changeBubbles":true, - "focusinBubbles":true, - "deleteExpando":true, - "noCloneEvent":true, - "inlineBlockNeedsLayout":false, - "shrinkWrapBlocks":false, - "reliableMarginRight":true, - "noCloneChecked":false, - "optDisabled":true, - "radioValue":false, - "checkClone":true, - "appendChecked":true, - "boxModel":true, - "reliableHiddenOffsets":true, - "ajax":true, - "cors":false, - "doesNotIncludeMarginInBodyOffset":true - }; - } else if ( /msie 8\.0/i.test( userAgent ) ) { - expected = { - "leadingWhitespace":false, - "tbody":true, - "htmlSerialize":false, - "style":false, - "hrefNormalized":true, - "opacity":false, - "cssFloat":false, - "checkOn":true, - "optSelected":false, - "getSetAttribute":true, - "enctype":true, - "html5Clone":false, - "submitBubbles":false, - "changeBubbles":false, - "focusinBubbles":true, - "deleteExpando":false, - "noCloneEvent":false, - "inlineBlockNeedsLayout":false, - "shrinkWrapBlocks":false, - "reliableMarginRight":true, - "noCloneChecked":false, - "optDisabled":true, - "radioValue":false, - "checkClone":true, - "appendChecked":true, - "boxModel":true, - "reliableHiddenOffsets":false, - "ajax":true, - "cors":false, - "doesNotIncludeMarginInBodyOffset":true - }; - } else if ( /msie 7\.0/i.test( userAgent ) ) { - expected = { - "ajax": true, - "appendChecked": false, - "boxModel": true, - "changeBubbles": false, - "checkClone": false, - "checkOn": true, - "cors": false, - "cssFloat": false, - "deleteExpando": false, - "doesNotIncludeMarginInBodyOffset": true, - "enctype": true, - "focusinBubbles": true, - "getSetAttribute": false, - "hrefNormalized": false, - "html5Clone": false, - "htmlSerialize": false, - "inlineBlockNeedsLayout": true, - "leadingWhitespace": false, - "noCloneChecked": false, - "noCloneEvent": false, - "opacity": false, - "optDisabled": true, - "optSelected": false, - "radioValue": false, - "reliableHiddenOffsets": false, - "reliableMarginRight": true, - "shrinkWrapBlocks": false, - "submitBubbles": false, - "tbody": false, - "style": false - }; - } else if ( /msie 6\.0/i.test( userAgent ) ) { - expected = { - "leadingWhitespace":false, - "tbody":false, - "htmlSerialize":false, - "style":false, - "hrefNormalized":false, - "opacity":false, - "cssFloat":false, - "checkOn":true, - "optSelected":false, - "getSetAttribute":false, - "enctype":true, - "html5Clone":false, - "submitBubbles":false, - "changeBubbles":false, - "focusinBubbles":true, - "deleteExpando":false, - "noCloneEvent":false, - "inlineBlockNeedsLayout":true, - "shrinkWrapBlocks":true, - "reliableMarginRight":true, - "noCloneChecked":false, - "optDisabled":true, - "radioValue":false, - "checkClone":false, - "appendChecked":false, - "boxModel":true, - "reliableHiddenOffsets":false, - "ajax":true, - "cors":false, - "doesNotIncludeMarginInBodyOffset":true - }; - } else if ( /5\.1\.1 safari/i.test( userAgent ) ) { - expected = { - "leadingWhitespace":true, - "tbody":true, - "htmlSerialize":true, - "style":true, - "hrefNormalized":true, - "opacity":true, - "cssFloat":true, - "checkOn":false, - "optSelected":true, - "getSetAttribute":true, - "enctype":true, - "html5Clone":true, - "submitBubbles":true, - "changeBubbles":true, - "focusinBubbles":false, - "deleteExpando":true, - "noCloneEvent":true, - "inlineBlockNeedsLayout":false, - "shrinkWrapBlocks":false, - "reliableMarginRight":true, - "noCloneChecked":true, - "optDisabled":true, - "radioValue":true, - "checkClone":false, - "appendChecked":false, - "boxModel":true, - "reliableHiddenOffsets":true, - "ajax":true, - "cors":true, - "doesNotIncludeMarginInBodyOffset":true - }; - } else if ( /firefox/i.test( userAgent ) ) { - expected = { - "leadingWhitespace":true, - "tbody":true, - "htmlSerialize":true, - "style":true, - "hrefNormalized":true, - "opacity":true, - "cssFloat":true, - "checkOn":true, - "optSelected":true, - "getSetAttribute":true, - "enctype":true, - "html5Clone":true, - "submitBubbles":true, - "changeBubbles":true, - "focusinBubbles":false, - "deleteExpando":true, - "noCloneEvent":true, - "inlineBlockNeedsLayout":false, - "shrinkWrapBlocks":false, - "reliableMarginRight":true, - "noCloneChecked":true, - "optDisabled":true, - "radioValue":true, - "checkClone":true, - "appendChecked":true, - "boxModel":true, - "reliableHiddenOffsets":true, - "ajax":true, - "cors":true, - "doesNotIncludeMarginInBodyOffset":true - }; - } - - if ( expected ) { - test("Verify that the support tests resolve as expected per browser", function() { - expect( 30 ); - - for ( var i in expected ) { - if ( jQuery.ajax || i !== "ajax" && i !== "cors" ) { - equal( jQuery.support[i], expected[i], "jQuery.support['" + i + "']: " + jQuery.support[i] + ", expected['" + i + "']: " + expected[i]); - } else { - ok( true, "no ajax; skipping jQuery.support['" + i + "']" ); - } - } - }); - } - -})();