views:

218

answers:

2

I am having problems selecting the text within a TextBox in an UpdatePanel in IE 8. Consider a very simple page that contains a single UpdatePanel. Within that UpdatePanel there are two Web controls:

  1. A DropDownList with three statically-defined list items, whose AutoPostBack property is set to True, and
  2. A TextBox Web control

The DropDownList has a server-side event handler for its SelectedIndexChanged event, and in that event handler there's two lines of code:

TextBox1.Text = "Whatever";
ScriptManager.RegisterStartupScript(this, 
                      this.GetType(), 
                      "Select-" + TextBox1.ClientID,
                      string.Format("document.getElementById('{0}').select();", 
                                                       TextBox1.ClientID), 
                      true);

The idea is that whenever a user chooses and item from the DropDownList there is a partial page postback, at which point the TextBox's Text property is set and selected (via the injected JavaScript). Unfortunately, this doesn't work as-is. (I have also tried putting the script in the pageLoad function with no luck, as in: ScriptManager.RegisterStartupScript(..., "function pageLoad() { ... my script ... }");) What happens is the code runs, but something else on the page receives focus at the conclusion of the partial page postback, causing the TextBox's text to be unselected.

I can "fix" this by using JavaScript's setTimeout to delay the execution of my JavaScript code. For instance, if I update the emitted JavaScript to the following:

setTimeout("document.getElementById('{0}').select();", 111);

It "works." I put works in quotes because it works for this simple page on my computer. In a more complex page on a slower computer with more markup getting passed between the client and server on the partial page postback, I have to up the timeout to over a second to get it to work. I would hope that there is a more foolproof way to achieve this. Rather than saying, "Delay for X milliseconds," it would be ideal to say, "Run this when you're not going to steal the focus."

What's perplexing is that the .Focus() method works beautifully. That is, if I scrap my JavaScript and replace it with a call to TextBox1.Focus(); then the TextBox receives focus (although the text is not selected). I've examined the contents of MicrosoftAjaxWebForms.js and see that the focus is set after the registered scripts run, but I'm my JavaScript skills are not strong enough to decode what all is happening here and why the selected text is unselected between the time it is selected and the end of the partial page postback. I've also tried using Firebug's JavaScript debugger and see that when my script runs the TextBox's text is selected. As I continue to step through it the text remains selected, but then after stepping off the last line of script (apparently) it all of the sudden gets unselected.

Any ideas? I am pulling my hair out.

Thanks in advance...

EDIT: Upon further testing I noticed that this behavior only occurs in IE 8. It does not occur when testing in Firefox, Chrome, or Safari...

+1  A: 

I have not used the UpdatePanel much, so do not know much about whether this is of any use in your specific circumstances, but have had success with focus difficulties using a jQuery document.ready wrapper. If you are not using jQuery already it may be worth a test - try changing the RegisterStartupScript to output something like:

$(document).ready(function() {
    document.getElementById('TextBox1.ClientID').select();
});

Of course there may be non jQuery ways to sort this, but this method generally makes it simple.

callcopse
callcopse, I tested your suggestion using Firefox and it worked!! I then tried my previous attempts (in Firefox), namely putting the code straight in RegisterStartupScript, putting it in pageLoad, and using setTimeout (all three). What I found is that it worked in FF for all three scenarios.Uh oh.So I fired up IE 8, which is what I used yesterday for my testing, and none of those three approaches worked in IE 8. So we're back to square one, but with a little more information.(I've updated the original question to include this added information...)
Scott Mitchell
+1  A: 
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(
        function(sender, args) {
            document.getElementById('TextBox1.ClientID').focus();
        });

This will be called once the UpdatePanel has completed it's request. You also need to re-pull the element from the DOM since any references to it prior to the update panel being invoked will not point to the field after the update panel finishes.

Justin
Thank you for your guidance. I ended up doing something similar and this did the trick. Thanks again...
Scott Mitchell