views:

48

answers:

2

Hi folks,

I want to bind an event to a certain class and ID for when matching objects are created in the DOM.

I am doing this as I have some jQuery code in an ASP UpdatePanel, which causes the DOM to be re-loaded on its partial postback. I have reset the events with live(), however I need to call a 2 line initialisation function as soon as the elements are created.

Is there any way to attach this to live(), or some other jQuery function, or will I have to write code to do this myself?

Thanks, Ed

+1  A: 

If you're using an UpdatePanel you can either write a function called:

function pageLoad() { } //Called by ASP.Net javascript code

That will be called every time the page initially loads and when it loads UpdatePanel content, or alternatively you can hook up any function you want to run when an UpdatePanel comes back by doing this:

$(document).ready(function() {
  Sys.WebForms.PageRequestManager.getInstance().add_endRequest(myFunction);
});
function myFunction() {
 //Do stuff with elements
}

Note this will NOT run the first page load, only on UpdatePanel loads. Just add a call to myFunction(); in document.ready if you need it to run on load as well.

Nick Craver
Sorry, forgot to mention that this is meant to be a non-page-specific WebControl, and so I don't want to have to attach any code to the page itself: I'm aware of methods of refreshing scripts after postback in an updatepanel (although I've not seen your latter option before), however this is not the approach I'm going for. Ideally, this code should not rely on outside methods to reduce dependencies.
Ed Woodcock
@Ed - I do this in places where an UpdatePanel is necessary, but it doesn't have to be in the page, the second set of code you can use in any external or registered javascript file and it'll work fine, just get `Sys.WebForms.PageRequestManager.getInstance()` check for null, and if not call `.add_endRequest(myFunction);` on it, it'll work with or without an UpdatePanel or even ScriptManager present. You're just registering a handler to the exact event you care about...doesn't get more efficient than that.
Nick Craver
Hmm, true. Definitely more efficient than Anurag's solution, I'll give it a try.
Ed Woodcock
well, that code *does* get executed on the first page load, and not afterwards, it appears that the event is not getting added. I've added a parameter to the function (clientID), could this be causing the issue?
Ed Woodcock
@Ed - Yes, an event handler can't have a variable like that, where's the clientID come from, is it not something you can determine after postback?
Nick Craver
No, the idea is that each Control has its own clientID, but not its own script, in order to save on processing and byte transfer (the function is about 50 lines of code). So, each Control simply adds $(function() { bind('<%= this.ClientID %>'); }); to the document body, and thus each Control is bound without having to inject the script. Thus, I need to be able to pass the ID to the function.
Ed Woodcock
@Ed - What event are you binding, something `.live()` can't handler, or you can't do with classes?
Nick Craver
this is the thing, I'm binding click events to the live handler, however I want to run some initalisation code: basically, I want to hide a certain element, and show another, which are then switched with the click event (this is a clone(ish) of the AjaxToolkit Tabs).
Ed Woodcock
@Ed - I'd do this on the server-side before sent, is that not possible? Adding the `style="display: none"` etc? Alternatively, just unbind and bind based on a class, like this: `$(".class1").unbind("click").bind("click", function() { //stuff });` or whatever binds you need to do.
Nick Craver
Yes, I just started to go through that option, it's probably a better option anyway. Also, using the class is not an option, as the CSS class is set by the user, hence my original use of IDs.
Ed Woodcock
+1  A: 

A DOMNodeInserted event is fired whenever a node is added to the DOM. Have the document body listen to this event, and whenever it's fired, search the inserted node for the class and ID selectors you're looking for.

$(document.body).bind("DOMNodeInserted", function(event) {
    // element is the newly inserted node
    var element = $(event.target);
    // if this element is of interest
    if($("<selector>", element).length > 0) {
        // run the initialization code here..
    }
}

Read more about DOM mutation events here.

Anurag
I like it, but how efficient will this be?
Ed Woodcock
Anurag
I understand that, however I'm slightly worried that this will get called on every single node insertion, which could add up to a lot of calls (some pages this will be used on are product catalogues with upward of 400 products on a page, all of which are dynamically bound). 1ms is still a lot when you do it 400 times :)
Ed Woodcock
the above link is using jQuery 1.2.6 which does not use the newer Sizzle selector engine which is claimed to be 50% faster. newer tests here - http://digitarald.de/repos/sly/speed/index.php
Anurag
If you have that many products, you shouldn't be doing individual insertions at all, especially for those people who just won't get off IE but still want all the niceties of life. Instead, combine it into one big chunk and append to DOM using innerHTML, or use DocumentFragment.
Anurag
I agree, unfortunately, I did not write 90% of the project, and thus most of the DOM insertion is done through an ASP UpdatePanel, which basically re-appends each element seperately (as far as I can tell).
Ed Woodcock