Green Cod

Good stuff I discover while I spend my days hammering on a keyboard.

Friday, May 23, 2008

Keep control in focus during a partial-page update

I was writing a tool using ASP.net and UpdatePanel that would automatically save the data any time the data entered changed. I was using AutoPostBack="true" to and thanks to the UpdatePanel, the save was invisible to the users.

Well, except for one little problem: if any control had focus before posting the page back to the server, it was lost at the end of the request. Which is rather annoying when you have a form and are used to TABbing between input elements.

I've looked around for a solution, but there was nothing that really worked for me. Some of them had a tab index in the element and assumed the focus should go to the next element after the update. But what happen if I shift-tab? Hummm. So I wrote this javascript code that does a pretty good job, but it is not perfect.

The issues are: there is a flicker of the caret between the time the AJAX framework clears focus and when I reset it. Also, the normal behavior of selecting the entire text in an input field (so that you can overwrite it) is lost; instead the caret is positioned at the end of the text. Finally (for what I've discovered so far), if you click from a AutoPostBack control to the middle of a text control (like click between the 'o' and 'r' in the word 'word'), the caret will be repositioned at the end of the word.

There may be other quirks as well, but the value of getting rid of any 'save' button is too good not to use. Why does Microsoft AJAX framework behave like this? After all, they have all the tools necessary to track which element has the focus. Maybe they will give us some options in a future patch. Or maybe there is something I simply overlooked and it is already there.

In any case here is my solution. You'll need this javascript:
function manageFocus_addOnFocus()
{
  var el = document.forms[0].elements;
  var el_type = "";
  for(var i=0;i
  {
      el_type = el[i].type;
      if( el_type )
      {
          if( el_type == "text" || el_type == "textarea" ||                             el_type.indexOf("select") >-1  ||
              el_type == "radio" || el_type == "checkbox" || el_type ==                 "submit" || el_type == "button" )
         {
              el[i].onfocus=function()
                      {
                          manageFocus_lastInFocusElement=this;
                      }
         }
      }
  }
}

var manageFocus_lastInFocusElement = null;

function manageFocus_RestoreFocus(source, args)
{
  if( manageFocus_lastInFocusElement )
  {
      document.getElementById(manageFocus_lastInFocusElement.id).focus();
  }
}

function manageFocus_AddEventHandlers()
{
  var prm = Sys.WebForms.PageRequestManager.getInstance();
  prm.add_endRequest(manageFocus_RestoreFocus);
}

function manageFocus_Init()
{
    manageFocus_addOnFocus();
  manageFocus_AddEventHandlers();
}
And a way to run manageFocus_Init() when the page loads. I use the following code to inject both the code and the onload command:
ScriptManager.RegisterClientScriptInclude(this, typeof(string),"manageFocus", "manageFocus.js");
ScriptManager.RegisterStartupScript(this, typeof(string),                     "manageFocus_startup", "manageFocus_Init();", true);

Labels:

Tuesday, May 6, 2008

More Convertion Woes in Visual Studio

Good day, Converting from Web Site Projects to Web Application Projects is not as straightforward as we would like. One specific problem is with control that were under App_Code in the Web Site project. When you are trying to 'Convert to Web Application', i.e. create the xyz.designer.cs file in the new project, you will get errors such as: unknown server tag 'abc'. Barring such obvious issues like not registering the control in %lt;%Register%$gt; or in the web.config, the problem comes from the fact that the control is not yet compiled and will not be compiled until you can generate all the designer files. What came first: the chicken or the egg? There are more details here: Steven Smith's blog. But also know that if you move your controls to a library and get your site to generate all the designer files and compile, you can then put the control files back in your Web Application project! I find it easier myself to keep all the controls and pages under the same part of the solution tree.

Labels:

Converting Web Site Project to Web Application Project

Good day, There is a lot of good information about conversion, but I hit a problem when I tried to move my project from Web Site Projects to Web Application Projects with Visual Studio 2008. The project would compile properly but when executing, it would throw errors that there were "unknown server tags". Whhaaat? But it just compiled fine! After much fudging around I discovered that the problem was with the following tag in my web.config file: <pages> <controls> <add tagprefix="comp" namespace="Competition.WebUI.Controls"> The above line works fine in Web Site Projects, but the new Web Application Projects wouldn't accept it. Change it to: <add tagprefix="comp" namespace="Competition.WebUI.Controls" assembly="MyAssembly"> to fix the problem. Basicly, you need to define the assembly. I believe that it should be done in Web Site projects as well, but that it let you get away with it if you don't. Anyway, hopefully it can be helpful to someone else.

Labels: