contentEditable - Firefox <br /> tag
Asked Answered
G

4

13

Firefox inserts a <br /> tag on press enter whereas the other browsers are adding either a <p> or <div>. I know that chrome and safari are inserting the same tag of the firstchild of the contentEditable div. So do Firefox, however, if the first tag's innerHTML is empty firefox is just ignoring the tag and creating a new line by pushing the default node in the second line and writes directly inside the editor instead of inside a child node. So basically, I want Firefox to write inside the given tag and continue to insert that kind of node on each press on enter. How can it be done? Any suggestions?

Gynaeceum answered 18/4, 2011 at 15:55 Comment(2)
Please add your solution as answer.Atavistic
I will but I have to wait 24 hours :)Gynaeceum
G
4

I've found the solution :) In order to make this work, you've to give an id to the caret's parent element. Then you can use the following code. Please note that I get the browsernName from c# and put it into a hidden field. That's why I equaled it to "firefox". The following code is tested with FF 3.6 and it works perfectly. The only thing is that you'll have to check the caret's parent element and if it is not equal to the current row's id, then you'll have to place the caret inside the current row by using a selection function. Also, perform this code on the keyup event and make sure that if you perform some other codes on the keyup event, put this code at the end of it! Anways, enjoy :)

// The code works good in the following cases:
// 1) If there is text inside the editor and the user selects the whole text
//    and replace it with a single character, the <p> tag will be placed and the
//    text will place inside the p tag
// 2) If the user selects the whole code and deletes it and begins to type again
// 3) If the user types normally and press enter 
// NB: Please note me if you find any bug

if (browserName == "firefox") {
    //remove all br tags
    var brs = txteditor.getElementsByTagName("br");
    for (var i = 0; i < brs.length; i++) { brs[i].parentNode.removeChild(brs[i]); }
    //check whether there is a p tag inside
    var para = txteditor.getElementsByTagName("p");
    if (para.length == 0) {
        var inner = txteditor.innerHTML.replace(/^\s+|\s+$/g, '');
        var str = (inner == "") ? "&#8203;" : txteditor.innerHTML;
        var nText = "<p id=\"" + cRow + "\">" + str + "</p>";
        // in order to prevent a dublicate row clear inside the text editor
        txteditor.innerHTML = "";
        document.execCommand('insertHTML', false, nText);
    } else {
        // always make sure that the current row's innerHTML is never empty
        if (document.getElementById(cRow).innerHTML == "")
            document.getElementById(cRow).innerHTML = "&#8203;";
    }
}
Gynaeceum answered 19/4, 2011 at 19:26 Comment(2)
I was just going to suggest a nasty little IF browser solution too. Thanks!Priddy
Thanks for the script! But for me it fails with a ReferenceError: cRow is not defined - can you please fix this?Crate
T
2

Try inserting a <p></p> inside your element. Then almost certainly every newline will be a new paragraph.

Trstram answered 18/4, 2011 at 15:58 Comment(4)
That's what I said actually, but Firefox ignores it when inside the <p></p> is empty or when the user hits the first keyGynaeceum
I've found the solution. First of all, when page loads follow these steps: 1) If there is focus on contenteditable div, focusout it. 2) If your texteditor has no initial tags, insert whatever you want, either a <p> or <div> tag or whatever. Now whenever the user deletes all the content, the text editor will automatically create a <p> tag. So basically the when you give focus in firefox on the page load, the bug occurs, when you don't it doesn't :) Hope those suffering from the same bug will enjoyGynaeceum
@Gynaeceum Interesting. The secret may be that the carret (editing point of the cursor) is initiated before the first tag by default. When you focus it (or unfocus and focus if needed) then the carret is placed inside the first element (if possible). - Interesting question: what happens when you have <div><p></p></div> inside the editable element. Will the cursor be placed in front of or inside the p tag? :)Trstram
If you have focus on the editor when the page loads then the caret will be placed in front of the div. Else if you let the user to focus then it will focus inside the <p> tag. However, whenever you press enter the <p> tags will be placed inside the <div> tag. Therefore, I guess Firefox is inserting the same type of node of whatever the deepest node is and is not being interested in the rest of the tree.Gynaeceum
E
0

If you change the contenteditable element to be a <span> instead of a <div> the new line will be made with a <br>. I haven't tested this with other elements, but it would be interesting to see how different elements would behave.

A <span> element can be styled with display: block to make it look like a <div> element.

Ezzell answered 3/8, 2020 at 9:58 Comment(1)
I tried this and it seemed to work... until I tried to copy paste something and suddenly got span within a span :( Anyone have a solution for this?Hasa
U
0

I met with a similar problem causing extra <br> in Firefox, but didn't find any <p> or <div>. The <br> was inserted either when the content is empty or after pressing space.

Anyway, I tried to solve it by MutationObserver API. It didn't work perfectly but I failed to find other solutions that meet my requirement.

if (navigator.userAgent.includes('Firefox')) {

    const observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        // when a <br> inserted
        if (mutation.addedNodes.length === 1 && mutation.addedNodes[0].tagName === 'BR') {
          // if at the beginning, remove it
          if (mutation.previousSibling === null) return mutation.addedNodes[0].remove()
          // or if after a space, remove it and add a space
          // since it seems Firefox need the <br> to keep that space
          if (mutation.previousSibling.nodeValue?.endsWith(' ')) {
            mutation.target.insertAdjacentText('beforeend', ' ')
            mutation.addedNodes[0].remove()
          }
        }
      })
    })

    observer.observe(contentEditableDiv, { childList: true })

}

Side effects:

  • Must input twice to add a new line, or to add a space sometimes
  • Unable to make the content a single new line

The problem is also mentioned as a bug in Firefox issue tracker: https://bugzilla.mozilla.org/show_bug.cgi?id=1615852

Extract that may help:

<br> elements are required when:

  • block elements are empty, for making them non-zero height and to put the first line for good caret position
  • text ends by a collapsible white-space, to make it visible
Uvula answered 1/7, 2024 at 9:36 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.