How to search a playlist in brightcove - brightcove

All -
I have implemented a simple html page and added brightcove js file and flash code to it. The code displays playlist for the user and a player. Does brightcove give us the ability to search from the playlist?

You can use Playlist read api methods.
http://docs.brightcove.com/en/media/reference.html#Playlist_Read
they return the members of the playlist. you need additional code to search within its members.

If playlist is too large, response may fail. Brightcove provides pagenation and total page number for each json element. So call first page and get total page number. Iterate all pages, call each page and get a playlist. And concatenate each playlist into an array which is the playlist.
var dataPageSize = 10;
var brightcoveAPiUrl ="https://api.brightcove.com/services/library";
var callBrightcove= function(data){
return $.ajax({
url: brightcoveAPiUrl,
dataType:'jsonp',
data:data
)}
};
function getPlaylist(pageNumber) {
return callBrightcove({
"command": "find_all_playlists",
"playlist_fields": "id,name,filterTags",
"page_number": pageNumber,
"page_size": dataPageSize,
"get_item_count": "true",
"token": brightcoveReadToken
}
);
}
function getAllPlaylist() {
var startPageNumber = 0;
getPlaylist(startPageNumber).done(function (data) {
var dataArr = [data];
var playlistArr = [], requests = [], i;
var requestCount = parseInt(data.total_count / dataPageSize);
// Deferred Requests Array
for (i = 0; i < requestCount; i++) {
requests.push(getPlaylist(i + 1).done(function (data) {
dataArr = dataArr.concat(data);
}))
}
}

Related

Problem with scope when inserting results of ajax call into page code

I have data returned from an Ajax call, but need to pass variables into or out of the Ajax onSuccess function to insert the results into my page. I'm pretty sure this is a scope problem.
I posted a complicated question here yesterday, mostly about the Ajax part of this, and that part is now working - I'm getting the results back correctly. I could insert it into my page code in two ways, but one involves getting a variable value out of the onSuccess function; the other needs to get a variable value into it! I can't make either of them work. Here's a stripped-down version of the code:
var base = 'http://10.0.1.2:90/~dvds/';
// initialization routines
document.observe ('dom:loaded', function() {
// set up handler for variable numbers of selects
var addselects = $$('.addselect');
for (var i = 0; i < addselects.length; i++) {
var addselect = addselects[i];
addselect.onchange = newSelect;
}
});
// handler for adding new field to array
function newSelect() {
var thisid = this.id;
var newhtml;
var url = base + 'ajaxtest';
// send request to do the business
var myAjax = new Ajax.Request (url, {
method: 'post',
onSuccess: function (req) {
var xml = req.responseXML;
var id = xml.getElementsByTagName('id')[0].firstChild.nodeValue;
if (id) {
newhtml = '\t\t<li>\r\t\t\t<select class="addselect" name="newlist" id="newlist" />\r\t\t\t\t<option value="" selected="selected"></option>\r';
// loop
var newid, newname;
var ids = xml.getElementsByTagName('id');
var names = xml.getElementsByTagName('name');
for (var i = 0; i < ids.length; i++) {
newid = ids[i].firstChild.nodeValue;
newname = names[i].firstChild.nodeValue;
newhtml += '\t\t\t\t<option value="' + newid + '">' + newname + '</option>\r';
}
newhtml += '\t\t\t</select>\r\t\t</li>\r';
// alert (thisid);
$('thisid').up('ul').insert (newhtml);
}
else {
alert (’ng');
newhtml = '<li>No good.</li>';
}
},
onFailure: function() {
alert ('Script failure.');
newhtml = '<li>No good.</li>';
}
});
// alert (newhtml);
// if (newhtml) {
// this.up('ul').insert (newhtml);
// }
}
Having established the variable thisid as this.id, I don't understand why $('thisid') doesn't work in the line $('thisid').up('ul').insert (newhtml); - especially as the value of thisid does show up correctly in the alert I've put in for testing (commented out). Why is this? If I put newhtml into that alert instead it's also correct.
And given that that seems not to work, I tried the alternative of passing the value of newhtml out (having declared it at the top) and inserting it in the page in the last block of code that's commented out - but that doesn’t work either.
Where am I going wrong?

Submitting data to google sheet with multiple tab sheets

I'm referencing this article "How to Submit an HTML Form to Google Sheets…without Google Forms", it worked perfectly for me for only a Google Sheet with one tab.
Need help how to dynamically select what sheet tab the data should be written in the case the google sheet has multiple tabs. I'm using Ajax to submit google sheet btw.
Here's the call by the Ajax:
var $form = $('form#test-form'),
url = 'https://script.google.com/macros/s/MyScript/exec'
$('#submit-form').on('click', function(e) {
e.preventDefault();
var jqxhr = $.ajax({
url: url,
method: "GET",
dataType: "json",
data: $form.serializeObject()
}).success(
// do something
);
})
The code on google sheet web app
function doGet(e){
return handleResponse(e);
}
// Enter sheet name where data is to be written below
var SHEET_NAME = "Sheet1";
var SCRIPT_PROP = PropertiesService.getScriptProperties(); // new property service
function handleResponse(e) {
// shortly after my original solution Google announced the LockService[1]
// this prevents concurrent access overwritting data
// [1] http://googleappsdeveloper.blogspot.co.uk/2011/10/concurrency-and-google-apps-script.html
// we want a public lock, one that locks for all invocations
var lock = LockService.getPublicLock();
lock.waitLock(30000); // wait 30 seconds before conceding defeat.
try {
// next set where we write the data - you could write to multiple/alternate destinations
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
// we'll assume header is in row 1 but you can override with header_row in GET/POST data
var headRow = e.parameter.header_row || 1;
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var nextRow = sheet.getLastRow()+1; // get next row
var row = [];
// loop through the header columns
for (i in headers){
if (headers[i] == "Timestamp"){ // special case if you include a 'Timestamp' column
row.push(new Date());
} else { // else use header name to get data
row.push(e.parameter[headers[i]]);
}
}
// more efficient to set values as [][] array than individually
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "row": nextRow}))
.setMimeType(ContentService.MimeType.JSON);
} catch(e){
// if error return this
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": e}))
.setMimeType(ContentService.MimeType.JSON);
} finally { //release lock
lock.releaseLock();
}
}
function setup() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
SCRIPT_PROP.setProperty("key", doc.getId());
}
If there is a way to change the variable SHEET_NAME dynamically then I think it will be good. Thanks

How do I access every index of a specific Array inside an AJAX object

I'm calling an ajax for giphy, with this code:
$.ajax({
url: queryURL,
method: "GET"
}). then(function(response) {
console.log(response);
when I look at the console log there's an object with the first property being data. Each index of data is another object, inside this object are two properties i'm trying to pull, rating and url. I want to be able to list the rating and url not just of a specific index, but every index in that data array. What would be the best way to do that? Currently I've tried a for loop
for (var i = 0; i<response.data.length;i++){
var dataIndex = response.data[i];
}
then <creating a variable something like>
var imgURL = response.data[dataIndex].url
but its not working.
Here's the entire code
function displayTopicGif() {
var topic = $(this).attr("data-name");
// query url
var queryURL = "https://api.giphy.com/v1/gifs/search?q=" + topic + "&limit=20&rating=r&api_key=";
$.ajax({
url: queryURL,
method: "GET"
}).then(function (response) {
console.log(response);
// for loop to create a variable for the index of the objects data
for (var i = 0; i < response.data.length; i++) {
var dataIndex = response.data[i];
}
// where the gif's will be dumped
var topicDiv = $("<div class='topic'>");
// rating of gif
var rating = response.data[0].rating;
console.log(rating);
// Creating an element to have the rating displayed
var pOne = $("<p>").text("Rating: " + rating);
// add to the rating element
topicDiv.append(pOne);
// retrieve the IMG of the gif
var imgURL = response.data[0].url;
var image = $("<img>").attr("src", imgURL);
topicDiv.append(image);
// put gif into topic-view div
$("#topic-view").prepend(topicDiv);
});
}
You can check that something is an object using $.isPlainObject and then read through its properties via:
for (key in object) {
var value = object[key];
//log
}
Or you can get the keys using Object.getOwnPropertyNames();. See this sample excerpt from MDN:
const object1 = {
a: 1,
b: 2,
c: 3
};
console.log(Object.getOwnPropertyNames(object1));
// expected output: Array ["a", "b", "c"]

Why my extension sends duplicates on request in geometric progression?

I've created extension that makes some JSON request & send it to some receiver.
My problem is:
Open popup window
After it closing, extensions sends 1 request
Open it on the same page again, and extension will send 2 requests
Open again, 4 requests
Open again, 8 requests
In each uses of popup, extension will be duplicate outgoing data in geometric progression.
Why that happens?
From the panel I'm send addnewurl to the port:
AddDialog.port.on("addnewurl", function (data) {
{
AddDialog is my popup
here It handle port messages aftre popup is closed(hidded)
}
var http = require("sdk/request").Request;
var req = CreateRequest("add_url", {});
req.params = {...};
var sreq = encodeURIComponent(JSON.stringify(req));
count += 1; //Global counter, u will see it in video
console.log('count = '+count);
var cfg = {
url : getRequestURL(),
contentType : "text/html",
content : sreq,
onComplete : function (response) {
var data = {
code : response.status,
body : response.json
};
AddDialog.port.emit("addnewurldone", data);
}
};
http(cfg).post();
});
For more sense I've created a AVI video record of that. See it here:
https://dl.dropboxusercontent.com/u/86175609/Project002.avi
1.6 MB
How to resolve that?
ADDED by request more info
That function emit addnewurl:
function AddNewURL() {
var node = $("#Tree").dynatree("getActiveNode");
if (node == null) {
$("#ServerStatus").text(LocalizedStr.Status_NoGroupSelected);
$("#ServerStatus").css("color", "red");
return;
};
var nkey = node.data.key;
var aImg = null;
var data = {
ownerId : nkey,
name : $("#LinkTitle").val(),
description : $("#LinkDesc").val(),
url : $("#CurrentURL").val(),
scrcapt:$("#ScrCaptureCB :selected").val()
};
$("#load").css("display", "inline");
$("#ServerStatus").text(LocalizedStr.Status_AddURL);
self.port.emit("addnewurl", data);
};
and it calls by button:
self.port.on("showme", function onShow(data) {
....
document.querySelector('#BtnOk').addEventListener('click', function () {
AddNewURL();
});
...
});
"swomme" goes from here(main.js):
AddDialog.on("show", function () {
count = 0;
AddDialog.port.emit("showme", locTbl);
});
function addToolbarButton() {
var enumerator = mediator.getEnumerator("navigator:browser");
while (enumerator.hasMoreElements()) {
var document = enumerator.getNext().document;
var navBar = document.getElementById('nav-bar');
if (!navBar) {
return;
}
var btn = document.createElement('toolbarbutton');
btn.setAttribute('id', cBtnId);
btn.setAttribute('type', 'button');
btn.setAttribute('class', 'FLAToolButton');
btn.setAttribute('image', data.url('icons/Add.png'));
btn.setAttribute('orient', 'horizontal');
btn.setAttribute('label', loc("Main_ContextMenu"));
btn.addEventListener('click', function () {
AddDialog.show();
}, false)
navBar.appendChild(btn);
}
}
I think the problem is here
document.querySelector('#BtnOk').addEventListener('click', function () {
AddNewURL();
});
If you are running AddDialog.port.emit("showme", locTbl); when you click your toolbar button then you're adding a click listener to #BtnOk every time as well.
On the first toolbar click it will have one click listener, on the second click two, and so on. You should remove the above code from that function and only run it once.

Youtube API v3 - Select menu to access public channel video data without Oauth

I want to access and view public Youtube videos (simple read only) from any Youtube channel without resorting to Oauth, just with plain API key. I haven't found a decent layman example on how to go about with API v3 ;-(
I have this to juggle with which I cannot get to work. Basically, a Select menu contains options whose values are existing channel IDs. When an option containing a channel ID is selected, it should trigger requestUserUploadsPlaylistId(). Then, when NEXTbutton or PREVIOUSbutton are activated, function requestVideoPlaylist() would kick in. Is there a better way to do this? I get the following error messages in Firebug:
TypeError: response.result is undefined (When I choose an option from SELECTmenu).
TypeError: response.result is undefined (After I click on buttons).
Here is what I am struggling with (am new to API v3 and kinda used to API v2 (sigh)):
<HTML is here>
script>
$('#NEXTbutton').prop('disabled', true).addClass('disabled');
</script>
<script type="text/javascript" src="https://apis.google.com
/js/client.js?onload=onJSClientLoad"></script>
<script>
var dd, playlistId, nextPageToken, prevPageToken;
function onJSClientLoad() {
gapi.client.setApiKey('YOUR-API-KEY');
gapi.client.load('youtube', 'v3', function(){
$('#NEXTbutton').prop('disabled', false).removeClass('disabled');
});
}
// Calling the following function via selected option value of select menu
// I am using "mine: false," since it's an unauthenticated request ??
function requestUserUploadsPlaylistId() {
var dd = $("#SELECTmenu option:selected").val();
var request = gapi.client.youtube.channels.list({
mine: false, // is this legit?
channelId: dd, // Variable is preset chosen value of SELECTmenu options
part: 'contentDetails,id'
});
request.execute(function(response) {
playlistId = response.result.items[0].contentDetails.relatedPlaylists.uploads;
channelId = response.result.items[0].id;
});
}
function requestVideoPlaylist(playlistId, pageToken) {
var requestOptions = {
playlistId: playlistId,
part: 'snippet,id',
maxResults: 5
};
if (pageToken) {
requestOptions.pageToken = pageToken;
}
var request = gapi.client.youtube.playlistItems.list(requestOptions);
request.execute(function(response) {
// Only show the page buttons if there's a next or previous page.
nextPageToken = response.result.nextPageToken;
var nextVis = nextPageToken ? 'visible' : 'hidden';
$('#NEXTbutton').css('visibility', nextVis);
prevPageToken = response.result.prevPageToken
var prevVis = prevPageToken ? 'visible' : 'hidden';
$('#PREVIOUSbutton').css('visibility', prevVis);
var playlistItems = response.result.items;
if (playlistItems) {
$.each(playlistItems, function(index, item) {
displayResult(item.snippet);
});
} else {
$('#CONTAINER').html('Sorry, no uploaded videos available');
}
});
}
function displayResult(videoSnippet) {
for(var i=0;i<response.items.length;i++) {
var channelTitle = response.items[i].snippet.channelTitle
var videoTitle = response.items[i].snippet.title;
var Thumbnail = response.items[i].snippet.thumbnails.medium.url;
var results = '<li><div class="video-result"><img src="'+Thumbnail+'" /></div>
<div class="chantitle">'+channelTitle+'</div>
<div class="vidtitle">'+videoTitle+'</div></li>';
$('#CONTAINER').append(results);
}
}
function nextPage() {
requestVideoPlaylist(playlistId, nextPageToken);
}
function previousPage() {
requestVideoPlaylist(playlistId, prevPageToken);
}
$('#NEXTbutton').on('click', function() { // Display next 5 results
nextPage();
});
$('#PREVIOUSbutton').on('click', function() { // Display previous 5 results
previousPage();
});
$("#SELECTmenu").on("change", function() {
$('#CONTAINER').empty();
if ($("#SELECTmenu option:selected").val().length === 24) { //Channel ID length
requestUserUploadsPlaylistId();
} else {
return false;
}
});
I'm surely missing something here, any pointers will be greatly appreciated.
FINAL UPDATE
A few updates later and I've finally answered my question after playing with the awesome Google APIs Explorer tool. Here is a sample working code allowing access to Youtube channel video-related data from a Select menu for read-only without using OAUTH, just an API key. The Select menu, based on a selected option's value (which contains a channel id), posts a video thumbnail, the thumbnail's channel origin; and the video's title. Should be easy to make the thumbnail clickable so as to load video in iframe embed or redirect to Youtube page. Enjoy!
// Change values and titles accordingly
<select id="SELECTmenu">
<option value="selchan">Select channel ...</option>
<option value="-YOUR-24digit-ChannelID-">Put-channel-title-here</option>
<option value="-YOUR-24digit-ChannelID-">Put-channel-title-here</option>
</select>
<button id="NEXTbutton">NEXT</button>
<button id="PREVIOUSbutton">PREV</button>
<ol id="CONTAINER"></ol> // Loads video data response
<script type="text/javascript"
src="https://apis.google.com/js/client.js?onload=onJSClientLoad">
</script>
var playlistId, nextPageToken, prevPageToken;
function onJSClientLoad() {
gapi.client.setApiKey('INSERT-YOUR-API-KEY'); // Insert your API key
gapi.client.load('youtube', 'v3', function(){
//Add function here if some action required immediately after the API loads
});
}
function requestUserUploadsPlaylistId(pageToken) {
// https://developers.google.com/youtube/v3/docs/channels/list
var selchan = $("#SELECTmenu option:selected").val();
var request = gapi.client.youtube.channels.list({
id: selchan,
part: 'snippet,contentDetails',
filter: 'uploads'
});
request.execute(function(response) {
playlistId = response.result.items[0].contentDetails.relatedPlaylists.uploads;
channelId = response.result.items[0].id;
requestVideoPlaylist(playlistId, pageToken);
});
}
function requestVideoPlaylist(playlistId, pageToken) {
$('#CONTAINER').empty();
var requestOptions = {
playlistId: playlistId,
part: 'snippet,id',
maxResults: 5 // can be changed
};
if (pageToken) {
requestOptions.pageToken = pageToken;
}
var request = gapi.client.youtube.playlistItems.list(requestOptions);
request.execute(function(response) {
// Only show the page buttons if there's a next or previous page.
nextPageToken = response.result.nextPageToken;
var nextVis = nextPageToken ? 'visible' : 'hidden';
$('#NEXTbutton').css('visibility', nextVis);
prevPageToken = response.result.prevPageToken
var prevVis = prevPageToken ? 'visible' : 'hidden';
$('#PREVIOUSbutton').css('visibility', prevVis);
var playlistItems = response.result.items;
if (playlistItems) {
displayResult(playlistItems);
} else {
$('#CONTAINER').html('Sorry, no uploaded videos.');
}
});
}
function displayResult(playlistItems) {
for(var i=0;i<playlistItems.length;i++) {
var channelTitle = playlistItems[i].snippet.channelTitle
var videoTitle = playlistItems[i].snippet.title;
var videoThumbnail = playlistItems[i].snippet.thumbnails.medium.url;
var results = '<li>
<div>'+channelTitle+'</div>
<div><img src="'+videoThumbnail+'" /></div>
<div>'+videoTitle+'</div>
</li>';
$('#CONTAINER').append(results);
}
}
function nextPage() {
$('#CONTAINER').empty(); // This needed here
requestVideoPlaylist(playlistId, nextPageToken);
}
function previousPage() {
$('#CONTAINER').empty(); // This needed here
requestVideoPlaylist(playlistId, prevPageToken);
}
$('#NEXTbutton').on('click', function() { // Display next maxResults
nextPage();
});
$('#PREVIOUSbutton').on('click', function() { // Display previous maxResults
previousPage();
});
// Using as filtering example Select option values which contain channel
// ID length of 24 alphanumerics/symbols to trigger functions just in case
// there are other option values in the menu that do not refer to channel IDs.
$("#SELECTmenu").on("change", function() {
$('#CONTAINER').empty();
if ($("#SELECTmenu option:selected").val().length === 24) {
requestUserUploadsPlaylistId();
return false;
} else {
return false;
}
});
NOTE:
Remember, code sample above is built based on what API v3 provided at the time of this posting.
TIP: It's better to make sure that the buttons be disabled during API call and re-enabled after API has posted the expected results. If you press those buttons while processing, you may get compounded and/or unexpected results. ~ Koolness

Resources