Search code examples
javascriptjqueryfadeout

jQuery fadeOut not working when looping


I'm trying to implement this script which will append words from an array onto a <p> tag, which when completed will replace the full sentence with another phrase and then start over again.

The problem i am getting is when applying a fade out effect when transitioning out of the second phrase and back into appending the first phrase which has a fade in effect. Without the fade out effect, it works as expected but when included it will not loop back to the start.

Can anyone help me figure out why the fade out effect messes up the code and how to get it working with the fade out effect.

Here is the broken code:

var index = 0;
Start();

function Start() { // DOM ready
  var str = ["First", ", Second", ", Third", ", Fourth."];
  var spans = '<span>' + str.join('</span><span>') + '</span>';
  $(spans).hide().appendTo('#motto').each(function(i) {
    $(this).delay(2000 * i).fadeIn('slow', 'swing', function() {
      if (index == 3) {
        setTimeout(Restart, 2000);
      } else {
        index++;
      }
    });
  });
}

function Restart() {
  $('#motto').fadeIn('slow', 'swing', function() {
    var div = $("<p id='motto'>Second Phrase.</p>").hide();
    $('#motto').replaceWith(div);
    $('#motto').fadeIn("slow", 'swing', function() {
      setTimeout(function() {
        var reset = $("<p id='motto'></p>").hide();
        $('#motto').replaceWith(reset).fadeOut('slow', 'swing', function() {
          index = 0;
          Start();
        });
      }, 3000);
    });
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="motto"></p>

Here is the code without the fade out effect:

var index = 0;
Start();

function Start() { // DOM ready
  var str = ["We Listen", ", We Plan", ", We Advise", ", We Deploy."];
  var spans = '<span>' + str.join('</span><span>') + '</span>';
  $(spans).hide().appendTo('#motto').each(function(i) {
    $(this).delay(2000 * i).fadeIn('slow', 'swing', function() {
      if (index == 3) {
        setTimeout(Restart, 2000);
      } else {
        index++;
      }
    });
  });
}

function Restart() {
  $('#motto').fadeIn('slow', 'swing', function() {
    var secondPhrase = $("<p id='motto'>Everything you need for a successful implementation.</p>").hide();
    $('#motto').replaceWith(secondPhrase);
    $('#motto').fadeIn("slow", 'swing', function() {
      setTimeout(function() {
        var reset = $("<p id='motto'></p>");
        $('#motto').replaceWith(reset);
        index = 0;
        Start();
      }, 3000);
    });
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="motto"></p>


Solution

  • It's because you have .hide() tacked on to the end of the reset declaration in the broken example. If you remove that method call, the code loops fine.

    Working solution:

    var index = 0;
    Start();
    
    function Start() { // DOM ready
      var str = ["First", ", Second", ", Third", ", Fourth."];
      var spans = '<span>' + str.join('</span><span>') + '</span>';
      $(spans).hide().appendTo('#motto').each(function(i) {
        $(this).delay(2000 * i).fadeIn('slow', 'swing', function() {
          if (index == 3) {
            setTimeout(Restart, 2000);
          } else {
            index++;
          }
        });
      });
    }
    
    function Restart() {
      $('#motto').fadeIn('slow', 'swing', function() {
        var div = $("<p id='motto'>Second Phrase.</p>").hide();
        $('#motto').replaceWith(div);
        $('#motto').fadeIn("slow", 'swing', function() {
          setTimeout(function() {
            var reset = $("<p id='motto'></p>");
            $('#motto').replaceWith(reset).fadeOut('slow', 'swing', function() {
              index = 0;
              Start();
            });
          }, 3000);
        });
      });
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <p id="motto"></p>