Ticket #5010 (closed bug: invalid)
show() & hide() do not work on elements that have a hidden parent
| Reported by: | fahrvergnuugen | Owned by: | |
|---|---|---|---|
| Priority: | low | Milestone: | 1.5 |
| Component: | effects | Version: | 1.4.3 |
| Keywords: | show hide slideup slidedown | Cc: | |
| Blocking: | Blocked by: |
Description
show() and hide() (and all other toggle effects) will ignore elements that have a parent that is not visible. This may seem like correct behavior but one could make the argument that if you wanted to target hidden or visible elements you should do so with the selector and not rely on the code within show()/hide().
The current implementation limits what can be done with show & hide. The following example scenario demonstrates the problem with the current implementation:
The scenario: A page of products with attributes and descriptions. A filter for showing & hiding products based on their attribute values. A preference checkbox for showing or hiding the descriptions.
The problem: 1) User filters the products, which hides several of them 2) User turns off descriptions (developer uses .hide() on the description containers) 3) User changes the filter so that previously hidden products are now visible
In this scenario, we will now have some products with hidden descriptions and some products with visible descriptions. This is because hide() ignored the description containers on the filtered products in step 2.
Change History
comment:2 Changed 3 years ago by jeanmonod
For people who need a fix for this bug, here is a little hack to fix it:
(function(){
var originalHideMethod = jQuery.fn.hide;
jQuery.fn.hide = function(speed,callback){
// We have to fix the case when speed is define
if ( speed !== undefined ) {
// Foreach object, we must act different if they are visible or not
$(this).each(function(){
if ($(this).is(":visible"))
originalHideMethod.apply($(this), [speed,callback]);
else
originalHideMethod.apply($(this),[null,callback]);
});
}
originalHideMethod.apply($(this),arguments);
};
})();
comment:3 Changed 3 years ago by jeanmonod
Here is a better version of the fix, previous version was missing the return before parent call, and so was not usable in a chain call like $('foo').hide().show()
(function(){
var originalHideMethod = jQuery.fn.hide;
jQuery.fn.hide = function(speed,callback){
// We have to fix the case when speed is define
if ( speed !== undefined ) {
// Foreach object, we must act different if they are visible or not
$(this).each(function(){
if ($(this).is(":visible"))
return originalHideMethod.apply($(this), [speed,callback]);
else
return originalHideMethod.apply($(this),[null,callback]);
});
}
return originalHideMethod.apply($(this),arguments);
};
})();
comment:4 Changed 3 years ago by addyosmani
- Type changed from bug to enhancement
The current behavior that indeed is correct. If a user wishes to adjust what happens when the default behavior is applied, they can simply alter the parent elements to not be hidden, change the structure of their mark-up to better suit the problem being targeted or alternatively, use one of the suggested custom-fixes in the above thread. Moving this to enhancements.
comment:5 Changed 3 years ago by addyosmani
- Version changed from 1.3.2 to 1.4.3
- Milestone 1.4 deleted
comment:6 Changed 3 years ago by SlexAxton
- Priority changed from major to low
- Status changed from new to closed
- Type changed from enhancement to bug
- Resolution set to invalid
- Milestone set to 1.5
I went through this and figured out exactly which combinations work which way, and I think the way the library works makes sense.
There is one ambiguity with 'toggle' and whether it should be element specific or not, but unfortunately it's infeasible from a performance aspect to check all parents of every element that's hidden, so this interpretation of how it works automatically wins.
I agree it's confusing, but I think you may be happier with an application architecture that doesn't rely on this type of thing. If you need more convincing, we're all around in the #jquery channel on freenode. I know this is a bit of a weird one...
comment:7 Changed 3 years ago by michaelhaszprunar@…
Hi, I guess the greatest confusion for people is that they think, hide() is taking longer (e.g. using "normal" as default speed) than hide(0). I thought so myself until I looked at the jQuery core code. Maybe this has changed in the past?
But I have to agree and disagree Alex Sexton: I agree that toggle() and show() are a problem, when parents are hidden but children are not. But in my opinion, hide() can not be compared to toggle()/show() as hiding does not involve the parents visibility. So at least fix this for hide ;)
Please follow the bug reporting guidlines and use jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

This problem happends only when we use the animated show/hide. Using hide(100) or even hide(0) doesn't act like hide(). Here is a test case to illustrate the situation:
<span id="parent1">foo<span id="child1">bar</span></span><br/> <span id="parent2">foo<span id="child2">bar</span></span> <script type="text/javascript"> $(document).ready(function() { $("#parent1").hide();$("#child1").hide();$("#parent1").show(); $("#parent2").hide();$("#child2").hide(0);$("#parent2").show(); }); </script>Result of this generate this text: