Set count variable where it where - javascript

I have made this simple content rotator with jQuery which works fine, but as you can see I have made a mouseenter function so that the rotator stops if your mouse in on the rotator.
My problem is that if I mouseenter and leave the function rotateReview() is restarted and the count variable (number) is 1. So automatically my rotator starts at the beginning where he should continue to the next one.
HTML:
<div id="review_rotator">
<div class="rotator">
<article>Content</article>
<article>Content</article>
<article>Content</article>
<article>Content</article>
</div><!--End .rotator-->
</div><!--End #review_rotator-->
jQuery
function rotateReview() {
var turn = $('#review_rotator article');
var numbers = turn.length;
var number = 1;
intv = setInterval(function() {
number++;
turn.fadeOut(300);
$('#review_rotator article:nth-child('+number+')').fadeIn(200);
if(numbers == number)
number = 0;
}, 4500)
}
rotateReview();
$(document).on('mouseenter mouseleave', '#review_rotator article', function(e) {
var mEnt = e.type == 'mouseenter';
if(mEnt) {
clearInterval(intv);
} else {
rotateReview();
}
})

You could do it like this:
function rotateReview() {
var turn = $('#review_rotator article');
intv = setInterval(function() {
var next = ($('#review_rotator article[style*="display: block"]')).next()[0];
if(next == undefined)
next = turn[0];
console.log(next);
turn.fadeOut(300);
$(next).delay(300).fadeIn(200);
}, 1000)
}
Check it out: http://jsfiddle.net/b53t39u7/

Every time you run rotateReview, the variable number will be assigned value 1. So you should store it outside the function or somewhere else, so that the variable number won't be freed after the function rotateReview finished.
I'will give 2 solutions.
1. As a global variable
var number = 1;
function rotateReview() {
var turn = $('#review_rotator article');
var numbers = turn.length;
intv = setInterval(function() {
number++;
turn.fadeOut(300);
$('#review_rotator article:nth-child('+number+')').fadeIn(200);
if(numbers == number)
number = 0;
}, 4500)
}
2. Store in the closure
If you don't like global variable, you can store it in a closure, which is a immediately-invoked function.
var rotateReview = (function () {
var number = 1;
return function () {
var turn = $('#review_rotator article');
var numbers = turn.length;
intv = setInterval(function() {
number++;
turn.fadeOut(300);
$('#review_rotator article:nth-child('+number+')').fadeIn(200);
if(numbers == number)
number = 0;
}, 4500)
}
}());

Related

How to make a setInterval wait until another one finishes?

How, when I click "one" link, make the second counter wait until the first one finishes and then count up to 14 (as instructed on line 155)?
https://jsfiddle.net/c4khk69f/27/
The function responsible for "one" link is function progressSim() on line 43.
$('a').on('click', function(e) {
e.preventDefault();
jQuery('.canvasmotherwrap').hide();
jQuery('.canvasmotherwrap').fadeIn();
al = 0;
al2 = 0;
window.clearInterval(sim1_1);
window.clearInterval(sim1_2);
window.clearInterval(sim2);
var storedata = $(this).attr('data');
console.log(storedata)
window[storedata]();
});
var sim1_1;
var sim1_2;
var sim2;
window.one = function() {
sim1_1 = setInterval(progressSim, 10);
sim1_2 = setInterval(progressSim, 1000);
}
window.two = function() {
sim2 = setInterval(progressSim2, 10);
}
I'm not entirely sure I understand what you are after, but I think you want two counters and when the "first" one has finished then the second should start and count to "14".
I hope this helps:
function doWork(targetDiv, startTime, countTo, onDone) {
var ticker = setInterval(function(){
diff = (((Date.now() - startTime) / 500) | 0);
targetDiv.innerText = diff;
if(diff < countTo){ return; }
clearInterval(ticker);
if(typeof(onDone) === 'function') { onDone(); }
}, 100);
}
var divFoo = document.getElementById("foo");
var divBar = document.getElementById("bar");
// your on "click"
doWork(divFoo, Date.now(), 5, function(){
doWork(divBar, Date.now(), 14);
});
<table><tr>
<td><div id="foo">0</div></td>
<td><div id="bar">0</div></td>
</table>

Confused about SetInterval and closures

How can we repeatedly update the contents of a div using setInterval
I am using the question from this link as a reference How to repeatedly update the contents of a <div> by only using JavaScript?
but i have got few questions here
Can we do it without anonymous functions,using closures. I have tried but could not end up with any workable solution.
How can we make it run infinitely, with the following code it gets stopped once i reaches 10.
window.onload = function() {
var timing = document.getElementById("timer");
var i = 0;
var interval = setInterval(function() {
timing.innerHTML = i++;
if (i > 10) {
clearInterval(interval);
i = 0;
return;
}
}, 1000);
}
<div id="timer"></div>
I am confused about setIntervals and closures
can some one help me here
Thanks
You could do something like this with a closure. Just reset your i value so, you will always be within your given range.
window.onload = function() {
var updateContent = (function(idx) {
return function() {
if (idx === 10) {
idx = 0;
}
var timing = document.getElementById("timer");
timing.innerHTML = idx++;
}
})(0);
var interval = setInterval(updateContent, 1000);
}
<div id="timer"></div>
This one should be clearer.
function updateTimer() {
var timer = document.getElementById("timer");
var timerValue = parseInt(timer.getAttribute("data-timer-value")) + 1;
if (timerValue == 10) {
timerValue = 0;
}
timer.setAttribute("data-timer-value", timerValue);
timer.innerHTML = "the time is " + timerValue;
}
window.onload = function() {
setInterval(updateTimer, 1000);
}
<div id="timer" data-timer-value="0"></div>

Javascript Closure functions

So I'm new to javascript and I am looking for a way to count how many times a function is executed. The code randomly generates a square or circle and displays from the shape is shown to when you click it (reactionTime). That works fine and dandy.
But I'm looking for a way to keep track of the number of times a shape is clicked and then eventually the cumulative time to calculate average time per click. If it helps, I come from a pretty good C++ background.
To count number of clicks, I was thinking of adding a closure function.
From here: How do I find out how many times a function is called with javascript/jquery?
myFunction = (function(){
var count = 0;
return function(){
count++
alert( "I have been called " + count + " times");
}
})();
And from here: Function count calls
var increment = function() {
var i = 0;
return function() { return i += 1; };
};
var ob = increment();
But I tried a global variable and several variations of closure functions to no avail (look for the comments). I tried putting the closure function in other functions. And I also tried something like:
var increment = makeBox();
I'm wondering if anyone can guide me in the right direction. It would be much appreciated!
var clickedTime; var createdTime; var reactionTime;
var clicked; var avg = 0;
avg = (avg + reactionTime) / clicked;
document.getElementById("clicked").innerHTML = clicked;
document.getElementById("avg").innerHTML = avg;
function getRandomColor() {
....
}
function makeBox() { // This is the long function that makes box
createdTime = Date.now();
var time = Math.random();
time = time * 3000;
///////// var increment = function () {
var i = 0;
//return function() { return i += 1; };
i++;
return i;
///////// };
// clicked++; /////////// global variable returns NaN
// console.log(clicked);
// alert("Clicked: "+clicked);
setTimeout(function() {
if (Math.random() > 0.5) {
document.getElementById("box").style.borderRadius="75px"; }
else {
document.getElementById("box").style.borderRadius="0px"; }
var top = Math.random(); top = top * 300;
var left = Math.random(); left = left * 500;
document.getElementById("box").style.top = top+"px";
document.getElementById("box").style.left = left+"px";
document.getElementById("box").style.backgroundColor = getRandomColor();
document.getElementById("box").style.display = "block";
createdTime = Date.now();
}, time);
}
ob = increment(); //////////////////////// I think this gives me 1 every time
alert("Increment: "+ob); //////////////////
document.getElementById("box").onclick = function() {
clickedTime = Date.now();
reactionTime= (clickedTime - createdTime)/1000;
document.getElementById("time").innerHTML = reactionTime;
this.style.display = "none";
makeBox();
}
makeBox();
You have a few problems but to answer your question:
You're not defining clicked as a number (or any other type) so trying to perform an operation on undefined returns NaN...because well, it's not a number.
Your second attempt var i = 0; won't work because i is re-defined on each function call.
You should be able to use your gobal variable clicked as long as you set it to zero.
Here is an example that shows how a closure can count calls to a function:
function add5(y) {
//A totally normal function
return y + 5;
}
var counter = 0, /*a counter scoped outside of the function counter function*/
trackedAdd5 = (function (func) {
/*This anonymous function is incrementing a counter and then calling the function it is passed*/
return function () {
counter++;
/*The trick is this function returns the output of calling the passed in function (not that it is applying it by passing in the arguments)*/
return func.apply(this, arguments);
}
})(add5); /*calling this tracking function by passing the function to track*/
document.getElementById('run').addEventListener('click', function () {
/*Here we are treating this new trackedAdd5 as a normal function*/
var y = document.getElementById('y');
y.value = trackedAdd5(parseInt(y.value, 10));
/*Except the outer counter variable now represents the number of times this function has been called*/
document.getElementById('counter').value = counter;
});
<label> <code>y = </code>
<input id='y' value='0' />
<button id='run'>add5</button>
</label>
<br/>
<label><code>add5()</code> was called
<input readonly id='counter' value='0' />times</label>
makeBox.click = 0; // define the function's counter outside the function
makeBox.click++; // replace the `i` usage with this inside the function
About ob = increment();: it is used erroneously (redefines ob many times);
var ob = increment(); // define it once
ob(); // increments the counter
// another way to define `increment`:
var increment = (function () {
var i = 0;
return function () {
return i += 1;
};
})();
ob = increment(); // ob becomes 1 initially
ob = increment(); // ob becomes 2, etc.

Trying to randomize words from an array and stop the loop after 5

I'm trying to write a script that will pick a random word from an array called words, and stop the loop after 5 times and replace the html with Amazing. so it always ends on amazing. Can't figure out best practice for something like this. My thinking is there just don't know where to put the script ender or how to properly implement this.
I feel like I need to implement something like this into my script, but can't figure out where. Please help.
if(myLoop > 15) {
console.log(myLoop);
$("h1").html('AMAZING.');
}
else {
}
Here is the Javascript that I'm using to loop and create bring new words in.
$(document).ready(function(){
words = ['respected​', 'essential', 'tactical', 'effortless', 'credible', 'smart', 'lucid', 'engaging', 'focussed', 'effective', 'clear', 'relevant', 'strategic', 'trusted', 'compelling', 'admired', 'inspiring', 'cogent', 'impactful', 'valued']
var timer = 2000,
fadeSpeed = 500;
var count = words.length;
var position, x, myLoop;
$("h1").html(words[rand(count)]);
function rand(count) {
x = position;
position = Math.floor(Math.random() * count);
if (position != x) {
return position;
} else {
rand(count);
}
}
function newWord() {
//clearTimeout(myLoop); //clear timer
// get new random number
position = rand(count);
// change tagline
$("h1").fadeOut(fadeSpeed, function() {
$("h1").slideDown('slow'); $(this).html(words[position]).fadeIn(fadeSpeed);
});
myLoop = setTimeout(function() {newWord()}, timer);
}
myLoop = setTimeout(function() {newWord()}, timer);
});
Here's my codepen
http://codepen.io/alcoven/pen/bNwewb
Here's a solution, which uses a for loop and a closure.
Words are removed from the array using splice. This prevents repeats.
I'm using jQuery delay in place of setTimeout:
var i, word, rnd, words, fadeSpeed, timer;
words = ['respected​', 'essential', 'tactical', 'effortless', 'credible', 'smart', 'lucid', 'engaging', 'focused', 'effective', 'clear', 'relevant', 'strategic', 'trusted', 'compelling', 'admired', 'inspiring', 'cogent', 'impactful', 'valued'];
fadeSpeed = 500;
timer = 2000;
for(i = 0 ; i < 6 ; i ++) {
if(i===5) {
word= 'awesome';
}
else {
rnd= Math.floor(Math.random() * words.length);
word= words[rnd];
words.splice(rnd, 1);
}
(function(word) {
$('h1').fadeOut(fadeSpeed, function() {
$(this).html(word);
})
.slideDown('slow')
.delay(timer)
.fadeIn(fadeSpeed);
}
)(word);
}
h1 {
text-transform: uppercase;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1></h1>
I added an iteration counter to check how many times it has changed.
Added this by other variables:
var iter = 1;
Added this in the newWord function:
iter = iter + 1;
if (iter > 5) {
return;
}
var word;
if (iter == 5) {
word = 'awesome';
}
else {
...
Here's my solution by changing your code:
http://codepen.io/anon/pen/YPGWYd

Execute function IF another function is complete NOT when

I am having trouble creating a slider that pauses on hover, because I execute the animation function again on mouse off, if I flick the mouse over it rapidly (thereby calling the function multiple times) it starts to play up, I would like it so that the function is only called if the other function is complete, otherwise it does not call at all (to avoid queue build up and messy animations)
What's the easiest/best way to do this?
$(document).ready(function() {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var n = 1;
$('.slider_container').hover(function() {
//Mouse on
n = 0;
$('.slider').stop(true, false);
}, function() {
//Mouse off
n = 1;
if (fnct == 0) sliderLoop();
});
//Called in Slide Loop
function animateSlider() {
$('.slider').delay(3000).animate({ marginLeft: -(slide_width * i) }, function() {
i++;
sliderLoop();
});
}
var i = 0;
var fnct = 0
//Called in Doc Load
function sliderLoop() {
fnct = 1
if(n == 1) {
if (i < number_of_slides) {
animateSlider();
}
else
{
i = 0;
sliderLoop();
}
}
fnct = 0
}
sliderLoop();
});
The slider works fine normally, but if I quickly move my mouse on and off it, then the slider starts jolting back and forth rapidly...been trying to come up with a solution for this for hours now..
Here's what fixed it, works a charm!
$(document).ready(function() {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var n = 1;
var t = 0;
$('.slider_container').hover(function() {
clearInterval(t);
}, function() {
t = setInterval(sliderLoop,3000);
});
var marginSize = i = 1;
var fnctcmp = 0;
//Called in Doc Load
function sliderLoop() {
if (i < number_of_slides) {
marginSize = -(slide_width * i++);
}
else
{
marginSize = i = 1;
}
$('.slider').animate({ marginLeft: marginSize });
}
t = setInterval(sliderLoop,3000);
});

Categories

Resources