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
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> </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/
Related
I am having trouble with some code for a chrome extension. The code is supposed to replace a word with another one. It does this, however, I would only like it to replace a word if it is within certain tags such as <p></p> or header tags. At the moment it replaces all the words in the HTML file within the <body></body>. This sometimes interferes with the HTML code and can break certain features of a website. Here's what I have currently.
document.body.innerHTML = document.body.innerHTML.replace(newRegExp("old", "g"), "new");
Thank you for the help!
So just loop over all the elements that you care about and do the replacement on those elements only.
// Get all the elements that you care about into an array
let elements = Array.prototype.slice.call(document.querySelectorAll("p, header"));
// Loop over the items in the array
elements.forEach(function(el){
// Do the replace on the element
el.textContent = el.textContent.replace(/text/g, "letters");
});
<header>This is some text in a header</header>
<h1>This is some text in an h1</h1>
<div>This is some text in a div</div>
<p>This is some text in a p</p>
<div>This is some text in a div</div>
<div>This is some text in a div
<p>This text is inside of a p with lots of text</p>
</div>
In an Html file that I have, there is a paragraph tag that basically looks like this:
<p class="col-sm-8 form-control-static wordwrap">
Hey
What's
Up
</p>
The contents of this paragraph are grabbed from a textarea that a user fills out and the value of this textarea is grabbed via jquery and filled into this element.
The output looks like this: Hey What's Up
This paragraph tag ignores the newlines within the paragraph, so the paragraph displays all on one line. Due to the format and layout of the project, I can't necessarily change the html source. I was wondering if there was a way to change this exact element to be:
<pre class="col-sm-8 form-control-static wordwrap">
Hey
What's
Up
</pre>
using only javascript. Is this possible? This is so my output will keep the newlines.
I think you are looking for something like this. you tagged jquery so I used that but this could be done in vanilla js too.
I linked to a onkeyup event if you wanted to change to use the button only if you wanted
$(document).ready(function(){
function updateContent() {
$('#p1').html($('#source').val());
}
$('#update').on('click', function(e){
updateContent();
// add other stuff here
// for only the click event
})
$('#source').on('keyup', updateContent);
})
button {
display:block;
}
#source {
height:100px;
}
#p1{
white-space:pre;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="source" placeholder="Update content and click 'update'">new content
add line breaks and <p>html markup</p>
</textarea>
<button id="update" >Update</button>
<p id="p1">THIS WILL CHANGE!</p>
It is very simple and has been asked before... BUT here it is, using DOM:
document.getElementById("p1").innerHTML = "<p>This</p><p>Has</p><p>Changed!</p>";
<p id="p1">THIS WILL CHANGE!</p>
So your piece of code you need is:
document.getElementById("p1").innerHTML = "New text!";
EDIT
This is simpler, easier and more browser friendly than using <pre> tags. Therefore, I would highly recommend you to use this instead.
When I'm trying to change document.documentElement.innerHTML using the innerHTML of a textarea like this:
document.documentElement.innerHTML = document.querySelector('#mytextarea').innerHTML
The innerHTML of #mytextarea is not used as actual HTML to change the DOM, but as plain text.
For example: if the innerHTML of #mytextarea is <p>A paragraph</p>.
Then the document after loading looks like: <p>A paragraph</p> instead of A paragraph
How should I do it so the value inside the #mytextarea could be used to change the DOM? (ex. appending new elements)
Use .value to get the contents of a textarea without it being encoded.
document.getElementById("documentElement").innerHTML = document.querySelector('#mytextarea').value;
<textarea id="mytextarea">
<p>A paragraph</p>
</textarea>
<div id="documentElement">
</div>
You can easily achieve this without the use of any JavaScript. You just have to insert special characters into your HTML code.
<p>A paragraph</p>
That weird code will show up as
<p>A paragraph</p>
If you don't know the codes, just use this: HTML Encoder
EDIT:
They are called HTML escape characters, or, HTML entities. Here is a list of a lot of them: List
I have to replace some characters in all a div, but when I run the code, the function replaces me also the html tags characters
my code is:
$("#main").children().each(function() {
$(this).html($(this).html().replace(/s/g, "K"));
})
<div id="main">
<p>Some contents that will be replaced... <span>this will not be in a span tag :(</span></p>
</div>
result:
<div id="main">
<p>Kome contentK that will be replaced... <Kpan>this will not be in a Kpan tag :(</Kpan></p>
</div>
If your goal is to preserve all the markup within the div but replace text within all those tags, that's difficult. You need to find just the text nodes and no other nodes and do the replacement within each of the text nodes individually.
This question may help: How do I select text nodes with jQuery?
I've crated html template file, I put some elements inside that template are non editable.
template.html contains
<body>
<div>This is a sample template </div>
<div contenteditable="false" style="color:red">Read Only Text</div>
</body>
on inserting this template file into the textarea the second div is editable, while inspecting over that div I've seen that the attribute contenteditable="false" is not there on insert, but its there on the preview before the insert of template.
Any help gratefully received!
From this page: http://www.tinymce.com/tryit/noneditable_content.php
Its using a textarea:
<textarea name="content" style="width:100%">
<p>Text with a <span class="mceNonEditable">[non editable]</span> inline element.</p>
<p class="mceNonEditable">Noneditable text block with <span class="mceEditable">[editable]</span> items within.</p>
<p>Text with tokens that isn't [[editable]] since they match the noneditabe_regexp.</p>
</textarea>
The key here is putting a class of mceNonEditable in your element:
span class="mceNonEditable"
Then whatever non-editable content you have, wrap it in greater than and less than:
>You cannot edit me<
Then finally close the element:
/span
I think you can also change the mode (in the example they're using textareas, so I guess you can also use divs or spans) when initializing tinymce:
tinyMCE.init({
mode : "textareas",
noneditable_regexp: /\[\[[^\]]+\]\]/g
});
There's also noneditable_regexp which lets you specify a regular expression of non-editable contents.
I think this is easier than using html entities.
I haven't actually tried it but that's the way I interpret the example in the page.