Reputation: 6217
I've googled and googled as well as search Stackoverflow. After looking though about 2 dozen other questions and not seeing the same situation, I decided to post a new question.
I don't need help getting this working. I just want to understand why it's not working. It just doesn't make any sense to me. So, my question is this:
Why would saving the jQuery object to a variable cause .addClass()
/.removeClass()
to not work?
I have a span
with class fa fa-eye
and I want to change the fa-eye
class to fa-eye-slash
and back again with a button click.
Here's my HTML:
<button id='visibility-toggle' data-status='hidden'>
<span class='fa fa-eye'></span>
Show
</button>
Here's my not working JavaScript:
jQuery('#visibility-toggle').click(function(e){
e.preventDefault();
var button = jQuery(this);
var icon = button.find('.fa');
if(button.data('status') === 'hidden') {
show_stuff();
button.html(button.html().replace('Show', 'Hide'));
icon.addClass('fa-eye-slash');
icon.removeClass('fa-eye');
button.data('status', 'visible');
} else {
hide_stuff();
button.html(button.html().replace('Hide', 'Show'));
icon.addClass('fa-eye');
icon.removeClass('fa-eye-slash');
button.data('status', 'hidden');
}
});
The string replacement is working and the show/hide functionality is working. The add/remove class functionality is not working.
I also tried making these changes.
HTML:
<span class='show-icon fa fa-eye'></span>
JS:
var icon = jQuery('.show-icon');
...still not working.
BUT here's the kicker. This works (not saving the jQuery object to a icon
variable, but just looking it up each time):
jQuery('#visibility-toggle').click(function(e){
e.preventDefault();
var button = jQuery(this);
if(button.data('status') === 'hidden') {
show_stuff();
button.html(button.html().replace('Show', 'Hide'));
jQuery('.show-icon').addClass('fa-eye-slash');
jQuery('.show-icon').removeClass('fa-eye');
button.data('status', 'visible');
} else {
hide_stuff();
button.html(button.html().replace('Hide', 'Show'));
jQuery('.show-icon').addClass('fa-eye');
jQuery('.show-icon').removeClass('fa-eye-slash');
button.data('status', 'hidden');
}
});
So, again, my question is:
Why would saving the jQuery object to a variable cause .addClass()
/.removeClass()
to not work?
I have been working with jQuery for years and have never noticed this behavior before. It seems very strange. Am I just missing something super simple? Am I just too tired?
I am seeing this behavior in Google Chome Version 45.0.2454.85 (64-bit)
on Ubuntu 14.04.3
. I have not tried other browsers or other systems.
I'm using jQuery 2.1.3
from: https://code.jquery.com/jquery-2.1.3.min.js
If I run this code in the console, it works as expected.
var icon = jQuery('.show-icon');
icon.addClass('fa-eye-slash');
icon.removeClass('fa-eye');
icon.addClass('fa-eye');
icon.removeClass('fa-eye-slash');
When I console.log(icon)
and console.log(jQuery('.show-icon'))
in the console, they look exactly the same.
[span.show-icon.fa.fa-eye, prevObject: n.fn.init[1], context: document, selector: ".show-icon"]
I am able to consistently toggle the code back and forth and one way it works, the other way it doesn't.
HTML:
<button id='visibility-toggle' data-status='hidden'>
<span class='fa fa-eye'></span>
<span class='text'>Show</span>
</button>
JS:
jQuery('#visibility-toggle').click(function(e){
e.preventDefault();
var button = jQuery(this);
var icon = button.find('.fa');
var text = button.find('.text');
if(button.data('status') === 'hidden') {
show_stuff();
text.text(text.text().replace('Show', 'Hide'));
icon.addClass('fa-eye-slash');
icon.removeClass('fa-eye');
button.data('status', 'visible');
} else {
hide_stuff();
text.text(text.text().replace('Hide', 'Show'));
icon.addClass('fa-eye');
icon.removeClass('fa-eye-slash');
button.data('status', 'hidden');
}
});
I know it's ugly. I'll refactor it in the morning.
Upvotes: 2
Views: 549
Reputation: 6781
When you replace a chunk of the document with .html()
you are throwing away all of the DOM objects that represent those elements and a bunch of new ones get created. Your saved copy of icon refers to the thrown-away object that got replaced by .html
. Avoid .html
like the plague - modify the object properly with .attr
, .text
, .empty
.append
, etc. .html
is a security hole waiting to happen.
Upvotes: 4