12

I'm trying to create a HTML5 contenteditable div, which only accept a plain text. I'm using html and jQuery below:

HTML

<div contenteditable="true"></div>

jQuery

(function () {
   $('[contenteditable]').on('paste', function (e) {
     e.preventDefault();
     var text = null;
     text = (e.originalEvent || e).clipboardData.getData('text/plain') || prompt('Paste Your Text Here');
     document.execCommand("insertText", false, text);
   });
 });

But it's not working for all browsers. getData not support in Internet Explorer browser. I tried a lot of solutions mention here on stackoverflow, But none worked for me.

I also tried

(function () {
  $('[contenteditable]').on('paste', function (e) {
    e.preventDefault();
    var text = null;

    if (window.clipboardData && clipboardData.setData) {
      text = window.clipboardData.getData('text');
    } else {
      text = (e.originalEvent || e).clipboardData.getData('text/plain') || prompt('Paste Your Text Here');
    }
    document.execCommand("insertText", false, text);
  });
});

But in that case document.execCommand("insertText", false, text); is not working for IE.

Is there any way to make it possible to accept data after filter HTML tags, So that anyone enters data in editable div by type, paste, drop, or any other way. It should display it as text.

Gaurav Gandhi
  • 3,041
  • 2
  • 27
  • 40
Tarun
  • 1,888
  • 3
  • 18
  • 30
  • Look at using this concept: `$('

    Hi, I\'m HTML

    ').text();`. That should give you `Hi, I'm HTML`.
    – Chris Peters Jun 25 '14 at 12:05
  • I guess It's the different thing you are talking about. In our case we have to get pasted content. Convert it to plain text and than display it in div. – Tarun Jun 25 '14 at 12:20
  • 1
    My comment covers the "convert it to plain text" part. I don't have any experience working with the JavaScript API for what you're trying to do, but as I read the question, I have trouble understanding what you're having trouble with. For example, is "_now_ working for IE" supposed to read as, "_not_ working for IE?" – Chris Peters Jun 25 '14 at 13:18
  • 5
    Just add `contendeditable='plaintext-only'` – Dustin Scott Aug 07 '14 at 15:15
  • 5
    Unfortunately `contenteditable='plaintext-only'` seems to be a webkit-only feature. – geo Jan 14 '15 at 09:44
  • Pasting is not the only way to get content into a contenteditable. Don't forget drag+drop, that completely circumvents checking for pasting. – LB-- Dec 24 '15 at 13:37
  • 1
    `plaintext-only` might hopefully be standardized one day: https://github.com/w3c/editing/issues/162 – BenMorel Aug 31 '18 at 23:45

3 Answers3

8

Try this:

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

Reference: https://w3c.github.io/editing/contentEditable.html#h-contenteditable

Pang
  • 9,564
  • 146
  • 81
  • 122
Indiana
  • 313
  • 4
  • 8
  • 9
    Webkit only I guess. The spec only allow for true, false and inherit. [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable) (3 specs inside) – aloisdg May 30 '17 at 09:58
7

Being not a big fan of jQuery, my solution will not make any use of it. Anyway here it goes (it should anyway work, as pure javascript):

function convertToPlaintext() {
  var textContent = this.textContent;
  this.innerHTML = "";
  this.textContent = textContent;
}

var contentEditableNodes = document.querySelectorAll('[contenteditable]');

[].forEach.call(contentEditableNodes, function(div) {
  div.addEventListener("input", convertToPlaintext, false);
});
<div contenteditable="true" style="border: dashed 1px grey">Editable</div>

Note that this solution is severely limited in that the caret will typically jump to the start of the text on every input event.

GKFX
  • 1,386
  • 1
  • 11
  • 30
humanityANDpeace
  • 4,350
  • 3
  • 37
  • 63
  • To fix the cursor issue you can use rangy: before: `let range = rangy.getSelection().getRangeAt(0)` after: `if (el.hasChildNodes()) { newRange.setStart(el.childNodes[0], Math.min(range.startOffset)); newRange.collapse(true); rangy.getSelection().setSingleRange(newRange); }` – Post Self Mar 31 '20 at 10:48
  • 1
    An alternative is to only target the `paste` event – Post Self Mar 31 '20 at 13:40
0

In inspired by @humanityANDpeace answer, I came up with this:

function convertToPlaintext() {
  this.innerHTML = this.innerText.replace(/(?:\r\n|\r|\n)/g, '<br>');
  this.focus();
  document.execCommand('selectAll', false, null);
  document.getSelection().collapseToEnd();}

called by:

ele.addEventListener("input", convertToPlaintext, false);

where 'ele' is your contentEditable div. This will replace any line breaks with <br> and keep the cursor at the end of text as you type. My primary motive was to replace all div tags that 'contentEditable' adds but still retain line breaks.

The 'replace line breaks' came from:https://stackoverflow.com/a/784547/2677034

user2677034
  • 624
  • 10
  • 20