In the previous post, I unveiled a new method of display block-level code snippets on the site. While developing this new method, I ran into a couple of cross-browser compatibility issues that delayed release of the work. Primarily, when dealing with elements that maintain whitespace (the <pre> tag and the <textarea> tag), special considerations need to be made to handle things in Internet Explorer to make the code function the same as in other browsers. Specifically, carriage returns/new lines are treated differently, as is assigning text via the innerHTML property.
Line Breaks, the <pre> Element, and IE
Typically, whitespace is ignored in HTML documents. The HTML standard, however, urges web browsers to maintain whitespace within the <pre> element. Thus, the following code:
<pre>
line 1
line 2
line 3
</pre>
…will produce the following result:
line 1 line 2 line 3
There’s an invisible character at the end of each line that tells the browser to end the line and move to the beginning of the next one. So if you wanted to add, remove, or interact with these line breaks you’d have to know what the special character is. In typical standards-based browsers, the special character is \n, so if you wanted to remove line breaks from preformatted text you could do something like this:
var pres = document.getElementsByTagName('pre');
for (var i in pres) {
pres[i].innerHTML = pres[i].innerHTML.replace(/\n/g,'');
}
This will not work for Internet Explorer though, as Internet Explorer uses \r for line breaks. In the example above, you’d have to modify the code to replace both \r and \n:
pres[i].innerHTML = pres[i].innerHTML.replace(/\n|\r/g,'');
Great! Except there’s also a problem with innerHTML, IE, and preformatted text… which leads me to:
innerHTML Removes Whitespace in IE
Apparently, whenever text is obtained or set via the innerHTML property, IE erroneously removes all the whitespace. Which is funny because innerHTML was created by Microsoft.
To address this issue, we’ll just have to use DOM based methods for getting and setting text (which we should be doing anyway). So instead of the previous code to remove line breaks, we could use this code in IE to double the line breaks:
var pres = document.getElementsByTagName('pre');
for (var i in pres) {
for (var j in pres[i].childNodes) {
if (pres[i].childNodes[j].nodeType == 3) {
pres[i].childNodes[j].nodeValue = pres[i].childNodes[j].nodeValue.replace(/\r/g,'\r\r');
}
}
}
The code checks every <pre> tag for text nodes, and if found doubles line breaks (in IE). Using nodeValue in this manner is similar to the use of innerHTML, but IE doesn’t see the same bug as before!