Reputation: 164
I am currently trying to set up a menu with a icon toggle, so when one icon is clicked it changes to a cross and then when that cross is clicked it changes back to the original. I have got that far, but when I click a new image I want the old icon to reset and the cross to be applied to the new icon.
This is how far I have got:
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingFive">
<a class="collapsed faq-links">
<i id="icon" class="fa fa-info-circle fa-3x"></i>
</a>
</div>
</div>
<br />
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading13">
<a class="collapsed faq-links">
<i id="icon" class="fa fa-heartbeat fa-3x"></i>
</a>
</div>
</div>
<br />
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingFour">
<a class="collapsed faq-links" >
<i id="icon" class="fa fa-comments fa-3x"></i>
</a>
</div>
</div>
Javascript:
$('.faq-links').click(function(){
var collapsed=$(this).find('i').hasClass('fa-info-circle');
$('.faq-links').find('i').removeClass('fa-times');
$('.faq-links').find('i').addClass('fa-info-circle');
if(collapsed)
$(this).find('i').toggleClass('fa-info-circle fa-3x fa-times fa-3x')
});
I've set up a JSFiddle to show it working https://jsfiddle.net/BenjiBaird/yycf2jb8/1/
So when I click on info-circle the cross is applied and when I click on another that cross is removed. How do I go about applying this so every icon.
Any help would be appreciated, hope I made myself clear.
Upvotes: 4
Views: 1387
Reputation: 323
HTML:
<i id="icon" class="fa fa-heartbeat fa-3x" data-icon="fa-heartbeat"></i>
About HTML:
For storing the icon name, the best way would be using data-attributes.
It is easy to understand + you will have no problem with changing it in the future. Make sure, you use id
attribute only for one DOM Element
, for multiple elements, use class
attribute.
JS:
// jQuery safety
(function($) {
// DOM ready
$(function() {
// icons
var $icons = $('.faq-links');
$icons.on('click', function(e) {
// variables
var $this = $(this);
var $icon = $this.find('i');
// iconName taken from data-icon attribute
var iconName = $icon.data('icon');
// close icon
var closeIconName = 'fa-times';
// prevent default browser behaviour, just in case
e.preventDefault();
// handle state
if ($icon.hasClass(closeIconName)) {
$icon.removeClass(closeIconName).addClass(iconName);
} else {
$icon.addClass(closeIconName).removeClass(iconName);
};
});
});
})(jQuery);
About JS:
I believe in clean code writing. The cleaner, the better - stick with that in your coding adventure.
First, we take $icons
- every icon we have.
We are waiting for click
event.
Once one of the $icons
is clicked, we set $this
as the clicked icon. We also set $icon
as <i></i>
element inside clicked icon, just for cleaner code.
iconName
is equal to icon's data-attribute, so we can use it easily in further steps.
Now we have // handle state
section. It is simple to understand, that if the $icon
has class, which is equal to closeIconName
(cross in this example), it is 'active'. So once this 'active' icon is clicked, we remove 'active' state, which means, we remove closeIconName
class and we add iconName
which is the default icon name (took from data-attribute). If the icon isn't 'active', we remove the icon and we add closeIconName
icon.
NOTE: icon without data-attribute simply doesn't change to fa-close icon.
EDIT: here is JSFiddle: https://jsfiddle.net/0fy2po3b/1/
Upvotes: 0
Reputation: 1
If you have a way to ensure that the class fa-times takes precedence over the fa-heartbeat, fa-info-circle and fa-comments classes this simple code would work just fine.
$('.faq-links').click(function() {
var blockI = $(this).find('i');
if(blockI.hasClass('fa-times')) {
// remove fa-times class if the element already has it
blockI.removeClass('fa-times');
}
else {
// clean the classes from other elements that might have it
$('.faq-links i').removeClass('fa-times');
// adds it on the clicked element
blockI.addClass('fa-times');
}
});
You can redefine class fa-times in a later css file or style block and/or using a more specific selector to redefine the class so that fa-times style "overrides" the other classes. That would be the best for me because you dont need to mess around with the other classes. You can modify the order of the links or add news ones and the script would still work.
Upvotes: 0
Reputation: 5176
I would remove the "cross" icon classes from all buttons, then reset all buttons to their default icon and finally draw the "cross" (if needed) for the current one. Like this:
$('.faq-links').click(function(){
var notCollapsed = $(this).find('i').hasClass('fa-times');
//Remove crosses from all buttons
$('.faq-links').find('i').removeClass('fa-times');
//Reset the default icon for each button
$('.faq-links:eq(0)').find('i').addClass('fa-info-circle');
$('.faq-links:eq(1)').find('i').addClass('fa-heartbeat');
$('.faq-links:eq(2)').find('i').addClass('fa-comments');
//Draw the cross if needed
if(!notCollapsed) $(this).find('i').attr("class",'fa fa-times fa-3x');
});
See your update fiddle https://jsfiddle.net/8odoros/yycf2jb8/10/
Upvotes: 1
Reputation: 12400
If you add a data attribute to the anchor tags with the specific icon class name like so
<a class="collapsed faq-links" data-icon-name="fa-info-circle">
<i id="icon" class="fa fa-info-circle fa-3x"></i>
</a>
You can use that attribute to toggle the icons between the 'fa-times' and the original one
Have a look at the code below and the JSFiddle to see how it works. Also there are inefficiencies in the code namely in the constantly using .find('i')
but i'll leave it up to you to come up with a solution for that.
$('.faq-links').click(function() {
if ($(this).find('i').hasClass('fa-times')) { //then change back to the original one
$(this).find('i').removeClass('fa-times').addClass($(this).data('icon-name'));
} else {
$('.faq-links').each(function(){ //Remove the cross from all other icons
if($(this).find('i').hasClass('fa-times')) {
$(this).find('i').removeClass('fa-times').addClass($(this).data('icon-name'));
}
});
$(this).find('i').addClass('fa-times').removeClass($(this).data('icon-name'));
}
});
The Fiddle is here
Upvotes: 4