I'm making a comment box using a contenteditable div, but I want to remove formatting from text a user might copy/paste into it (also no CTRL+B or CTRL+I shortcuts allowed either). Only "approved" formatting ("tagged" names, URLs, etc).
Originally I went the regex route but was informed regex + html is not a good approach, so I then tried using jQuery/DOM manipulation and found a solution there as well.
I am worried though, that my jQuery selector used in $nodesToReplace
is too long and possibly inefficient although it basically describes what I want returned. I'm just wondering if there was another more elegant/shorter/more efficient way to do this that I may have overlooked. Here's the code:
Two utility functions (for reference)
// Change an Element's type (change it's html tags) to "newType"
jQuery.fn.changeElemTypeTo = function(newType){
// just make sure it's a plain element name
newType.replace(/[<\/>]/ig,'');
var newElemStr = '<' + newType + '>' + this.html() + '</' + newType + '>';
console.log('*Nodes with tags replaced: ',newElemStr);
return this.replaceWith(newElemStr);
};
// Remove/strip the html tags from an element
jQuery.fn.removeElemTags = function(){
var tmp = this.replaceWith(this.html());
console.log('*Node with tags Removed: ',this.html());
return tmp;
};
main handler with super long selector in $nodesToReplace
...
$('#input').on('paste', function() {
var $inputDiv = $(this);
setTimeout(function() {
var oldHTML = '', newHTML = '';
// look through the commentbox for headings and other (mostly) block
// elements
var $nodesToReplace = $inputDiv.find('h1,h2,h3,h4,h5,h6,address,article,aside,blockquote,div,p,pre,dd,dt');
var $nodesToRemove = $inputDiv.find('*').not($nodesToReplace);
$nodesToRemove.each(function(){
console.log('Nodes with tags to remove: ',$(this).outerHtml());
$(this).removeElemTags();
});
$nodesToReplace.each(function(){
console.log('Nodes with tags to replace: ',$(this).outerHtml());
$(this).changeElemTypeTo('p');
});
}, 10);
});
I also have a demo on JSBin: http://jsbin.com/adazel/10/edit
1 Answer 1
I struggled with the same issue in the past, and decided to simply use a disposable DOM element to convert the HTML to plaintext:
var message = "..."; // Contains HTML markup
var tmp = document.createElement("DIV");
tmp.innerHTML = message;
var message = tmp.textContent||tmp.innerText;
// message now contains plaintext, and tmp can be disposed of
With this approach, we still needed to allow the user to enter a single tag. For this, we simply implemented a microformat where the user enters "placeholders" with bracket symbols:
Hello [[person]], having a good day?
Since this is just plain text, it will not be removed by the above conversion process, and can simply be replaced with the appropriate HTML tags:
message.replace('/\[\[person\]\]/g', '<strong>some name</strong>');
-
\$\begingroup\$ wow thanks, can't believe I didn't know about the
textContent
property before \$\endgroup\$Ray– Ray2013年06月01日 19:47:48 +00:00Commented Jun 1, 2013 at 19:47