views:

207

answers:

3

I am having a very specific problem in JQuery

The code below is used to Show/Hide a div. The trigger to show/hide the div will have the same ID as the div, and have classes (as selectors) showTrigger/hideTrigger respectively.

wireActionPanelv3 = function(panel, fnDoThisOnShow, fnDoThisOnHide) {

var id = $(panel).attr("id");
var showTrigger = $('#' + id + '.showTrigger');
var hideTrigger = $('#' + id + '.hideTrigger');

$(showTrigger).live('click', function(event) {
    if (fnDoThisOnShow != null) fnDoThisOnShow();
    $(panel).slideDown("fast");
    return false;
});

$(hideTrigger).live('click', function(event) {
    if (fnDoThisOnHide != null) fnDoThisOnHide();
    $(panel).slideUp("fast");
    return false;
});
};

This is how I call this function

wireActionPanelv3($('div[id="configure-filter"]'),null, null);

When the page first loads, this works perfectly when the triggers are clicked. Everything fine till now.

There are some actions which refresh the div in context. Now, when I click on the show/hide trigger, the code enters the click event above, but it does not show me the div back.

When I use bind instead of live, and call the initialization again it works. I wanted to use live as I don't need to bother about the reinitialization again.

What fact am I missing about live which can explain this behavior to me?

A: 

Hi Zuber,

in jquery 1.3 live can only be attached to one selector for one event. You may try something like this. Try to combine it to one event or upgrade to 1.4 if you didn't already :)

Greetings, Joe

edit: something like this?

$("#id").live("click", function(event) {
  if ($(this).is(":visible")) {
    $(panel).slideDown("fast");
  } else {
    $(panel).slideUp("fast");
  }
});

You may include your function call in the same style.

Joe
+1  A: 

Live is going to rig up the the cleanest selector it can. This is your problem: will have the same ID as the div...elements can't have the same ID, that's invalid HTML. .live() is trying to rig up based on ID since it should be unique and failing.

Since live() actually lives up at the DOM level, it has to have something it can uniquely identify events by as the bubble up, since that's how it catches the event. When you assign what should be guaranteed to be unique to multiple elements, you're going to get unpredictable behavior.

Nick Craver
I am not sure what you mean by double-wrapping. To be more clear on panel, this is an example of how the function is called.wireActionPanelv3($('div[id="configure-filter"]', controlContext),null, null);
Zuber
@Zuber - Re-read the answer, something you said slipped by me before, I see your actual problem now.
Nick Craver
The showTrigger/hideTrigger classes uniquely identified the elements used for the events. As a result of this the events do fire.But, $(panel).slideDown() does not work. During debugging, the panel element is correctly selected(length = 1). So, why does it now show up again?Does refreshing the div after initialization cause any change because of which the original JQuery selectors don't work anymore?P.S: I also changed the id's to be unique just to make sure that wasn't the problem. The problem still exists.
Zuber
@Zuber - Based on your post, it's both issues, IDs and that you're double wrapping jQuery objects in both places. Unwrap these: `var showTrigger = '#' + id + '.showTrigger'; var hideTrigger = '#' + id + '.hideTrigger'` **or** unwrap the `$(showTrigger)` and `$(hideTrigger)` below. Also, pass the panel selector as a string (just `#"configure-filter`), and don't wrap it below `panel = $(panelSelector, context);` creates a jQuery object, then you're wrapping it again: `$(panel).slideDown("fast");`, change to just: `panel.slideDown("fast");`
Nick Craver
A: 

I think I got some insight into the problem.

When the panel is defined as $('div[id="configure-filter"]'), it creates a jQuery object which has a unique Identifier assigned to it. It is defined as uniqueId and uniqueNumber in the object.

When the content is refreshed, the panel although existing on the page does not map to correct uniqueId, which is why any actions on the panel do not work. To get around this, you should also refresh the jQuery object in such cases.

This is the code change I had to do...

wireActionPanelv3 = function(panelSelector, context, fnDoThisOnShow, fnDoThisOnHide) {

var panel = $(panelSelector, context);
var id = $(panel).attr("id");
var showTrigger = $('#' + id + '.showTrigger');
var hideTrigger = $('#' + id + '.hideTrigger');

$(showTrigger).live('click', function(event) {
    panel = $(panelSelector, context);
    if (fnDoThisOnShow != null) fnDoThisOnShow();
    $(panel).slideDown("fast");
    return false;
});

$(hideTrigger).live('click', function(event) {
    panel = $(panelSelector, context);
    if (fnDoThisOnHide != null) fnDoThisOnHide();
    $(panel).slideUp("fast");
    return false;
});
};

I am reinitializing the panel using the selectors.

And it is used as ...

wireActionPanelv3('div[id="configure-filter"]', controlContext, function() {
    ...blah blah ...
}, null);

Here I simply pass the selector as a string.

If someone has a better explanation to this, please share.

Zuber