djt
djt

Reputation: 7535

JQuery - Paste event, stripping rich text

I have a contentEditable field where I'd like to do the following. When a user pastse rich text into the field (microsoft word, or otherwise) I'd like to strip all the rich text, but retain the line breaks.

My thinking was: If you paste rich text into a plain <texarea>, it removes all the formatting and retains the breaks (created by explicit new lines, as well as block level elements). I'd like to somehow simulate this. In other words, create a temporary textarea, intercept the paste event, apply it to the Textarea, retrieve the results, and insert them back into the original Content Editable field.

However, i haven't found a way to simulate this. If I paste the contents into a textarea via jquery, it seems to retan all the rich text formatting when I try and copy it from there, back to the original fields

Upvotes: 3

Views: 2849

Answers (1)

Alvaro Montoro
Alvaro Montoro

Reputation: 29675

You could achieve something like this without needing a textarea, just processing the code in the content editable div every time that there is a change in its value, and removing all the tags but the paragraphs and line breaks.

The idea would be that every time that the content changes in the div (listen to the input event):

  • Replace in the inner HTML all </p> and <br> for non-HTML tokens (e.g.: [p] and [br] respectively).
  • Remove all HTML tags (you can do it with .text())
  • Replace the tokens that you used for their equivalents (and their openings!)
  • Wrap everything between <p> and </p>.

Here a simple demo:

$("#editable").on("input", function() {

  $this = $(this);

  // replace all br and closing p tags with special tokens
  $this.html($this.html().replace(/\<\/p\>/g,"[p]").replace(/\<br\>/g,"[br]"));

  // remove all the tags, and then replace the tokens for their original values
  $this.html("<p>" + $this.text().replace(/\[p\]/g, "</p><p>").replace(/\[br\]/g,"<br>") + "</p>");

});
div#editable, div#demo {
    border:1px solid gray;
    padding:6px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

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

<h3>Demo</h3>
<p>Copy this code and paste it on the editable div above:</p>
<div id="demo">
  <p>This <b>is</b> <i>a</i> styled paragraph.</p>
  <p>&nbsp;</p>
  <p>The <span style="font-weight:bold">above paragraph</span> is empty.</p>
  <p>And this is a new paragraph…<br>with a line break!</p>
</div>

You can also see it running on this JSFiddle: http://jsfiddle.net/v5rae96w/

I tried this solution with MS Word and HTML and it works fine. But it has one issue: it only does line breaks with p and br (that works nicely with MS Word and other word processors). If the user copies HTML like div (or other block elements that cause a line break), it won't work as nicely. If you need to break with all block elements, this solution may require some changes.


To fix that, you could replace all the block tags with p (or div or the element that you want), by indicating it on the regular expression:

$this.html().replace(/(\<\/p\>|\<\/h1\>|\<\/h2\>|\<\/div\>)/gi,"[p]")

As you can see here:

$("#editable").on("input", function() {
    
    $this = $(this);

    // replace all closing block tags with special token
    $this.html($this.html().replace(/(\<\/p\>|\<\/h1\>|\<\/h2\>|\<\/h3\>|\<\/h4\>|\<\/h5\>|\<\/h6\>|\<\/div\>)/gi,"[p]").replace(/\<br\>/gi,"[br]"));
    
    // remove all the tags
    $this.html("<p>" + $this.text().replace(/\[p\]/g,"</div><p>").replace(/\[br\]/g,"<br>") + "</p>");

});
div#editable, div#demo {
    border:1px solid gray;
    padding:6px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div contenteditable="true" id="editable"></div>

<div>
    <h3>Demo</h3>
    <p>Copy this code and paste it on the editable div above:</p>
    <div id="demo">
        <p>This <b>is</b> <i>a</i> styled paragraph.</p>
        <p> </p>
        <p>The <span style="font-weight:bold">above paragraph</span> is empty.</p>
        <p>And this is a new paragraph…<br>with a line break!</p>
    </div>
</div>

Or on this JSFiddle: http://jsfiddle.net/v5rae96w/1/

Upvotes: 2

Related Questions