Skip to content
Permalink
Browse files

Remove the invisible body in support; Add temporary tests to verify c…

…orrect support completions for upcoming support changes.
  • Loading branch information...
timmywil committed Nov 17, 2011
1 parent 0de484d commit 3d6237ef8aff8a31ace3e956e2700aa11e3da752
Showing with 331 additions and 103 deletions.
  1. +65 −101 src/support.js
  2. +1 −1 test/data/support/boxModelIE.html
  3. +1 −1 test/index.html
  4. +264 −0 test/unit/support.js
@@ -2,31 +2,26 @@

jQuery.support = (function() {

var div = document.createElement( "div" ),
documentElement = document.documentElement,
var support,
all,
a,
select,
opt,
input,
marginDiv,
support,
fragment,
body,

This comment has been minimized.

Copy link
@mikesherov

mikesherov Nov 18, 2011

Member

body leaks to global now, right? I found this with JSHint, btw. ;-)

testElementParent,
testElement,
testElementStyle,
tds,
events,
eventName,
i,
isSupported;
isSupported,
div = document.createElement( "div" ),
documentElement = document.documentElement;

// Preliminary tests
div.setAttribute("className", "t");
div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";


all = div.getElementsByTagName( "*" );
a = div.getElementsByTagName( "a" )[ 0 ];

@@ -46,19 +41,19 @@ jQuery.support = (function() {

// Make sure that tbody elements aren't automatically inserted
// IE will insert them into empty tables
tbody: !div.getElementsByTagName( "tbody" ).length,
tbody: !div.getElementsByTagName("tbody").length,

// Make sure that link elements get serialized correctly by innerHTML
// This requires a wrapper element in IE
htmlSerialize: !!div.getElementsByTagName( "link" ).length,
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" ),
hrefNormalized: ( a.getAttribute("href") === "/a" ),

// Make sure that element opacity exists
// (IE uses filter instead)
@@ -140,95 +135,28 @@ jQuery.support = (function() {
// WebKit doesn't clone checked state correctly in fragments
support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;

div.innerHTML = "";

// Figure out if the W3C box model works as expected
div.style.width = div.style.paddingLeft = "1px";

// We don't want to do body-related feature tests on frameset
// documents, which lack a body. So we use
// document.getElementsByTagName("body")[0], which is undefined in
// frameset documents, while document.body isn’t. (7398)
body = document.getElementsByTagName("body")[ 0 ];
// We use our own, invisible, body unless the body is already present
// in which case we use a div (#9239)
testElement = document.createElement( body ? "div" : "body" );
testElementStyle = {
visibility: "hidden",
width: 0,
height: 0,
border: 0,
margin: 0,
background: "none"
};
if ( body ) {
jQuery.extend( testElementStyle, {
position: "absolute",
left: "-999px",
top: "-999px"
});
}
for ( i in testElementStyle ) {
testElement.style[ i ] = testElementStyle[ i ];
}
testElement.appendChild( div );
testElementParent = body || documentElement;
testElementParent.insertBefore( testElement, testElementParent.firstChild );

// Check if a disconnected checkbox will retain its checked
// value of true after appended to the DOM (IE6/7)
support.appendChecked = input.checked;

support.boxModel = div.offsetWidth === 2;

if ( "zoom" in div.style ) {
// Check if natively block-level elements act like inline-block
// elements when setting their display to 'inline' and giving
// them layout
// (IE < 8 does this)
div.style.display = "inline";
div.style.zoom = 1;
support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );

// Check if elements with layout shrink-wrap their children
// (IE 6 does this)
div.style.display = "";
div.innerHTML = "<div style='width:4px;'></div>";
support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
}

div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
tds = div.getElementsByTagName( "td" );

// Check if table cells still have offsetWidth/Height when they are set
// to display:none and there are still other visible table cells in a
// table row; if so, offsetWidth/Height are not reliable for use when
// determining if an element has been hidden directly using
// display:none (it is still safe to use offsets if a parent element is
// hidden; don safety goggles and see bug #4512 for more information).
// (only IE 8 fails this test)
isSupported = ( tds[ 0 ].offsetHeight === 0 );

tds[ 0 ].style.display = "";
tds[ 1 ].style.display = "none";
fragment.removeChild( input );
fragment.appendChild( div );

// Check if empty table cells still have offsetWidth/Height
// (IE < 8 fail this test)
support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
div.innerHTML = "";

// Check if div with explicit width and no margin-right incorrectly
// gets computed margin-right based on width of container. For more
// info see bug #3333
// Fails in WebKit before Feb 2011 nightlies
// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
if ( document.defaultView && document.defaultView.getComputedStyle ) {
if ( window.getComputedStyle ) {
marginDiv = document.createElement( "div" );
marginDiv.style.width = "0";
marginDiv.style.marginRight = "0";
div.style.width = "2px";
div.appendChild( marginDiv );
support.reliableMarginRight =
( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;

This comment has been minimized.

Copy link
@mikesherov

mikesherov Nov 17, 2011

Member

excuse my ignorance, but doesn't FF3.6 need document.defaultView so IFRAME's will be happy? #524 (comment)

This comment has been minimized.

Copy link
@timmywil

timmywil Nov 18, 2011

Author Member

It is needed in css.js, not in the support test.

This comment has been minimized.

Copy link
@rwaldron

rwaldron Nov 18, 2011

Member

What if jQuery is loaded in an iframe that has display:none in Firefox 3.6? (I'm curious, I haven't tested this)

This comment has been minimized.

Copy link
@mikesherov

mikesherov Nov 18, 2011

Member

funny you should ask, @rwldrn, I have a PR for this sitting in the queue: #555

This comment has been minimized.

Copy link
@jdalton

jdalton Nov 18, 2011

Member

Ok, so this is kinda an interesting issue. Would ❤️ a blog post on it.

This comment has been minimized.

Copy link
@timmywil

timmywil Nov 18, 2011

Author Member

@rwldrn: Just tested and looks like it has the correct result.

}

// Technique from Juriy Zaytsev
@@ -242,7 +170,7 @@ jQuery.support = (function() {
submit: 1,
change: 1,
focusin: 1
} ) {
}) {
eventName = "on" + i;
isSupported = ( eventName in div );
if ( !isSupported ) {
@@ -253,11 +181,10 @@ jQuery.support = (function() {
}
}

testElement.innerHTML = "";
testElementParent.removeChild( testElement );
fragment.removeChild( div );

// Null connected elements to avoid leaks in IE
testElement = fragment = select = opt = body = marginDiv = div = input = null;
// Null elements to avoid leaks in IE
fragment = select = opt = body = marginDiv = div = input = null;

This comment has been minimized.

Copy link
@mikesherov

mikesherov Nov 18, 2011

Member

body is not defined before this.


// Run fixed position tests at doc ready to avoid a crash
// related to the invisible body in IE8
@@ -268,8 +195,8 @@ jQuery.support = (function() {
vb = "visibility:hidden;border:0;",
style = "style='" + ptlm + "border:5px solid #000;padding:0;'",
html = "<div " + style + "><div></div></div>" +
"<table " + style + " cellpadding='0' cellspacing='0'>" +
"<tr><td></td></tr></table>";
"<table " + style + " cellpadding='0' cellspacing='0'>" +
"<tr><td></td></tr></table>";

// Reconstruct a container
body = document.getElementsByTagName("body")[0];
@@ -283,13 +210,53 @@ jQuery.support = (function() {
container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
body.insertBefore( container, body.firstChild );

// Construct a test element
testElement = document.createElement("div");
testElement.style.cssText = ptlm + vb;
// Construct the test element
div = document.createElement("div");
container.appendChild( div );

// Check if table cells still have offsetWidth/Height when they are set
// to display:none and there are still other visible table cells in a
// table row; if so, offsetWidth/Height are not reliable for use when
// determining if an element has been hidden directly using
// display:none (it is still safe to use offsets if a parent element is
// hidden; don safety goggles and see bug #4512 for more information).
// (only IE 8 fails this test)
div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
tds = div.getElementsByTagName( "td" );
isSupported = ( tds[ 0 ].offsetHeight === 0 );

tds[ 0 ].style.display = "";
tds[ 1 ].style.display = "none";

// Check if empty table cells still have offsetWidth/Height
// (IE <= 8 fail this test)
support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );

// Figure out if the W3C box model works as expected
div.innerHTML = "";
div.style.width = div.style.paddingLeft = "1px";
jQuery.boxModel = support.boxModel = div.offsetWidth === 2;

if ( typeof div.style.zoom !== "undefined" ) {
// Check if natively block-level elements act like inline-block
// elements when setting their display to 'inline' and giving
// them layout
// (IE < 8 does this)
div.style.display = "inline";
div.style.zoom = 1;
support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );

// Check if elements with layout shrink-wrap their children
// (IE 6 does this)
div.style.display = "";
div.innerHTML = "<div style='width:4px;'></div>";
support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
}

div.style.cssText = ptlm + vb;
div.innerHTML = html;

testElement.innerHTML = html;
container.appendChild( testElement );
outer = testElement.firstChild;
outer = div.firstChild;
inner = outer.firstChild;
td = outer.nextSibling.firstChild.firstChild;

@@ -312,15 +279,12 @@ jQuery.support = (function() {
offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );

body.removeChild( container );
testElement = container = null;
div = container = null;

jQuery.extend( support, offsetSupport );
});

return support;
})();

// Keep track of boxModel
jQuery.boxModel = jQuery.support.boxModel;

})( jQuery );
@@ -22,7 +22,7 @@
<script src="../../../src/offset.js"></script>
<script src="../../../src/dimensions.js"></script>
<script>
window.parent.supportCallback( document.compatMode, jQuery.support.boxModel );
jQuery(function() { window.parent.supportCallback( document.compatMode, jQuery.support.boxModel ) });
</script>
</body>
</html>
@@ -36,9 +36,9 @@
<script src="data/testrunner.js"></script>

<script src="unit/core.js"></script>
<script src="unit/support.js"></script>
<script src="unit/callbacks.js"></script>
<script src="unit/deferred.js"></script>
<script src="unit/support.js"></script>
<script src="unit/data.js"></script>
<script src="unit/queue.js"></script>
<script src="unit/attributes.js"></script>

18 comments on commit 3d6237e

@rwaldron

This comment has been minimized.

Copy link
Member

replied Nov 18, 2011

These tests are great.

@rwaldron

This comment has been minimized.

Copy link
Member

replied Nov 18, 2011

One thing... really inconsistent with space around foo("here") vs foo( "here" )...

@timmywil

This comment has been minimized.

Copy link
Member Author

replied Nov 18, 2011

True, that is inconsistent. I should fix that.

But...since we're discussing it, I prefer foo("here") to foo( "here" ). Double quotes provide a visible space by themselves don't you think?

@rwaldron

This comment has been minimized.

Copy link
Member

replied Nov 18, 2011

@timmywil As it turns out, I do agree. My nit wasn't that it should be padded, but just that you're all over the damn place ;)

I think I'm going to open a ticket to officially change the style guide to reflect this, what do you think? I'll deal with the grunt work myself.

@rdworth

This comment has been minimized.

Copy link
Contributor

replied Nov 18, 2011

@rwldrn your proposed change seems like a real source for even worse inconsistency. Imagine
foo("here", 4 )
or
foo( 4, "here")
Yuck.

@rwaldron

This comment has been minimized.

Copy link
Member

replied Nov 18, 2011

@rdworth tough one, part of me thinks that's not too bad and pretty damn readable.

@rdworth

This comment has been minimized.

Copy link
Contributor

replied Nov 18, 2011

My cry is not "it's not readable because of lack of horizontal space" it's "that's an ugly inconsistency that adds complexity to something that should be as simple as possible (and already isn't)". My 2c

@rwaldron

This comment has been minimized.

Copy link
Member

replied Nov 18, 2011

@rdworth hahaha, ok! stop yelling at me.. geez... ;)

@rwaldron

This comment has been minimized.

Copy link
Member

replied Nov 18, 2011

@timmywil Can you update the whitespace in accordance with style guide - thanks dude :)

@timmywil

This comment has been minimized.

Copy link
Member Author

replied Nov 18, 2011

haha, and it's over that quick? @rdworth: we already have an answer to that. If either one or both of the parenthesis do not have quotes next to them, insert an extra space next to the quote. So what I propose would still be:

foo( "here", 4 );
foo( 4, "here" );
foo("here");
@rdworth

This comment has been minimized.

Copy link
Contributor

replied Nov 18, 2011

Oh, if it's single arg only, I won't lose sleep. Sorry for the noise.

@rwaldron

This comment has been minimized.

Copy link
Member

replied Nov 18, 2011

Yes, that is nice. Thanks for the follow through haha.

@eddiemonge

This comment has been minimized.

Copy link
Contributor

replied Nov 18, 2011

How is foo(4) handled? is it like that or foo( 4 )? If its the second, then seems like it should always be spaced wrapped in parens

@timmywil

This comment has been minimized.

Copy link
Member Author

replied Nov 18, 2011

Everything else is the same, so foo( 4 ). Quotes on both sides of the parens is the only exception.

@mikesherov

This comment has been minimized.

Copy link
Member

replied Nov 18, 2011

@rdworth

This comment has been minimized.

Copy link
Contributor

replied Nov 18, 2011

Quotes on both sides of the parens is the only exception.

Other than curly braces and square brackets which are the current exceptions it is proposed quotes be added to ;)

@eddiemonge

This comment has been minimized.

Copy link
Contributor

replied Nov 18, 2011

So many inconsistencies. I say its spaces next to the parens always, and maybe braces and brackets should be added to that.

@rwaldron

This comment has been minimized.

Copy link
Member

replied Nov 18, 2011

Other style guide changes are not up for discussion. Thanks to everyone, please consider the thread closed

Please sign in to comment.
You can’t perform that action at this time.