I am trying to get a slider to stop auto sliding as soon as the user clicks on the next arrow. The slider should stop and come to a full pause as the user clicks on the next slider.
I put all of the slider code into a function called dontRun. I initially set it to dontRun(1) so that it meets the conditional and the slider functions upon loading the page. Once the user clicks on the next arrow, I have it go to the function dontRun(0) which should set the autoplay to a slow amount so that it no longer autoslides.
The problem is that while dontRun(0) is working, it is not accessing the autoplay feature, nor is it stopping the slider.
How can this be fixed?
function dontRun(value){
if(value === 1) {
var wallopEl = document.querySelector('.Wallop');
var wallop = new Wallop(wallopEl);
// To start Autoplay, just call the function below
// and pass in the number of seconds as interval
// if you want to start autoplay after a while
// you can wrap this in a setTimeout(); function
autoplay(5000);
// This a a helper function to build a simple
// auto-play functionality.
function autoplay(interval) {
var lastTime = 0;
function frame(timestamp) {
var update = timestamp - lastTime >= interval;
if (update) {
wallop.next();
lastTime = timestamp;
}
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
};
}//if
else if (value === 0){
alert("This slider should not be auto updating anymore.");
autoplay(50000000000);
}
}// end of function
dontRun(1);
$(".Next").click(function(){
dontRun(0);
})
Your autoplay function cannot be called due to its accessibility. You need take out the function and add before dontRun method.
function autoplay(interval) {
console.log('called');
};
function dontRun(value){
autoplay(5000);
// logic
}
function autoplay(interval) {
console.log('called');
var lastTime = 0;
function frame(timestamp) {
var update = timestamp - lastTime >= interval;
if (update) {
wallop.next();
lastTime = timestamp;
}
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
};
function dontRun(value) {
if (value === 1) {
var wallopEl = document.querySelector('.Wallop');
var wallop = new Wallop(wallopEl);
// To start Autoplay, just call the function below
// and pass in the number of seconds as interval
// if you want to start autoplay after a while
// you can wrap this in a setTimeout(); function
autoplay(5000);
// This a a helper function to build a simple
// auto-play functionality.
} //if
else if (value === 0) {
alert("This slider should not be auto updating anymore.");
autoplay(50000000000);
}
} // end of function
//dontRun(0);
function clickMe() {
console.log('clicked');
dontRun(0);
}
#btntag {
width: 100px;
height: 50px;
}
<button onclick="clickMe()" id="btntag">click</button>
Related
Why is timeout not being cleared in this setup? How can I make up() stop the delayed actions from running?
var active = false;
var delay;
window.addEventListener("mousedown", down, false);
window.addEventListener("mouseup", up, false);
window.addEventListener("mousemove", move, false);
function down(e) {
active = true;
console.log("down")
window.scrollTo(0,document.body.scrollHeight);
}
function up(e) {
active = false;
clearTimeout(delay); //expecting this to clear delay
console.log("up")
window.scrollTo(0,document.body.scrollHeight);
}
function move(e) {
if (active) {
delay = setTimeout(function() {
console.log("move")
window.scrollTo(0,document.body.scrollHeight);
}, 50);
}
}
Expecting delay to be cleared on mouseup but it still executes.
You keep making timeouts on every movement. It does not replace the last one...
Your code is basically this
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- will run
delay = setTimeout(function() { } <-- cancels this one
window.clearTimeout(delay)
So you need to remove it before you create a new one
if (active) {
if (delay) window.clearTimeout(delay)
delay = setTimeout(function() {
console.log("move")
window.scrollTo(0,document.body.scrollHeight);
}, 50);
}
If you need to move to fire more than once, that you want to look into throttling scripts.
So, I've learned from the replies that setTimeout produces a new independent timer every time move() is executed. My understanding was that each new timer overwrites the previous one but as this is not the case I had to think of something else.
I did't really explain what I actually needed to achieve with the delay so let me clarify. I want to create a timeout for an action if that action has not been executed for x amount of time. Using setTimeout on the action it self created the problem that the action would still potentially have multiple queued executions waiting to happen even after mouseup events.
So instead I used setTimeout on a new variable that acts as a lock to the action. The result is the following code:
var active = false;
var actionTimeout = false;
var actionTimeStamp;
var actionLock = false;
window.addEventListener("mousedown", down, false);
window.addEventListener("mouseup", up, false);
window.addEventListener("mousemove", move, false);
function down(e) {
active = true;
console.log("down")
window.scrollTo(0,document.body.scrollHeight);
}
function up(e) {
active = false;
console.log("up")
window.scrollTo(0,document.body.scrollHeight);
}
function move(e) {
if (active) {
if ((Date.now() - actionTimeStamp > 500) && (!actionTimeout)) { // get time elapsed and compare to threshold (500ms)
actionTimeout = true; //this is for the if statement above to prevent multiple timeouts
actionLock = false; // set the lock
setTimeout(function() { // remove lock after 50ms
actionTimeout = false;
actionLock = true;
actionTimeStamp = Date.now(); // timestamp here to make sure we don't lock again to soon. (helps if setTimeout is => than threshold.
}, 50);
}
if (actionLock) { //do our action
console.log("move")
window.scrollTo(0,document.body.scrollHeight);
actionTimeStamp = Date.now(); // timestamp last execution
}
}
}
Thanks to everyone for chipping in with comments and answers. Really appreciated.
Answer:
There are a few things to adjust in your code:
Instead of continuously reassigning delay with a new Timeout Timer, simply use an Interval.
You should only set the Timer if the state is active AND delay does not exist already. this stops multiple Timers from existing
There are a few things to adjust and understand about Timers in JavaScript:
When you set a Timer, the variable that houses the Timer is set to return an Integer. This is the ID of the Timer in the current scope.
When you clear a Timer, the variable isn't reset to undefined - it stays the same Integer/ID. This is because you're not clearing the variable, the scope is stopping the Timer that matches the ID the variable houses.
Because of the above you have to explicitly set the variable housing the Timer to undefined (or some other falsy value) after clearing it for an existence check to work.
var active = false;
var delay;
window.addEventListener("mousedown", down, false);
window.addEventListener("mouseup", up, false);
window.addEventListener("mousemove", move, false);
function down(e) {
active = true;
console.log("down")
window.scrollTo(0,document.body.scrollHeight);
}
function up(e) {
active = false;
clearTimeout(delay); //expecting this to clear delay
delay = undefined;
console.log("up")
window.scrollTo(0,document.body.scrollHeight);
}
function move(e) {
if (active) {
if(!delay) {
delay = setInterval(function() {
console.log("move")
window.scrollTo(0,document.body.scrollHeight);
}, 50);
}
}
else { //fallback in case of Browser Queuing issues
if(delay) {
clearTimeout(delay);
delay = undefined;
}
}
}
Edited
Due to comments with issues I added a fallback in mousemove that will remove the timer if the state is inactive, but delay is still defined. I don't believe that you technically should need this, but in practice Browser Event Queuing and Timers occasionally don't get along as expected.
hello i try to create the function to prevent the other function to run for 10 minutes IF user close the content and refresh the page.
the other function is to show the content when we scroll with 2 argument
first: it will run the function with first argument with no interval, if user click close and refresh. it will run the second argument that give interval
heres my code.
https://jsfiddle.net/8c1ng49a/1/
please look this code
var popUp= document.getElementById("popup");
var closePopUp= document.getElementsByClassName('popup-close');
var halfScreen= document.body.offsetHeight/2;
var showOnce = true;
var delay;
function slideUp(){
popUp.style.maxHeight="400px";
popUp.style.padding="10px 20px";
popUp.style.opacity="1";
if(popUp.className==="closed"){
popUp.className="";
}
}
function slideDown(){
popUp.style.maxHeight="0";
popUp.style.padding="0 20px";
popUp.style.opacity="0";
// add class closed for cache
if(popUp.className===""){
popUp.className="closed";
localStorage.setItem('closed', 'true'); //store state in localStorage
}
}
// start interval
function startDelay() {
delay = setInterval(slideUp, 1000);
}
// clear interval
function clearDelay() {
window.clearTimeout(delay);
}
// check if cache heve class close
window.onload = function() {
var closed = localStorage.getItem('closed');
if(closed === 'true'){
popUp.className="closed";
}
}
// show popup when scroll 50%
window.onscroll = function scroll(ev) {
// first time visited
if ((window.innerHeight+window.scrollY) >= halfScreen && showOnce) {
slideUp();
showOnce = false;
}
//same user mutilple time visited the site
else if((popUp.className==="closed" && window.innerHeight+window.scrollY) >= halfScreen && showOnce ){
startDelay();
showOnce = false;
}
};
// close button when click close
for(var i = 0; i<closePopUp.length; i++){
closePopUp[i].addEventListener('click', function(event) {
slideDown();
});
}
my interval didnt work onthe second argument its fire when i refresh, i dont know why.
but if add startDelay on my first arguments its work. but i need to place the interval on my second argu
When you want to make delay use setTimeout function.
Here is documentation of this function.
setInterval Repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.
I have a click event that has a Jquery animation in it.
How can i guarantee that the animation has finished when multiple click events are being fired.
$(this._ScrollBarTrack).click(function(e) {
if(e.target === this && _self._horizontalClickScrollingFlag === false){
_self._horizontalClickScrollingFlag = true;
if(_self._isVertical){
} else{ //horizontal
if(e.offsetX > (this.firstChild.offsetWidth + this.firstChild.offsetLeft)){ // Moving Towards Right
var scrollableAmountToMove = _self._arrayOfCellSizes[_self._scrollBarCurrentStep + 1]; // additional amount to move
var scrollableCurrentPosition = -($(_self._bodyScrollable).position().left);
var scrollBarCurrentPosition = $(_self._ScrollBarTrackPiece).position().left;
var scrollBarAmountToMove = _self.getScrollBarTrackPiecePositionBasedOnScrollablePosition(scrollableAmountToMove);
$(".event-scroll-horizontally").animate({left:-(scrollableCurrentPosition+ scrollableAmountToMove)});
$(_self._ScrollBarTrackPiece).animate({left: (scrollBarCurrentPosition + scrollBarAmountToMove)});
_self._scrollBarCurrentStep += 1;
} else{
var scrollableAmountToMove = _self._arrayOfCellSizes[_self._scrollBarCurrentStep - 1]; // additional amount to move
var scrollableCurrentPosition = -($(_self._bodyScrollable).position().left);
var scrollBarCurrentPosition = $(_self._ScrollBarTrackPiece).position().left;
var scrollBarAmountToMove = _self.getScrollBarTrackPiecePositionBasedOnScrollablePosition(scrollableAmountToMove);
$(".event-scroll-horizontally").animate({left:-(scrollableCurrentPosition - scrollableAmountToMove)});
$(_self._ScrollBarTrackPiece).animate({left: (scrollBarCurrentPosition - scrollBarAmountToMove)});
_self._scrollBarCurrentStep -= 1;
}
}
_self._horizontalClickScrollingFlag = false;
}
});
jQuery has a hidden (I'm not sure why it's not in the docs someplace) variable $.timers that you can test against.
I made this function a long time ago to handle situations like this. Mind you, this will test to make sure there are NO animations currently being executed.
function animationsTest (callback) {
var testAnimationInterval = setInterval(function () {
if ($.timers.length === 0) { // any page animations finished
clearInterval(testAnimationInterval);
callback(); // callback function
}
}, 25);
};
Useage: jsFiddle DEMO
animationsTest(function () {
/* your code here will run when no animations are occuring */
});
If you want to test against one individually you could do a class/data route.
$('#thing').addClass('animating').animate({ left: '+=100px' }, function () {
// your callback when the animation is finished
$(this).removeClass('animating');
});
You could declare a global boolean called isAnimating and set it to true right when you begin the animation. Then add a done or complete function to the animation that sets it back to false. Then set your click event to only begin the animation if isAnimating is false.
I have the following function to calculate the loading progress of a video (quite common):
function updateProgressBar (video) {
if (video.buffered.length > 0) {
var percent = (video.buffered.end(0) / video.duration) * 100;
$('#loading').css({'width': percent + '%'});
console.log(percent);
if (percent == 100) {
console.log('video loaded!');
//everything is loaded, do something.
$(video).unbind('loadeddata canplaythrough playing'); //prevents the repetition of the callback
}
}
}
...bound to the 'progress' event (and some others as a safety meassure) inside a $(document).ready function:
var videoTest = document.getElementById("videoTest");
$('#videoTest').bind('progress', function () {
updateProgressBar (videoTest);
});
$('#videoTest').bind('loadeddata', function () {
updateProgressBar (videoTest);
});
$('#videoTest').bind('canplaythrough', function () {
updateProgressBar (videoTest);
});
$('#videoTest').bind('playing', function () {
updateProgressBar (videoTest);
});
You can view a live example here: http://www.hidden-workshop.com/video/
As you can see, it all works well on firefox, but in the rest of the browsers, the 'percent' variable never reaches the value of '100' as it would be expected; the function always stops at 90~, and thus I'm unable to know when the video has finished loading (vital for what I'm trying to do).
It's like the 'progress' event stops working before I can get the final value of 'percent', because if you click the 'play' button, the 'playing' event fires and then successfully calculates and reads the 'percent' variable's last value (which is 100).
Am I missing something, or is it a common issue? Is there any workaround I could use?
Thanks in advance!
var videoElement = null; //TODO set reference to video element
var checkVideoLoadingProgressTimerDelay = 50;
var checkVideoLoadingProgressTimerID = -1;
function getVideoLoadingProgress(){
var end = 0;
if(videoElement.buffered.length >= 1){
end = videoElement.buffered.end(0);
}
var progress = end / videoElement.duration;
progress = isNaN(progress) ? 0 : progress;
return progress;
};
function startCheckVideoLoadingProgressTimer(){
checkVideoLoadingProgressTimerID =
setTimeout(checkVideoLoadingProgressTimerHandler, checkVideoLoadingProgressTimerDelay);
};
function checkVideoLoadingProgressTimerHandler(){
var progress = getVideoLoadingProgress();
//TODO update progress bar
if(progress < 1){
startCheckVideoLoadingProgressTimer();
}
};
Also value "auto" for "preload" attribute of video not guarantee that user agent will load whole video.
I have a website which I would like to auto refresh ONLY if user is not using it for a specific time (ie.180 sec).Is there a way to auto refresh HTML only if there has been no activity on a page?
Thank you!
Two approaches:
1. Use a once-a-second timer and a "timeout" value.
You probably want to wrap this up in an object:
var activityHandler = (function() {
var timerHandle = 0,
timeout;
flagActivity();
function start() {
stop();
flagActivity();
timerHandle = setInterval(tick, 1000);
}
function stop() {
if (timerHandle != 0) {
clearInterval(timerHandle);
timerHandle = 0;
}
}
function flagActivity() {
timeout = new Date() + 180000;
}
function tick() {
if (new Date() > timeout) {
stop();
location.reload();
}
}
return {
start: start,
stop: stop,
flagActivity: flagActivity
};
})();
Then start it on page load:
activityHandler.start();
And ping it every time you see "activity":
activityHandler.flagActivity();
So for instance, you might do this:
if (document.addEventListener) {
document.addEventListener('mousemove', activityHandler.flagActivity, false);
}
else if (document.attachEvent) {
document.attachEvent('onmousemove', activityHandler.flagActivity);
}
else {
document.onmousemove = activityHandler.flagActivity;
}
2. Use a timer you reset every time there's "activity".
This is less ongoing work (we don't have something happening every second), but more work when you flag that activity has happened.
Set up a timer to do the refresh:
var handle = setTimeout(function() {
location.reload();
}, 180000);
...and then cancel and reschedule any time you see whatever you consider to be "activity":
clearTimeout(handle);
handle = setTimeout(...);
You can wrap this up in a function:
var inactivityTimerReset = (function() {
var handle = 0;
function reset() {
if (handle != 0) {
clearTimeout(handle);
}
handle = setTimeout(tick, 180000);
}
function tick() {
location.reload();
}
return reset;
})();
// Kick start
inactivityTimerReset();
// ...and anywhere you see what you consider to be activity, call it
// again
inactivityTimerReset();
Then, again, ping it on every activity. But this is a lot more work than I'd put in a mousemove handler, hence solution #1 above.
var docTimeOut;
function bodyTimeOut()
{
docTimeOut=setTimeout(function(){location.reload();},18000);
}
function resetTimeOut()
{
clearTimeout(docTimeOut);
bodyTimeOut();
}
document.onload = bodyTimeOut;
document.body.onmouseover= resetTimeOut;
you could declare a variable pageActive or something, set it to false, and whenever user does something set it to true.
Then, set a function to execute periodically as frequently as you want with setinterval() that checks this variable, if it's true set it to false to start again, if is false then refresh page.
You can use onblur and onfocus on body element to see if there is a kind of activity on your page.