Skip to content

Commit 4ae9095

Browse files
committed
CSS: Ignore the CSS cascade in show()/hide()/etc.
WIP (failing effects tests) Fixes gh-1767
1 parent f5aa89a commit 4ae9095

File tree

4 files changed

+85
-154
lines changed

4 files changed

+85
-154
lines changed

src/css.js

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -152,58 +152,39 @@ function getWidthOrHeight( elem, name, extra ) {
152152
}
153153

154154
function showHide( elements, show ) {
155-
var display, elem, hidden,
155+
var display, elem,
156156
values = [],
157157
index = 0,
158158
length = elements.length;
159159

160+
// Determine new display value for elements that need to change
160161
for ( ; index < length; index++ ) {
161162
elem = elements[ index ];
162163
if ( !elem.style ) {
163164
continue;
164165
}
165166

166-
values[ index ] = dataPriv.get( elem, "olddisplay" );
167167
display = elem.style.display;
168168
if ( show ) {
169-
// Reset the inline display of this element to learn if it is
170-
// being hidden by cascaded rules or not
171-
if ( !values[ index ] && display === "none" ) {
172-
elem.style.display = "";
173-
}
174-
175-
// Set elements which have been overridden with display: none
176-
// in a stylesheet to whatever the default browser style is
177-
// for such an element
178-
if ( elem.style.display === "" && isHidden( elem ) ) {
179-
values[ index ] = dataPriv.access(
180-
elem,
181-
"olddisplay",
182-
defaultDisplay(elem.nodeName)
183-
);
169+
if ( display === "none" ) {
170+
// Restore a pre-hide() value if we have one
171+
values[ index ] = dataPriv.get( elem, "olddisplay" ) || "";
184172
}
185173
} else {
186-
hidden = isHidden( elem );
174+
if ( display !== "none" ) {
175+
values[ index ] = "none";
187176

188-
if ( display !== "none" || !hidden ) {
189-
dataPriv.set(
190-
elem,
191-
"olddisplay",
192-
hidden ? display : jQuery.css( elem, "display" )
193-
);
177+
// Remember the value we're replacing
178+
dataPriv.set( elem, "olddisplay", display );
194179
}
195180
}
196181
}
197182

198-
// Set the display of most of the elements in a second loop
183+
// Set the display of the elements in a second loop
199184
// to avoid the constant reflow
200185
for ( index = 0; index < length; index++ ) {
201-
elem = elements[ index ];
202-
if ( !elem.style ) {
203-
continue;
204-
}
205-
if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
206-
elem.style.display = show ? values[ index ] || "" : "none";
186+
if ( values[ index ] != null ) {
187+
elements[ index ].style.display = values[ index ];
207188
}
208189
}
209190

test/data/testsuite.css

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ div.noopacity {
6868
opacity: 0;
6969
}
7070

71-
div.hidden {
71+
div.hidden,
72+
span.hidden {
7273
display: none;
7374
}
7475

@@ -116,19 +117,10 @@ div#fx-tests div.noback {
116117
display: none;
117118
}
118119

119-
/* tests to ensure jQuery can determine the native display mode of elements
120-
that have been set as display: none in stylesheets */
121-
div#show-tests * { display: none; }
122-
123120
#nothiddendiv { font-size: 16px; }
124121
#nothiddendivchild.em { font-size: 2em; }
125122
#nothiddendivchild.prct { font-size: 150%; }
126123

127-
/* 8099 changes to default styles are read correctly */
128-
tt { display: none; }
129-
sup { display: none; }
130-
dfn { display: none; }
131-
132124
/* #9239 Attach a background to the body( avoid crashes in removing the test element in support ) */
133125
body, div { background: url(http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif) no-repeat -1000px 0; }
134126

test/unit/css.js

Lines changed: 49 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -475,14 +475,14 @@ test("show(); hide()", function() {
475475

476476
hiddendiv = jQuery("div.hidden");
477477
hiddendiv.hide();
478-
equal( hiddendiv.css("display"), "none", "Non-detached div hidden" );
478+
equal( hiddendiv.css("display"), "none", "Cascade-hidden div after hide()" );
479479
hiddendiv.show();
480-
equal( hiddendiv.css("display"), "block", "Pre-hidden div shown" );
480+
equal( hiddendiv.css("display"), "none", "Show does not trump CSS cascade" );
481481

482482
div = jQuery("<div>").hide();
483483
equal( div.css("display"), "none", "Detached div hidden" );
484484
div.appendTo("#qunit-fixture").show();
485-
equal( div.css("display"), "block", "Pre-hidden div shown" );
485+
equal( div.css("display"), "block", "Initially-detached div after show()" );
486486

487487
});
488488

@@ -545,129 +545,88 @@ test("show();", function() {
545545
jQuery("<div>test</div> text <span>test</span>").hide().remove();
546546
});
547547

548-
test("show() resolves correct default display #8099", function() {
549-
expect(7);
550-
var tt8099 = jQuery("<tt/>").appendTo("body"),
551-
dfn8099 = jQuery("<dfn/>", { "html": "foo"}).appendTo("body");
552-
553-
equal( tt8099.css("display"), "none", "default display override for all tt" );
554-
equal( tt8099.show().css("display"), "inline", "Correctly resolves display:inline" );
555-
556-
equal( jQuery("#foo").hide().show().css("display"), "block", "Correctly resolves display:block after hide/show" );
557-
558-
equal( tt8099.hide().css("display"), "none", "default display override for all tt" );
559-
equal( tt8099.show().css("display"), "inline", "Correctly resolves display:inline" );
560-
561-
equal( dfn8099.css("display"), "none", "default display override for all dfn" );
562-
equal( dfn8099.show().css("display"), "inline", "Correctly resolves display:inline" );
563-
564-
tt8099.remove();
565-
dfn8099.remove();
566-
});
567-
568548
test( "show() resolves correct default display for detached nodes", function(){
569-
expect( 13 );
549+
expect( 16 );
570550

571-
var div, span, tr, trDisplay;
551+
var div, span, tr;
572552

573553
div = jQuery("<div class='hidden'>");
574554
div.show().appendTo("#qunit-fixture");
575-
equal( div.css("display"), "block", "Make sure a detached, pre-hidden( through stylesheets ) div is visible." );
555+
equal( div.css("display"), "none",
556+
"A shown-while-detached div can be hidden by the CSS cascade" );
576557

577-
div = jQuery("<div style='display: none'>");
558+
div = jQuery("<div><div class='hidden'></div></div>").children("div");
578559
div.show().appendTo("#qunit-fixture");
579-
equal( div.css("display"), "block", "Make sure a detached, pre-hidden( through inline style ) div is visible." );
560+
equal( div.css("display"), "none",
561+
"A shown-while-detached div inside a visible div can be hidden by the CSS cascade" );
580562

581563
span = jQuery("<span class='hidden'/>");
582564
span.show().appendTo("#qunit-fixture");
583-
equal( span.css("display"), "inline", "Make sure a detached, pre-hidden( through stylesheets ) span has default display." );
584-
585-
span = jQuery("<span style='display: inline'/>");
586-
span.show().appendTo("#qunit-fixture");
587-
equal( span.css("display"), "inline", "Make sure a detached, pre-hidden( through inline style ) span has default display." );
588-
589-
div = jQuery("<div><div class='hidden'></div></div>").children("div");
590-
div.show().appendTo("#qunit-fixture");
591-
equal( div.css("display"), "block", "Make sure a detached, pre-hidden( through stylesheets ) div inside another visible div is visible." );
592-
593-
div = jQuery("<div><div style='display: none'></div></div>").children("div");
594-
div.show().appendTo("#qunit-fixture");
595-
equal( div.css("display"), "block", "Make sure a detached, pre-hidden( through inline style ) div inside another visible div is visible." );
565+
equal( span.css("display"), "none",
566+
"A shown-while-detached span can be hidden by the CSS cascade" );
596567

597568
div = jQuery("div.hidden");
598569
div.detach().show();
599-
equal( div.css("display"), "block", "Make sure a detached( through detach() ), pre-hidden div is visible." );
570+
ok( !div[ 0 ].style.display,
571+
"show() does not update inline style of a cascade-hidden-before-detach div" );
572+
div.appendTo("#qunit-fixture");
573+
equal( div.css("display"), "none",
574+
"A shown-while-detached cascade-hidden div is hidden after attachment" );
600575
div.remove();
601576

602-
span = jQuery("<span>");
603-
span.appendTo("#qunit-fixture").detach().show().appendTo("#qunit-fixture" );
604-
equal( span.css("display"), "inline", "Make sure a detached( through detach() ), pre-hidden span has default display." );
577+
span = jQuery("<span class='hidden'>");
578+
span.appendTo("#qunit-fixture").detach().show().appendTo("#qunit-fixture");
579+
equal( span.css("display"), "none",
580+
"A shown-while-detached cascade-hidden span is hidden after attachment" );
605581
span.remove();
606582

607-
div = jQuery("<div>");
583+
div = jQuery( document.createElement("div") );
608584
div.show().appendTo("#qunit-fixture");
609-
ok( !!div.get( 0 ).style.display, "Make sure not hidden div has a inline style." );
585+
ok( !div[ 0 ].style.display, "A shown-while-detached div has no inline style" );
586+
equal( div.css("display"), "block",
587+
"A shown-while-detached div has default display after attachment" );
610588
div.remove();
611589

612-
div = jQuery( document.createElement("div") );
590+
div = jQuery("<div style='display: none'>");
591+
div.show();
592+
equal( div[ 0 ].style.display, "",
593+
"show() updates inline style of a detached inline-hidden div" );
594+
div.appendTo("#qunit-fixture");
595+
equal( div.css("display"), "block",
596+
"A shown-while-detached inline-hidden div has default display after attachment" );
597+
598+
div = jQuery("<div><div style='display: none'></div></div>").children("div");
613599
div.show().appendTo("#qunit-fixture");
614-
equal( div.css("display"), "block", "Make sure a pre-created element has default display." );
615-
div.remove();
600+
equal( div.css("display"), "block",
601+
"A shown-while-detached inline-hidden div inside a visible div has default display " +
602+
"after attachment" );
603+
604+
span = jQuery("<span style='display: none'/>");
605+
span.show();
606+
equal( span[ 0 ].style.display, "",
607+
"show() updates inline style of a detached inline-hidden span" );
608+
span.appendTo("#qunit-fixture");
609+
equal( span.css("display"), "inline",
610+
"A shown-while-detached inline-hidden span has default display after attachment" );
616611

617612
div = jQuery("<div style='display: inline'/>");
618613
div.show().appendTo("#qunit-fixture");
619-
equal( div.css("display"), "inline", "Make sure that element has same display when it was created." );
614+
equal( div.css("display"), "inline",
615+
"show() does not update inline style of a detached inline-visible div" );
620616
div.remove();
621617

622618
tr = jQuery("<tr/>");
623619
jQuery("#table").append( tr );
624-
trDisplay = tr.css( "display" );
625620
tr.detach().hide().show();
626621

627-
equal( tr[ 0 ].style.display, trDisplay, "For detached tr elements, display should always be like for attached trs" );
622+
ok( !tr[ 0 ].style.display, "Not-hidden detached tr elements have no inline style" );
628623
tr.remove();
629624

630625
span = jQuery("<span/>").hide().show();
631-
equal( span[ 0 ].style.display, "inline", "For detached span elements, display should always be inline" );
626+
ok( !span[ 0 ].style.display, "Not-hidden detached span elements have no inline style" );
632627
span.remove();
633628
});
634629

635-
test("show() resolves correct default display #10227", 4, function() {
636-
var html = jQuery( document.documentElement ),
637-
body = jQuery( "body" );
638-
639-
body.append( "<p class='ddisplay'>a<style>body{display:none}</style></p>" );
640-
641-
equal( body.css("display"), "none", "Initial display for body element: none" );
642-
643-
body.show();
644-
equal( body.css("display"), "block", "Correct display for body element: block" );
645-
646-
body.append( "<p class='ddisplay'>a<style>html{display:none}</style></p>" );
647-
648-
equal( html.css("display"), "none", "Initial display for html element: none" );
649-
650-
html.show();
651-
equal( html.css( "display" ), "block", "Correct display for html element: block" );
652-
653-
jQuery( ".ddisplay" ).remove();
654-
});
655-
656-
test("show() resolves correct default display when iframe display:none #12904", function() {
657-
expect(2);
658-
659-
var ddisplay = jQuery(
660-
"<p id='ddisplay'>a<style>p{display:none}iframe{display:none !important}</style></p>"
661-
).appendTo("body");
662-
663-
equal( ddisplay.css("display"), "none", "Initial display: none" );
664-
665-
ddisplay.show();
666-
equal( ddisplay.css("display"), "block", "Correct display: block" );
667-
668-
ddisplay.remove();
669-
});
670-
671630
test("toggle()", function() {
672631
expect(9);
673632
var div, oldHide,
@@ -1094,29 +1053,6 @@ asyncTest( "Clearing a Cloned Element's Style Shouldn't Clear the Original Eleme
10941053
window.setTimeout( start, 1000 );
10951054
});
10961055

1097-
asyncTest( "Make sure initialized display value for disconnected nodes is correct (#13310)", 4, function() {
1098-
var display = jQuery("#display").css("display"),
1099-
div = jQuery("<div/>");
1100-
1101-
equal( div.css( "display", "inline" ).hide().show().appendTo("body").css( "display" ), "inline", "Initialized display value has returned" );
1102-
div.remove();
1103-
1104-
div.css( "display", "none" ).hide();
1105-
equal( jQuery._data( div[ 0 ], "olddisplay" ), undefined, "olddisplay is undefined after hiding a detached and hidden element" );
1106-
div.remove();
1107-
1108-
div.css( "display", "inline-block" ).hide().appendTo("body").fadeIn(function() {
1109-
equal( div.css( "display" ), "inline-block", "Initialized display value has returned" );
1110-
div.remove();
1111-
1112-
start();
1113-
});
1114-
1115-
equal( jQuery._data( jQuery("#display").css( "display", "inline" ).hide()[ 0 ], "olddisplay" ), display,
1116-
"display: * !Important value should used as initialized display" );
1117-
jQuery._removeData( jQuery("#display")[ 0 ] );
1118-
});
1119-
11201056
test( "show() after hide() should always set display to initial value (#14750)", 1, function() {
11211057
var div = jQuery( "<div />" ),
11221058
fixture = jQuery( "#qunit-fixture" );

test/unit/effects.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,5 +2212,27 @@ test( "Animation should go to its end state if document.hidden = true", 1, funct
22122212
}
22132213
});
22142214

2215+
asyncTest( "Make sure initialized display value for disconnected nodes is correct (#13310)", 4, function() {
2216+
var display = jQuery("#display").css("display"),
2217+
div = jQuery("<div/>");
2218+
2219+
equal( div.css( "display", "inline" ).hide().show().appendTo("body").css( "display" ), "inline", "Initialized display value has returned" );
2220+
div.remove();
2221+
2222+
div.css( "display", "none" ).hide();
2223+
equal( jQuery._data( div[ 0 ], "olddisplay" ), undefined, "olddisplay is undefined after hiding a detached and hidden element" );
2224+
div.remove();
2225+
2226+
div.css( "display", "inline-block" ).hide().appendTo("body").fadeIn(function() {
2227+
equal( div.css( "display" ), "inline-block", "Initialized display value has returned" );
2228+
div.remove();
2229+
2230+
start();
2231+
});
2232+
2233+
equal( jQuery._data( jQuery("#display").css( "display", "inline" ).hide()[ 0 ], "olddisplay" ), display,
2234+
"display: * !Important value should used as initialized display" );
2235+
jQuery._removeData( jQuery("#display")[ 0 ] );
2236+
});
22152237

22162238
})();

0 commit comments

Comments
 (0)