1

I'm sure this is a very basic mistake I'm making but I can't work out where I am going wrong.

In this basic fiddle example, you will see I have 5 divs. I'm trying to replace a word in the middle of each div with another word, but it seems to be copying the contents of the first div into all of the other ones, as you can see from the beginning post numbers.

The snippet of code I'm using to do this is

$('.post').each(function(){
 $('em').html( 
 $('em').html().replace('in','hello')
 );
});

Please can someone help me to see where I'm going wrong?

asked Feb 14, 2013 at 12:08

2 Answers 2

5

You are replacing each em text with the content of all the ems' text. html also accepts a function that you can use to reference this, or take the current html as a parameter:

$('.post em').html(function (idx, html){
 return html.replace("in", "hello");
});

Your updated jsFiddle demo.

answered Feb 14, 2013 at 12:11
Sign up to request clarification or add additional context in comments.

Comments

3

There's no need for .each - you can use the version of .text that takes a mutator function and does an implicit .each on each matching element. The mutator function is passed the original text, and the return value gets put back in its place:

replaceIn = function() {
 $('.post em').text(function(ix, txt) {
 return txt.replace(/\b(in)\b/g, 'hello');
 });
}

See http://jsfiddle.net/alnitak/ZUQ4W/

I've used .text instead of .html because there's no HTML inside the matched elements.

Note the use of a regexp with the /g flag to ensure that all occurrences of "in" are replaced and the \b markers to ensure that it only matches whole words.

The string version of replace can only replace the first match in a string. Do feel free to use that instead if that's your intent, of course!

Also note that you must me very careful if you use this (or variants using .html) on elements with descendants, because outer elements get processed before inner elements and the operations on the outer element might make unexpected changes to the descendants. Chose your selector wisely so that only leaf nodes are altered!

Another good reason to avoid .html() is that if you serialise an element and then deserialise it again with .html() then any properties or events that have been set on that element will be lost. So far as possible changes to the DOM should be done without using HTML string manipulation!

To be on the safe side, use this:

replaceIn = function () {
 $('.post em').contents().filter(function () {
 return this.nodeType === 3;
 }).each(function() {
 // NB: DOM level 3 uses .textContent in preference to .nodeValue
 this.nodeValue = this.nodeValue.replace(/\b(in)\b/g, 'hello');
 });
}

which makes absolutely sure that any nested elements (e.g. an index tag!) can't be modified.

See http://jsfiddle.net/alnitak/rZU5d/

answered Feb 14, 2013 at 12:15

2 Comments

Thanks for this, it does exactly as I wanted. +1 for the extra info too. In the actual page I'm trying to replace text on it doesn't include any html tags so using .text is fine here.
Extra elaboration on what not to use: +1

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.