Wednesday, 24 November 2010

Accents clipped off text in IE7 and IE8 with Compatibility Mode

As I work in Canada, which is a bilingual country, the applications I develop usually have to be available in both English and French. Today I had a rather odd problem regarding accented characters with missing accents.

The character in question was an 'É' and I had a bug where the accent was missing. My first call was the database to check the accent was there, and it was. So I thought it was being lost due to some difference of character set between database and application layer, but breakpoints showed it was all correct at the application layer. Next I checked the source for the rendered web page and that showed the accent was there too. I even tried a copy and paste of the text and pasting the text into an editor showed the accent was present, even though it was missing in the browser.

Some more tests revealed that the accent displayed correctly in IE8 with Compatibility Mode disabled, but when Compatibility Mode was enabled the accent was clipped off. I spent some time adjusting parameters on the ASP.Net Label control and at higher levels in the mark up to get the height to increase with no more result that lots of whitespace but no accent. I was able to get the accent to appear by sacrificing the bottom few pixels of the text when setting the valign property, but this clearly wasn't acceptable. By making the text size 11 or smaller the accent appeared, but at 12 or above it was missing.

After some more searching I eventually found the CSS property to fix it. By adding "Font" tags around the label and applying "line-height: 1.1;" to the style I got it to display the accent correctly.

It seems that in the IE8 beta, Compatibility Mode was actually called IE7 Emulation Mode, a name which they really should have kept as "Compatibility" is more suggestive of standards compliance which is exactly what Compatibility Mode/IE7 Emulation Mode/IE7 is NOT.

Tuesday, 9 November 2010

Javascript popup appears again when back button pressed

One of the bugs I was looking at today was regarding use of the back button in our webapp. We have a screen that lets the user enter some data and click submit. The server side validates that data, and if necessary it alerts the user of errors using a alert issued with RegisterStartupScript.

If the user gets the error, corrects there input data, then resubmits they will be taken to the next page in the process. The problem comes when they click the back button. When the back button is pressed it takes them back to the first page which still has the startup script in it, causing the old validation error popup to appear again.

I did a lot of searching on this to see if there was a simple solution. I discovered the following:
  • There is no simple way to "unregister" a startup script.
  • Ideally the popup should be generated inside an onclick event, but this wasn't possible in my case due to the server side validation.
  • The first webpage can be set to expire, but this causes a "webpage expired" page to be displayed, which isn't any use.
  • The popup button can be pseudo disabled but that doesn't afford the user the behavior they expect.
  • Meta tags can be used to force a page to always refresh, rather than loading from the browser's cache. I wasn't able to get these to work correctly for me.
So after much effort trying different ways to do this, I went with this rather simple solution:

When we register the startup script with the alert, immediately follow the alert statement with one which will refresh the page. This ensures that the startup script is removed from the page as soon as the OK is clicked, and if the user returns to the page the pop up does not reappear.

Here's a code sample of the script injected with Page.RegisterStartupScript:

alert(\"Error with Data\");
__doPostBack('__Page', 'EmptyPostback');

Originally I was using "window.location = PageName.aspx" instead of "__doPostBack" to refresh my page without the popup, but that caused some ViewState that I needed to be lost. If you are developing in something other than ASP.Net then window.location may be better for you.