jQuery fade in and fade out list of messages

Viewed 122

I tried modifying the code below in order to fade through a list of messages and I need it to stop at the last message, I managed to do it but the last message keeps on fading in and out and I can't figure out how to stop it from fading like a dim bulb.

<script>jQuery(function($) {$(document).ready(function(){
      $("button").click(function(){
    $("#demo").fadeTo( "slow", 1 );
        (function($){
        $.fn.extend({
            rotaterator: function(options) {

                var defaults = {
                    fadeSpeed: 500,
                    pauseSpeed: 100,
                    child:null
                };

                var options = $.extend(defaults, options);

                return this.each(function() {
                      var o =options;
                      var obj = $(this);
                      var items = $(obj.children(), obj);
                      items.each(function() {$(this).hide();})
                      if(!o.child){var next = $(obj).children(':first');
                      }else{var next = o.child;
                      }
                      $(next).fadeIn(o.fadeSpeed, function() {
                            $(next).delay(o.pauseSpeed).fadeOut(o.fadeSpeed, function() {
                                var next = $(this).next();
                                if (next.length == 0){
                                        next = $(obj).children(':last');
                                }
                                $(obj).rotaterator({child : next, fadeSpeed : o.fadeSpeed, pauseSpeed : o.pauseSpeed});
                            })
                        });
                });
            }
        });
    })(jQuery);

     $(document).ready(function() {
            $('#rotate').rotaterator({fadeSpeed:500, pauseSpeed:100});
     });
      });
    });});</script>

    <button class="btn" type="submit" style="min-width: 200px;margin-top: 40px;margin-bottom: 0px;" onclick="myFunction()">Sign Up!</button>
    <h1 id="demo" style="opacity:0;"> I am <div id="rotate"> <div>awesome.</div> <div>invincible.</div> <div>unbeatable.</div> <div>indestructible.</div> </div> </h1>
1 Answers

That's some pretty fancy code! I probably would have tried a much simpler solution, but what you have is a nice and flexible jQuery function.

Here's a JSFiddle of your code with only one change - to stop the animation after the last element has been displayed, which is what you need.

The problem was that this code:

if (next.length == 0) {
    next = $(obj).children(':last');
}

Says that when there is no "next" element to animate, to instead use the last element in the set you are animating (#rotate in your example). So once it hits the last item and can't find another, it just cycles, reanimating the last item, and will never stop.

To fix that problem, I:

  • Removed that code shown above;

  • Added a new test so that when the item we are animating is the last one in the set, bail out early, before fading it out and looking for another to fade in. To do that test, I find the .index() of the current element in the set, and compare that to the total number of elements. The index is zero-based, whereas the count isn't of course, so I need to add 1 to the index value:

    if (next.index() +1 === items.length) {
        return;
    }
    

And now your code works as you intended.

However there are a few issues with that code which need fixing:

  • The button has an onclick="myFunction()", but myFunction() is not defined. AFAICT the button click handler in the JS is all you need, and is better practice than using inline onClick handlers, so I removed that.

  • AFAIK jQuery(function($) { and $(document).ready(function() { are basically the same, and only one should be used.

  • Likewise there's no need to wrap the jQuery function definition inside another self-executing (function($) {.

  • The jQuery function definition shouldn't be defined inside the click handler.

  • The actual call to run rotaterator() is wrapped inside a $(document).ready(function() {, but the code is already nested inside another of those, they shouldn't be nested/doubled up like that.

  • Minor thing - the next variable is defined as a jQuery object, so you can use it like next.fadeIn(), there is no need to use it like $(next).

  • In the click handler, this code would fade in your entire h1:

    $("#demo").fadeTo("slow", 1);
    

    I'm guessing you have some CSS which makes it initially not visible? I've added that.

Here's another JSFiddle with all those changes.

Related