Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make HTML5 contenteditable div allowing only text in firefox?

I want to make div with contentEditable attribute which is allowing only text. It's easily achievable in Chrome by using:

<div contenteditable="plaintext-only"></div>

However it doesn't work in Firefox. Is there a way how to make text-only contenteditable div in Firefox ? I know it is possible, because Google Plus has such div, but I don't know how they do it.

like image 742
Frodik Avatar asked Jan 18 '14 15:01

Frodik


People also ask

How do I make content editable?

To edit the content in HTML, we will use contenteditable attribute. The contenteditable is used to specify whether the element's content is editable by the user or not. This attribute has two values. true: If the value of the contenteditable attribute is set to true then the element is editable.

How do I make a text field editable in HTML?

You can set the HTML5 contenteditable attribute with the value true (i.e. contentEditable="true" ) to make an element editable in HTML, such as <div> or <p> element.

What is false about Contenteditable attribute?

The contentEditable property of the HTMLElement interface specifies whether or not the element is editable. This enumerated attribute can have the following values: ' true ' indicates that the element is contenteditable . ' false ' indicates that the element cannot be edited.

Is Contenteditable safe to use?

Its totally secure. The contenteditable attribute is an enumerated attribute whose keywords are the empty string, true, and false.


2 Answers

I ran into this problem myself. Here is my solution which I have tested in Firefox and Chrome:

Ensure the contenteditable div has the css white-space: pre, pre-line or pre-wrap so that it displays \n as new lines.

Override the "enter" key so that when we are typing, it does not create any <div> or <br> tags

myDiv.addEventListener("keydown", e => {
    //override pressing enter in contenteditable
    if (e.keyCode == 13)
    {
        //don't automatically put in divs
        e.preventDefault();
        e.stopPropagation();
        //insert newline
        insertTextAtSelection(myDiv, "\n");
    }
});

Secondly, override the paste event to only ever fetch the plaintext

//override paste
myDiv.addEventListener("paste", e => {
    //cancel paste
    e.preventDefault();
    //get plaintext from clipboard
    let text = (e.originalEvent || e).clipboardData.getData('text/plain');
    //insert text manually
    insertTextAtSelection(myDiv, text);
});

And here is the supporting function which inserts text into the textContent of a div, and returns the cursor to the proper position afterwards.

function insertTextAtSelection(div, txt) {
    //get selection area so we can position insert
    let sel = window.getSelection();
    let text = div.textContent;
    let before = Math.min(sel.focusOffset, sel.anchorOffset);
    let after = Math.max(sel.focusOffset, sel.anchorOffset);
    //ensure string ends with \n so it displays properly
    let afterStr = text.substring(after);
    if (afterStr == "") afterStr = "\n";
    //insert content
    div.textContent = text.substring(0, before) + txt + afterStr;
    //restore cursor at correct position
    sel.removeAllRanges();
    let range = document.createRange();
    //childNodes[0] should be all the text
    range.setStart(div.childNodes[0], before + txt.length);
    range.setEnd(div.childNodes[0], before + txt.length);
    sel.addRange(range);
}

https://jsfiddle.net/1te5hwv0/

like image 107
Manstie Avatar answered Nov 15 '22 23:11

Manstie


Sadly, you can’t. As this answer points out the spec only specifies true, false and inherit as valid parameters. The subject seems to have been discussed but if I’m not mistaken only Webkit implements support for plaintext-only.

like image 34
polarblau Avatar answered Nov 16 '22 00:11

polarblau