115

I'm having jQuery take some textarea content and insert it into an li.

I want it to visually retain the line breaks.

There must be a really simple way to do this...

Luca Filosofi
  • 30,905
  • 9
  • 70
  • 77
gbhall
  • 13,139
  • 9
  • 37
  • 42
  • XSS note:If you're doing this it sounds like you're directly mixing user input and
    's, which means you're either displaying newlines or
    , and thus *may* be open to XSS attack, that is if your input is coming from any other user on the site.
    – user420667 Jan 31 '17 at 03:08

9 Answers9

171

demo: http://so.devilmaycode.it/jquery-convert-line-breaks-to-br-nl2br-equivalent

function nl2br (str, is_xhtml) {   
    var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br />' : '<br>';    
    return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1'+ breakTag +'$2');
}
Luca Filosofi
  • 30,905
  • 9
  • 70
  • 77
  • 5
    Thank you this works perfectly. Odd how this isn't an official function of jQuery. – gbhall May 27 '10 at 08:03
  • 4
    cause jQuery is not meant to replace native javascript function like replace, it is focused on CSS selector chaining and easy access! maybe in future version;-) – Luca Filosofi May 27 '10 at 08:08
  • 1
    Awesome. Helped me get past the problem with IE7 not supporting white-space: pre-wrap – Kevin Pauli Nov 10 '10 at 22:45
  • Wouldn't that regex mean if a line ends with ">" it wouldn't add the BR? I know in my HTML I use > but user generated content doesn't work so well with that... – Dave Stein Nov 08 '11 at 19:58
  • @DaveStein no I have tried this with both '>' and '>' and both times the line breaks are added. I think this function code is basically perfect :) – Jake Jun 09 '12 at 17:56
  • Neat! But what's with the `(str+'').replace()`?? why not just `str.replace()`? – designosis Jan 09 '13 at 11:52
  • @neokio: to be sure str is a string? – Luca Filosofi Jan 09 '13 at 15:21
  • Anybody else getting double
    's with this function? Seems like a similar issue to the php version, but I can't seem to fix it: http://stackoverflow.com/questions/11275006/double-line-breaks-with-pre-tag-and-nl2br
    – Adam Tal Mar 26 '16 at 19:22
  • It was not removing line breaks completely from my code instead it was always leaving behind line breaks and adding `
    ` i fixed it by removing the `$1` and `$2` from return statement like this: `return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, breakTag)`
    – Sheraz Ahmad Khilji Nov 10 '16 at 17:33
97

you can simply do:

textAreaContent=textAreaContent.replace(/\n/g,"<br>");
mck89
  • 18,918
  • 16
  • 89
  • 106
  • Cheers, this kind of worked, except it would treat multiple line breaks as a single line break. – gbhall May 27 '10 at 08:02
  • 4
    I've updated it and now it uses a regexp so if you want to treat multiple line breaks as a single br change the regexp with: /\n+/g – mck89 May 27 '10 at 08:05
  • Thank you. Hopefully someone will find your answer useful, but the function below works as well. I feel kind of bad that you're making more effort, but a function is more desirable. – gbhall May 27 '10 at 08:09
  • if you get the error "x.replace is not a function" then use x.toString().replace – Vörös Imi Aug 15 '19 at 12:18
39

In the spirit of changing the rendering instead of changing the content, the following CSS makes each newline behave like a <br>:

white-space: pre;
white-space: pre-line;

Why two rules: pre-line only affects newlines (thanks for the clue, @KevinPauli). IE6-7 and other old browsers fall back to the more extreme pre which also includes nowrap and renders multiple spaces. Details on these and other settings (pre-wrap) at mozilla and css-tricks (thanks @Sablefoste).

While I'm generally averse to the S.O. predilection for second-guessing the question rather than answering it, in this case replacing newlines with <br> markup may increase vulnerability to injection attack with unwashed user input. You're crossing a bright red line whenever you find yourself changing .text() calls to .html() which the literal question implies would have to be done. (Thanks @AlexS for highlighting this point.) Even if you rule out a security risk at the time, future changes could unwittingly introduce it. Instead, this CSS allows you to get hard line breaks without markup using the safer .text().

Bob Stein
  • 16,271
  • 10
  • 88
  • 101
  • 2
    Depending upon the case, this is the simplest solution, and really answers the question best. You might also consider any of the the other `white-space:` options, such as `pre-wrap`. See https://css-tricks.com/almanac/properties/w/whitespace/ – Sablefoste Oct 28 '16 at 14:16
  • This is really the best answer - string replacement solutions would mean the need to use `.html()` to set the content, which in turn would allow the user to insert arbitrary HTML unless you filter that out in advance. – Alex S Jul 01 '17 at 20:19
  • Good point about `.html()` danger @AlexS, tried to incorporate. – Bob Stein Jul 02 '17 at 17:15
30

Put this in your code (preferably in a general js functions library):

String.prototype.nl2br = function()
{
    return this.replace(/\n/g, "<br />");
}

Usage:

var myString = "test\ntest2";

myString.nl2br();

creating a string prototype function allows you to use this on any string.

jnl
  • 447
  • 4
  • 7
3

Solution

Use this code

jQuery.nl2br = function(varTest){
  return varTest.replace(/(\r\n|\n\r|\r|\n)/g, "<br>");
};
Ata ul Mustafa
  • 1,172
  • 12
  • 18
2

This JavaScript function considers whether to use insert or replace to handle the swap.

(Insert or replace HTML line breaks)

/**
 * This function is same as PHP's nl2br() with default parameters.
 *
 * @param {string} str Input text
 * @param {boolean} replaceMode Use replace instead of insert
 * @param {boolean} isXhtml Use XHTML 
 * @return {string} Filtered text
 */
function nl2br (str, replaceMode, isXhtml) {

  var breakTag = (isXhtml) ? '<br />' : '<br>';
  var replaceStr = (replaceMode) ? '$1'+ breakTag : '$1'+ breakTag +'$2';
  return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, replaceStr);
}

Demo - JSFiddle

JavaScript nl2br & br2nl functions

Nick Tsai
  • 3,799
  • 33
  • 36
1

I wrote a little jQuery extension for this:

$.fn.nl2brText = function (sText) {
    var bReturnValue = 'undefined' == typeof sText;
    if(bReturnValue) {
        sText = $('<pre>').html(this.html().replace(/<br[^>]*>/i, '\n')).text();
    }
    var aElms = [];
    sText.split(/\r\n|\r|\n/).forEach(function(sSubstring) {
        if(aElms.length) {
            aElms.push(document.createElement('br'));
        }
        aElms.push(document.createTextNode(sSubstring));
    });
    var $aElms = $(aElms);
    if(bReturnValue) {
        return $aElms;
    }
    return this.empty().append($aElms);
};
0

to improve @Luca Filosofi's accepted answer,

if needed, changing the beginning clause of this regex to be /([^>[\s]?\r\n]?) will also ingore the cases where the newline comes after a tag AND some whitespace, instead of just a tag immediately followed by a newline

phlare
  • 318
  • 3
  • 11
0

Another way to insert text from a textarea in the DOM keeping the line breaks is to use the Node.innerText property that represents the rendered text content of a node and its descendants.

As a getter, it approximates the text the user would get if they highlighted the contents of the element with the cursor and then copied to the clipboard.

The property became standard in 2016 and is well supported by modern browsers. Can I Use: 97% global coverage when I posted this answer.

Volo
  • 1
  • 1