简体   繁体   中英

jQuery not recognising change of class on element

OK so I made a custom function which I can then call using a div's class.

I target the class 'back' then this function is applied which enlarges and moves the div. Once this animation is complete, I remove the class 'back' and add the class 'front'.

I have another function which is looking for a click on the element with class 'front', however when I click this element, which only has the class 'front' and not 'back' it is still triggering the first function.

How can this be if it doesn't have that class anymore?

Here is my code...

$(document).ready(function () {
    "use strict";

    (function ($) {
        $.fn.expand = function () {

            var wide = this.css('width').replace(/[^-\d\.]/g, '') * 10;
            var high = this.css('height').replace(/[^-\d\.]/g, '') * 10;
            var marg = -(wide / 2);
            $(this).removeClass('back');
            $(this).animate({
                'width': wide,
                'height': high,
                'margin-left': marg,
                'bottom': '0'
            }, 3000, 'easeInOutCubic', function () {
                $(this).addClass('front');
            });

        };
    })(jQuery);

    $('.back').click(function () {
        $(this).expand();
        $('.wall').animate({
            'bottom': '+=10px'
        }, 3000, 'easeInOutCubic');
    });

    $('.front').click(function () {
        $('.wall').animate({
            'bottom': '-=100px'
        }, 300);
        $('.floor').animate({
            'bottom': '-=100px'
        }, 300);
    });
}); // JavaScript Document

...and the current file here.. http://thetally.efinancialnews.com/tallyassets/chinahurdles/index.html

The problem is caused by statically attaching event handlers to elements with classes of .back and .front at load time . The handers stay attached to those specific elements, even if you change the classes.

As the classes change dynamically, use delegated event handlers attached to a non-changing ancestor element ( document is the best default if nothing else is closer/convenient) .

$(document).on('click', '.back', function() {
    $(this).expand();
    $('.wall').animate({'bottom':'+=10px'}, 3000, 'easeInOutCubic');
});

$(document).on('click', '.front', function() {
    $('.wall').animate({'bottom':'-=100px'}, 300);
    $('.floor').animate({'bottom':'-=100px'}, 300);
});

Delegated events work by listening for an event to bubble up to the targeted ancestor element (in this case document ), then they apply the jQuery selector to only the elements in the bubble chain , then it applies the function to any matching elements that actually caused the event .

Basically they evaluate the selector at event time , not when the event was registered , so work with dynamically changed/added content.

Side note:

You have nested two DOM ready handlers. $(function ($) { is just a shortcut for $(document).ready( with a locally scoped $ . Although nesting DOM ready handlers is harmless, it is a waste (as the inner one fires immediately)

Use either just this:

$(document).ready(function () {
    "use strict";
    $.fn.expand = function () {

or

jQuery(function ($) {
    $.fn.expand = function () {
    ...
});

The problem is that browser reads all your handlers and applies its ones page is loaded. So it's wrong to set handler to class. Class is only specifier to find specific DOM element

I suggest you to use next solution Use on event on any parent element and apply your handler to it

$(document).on('click', '.front', function() {
});

$(document).on('click', '.back', function() {
});

So each time your click has fired on element it propagates to element with handler, and will search to call exactly callback with specific selector (class .back or .front)

You have added a listener to the DOM element. Changing the elements classes won't remove the listeners you have already attached. The closest solution to what you have tried to do with classes would be something like this:

$( document ).ready(function() {
    "use strict";

    (function($){
        $.fn.expand = function() {

            var wide = this.css('width').replace(/[^-\d\.]/g, '')*10;
            var high = this.css('height').replace(/[^-\d\.]/g, '')*10;

            var marg = - ( wide / 2 );

            $(this).unbind("click");
            $(this).animate({'width' : wide ,'height': high, 'margin-left': marg, 'bottom':'0' }, 3000, 'easeInOutCubic', function() {
                $(this).click(frontFunction);
            });

        };

        $('.back').click(backFunction);
    })(jQuery);

    var backFunction = function() {
        $(this).expand();
        $('.wall').animate({'bottom':'+=10px'}, 3000, 'easeInOutCubic');
    };

    var frontFunction = function() {
        $('.wall').animate({'bottom':'-=100px'}, 300);
        $('.floor').animate({'bottom':'-=100px'}, 300);
    };


});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM