Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paste fix for contenteditable

I'm running a script to sanitize pasted text in a div with contenteditable.

It's working pretty good, but in FF the line-breaks are removed if the text is copied to the same or between the divs.

Any solution for that?
If I paste text from a different source the line-breaks are intact.
I'm also open to different solutions than the one below.

// Paste fix for contenteditable
$(document).on('paste', '[contenteditable]', function (e) {
    e.preventDefault();

    if (window.clipboardData) {
        content = window.clipboardData.getData('Text');        
        if (window.getSelection) {
            var selObj = window.getSelection();
            var selRange = selObj.getRangeAt(0);
            selRange.deleteContents();                
            selRange.insertNode(document.createTextNode(content));
        }
    } else if (e.originalEvent.clipboardData) {
        content = (e.originalEvent || e).clipboardData.getData('text/plain');
        document.execCommand('insertText', false, content);
    }        
});
div {
  white-space: pre-wrap;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable="true">Copy
and
paste
this
back in the same box or the one below. Where do they line-breaks go in FF?</div>
<div contenteditable="true">Copy
and
paste
this
back in the same box or the one above. Where do they line-breaks go FF?</div>
like image 310
SeaBass Avatar asked Aug 09 '18 03:08

SeaBass


People also ask

How do you focus on Contenteditable?

Changing your tabIndex to >= 0 will let you focus on the elements.

How do I stop Enter key in Contenteditable?

To prevent contenteditable element from adding div on pressing enter with Chrome and JavaScript, we can listen for the keydown event on the contenteditable element and prevent the default behavior when Enter is pressed. to add a contenteditable div. document. addEventListener("keydown", (event) => { if (event.

Should you use Contenteditable?

Would I be shooting myself in the foot by using a div with attribute contentEditable="true" as a text field rather than a textarea? If you want a text field, use a textarea, it's less likely to screw things up. Only use a contentEditable div when you need the ability to format the text. It would not work with forms.


1 Answers

As promised, here is a working solution of such implementation discussed in question's comments.

While working with Selection and Range API (https://developer.mozilla.org/en-US/docs/Web/API/Range), i found that Range object has a toString() method and i thought to test it to see if newlines were trimmed here, before, or later.

Fortunatly, i found out that the toString() method in FF Range object doesn't trim out newlines.

According to that, here is my code and fiddle to override default copy function, overwriting (on copy event) what's inside the clipboard.

$(document).on('copy', '[contenteditable]', function (e) {
  e = e.originalEvent;
  var selectedText = window.getSelection();
  console.log("original copied text\n--------\n", selectedText.toString());
  var range = selectedText.getRangeAt(0);
  var selectedTextReplacement = range.toString()
  console.log("replacement in clipboard\n--------\n", selectedTextReplacement);
  e.clipboardData.setData('text/plain', selectedTextReplacement);
  e.preventDefault(); // default behaviour is to copy any selected text
});



// Paste fix for contenteditable
$(document).on('paste', '[contenteditable]', function (e) {
    e.preventDefault();

    if (window.clipboardData) {
        content = window.clipboardData.getData('Text');        
        if (window.getSelection) {
            var selObj = window.getSelection();
            var selRange = selObj.getRangeAt(0);
            selRange.deleteContents();                
            selRange.insertNode(document.createTextNode(content));
        }
    } else if (e.originalEvent.clipboardData) {
        content = (e.originalEvent || e).clipboardData.getData('text/plain');
        document.execCommand('insertText', false, content);
    }        
});
div {
  white-space: pre-wrap;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable="true">Copy
and
paste
this
back in the same box or the one below. Where do they line-breaks go in FF?</div>
<div contenteditable="true">Copy
and
paste
this
back in the same box or the one above. Where do they line-breaks go FF?</div>

I also made rough test with edge and chrome, and that override "doesn't mess them up", so maybe you can keep it to have control over what they are doing when something is copied.

At the end of all, i still have a question that keeps yelling in my mind and it is: Why use contenteditable div instead of textarea if you don't want html into your frontend element?

like image 171
Giacomo Penuti Avatar answered Oct 09 '22 17:10

Giacomo Penuti