Deets McGeets
Deets McGeets

Reputation: 6377

Sanitizing paste event using jQuery in contentEditable div

I am trying to sanitize a paste in a contentEditable div. That is, the code should look something like the following:

$('#content').bind('paste',function(e)
{
    // Ensure pasted markup is valid
});

Ideally, I would be able to parse through the pasted text and re-format it in a way that is appropriate to the site, but I don't know how to do this.

Alternatively, I would be comfortable pasting as plain text (as opposed to HTML), but I don't know how to do this either.

I am slightly less comfortable with the solution of having a box pop up with a textarea, asking the user to paste into this text area and then putting the text into the content at the previous cursor position. I know how to do this, but want to avoid it.

And I am completely uncomfortable with just preventing the user from pasting by using e.preventDefault().

Upvotes: 5

Views: 9485

Answers (4)

James Williams
James Williams

Reputation: 19

New Answer!

The "new" plaintext-only contenteditable value can now be used to prevent HTML from being pasted. This allows users to only enter text inside the div.

Snippet:

<style> 
 div {
 outline: .1rem solid #000;
 }
 </style>
 <div contenteditable="plaintext-only">
 This is editable
 </div>
 <div contenteditable="true">
 This is also editable, this does not sanitize HTML elements.
 </div>


<a href="https://1v1.lol">Link</a>


<p>
Try to drag the link above to the contenteditable elements.
</p>

Note: If you have existing HTML inside of the div, that cannot be edited.

EDIT

To update paste content based on if HTML is detected, use the following code,

document.querySelector('[contenteditable]').onpaste = function (event) {
   var data = (event.clipboardData || window.clipboardData).getData('text');
   
   if (/<([^]+)([\s]+)([^]+)(?:(>|<))/.exec(data) !== null) {
      event.preventDefault();
      alert('This is HTML');
      return false;
  }
}
<div contenteditable></div>

While not perfect nor a great solution, it does get the job done nonetheless. If this does not help you, I recommend visiting here.

Upvotes: 1

Etienne Martin
Etienne Martin

Reputation: 11569

I've been able to achieve this with the rangy javascript library allowing me to save and restore the caret position after sanitizing the content.

https://github.com/timdown/rangy

Tested in chrome and safari.

$("#content").on('paste', function(){
    sanitize();
});

function sanitize(){
    setTimeout(function(){

        var savedSelection = rangy.saveSelection();

        $("#content *").removeAttr("style"); // Do your parsing here.

        rangy.restoreSelection(savedSelection);         

    }, 0);  
}

Upvotes: 3

Daniel
Daniel

Reputation: 11

Could you not verify the content once it is already in the field some how? Let the content paste in, save the original content first and if the new content is not valid, replace it back with the old. It's just a theory but I'm just going to have to experiment too for now.

Upvotes: 0

Tim Down
Tim Down

Reputation: 324507

There is no direct way in most browsers to access the content pasted before it goes into the DOM. There is, however, a fairly elaborate way to do this that only works for pastes triggered by the keyboard. See my answer here:

JavaScript get clipboard data on paste event (Cross browser)

Upvotes: 2

Related Questions