Skip to content Skip to sidebar Skip to footer

How To Force
Line Break In Firefox Contenteditable

I have a JavaScript WYSIWYG editor (not unlike CKEditor) running on a site. It has a setting that makes IE create line breaks when you press Enter in the editor. That w

Solution 1:

From looking at the standards, it looks like this action is the way it is supposed to be handled. Blocks are broken when no modifier is set on an enter key, and <br>'s are used when shift is pressed. [Source].

That said, that does not solve your problem, so let's work on that. This line should do

document.execCommand('insertBrOnReturn', false, true);

Set's it so that when you just hit return, it only puts in a <br> tag. This is only supported by FF, so it shouldn't affect anything on IE. Don't know about other browsers though.

Note: If the user hits Enter a second time, without typing anything, it creates a new paragraph tag no matter what. To prevent this, you can catch the Enter using the keypress event and stop it, or you could insert in a &nbsp; before you continue with the event (what I'd recommend).

The tough part for you with this note is checking on the state of the element on keypress. The lazy solution (and the one I would recommend unless it's important to not do this) is to just insert it before every Enter key. If you want to do it the other way, I would check the .innerHTML for the element and see if the last few characters (without trimming the content) are <br/> (so maybe a regex match on /\<br\s?\/?\>$/).

Solution 2:

Consider this:

HTML:

<div contentEditable id="input"></div>

CSS:

#input {
    border: 3px solid #07c;
    width: 300px;
    height: 200px;
    white-space: pre;
}

JavaScript:

$( input ).keypress( function ( e ) {
    var sel, node, offset, text, textBefore, textAfter, range;

    sel = window.getSelection();

    // the node that contains the caret
    node = sel.anchorNode;

    // if ENTER was pressed while the caret was inside the input fieldif ( node.parentNode === input && e.keyCode === 13 ) {

        // prevent the browsers from inserting <div>, <p>, or <br> on their own
        e.preventDefault();

        // the caret position inside the node
        offset = sel.anchorOffset;        

        // insert a '\n' character at that position
        text = node.textContent;
        textBefore = text.slice( 0, offset );
        textAfter = text.slice( offset ) || ' ';
        node.textContent = textBefore + '\n' + textAfter;

        // position the caret after that new-line characterrange = document.createRange();
        range.setStart( node, offset + 1 );
        range.setEnd( node, offset + 1 );

        // update the selection
        sel.removeAllRanges();
        sel.addRange( range );
    }
});

Live demo:http://jsfiddle.net/FhEf6/3/

I use '\n' characters instead of BR elements (the DIV has white-space:pre set). As a result, no BR, or P elements are added to the DIV when ENTER is pressed. There is only one TextNode inside the DIV at all times and all new-lines are represented by '\n' characters.

Solution 3:

// not exactly what you asked but this function may be interesting when you want to force // the other browsers opera,chrome,internet explorer to insert a regular BR on enter. // could be better written but works so far

enterBR = function(e)
{   
    var iframeElement=parent.window.$("wysiwyg"+n);
    e = e || iframeElement.contentWindow.event;                 // eventhandler inside iframe (!)var keyCode= e.keyCode? e.keyCode: e.which;                 // req. for IE below v8if (keyCode==13)                                // if enter key gets pressed
{ 
     if(IE)      // internet explorer
     { e.preventDefault?e.preventDefault():e.returnValue=false; // block default handling ( i tell yo!)
       iframeElement.contentDocument.selection.createRange().pasteHTML("<br/>");  // insert a br tag
     }

     if(OP||CR)  // opera and chrome
     { 
      iframeElement.contentWindow.document.execCommand('formatBlock',false,'p');
     } // creates a paragraph around a br tag <p><br/></p> replace with regExp//here the regExp to replace the unneeded paragraph tags and a detection if you have whatever xhtml compatible <br/>'s or not.HTML=iframeElement.contentWindow.document.body.innerHTML;
    HTML=HTML.replace(/<p><br([\/]?)><\/p>/gi,'<br/>');
    HTML=HTML.replace(/<br(.*?|\s*[^\/]+[^>]?)([\/]?)>/mgi,"<br$1/>\n"); 

}
  returnfalse;
}

// finaly add an eventlistener. remember this is used inside an iframe so dont forget to advise the script to work from one dom layer above (parent.window)// but i think it can be easily rewritten for contenteditable div or something...addEventListener(parent.window.$("mywysiwygeditor").contentDocument,'keypress',enterBR);

// hf

Solution 4:

My solution works perfectly in Firefox, although it came around quite unexpectedly! I've also tested it in Edge and Chrome. It's based on the answer of @Ktash, replacing the nbsp with three disappearing nodes: an empty span (with a class), a <br> in the middle and a span containing &nbsp;.

JS:

var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
var isChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;

document.execCommand('insertBrOnReturn', false, true);

var elements = document.getElementsByClassName('editable');
Array.from(elements).forEach( (el) => {
    el.addEventListener('keydown',function(e) {
        if (e.which == 13) {
            if (isFirefox) {
                document.execCommand('insertHTML', false, '<span class="nbsp-break"></span><br><span>&nbsp;</span>');
                e.preventDefault();
            } elseif (!isChrome) {
                document.execCommand('insertText', true, '\r\n');
                document.execCommand('insertHTML', false, "<br>");
                e.preventDefault();
            }
        }
    });

    if (isFirefox) {
        el.addEventListener('input',function(e) {
            var elements = document.getElementsByClassName('nbsp-break');
            Array.from(elements).forEach( (el) => {
                el.parentNode.removeChild(el.nextSibling.nextSibling);
                el.parentNode.removeChild(el);
            });
        });
    }
});

CSS:

.nbsp-break + br + span {
    font-size: 0;
}

Post a Comment for "How To Force
Line Break In Firefox Contenteditable"