1

This code works perfectly to replace a string with some html:

$('.active_admin_comment_body').each(function(comment_index){
    the_string = $(this).text().replace("#Excitement", "<span style=\"background-color: lightgrey;\">#Excitement</span>");
     $(this).html(the_string);
)};

The problem with the code above is it only works to replace one value. I have an array of values, so I wrote the following code to loop through the array and then modify each comment with a value from the array:

$('.active_admin_comment_body').each(function(comment_index){
    hashtags = ["#Excitement", "#Sad News", "#Moderate"];
    comment = $(this);
    $.each(hashtags, function(index, value){
        new_comment = comment.text().replace(value, "<span style='background-color: lightgrey;'>" + value + "</span>");
        comment.html(new_comment);
    });
});

The first block of code works 100%. The second block of code only works if you remove the html inside of the replace method. How do I get the second block of code to work?

5
  • 1
    If you want to replace all matches use str.replace(/textToReplace/g, 'replaceWith'); Commented Jul 19, 2017 at 14:38
  • Thanks, but I'm not sure I understand your comment. I tried switching replace with replaceWith but nothing changed. Also I looked at the documentation for replaceWith and it seems like that's for DOM elements, not particular text. Commented Jul 19, 2017 at 14:44
  • @Philip7899 That's not what @YordanNikolov said. He is pointing out that you should change "#Excitement" to /#Excitement/g or to RegExp("#Excitement", "g"). The g means to replace all instances instead of replacing the first and then stopping. Commented Jul 19, 2017 at 14:51
  • At the risk of giving a jerk answer, the proper solution is to ditch your code and use a templating engine. Commented Jul 19, 2017 at 14:52
  • I think that comment.text().replace... should be changed to comment.html().replace.... See my answer. Commented Jul 19, 2017 at 15:01

4 Answers 4

1

The culprit is the text() method. When you call it, it only returns the text inside the element, inadvertently undoing any HTML that have already been put in.

$('.active_admin_comment_body').each(function(comment_index){
    var hashtags = ["#Excitement", "#Sad News", "#Moderate"];
    var comment = $(this);
    $.each(hashtags, function(index, value){
        // I changed text() to html() in the next line.
        var new_comment = comment.html().replace(value, "<span style='background-color: lightgrey;'>" + value + "</span>");
        comment.html(new_comment);
    });
});

You should also note that replace will only replace the first match. For example, "foo bar foo".replace("foo", "baz") returns "baz bar foo"; you can see that only the first foo is replaced. If you want to replace all instances, you need to specify the g option; "foo bar foo".replace(RegExp("foo", "g"), "baz") returns "baz bar baz". In your code:

$('.active_admin_comment_body').each(function(comment_index){
    var hashtags = ["#Excitement", "#Sad News", "#Moderate"];
    var comment = $(this);
    $.each(hashtags, function(index, value){
        // I changed text() to html() and added the RegExp constructor.
        var new_comment = comment.html().replace(RegExp(value, "g"), "<span style='background-color: lightgrey;'>" + value + "</span>");
        comment.html(new_comment);
    });
});

If you change the items inside hashtags to include strings that are not hashtags, you may need to escape certain characters with a \ so that they aren't interpreted as special characters. See this link for a table of characters that need to be escaped. The # sign is not one of the special characters, so if you stick to just hashtags, then you don't need to worry about this.

Finally, instead of using a loop to change multiple strings, you may want to use a callback replace:

$('.active_admin_comment_body').each(function(comment_index){
    var hashtags = ["#Excitement", "#Sad News", "#Moderate"];
    var comment = $(this);
    var new_comment = comment.html().replace(/#(Excitement|Sad News|Moderate)/g, function(tag){
        return "<span style='background-color: lightgrey;'>" + tag + "</span>";
    });
    comment.html(new_comment);
});

You'll also notice that I added the var keyword to your code; this makes your variables local instead of global. This does not change the functionality of your code.

Sign up to request clarification or add additional context in comments.

Comments

1

Using html(function) and new RegExp() that joins the array using | for an OR

var hashtags = ["#Excitement", "#Sad News", "#Moderate"];

$('.active_admin_comment_body').html(function(_, txt) {
  var reg = new RegExp('(' + hashtags.join('|') + ')', 'g');
  return txt.replace(reg, '<span class="lightgrey">$1</span>');
});
.lightgrey{
  background-color: lightgrey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='active_admin_comment_body'>
  Test1 #Excitement
</div>
<div class='active_admin_comment_body'>
  Test2 #Sad News
</div>
<div class='active_admin_comment_body'>
  Test3 #Moderate
</div>

Comments

0

Looks like you were actually just missing one small thing. The way you loop was working it was only replacing the last one in the array. Changing the last value in the array caused it to switch which one was working.

Just matched the hashtag to the current string and everything is in order.

Only thing added to your code is the if statement, comparing for a match.

$(function(){
$('.active_admin_comment_body').each(function(comment_index){
    hashtags = ["#Excitement", "#Sad News", "#Moderate"];
    comment = $(this);
    $.each(hashtags, function(index, value){
    	if(comment.text().includes(value)){
      	new_comment = comment.text().replace(value, "<span style='background-color: lightgrey;'>" + value + "		</span>");
        comment.html(new_comment);
      }
    });
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='active_admin_comment_body'>
Test1 #Excitement
</div>
<div class='active_admin_comment_body'>
Test2 #Sad News
</div>
<div class='active_admin_comment_body'>
Test3 #Moderate
</div>

https://jsfiddle.net/75e0o36s/

Comments

0

textToReplace is "#Excitement" & replaceWith is "<span style=\"background-color: lightgrey;\">#Excitement</span>" in your case it will become

the_string = $(this).text().replace(/#Excitement/g, "<span style=\"background-color: lightgrey;\">#Excitement</span>");

new_comment = comment.text();
$.each(hashtags, function(index, value){
        new_comment = new_comment.replace(value, "<span style='background-color: lightgrey;'>" + value + "</span>");
    });
comment.html(new_comment);

Updated

1 Comment

Thanks but I got it to work already with just #excitement. I'm trying to get the second block of code to work where you loop through the array

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.