Jquery: Infinite loop and pause - javascript

I have this code
var timeout = 0;
$('#container td').each(function(){
var td = this;
setTimeout(function() {
var new_text = $(td).find(text).html();
popup_text.html(new_text);
popup.fadeIn('fast').delay(1000).fadeOut('slow');
}, timeout);
timeout += 1000 + 1000;
});
I get text from table cells and is displayed in the layer with a delay.
1 question: How do I make this code to run in an endless loop?
2 question: How to do that when you hover the mouse over popop cycle temporarily stopped and then continue?
Thanks a lot!

One way is to put the code to be repeated in a function, and have the function repeat itself at the end:
var timeout = 1000;
var action = function() {
// Do stuff here
setTimeout(action, timeout);
};
action();
However, as ahren suggested, setInterval might be better:
var timeout = 1000;
var action = function() {
// Do stuff here
};
setInterval(action, timeout);
The difference is slight, but if the machine is running slowly for some reason, the setInterval version will run the code every second on average, whereas the setTimeout version will run the code once each second at most.
Neither of those methods really work well with each(), however, so you'll need to store the sequence of popups somewhere and step through them:
var timeout = 1000;
var tds = $('#container td');
var index = 0;
var action = function() {
var td = tds[index];
var new_text = $(td).html();
popup.html(new_text);
popup.fadeIn('fast').delay(1000).fadeOut('slow');
if(++index >= tds.length)
index = 0;
};
setInterval(action, timeout);
action();
Finally, to avoid moving to the next popup while the popup is hovered, you can add a check for that at the start of the function. It's also necessary to rearrange the animations so that they go "check for hover - fade out - change text - fade in".
var timeout = 1000;
var tds = $('#container td');
var index = 0;
var action = function() {
if(popup.is(':hover'))
return;
var td = tds[index];
var new_text = $(td).html();
popup.fadeOut('slow', function() {
popup.html(new_text);
}).fadeIn('fast');
if(++index >= tds.length)
index = 0;
};
setInterval(action, timeout);
action();
jsFiddle: http://jsfiddle.net/qWkYE/2/

If you like the short clean way, then use the jquery-timing plugin and write:
$.fn.waitNoHover = function(){
return this.is(':hover') ? this.wait('mouseleave') : this;
};
$('#popups div').repeat().each($).fadeIn('fast',$)
.wait(200).waitNoHover().fadeOut('slow',$).all()
​
See this on http://jsfiddle.net/creativecouple/fPQdU/3/

Related

jQuery nicescroll is not working with dynamic content and other JavaScript function that makes random effect

So here is the thing, I have a sidebar that has big height due the lots of navigation links. And I'm using jQuery nicescroll plugin to make it look fine. In the sidebar I also have h3 tag which makes a random effect of showing letters (see the code) every 4 seconds. So, when it's on - scroll is not working at all for these 4 seconds and you can't do any scrolling. I tried to use $("#sidebar").getNiceScroll().resize() but it doesn't work either. Is there any way to make it work?
<div id="sidebar">
<h3 id="output">Random</h3>
</div>
//Calling for nicescroll function for my sidebar
$(function(){
$("#sidebar").niceScroll({ cursorcolor:"#66aee9", cursorfixedheight: 400 });
})
//Random effect for my h3 tag
setInterval(function(){
$(document).ready(function(){
var theLetters = "abcdefghijklmnopqrstuvwxyz#%&^+=-"; //You can customize what letters it will cycle through
var ctnt = "Random"; // Your text goes here
var speed = 50; // ms per frame
var increment = 8; // frames per step. Must be >2
var clen = ctnt.length;
var si = 0;
var stri = 0;
var block = "";
var fixed = "";
//Call self x times, whole function wrapped in setTimeout
(function rustle (i) {
setTimeout(function () {
if (--i){rustle(i);}
nextFrame(i);
si = si + 1;
}, speed);
})(clen*increment+1);
function nextFrame(pos){
for (var i=0; i<clen-stri; i++) {
//Random number
var num = Math.floor(theLetters.length * Math.random());
//Get random letter
var letter = theLetters.charAt(num);
block = block + letter;
}
if (si == (increment-1)){
stri++;
}
if (si == increment){
// Add a letter;
// every speed*10 ms
fixed = fixed + ctnt.charAt(stri - 1);
si = 0;
}
$("#output").html(fixed + block);
block = "";
}
});
}, 4000);
I change to rows and check it in jsfiddle, looks like working scroll fine.
Before:
setInterval(function(){
$(document).ready(function(){
...
});
}, 4000);
After:
$(document).ready(function(){
setInterval(function(){
...
}, 4000);
});

Javascript vanilla (jquery not preferred)

I'd like to know how to take this code I found here
http://jsfiddle.net/T42jj/
var imageGallery = [
"http://placehold.it/350x150",
"http://placehold.it/350x250",
"http://placehold.it/350x350",
"http://placehold.it/350x450"
];
var imgCount = 0; var totalImgs = imageGallery.length - 1; var timer;
function next() {
timer = setInterval(function fn() {
imgCount++;
if (imgCount > totalImgs) imgCount = 0
document.getElementById("gallery").src = imageGallery[imgCount];
return fn;
}(), 500)
}
function previous() {
timer = setInterval(function fn() {
console.log('prev')
imgCount--;
if (imgCount < 0) imgCount = totalImgs;
document.getElementById("gallery").src = imageGallery[imgCount];
return fn;
}(), 100)
}
function stopInterval() {
clearInterval(timer)
}
window.onmouseup = stopInterval;
and changing the "onMousedown" to onmouseOver so it continuously loops as you mouse over, which I've managed to do.
Then adding a stop function button that works
onmouseClick
Back
Stop
with a Stop function breaking the loop. e.g break;
sorry i cant figure out how to format any of this. this is the worst system ever.
does this [code] work? [/code]
or something like it?
basically look at the jsfiddle code and help me if you could make a function that stops the loop from infinitely repeating images when a mouse click event occurs.

setInterval doesnt tigger inner script on first time run

Maybe I'm not properly understanding setInterval but I have made a kind of slideshow script, as below:
var i = 0;
setInterval(function() {
$('.slide').fadeOut('slow').delay(200);
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i++;
if(i == 5){
i = 0;
}
}, 4000);
This works, except for the first run - no slides will display for the first 4 seconds.
See Fiddle here: http://jsfiddle.net/vpa89snf/6/
Is there anyway I can trigger whats inside the setInterval function when it runs the first time round?
Use setTimeOut instead of setInterval for better performance, inspect the sample below:
Here is working jsFiddle.
var i = -1;
var totalSlide = $('.slide').length-1;
var slideTimer = 0;
function nextFrame() {
i == totalSlide ? i = -1 : i;
i++;
$('.slide').fadeOut(200);
$('.slide').eq(i).fadeIn(200);
slideTimer = setTimeout(nextFrame,4000);
}
$('#holder').addClass('isAni');
nextFrame();
// play / pause animation
$('#holder').click(function() {
if ( $(this).hasClass('isAni') ) {
$(this).removeClass('isAni');
clearTimeout(slideTimer);
}else{
$(this).addClass('isAni');
nextFrame();
}
});
You need to run the function and not wait for the 4 first seconds:
var i = 0;
function doSomething() {
$('.slide').fadeOut('slow').delay(200);
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i = (i + 1) % 5;
}
$document.ready(function () {
setInterval(doSomething, 4000);
doSomething(); // run it!
});
JSFIDDLE.
This is how setInterval is executed. It runs your function after x milliseconds set as 2nd parameter.
What you have to do in order to show the first slide is to have the 1rst slide fadein like below:
var i = 0;
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i++;
setInterval(function() {
...
}, 4000);

Sequentially highlighting divs using javascript

I'm trying to create kind of runway of lights and here's what it looks like now
http://jsfiddle.net/7NQvq/
var divs = document.querySelectorAll('div');
var index = 0;
setInterval(function(){
if(index > divs.length+20){
index = 0;
}
if(divs[index-1]){
divs[index-1].className = '';
}
if(divs[index]){
divs[index].className = 'active';
}
index++;
}, 50);
What I don't like about it is that it's completely inflexible and hard to adjust. Furthermore it also runs additional 20 empty cycles which is wrong. Is there a better way to achieve it (preferrably pure JS)?
It seemes that there must be some combination of setInterval and setTimeout but I just can't make it work.
I've made some adjustments to use a CSS animation rather than messing around with transitions and class toggling.
Updated Fiddle
All the JavaScript does now is define the animation delay for each dot.
You can adjust:
The animation delay - I just have i/10, but you could make it i/5, i/20... experiment!
The animation duration - it's set to 1s in my Fiddle, but try shorter and longer to see what happens
The 50% that indicates when the light has faded out
How about
function cycle(selector, cssClass, interval) {
var elems = document.querySelectorAll(selector),
prev = elems[0],
index = 0,
cssClassRe = new RegExp("\\s*\\b" + cssClass + "\\b");
if (elems.length === 0) return;
return setInterval(function () {
if (prev) prev.className = prev.className.replace(cssClassRe, "");
index %= elems.length;
elems[index].className += " " + cssClass;
prev = elems[index++];
}, interval);
}
and
var runwayIntval = cycle("div", "active", 100);
and at some point
clearInterval(runwayIntval);
See: http://jsfiddle.net/arNY8/1/
Of course you could argue that toggling a CSS class is a little limited. You could work with two callback functions instead: one to switch on a freely definable effect, one to switch it off:
function cycle(elems, enable, disable, interval) {
var prev = elems[0], index = 0;
if (elems.length === 0) return;
return setInterval(function () {
index %= elems.length;
if (prev) disable.call(prev);
enable.call(elems[index]);
prev = elems[index++];
}, interval);
}
and
var cycleIntval = cycle(
document.querySelectorAll("div"),
function () {
this.className += " active";
},
function () {
this.className = this.className.replace(/\s*\bactive\b/, "");
},
100
);

How to stop my javascript countdown?

How can I stop my javascript function when countdown = 0?
JS:
var settimmer = 0;
$(function(){
window.setInterval(function() {
var timeCounter = $("b[id=show-time]").html();
var updateTime = eval(timeCounter)- eval(1);
$("b[id=show-time]").html(updateTime);
}, 1000);
});
HTML:
<b id="show-time">20</b>
For one thing remove those evals. They don't do anything.
Then all you have to do is clear the timer when it reaches zero.
$(function(){
var timer = setInterval(function() {
var timeCounter = parseInt($("b[id=show-time]").text());
$("b[id=show-time]").text(--timeCounter); // remove one
if(!timeCounter) clearInterval(timer);
}, 1000);
});
It is easy! When you call setInterval it return an ID, so you can destroy the interval later. To destroy it you must use clearInterval(id), and voilà!
It works like this:
// Activate timer
var iv = window.setInterval(...);
// Deactive timer
window.clearInterval(iv);
Also you should use parseInt() instead of eval():
$(function() {
// Read the start value once and store it in a variable
var timeCounter = parseInt( $("b[id=show-time]").text() );
// Active the counter
var iv = window.setInterval(function() {
// Decrement by one and write back into the document
$("b[id=show-time]").text(--timeCounter);
// Check if counter == 0 -> stop counting
if (0 == timeCounter) {
window.clearInterval(iv);
// ...do whatever else needs to be done when counter == 0 ..
}
}, 1000);
});
Example:
var i = 0,
pid = setInterval(function() {
if (++i > 10)
clearInterval(pid);
}, 1000);
Based on what you wanted for your code ...
$(function() {
var el = document.getElementById('show-time'),
pid = setInterval(function() {
// (s - i) coerces s to Number
var t = el.innerHTML - 1;
el.innerHTML = t;
if (t < 1)
clearInterval(pid);
}, 1000);
});
Keep in mind that JS won't be 100% accurate with its timing.
Pasted code below or see the fiddle: http://jsfiddle.net/raHrm/
<script type="text/javascript">
$(function(){
var settimmer = 0,
timeCounter = $("#show-time").html(),
updateTime = timeCounter;
(function countDown() {
timeCounter = $("#show-time").html();
updateTime = parseInt(timeCounter)-1;
$("#show-time").html(updateTime);
if ( updateTime ) {
setTimeout(countDown, 1000);
}
})();
});​
</script>
Set the timer to a variable, then use clearInterval in-order to stop the loop. As for catching the end, use a simple conditional:
$(function(){
var elem=$('strong[id="show-time"]'),settimmer=0,updateTime,t;
t=window.setInterval(function() {
updateTime=parseFloat(elem.html(),10)-1;
if(updateTime==0) {
window.clearInterval(t);
elem.html('Done!');
} else {
elem.html(updateTime);
}
},1000);
});
Then in the HTML:
<strong id="show-time">20</strong>
The <b> tag is depreciated, try to avoid using it. Also, there is no reason to eval() the HTML you are getting from the element; a simple parseFloat() works just fine.

Categories