Skip to main content

Bug Tracker

Side navigation

#5010 closed bug (invalid)

Opened August 04, 2009 02:20PM UTC

Closed October 29, 2010 05:22AM UTC

Last modified November 12, 2012 12:11AM UTC

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:
Blocked by: Blocking:
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.

Attachments (0)
Change History (9)

Changed April 29, 2010 01:03PM UTC by jeanmonod comment:1

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:

foo
foobar

Changed April 29, 2010 02:22PM UTC by jeanmonod comment:2

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);
    };
  })();

Changed May 18, 2010 01:15PM UTC by jeanmonod comment:3

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);
    };
  })();

Changed October 28, 2010 04:30AM UTC by addyosmani comment:4

type: bugenhancement

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.

Changed October 28, 2010 04:31AM UTC by addyosmani comment:5

milestone: 1.4
version: 1.3.21.4.3

Changed October 29, 2010 05:22AM UTC by SlexAxton comment:6

milestone: → 1.5
priority: majorlow
resolution: → invalid
status: newclosed
type: enhancementbug

I went through this and figured out exactly which combinations work which way, and I think the way the library works makes sense.

http://jsfiddle.net/wWaqL/

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...

Changed November 17, 2010 09:17PM UTC by michaelhaszprunar@googlemail.com comment:7

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 ;)

Changed May 13, 2012 12:39AM UTC by masimao@gmail.com comment:8

I've resolved the problem with a dirty hack, i called a callback that do the same thing.


$("#element").hide("slow", function() { 

    $("#box-produto-visivel-zerar-estoque").show();

});

Changed November 12, 2012 12:11AM UTC by calingasan comment:9

_comment0: This issue only occurs with IE7. 1352679584827730
_comment1: This issue only occurs on IE7. \ \ Fix \ $("selector").hide(0, function(){ $(this).hide(); });1352679602404787

This issue only occurs on IE7.

Fix

$("selector").hide(0, function(){ $(this).hide(); });