Reputation: 6693
I am trying to get the button to change from the default 'this Will Change' to then change what it says to 'New message' and back to 'someButton' every 2 seconds and then stop it with a click.
So far, I have this code:
var timeouts = [];
var someArray = {button: 'new Message', button: 'Some Btn'};
$(document).ready(function(){
var i = 2000;
$.each(someArray, function(index, value){
timeouts.push(setTimeout(function(){
$(index).html(value);
},i));
i = i + 2000;
});
$('#stop').click(function(){
$.each(timeouts, function (_, id) {
clearTimeout(id);
});
timeouts = [];
$(button).html('Some Btn');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type='button'>
This will change
</button>
<a id='stop' href='#'>Stop</a>
It seems to ignore the first setTimeout()
or that timeout is not run on the New message index.. Then when I press the click button, no timeouts get cleared?
Any help would be greatly appreciated to where I'm going wrong.
Update: I'd like to keep this as jQuery oriented as possible, thanks!
Upvotes: 0
Views: 101
Reputation: 3051
Your use case describes exactly what a setInterval is meant for.
"Repeatedly calls a function or executes a code snippet, with a fixed time delay between each call. Returns an intervalID."
the setInterval
function returns an ID, which can be passed into clearInterval
to stop the code from executing every X seconds.
I've posted a code snippet to what I think you're trying to achieve.
var strings = ["This will change", "Some button"];
var intervalID;
var button;
var index = 0;
$(document).ready(function() {
button = $("#myButton");
intervalID = window.setInterval(function() {
console.log("hi");
button.html(strings[index]);
index = (index == 1 ? 0 : 1);
}, 2000);
$("#stop").click(function() {
window.clearInterval(intervalID);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="myButton" type='button'>
This will change
</button>
<a id='stop' href='#'>Stop</a>
Upvotes: 2
Reputation: 806
Here's a clean, functional way. Just for fun.
The selected answer is spot on. I'm just offering another option, using a slightly different style.
It starts, toggles and stops.
// "constant" array of messages
var messagesArray = ['new Message', 'Some Btn'];
// original button text
var btnOrigText = $('button').text()
// reverse an array
var _arrReverse = function(arr) {
return arr.reverse()
}
// insert text from array 0th index into an element
var _insertTextArrayZero = function(el, messages) {
// inserts an array's 0th index as HTML to an element
return $(el).html(messages[0]);
}
// clears a timeout when given an id
var _clearIntvlAt = function(intvlId) {
return clearTimeout(intvlId);
}
$(document).ready(function(){
// set interval
var intvl = 2000;
// keep our original array intact
var messagesCloned = messagesArray.slice(0)
// run interval
var toggleTextIntvl = setInterval(function() {
// insert reversed array from [0] index of array into HTML element
// NOTE: this only works for arrays of 2 items which need to toggle
return _insertTextArrayZero('button', _arrReverse(messagesCloned))
}, intvl);
// initiate "stopping" of toggle text
$('#stop').click(function() {
// stop toggleTextIntvl
_clearIntvlAt(toggleTextIntvl)
// set markup back to default
$('button').html(btnOrigText);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type='button'>
This will change
</button>
<a id='stop' href='#'>Stop</a>
Upvotes: 1
Reputation: 24955
The reason why its skipping new Message
is because of this:
var someArray = {button: 'new Message', button: 'Some Btn'};
Your someArray
is an object. So if you have same property name, it will get overriden and it will be parsed as
var someArray = {button: 'Some Btn'};
Just use a proper structure and it should work
var timeouts = [];
var someArray = [{
type: "button",
message: 'new Message',
}, {
type: "button",
message: 'Some Btn'
}];
$(document).ready(function() {
var i = 2000;
$.each(someArray, function(index, value) {
timeouts.push(setTimeout(function() {
$(value.type).html(value.message);
}, i));
i = i + 2000;
});
$('#stop').click(function() {
$.each(timeouts, function(_, id) {
clearTimeout(id);
});
timeouts = [];
$(button).html('Some Btn');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type='button'>
This will change
</button>
<a id='stop' href='#'>Stop</a>
This is how I would write. Few basic changes,
$(document).ready
as start of your code flow. Not as wrapper for your code. It should call to necessary function.Array.map
, Array.forEach
instead of $.each()
. These functions are very powerful and handy.$(document).ready(function() {
var someArray = [
{ type: "button", message: 'new Message', },
{ type: "button", message: 'Some Btn' }
];
var timeouts = registerTimeouts(someArray);
registerEvents(timeouts)
});
function registerTimeouts(array) {
return array.map(function(value, index) {
return setTimeout(function() {
$(value.type).html(value.message);
}, (index + 1) * 2000);
});
}
function registerEvents(timeouts) {
$('#stop').click(function() {
timeouts.forEach(function(id) {
clearTimeout(id);
});
timeouts = [];
$(button).html('Some Btn');
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type='button'>
This will change
</button>
<a id='stop' href='#'>Stop</a>
Upvotes: 2