72

I'm using a jQuery tip plugin to show help tips when the user hovers certain elements of the page.

I need to register the plugin events after the page is loaded using css selectors.

The problem is I'm using an ASP.NET Update Panel and after the first postback, the tips stop working because the update panel replaces the page content but doesn't rebind the javascript events.

I need a way to execute a javascript callback after the Update Panel refreshes its content, so I can rebind the javascript events to have the tips working again.

Is there any way to do this?

tsbnunes
  • 1,003
  • 2
  • 10
  • 11

5 Answers5

169

Instead of putting your jQuery code inside of $(document).ready(), put it inside

function pageLoad(sender, args) { 
    ... 
}

pageLoad is executed after every postback, synchronous or asynchronous. pageLoad is a reserved function name in ASP.NET AJAX that is for this purpose. $(document).ready() on the other hand, is executed only once, when the DOM is initially ready/loaded.

See this Overview of ASP.NET AJAX client lifecycle events

Hill
  • 463
  • 3
  • 15
Russ Cam
  • 124,184
  • 33
  • 204
  • 266
  • 4
    Thanks for your answer. I didn't know there was a client-side pageLoad event and it's exactly what I need. Problem solved. :) – tsbnunes Jul 20 '09 at 12:48
  • i didnt know that either, useful! bear in mind i suspect this will occur for all UPs on a page, you'll need my clientid filter to be specific – Andrew Bullock Jul 21 '09 at 08:13
  • +1 FTW! I also did not know this existed and it was exactly what I was looking for to solve my issue! Big ups @Russ Cam! – longda Dec 15 '10 at 22:43
  • I have 2 update panels in my page. Is there a way to know which Update Panel caused the async refresh inside pageLoad? – empz Jun 29 '11 at 23:47
  • +1- Could not get some Jquery to run, due to the iD's being called after Dom ready. This worked perfectly. Thank you! – Hairgami_Master Apr 26 '12 at 19:28
  • 1
    Thanks buddy, its solves my problems as i have update panel on evey page with JQuery. It worked like a magic to me. Thanks a ton – Sumit Gupta Nov 15 '13 at 06:47
  • +1 - great answer: solved problem, clearly explains why, and links to further reading. Thanks - helped me a lot. – J King May 03 '14 at 20:41
  • Did not work for me! :( Neither does the solution with `Sys.Webforms...` work for me either? Am I missing a script or something? **Yes**, I was putting the script in `` but scriptmanager is laoded in `` !? - I just needed to move my script tag to the bottom of the page and it worked. PS- I also never knew about this JS Hook. – Piotr Kula Sep 16 '15 at 13:37
  • @Russ Cam your link to encosia.com appears to be dangerous. Google is warning me when I attempt to visit the page. [Check out the warning here.](https://www.google.com/transparencyreport/safebrowsing/diagnostic/index.html#url=http://encosia.com/2009/03/25/document-ready-and-pageload-are-not-the-same/) – Hill Aug 11 '16 at 18:46
  • @Hill Thanks. I'll ping the author. – Russ Cam Aug 11 '16 at 21:34
19

The pageLoad didn't work. I used this instead:

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(pageLoaded);

function pageLoaded() {
}
Chris Stillwell
  • 10,266
  • 10
  • 67
  • 77
rball
  • 6,925
  • 7
  • 49
  • 77
  • 2
    If you getting Sys id not defined that is because you are calling the script, BEFORE the script manager script is loaded. Usually in the , while the scriptmanger stuff is loaded in - Yea I know, right?! Just move your script to the bottom of the page or your control and it will work with the accepted answer fine. – Piotr Kula Sep 16 '15 at 13:38
12

This is probably far from the most elegant solution, but its a solution nonetheless:

public class UpdatePanel : System.Web.UI.UpdatePanel
{
    /// <summary>
    /// Javascript to be run when the updatepanel has completed updating
    /// </summary>
    [Description("Javascript to be run when the updatepanel has completed updating"),
        Category("Values"),
        DefaultValue(null),
        Browsable(true)]
    public string OnUpdateCompleteClientScript
    {
        get
        {
            return (string)ViewState["OnUpdateCompleteClientScript"];
        }
        set
        {
            ViewState["OnUpdateCompleteClientScript"] = value;
        }
    }

    protected override void OnPreRender(System.EventArgs e)
    {
        base.OnPreRender(e);
        if(!string.IsNullOrEmpty(this.OnUpdateCompleteClientScript))
            Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID, string.Concat("Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function(sender, args){for(var panelId in sender._updatePanelClientIDs){if(sender._updatePanelClientIDs[panelId] == '", this.ClientID, "'){", this.OnUpdateCompleteClientScript, "}}});"), true);
    }
}

Use it like this:

<uc:UpdatePanel OnUpdateCompleteClientScript="alert('update complete');">
    <!-- stuff in here -->
</uc:UpdatePanel>

Of course you'll need to register the custom control in youre webconfig or page to use it like this.

Edit: also, have you looked at jquery.live?

Andrew Bullock
  • 36,616
  • 34
  • 155
  • 231
  • 1
    The custom Update Panel User Control is overkill for my problem, but I didn't know about the jquery.live method and it would probably work and solve my problem! But in this case I think the solution presented by Russ Cam is better and I already tried it and works good. Thanks for your help. :) – tsbnunes Jul 20 '09 at 12:54
  • There must be an easier way..? – HasanG Jul 29 '10 at 14:49
0

If you want to do specific operations before and after the UpdatePanel has loaded, you can override BeginPostbackRequest and EndPostbackRequest like so:

var postbackControl = null;
var updatePanels = null;
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(BeginPostbackRequest);
prm.add_endRequest(EndPostbackRequest);

function BeginPostbackRequest(sender, args) {
    prm._scrollPosition = null;
    postbackControl = args.get_postBackElement();
    postbackControl.disabled = true;
    updatePanels = args._updatePanelsToUpdate;
    // do your stuff
}

function EndPostbackRequest(sender, args) {
    // do your stuff
    postbackControl.disabled = false;
    postbackControl = null;
    updatePanels = null;
}

This is very handy if you want to process only HTML that was delivered by the update panel. Some operations require more resources and it would be overkill to process the whole DOM tree on pageLoad.

Martin Braun
  • 10,906
  • 9
  • 64
  • 105
0

Use pageLoaded event and check whether callback or postback:

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(function (sender, args) {
    if (args._panelsUpdated && args._panelsUpdated.length > 0) {
        //callback;
    }
    else {
        //postback;
    }
});
Rover
  • 2,203
  • 3
  • 24
  • 44