views:

438

answers:

8

If I have some HTML that looks like this:

<div id="text">
      This is some text that is being written <span class="highlight">with
      a highlighted section</span> and some text following it.
</div>

And I want to remove the "span" leaving the text node within, how would I go about doing that? I tried using jQuery to do the following:

wrap = $('.highlight');
wrap.children().insertBefore(wrap);
wrap.remove();

But that doesn't work I'm guessing because children returns an empty set since there's only a text node in there. So all that happens is that the span and its contents are removed.

I'm also open to alternatives to my approach here. What's happening is that my code actually creates that span when a user selects a block of text. It wraps the selected text in a span to visually differentiate it. I need to remove the span afterward though because of some quirks with the way mozilla's range object works.

EDIT: I don't want to replace the entire content of '#text' by the way since it could be very large.

A: 

text.replace(/<\/?[^>]+(>|$)/g, "");

cw22
Ah, regular expressions. I've never met one that didn't make my brain cry. But this is a good approach. Just replace the inner html with the results of a regex. I like it.
Karim
It's best to never use regex for (X)(HT)ML as these are not regular languages. however in this case the above should work.
Pim Jager
-1 This removes the tags, but not in the way the OP specified.
Imagist
+3  A: 

This works:

wrap = $('.highlight');
wrap.before(wrap.text());
wrap.remove();
Gabriel Hurley
Reason for the downvote? I tested this on the Google AJAX Playground for jQuery and it worked...
Gabriel Hurley
+1 - it does indeed work - click on output tab - http://jsbin.com/iqola/edit
Russ Cam
+6  A: 

You get the text, and replace the span with it:

var wrap = $('.highlight');
var text = wrap.text();
wrap.replaceWith(text);
Pim Jager
Why was this downvoted? seems like a good solution to me?
Pim Jager
doesn't quite work - if you change replace to replaceWith() it works fine
Russ Cam
ah yes, wrong function, you're right (didn't test it)
Pim Jager
+1 - for the edit
Russ Cam
+2  A: 

This will do what you want, and also preserve any tags within the .highlight span.

content = $(".highlight").contents();
$(".highlight").replaceWith(content);
sixthgear
A: 

it would be much easier to just change the class of the span than to actually remove it. You can use pure javascript:

document.getElementById("span id").className="";

Or jquery's toggleClass function:

 $("element").toggleClass("highlight");

Also, best practices say that you shouldn't use class names that imply a style, like highlight. Try "emphasized" instead. :D

CrazyJugglerDrummer
yeah, sadly the span has to be removed due to the weirdness with the range object i mentioned.
Karim
+5  A: 

wrap it in a plugin

(function($) {   
    $.fn.tagRemover = function() {           
        return this.each(function() {            
        var $this = $(this);
        var text = $this.text();
        $this.replaceWith(text);            
        });            
    }    
})(jQuery);

and then use like so

$('div span').tagRemover();

Working Demo here - add /edit to the URL to play with the code

Russ Cam
Heh, nice.
Gabriel Hurley
Talk about going the extra mile... nice.
Karim
Putting stuff in a plugin is almost always a good move (and now it is) +1
Pim Jager
A: 

A better unwrap plugin:

$.fn.unwrap = function() {
  this.parent(':not(body)')
    .each(function(){
      $(this).replaceWith( this.childNodes );
    });

  return this;
};

from Ben Alman

tb
A: 
element = document.getElementById("span id");
element.parentNode.insertBefore(element.firstChild, element);
element.parentNode.removeChild(element);
nadavkav