views:

65

answers:

2

I have an UpdatePanel with a repeater in it that is re-bound after a user adds an item to it via a modal popup.

When they click the button to add a new row to the repeater the code-behind looks something like this:

protected void lbtnAddOption_Click(object sender, EventArgs e)
{               
    SelectedOption = new Option()
    {
        Account = txtAddOptionAccountNumber.Text,
        Margin = chkAddOptionMargin.Checked,
        Symbol = txtAddOptionSymbol.Text,
        Usymbol = txtAddOptionUsymbol.Text,
     };

     Presenter.OnAddOption(); // Insert the new item
     RefreshOptions(); // Pull down and re-bind all the items
     mpeAddOptionDialog.Hide(); // Hide the modal 

     // ... Make call to jQuery scrollTo() method here?

}

This works fine and the new row will show up quickly via the UpdatePanel.

However, there are often hundreds of rows and where the new one is added is based on the current sorting column used.

So, I wanted to take this as a chance to use the sweet jQuery ScrollTo plugin. I know that if I give it the ID of my overflowed container div and the ID of an element within it, it will smoothly scroll straight to the users newly added row.

However, there are two problems:

  1. I need to find the appropriate row so I can snag the ClientID for it.
  2. I need to execute the jQuery snippet from my code-behind that will cause my newly updated repeater to scroll to the right row.

I've solved #1. I have a reliable method that will produce the newly added row's ClientID.

However, problem #2 is proving to be tricky. I know I can just call ScriptManager.RegisterStartupScript() form my code-behind and it will execute the JavaScript on my page.

The problem I'm having is that it seems that it is executing that piece of JavaScript before (I'm guessing) the newly refreshed DOM elements have fully loaded. So, even though I am passing in the appropriate jQuery line to scroll to the element I want, it is erroring out for me because it can't find that element yet.

Here is the line I'm using at the end of the method I posted above:

     string clientID = getClientIdOfNewRow();  
     ScriptManager.RegisterStartupScript(this, typeof(Page), "ScrollScript", String.Format("$(\"#optionContainer\").scrollTo(\"{0}\", 800);", clientID), true);

What do I need to do so I can ensure that this line of JavaScript isn't called until the page with the UpdatePanel is truly ready?

A: 

You can use the Sys.Application.load event which is raised after all scripts have been loaded and the objects in the application have been created and initialized.

So your code would be:

string clientID = getClientIdOfNewRow();         
ScriptManager.RegisterStartupScript(this, typeof(Page)
    ,"ScrollScript"
    ,String.Format("Sys.Application.add_load(function(){{$(\"#optionContainer\").scrollTo(\"{0}\", 800);}});"
    , clientID)
    , true);
MK
+1  A: 

If the stuff you need to process is in the update panel, then you need to run your JS once that panel is loaded. I use add_endRequest for that. This below is hacked from something rather more complex. It runs once on document ready, but installs the "end ajax" handler which is triggered every time your update panel is updated. And by the time it fires, it's all there for you.

var prm = Sys.WebForms.PageRequestManager.getInstance();
jQuery(document).ready(function () {
    prm.add_endRequest(EndRequestHandler);
});

function EndRequestHandler(sender, args) {
  // do whatever you need to do with the stuff in the update panel.
}

Obviously you can inject that from code-behind if you want.

philw