Chri.s Chri.s - 3 years ago 128
jQuery Question

jQuery - text deleted by .html() when targeting element directly but not when using .each()

I've got a hard time understanding why one version of my code is working, while the other one isn't.

Background info:

I've got some text strings that hold the following character in it, to separate one part of the text from another:

|



My goal is to wrap the text following this character in a
<span>
which is also working with the code beneath, using jQuery
.each()
. However, as I have single elements (the original element can be on each page up to 40 times) that also contains this text, and needs the same process, I wanted to target these "individually" (not looping through all of them). However, when I target the elements individually the entire text of the element is deleted rather than being wrapped / replaced. You can see the code that is not working a little further down, and in the bottom an example.

I've got the following code which is working as intended/imagined:

// This part works fine

$('.aa').each(function() {
$(this).html($(this).text().replace('| ', '<span>')).append('</span>');
});


This part is not working as imagined:

// Not working as imagined

$(".bb").html($(this).text().replace('| ', '<span>')).append('</span>');


Here's a live example:



// This part works fine
$('.aa').each(function() {
$(this).html($(this).text().replace('| ', '<span>')).append('</span>');
});


// This part does not work as imagined?
setTimeout(function(){
// ---------------
$(".bb").html($(this).text().replace('| ', '<span>')).append('</span>');
// ---------------
},3000)

span{
color:red;
display:block;
}
.aa{
margin-bottom: 30px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="aa">
Hi | There</div>

<div class="bb">
a | b
</div>





Question:

Why doesn't the last code work as I would have imagined, and rather than replacing the text it completely deletes it all?

And on another note, is there a better way of wrapping the remaining text than the one I'm using?



Additional question
Following up on the splendid answers given, I've got another question:
Since it's not possible to use the
$(this)
selector like this due to scope issues, how would one then target multiple elements such as this:

$(".bb, .cc").html($(this).text().replace('| ', '<span>')).append('</span>');


Note that I'm aware that the above piece is incorrect - but the
$(this)
part is just to underline my question as to how you should target those different elements. Is it optimal to use the
.each()
function for this purpose?




For sake of answering other people's problem regarding this matter: The answer for the additional question is "yes" to the use of
.each()
based on the comment of @mhodges in the answer from @woodrow

Answer Source

Please see below. The "$(this)" inside of your setTimeout is referring to the scope within the setTimeout function, which could be "window", which isn't valid, whereas "$(this)" inside of the each statement for "aa" refers to each "aa" element in the loop. You need to reference "bb" as the class inside the setTimeout function..

// This part works fine 
$('.aa').each(function() {
  $(this).html($(this).text().replace('| ', '<span>')).append('</span>');
});


// This part does not work as imagined?
setTimeout(function() {
  // ---------------
  $(".bb").html($(".bb").text().replace('| ', '<span>')).append('</span>');
  // ---------------
}, 3000)
span {
  color: red;
  display: block;
}

.aa {
  margin-bottom: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="aa">
  Hi | There</div>

<div class="bb">
  a | b
</div>

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download