tags:

views:

83

answers:

4

Hi.

I currently am trying to add tags around certain words in a webpage. This webpage can have many different id's, classes, and names, so it's important that if I'm trying to put a span around "foo" I do the following:

<p class='foo'>blah blah blah foo blah blah blah </p>

changes into

<p class='foo'>blah blah blah <span class='bar'> foo </span> blah blah blah </p>

and not

<p class='<span class='bar'> foo </span>'>blah blah blah <span class='bar'> foo </span> blah blah blah </p>

I'm investigating parsing the website out using the following code:

var obj = $(this.innerHTML);  //in my selector which selects the part of the website I want to apply the span to

I'm able to browse this data structure in firebug, but modifying it (or searching it) is proving to be more difficult.

If I look at obj[1], the innerHTML property looks like this:

<h4 id="3423df" class="pzCMD">blah blah foo blah </h4>

I have no idea how to modify this element (if possible) or add new nodes to it. I can extract the "text" by looking at the textContent

obj[1].textContent = blah blah foo blah

but I'm unsure how I would go about changing the html code of this element to

<h4 id="3423df" class="pzCMD">blah blah <span class='bar' foo <span> blah </h4>

Thanks for any help, sorry for the long drawn out explanation.

+1  A: 

jQuery.add() allows you to append dom elements on the fly but dropping into straight Jscript is a possibility too:

 var obj = $(this.innerHTML); 
 obj[1].innerHTML = obj[1].innerHTML+'blah hi</span>';
 //<h4 id="3423df" class="pzCMD">blah blah <span class='bar' foo <span> blah blah hi  </span> </h4>
ebt
Thanks for the reply.I should have been more clear in my original question. The value of "foo" can change, sometimes being the same as an id or class in the <p> or <div> that contains the text I want to add my span to.In this example, If I'm searching for all the instances of 'foo', and 'foo' is in both the text and the markup code, I run into the issue which I'm trying to solve. Correct me if I'm wrong here, of course! :)
A: 

Hello!

Maybe I didn't get the idea, but I'll give you an explanation anyways. Tell me if it fits you: The idea is to get all divs with class foo and text foo, take that text away and replace it with a span with another class. so

<div class="foo">some ttext nmot changed except the foo part</div>

would be changed to:

<div class="foo">some ttext nmot changed except the <span class="bar">foo</span> part</div>

here is the code:

var allFoosInTheWorld = $("div.foo");

for (var i = 0; i < allFoosInTheWorld.length; i++ ){
    var text = $(allFoosInTheWorld[i]).text();
    var index = text.indexOf("foo");

    if ( index != -1 ){
        var elem = '<span class="bar">' + "foo!!!" + '</span>';
        text = text.replace("foo", elem);
        $(allFoosInTheWorld[i]).text(text);
    }
}
David Conde
you could probably do this better if you're using jquery, using each() instead of setting up the for loop.
Steve-O-Rama
Thanks for the reply. I'm looking into using this method of inserting the span code into the html. One issue I can see (and something I probably wasn't clear on) is that in this code, you assume that all the divs I want to perform the replacement on are named foo. This might have been the way I worded it, but is not the case... each div/<p> on the page can have a different class, and regardless of this class I need to search through it. However, I'm going to try modifying what you did in your example to work! Thanks!
Okay, after looking at this solution a little more, I don't think it'll work. Say there was something like this: <div class='foo'> blah foo blah <span class='another_class'>some content</span></div>This method seems to erase any html code since of the div, with the exception of the code that is placed in <span class="bar">foo!!!</span> part.Does this seem correct?
It doesn't erases the code, it justs replaces all "foo" for the spam code, and yes! I could have used the iterator, sorry about that, old c habbits die hard
David Conde
A: 

Now it supports different divs! sorry for the delay, and sorry for not using foreach!!! i just can't seem to adapt to it :)

var classesIWant = ["foo", "foo1", "foo2"];
var allDivsInTheWorld = jQuery("div");

for( var i = 0; i < allDivsInTheWorld.length; i++) {
    var element = allDivsInTheWorld[i];
    var good = false;    

    for (var j = 0; j < classesIWant.length; j++){
        if ( $(element).hasClass(classesIWant[j]) )
            good = true;
    }

    if ( !good )
        continue;

    var text = $(element).text();
    var index = text.indexOf("foo");

    if ( index != -1 ){
        var elem = '<span class="bar">' + "foo!!!" + '</span>';
        text = text.replace("foo", elem);
        $(element).text(text);
    }
}
David Conde
A: 

I was attempting to do this in the wrong way. Here is the solution that I created, and seems to work great. It uses two recursive functions + DOM traversal + regular expressions to create the proper text and span nodes.

function replaceText(element, pattern, syn_text) {

for (var childi = 0; childi < element.childNodes.length;childi++) {
    var child= element2.childNodes[childi];
    if (child.nodeType==1 && child.className!=syn_text){ //make sure we don't call function on newly created node
        replaceText(child, pattern, syn_text);  //call function on child
    }
    else if (child.nodeType==3){ //this is a text node, being processing with our regular expression
        var str = child.data;
        str = str.replace(pattern,function(s, p1,p2,p3) {
            var parentNode = child.parentNode;
            do_replace(s, p1,p2,p3,parentNode,pattern,syn_text);
            parentNode.removeChild(child);  //delete old child from parent node.  we've replaced it with new nodes at this point
         });
    }
}}




function do_replace(s, p1,p2,p3,parentNode,pattern,syn_text) {
   if(p1.length>0){   //this might not be necessary
     //create textnode
      var text_node = document.createTextNode(p1);
      parentNode.appendChild(text_node);
   }
   if(p2.length > 0){ //create a span + next_node for the highlighting code
      spanTag = document.createElement("span");
      spanTag.id = "SString" + id++;
      spanTag.className = syn_text;
      spanTag.innerHTML = p2;
      parentNode.appendChild(spanTag);
   }
   if(p3.length > 0){
       //test to see if p3 contains another instance of our string.

      if(pattern.test(p3)){  //if there is a instance of our text string in the third part of the string, call function again
          p3.replace(pattern,function(s, p1,p2,p3) {
            //debugger;
            do_replace(s, p1,p2,p3,parentNode,pattern);
            return;
          });
      }
      else{  //otherwise, it's just a plain textnode, so just reinsert it.
          var text_nodep3 = document.createTextNode(p3);
          parentNode.appendChild(text_nodep3);
          return;
      }
    }
    else{ //does this do anything?
        return;
     }
return}

This function is called as follows:

syn_highlight = "highlight_me";  //class to signify highlighting 
pattern = new RegExp('([\\w\\W]*?)\\b('+ searchTerm + '[\\w]*)\\b([\\w\\W]*)',"ig");
replaceText($('#BodyContent')[0],pattern,syn_highlight);