Reputation:
I have the following script:
// dashboard maximize
$('#dashboard-actions .btn-maximize').click(function() {
// max / restore buttons
$(this).removeClass('btn-maximize').addClass('btn-restore');
$(this).find('span').removeClass('icon-maximize').addClass('icon-restore');
// swap tables
$('#table-dashboard-actions-mini').hide();
$('#table-dashboard-actions').show();
// show form
$('#form-dashboard-actions-btm').show();
// restyle panel
$(this).parents('.panel-dashboard').addClass('panel-dashboard-max');
// animate panel
$(this).parents('.panel-dashboard').animate({
width: "100%",
}, 250, function() {
// Animation complete.
});
$(this).parents('.panel-primary').animate({
height: "725px"
}, 250, function() {
// Animation complete.
});
});
As you can see, at one point the script changes the class of the clicked button to .btn-restore
However this means that I cannot seem to bind an event to .btn-restore
I originally had this:
// dashboard restore
$('#dashboard-actions .btn-restore').click(function() {
alert('asdf');
});
And the alert statement didn't work, so I changed it to this:
$('#dashboard-actions .btn-restore').on('click', function() {
But still no joy. Can anyone see what I'm doing wrong?
Upvotes: 1
Views: 2659
Reputation: 2608
As a couple of people have mentioned, event delegation is the key to binding to selectors that don't match yet. The alternative suggestion of binding to the generic selector .button
that will always exist and then maintaining the state (maximised or restored) in a variable is also valid.
Your issue with the panel opening and then immediately closing seems to be that you add the .btn-restore
class inside the event handler immediately. It shouldn't happen, but it seems like the click event is firing again on the new selector (perhaps something to do with mouseup
and mousedown
components of the click
event?). I'd suggest wrapping your addClass
calls within a setTimeout()
like so to ensure the classes are changed after any events fire, essentially "pushing" the change to the end of the current execution:
var $btn = $(this);
setTimeout(function () {
$btn.removeClass('btn-maximize').addClass('btn-restore');
$btn.find('span').removeClass('icon-maximize').addClass('icon-restore');
});
You'll notice the new variable $btn
. This is required because this
inside your setTimeout
function will no longer refer to the clicked element (a quick search for "javascript scope and this" or similar will explain this further if required). It also doesn't hurt to cache the $(this) result in any case.
Hope that works for you - let me know if I can be of further help.
Upvotes: 2
Reputation: 96
check the Jquery Documentation
So maybe you need to put something like this.
using the childs element of #dashboard-actions
$('#dashboard-actions .button').on('click', function() {})
and inside of the function using hasClass documentation
$(this).hasClass('className')
Upvotes: 0
Reputation: 20636
You need to use event delegation as the class changes dynamically.
$('#dashboard-actions').on('click','.btn-restore', function() {
When you bind the event handler initially, there exists no element with class btn-restore
, so the click event after class change does not fire.
Also, I see btn-maximize
being altered, of this is later added/toggled I woould suggest using a single common class like 'btn-toggle' and then add/remove btn-maximize/btn-restore
. This would prevent adding two separate event handlers.
Upvotes: 4
Reputation: 6689
Try this:
$(document).on('click','#dashboard-actions .btn-restore', function() {
instead of:
$('#dashboard-actions .btn-restore').on('click', function() {
Delegated events must be bind to something that exist in the dom and in the second part will define the element ('#dashboard-actions .btn-restore') you want to trigger click on.
Upvotes: 3