I'm trying to invoke a function everytime the "paused" property of a html audio element gets false.
I have a timer which shall count the time a audiofile is actually listened to (i also want to exclude the time while searching with the time bar).
I tried it with SetInterval checking all the time for the status of "paused". Unfortunately this isn't working accurately and quite often misses the status change and so lets the time counter count on.
Is there a simple way to invoke a function everytime a boolean changes?
Help would be very appreciated.
Thanks, f.
Thanks for you answer. Unfortunately this didn't do the trick.
Here's the Code:
<html>
<head>
</head>
<body>
<h5 id="test">Audio Timer</h5>
<audio id="player" src="kerry.wav" controls></audio>
<form name="d">
<input type="text" size="8" name="d2">
<h1 id="time"></h1>
</form>
<script>
var audio = document.getElementById("player");
var millisec = 0;
var seconds = 0;
var timer;
function display() {
if (millisec >= 99) {
millisec = 0
seconds += 1
} else
millisec += 1
document.d.d2.value = seconds + "." + millisec;
timer = setTimeout("display()", 10);
}
function starttimer() {
if (timer > 0) {
return;
}
display();
}
function stoptimer() {
clearTimeout(timer);
timer = 0;
}
function startstoptimer() {
if (timer > 0) {
clearTimeout(timer);
timer = 0;
} else {
display();
}
}
function resettimer() {
stoptimer();
millisec = 0;
seconds = 0;
}
setInterval(function () {
var time = audio.paused;
if (time == false) {
startstoptimer();
}
}, 1);
</script>
</body>
</html>
Unfortunately the SetInterval(function().. isn't fast enough to track the audio.paused. which seems is what i need. As you can see this code always does start the timer, but quite often it doesn't stop it when you press pause or when you use the time bar to seek through the audio.
Any idea how to accomplish that?
Create a variable that calls your audio tag
var yourAudio = document.getElementById("audio")
And then
yourAudio.onpause=YourFunction()
If that is not what you are looking for, post your code or part of it, give us more information.
With a while (true) my page didn't even load. But I finally brought it to life by adding two event listeners listening to "playing" and "pause" which invoke the startstoptimer function.
audio.addEventListener("playing", startstoptimer);
audio.addEventListener("pause", startstoptimer);
those two lines were all it needed :)
thanks.
Related
I am very new to javascript so bear with me if I make mistakes, I am designing a website that allows the user to change the background with a button press, this all works very well and it's great but I want the images to be able to cycle with a time delay. In essence, I want the user to be able to click a button to change the background but I also want a javascript loop running in the background clicking the same button after a set period of time, is this possible?
The code to change the background is as follows:
$(document).ready(function () {
var i = 0;
$("#n").click(function () {
i++;
if (i > 16) { i = 1; };
$('body').css('background-image', 'url(img/' + i + '.jpg)');
});
$("#p").click(function () {
i--;
if (i <= 0) { i = 16; };
$('body').css('background-image', 'url(img/' + i + '.jpg)');
});
});
And the code for the buttons used is:
<button id="n" class="btn">Nxt</button>
<button id="p" class="btn">Prv</button>
You can use setInterval for looping -
setInterval(() => {
console.log('this will repeat every 500 milliseconds');
}, 500);
My recommendation would be not to simulate a click but just call the same function that the click does.
So let's make a function that can be called:
function increment() {
i++;
if ( i > 16 ){ i = 1; };
$('body').css('background-image', 'url(img/' + i + '.jpg)');
}
Then we can use that for the regular click that you already have:
$("#n").click(increment)
And we can also define a repeating call to this function:
setInterval(increment, 1000)
setInterval is pretty neat for non time sensitive tasks like this. Look at the link provided to see how it works, how to cancel it if you want to stop it...
#Ritesh Ganjewala wrote a nice little snippet in her answer that will show you what setInterval does.
#trincot also has an answer that, while a little more complicated to understand, allows you to have less repeating code by using the same function to increment and decrement your counter. Which is something you should strive for when programming something. This is called the DRY principle.
By design, you can't create user inputs with JavaScript. This makes sense if you think about it, certain browser features like requesting permissions can only be done if the user performs an action. You wouldn't want sites agreeing to grant permissions without your input.
So in your case, the best thing to do would be to have the event listener (for user input) and the setTimeout or requestAnimationFrame (for automatic cycling) call the same function.
document.getElementById('n').addEventListener('click', nextColor);
document.getElementById('p').addEventListener('click', prevColor);
var i = 0;
function nextColor() {
i++;
if ( i > 16 ){ i = 1; };
document.body.style.backgroundImage = `url(img/${i}.jpg)`;
}
function prevColor() {
i--;
if ( i <= 0 ){ i = 16; };
document.body.style.backgroundImage = `url(img/${i}.jpg)`;
}
setInterval(nextColor, 5000);
Don't attempt to send a click event to a button. Instead isolate the function that such a click executes, and then use setTimeout to execute that function. You may also want to reset an ongoing timeout when the user clicks again.
Here is how that could look:
$(document).ready(function(){
var i = 0;
var delay = 1000; // number of milliseconds
var timer = setTimeout(next, delay); // <-- set the time out
function next(step=1) { // optional argument that should be 1 or -1
i = (i + 16 + step) % 16; // Use modulo arithmetic to rotate in the range [0..15]
$('body').css('background-image', 'url(img/' + (i+1) + '.jpg)');
clearTimeout(timer); // interrupt the ongoing time out ...
timer = setTimeout(next, delay); // <-- and start it again
}
$("#n").click(next);
$("#p").click(next.bind(null, -1)); // bind the argument to be -1
});
try this setInterval, this will allow you to run a function with a fixed time delay.
function doThis() {
console.log('2 seconds over ...');
}
var xyz = setInterval(doThis, 2000);
and if you need to stop this,
clearInterval(xyz);
Yes, It is possible...
On click of the button on which you are changing the background color you can also initiate a timeout which will call a function after the specified time period (callback function) which in your case will change the image.and setinterval will do the same repeatedly after a specified interval.
$(document).ready(function(){
var i = 0;
function increment() {
i++;
if ( i > 16 ){ i = 1; };
$('body').css('background-image', 'url(img/' + i + '.jpg)');
}
function decrement() {
i--;
if ( i <= 0 ){ i = 16; };
$('body').css('background-image', 'url(img/' + i + '.jpg)');
}
$("#p").click(function(){
increment();
setInterval(increment, 1000);
}
$("#n").click(function(){
decrement();
setInterval(decrement, 1000);
}
}
Ok so ive figured something out from a couple of people who answered, what ive got now is this:
<script>
setInterval(() => {
$("#n").click();
}, 7000);
</script>
This has the effect of clicking the button i want every 7 seconds and its perfect, thanks for everyones help!
What I want:
There are two pictures that are being switched/swapped every three seconds.
I want to make it so that when the button is clicked, the picture switches and the auto-swap resets. So if the button is clicked, the image swaps and three seconds later, it will auto-swap, until the button is clicked again in which the cycle will repeat.
What I have right now
Currently, the problem is that: when the button is clicked, it messes up the timing of the auto-switches.
Edit:
Please don't create a new code base. Just modify mines. The code doesn't have to be an expert super concise level. I'm only three weeks into JavaScript (and it's my first programming language). I have to explain to classmates and it wouldn't be nice the code had elements I don't understand. So sorry for the inconvenience.
Right now I just need the button to correctly stop and restart the time.
<html>
<head>
<script>
let reset = setTimeout(change, 3000);
function change() {
if(document.getElementById("picture").src == "https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350") {
document.getElementById("picture").src = "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&h=350";
}
else {
document.getElementById("picture").src = "https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350";
}
setTimeout(change, 3000);
}
function fastChange() {
clearTimeout(reset);
if(document.getElementById("picture").src == "https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350") {
document.getElementById("picture").src = "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&h=350";
}
else {
document.getElementById("picture").src = "https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350";
}
}
</script>
</head>
<body>
<input type="button" onclick="fastChange();">
<img src="https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350" id="picture">
</body>
</html>
The reason why your timer resets is because you are not clearing the timeout.
you need to make a reference to the timeout and then use clearTimeout() on it whne you make the fast change. I don't think it is possible or wise to do that inline the way you have it so you code needs to be refactored
let imgSrc1 = 'https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350'
let imgSrc2 = 'https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&h=350'
let imgElement = document.getElementById('picture');
let timeout;
function change() {
if(imgElement.src === imgSrc1) {
imgElement.src = imgSrc2;
} else {
imgElement.src = imgSrc1;
}
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(change, 3000);
}
You don't even need the second function fastChange. Now you can sent the onClick listener to change() like this
document.getElementById('whatever you want to click').onCLick = change;
Setting and clearing timeouts in multiple places will work, but I prefer using a "main loop" and a variable to count frames.
Here's an example that uses setInterval and resets a timer variable when the button was clicked:
const url1 = "https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350";
const url2 = "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&h=350";
function change() {
picture.src = picture.src == url1 ? url2 : url1;
}
var timer = 0;
setInterval(function() {
timer++;
time.textContent = timer;
if (timer === 30) fastChange();
}, 100);
function fastChange() {
change();
timer = 0;
}
picture.src = url1;
swap.onclick = fastChange;
#picture {
height: 70vh
}
<button id="swap">SWAP</button> <span id="time"></span><br>
<img id="picture">
You can do this by calling setTimeout and updating the index as necessary. Just be sure to store the most recent timeout id so that it can be cancelled on reset using clearTimeout.
// store the reference to the <img> that contains the picture
const pic = document.getElementById('picture')
// store a list (array) of the two picture urls
const sources = [
'https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350',
'https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&h=350'
]
// used to store a reference to the interval timer you created.
var lastTimer
// a starting index of the list (i.e. which image we are up to right now)
var index = 1
// this functions swaps the image and sets a timer
function startRotation() {
// update the index to the next one (goes 0-1-0-1->etc)
index = 1 - index
// sets the .src of the image element
pic.src = sources[index]
// starts a 3 second timer to call this same function again
// but also stores a reference to the timer so that it can be cancelled
lastTimer = setTimeout(startRotation, 3000)
}
// this functions resets the timer and restarts the process
function reset() {
// stop the current timer if there is one
if(lastTimer){
clearTimeout(lastTimer)
}
// restart the process
startRotation()
}
// start the swapping process on start
startRotation()
<input type="button" onclick="reset();">
<img id="picture">
NOT HOW YOU CLEARTIMEOUT:
<html>
<head>
<script>
var i;
function change() {
if(document.getElementById("picture").src == "https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350") {
document.getElementById("picture").src = "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&h=350";
}
else {
document.getElementById("picture").src = "https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350";
}
i = setTimeout(change, 3000);
}
function fastChange() {
clearTimeout(i);
if(document.getElementById("picture").src == "https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350") {
document.getElementById("picture").src = "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&h=350";
}
else {
document.getElementById("picture").src = "https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350";
}
i = setTimeout(change, 3000);
}
</script>
</head>
<body onload="setTimeout(change, 3000)">
<input type="button" onclick="fastChange();">
<img src="https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350" id="picture">
</body>
</html>
I am going crazy here.
I want to show an element on mouse move, and hide it 10 sec after last move of the mouse.
I wrote this:
document.addEventListener("DOMContentLoaded", function(event) {
var time = 0;
document.addEventListener("mousemove", function(event) {
console.log('$');
document.getElementsByClassName("mybar")[0].style.visibility = 'visible';
time = 0;
while (time < 11) {
setTimeout(function() {
time++
}, 1000);
console.log(time, time == 10);
if (time == 10) {
document.getElementsByClassName("mybar")[0].style.visibility = 'hidden';
}
}
});
});
<div class='mybar'>
<h1> TESTING </h1>
</div>
Why does it end up in an endless loop?
Why doesn't it exit on condition? why does the if never gets the 'true' parameter?
Notice : don't run it this way... it will kill your tab.
First, you don't need to wait for DOMContentLoaded to add an event listener to document, since if you did, you couldn't add DOMContentLoaded in the first place.
The infinite loop is because setTimeout doesn't pause the script. It schedules its callback for the time you provide, and irrespective of that time, the callbacks will not run until the current running code in the thread completes, which never happens because you don't increment the time variable.
So the loop never ends, and so the thread is never made available, so your callbacks never can run, so time can never be incremented.
Lastly, starting a setTimeout inside an event handler that shares a local variable and executes very rapidly on an event like mousemove is prone to give unexpected results. For example, in your code, every time the handler runs, it'll reset time to 0, which doesn't seem to be what you'd want.
A solution would be to ditch the loop, schedule the visibility for 10 seconds, and prevent the main part of the code in the handler from running in the meantime by using a boolean variable.
var timer = null;
document.addEventListener("mousemove", function(event) {
var myBar = document.querySelector(".mybar");
if (!myBar) {
return; // there's no mybar element
}
if (timer == null) {
myBar.style.visibility = 'visible';
} else {
clearTimeout(timer); // clear the currently running timer
}
// set to hidden in 10 seconds
timer = setTimeout(function() {
myBar.style.visibility = 'hidden';
timer = null; // clear the timer
}, 10000);
});
I also switched to querySelector instead of getElementsByClassName because it's shorter and cleaner. And I used a variable to make sure the element is found before setting the style.
You need a flag out of the mousemove scope that tells your listener that you've already ran.
if(running) return;
running = true;
In context:
document.addEventListener("DOMContentLoaded", function(event) {
var time = 0;
var running = false;
document.addEventListener("mousemove", function(event) {
console.log('$');
if(running) return;
running = true;
document.getElementsByClassName("mybar")[0].style.visibility = 'visible';
time = 0;
while (time < 11) {
setTimeout(function() {
time++
}, 1000);
console.log(time, time == 10);
if (time == 10) {
document.getElementsByClassName("mybar")[0].style.visibility = 'hidden';
}
}
});
});
Here's a way to do it with regular JavaScript. If your browser isnt ES6 compliant, you can replace the arrow functions with regular function expressions. The example hides the text after 2 seconds instead of 10, just so you can see it work without having to waste 8 extra seconds.
//hide by default
document.getElementById('myBar').style.display = 'none';
var timer = null;
var hideDivTimer = () => {
timer = setTimeout(() => {
document.getElementById('myBar').style.display = 'none';
}, 2000);
};
document.addEventListener('mousemove', () => {
clearTimeout(timer);
document.getElementById('myBar').style.display = 'inline';
hideDivTimer();
});
<body>
<div id='myBar'>
<h1> TESTING </h1>
</div>
</body>
this is the code that comes in head section and it will automatically refresh the whole page in 1 min as i put 6000 in the code below
<script type="text/javascript">
setTimeout('window.location.href=window.location.href;', 6000);
</script>
is there any way for example, when there's 10 seconds left to refresh the page then, a button will display and say "Click here to reset timer" and it will reset that timer to 1 min again?
<script language="javascript">
var timeout,interval
var threshold = 15000;
var secondsleft=threshold;
startschedule();
window.onload = function()
{
startschedule();
}
function startChecking()
{
secondsleft-=1000;
if(secondsleft <= 10000)
{
document.getElementById("clickme").style.display="";
document.getElementById("timercounter").innerHTML = Math.abs((secondsleft/1000))+" secs";
}
}
function startschedule()
{
clearInterval(timeout);
clearInterval(interval);
timeout = setTimeout('window.location.href=window.location.href;', threshold);
secondsleft=threshold;
interval = setInterval(function()
{
startChecking();
},1000)
}
function resetTimer()
{
startschedule();
document.getElementById("clickme").style.display="none";
document.getElementById("timercounter").innerHTML="";
}
</script>
Please wait...<span id="timercounter"></span>
<button id="clickme" style="display:none;" onclick="javascript:resetTimer();">Click here to reset timer</button>
Assuming you have the following html for the button:
<button id="cancel-reload-button" style="display: none" onclick="cancelReload()">Cancel Reload</button>
And this as the script (Note: this gives the idea, but is not neccesarily fully tested):
// Variable for holding the reference to the current timeout
var myTimeout;
// Starts the reload, called when the page is loaded.
function startReload() {
myTimeout = setTimeout(function() {
document.getElementByID("cancel-reload-button").style.display = "inline";
myTimeout = setTimeout(function() {
window.location.reload();
} 10000)
}, 50000);
}
// Cancel the reload and start it over. Called when the button is
// clicked.
function cancelReload() {
clearTimeout(myTimeout)
startReload()
}
// On page load call this function top begin.
startReload();
I created two functions, one for starting the reload and the second one for cancelling it.
Then I assigned the timeout to the variable myTimeout which can be used to later cancel the timeout.
Then I called myTimeout twice - Once for 50 secs, at which point it shows the button and once for 10 secs after which it finally reloads.
How about below? If you click on OK to reset timer, it would keep giving the confirm box every 50 seconds. If you click cancel, it will refresh the page in 10 seconds.
setInterval(function(){ var r = confirm("Reset Timer");
if (r == true) {
setTimeout('window.location.href=window.location.href;', 60000);
} else {
setTimeout('window.location.href=window.location.href;', 10000);
}
}, 50000);
Note: In your question you specified 1 minute, but your code works for 6 seconds(6000 -- > 6 seconds not 60 seconds) I have included for a minute
You can use 2 setTimeout calls, one to make the "Reset" button show up and another one for the refresh timer reset. The trick is to store the second setTimeout on a global variable and use clearTimeout to reset it if the button is pressed.
Here is some JavaScript code to illustrate:
<script type="text/javascript">
var autoRefreshTime = 30 * 1000; // 60000ms = 60secs = 1 min
var warningTime = autoRefreshTime - (10 * 1000); // 10 secs before autoRefreshTime
waitTimeout = setTimeout('window.location.href=window.location.href;', autoRefreshTime);
warningTimeout = setTimeout('ShowResetButton();', warningTime);
function ShowResetButton() {
// Code to make the "Reset" button show up
}
// Make this function your button's onClick handler
function ResetAutoRefreshTimer() {
clearTimeout(waitTimeout);
waitTimeout = setTimeout('window.location.href=window.location.href;', autoRefreshTime);
}
</script>
The way I would do it is make a function with a timeout, and invoke that function
<script type="text/javascript">
var refreshFunc = function(){
setTimeout(function(){
var r = confirm("Do you want to reset the timer?");
if(r === false){
window.location.href=window.location.href;
}else{
refreshFunc();
}
}, 6000);
};
refreshFunc();
</script>
One big problem with using confirm in this case is you cannot program it to reject. You would have to implement you own modal/dialog box so you can auto reject in 10 seconds.
Try using setInterval():
var time;
$(function() {
time = $('#time');
$('#reset').on('click', reset);
start();
});
var timer, left;
var start = function() {
left = +(time.text()); //parsing
timer = setInterval(function() {
if (0 <= left) {
time.text(left--);
} else {
clearInterval(timer);
location.replace(location);
}
}, 1000);
};
var reset = function() {
if (timer) {
clearInterval(timer);
}
time.text('59');
start();
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h1><span id='time'>59</span> second(s) left</h1>
<input id='reset' value='Reset' type='button' />
hey, how can I have my download link hidden, and make a count down type thing. Maybe have it count down from 10 and once it's done that have the download link appear, it would be best to do it in js right?
does anyone know how to do this? :D
Thanks
Complete example:
<span id="countdown"></span>
<a id="download_link" href="download.zip" style="display:none;">Download</a>
<noscript>JavaScript needs to be enabled in order to be able to download.</noscript>
<script type="application/javascript">
(function(){
var message = "%d seconds before download link appears";
// seconds before download link becomes visible
var count = 10;
var countdown_element = document.getElementById("countdown");
var download_link = document.getElementById("download_link");
var timer = setInterval(function(){
// if countdown equals 0, the next condition will evaluate to false and the else-construct will be executed
if (count) {
// display text
countdown_element.innerHTML = "You have to wait %d seconds.".replace("%d", count);
// decrease counter
count--;
} else {
// stop timer
clearInterval(timer);
// hide countdown
countdown_element.style.display = "none";
// show download link
download_link.style.display = "";
}
}, 1000);
})();
</script>
You can use setInterval for this. setInterval behaves like a timer, where you can run a certain function periodically. Something like this should do the work(untested):
$(".link").hide();
var iteration = 0;
var timer = setInterval(function() {
if(iteration++ >= 10) {
clearTimeout(timer);
$(".link").show();
$(".counter").hide();
}
$(".counter").text(10 - iteration);
}, 1000);
This will initially hide the download link and run a function every second which counts down from 10. When we reaced ten, we hide the counter and show the link. ClearTimeout is used so that we don't count after we reached ten. Easy as dell.
Edit: As mentioned in the comments, this function is using jQuery to find the elements.
Take a look at the setTimeout function. You can do something like:
function displayLink() {
document.getElementById('link_id').style.display = 'block';
}
setTimeout(displayLink, 10000);
var WAIT_FOR_SECONDS = 10;
var DOWNLOAD_BUTTON_ID = "btnDownload";
if (document.body.addEventListener) {
document.body.addEventListener("load", displayDownloadButton, false);
} else {
document.body.onload = displayDownloadButton;
}
function displayDownloadButton(event) {
setTimeout(function() {
_e(DOWNLOAD_BUTTON_ID).style.display = "";
}, WAIT_FOR_SECONDS*1000);
}
function _e(id) {
return document.getElementById(id);
}