I am trying to make a custom video. I can get my functions to work. However when I have two event listeners together:
e.g. video.ontimeupdate
only the bottom one will operate when I play the video. Is there a better way for me to write my functions, so that I do not have this problem?
Event listeners
time.addEventListener("timeupdate", currentTime, true);
video.ontimeupdate = function() {currentTime()};
seek.addEventListener("timeupdate", progressBarUpdate, true);
video.ontimeupdate = function() {progressBarUpdate()};
Function code example
// Updating the progress bar function
function progressBarUpdate() {
// Calculate the progress bar value
var value = (100 / video.duration) * video.currentTime;
// Update the progress bar value
seek.value = value;
}
There are two different JavaScript mechanisms for registering event handlers:
time.addEventListener("timeupdate", currentTime, true); // W3C DOM Standard
video.ontimeupdate = function() { currentTime() }; // Event handling property
When you use a property (ontimeupdate) and you give it a value, that value will be overwritten when you set that property to another value.
So, when you do this:
video.ontimeupdate = function() {currentTime()};
It gets overridden by this later:
video.ontimeupdate = function() { progressBarUpdate() };
To prevent this from happening, use the more modern W3C DOM Level 2 event handling model that uses addEventListener
video.addEventListener("timeupdate", currentTime);
video.addEventListener("timeupdate", progressBarUpdate);
This will register both functions as callbacks to the timeupdate event.
Additionally, there is a third parameter for addEventListener (a boolean) which indicates whether you want the callback to fire during the capture phase (true) or the bubbling phase (false). It's rather unusual to need the capture phase (it's not supported in IE until IE 9), so you may want to modify your existing true values to false or just omit the third argument as false is the default.
Here's a working example that actually shows 3 event handlers all tied into the timeupdate event (make sure to scroll down in the snippet window to see the messages):
var videoElement = null;
var current = null
var duration = null;
var div1, div2;
window.addEventListener("DOMContentLoaded", function(){
// Get DOM References to media element:
videoElement = document.getElementById('bikeSafe');
// ...to video span elements:
current = document.getElementById('current');
duration = document.getElementById('duration');
div1 = document.getElementById("timeUpdate1");
div2 = document.getElementById("timeUpdate2");
// Wire Up Video to use its API:
videoElement.addEventListener("play", setCounter);
videoElement.addEventListener("ended", endVideo);
videoElement.addEventListener("durationchange", updateStatus);
videoElement.addEventListener("timeupdate", setCounter);
videoElement.addEventListener("timeupdate", updateDiv1);
videoElement.addEventListener("timeupdate", updateDiv2);
});
// Video API:
function updateDiv1(){ div1.innerHTML = "Hello from timeupdate event handler!" }
function updateDiv2(){ div2.innerHTML = "Hello from different timeupdate event handler!" }
// Set the value for the current position in the video
function setCounter() {
// This function is wired up to the video element's timeupdate event, which
// fires when the current time value changes.
current.innerHTML = (videoElement.duration - videoElement.currentTime).toFixed(3);
}
function endVideo() {
// Reset video back to beginning when it ends
videoElement.currentTime = 0;
};
function updateStatus() {
// This will fire when the video's durationchange event fires
// and that will happen upon the successful loading of the image
// for the first time when it becomes known how long the duration
// of the video is.
current.innerHTML = videoElement.duration.toFixed(3);
duration.innerHTML = videoElement.duration.toFixed(3);
};
video { width:40%; }
<video id="bikeSafe" width="400" controls>
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
<p>Your browser does not support HTML5 video.</p>
</video>
<p>
Time Remaining: <span id="current"></span> |
Total Length: <span id="duration"></span>
</p>
<div id="timeUpdate1"></div>
<div id="timeUpdate2"></div>
video.ontimeupdate is similar to window.onload. They are properties that are updated. The most recent function definition for them will be executed. Use addEventListener()
video.addEventListener("timeupdate", currentTime, true);
video.addEventListener("timeupdate", progressBarUpdate, true);
Here is a snippet showing the problem with using window.onload syntax.
window.onload = function(){
console.log('Window loaded #1'); // Will not excecute
}
window.onload = function(){
console.log('Window loaded #2'); // Window loaded #2
}
Related
I have a problem with Javascript:
I want to stop the audio in a Js program when the game comes to an end. For this I define a variable "endGame" and I make it false, so that when I call it true in an event, the audio stops. But the problem is that the audio does not stop when this variable is set to true.
Here's the piece of code that I need some help with:
let endGame = false
main.addEventListener("click", (e) => {
themeSong.play()
if(endGame == true) {
themeSong.pause()
}
EventListeners will not be triggered when the variable change. You should do it manually.
let endGame = false;
main.addEventListener("click", (e) => {
themeSong.play();
});
// The function which updates the endGame variable and stop the audio
function fnEndGame() {
endGame = true;
themeSong.pause();
}
// You should call fnEndGame() to stop the game, DO NOT update the variable directly.
By using a custom event, and then throwing that event whenever you want, you can pause your music execution the moment you want to.
So instead of using an "endgame" variable, I suggest you throw a custom event named "supergame_endgame" and listen to that event, and halt all relevant audio's in that event listener.
See my comments in the code below for more explanation.
let audio = document.querySelector('audio');
let start = document.getElementById('play');
let stop = document.getElementById('stop');
/** simple starter of the sound **/
start.addEventListener('click', () => {
audio.play();
});
/** Event handler for own custom event, named `stop_my_audio_play`
* This will actually stop audio play, regardless from where the event `stop_my_audio_play` is
* cast from
*/
window.addEventListener('stop_my_audio_play', (e) => {
audio.pause();
});
/** Throw an event `stop_my_audio_play` with the attribute bubbles set to true
* So it can be caught at window level
*/
stop.addEventListener('click', () => {
stop.dispatchEvent(new Event('stop_my_audio_play', {bubbles:true}))
});
audio {
display:none;
}
<audio controls="controls" autobuffer="autobuffer" autoplay="autoplay" loop>
<source src="data:audio/wav;base64,UklGRhwMAABXQVZFZm10IBAAAAABAAEAgD4AAIA+AAABAAgAZGF0Ya4LAACAgICAgICAgICAgICAgICAgICAgICAgICAf3hxeH+AfXZ1eHx6dnR5fYGFgoOKi42aloubq6GOjI2Op7ythXJ0eYF5aV1AOFFib32HmZSHhpCalIiYi4SRkZaLfnhxaWptb21qaWBea2BRYmZTVmFgWFNXVVVhaGdbYGhZbXh1gXZ1goeIlot1k6yxtKaOkaWhq7KonKCZoaCjoKWuqqmurK6ztrO7tbTAvru/vb68vbW6vLGqsLOfm5yal5KKhoyBeHt2dXBnbmljVlJWUEBBPDw9Mi4zKRwhIBYaGRQcHBURGB0XFxwhGxocJSstMjg6PTc6PUxVV1lWV2JqaXN0coCHhIyPjpOenqWppK6xu72yxMu9us7Pw83Wy9nY29ve6OPr6uvs6ezu6ejk6erm3uPj3dbT1sjBzdDFuMHAt7m1r7W6qaCupJOTkpWPgHqAd3JrbGlnY1peX1hTUk9PTFRKR0RFQkRBRUVEQkdBPjs9Pzo6NT04Njs+PTxAPzo/Ojk6PEA5PUJAQD04PkRCREZLUk1KT1BRUVdXU1VRV1tZV1xgXltcXF9hXl9eY2VmZmlna3J0b3F3eHyBfX+JgIWJiouTlZCTmpybnqSgnqyrqrO3srK2uL2/u7jAwMLFxsfEv8XLzcrIy83JzcrP0s3M0dTP0drY1dPR1dzc19za19XX2dnU1NjU0dXPzdHQy8rMysfGxMLBvLu3ta+sraeioJ2YlI+MioeFfX55cnJsaWVjXVlbVE5RTktHRUVAPDw3NC8uLyknKSIiJiUdHiEeGx4eHRwZHB8cHiAfHh8eHSEhISMoJyMnKisrLCszNy8yOTg9QEJFRUVITVFOTlJVWltaXmNfX2ZqZ21xb3R3eHqAhoeJkZKTlZmhpJ6kqKeur6yxtLW1trW4t6+us7axrbK2tLa6ury7u7u9u7vCwb+/vr7Ev7y9v8G8vby6vru4uLq+tri8ubi5t7W4uLW5uLKxs7G0tLGwt7Wvs7avr7O0tLW4trS4uLO1trW1trm1tLm0r7Kyr66wramsqaKlp52bmpeWl5KQkImEhIB8fXh3eHJrbW5mYGNcWFhUUE1LRENDQUI9ODcxLy8vMCsqLCgoKCgpKScoKCYoKygpKyssLi0sLi0uMDIwMTIuLzQ0Njg4Njc8ODlBQ0A/RUdGSU5RUVFUV1pdXWFjZGdpbG1vcXJ2eXh6fICAgIWIio2OkJGSlJWanJqbnZ2cn6Kkp6enq62srbCysrO1uLy4uL+/vL7CwMHAvb/Cvbq9vLm5uba2t7Sysq+urqyqqaalpqShoJ+enZuamZqXlZWTkpGSkpCNjpCMioqLioiHhoeGhYSGg4GDhoKDg4GBg4GBgoGBgoOChISChISChIWDg4WEgoSEgYODgYGCgYGAgICAgX99f398fX18e3p6e3t7enp7fHx4e3x6e3x7fHx9fX59fn1+fX19fH19fnx9fn19fX18fHx7fHx6fH18fXx8fHx7fH1+fXx+f319fn19fn1+gH9+f4B/fn+AgICAgH+AgICAgIGAgICAgH9+f4B+f35+fn58e3t8e3p5eXh4d3Z1dHRzcXBvb21sbmxqaWhlZmVjYmFfX2BfXV1cXFxaWVlaWVlYV1hYV1hYWVhZWFlaWllbXFpbXV5fX15fYWJhYmNiYWJhYWJjZGVmZ2hqbG1ub3Fxc3V3dnd6e3t8e3x+f3+AgICAgoGBgoKDhISFh4aHiYqKi4uMjYyOj4+QkZKUlZWXmJmbm52enqCioqSlpqeoqaqrrK2ur7CxsrGys7O0tbW2tba3t7i3uLe4t7a3t7i3tre2tba1tLSzsrKysbCvrq2sq6qop6alo6OioJ+dnJqZmJeWlJKSkI+OjoyLioiIh4WEg4GBgH9+fXt6eXh3d3V0c3JxcG9ubWxsamppaWhnZmVlZGRjYmNiYWBhYGBfYF9fXl5fXl1dXVxdXF1dXF1cXF1cXF1dXV5dXV5fXl9eX19gYGFgYWJhYmFiY2NiY2RjZGNkZWRlZGVmZmVmZmVmZ2dmZ2hnaGhnaGloZ2hpaWhpamlqaWpqa2pra2xtbGxtbm1ubm5vcG9wcXBxcnFycnN0c3N0dXV2d3d4eHh5ent6e3x9fn5/f4CAgIGCg4SEhYaGh4iIiYqLi4uMjY2Oj5CQkZGSk5OUlJWWlpeYl5iZmZqbm5ybnJ2cnZ6en56fn6ChoKChoqGio6KjpKOko6SjpKWkpaSkpKSlpKWkpaSlpKSlpKOkpKOko6KioaKhoaCfoJ+enp2dnJybmpmZmJeXlpWUk5STkZGQj4+OjYyLioqJh4eGhYSEgoKBgIB/fn59fHt7enl5eHd3dnZ1dHRzc3JycXBxcG9vbm5tbWxrbGxraWppaWhpaGdnZ2dmZ2ZlZmVmZWRlZGVkY2RjZGNkZGRkZGRkZGRkZGRjZGRkY2RjZGNkZWRlZGVmZWZmZ2ZnZ2doaWhpaWpra2xsbW5tbm9ub29wcXFycnNzdHV1dXZ2d3d4eXl6enp7fHx9fX5+f4CAgIGAgYGCgoOEhISFhoWGhoeIh4iJiImKiYqLiouLjI2MjI2OjY6Pj46PkI+QkZCRkJGQkZGSkZKRkpGSkZGRkZKRkpKRkpGSkZKRkpGSkZKRkpGSkZCRkZCRkI+Qj5CPkI+Pjo+OjY6Njo2MjYyLjIuMi4qLioqJiomJiImIh4iHh4aHhoaFhoWFhIWEg4SDg4KDgoKBgoGAgYCBgICAgICAf4CAf39+f35/fn1+fX59fHx9fH18e3x7fHt6e3p7ent6e3p5enl6enl6eXp5eXl4eXh5eHl4eXh5eHl4eXh5eHh3eHh4d3h4d3h3d3h4d3l4eHd4d3h3eHd4d3h3eHh4eXh5eHl4eHl4eXh5enl6eXp5enl6eXp5ent6ent6e3x7fHx9fH18fX19fn1+fX5/fn9+f4B/gH+Af4CAgICAgIGAgYCBgoGCgYKCgoKDgoOEg4OEg4SFhIWEhYSFhoWGhYaHhoeHhoeGh4iHiIiHiImIiImKiYqJiYqJiouKi4qLiouKi4qLiouKi4qLiouKi4qLi4qLiouKi4qLiomJiomIiYiJiImIh4iIh4iHhoeGhYWGhYaFhIWEg4OEg4KDgoOCgYKBgIGAgICAgH+Af39+f359fn18fX19fHx8e3t6e3p7enl6eXp5enl6enl5eXh5eHh5eHl4eXh5eHl4eHd5eHd3eHl4d3h3eHd4d3h3eHh4d3h4d3h3d3h5eHl4eXh5eHl5eXp5enl6eXp7ent6e3p7e3t7fHt8e3x8fHx9fH1+fX59fn9+f35/gH+AgICAgICAgYGAgYKBgoGCgoKDgoOEg4SEhIWFhIWFhoWGhYaGhoaHhoeGh4aHhoeIh4iHiIeHiIeIh4iHiIeIiIiHiIeIh4iHiIiHiIeIh4iHiIeIh4eIh4eIh4aHh4aHhoeGh4aHhoWGhYaFhoWFhIWEhYSFhIWEhISDhIOEg4OCg4OCg4KDgYKCgYKCgYCBgIGAgYCBgICAgICAgICAf4B/f4B/gH+Af35/fn9+f35/fn1+fn19fn1+fX59fn19fX19fH18fXx9fH18fXx9fH18fXx8fHt8e3x7fHt8e3x7fHt8e3x7fHt8e3x7fHt8e3x7fHt8e3x8e3x7fHt8e3x7fHx8fXx9fH18fX5+fX59fn9+f35+f35/gH+Af4B/gICAgICAgICAgICAgYCBgIGAgIGAgYGBgoGCgYKBgoGCgYKBgoGCgoKDgoOCg4KDgoOCg4KDgoOCg4KDgoOCg4KDgoOCg4KDgoOCg4KDgoOCg4KDgoOCg4KDgoOCg4KDgoOCg4KCgoGCgYKBgoGCgYKBgoGCgYKBgoGCgYKBgoGCgYKBgoGCgYKBgoGCgYKBgoGBgYCBgIGAgYCBgIGAgYCBgIGAgYCBgIGAgYCBgIGAgYCAgICBgIGAgYCBgIGAgYCBgIGAgYCBgExJU1RCAAAASU5GT0lDUkQMAAAAMjAwOC0wOS0yMQAASUVORwMAAAAgAAABSVNGVBYAAABTb255IFNvdW5kIEZvcmdlIDguMAAA" />
</audio>
<button id="play">Play</button>
<button id="stop">Stop</button>
I am trying to stream video using links that expire every 2 minutes.
Basically, I use this function to replace the URL, and it works great:
function test(){
var videoFile = 'new.mp4';
var $video = $('#m video');
var curtime = $video[0].currentTime;
videoSrc = $('source', $video).attr('src', videoFile);
$video[0].load();
$video[0].currentTime = (curtime);
$video[0].play();
}
The question I have is how do I fire this function every time the video starts playing/after someone seeks in it? If i fire the ok(); function using a play event then it starts a loop since the function itself causes a play event.
Does anyone have any ideas on how to fix this in a good way?
The solution would be to register the play event once the video has actually started playing. That way it will react after a pause or a seek.
If you need to disable the event on other conditions then you simply disable the play event (as done in the start of the playing function)...
function test(){
var videoFile = 'trailer.mp4';
var $video = $('#video');
var curtime = $video[0].currentTime;
videoSrc = $('source', $video).attr('src', videoFile);
$video[0].load();
$video[0].currentTime = (curtime);
$video[0].play();
$video.on('playing', function () {
$video.off('play') // remove existing Play event if there is one
console.log("Play event bound")
$video.on('play', function () {
console.log("Video play. Current time of videoplay: " + $video[0].currentTime );
});
});
}
I have an HTML audio player like this:
<audio id="audioPlayer" controls>
<source src="test.mp3">
</audio>
I want to display some images in sync the audio file, including when the user is moving the seekbar.
However, I can't find a way to check whether user is currently using the audio seekbar.
I have tried to use the timeupdateevent with no success: the code below works only when user seeks back in time.
var audioPlayer = document.getElementById('audioPlayer');
var lastUpdateTime;
audioPlayer.addEventListener('timeupdate', function() {update();});
function update() {
if ( audioPlayer.currentTime - lastUpdateTime < 0 )
console.log("seeking");
lastUpdateTime = audioPlayer.currentTime;
}
I am looking for something working on "recent" browsers (e.g. IE10+).
It's a bit hacky but works:
Version with jQuery:
var $audio = $( '#myAudio' );
var onPause = false;
// Pause event helps us to know is player playing or not
$audio.on( 'pause', function() {
onPause = true;
setTimeout(function() {
onPause = false;
});
});
$audio[0].on( 'timeupdate', function(e) {
// trick to get current pause state
setTimeout(function(){
// checks if player paused and not last timeupdate event call
if ( $audio[0].paused && !onPause ) {
// Fire event then user is changing seek bar
$audio.trigger( 'userSeeking' );
}
});
});
$audio.on( 'userSeeking', function(){
// do some magic
});
Version with pure javascript:
var audio = document.getElementById( 'myAudio' );
var onPause = false;
var seek = false;
// Pause event helps us to know is player playing or not
audio.addEventListener( 'pause', function(e) {
onPause = true;
setTimeout(function() {
onPause = false;
});
});
audio.addEventListener( 'timeupdate', function(e) {
// trick to get current pause state
setTimeout(function(){
seek = false;
// checks if player paused and not last timeupdate event call
if ( $audio[0].paused && !onPause ) {
seek = true;
// Fire event then user is changing seek bar
}
// or you can return current state of seeking here
});
});
And here is working example ( codepen using jQuery version ):
http://codepen.io/GomatoX/pen/ZYpWbN
I have read previous posts on this and documents by microsoft but cannot seem to get my app to run Sound in the background. It plays 100% but when ever the app is then suspended the music also stops. I have added "Background Tasks" declarations selecting Audio and my audio tag looks like this
<audio id="musicplayr" msAudioCategory="BackgroundCapableMedia" controls="controls"><source src="song.mp3"/> </audio
and finally my javascript includes the references to MediaControls
var MediaControls = Windows.Media.MediaControl;
// Add event listeners for the buttons
MediaControls.addEventListener("playpressed", play, false);
MediaControls.addEventListener("pausepressed", pause, false);
MediaControls.addEventListener("playpausetogglepressed", playpausetoggle, false);
// Add event listeners for the audio element
document.getElementById("musicplayr").addEventListener("playing", playing, false);
document.getElementById("musicplayr").addEventListener("paused", paused, false);
document.getElementById("musicplayr").addEventListener("ended", ended, false);
and below in the code i have the event handlers
// Define functions that will be the event handlers
function play() {
document.getElementById("musicplayr").play();
}
function pause() {
document.getElementById("musicplayr").pause();
}
function playpausetoggle() {
if(MediaControls.isPlaying === true) {
document.getElementById("musicplayr").pause();
} else {
document.getElementById("musicplayr").play();
}
}
function playing() {
Windows.Media.MediaControl.isPlaying = true;
}
function paused() {
Windows.Media.MediaControl.isPlaying = false;
}
function ended() {
Windows.Media.MediaControl.isPlaying = false;
}
*Note musicplayr is the reference for the html5 tag
Any help appreciated why this is not working?
You also need an event handler for the stoppressed event. Without any of the four handlers--playpressed, pausepressed, playpausetogglepressed, and stoppressed--background audio won't be enabled. See http://social.msdn.microsoft.com/Forums/en-IN/winappswithhtml5/thread/2ca0c122-df31-401c-a444-2149dd3e8d68 on the MSDN forums where the same problem was raised.
.Kraig
In order to get an HTML5 animation playing with sound on an idevice, I've made a div the size of the entire browser named "theScreen", and use the following code:
audioCont.prototype.iCrapLoadPlayThrough = function () {
if (this.supported) {
theScreen = document.getElementById("theScreen");
var self = this;
theScreen.addEventListener('touchstart', function(){self.iCrapClickedLoadPlayThrough();}, false);
return(1);
} else {
return(0); // Not supported
}
};
audioCont.prototype.iCrapClickedLoadPlayThrough = function () { // Check if supported, then load the audio file
var self = this;
theScreen.removeEventListener('touchstart', function(){self.iCrapClickedLoadPlayThrough();}, false);
this.addCanPlayThrough();
this.load();
}
Now this works, and the sound/animation starts when the user taps on the screen. The problem is, if they tap on it again the sound stops, and each repeat tap you hear a few ms of audio. Does anyone know why?
It's not removing the event listener because it's an anonymous function. Remove the anonymous function and just have the function name instead
theScreen.addEventListener('touchstart',self.iCrapClickedLoadPlayThrough,false)
theScreen.removeEventListener('touchstart',self.iCrapClickedLoadPlayThrough,true)
I've found a solution to the problem:
theScreen.addEventListener('touchstart', eventID=function() {self.iCrapClickedLoadPlayThrough();}, false);
then
theScreen.removeEventListener('touchstart', eventID, false);