Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

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

share|improve this question

1 Answer 1

up vote 2 down vote accepted

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>');
share|improve this answer
    
wow thanks, can't believe I didn't know about the textContent property before –  Ray Jun 1 '13 at 19:47

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.