Eyad Fallatah
Eyad Fallatah

Reputation: 1948

Remove nested <SPAN> without ID

Ok, I have the following string

I have a string that contains the following:

<span>A</span>BC<span id="blabla">D<span>EF</span></span>GH

I want to be able to use pure JavaScript to strip out any span tag that does not have an id so that the output looks like:

ABC<span id="blabla">DEF</span>GH

I have the following code which works fine but does not handle the nested span in the middle (the one that holds EF). I just need to know how can I use recursion to accomplish my goal.

function removeSpans2(s) {
  var a = document.createElement('div');
  a.innerHTML = s;
  var node, next = a.firstChild;

  while (node = next) {
    next = next.nextSibling

    if (node.tagName && node.tagName.toLowerCase() == 'span' && !node.id) {
      a.replaceChild(document.createTextNode(node.textContent || node.innerText), node);
    }
  }
  return a.innerHTML;
}

Upvotes: 0

Views: 445

Answers (4)

anson
anson

Reputation: 4164

why don't you simply just use String.replace() if it is an html string like you seemed to indicate.

str.replace(/<span>([A-Za-z0-9]*)<\/span>/g, '$1');

You can tweak the values between the brackets to accommodate for what content you would find between your spans

EDIT edited above code to remove just the tags and not the content inside

Upvotes: 1

Godwin
Godwin

Reputation: 9907

Perfect time to pull out some recursion:

function removeSpans2(s) {
  var a = document.createElement('div');
  a.innerHTML = s;
  var node, next = a.firstChild;

  while (node = next) {
    next = next.nextSibling

    if (node.tagName && node.tagName.toLowerCase() == 'span' && !node.id) {
      a.replaceChild(document.createTextNode(removeSpans2(node.textContent || node.innerText)), node);
    } else if (node.innerText != undefined){
        var node2 = node.cloneNode(true);
        node2.innerText = removeSpans2(node2.innerText);
        a.replaceChild(node2, node);
    }
  }
  return a.innerHTML;
}

Upvotes: 1

RobG
RobG

Reputation: 147413

No recursion needed, figured out a simpler algorithm. This one handles all sorts of nested elements, you can have A elements inside the spans, or spans in side As, or spans in spans in spans... whatever.

function removeSpans3(s) {
  var a = document.createElement('div');
  a.innerHTML = s;
  var span, spans = a.getElementsByTagName('span');
  var frag, arr = [];

  // Stabilise spans collection in array
  for (var i=0, iLen=spans.length; i<iLen; i++) {
    arr[i] = spans[i];
  }

  // Process spans
  for (i=0; i<iLen; i++) {
    span = arr[i];

    // If no id, put content into a fragment
    if (!span.id) {

      // Some older IEs may not like createDocumentFragment
      frag = document.createDocumentFragment();

      while (span.firstChild) {
        frag.appendChild(span.firstChild);
      }

      // Replace span with its content in the fragment
      span.parentNode.replaceChild(frag, span);
    }
  }
  return a.innerHTML;
}

Upvotes: 1

demix
demix

Reputation: 76

I think this will work, just add a recursion

function removeSpans2(s , el) {
    var a = el || document.createElement('div');
    a.innerHTML = s;

    var node, next = a.firstChild;

    while (node = next) {
        next = next.nextSibling;
        if( node.children && node.children.length ) {
            arguments.callee(node.innerHTML , node);
        }else if (node.tagName && node.tagName.toLowerCase() == 'span' && !node.id) {
            a.replaceChild(document.createTextNode(node.textContent || node.innerText), node);
        }
    }
    return a.innerHTML;
}

Upvotes: 1

Related Questions