Compsoft Flexible Specialists

Compsoft plc

Compsoft Weblog Compsoft Website News Archive Privacy Policy Contact Us  

Thursday, February 12, 2009

Empty UpdatePanels add a blank line after callback in IE

We hit a bug the other day where we found that UpdatePanels misbehave somewhat in Internet Explorer.

We spotted it because we always have an area at the top of our pages for displaying error messages. (You can see an example of this if you go to our Contact Us page and click "Send Message" without filling in your contact details.)

If you did a callback to the page that didn't result in any errors, the UpdatePanel around the error box would remain empty. Thus in most browsers you wouldn't see anything happen at the top of the page.

However, IE would insert a blank line where the UpdatePanel was, bumping the rest of the page content down by 12 pixels or so.

This is supremely annoying as it can really throw out the design of your site. It turns out it happens even if there elements in the UpdatePanel, if they're elements that don't render anything visible on the page (empty spans, hidden input controls, etc.).

Now, one way to fix it is to set the RenderMode of the UpdatePanel to Inline. This stops the bug in IE, but it also makes the UpdatePanel render as a span instead of a div. This is no good for us because the error box (when it renders) is a div, and nesting a div inside a span is invalid html.

So here's the solution we came up with - I hope it's useful to you too!

We created a class that inherits from UpdatePanel, but overrides how it renders, adding a style of display:inline if it's rendering as a div. So now it's still a div (and so it's valid to nest div within it), but it renders inline as a span would, thus sidestepping the IE bug.

Also, as it inherits directly from UpdatePanel, we can use <Compsoft:UpdatePanel> everywhere that we'd use <asp:UpdatePanel>. It's fire-and-forget: it behaves exactly like an UpdatePanel, except without the problems.

public class UpdatePanel : UpdatePanel
{
  protected override void RenderChildren(HtmlTextWriter writer)
  {
    // IsInPartialRendering is a reliable way of
    // telling it's a callback
    if (!this.IsInPartialRendering &&
      this.RenderMode == UpdatePanelRenderMode.Block)
    {
      StringBuilder sb = new StringBuilder();
      base.RenderChildren(new HtmlTextWriter(
        new StringWriter(sb)));

      string renderedHtml = sb.ToString();

      if (!renderedHtml.StartsWith("<div "))
        // This should never happen; better safe than sorry
        throw new Exception(
          "An UpdatePanel with a RenderMode of Block "
          + "isn't rendering as a <div>");

        writer.Write("<div style=\"display:inline\"");
        writer.Write(renderedHtml.Substring(4));
    }
    else
      base.RenderChildren(writer);
  }
}

Labels: , , , , , , , ,

1 Comments:

At 6:29 pm, Blogger Alessandro Bordignon said...

Muito obrigado,

Seguindo sua dica fiz a mesma implementação mas usando Jquery.

$(document).ready(function() {
//Para não gerar linhas em branco nos updatepanels vazios após o postback
$('div[id*="update"]').each(function(index) {
if($(this).text().length == 0)
{
$(this).css({
"display":"inline"
});
}
});
});

 

Post a Comment

Links to this post:

Create a Link

<< Home