kaltura multiple players on the same page - javascript

I am trying to embed more than one players on the same page, but that has no success until now. In order to embed the player we need a unique target_id to target the element of the DOM and then the entry_id of the specific video. This is done in the following function:
function embedPlayer() {
var linkPart = $('#uniqueTarget').data('entry');
var conf = {
"targetId": "uniqueTarget",
"wid": "_1912616",
"uiconf_id": "37591811",
"entry_id": linkPart,
"flashvars": {
"controlBarContainer.plugin": false,
"inlineScript": false
}
};
kWidget.thumbEmbed(conf);
}
Here is the related HTML, which is dynamically created from WordPress every time that the user wants to embed a video:
<div style="width: 100%; display: inline-block; position: relative;">
<div class="theRatio"></div>
<div id="uniqueTarget" data-entry="'+ linkPart +'"
style="position:absolute;top:0;left:0;right:0;bottom:0">
</div>
</div>
Unfortunately if I try to embed a second player on the same page it will only do the API call for the first player and the second(or the rest, if more) will leave me with plain HTML and the call is not being done. There is an article about the issue at https://knowledge.kaltura.com/javascript-api-kaltura-media-players#ManagingMultiplePlayersontheSamePage, but unfortunately my knowledge is limited and I would need some help with it.

Kaltura recommend using thumb embed when you have multiple players on a page - this will embed thumbnails which will play when they are clicked:
Thumb Embed
This method takes the same arguments as the dynamic embed. Thumbnail embed passes the entire configuration to the kWidget.embed when the user "clicks" on the play button. This is the recommended method to use when you need to embed multiple players/entries in the same web page. The syntax for ThumbEmbed is identical to kWidget.embed ( dynamic embed ) except we call "kWidget.thumbEmbed" instead of "kWidget.embed"
There is more information including example Javascript and examples thumbnails here:
http://player.kaltura.com/docs/thumb
Example Javascript from this link (you can also look at the page in a browser debugger to see exactly how they have set it up):
<div id="myEmbedTarget" style="width:400px;height:330px;"></div>
<script src="{{HTML5LibraryURL}}"></script>
<script>
mw.setConfig("EmbedPlayer.DisableContextMenu",true);
kWidget.thumbEmbed({
'targetId': 'myEmbedTarget',
'wid': '_243342',
'uiconf_id' : '12905712',
'entry_id' : '0_uka1msg4',
});
</script>

Create DIV containers for each of your videos - give them unique IDs, then you can target them and create as many videos as you like. Make sure the kWidget script is loaded. Put this script in your page:
function _embedVideo(targetId,wid,uiconf_id,flashvars,entry_id,cb){
kWidget.embed({
targetId: targetId,
wid: wid,
uiconf_id: uiconf_id,
flashvars: flashvars || {},
entry_id: entry_id,
readyCallback: cb
});
}
For each of your videos, load them like so:
_embedVideo('id-of-div-container','wid-here','uiconfid-here',null,'entryid-here',yourCallbackFunc);
This is how I create multiple videos in my pages. Be sure to specify a callback else pass null.

Related

How Can I Pass String Variable to Anonymous Adobe View SDK Script?

I have a very basic knowledge of javascript and I have been unable to find a solution for my specific use of the Adobe View SDK API, though it seems like there should be a way. I am working on a web page to show newsletters in the pdf viewer. I have created a w3.css modal element so that I can open the viewer with a button click, and then close it with an "x" in the corner. The button click and the "x" toggle between the display style being "none" or "block". I really like this solution as it lets me use small images of the newsletters as the buttons, and it can be observed here: Test News Page by clicking on the newsletter image below May 4, 2020.
The ultimate goal I have is to be able to change the name of the pdf document that is opened in the viewer by clicking the button, which would need to pass a string variable called "docName" to the url called by the View SDK script. Since the url is already specified in the script inside my modal element when the page loads, here is the thinking I have for the additional script I need to pass my string variables: The button-click invokes my script (function changeName(docName)) and passes the "docName" variable. Then my script needs to pass this variable to the url in the View script (this is the part I don't know how to do), then refresh the page to reload my modal, and then change the display style of the modal to "block". I will copy the code for the View SDK below, showing where I need to insert the string variable with my document name:
<script src="https://documentcloud.adobe.com/view-sdk/main.js"></script>
<script type="text/javascript">
document.addEventListener("adobe_dc_view_sdk.ready", function(){
var adobeDCView = new AdobeDC.View({clientId: "06179511ab964c9284f1b0887eca1b46", divId: "adobe-dc-view"});
adobeDCView.previewFile({
content:{location: {url: "https://www.shcsfarmington.org/" + docName + ".pdf"}},
metaData:{fileName: "Newsletter_050420.pdf"}
}, {embedMode: "FULL_WINDOW", defaultViewMode: "FIT_WIDTH"});
});
</script>
It seems like this should work, but with my limited knowledge of javascript I don't know how to pass this variable to the anonymous function in the View SDK code, and I would need as much detail and specifics in the syntax of the solution. I appreciate any help with this. Thanks.
EDIT: I thought maybe it would help to show the code for the function that I have come up with so far - then it could be examined and easier to debug and comment on:
<button id="CSS-050420" onclick="changeDoc('Newsletter_050420');"></button>
<script>
function changeDoc(docName) {
/* Need to pass docName to url=https://shcsfarmington.org/2020/news/Newsletter_" + newsDate + ".pdf"; */
window.location.reload(true);
document.getElementById('viewerModal').style.display='block';
}
</script>
I created a CodePen here for you to look at.
Basically, you'll load the first file when the SDK is ready but then you need to set the adobeDCView to null before recreating it.
function showPDF(url) {
adobeDCView = null;
fetch(url)
.then((res) => res.blob())
.then((blob) => {
adobeDCView = new AdobeDC.View({
// This clientId can be used for any CodePen example
clientId: "e800d12fc12c4d60960778b2bc4370af",
// The id of the container for the PDF Viewer
divId: "adobe-dc-view"
});
adobeDCView.previewFile(
{
content: { promise: Promise.resolve(blob.arrayBuffer()) },
metaData: { fileName: url.split("/").slice(-1)[0] }
},
{
embedMode: "FULL_WINDOW",
defaultViewMode: "FIT_PAGE",
showDownloadPDF: true,
showPrintPDF: true,
showLeftHandPanel: false,
showAnnotationTools: false
}
);
});
}
The link click even will pass the url to the PDF and then display it.

Soundcloud custom player add and play song dynamically

I am using soundcloud custom player to create a player which can play all the songs on
my site. This works pretty good when i just place static url of any track or a post. But what i want is to add the song to the list dynamically.
I have done lots of research but couldn't get it to work. What i want is there would be multiple players through out the site. kind of(http://soundcloud.com) and there would a main player on the top(like soundcloud) which would play around 100 latest songs on site and there would be a smaller player clicking on which will just append that song to the list and start playing that song.
I am not sure if this is the right process. If any one can just give me any hint how i can proceed further then it would be great.
After doing a lot of research in the Wiki, studying the code in sc-player.js, and some testing, I think I've found a solution to your problem. Try the following:
First, add this code to sc-player.js file, just before the comment // the default Auto-Initialization (this line is just like 8 lines before the end of the file)
$.scPlayer.loadTrackInfoAndPlay=function($elem,track){
var playerObj=players[$elem.data('sc-player').id];
playerObj.tracks.push(track);
var index =playerObj.tracks.length-1;
var $list=$(playerObj.node).find('.sc-trackslist');
var $artworks=$(playerObj.node).find(".sc-artwork-list");
// add to playlist
var $li=$('<li>' + track.title + '<span class="sc-track-duration">' + timecode(track.duration) + '</span></li>')
.data('sc-track', {id:index})
.appendTo($list);
// add to artwork list
$('<li></li>')
.append(artworkImage(track, true))
.appendTo($artworks)
.data('sc-track', track);
$li.click();
}
The function above, takes care of adding a new track to the playlist and starts playing the track.
Now, suppose you have this html code for the players
<h2>Top Player</h2>
<div id="topPlayer">
<div class="sc-player">
My live track
On the bridge
</div>
</div>
<h2>Small Player</h2>
<div id="smallPlayer">
Soulhack
</div>
Make sure to wrap your sc-players in a div, preferably with an id, so you can reference the players later in Javascript:
Finally, you can use this Javscript code to detect when a track is clicked in smallPlayer and add and play that track in topPlayer
$(function(){
var $topPlayer=$("#topPlayer .sc-player");//Top player
var $smallPlayer=$("#smallPlayer .sc-player");//Small Player
$smallPlayer.on("onPlayerInit.scPlayer",function(evt){//When player is ready
$smallPlayer.on("onPlayerTrackSwitch.scPlayer",function(evt,track){//Listen to track switch in smallPlayer
setTimeout(function(){//Wait a bit, to avoid playing problems between both players
$.scPlayer.loadTrackInfoAndPlay($topPlayer, track);
},250);
});
});
});
And that's It!.
EDIT
If you only have the url of the song to be added, you can do the following:
First, add this other function to sc-player.js file, just after the previous loadTrackInfoAndPlay function:
$.scPlayer.loadTrackUrlAndPlay=function($elem,url){
var apiUrl = scApiUrl(url, apiKey);
$.getJSON(apiUrl, function(data) {
if(data.duration){
data.permalink_url = url;
$.scPlayer.loadTrackInfoAndPlay($elem,data);//Call the previous function
}
});
}
Now, suppose you have this code for the urls of the songs:
<p>
The links <br />
<a class="songUrl" href="https://soundcloud.com/feintdnb/coldplay-fix-you-feint-bootleg">Coldplay-Fix you</a><br />
<a class="songUrl" href="https://soundcloud.com/nct-1/nct-you-preview-out-soon-for">NCT - You</a><br />
<a class="songUrl" href="https://soundcloud.com/tufftouch/devil-eyes-konflix-feat-leanne">Konflix - Devil Eyes</a>
</p>
Then, you can use this code to add the song to the playlist and start playing it (or just playing it if it already exists)
$(".songUrl").click(function(event){
event.preventDefault();
var url=$(this).attr("href");//Url of the song
//If the song is in the tracks list, this line finds it
var $theSong=$topPlayer.find(".sc-trackslist a[href='"+url+"']");
if($theSong.length==0){//
$.scPlayer.loadTrackUrlAndPlay($topPlayer,url );
}else{
$theSong.parent().click();//Fire click = play the song
}
});
And that's all that is needed.
I'll try to give you as much info as I can, but as there's nowhere to start, I'm not sure if it will help. It's important to start with the wiki. This is what I could extract from there:
Dynamic Track Loading
The player can be created on the fly, and therefore any url can be added. In order to do that, the following methods are available:
Appending directly to the element:
$('div.your-container-class').scPlayer({
links: [{url: "http://soundcloud.com/matas/hobnotropic", title: "http://soundcloud.com/matas/hobnotropic"}]
});
or Create the object and append where you want:
var $myPlayer = $.scPlayer({
links: [{url: "http://soundcloud.com/matas/hobnotropic", title: "http://soundcloud.com/matas/hobnotropic"}]
});
$myPlayer.appendTo($('#somewhere-deep-in-the-dom'));
A little example I just found:
$(function() {
$('a.sc-remote-play1').on('click', function(event) {
$('.sc-player').scPlayer({
links: [{url: "http://soundcloud.com/matas/hobnotropie", title: "Hobnotropic"}],
});
});
});
I believe that should solve the dynamic track loading.
Initializing scPlayer
It's important to take into account that the scPlayer must load itself, and therefore will not work if you change the url directly with jQuery. In order to initialize the scPlayer, which takes place once the DOM has loaded, you can use
$('a.your-link-class').scPlayer();
or
$('div.your-container-class').scPlayer();
Default loading takes place, as I said, on DOM load with the following method
$('a.sc-player, div.sc-player').scPlayer();
This default behaviour can be changed as follows:
$.scPlayer.defaults.onDomReady = function(){
// Default behaviour wanted. Per default we have:
$('a.your-link-class').scPlayer();
};
That's what I've got up to now. Try to get the scPlayer working (loading songs dynamically) and we can follow with the data load and all that stuff.

Play a sound on hover state

I'm trying to create a banner that would somehow look like a soundwave but behave like a piano keyboard. I'd like each key of this keyboard to play a short unique sound (.ogg or .mp3 samples) on hover state.
I know how to implement this using Flash but I'd like to stick to HTML/JS for this project and I'm having trouble actually getting it done.
The "keyboard" would look like this (SVG) :
Could you give me a few hints on how to implement this?
I'm thinking <svg>, <canvas>, or image maps could be good options.
Thank you very much for your help.
EDIT: You can try something like this instead:
Demo: http://jsfiddle.net/SO_AMK/xmXFf/
jQuery:
$("#layer1 rect").each(function(i) {
$("#playme").clone().attr({
"id": "playme-" + i,
"src": B64Notes[i]
}).appendTo($("#playme").parent());
$(this).data("audio", i);
});
$("#layer1 rect").hover(function() {
var playmeNum = $("#playme-" + $(this).data("audio"));
playmeNum.attr("src", playmeNum[0].src)[0].play();
// Reset the src to stop and restart so you can mouseover multiple times before the audio is finished
$(this).css("fill", "red");
}, function() {
$(this).css("fill", "#d91e63");
});​
I realize that you want to avoid duplication but there's no way to have multiple notes playing at the same time otherwise.
The svg is directly in the page to make the code simpler and because it would load from another domain preventing the jQuery from accessing and modifying it. To access the svg document when it's embedded from an external source, please see: http://xn--dahlstrm-t4a.net/svg/html/get-embedded-svg-document-script.html
How about assigning each key an id and using html5 <audio>?
Then using jQuery change the src attribute of audio tag?
$('#a').hover(function(){
$('#oggfile').attr("src","a.ogg");
$('#mpegfile').attr("src","a.mp3");
});
$('#c').hover(function(){
$('#oggfile').attr("src","a.ogg");
$('#mpegfile').attr("src","a.mp3");
});
$('#c').hover(function(){
$('#oggfile').attr("src","c.ogg");
$('#mpegfile').attr("src","c.mp3");
});
​
http://jsfiddle.net/wPGSv/

How to move an iFrame in the DOM without losing its state?

Take a look at this simple HTML:
<div id="wrap1">
<iframe id="iframe1"></iframe>
</div>
<div id="warp2">
<iframe id="iframe2"></iframe>
</div>
Let's say I wanted to move the wraps so that the #wrap2 would be before the #wrap1. The iframes are polluted by JavaScript. I am aware of jQuery's .insertAfter() and .insertBefore(). However, when I use those, the iFrame loses all of its HTML, and JavaScript variables and events.
Lets say the following was the iFrame's HTML:
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
// The variable below would change on click
// This represents changes on variables after the code is loaded
// These changes should remain after the iFrame is moved
variableThatChanges = false;
$(function(){
$("body").click(function(){
variableThatChanges = true;
});
});
</script>
</head>
<body>
<div id='anything'>Illustrative Example</div>
</body>
</html>
In the above code, the variable variableThatChanges would...change if the user clicked on the body. This variable, and the click event, should remain after the iFrame is moved (along with any other variables/events that have been started)
My question is the following: with JavaScript (with or without jQuery), how can I move the wrap nodes in the DOM (and their iframe childs) so that the iFrame's window stays the same, and the iFrame's events/variables/etc stay the same?
It isn't possible to move an iframe from one place in the dom to another without it reloading.
Here is an example to show that even using native JavaScript the iFrames still reload:
http://jsfiddle.net/pZ23B/
var wrap1 = document.getElementById('wrap1');
var wrap2 = document.getElementById('wrap2');
setTimeout(function(){
document.getElementsByTagName('body')[0].appendChild(wrap1);
},10000);
This answer is related to the bounty by #djechlin
A lot of search on the w3/dom specs and didn't find anything final that specifically says that iframe should be reloaded while moving in the DOM tree, however I did find lots of references and comments in the webkit's trac/bugzilla/microsoft regarding different behavior changes over the years.
I hope someone will find anything specific regarding this issue, but for now here are my findings:
According to Ryosuke Niwa - "That's the expected behavior".
There was a "magic iframe" (webkit, 2010), but it was removed in 2012.
According to MS - "iframe resources are freed when removed from the DOM". When you appendChild(node) of existing node - that node is first removed from the dom.
Interesting thing here - IE<=8 didn't reload the iframe - this behavior is (somewhat) new (since IE>=9).
According to Hallvord R. M. Steen comment, this is a quote from the iframe specs
When an iframe element is inserted into a document that has a browsing context, the user agent must create a new browsing context, set the element's nested browsing context to the newly-created browsing context, and then process the iframe attributes for the "first time".
This is the most close thing I found in the specs, however it's still require some interpretation (since when we move the iframe element in the DOM we don't really do a full remove, even if the browsers uses the node.removeChild method).
Whenever an iframe is appended and has a src attribute applied it fires a load action similarly to when creating an Image tag via JS. So when you remove and then append them they are completely new entities and they refresh. Its kind of how window.location = window.location will reload a page.
The only way I know to reposition iframes is via CSS. Here is an example I put together showing one way to handle this with flex-box:
https://jsfiddle.net/3g73sz3k/15/
The basic idea is to create a flex-box wrapper and then define an specific order for the iframes using the order attribute on each iframe wrapper.
<style>
.container{
display: flex;
flex-direction: column;
}
</style>
<div class="container">
<div id="wrap1" style="order: 0" class="iframe-wrapper">
<iframe id="iframe1" src="https://google.com"></iframe>
</div>
<div id="warp2" style="order: 1" class="iframe-wrapper">
<iframe id="iframe2" src="https://bing.com"></iframe>
</div>
</div>
As you can see in the JS fiddle these order styles are inline to simplify the flip button so rotate the iframes.
I sourced the solution from this StackOverflow question: Swap DIV position with CSS only
Hope that helps.
If you have created the iFrame on the page and simply need to move it's position later try this approach:
Append the iFrame to the body and use a high z-index and top,left,width,height to put the iFrame where you want.
Even CSS zoom works on the body without reloading which is awesome!
I maintain two states for my "widget" and it is either injected in place in the DOM or to the body using this method.
This is useful when other content or libraries will squish or squash your iFrame.
BOOM!
Unfortunately, the parentNode property of an HTML DOM element is read-only. You can adjust the positions of the iframes, of course, but you can't change their location in the DOM and preserve their states.
See this jsfiddle I created that provides a good test bed. http://jsfiddle.net/RpHTj/1/
Click on the box to toggle the value. Click on the "move" to run the javascript.
This question is pretty old... but I did find a way to move an iframe without it reloading. CSS only. I have multiple iframes with camera streams, I dont like when they reload when i swap them. So i used a combination of float, position:absolute, and some dummy blocks to move them around without reloading them and having the desired layout on demand (resizing and all).
If you are using the iframe to access pages you control, you could create some javascript to allow your parent to communicate with the iframe via postMessage
From there, you could build login inside the iframe to record state changes, and before moving dom, request that as a json object.
Once moved, the iframe will reload, you can pass the state data into the iframe and the iframe listening can parse the data back into the previous state.
PaulSCoder has the right solution. Never manipulate the DOM for this purpose. The classic approach for this is to have a relative position and "flip" the positions in the click event. It's only not wise to put the click event on the body, because it bubbles from other elements too.
$("body").click(function () {
var frame1Height = $(frame1).outerHeight(true);
var frame2Height = $(frame2).outerHeight(true);
var pos = $(frame1).css("top");
if (pos === "0px") {
$(frame1).css("top", frame2Height);
$(frame2).css("top", -frame1Height);
} else {
$(frame1).css("top", 0);
$(frame2).css("top", 0);
}
});
If you only have content that is not cross-domain you could save and restore the HTML:
var htmlContent = $(frame).contents().find("html").children();
// do something
$(frame).contents().find("html").html(htmlContent);
The advantage of the first method is, that the frame keeps on doing what it was doing. With the second method, the frame gets reloaded and starts it's code again.
At least in some circumstances a shadow dom with slotting might be an option.
<template>
<style>div {outline:1px solid black; height:45px}</style>
<div><slot name="a" /></div>
<div><slot name="b" /></div>
</template>
<div id="shadowhost">
<iframe src="data:text/html,<button onclick='this.innerText+=`!`'>!</button>"
slot="a" height=40px ></iframe>
</div>
<button onclick="ifr.slot= (ifr.slot=='a') ? 'b' : 'a';">swap</button>
<script>
document.querySelector('#shadowhost').attachShadow({mode: 'open'}).appendChild(
document.querySelector('template').content
);
ifr=document.querySelector('iframe');
</script>
In response to the bounty #djechlin placed on this question, I have forked the jsfiddle posted by #matt-h and have come to the conclusion that this is still not possible.
http://jsfiddle.net/gr3wo9u6/
//this does not work, the frames reload when appended back to the DOM
function swapFrames() {
var w1 = document.getElementById('wrap1');
var w2 = document.getElementById('wrap2');
var f1 = w1.querySelector('iframe');
var f2 = w2.querySelector('iframe');
w1.removeChild(f1);
w2.removeChild(f2);
w1.appendChild(f2);
w2.appendChild(f1);
//f1.parentNode = w2;
//f2.parentNode = w1;
//alert(f1.parentNode.id);
}

Automatically rotate through content

I have 7 graphs that are accessible to me through a web site. I want to develop my own web application that automatically cycles through each of these graphs, so I can display them on a huge monitor.
I want the functionality to be similar to an image carousel but it would be for web pages instead of images. What are my options? A jQuery plugin? AJAX and an iframe? Keep in mind that I want the data to be live while I display it.
You could use javascript, and a Frame with a simple timer to load it.
Nothing complex needed,
In the title frame set add this:
<script language="JavaScript">
var toShow;
var URL = new Array ('http://www.google.com','www.yahoo.com','www.bit.ly');
function setupTimer() {
toShow = 0;
loadNext();
var t=setTimeout("loadNext()", 3000);
}
function loadNext(){
parent.reportframe.location=URL[toShow];
toShow++;
if (toShow>3) toShow = 0;
}
</script>
<body onLoad="setupTimer()">
Then it will keep reloading the frames.
I just wrote this, did not test it, let me know if you need more help.
http://jsfiddle.net/5dazE/5/show
That's a basic slideshow. You can add or remove sites and then press play. It will rotate every 30 seconds. the code can be fond here: http://jsfiddle.net/5dazE/5
it could use more work, but I am in agreement with #nycynik. It is a great idea.

Categories