0

I want to replace all the tags with different tag using javascript.

Lets say I want to replace "asdf" tag with "xyz"

<asdf>
<asdf> First 
      <asdf> First nested </asdf>
</asdf>
<asdf> Second</asdf
</asdf>

This is what I am expecting:

<xyz>
<xyz>  First
   <xyz> First nested </xyz>
</xyz>
<xyz> Second </xyz>
</xyz>

i tried with using jquery

$('asdf').each(function() {
$(this).replaceWith("<xyz>"+$(this).html()+"</xyz>")
});

but it replaces only the first not all.

gabf Hahn
  • 117
  • 1
  • 3
  • 13
  • 1
    You may want to have a look at http://stackoverflow.com/questions/7093417/using-jquery-to-replace-one-tag-with-another – Norman Jan 27 '16 at 18:00
  • 1
    [Works for me.](https://jsfiddle.net/q0s2uw6c/) – Mike Cluck Jan 27 '16 at 18:01
  • 4
    by replacing the content of first (outer) one you're removing all other (child) elements as well. – Jörn Jan 27 '16 at 18:01
  • Are you expecting it to change the inner ones as well? You'll need to target them first because the parents will get picked up in the selection process first. Then you're replacing their children so the ones you *did* get originally no longer exist. – Mike Cluck Jan 27 '16 at 18:04

2 Answers2

2

I'd do it in reverse document order so that we process descendant elements before ancestor ones, and I'd avoid making a round-trip through markup since that's unnecessary overhead and will wipe out event handlers we could avoid wiping out. (Not much we can do about the ones on the actual elements we're changing, at least not ones attached with modern techniques.)

See comments:

// Get all target elements, and then get a raw array for them
// and reverse it. Then loop through the reversed copy.
$("div").get().reverse().forEach(function(src) {
  // Get a jQuery wrapper for this element
  var $src = $(src);

  // Create the replacement
  var $dest = $("<span>");

  // Move all its contents over
  $dest.append($src.contents());

  // Copy its attributes
  Array.prototype.forEach.call(src.attributes, function(attr) {
    $dest[0].setAttribute(attr.nodeName, attr.nodeValue);
  });

  // Replace it
  $src.replaceWith($dest);
});

Live Example:

setTimeout(function() {
  // Get all target elements, and then get a raw array for them
  // and reverse it. Then loop through the reversed copy.
  $("div").get().reverse().forEach(function(src) {
    // Get a jQuery wrapper for this element
    var $src = $(src);

    // Create the replacement
    var $dest = $("<span>");

    // Move all its contents over
    $dest.append($src.contents());

    // Copy its attributes
    Array.prototype.forEach.call(src.attributes, function(attr) {
      $dest[0].setAttribute(attr.nodeName, attr.nodeValue);
    });

    // Replace it
    $src.replaceWith($dest);
  });
}, 500);
div {
  border: 1px solid red;
}
span {
  border: 1px solid green;
}
.test {
  color: blue;
  font-weight: bold;
}
<p>Divs will change to spans in a moment. "Second" is blue because it has a class on it, to check that we copy attributes correctly.</p>
<div>
  <div>First
    <div>First nested</div>
  </div>
  <div class="test">Second</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
-1

Made simple jquery plugin

$.fn.renameTag = function(replaceWithTag){
  this.each(function(){
        var outerHtml = this.outerHTML;
        var tagName = $(this).prop("tagName");
        var regexStart = new RegExp("^<"+tagName,"i");
        var regexEnd = new RegExp("</"+tagName+">$","i")
        outerHtml = outerHtml.replace(regexStart,"<"+replaceWithTag)
        outerHtml = outerHtml.replace(regexEnd,"</"+replaceWithTag+">");
        $(this).replaceWith(outerHtml);
    });
    return this;
}

Usage:

$('asdf').renameTag('xyz')
Jagdish Idhate
  • 7,513
  • 9
  • 35
  • 51