16

In IE when I insert text into a <pre> tag the newlines are ignored:

<pre id="putItHere"></pre>

<script>
function putText() {
   document.getElementById("putItHere").innerHTML = "first line\nsecond line";
}
</script>

Using \r\n instead of a plain \n does not work.

<br/> does work but inserts an extra blank line in FF, which is not acceptable for my purposes.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Itay Maman
  • 30,277
  • 10
  • 88
  • 118
  • 1
    doesn't add an extra line in Firefox for me. – Vincent McNabb Oct 12 '08 at 11:44
  • Me neither, I guess he left the \n after it hence my answer. – GavinCattell Oct 12 '08 at 11:45
  • I thought one of the points of jQuery was to abstract away the differences between browsers and versions. If i wanted the new (broken) IE behavior I would use `.innerHTML = "..."` instead of `.html("...")`. Am I missing something? –  Dec 03 '11 at 19:54

11 Answers11

13

These quirksmode.org bug report and comments about innerHTML behaviour of Internet Explorer could help:

"IE applies HTML normalization to the data that is assigned to the innerHTML property. This causes incorrect display of whitespace in elements that ought to preserve formatting, such as <pre> and <textarea>."

splattne
  • 102,760
  • 52
  • 202
  • 249
7

Does this work in IE?

document.getElementById("putItHere")
    .appendChild(document.createTextNode("first line\nsecond line"));

I tested it with Firefox and it works. :-)

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
5

The workaround can be found in the page linked to in the accepted answer. For ease of use here it is:

if (elem.tagName == "PRE" && "outerHTML" in elem)
{
    elem.outerHTML = "<PRE>" + str + "</PRE>";
}
else
{
    elem.innerHTML = str;
}
Edward Wilde
  • 25,967
  • 8
  • 55
  • 64
4

<br/> shoud only output one line in all browsers. Of course remove the \n as well, code should be:

document.getElementById("putItHere").innerHTML = "first line<br/>second line";
GavinCattell
  • 3,863
  • 20
  • 22
4

Content inside the <pre> tag should not be considered HTML.

In fact, the point of <pre> tag is so that it does display formatted text.

Using the innerText property is the correct way to modify the content of a <pre> tag.

document.getElementById("putItHere").innerText = "first line\nsecond line";
Samuel Kim
  • 3,723
  • 2
  • 23
  • 18
  • 1
    True, this would work fine in IE, but note that innerText is not available in Firefox - DOM manipulation methods would likely be a more robust solution in this case, such as Chris Jester-Young's answer using appendChild and document.createTextNode. – J c Oct 12 '08 at 12:37
2

IE9 does not normalize white spaces, unlike its predecessors.

You should test for support rather than targeting any specific browser. E.g...

var t = document.createElement(elem.tagName);
t.innerHTML = "\n";

if( t.innerHTML === "\n" ){
    elem.innerHTML = str;
}
else if("outerHTML" in elem)
{
    elem.outerHTML = "<"+elem.tagName+">" + str + "</"+elem.tagName+">";
}
else {
    // fallback of your choice, probably do the first one.
}
Drew
  • 1,420
  • 1
  • 11
  • 14
1

I reckon this.

What I found was IE is using \r\n and Fx(others) is using \n

var newline;
if ( document.all ) newline = '\r\n';
else newline = '\n';

var data = 'firstline' + newline + 'second line';
document.getElementById("putItHere").appendChild(document.createTextNode(data));

For a TinyMCE(wysiwyg editor) plugin I once made I ended up with using BR i edit mode and cleaned it up on submit etc.

This code loops through all BR elements inside PRE elements and replaces BR with newlines.

Note that the code relies on the TinyMCE API, but can easily be written using standard Javascript.

Clean up:

        var br = ed.dom.select('pre br');
        for (var i = 0; i < br.length; i++) {
          var nlChar;
          if (tinymce.isIE)
            nlChar = '\r\n';
          else
            nlChar = '\n';

          var nl = ed.getDoc().createTextNode(nlChar);
          ed.dom.insertAfter(nl, br[i]);
          ed.dom.remove(br[i]);
        }

Good luck!

  • This is actually the best solution I've found here. Here is what I ended up with, which actually works incredibly closely to how .innerText works normally. This is what I ended up with: ```element.innerText = ""; element.appendChild(document.createTextNode(textContent));``` – Karl White Jan 30 '17 at 03:53
1

If you don't want to use outerHTML, you can also do the following for IE, if an additional pre tag is not an issue:

 if(isIE)
     document.getElementById("putItHere").innerHTML = "<pre>" + content+"</pre>";
 else
     document.getElementById("putItHere").innerHTML = content;
Vivek Jani
  • 11
  • 1
1

I've found that innerHTML is processed before it is applied to the element, hence <br> becomes a newline and multiple white spaces are removed.

To preserve the raw text you must use nodeValue, for example;

document.getElementById('pre_id').firstChild.nodeValue='    white space \r\n ad new line';
  • I think that this is a better answer that the accepted one. The accepted answer does not preserve the attributes in the
     tag and doing so would be even more work.
    –  Dec 03 '11 at 20:23
  • It turns out that this doesn't work in IE9. The lesson learned is not to post when tired, frustrated and testing half a dozen browsers. –  Dec 06 '11 at 15:08
1

Here is a very small tweak to Edward Wilde's answer that preserves the attributes on the <pre> tag.

if (elem.tagName == "PRE" && "outerHTML" in elem) {
    var outer = elem.outerHTML;
    elem.outerHTML = outer.substring(0, outer.indexOf('>') + 1) + str + "</PRE>";
}
else {
    elem.innerHTML = str;
}
0
if (typeof div2.innerText == 'undefined')
    div2.innerHTML = value;
else
    div2.innerText = value;

that worked for me.