0

Thought I had this in the bag...guess I was wrong:

Expected behavior - page loads, then for each element in the array it updates my innerHTML value using setTimeout

Observed behavior - On my hosting it seems to update the value just one time, then it breaks my css before becoming unresponsive. I threw in an alert to see if it's ever running on jsFiddle and it appears to not be running so there's also that 😰

The markup:

<button type="button" id="ctaButton" class="cta btn btn-lg btn-success pulsate" data-keyboard="true" data-toggle="modal" data-target="#contactUs">Get Started Today</button>

The JS:

$(warmup());

function warmup(){
    //sanity check
confirm("working???");
    setTimeout(changeCTAtext, 3000);
}



 function changeCTAtext(){

    var ctaList = [ 'Complementary Quotes', 'Book Your Consultation', 'Get Started Today' ];
    var myField = document.getElementById("ctaButton");

    while (true){
        for (var i = 0; i<ctaList.length, i++;){
    setTimeout('myField.innerHTML = ctaList[i];', 1000);
        };
    };
};

and here is the mandatory fiddle as usually requested.

3
  • setTimeout("changeCTAtext()", 3000); should be setTimeout(changeCTAtext, 3000); to prevent EVAL-ing the string. Commented May 4, 2016 at 21:36
  • alright I'll fix that accordingly...do you think it's happening because I have to wrap 'myField.innerHTML = ctaList[i];' in an anonymous function? Commented May 4, 2016 at 21:41
  • 1
    the while loop is stacking massive amounts of timers... this is probably a bad thing. Commented May 4, 2016 at 21:51

2 Answers 2

1

There's absolutely no need to set synchronous multiple timeouts inside a loop.
Use only a single setInterval or recall a function than has a single setTimeout

You could easily do this using setInterval()

If you want to make your code simpler (without the iterations counter) you could just manipulate the Array like:

jQuery(function($){

  var $btn = $("#ctaButton"),
      ctaList = ['Get Started Today', 'Complementary Quotes', 'Book Your Consultation'];
  
  function changeCTAtext(){
    ctaList.push( ctaList.shift() ); // manipulate
    $btn.html( ctaList[0] );         // and use always the [0]th index
  };

  setInterval(changeCTAtext, 1000); // Start

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button  id="ctaButton">Get Started Today</button>

usign a c counter and loop using ++c % array.length

jQuery(function($){

  var $btn = $("#ctaButton"),
      ctaList = ['Get Started Today', 'Complementary Quotes', 'Book Your Consultation'],
      tot = ctaList.length,
      c = 0; // iterations counter
  
  function changeCTAtext(){
    $btn.html( ctaList[++c%tot] );
  };

  setInterval(changeCTAtext, 1000); // Start

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button  id="ctaButton">Get Started Today</button>

Using setTimeout() it's like this:

jQuery(function($){

  var $btn = $("#ctaButton"),
      ctaList = ['Get Started Today', 'Complementary Quotes', 'Book Your Consultation'],
      tot = ctaList.length,
      c = 0; // iterations counter
  
  function changeCTAtext(){
    $btn.html( ctaList[c++%tot] );
    setTimeout(changeCTAtext, 1000); // ...and repeat every NNNms
  };

  changeCTAtext(); // Start

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button  id="ctaButton">Get Started Today</button>

Sign up to request clarification or add additional context in comments.

4 Comments

is the $ in front of $btn required because its assigned to a jquery selector?
@Frankenmint yes but it's not required. It's just a useful way to know that a variable is assigned to a jQuery object. Let's say you're looking at someone's code, when you see i.e: $value you'll know immediately that it's not a string or a number but a reference to a DOM element.
okay so it's more of a styling preference and has no impact on code execution?
@Frankenmint yes and a totally useful one. I also use it all the time and like really much seeing developers use it too. $ is just a character as _ or aZ allowed in variable names. You coul've used btn aswell. But following the above logic it's good to be consistent troughout the whole code.
1

I found two mistakes in your code:

  1. setTimeout first param should be a function. So it should be written as follows

setTimeout(changeCTAtext, 3000);

and

while (true){
    for (var i = 0; i < ctaList.length; i++){
setTimeout(function(){myField.innerHTML = ctaList[i]}, 1000);
    };
};
  1. When you use the iterated index of a for loop inside a timeout, when the timeout ends the index has already changed. Thus you need to bind the index in each iteration. There are several fixes for this, one of them is placing the timeout inside an IIFE with the index as closure:

.

for (var i=0; i < ctaList.length; i++) {
  (setTimeout(function(i) {myField.innerHTML = ctaList[i]}, 1000)(i);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.