diff options
author | Richard Gibson <richard.gibson@gmail.com> | 2012-12-08 18:04:13 -0500 |
---|---|---|
committer | Richard Gibson <richard.gibson@gmail.com> | 2012-12-08 18:04:13 -0500 |
commit | d343e6b9ed501052f1676694d5e53649c92e65a0 (patch) | |
tree | 50879e4c04e34f7c51e2aa21958203242808b006 | |
parent | 23d7cf0488bfeaab51d8f55435cab01f5cf990ca (diff) | |
download | jquery-d343e6b9ed501052f1676694d5e53649c92e65a0.tar.gz jquery-d343e6b9ed501052f1676694d5e53649c92e65a0.zip |
Fix #12904: Firefox defaultDisplay with body/iframe display:none. Report and solution by @maranomynet; test by @rwldrn.
-rw-r--r-- | src/css.js | 64 | ||||
-rw-r--r-- | test/unit/css.js | 48 |
2 files changed, 60 insertions, 52 deletions
diff --git a/src/css.js b/src/css.js index 334e31a92..c9a1ab433 100644 --- a/src/css.js +++ b/src/css.js @@ -1,4 +1,4 @@ -var curCSS, iframe, iframeDoc, +var curCSS, iframe, ralpha = /alpha\([^)]*\)/i, ropacity = /opacity\s*=\s*([^)]*)/, rposition = /^(top|right|bottom|left)$/, @@ -446,44 +446,38 @@ function getWidthOrHeight( elem, name, extra ) { // Try to determine the default display value of an element function css_defaultDisplay( nodeName ) { - if ( elemdisplay[ nodeName ] ) { - return elemdisplay[ nodeName ]; - } - - var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ), - display = elem.css("display"); - elem.remove(); - - // If the simple way fails, - // get element's real default display by attaching it to a temp iframe - if ( display === "none" || display === "" ) { - // Use the already-created iframe if possible - iframe = document.body.appendChild( - iframe || jQuery.extend( document.createElement("iframe"), { - frameBorder: 0, - width: 0, - height: 0 - }) - ); - - // Create a cacheable copy of the iframe document on first call. - // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML - // document to it; WebKit & Firefox won't allow reusing the iframe document. - if ( !iframeDoc || !iframe.createElement ) { - iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document; - iframeDoc.write("<!doctype html><html><body>"); - iframeDoc.close(); + var elem, + doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + elem = jQuery( doc.createElement( nodeName ) ); + display = curCSS( elem.appendTo( doc.body )[0], "display" ); + elem.remove(); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery("<iframe frameborder='0' width='0' height='0'/>") + .css( "cssText", "display:block !important" ) + ).appendTo( doc.documentElement ); + + // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse + doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document; + doc.write("<!doctype html><html><body>"); + doc.close(); + + elem = jQuery( doc.createElement( nodeName ) ); + display = curCSS( elem.appendTo( doc.body )[0], "display" ); + elem.remove(); + iframe.detach(); } - elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) ); - - display = curCSS( elem, "display" ); - document.body.removeChild( iframe ); + // Store the correct default display + elemdisplay[ nodeName ] = display; } - // Store the correct default display - elemdisplay[ nodeName ] = display; - return display; } diff --git a/test/unit/css.js b/test/unit/css.js index 94d972793..c90011687 100644 --- a/test/unit/css.js +++ b/test/unit/css.js @@ -574,19 +574,33 @@ test( "show() resolves correct default display for detached nodes", function(){ test("show() resolves correct default display #10227", function() { expect(2); - jQuery("html").append( + var body = jQuery("body"); + body.append( "<p id='ddisplay'>a<style>body{display:none}</style></p>" ); - equal( jQuery("body").css("display"), "none", "Initial display: none" ); + equal( body.css("display"), "none", "Initial display: none" ); - jQuery("body").show(); - - equal( jQuery("body").css("display"), "block", "Correct display: block" ); + body.show(); + equal( body.css("display"), "block", "Correct display: block" ); jQuery("#ddisplay").remove(); + QUnit.expectJqData( body[0], "olddisplay" ); +}); + +test("show() resolves correct default display when iframe display:none #12904", function() { + expect(2); + + var ddisplay = jQuery( + "<p id='ddisplay'>a<style>p{display:none}iframe{display:none !important}</style></p>" + ).appendTo("body"); + + equal( ddisplay.css("display"), "none", "Initial display: none" ); + + ddisplay.show(); + equal( ddisplay.css("display"), "block", "Correct display: block" ); - jQuery.cache = {}; + ddisplay.remove(); }); test("toggle()", function() { @@ -871,17 +885,17 @@ test( "cssHooks - expand", function() { test( "css opacity consistency across browsers (#12685)", function() { expect( 4 ); - var fixture = jQuery("#qunit-fixture"), - style = jQuery("<style>.opacityWithSpaces_t12685 { opacity: 0.1; filter: alpha(opacity = 10); } .opacityNoSpaces_t12685 { opacity: 0.2; filter: alpha(opacity=20); }</style>").appendTo(fixture), - el = jQuery("<div class='opacityWithSpaces_t12685'></div>").appendTo(fixture); - - equal( Math.round( el.css("opacity") * 100 ), 10, "opacity from style sheet (filter:alpha with spaces)" ); - el.removeClass("opacityWithSpaces_t12685").addClass("opacityNoSpaces_t12685"); - equal( Math.round( el.css("opacity") * 100 ), 20, "opacity from style sheet (filter:alpha without spaces)" ); - el.css( "opacity", 0.3 ); - equal( Math.round( el.css("opacity") * 100 ), 30, "override opacity" ); - el.css( "opacity", "" ); - equal( Math.round( el.css("opacity") * 100 ), 20, "remove opacity override" ); + var fixture = jQuery("#qunit-fixture"), + style = jQuery("<style>.opacityWithSpaces_t12685 { opacity: 0.1; filter: alpha(opacity = 10); } .opacityNoSpaces_t12685 { opacity: 0.2; filter: alpha(opacity=20); }</style>").appendTo(fixture), + el = jQuery("<div class='opacityWithSpaces_t12685'></div>").appendTo(fixture); + + equal( Math.round( el.css("opacity") * 100 ), 10, "opacity from style sheet (filter:alpha with spaces)" ); + el.removeClass("opacityWithSpaces_t12685").addClass("opacityNoSpaces_t12685"); + equal( Math.round( el.css("opacity") * 100 ), 20, "opacity from style sheet (filter:alpha without spaces)" ); + el.css( "opacity", 0.3 ); + equal( Math.round( el.css("opacity") * 100 ), 30, "override opacity" ); + el.css( "opacity", "" ); + equal( Math.round( el.css("opacity") * 100 ), 20, "remove opacity override" ); }); } |