Cuepoints play button not playing video on second click - javascript

Hi I am using this small script to create cuepoints for my video:
(function(a){a.fn.cuepoints=function(c){var e=this[0];var d={};function b(){d=a.extend({},c)}b();e.addEventListener("playing",b);e.addEventListener("ended",b);e.addEventListener("loadstart",b);e.addEventListener("seeked",b);e.addEventListener("timeupdate",function(){for(var g in d){var f=parseFloat(g,10);g=g+"";if(f<=e.currentTime&&e.currentTime<=f+0.5){d[g]();delete d[g]}}});return this}})(jQuery);
The problem I am facing is my button will play the video on the first click just fine and when the cuepoint is reached the video pauses however when I press the play button a second time the video will not play (even though the console confirms it has been clicked twice) but if I click the button a third time the video will play again any ideas?
Here's the code:
var vid = document.getElementById("video");
$(document).on('click touchstart tap', '.nextSlide', function() {
vid.play();
console.log('Clicked');
});
$('#video').cuepoints({
10.5: function () {
vid.pause();
},
15: function() {
}
});

Here's what's happening:
The $.cuepoints() plugin keeps track of all the times and callbacks in an object: {10.5: function() {...}, ...}. Whenever the video's timeupdate event fires, the plugin looks at the object, checks to see if the current time is within half a second range of any of the callback times. If so, the associated function is executed and the entry is removed.
However, if someone were to rewind the video, there has to be a way to run those functions at the specified times again. To handle that, the plugin listens for playing, ended, loadstart, and seeked events. When any of those events occur, the time and callback object gets reset.
So here's your problem: when you run vid.pause() in your callback function, the video stops. When the user unpauses video, the playing event fires, resetting all the callbacks. Almost immediately, a timeupdate event realizes that you're still within the half second period, and calls your callback function yet again.
In point of fact, it doesn't always play on the third click. Sometimes it takes four clicks, because the timeupdate event keeps firing inside that half-second period.
Now, the half-second range is necessary. You don't get any guarantee of how often the timeupdate is going to fire, so if you don't have something like that, you run a good chance of skipping the callbacks altogether.
My solution is to stop listening to playing events. The time/event object gets set up when the plugin is originally called, so the first play work fine. When users use the meter to move to a different time, the seeked event will fire. When users get to the end and decide to replay it, the ended event will already have fired. I don't think that the playing event is necessary.
Here's a JSFiddle demonstrating the fix: https://jsfiddle.net/zxfzjqu2/

Related

AudioJS: play only html5 audio at time per page

I'm currently using the simple AudioJs script which is very easy to integrate, but If I have multiple audio files in the same page, I wan the user to be able to click play on any and listening without the need to stop the previous file first... ti basically i need a toggle that says "stop all" THEN play this
any help on how to implement this?
i tried
$.each($('audio'), function() {
this.pause();
});
but this doesn't reverse the button and the status "playing" of each instance created by AudioJs
The general trick for such functionality is to bind onplay event on all the players; when you play one it would trigger now you pause all players except the one on which onplay got triggered , but problem here is audiojs doesn't provide audio events (it only provides methods to play ,pause etc)in its wrapper objects.But there is something you can do: each player object will have a reference to its corresponding HTML5 <audio> element (that's actually playing the mp3) you can use this and bind directly on that using element property .
1.bind onplay on all the players
allAud = a.createAll();
for(var i=0; i<allAud.length;i++)
{
allAud[i].element.onplay = function pauseOthers();
}
2.when onplay triggers loop over all player's <audio> and pause all except the one on which event was triggered (using audiojs wrapper pause() method
function pauseOthers() {
for(var j=0; j<allAud.length;j++)
{
if(allAud[j].element != this) //pause all except the one being played
allAud[j].pause(); // can also use `this.pause()` , but better let audiojs do that incase it's handling some play/pause animation
}
}
Demo : http://jsfiddle.net/rqsxxjmd/

Video canplay event triggers thousands of times per second

I have the following jQuery code in my page onload function:
$("#vid-pages").find("video").on('canplay', function() {
$(this)[0].currentTime = $(this)[0].duration / 2;
console.log($(this)[0].currentTime);
});
There are only two videos in that container, and none anywhere else on the page. When I check the console, it's continuously flooded with the time returned in that code block. What is the solution to make this trigger only once, instead of constantly?
When the current time is changed the browser needs to load more data either from cache or the network. This can trigger the canplay event. And since a time is set in the event handler you will get a never-ending loop (you can see the effect of canplay being triggered here by choosing a video, hit play then skip to the middle right after). It may depend on the browser.
This page on MDN states the following to the related canplaythrough (though not entirely the same it is reasonable to believe this also applies to canplay as shown in the media event page using Firefox):
Note: Manually setting the currentTime will eventually fire a
canplaythrough event in firefox. Other browsers might not fire this
event.
To avoid either unsubscribe from the event, or use a flag which forces exit at the second time the event is triggered.
var initialPlay = false;
$("#vid-pages").find("video").on('canplay', function() {
if (initialPlay) return;
initialPlay = true;
$(this)[0].currentTime = $(this)[0].duration / 2;
console.log($(this)[0].currentTime);
});
For unsubscribing you would need to use a non-anonymous function.

to add event listener for getting video duration in run time in videojs

I want to monitor the video duration as the video plays using any event listener. I am using videojs for video playback.
I came across events like play, myplayer.isPaused but they fire only once.
myplayer is the video element for videojs.
Now upon further research i got an event named on.
So here goes the code :
myPlayer.on("play", myfun);
function myfun() {
console.log("myPlayer.currentTime()");
console.log(myPlayer.currentTime());
myfun();
}
Here is what i expected that it will give me currentTime as you can see i am calling myfun recursively.
But this function is getting called a million times but only gives me the starting time which is 0.
I even tried to put myPlayer.currentTime() in setInterval, but this method is not trustworthy and ofcourse not a good idea.
I used native javascript eventlisteners but they are not likely to be useful.
So any help to attach event listener for the videoplayback sothat i would get the play duration?
The play event is fired only when playback starts. If you want to monitor progress into the video then the correct event is timeupdate. Here is an example:
myPlayer.on("timeupdate", myfun);
function myfun() {
console.log("myPlayer.currentTime()", myPlayer.currentTime());
}

Adding event handler to loop through dynamically created playlist (YouTube API)

Attempting to implement a playlist function along with a listening history. Thumbnails of videos for the playlist are dynamically dragged/dropped/sorted by the user into a div. Each time a thumbnail is clicked, the video is loaded in the player and the video is added to the history (subHist.click()).
Because the videos are dynamically created, I cannot create the event listener to move on to the next video at the beginning, and have to add it later. The problem with that is I have the listening history function within the function that creates the event listener, so the event listener is called increasing number of times as we go through the playlist, meaning a video appears multiple times in the playlist when clicked only once.
This might make more sense with some code:
$('#Playlist').on('click', '.playlistYT', function(){
$('#subHistory').click();
videoID = $(this).attr("src").slice(27,38);
$('#infoID').val(videoID);
player.loadVideoById(videoID );
var nextVideo = $(this).parent().next().find('.playlistYT');
player.addEventListener('onStateChange', function stopCycle(event) {
if (event.data == YT.PlayerState.ENDED) {
$(nextVideo).click();
}
});
});
The images are of the class .playlistYT once they are dropped (i.e. this class does not exist before any videos are dropped), and $('#subHistory').click() which adds the video the listening history.
If I move the var nextVideo within the addEventListener, then it does not recognise it (can't use $(this) as it seems to redefine that to the event within the event handler). Moving $('#subHistory').click() to the stopCycle function seems to make no difference.
Spent past couple of days playing around with .one, .off, .live, can't seem to crack it. removeEventListener doesn't seem to make any difference, either. I thought of adding a hidden video to the playlist but that then becomes a question of making sure that video doesn't appear in users' listening history/playlists.
The onStateChange event that is passed to the event listener has the 'data' object, but it also has the 'target' object that represents the player that raised the event. So for example, you could define the function that handles onStateChange when you initialize the iFrame API, and within that listener function, you could use something like:
event.target.getVideoData().video_id
To find the ID of the playing video that raised the event. Based on your sample code, it looks like knowing the video ID may help you write the proper jQuery selector to find where in your DOM the video is, and then navigate to the next one from there. Hence your event listener will only be defined once but it will be able to handle the dynamic nature of your app's playlist.

hook to click event inside embedded youtube player

I want to run a function called stopSlide whenever someone clicks the 'play' button on an embedded youtube video. Or even getting the function to run when they click anywhere inside the embedded video would work fine for me right now.
How can I do this?
There is a YouTube JavaScript API that provides event callbacks.
There is, unfortunately, no way to directly detect a click event (at least I am not aware of any). You can, however, detect changes in the player state for which you can use onStateChange.
First, you will need to enable the JS API in the player by embedding it by using a special URL:
http://www.youtube.com/v/VIDEO_ID?version=3&enablejsapi=1
Then you need to create an event handler function:
function player_state_changed(state) {
/* This event is fired whenever the player's state changes.
Possible values are:
- unstarted (-1)
- ended (0)
- playing (1)
- paused (2)
- buffering (3)
- video cued (5).
When the SWF is first loaded it will broadcast an unstarted (-1) event.
When the video is cued and ready to play it will broadcast a video cued event (5).
*/
if (state == 1 || state == 2) {
alert('the "play" button *might* have been clicked');
}
}
Lastly, you need to make sure that the handler gets called whenever the state of the movie changes:
document.getElementById('MY-PLAYER-ID').addEventListener('onStateChange', 'player_state_changed');
Might be helpful ... edit according to your requirement
http://jsfiddle.net/masiha/4mEDR/
i tried using the suggestions above but didnt succeed.
it can't handle timer slider.
please see Google example for automatic slider, they used a popup for the video.
google slider with embedded video
Upto my knowledge you can't detect a click inside a iframe,or you can't trigger any click event inside the iframe
My solution is place a button inside the Iframe set it's properties as transparent(opacity) inside that button you can call your click function using playmethod and pause method you can enable autoplay
You need to just register an event listener on the player to call your stopSlide function. The following line of code should do it for you (first you have to replace the two "strings" with the appropriate values - the ID of the embedded player, and the name of the function that you want to call. eg: "stopSlide"):
document.getElementById("_idOfEmbeddedPlayerElement_").addEventListener("onStateChange", "_nameOfFunctionToCall_");`

Categories