Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a challenging mission in JS string manipulation: There is a HTML string in which I need to replace a word at a specific word index. The word index is the number of the word when ignoring the HTML tags.

For example, here is the HTML string:

<span style="font-family:Times New Roman;">At times like this I don't know what to
do. Other times I have no problem.</span>

The task is to replace word number 2 in the html (which is the word times) with the text: <span style="color:red;">times</span>

So the final HTML string should be:

<span style="font-family:Times New Roman;">At <span style="color:red;">times</span> 
like this I don't know what to do. Other times I have no problem.</span>

Any ideas for this challenge?

share|improve this question
 
Do you want to replace all occurrences of that word or just the first one ? –  dystroy Sep 3 at 11:21
add comment

5 Answers

up vote 2 down vote accepted

I would first find the word by tokenizing the filtered HTML, and then do the replacement.

Let's start from your string :

var html = '<span style="font-family:Times New Roman;">At times like this don\'t know what to do. Other times I have no problem.</span>';

Case 1, you want to replace all occurrences :

var tokens = html.replace(/<[^>]*>/g,'').split(/\W+/).filter(Boolean);
var newHTML = html.replace(new RegExp('\\b'+tokens[1]+'\\b', 'g'), function(s){
     return '<span style="color:red;">'+s+'</span>'
});

Demonstration

Case 2, you just want to replace the word at the specified index (this one is surprisingly tricky) :

var tokens = html.replace(/<[^>]*>/g,'').split(/\W+/).filter(Boolean);
var wordToReplaceIndex = 1, wordToReplace = tokens[wordToReplaceIndex];
var occIndex = 0;
for (var i=0; i<wordToReplaceIndex; i++) {
   if (tokens[i]===wordToReplace) occIndex++;
}
i=0;
var newHTML = html.replace(new RegExp('\\b'+wordToReplace+'\\b', 'g'), function(s){
    return (i++===occIndex) ? '<span style="color:red;">'+s+'</span>' : s
});

Demonstration

Alternate solution for case 2 :

var i=0, wordToReplaceIndex = 1;
var newHTML = html.replace(/>([^<]+)</, function(txt) {
  return txt.replace(/\w+/g, function(s) {
    return i++==wordToReplaceIndex ? '<span style="color:red;">'+s+'</span>' : s;
  })
});

Can you spot why the second one was tricky ? ;)

share|improve this answer
 
your solutions only replaces the first occurrence, not sure if they is the requirement or not. –  Johan Sep 3 at 11:12
 
In the example of the question, it's the first occurrence. For replacing all occurrence, just add the g flag. –  dystroy Sep 3 at 11:14
 
I get that, just making the OP aware, it could be a mistake in his/her question :) –  Johan Sep 3 at 11:16
 
I am still trying to understand your code, but anyway your solution in 'case 2' works great. I don't know regex well so I can't tell why it was tricky :) Thank you very much! –  Light Sep 8 at 6:39
add comment

I think a decent solution would be to split and replace then join. Here's an example:

<div id="replace-me">Hello, world</div>

replaceWordAtIndex = function (text, index, replacement) { 
    text = text.split(' ');
    text[index] = replacement;
    text = text.join(' ');
    return text;
}

wrapWordAtIndex = function (text, index, before, after) { 
    text = text.split(' ');
    text[index] = before + text[index] + after;
    text = text.join(' ');
    return text;
}

var obj = document.getElementById('replace-me');
obj.innerText = replaceWordAtIndex(obj.innerText, 1, 'Universe');
obj.innerHTML = wrapWordAtIndex(obj.innerText, 1, '<b>', '</b>');

Should result in:

<div id="replace-me">Hello, <b>Universe</b></div>

And here's a JSFiddle for you to see it in action

share|improve this answer
add comment
function smartReplace(str,index,strReplace){

    var wStart=0,wEnd=0;
    var startInd=str.indexOf(">")+1;    
    var wc=0;
    for(i=startInd;i<str.length;i++)
    {
        if (str.charAt(i) == ' ')
        {
            wc=wc+1;
            if (wc==index) 
            {   
                wEnd=i-1;
                break;
            }
            wStart=i+1;
        }
    }

    var newString = str.substring(0,wStart) + strReplace + str.substring((wEnd +1),(str.length-1));
    document.write(newString);
}

> call the smartReplace() like follows

var str1="<span style=\"font-family:Times New Roman;\">At times like this I don't know what to do. Other times I have no problem.</span>)";
smartReplace(str1,3,"<span style=\"color:red;\">times</span>");
share|improve this answer
 
Thanks, this is good, but I am looking for a function that can replace a specific word when the character index is unknown. For example "replace word number 2". –  Light Sep 8 at 6:40
add comment
var html = '<span style="font-family:Times New Roman;">At times like this don\'t know what to do. Other times I have no problem.</span>';
var tokens = html.replace("Times","<span style="color:red;">times</span>");
share|improve this answer
1  
It'd be best to explain the code rather than just dumping. It helps educate those who find the answer in future! –  danielhanly.com Sep 3 at 12:09
add comment

ive been using this jQuery plugin to replace/edit text in any part of the DOM. quite helpful and easy to use with complete REGEX support

http://benalman.com/projects/jquery-replacetext-plugin/

share|improve this answer
add comment

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.