简体   繁体   中英

How to prevent jQuery function from being initialized more than once (Drupal behaviours involved)?

My goal: To enable a user to load a template (which contains preset jquery, html and css) to allow them to click one of five dots to trigger an animation on an image.

My issue: When I load more than one of these templates to my page, my animation value (margin-left in this case) applies double the number of times that there is an instance of this template on the page. If my template is loaded twice, the margin-left sets to a value, jumps to the correct value, then back before finally setting on the correct value. This means that if I was to add 10 instances to the page, it would take 20 times as long to get that last value.

Before testing I thought that my code would be ok, as due to the context and .once() function, I believed it would only fire once.

All html and CSS are functioning as expected, it's just the jQuery is an issue.

My code:

(function ($) {
 Drupal.behaviors.click_the_dots = {
  attach: function (context, settings) {
   $('.wrapper_class', context).once('click_the_dots', function () {
    // Prevent other buttons from being clickable until the
    // previous animation is complete.
    var animationDone = false;

    function clickDots(dotNum) {
      $('.dot_class_num_' + dotNum).click(function () {
        // Setup context, to keep animations to the container in which the dots exist.
        var findElem = $(this).parent().parent().parent().find('.inner_wrapper');
        // Prevent other buttons from being clickable until the
        // previous animation is complete.
        if (animationDone === false) {
          animationDone = true;
          // Find the visible image.
          var animatingImage = findElem.find('.dot_class_num_active');
          // Find the image that will be animating in.
          var thisImageAnim = findElem.find('.dot_num_img_src_' + dotNum);
          if (animatingImage.is(thisImageAnim)) {
            // Can't click on the same dot again, until another dot is clicked.
            animationDone = false;
            return;
          } else {
            // Animate out the already visible image.
            // Remove the visible image class as it's going to be hidden.
            findElem.find('.dot_class_num_active').removeClass('dot_class_num_active');
            // Animate it to hide to the left.
            animatingImage.animate({
              marginLeft: '-10%',
              opacity: 0
            }, 280, 'easeInOutQuad');
            // Animate in the image associated with the dot click
            // Set the image css to be further right in order to animate to left at 0.
            thisImageAnim.css('margin-left', '10%').delay(200).animate({
              marginLeft: '0',
              opacity: 1
            }, 300, 'easeInOutQuad', function () {
              // Set the now visible image to the visible image.
              thisImageAnim.addClass('dot_class_num_active');
            }).promise().done(function () {
              // Now allow the other dots to be clicked.
              animationDone = false;
            });
          }
        }
      });
    }

    // For each of the five dots.
    for (i = 1; i <= 5; i++) {
      clickDots(i);
    }
});}};})(jQuery);

I would like to add as many instances of this jQuery as required, but only have the function be looped through once. I'm not sure how to check if this has already been done, or how to ensure that once it has been done at least once, it shouldn't happen again.

:)

I figured out what my issue was - I was attaching the behaviour to the wrapper class of my content, ie $('.wrapper_class', context).once... - this meant that it attached the behaviour to each instance of this class, of which there could be many.

What I did was attach the behaviour to a higher parent element, of which I knew there would be only one instance. It attaches just once and the code works perfectly.

Thanks to the commenters above who helped me realise my issue!

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