views:

26

answers:

3

I have a chat window (using a <div>) that sometimes needs to get multiline entries. Until now, I've simply replaced incoming \n with <br> and displayed the text with .append(). Unfortunately, I've discovered leaving a naked .append() based on user input allows the user to insert arbitrary HTML, which will then be executed by the browser. Discovered this while copying a random StackOverflow page to it (to test large sends) and in it was a <link> tag, which promptly caused the browser to try to download the CSS file.

Changing this method to use .text() solved that particular problem, but now I am unable to display newlines. <br>s come through as literal text rather than HTML, and \n doesn't seem to have any effect.

Any suggestions? Should I use .append() but find some way to escape all HTML tags except <br>? Or is there a way to slip newlines in to .text()? Or is there a third option I'm missing completely?

+1  A: 

Use a <pre> element to preserve newlines in plain text (among other things).

http://www.codetoad.com/html/text/pre_tag.asp

If you want to insert html tags, you should be using $.html(), not $.text().

Matt Ball
But I don't want a monospace font...
Andrew
You can easily override your browser's default `<pre>` styling using CSS: `pre { font-family: Sans-Serif;}` changes all `<pre>`s to use Sans-Serif.
Matt Ball
I'd love to give checkmarks to both this and the `white-space:` answers, but seeing as how `<pre>` was the solution I went with, I had to mark this one as my answer.
Andrew
A: 

If you want them to be able to chat HTML (As text):

You can escape the HTML elements first, by replacing < with &lt; and > with &gt; and then replace the new lines with BR tags.

Fosco
+2  A: 

You can use html() and <br> as long as you escape other characters that may be special in HTML. eg.

function encodeHTML(s) {
    return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
}

$('#something').append(encodeHTML(userinput).replace(/\n/g, '<br>'));

You might also consider turning \n\n into a paragraph break.

The other approach would be to continue using text() but set a white-space: pre-wrap style to keep the \n characters as line breaks

Since IE prior to version 8 doesn't support this you would need a fallback style to set white-space: pre; word-wrap: break-word; for that browser. Other older and obscure browsers may also not support this.

bobince
I'll try both of these, but in the meantime, if I wanted to go with the first option, and also wanted to maintain `<a>` tags... I'd have to go with a big regex for this, wouldn't I?
Andrew
@Andrew: funny you should ask bobince about regex and HTML. Just a heads up - the `<center>` cannot hold. :P
Matt Ball
Mere <a>narchy is loos'd upon the world.
Andrew
bobince
Actually it doesn't matter too much. The input problem doesn't matter for <a> tags, because it's not like the person is posting a link to themselves. The server can handle replacement of tags in this case.
Andrew
I'd love to give a checkmark to this answer, as it enlightened me to the existence of `white-space:`, but I went with the `<pre>` solution.
Andrew