Use a delegate
You can use separate state-based event handlers via event delegation. Instead of binding either event to the #websites
element, bind the event handlers to the nearest stable parent (I'm using 'body'
here, but you may want to use a different selector):
$('body').on('click', '#websites:not(.open)', function () {
...executed when not open...
}).on('click', '#websites.open', function () {
...executed when open...
});
The delegate syntax will allow the click callback to be called on the #websites.open
element despite it not existing in the DOM at the time of binding.
This form is particularly useful when you have significantly different behaviors between the two states.
Use a single callback
If you're just toggling everything, I'd recommend making use of jQuery's toggle functions and do it all in one go:
$('#websites').on('click', function () {
$(this)
.slideToggle('fast')
.toggleClass('open')
.find('span')
.toggleClass('icon-chevron-right icon-chevron-down');
});
If you have separate functionality between the two states, you can use a simple if .is
check:
$('#websites').on('click', function () {
if ($(this).is('.open')) {
$(this)
.removeClass('open')
...
} else {
$(this)
.addClass('open')
...
}
});
Toggle multiple callbacks
You can expose callbacks as function references, and toggle which ones are active at any given time:
function openWebsites() {
$(this)
.off('click', openWebsites)
.on('click', closeWebsites)
.addClass('open')
...
}
function closeWebsites() {
$(this)
.off('click', closeWebsites)
.on('click', openWebsites)
.removeClass('open')
...
}
$('#websites').on('click', openWebsites);