Skip to content

Commit d343e6b

Browse files
committed
Fix #12904: Firefox defaultDisplay with body/iframe display:none. Report and solution by @maranomynet; test by @rwldrn.
1 parent 23d7cf0 commit d343e6b

File tree

2 files changed

+60
-52
lines changed

2 files changed

+60
-52
lines changed

src/css.js

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var curCSS, iframe, iframeDoc,
1+
var curCSS, iframe,
22
ralpha = /alpha\([^)]*\)/i,
33
ropacity = /opacity\s*=\s*([^)]*)/,
44
rposition = /^(top|right|bottom|left)$/,
@@ -446,44 +446,38 @@ function getWidthOrHeight( elem, name, extra ) {
446446

447447
// Try to determine the default display value of an element
448448
function css_defaultDisplay( nodeName ) {
449-
if ( elemdisplay[ nodeName ] ) {
450-
return elemdisplay[ nodeName ];
451-
}
452-
453-
var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ),
454-
display = elem.css("display");
455-
elem.remove();
456-
457-
// If the simple way fails,
458-
// get element's real default display by attaching it to a temp iframe
459-
if ( display === "none" || display === "" ) {
460-
// Use the already-created iframe if possible
461-
iframe = document.body.appendChild(
462-
iframe || jQuery.extend( document.createElement("iframe"), {
463-
frameBorder: 0,
464-
width: 0,
465-
height: 0
466-
})
467-
);
468-
469-
// Create a cacheable copy of the iframe document on first call.
470-
// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
471-
// document to it; WebKit & Firefox won't allow reusing the iframe document.
472-
if ( !iframeDoc || !iframe.createElement ) {
473-
iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
474-
iframeDoc.write("<!doctype html><html><body>");
475-
iframeDoc.close();
449+
var elem,
450+
doc = document,
451+
display = elemdisplay[ nodeName ];
452+
453+
if ( !display ) {
454+
elem = jQuery( doc.createElement( nodeName ) );
455+
display = curCSS( elem.appendTo( doc.body )[0], "display" );
456+
elem.remove();
457+
458+
// If the simple way fails, read from inside an iframe
459+
if ( display === "none" || !display ) {
460+
// Use the already-created iframe if possible
461+
iframe = ( iframe ||
462+
jQuery("<iframe frameborder='0' width='0' height='0'/>")
463+
.css( "cssText", "display:block !important" )
464+
).appendTo( doc.documentElement );
465+
466+
// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
467+
doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
468+
doc.write("<!doctype html><html><body>");
469+
doc.close();
470+
471+
elem = jQuery( doc.createElement( nodeName ) );
472+
display = curCSS( elem.appendTo( doc.body )[0], "display" );
473+
elem.remove();
474+
iframe.detach();
476475
}
477476

478-
elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) );
479-
480-
display = curCSS( elem, "display" );
481-
document.body.removeChild( iframe );
477+
// Store the correct default display
478+
elemdisplay[ nodeName ] = display;
482479
}
483480

484-
// Store the correct default display
485-
elemdisplay[ nodeName ] = display;
486-
487481
return display;
488482
}
489483

test/unit/css.js

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -574,19 +574,33 @@ test( "show() resolves correct default display for detached nodes", function(){
574574
test("show() resolves correct default display #10227", function() {
575575
expect(2);
576576

577-
jQuery("html").append(
577+
var body = jQuery("body");
578+
body.append(
578579
"<p id='ddisplay'>a<style>body{display:none}</style></p>"
579580
);
580581

581-
equal( jQuery("body").css("display"), "none", "Initial display: none" );
582+
equal( body.css("display"), "none", "Initial display: none" );
582583

583-
jQuery("body").show();
584-
585-
equal( jQuery("body").css("display"), "block", "Correct display: block" );
584+
body.show();
585+
equal( body.css("display"), "block", "Correct display: block" );
586586

587587
jQuery("#ddisplay").remove();
588+
QUnit.expectJqData( body[0], "olddisplay" );
589+
});
590+
591+
test("show() resolves correct default display when iframe display:none #12904", function() {
592+
expect(2);
593+
594+
var ddisplay = jQuery(
595+
"<p id='ddisplay'>a<style>p{display:none}iframe{display:none !important}</style></p>"
596+
).appendTo("body");
597+
598+
equal( ddisplay.css("display"), "none", "Initial display: none" );
599+
600+
ddisplay.show();
601+
equal( ddisplay.css("display"), "block", "Correct display: block" );
588602

589-
jQuery.cache = {};
603+
ddisplay.remove();
590604
});
591605

592606
test("toggle()", function() {
@@ -871,17 +885,17 @@ test( "cssHooks - expand", function() {
871885
test( "css opacity consistency across browsers (#12685)", function() {
872886
expect( 4 );
873887

874-
var fixture = jQuery("#qunit-fixture"),
875-
style = jQuery("<style>.opacityWithSpaces_t12685 { opacity: 0.1; filter: alpha(opacity = 10); } .opacityNoSpaces_t12685 { opacity: 0.2; filter: alpha(opacity=20); }</style>").appendTo(fixture),
876-
el = jQuery("<div class='opacityWithSpaces_t12685'></div>").appendTo(fixture);
877-
878-
equal( Math.round( el.css("opacity") * 100 ), 10, "opacity from style sheet (filter:alpha with spaces)" );
879-
el.removeClass("opacityWithSpaces_t12685").addClass("opacityNoSpaces_t12685");
880-
equal( Math.round( el.css("opacity") * 100 ), 20, "opacity from style sheet (filter:alpha without spaces)" );
881-
el.css( "opacity", 0.3 );
882-
equal( Math.round( el.css("opacity") * 100 ), 30, "override opacity" );
883-
el.css( "opacity", "" );
884-
equal( Math.round( el.css("opacity") * 100 ), 20, "remove opacity override" );
888+
var fixture = jQuery("#qunit-fixture"),
889+
style = jQuery("<style>.opacityWithSpaces_t12685 { opacity: 0.1; filter: alpha(opacity = 10); } .opacityNoSpaces_t12685 { opacity: 0.2; filter: alpha(opacity=20); }</style>").appendTo(fixture),
890+
el = jQuery("<div class='opacityWithSpaces_t12685'></div>").appendTo(fixture);
891+
892+
equal( Math.round( el.css("opacity") * 100 ), 10, "opacity from style sheet (filter:alpha with spaces)" );
893+
el.removeClass("opacityWithSpaces_t12685").addClass("opacityNoSpaces_t12685");
894+
equal( Math.round( el.css("opacity") * 100 ), 20, "opacity from style sheet (filter:alpha without spaces)" );
895+
el.css( "opacity", 0.3 );
896+
equal( Math.round( el.css("opacity") * 100 ), 30, "override opacity" );
897+
el.css( "opacity", "" );
898+
equal( Math.round( el.css("opacity") * 100 ), 20, "remove opacity override" );
885899
});
886900

887901
}

0 commit comments

Comments
 (0)