Is it possible to do a javascript action after play button is pushed? I know I will need to use onStateChange function form Youtube's API. But I really don't know where to start? Any help? Thank you.
--
I have also found something here: http://apiblog.youtube.com/2011/01/introducing-javascript-player-api-for.html
Here's a solution that you should be able to extend easily: http://jsbin.com/evagof
Hey here is the answer .
http://jsfiddle.net/masiha/4mEDR/
Enjoy ...let me know if you have more qtns
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
google.load("swfobject", "2.1");
</script>
<script type="text/javascript">
// Update a particular HTML element with a new value
function updateHTML(elmId, value) {
document.getElementById(elmId).innerHTML = value;
}
// This function is called when the player changes state
function onPlayerStateChange(newState) {
updateHTML("playerState", newState);
if(newState === 1){
//if the player is now playing
//add your code here
}
}
// This function is automatically called by the player once it loads
function onYouTubePlayerReady(playerId) {
ytplayer = document.getElementById("ytPlayer");
// This causes the updatePlayerInfo function to be called every 250ms to
// get fresh data from the player
setInterval(updatePlayerInfo, 250);
updatePlayerInfo();
ytplayer.addEventListener("onPlayerStateChange");
}
// The "main method" of this sample. Called when someone clicks "Run".
function loadPlayer() {
// The video to load
var videoID = "ylLzyHk54Z0"
// Lets Flash from another domain call JavaScript
var params = { allowScriptAccess: "always" };
// The element id of the Flash embed
var atts = { id: "ytPlayer" };
// All of the magic handled by SWFObject (http://code.google.com/p/swfobject/)
swfobject.embedSWF("http://www.youtube.com/v/" + videoID +
"?version=3&enablejsapi=1&playerapiid=player1",
"videoDiv", "480", "295", "9", null, null, params, atts);
}
function _run() {
loadPlayer();
}
google.setOnLoadCallback(_run);
</script>
<div id="videoDiv">Loading...</div>
<p>Player state: <span id="playerState">--</span></p>
http://code.google.com/apis/ajax/playground/?exp=youtube#polling_the_player
Maybe Youtube made some changes since this question was posted, but most of the answers didn't work. I found that the easiest way was to use the iframe_api (https://developers.google.com/youtube/iframe_api_reference)
Here is an example
https://thimble.webmaker.org/en-US/project/39354/edit
Related
I’ve seen different web apps like Playmoss, Whyd, and Songdrop etc. that, I believe, HAVE to utilize the Soundcloud Embedded Widget in order to produce the functionality of playing multiple tracks, in sucession, not apart of a set/(playlist). Currently I am having issues reproducing this functionality with the following library, so I decided to attempt to write my own:
https://github.com/eric-robinson/SCLPlayer
I am very new to writing javascript, but my below code, will load a first track, and play it once hitting the “ready” bind. Once hitting the “finish” bind, It will then jump to the loadNextTrack() function and load the next tracks URL, into the src of the widget’s iFrame. After that, it doesn’t ever hit the original “ready” bind, which would then begin playback.
So to clear things up, playback doesn’t begin for the second track.
<script type = "text/javascript">
var SCLPlayer = {
isPlayerLoaded : false,
isPlayerFullLoaded : false,
needsFirstTrackSkip : true,
isPaused: true,
scPlayer : function() {
widgetContainer = document.getElementById('sc');
widget = SC.Widget(widgetContainer);
return widget;
},
loadNextTrack : function() {
var ifr = document.getElementById('sc');
ifr.src = 'http://w.soundcloud.com/player/?url=https://api.soundcloud.com/tracks/231758952';
console.log ('Loading Next Track');
SCLPlayer.scPlayer().bind(SC.Widget.Events.READY, function() {
console.log ('Player is Ready, next Track');
SCLPlayer.scPlayer().play();
});
}
};
$( '#sc' ).ready(function() {
SCLPlayer.scPlayer().bind(SC.Widget.Events.READY, function() {
SCLPlayer.isPlayerLoaded = true;
//window.location = 'sclplayer://didLoad';
console.log ('Player is Ready');
SCLPlayer.scPlayer().play();
});
SCLPlayer.scPlayer().bind(SC.Widget.Events.PLAY, function() {
SCLPlayer.isPaused = false;
//window.location = 'sclplayer://didPlay';
console.log ('Player did Play');
});
SCLPlayer.scPlayer().bind(SC.Widget.Events.PAUSE, function() {
SCLPlayer.isPaused = true;
//window.location = 'sclplayer://didPause';
console.log ('Player did Pause');
});
SCLPlayer.scPlayer().bind(SC.Widget.Events.FINISH, function() {
SCLPlayer.isPaused = true;
//window.location = 'sclplayer://didFinish';
console.log ('Player did Finish');
SCLPlayer.loadNextTrack();
});
});
</script>
</head>
<body>
<iframe id = "sc" width="100%" height="100%" scrolling="no" frameborder="no" src="http://w.soundcloud.com/player/?url=https://api.soundcloud.com/tracks/226183306"></iframe>
</body>
The whole point of me writing this Javascript is so that I can then use a Swift to Javascript bridge in my iOS app to then control the loading of tracks into the embedded players. For some reason over a slower connection, the next track doesn't always load into the player, using the "bridge". I hope to provide the nextTrackURL to the javascript side of things before the currentTrack finishes, so that the bridge conveys nothing and the Javascript handles new track loading, solely on its own.
I think you want to use the load function to specify the url for the new track
From the soundcloud Widget API docs:
load(url, options) — reloads the iframe element with a new widget specified by the url. All previously added event listeners will continue working. options is an object which allows you to define all possible widget parameters as well as a callback function which will be executed as soon as new widget is ready. See below for detailed list of widget parameters.
var url = "https://api.soundcloud.com/";
var options = [];
// if a track
url += "tracks/";
// if a playlist
url += "playlists/"
// append the id of the track / playlist to the url
url += id;
// set any options you want for the player
options.show_artwork = false;
options.liking = false;
options.auto_play = true;
widget.load(url, options, OPTIONAL_CALLBACK_FUNCTION);
Edited to show binding...
The bind code is called once, after the widget is initially loaded.
The ready event is only called once, when the widget is initially loaded, it is not called for each subsequent call using load().
try {
widget.bind(SC.Widget.Events.FINISH,
function finishedPlaying() {
// your code / function call
}
);
widget.bind(SC.Widget.Events.PAUSE,
function paused() {
// your code / function call
}
);
widget.bind(SC.Widget.Events.PLAY,
function playing() {
// your code / function call
widget.getCurrentSound(function scCurrentSound(sound) {
// this also binds getCurrent sound which is called
// each time a new sound is loaded
});
}
);
widget.bind(SC.Widget.Events.PLAY_PROGRESS,
function position(pos) {
// your code / function call
}
);
widget.bind(SC.Widget.Events.SEEK,
function seek(pos) {
// your code / function call
}
);
widget.bind(SC.Widget.Events.READY,
function ready() {
// your code / function call
}
);
} catch(e) {
// exception handler code
}
hi i am new on javascript and i have player name player.swf i am getting list of videos from the database like videos/dhoom3.flv and passing it from there to js and then to flash for that i have use
<script language="javascript" type="text/javascript">
function playFirstVid() // plays the first video when the page is loaded
{
sendToJavaScript("videos/dhoom3.flv");
}
function sendToJavaScript( id )
{
var name = getMovieName("player");
alert(id);
getMovieName("player").sendToFlash( id );
}
function getMovieName(movieName)
{
if (navigator.appName.indexOf("Microsoft") != -1)
{
return window[movieName];
}
else
{
return document[movieName];
}
}
</script>
Firstly is it right way ? For now its not showing my video in player of flash because it says sendToFlash function is missing so can anyone tell what to do next?
As Lukasz pointed out, if the function does not exist on the class, you can't call it. Assuming it is a public function, you can call any method on an swf by dot.notation.
mySWF.theFunctionName(myArguments);
Depending on how you wire your events (and I would recommend a unified event listener), it's just a matter of sending that numerically indexed string to your play method.
Note: The following is not using a unified listener, but is in keeping with you example.
<script language="javascript" type="text/javascript">
var videosArr = ["videos/dhoom3.flv", "videos/dhoom2.flv", "videos/dhoom1.flv"];
function playFirstVid() {
playVid(videosArr[0]);
}
function playVid(filename) {
var player;
if (navigator.appName.indexOf("Microsoft") != -1) {
player = window[movieName];
} else {
player = document.getElementById("player");
}
try {
player.sendToFlash(filename);
} catch (err) {
alert(err.message);
}
}
</script>
Here's an example
parent.html
<script>
function printWhoCalledMe() {
console.log(???); // what goes here that will identify the caller?
}
<iframe src="iframe1.html"></iframe>
<iframe src="iframe2.html"></iframe>
iframe1.html
<script>
window.parent.printWhoCalledMe();
</script>
iframe2.html
<script>
window.parent.printWhoCalledMe();
</script>
The larger question is, I have a test harness that runs a bunch of tests, one at a time, in an iframe. Each test calls window.parent.reportOnTest(success)
I'm looking into parallelizing the tests by running them in more than 1 iframe but I'd have to go through every test, currently 1000 tests, and change their call from window.parent.reportOnTest(success) to something like window.parent.reportOnTest(success, window.location.href) or something like that.
I'm wondering if there is a way without modifying the tests, to figure out which test is calling into the parent.
Note: I tried
function printWhoCalledMe() {
console.log(window.location.href);
}
But that's prints the parent's href.
i am worried you may have to use string values like that..
function printWhoCalledMe(callerPage) {
console.log(callerPage); // what goes here that will identify the caller?
}
and you may call this function from your child frames with arguments like that..
iframe1.html
<script>
window.parent.printWhoCalledMe("iframe1");
</script>
iframe2.html
<script>
window.parent.printWhoCalledMe("iframe2");
</script>
If you call your parent function using apply you can change the context to the frame window
window.parent.printWhoCalledMe.apply(this);
function printWhoCalledMe() {
console.log(this); // this now refers to the frame window
}
So hacky, but you can use something like this:
Use caller to get a reference to the function which called your desired function.
Keep using Object.getPrototypeOf until you reach the Object.prototype of that realm.
Iterate all frame windows, and compare the Object.prototype
Once you find the match, use frameElement to get the iframe.
This requires sameorigin, no sandboxing, and sloppy mode. Example:
window.func = function func() {
var proto, nextProto = func.caller;
while (nextProto) {
proto = nextProto;
nextProto = Object.getPrototypeOf(proto);
}
var win = [].find.call(window.frames, function(win) {
try {
return win.Object.prototype === proto;
} catch(err) {
return false;
}
});
if (win) {
var iframe = win.frameElement;
console.log("function called from frame " + iframe.name);
}
};
var iframe = document.createElement('iframe');
iframe.name = "myframe";
document.body.appendChild(iframe);
var doc = iframe.contentDocument;
var script = doc.createElement('script');
script.text = "(function f(){parent.func()})()";
doc.body.appendChild(script);
// Logs "function called from frame myframe"
There is no way to get this information without including it in the arguments when you call the parent function.
Fortunately, this is rather easy. Assuming you give each iframe an id, you just have to pass the id of your iframe into the function you're calling. You can get the id of the iframe you're in like this: window.frameElement.id.
So for example:
iframe1.html
<script>
window.parent.printWhoCalledMe(window.frameElement.id);
</script>
parent.html
<script>
function printWhoCalledMe(iframeId) {
console.log(iframeId); // Prints the id of the iframe that called the function
}
</script>
I am using SWFObject to embed YouTube videos into our website. There are many links to videos in one page and each link clears a wrapper div, then loads a new embed into it, with this code:
$('a.video-link').each(function () {
$(this).on('click', function(e) {
e.preventDefault();
if ($('#video-wrap').has('object').length == 0) {
var params = { allowScriptAccess: 'always', allowFullScreen: 'true' };
var atts = { id: 'ytapiplayer' };
swfobject.embedSWF($(this).attr('href'), 'ytapiplayer', '1000', '562', '8', null, null, params, atts);
$('#video-wrap').show();
} else {
$('#video-wrap').find('object').remove();
$(this).trigger('click');
}
});
});
These are the Youtube links I am using for each embed:
http://www.youtube.com/v/{Youtube ID}?hl=en_US&rel=0&hd=1&border=0&version=3&fs=1&autoplay=1&autohide=1&enablejsapi=1&playerapiid=ytapiplayer
Then, here is the onYouTubePlayerReady() event handler:
function onYouTubePlayerReady(id) {
console.log('youtube player is ready.');
var ytplayer = document.getElementById('ytapiplayer');
ytplayer.addEventListener('onStateChange', 'onYouTubePlayerStateChange');
ytplayer.addEventListener('onError', 'onYouTubePlayerError');
}
All videos load fine, however the onYouTubePlayerReady is never hit!
I have tried solutions from here and here but nothing worked :(
Please help me solve this problem. The ultimate goal is to get the Youtube API to work.
Thanks.
EDIT: I tried to play with the code, make sure all names are correct, separate into different script tags and/or .js file, load it on the beginning, inside document.ready(), still, onYouTubePlayerReady is not firing. What do you think?
Here is the working code:
Executing SWFObject on each video link:
$('a.video-link').on('click', function(e) {
e.preventDefault();
// SWFObjects loads a video object into div with ID ytapiplayer.
// If the wrapper div already contains a video we need to remove it first:
if ($('#video-wrap').has('object').length == 0) {
var params = { allowScriptAccess: 'always', allowFullScreen: 'true' };
var atts = { id: 'ytapiplayer' };
swfobject.embedSWF($(this).attr('href'), 'ytapiplayer', '1000', '562', '8', null, null, params, atts);
$('#video-wrap').show();
} else {
$('#video-wrap').find('object').remove();
$(this).trigger('click');
}
});
The YouTube link with API values:
http://www.youtube.com/v/' + data.YoutubeLink + '?hl=en_US&rel=0&hd=1&border=0&version=3&fs=1&autoplay=1&autohide=1&enablejsapi=1&playerapiid=ytapiplayer
And the SWFObject event handlers I put this code in a separate .js file, loaded before the code executing SWFObject. I don't know if it's necessary, but it's working anyway:
function onYouTubePlayerReady(id) {
// We need the actual DOM element for this, if we want to use more advanced API.
// This is because addEventListener activates the API.
var ytplayer = $('#ytapiplayer').get(0);
ytplayer.addEventListener('onStateChange', 'onYouTubePlayerStateChange'); // onYouTubePlayerStateChange(newState)
ytplayer.addEventListener('onError', 'onYouTubePlayerError'); // onYouTubePlayerError(errorCode)
}
My javascript:
function onYouTubePlayerReady()
{
playerObj = document.getElementById("player_embed");
playerObj.addEventListener("onStateChange", test);
// Make sure the document is loaded before any DOM-manipulation
$(document).ready(function() {
// Update player information every 500ms
setInterval(updatePlayerInfo, 500);
});
}
function test(newState)
{
alert(newState);
}
My videos are loaded correctly and I can control fine them through my javascript. However the onStateChange event never seems to trigger. It never comes up with an alert when I'm playing/stopping/pausing videos etc. Anyone with a solution/similar problem?
You must pass the function name as a string to addEventListener.
playerObj.addEventListener("onStateChange", "test");
This format is for JQuery but the logic is same, create a function inside onYouTubePlayerReady to pass the playerId
$(document).ready(function() {
onYouTubePlayerReady = function(playerId) {
eventHandler=function(state){onStateChangeID(state,playerId);}
playerObj = document.getElementById("player_embed");
playerObj.addEventListener('onStateChange','eventHandler',false);
}
onStateChangeID=function(newState,playerId) {
console.log("onStateChange: ("+playerId+") " + newState);
}
});