Browser difference when using "innerHTML"

Published Friday, August 15, 2008 2:07 PM

This week we found another subtle browser difference as we were running MVC Ajax tests. If you have been following the Asp.Net MVC project, you will know that we are currently working on adding an Ajax story to the framework. Basically, adding helper methods so that a developer can render links that do "partial view renderings" via XmlHttpRequests. For example:

         <%= Ajax.ActionLink("Ajax.ActionLink in View Insert Before", "ResultView",
            new AjaxOptions { 
                InsertionMode = InsertionMode.InsertBefore, 
                UpdateTargetId = "div1", 
            })%>

The result will be a link that when clicked will call the "ResultView" action on the controller, and append the response to the contents of a div with id="div1".

The test team uses an internal UI automation framework to write tests, and usually what we do is write the test for IE and then run it in all other supported browsers (Safari Mac, Safari Windows, Opera, FireFox Mac, FireFox Windows), and one of these tests ran into a difference between how innerHTML is handled between different browsers: In FireFox, innerHTML is the content of the element before whitespace normalization occurs; in IE, innerHTML is the content of the element after normalization.

The following page shows the difference:

<html>
<head>
</head>
<body>
<div id="foo">
    bar
</div>
<input type="button" onclick='alert("\"" + document.getElementById("foo").innerHTML + "\"");' value="What's in the Div?" />
<input type="button" onclick='document.getElementById("foo").innerHTML = "Here is some HTML inserted by javascript." + document.getElementById("foo").innerHTML;' 

value="Insert some HTML" />
</body>
</html>

 

When you click the first button, FireFox displays:

“
                bar
“

However, in IE it displays:

“bar “

Now, when you click the second button it simulates the MVC Ajax code that appends the content of the response to the div. And what you will get is, in FireFox:

“Here is some HTML inserted by javascript.
                This is div1
“

And in IE:

“Here is some HTML inserted by javascript.This is div1 “

It's a small difference in terms of visual rendering, but an extra space is shown on the browser. At the end, the MVC feature crew decided that consistency was better in this case and chose to fix our script code to handle this case. This is one case where having a good functional automation story can help to catch product issues.

Thanks to Andrew Nurse, the dev in MVC that investigated this problem.

Federico Silva Armas
Asp.NET QA Team

by farmas
Filed under: ,

Comments

# funny wallpaper » Browser difference when using “innerHTML” said on Friday, August 15, 2008 2:18 PM

Pingback from  funny wallpaper &raquo; Browser difference when using &#8220;innerHTML&#8221;

# Joe Chung said on Friday, August 15, 2008 11:00 PM

The way it is in Firefox is also the way it is in Safari and Opera.  Good to know that you are paying attention to the details, thanks!

# ASP.NET MVC Archived Blog Posts, Page 1 said on Saturday, August 16, 2008 11:29 AM

Pingback from  ASP.NET MVC Archived Blog Posts, Page 1

# harold said on Sunday, August 17, 2008 10:55 PM

Who writes HTML like that?! what a mess!

HTML should use double-quotes for ALL attributes, and if you want to insert script, do so with single quotes.

<input type="button" onclick="alert('single quoted script strings inside HTML attributes"/>

As for the statement: "and usually what we do is write the test for IE and then run it in all other supported browsers"... woah! what a huge mistake! NEVER EVER render in IE first, you have NO idea how badly IE will botch a rendering.

Rendering in Firefox/Opera/Safari FIRST is much better process, as you won't get accidentally locked into any silly IE quirks before testing against standards.

As for the trailing whitespace in this scenario, its a 50/50% in terms of the correct behavior.  Although since the $('#foo').parentNode.innerHTML would indicate INVALID markup by MSIE, and not in any other browser, I would have to lean on the Firefox/Safari/Opera camp's side, and treat IE's behavior as incorrect.

By the way, this changing of the ID. does it update the document.all collection properly too? As this collection is used by many frameworks to overcome IE's bugs with .getElementById()

Thanks.

Harold

# aspnetqa said on Monday, August 18, 2008 11:16 PM

Thanks for your comments.

I didn't properly explain our test methodology in this post (will do in some later time). But in summary: we are responsible for verifying that all features work across all browsers, and our strategy is based on exploratory testing to find as many defects as early as possible. By the time we get to writting regression tests, the feature has already been verified on all browsers. Even though we use one browser while we are developing the test, we constantly run all tests in all browsers (at least once per every daily build) to catch any regressions.

In this case, the rendering difference was so small that we didn't see it while exploring, but it was caught while developing the regression test.

- Federico

# YESChandana -Blog said on Sunday, August 31, 2008 9:42 AM

My favorite links from the 2nd week of August 2008

# Bryan said on Friday, September 19, 2008 11:45 AM

I've come across a similar situation where if you apply the style property 'pre' for whitespace on the element, it should preserve the white space.  The issue that i'm having is that if you set the innerHTML and then access the object through the dom after that and inspect the innerHTML, it will be "normalized" even though the style attribute for whitespace was there, but if you want for the execution to finish or put a setTimeout to run after the dom refreshes, it will be corrected.  

Leave a Comment

(required) 
(required) 
(optional)
(required)