Video.js - How to reference multiple videos in one page? - arrays

My goodness, I cannot find an answer for this and I spent several hours already.
How can you reference multiple videos at the same time in video.js?
The API documentation says:
Referencing the Player: You just need to make sure your video tag has an ID. The example embed code has an ID of "example_video_1". If you have multiple videos on one page, make sure every video tag has a unique ID.
var myPlayer = V("example_video_1");
This example shows a single ID, but it doesnt show how I can reference multiple IDs at the same time.
If I have 3 different tags: "video_1", "video_2", "video_3", how do I reference them all?
I tried an array and it didnt work. I also tried listing the videos like this:
var myPlayer = _V_("video_1", "video_2");
and didnt work neither.
Can somebody help me here?
Thank you.

You can't pass multiple ids to _V_(). Either do them one at a time:
var myPlayer1 = _V_("video_1");
var myPlayer2 = _V_("video_2");
var myPlayer3 = _V_("video_3");
Or if you want them as an array:
var myPlayers = Array(_V_("video_1"), _V_("video_2"), _V_("video_3"));
myPlayers[1].play();
Note: this was written for an older version of video.js. _V_() still works but is deprecated: use videojs() instead.

This would also work:
var video = [];
video[1] = _V_("Video1");
video[2] = _V_("Video2");
video[3] = _V_("Video3");
video[4] = _V_("Video4");
video[5] = _V_("Video5");
video[6] = _V_("Video6");
video[7] = _V_("Video7");
video[8] = _V_("Video8");
video[9] = _V_("Video9");
video[10] = _V_("Video10");

Related

Google Apps Script: Use array out of spreadsheet

I try to use Google Script Apps (instead of VBA which I am more used to) and managed now to create a loop over different spreadsheets (and not only different sheets in one document) using the forEach function.
(I tried with a for (r=1;r=lastRow; r++) but I did not manage).
It is working now defining the array for the sheetnames manually:
var SheetList = ["17DCu1nyyX4a6zCkkT3RfBSfo-ghoc2fXEX8chlVMv5k", "1rRGQHs_JShPSBIGFCdG6AqXM967JFhdlfQ92cf5ISL8", "1pFDyXgYmvC5gnN5AU5xJ8vGiihwtubcbG2n4LPhPACQ", "1mK_X4Q7ysJQTt8NZoZASBE5zuUllPmmWSJsxu5Dnu9Y", "1FpjIGWTG5_6MMYJF72wvoiBRp_Xlt5BDpzvSZKcsU"]
And then for information the loop:
SheetList.forEach(function(r) {
var thisSpreadsheet = SpreadsheetApp.openById(r)
var thisData = thisSpreadsheet.getSheetByName('Actions').getDataRange()
var values = thisData.getValues();
var toWorksheet = targetSpreadsheetID.getSheetByName(targetWorksheetName);
var last = toWorksheet.getLastRow ()+ 1
var toRange = toWorksheet.getRange(last, 1, thisData.getNumRows(), thisData.getNumColumns())
toRange.setValues(values);
})
Now I want to create the definition of the array "automatically" out of the spreadsheet 'List' where all spreadsheets which I want to loop are listed in column C.
I tried several ideas, but always failed.
Most optimistic ones were:
var SheetList = targetSpreadsheetID.getSheetByName('List').getRange(2,3,lastRow-2,3).getValues()
And I also tried with the array-function:
var sheetList=Array.apply(targetSpreadsheetID.getSheetByName('List').getRange(2,3,lastRow-2,3))
but all without success.
It should be possible normally in more or less one single line to import the array from the speadsheet to the Google apps scripts?
I would very much appreciate if someone could please give me a hint where my mistake is.
Thank you very much.
Maria
I still did not manage to put the array as I wanted it initially, but now I found a workable solution with the For Loop which I want to share here in case someone is looking for a similar solution (and then finds at least my workaround ;) )
for (i=2; i<lastRow;i++){
var SheetList = targetSpreadsheetID.getSheetByName('List').getRange(i,3).getValues()
Logger.log(SheetList);
var thisSpreadsheet = SpreadsheetApp.openById(SheetList);
... // the rest identical to loop above...
Don't hesitate to add your comments or advice anyhow, but I will mark the question as closed.
Thanks a lot.
Maria

Problem with connectorConfig in direct link for MULTIPLE field

When transferring connector config via a direct link, it does not work for MULTIPLE field. I tried different options:
https://datastudio.google.com/u/0/datasources/create?connectorId=...&connectorConfig={"project_id":"[11]"}&reportTemplateId=...
{"project_id":"11"}
{"project_id":["11"]}
{"project_id":"[\"11\"]"}
function getConfig(request) {
var cc = DataStudioApp.createCommunityConnector();
var config = cc.getConfig();
var option1 = config.newOptionBuilder()
.setLabel("11")
.setValue("11");
var info1 = config.newSelectMultiple()
.setId('project_id')
.setName('Name project')
.addOption(option1)
.setAllowOverride(true);
config.setDateRangeRequired(true);
return config.build();
}
Edit: 10-17-2019
Turns out this was a bug! Thanks for bringing up the issue. It should be resolved now. The correct format is an array of strings (the second 3rd bullet point above).

Best practices to execute faster a CasperJS script that scrapes thousands of pages

I've written a CasperJS script that works very well except that it takes a (very very) long time to scrape pages.
In a nutshell, here's the pseudo code:
my functions to scrape the elements
my casper.start() to start the navigation and log in
casper.then() where I loop through an array and store my links
casper.thenOpen() to open each link and call my functions to scrap.
It works perfectly (and fast enough) for scraping a bunch of links. But when it comes to thousands (right now I'm running the script with an array of 100K links), the execution time is endless: the first 10K links have been scrapped in 3h54m10s and the following 10K in 2h18m27s.
I can explain a little bit the difference between the two 10K batches : the first includes the looping & storage of the array with the 100K links. From this point, the scripts only open pages to scrap them. However, I noticed the array was ready to go after roughly 30 minutes so it doesn't explain exactly the time gap.
I've placed my casper.thenOpen() in the for loop hoping that after each new link built and stored in the array, the scrapping will happen. Now, I'm sure I've failed this but will it change anything in terms of performance ?
That's the only lead I have in mind right now and I'd be very thankful if anyone is willing to share his/her best practices to reduce significantly the running time of the script's execution (shouldn't be hard!).
EDIT #1
Here's my code below:
var casper = require('casper').create();
var fs = require('fs');
// This array maintains a list of links to each HOL profile
// Example of a valid URL: https://myurl.com/list/74832
var root = 'https://myurl.com/list/';
var end = 0;
var limit = 100000;
var scrapedRows = [];
// Returns the selector element property if the selector exists but otherwise returns defaultValue
function querySelectorGet(selector, property, defaultValue) {
var item = document.querySelector(selector);
item = item ? item[property] : defaultValue;
return item;
}
// Scraping function
function scrapDetails(querySelectorGet) {
var info1 = querySelectorGet("div.classA h1", 'innerHTML', 'N/A').trim()
var info2 = querySelectorGet("a.classB span", 'innerHTML', 'N/A').trim()
var info3 = querySelectorGet("a.classC span", 'innerHTML', 'N/A').trim()
//For scraping different texts of the same kind (i.e: comments from users)
var commentsTags = document.querySelectorAll('div.classComments');
var comments = Array.prototype.map.call(commentsTags, function(e) {
return e.innerText;
})
// Return all the rest of the information as a JSON string
return {
info1: info1,
info2: info2,
info3: info3,
// There is no fixed number of comments & answers so we join them with a semicolon
comments : comments.join(' ; ')
};
}
casper.start('http://myurl.com/login', function() {
this.sendKeys('#username', 'username', {keepFocus: true});
this.sendKeys('#password', 'password', {keepFocus: true});
this.sendKeys('#password', casper.page.event.key.Enter, {keepFocus: true});
// Logged In
this.wait(3000,function(){
//Verify connection by printing welcome page's title
this.echo( 'Opened main site titled: ' + this.getTitle());
});
});
casper.then( function() {
//Quick summary
this.echo('# of links : ' + limit);
this.echo('scraping links ...')
for (var i = 0; i < limit; i++) {
// Building the urls to visit
var link = root + end;
// Visiting pages...
casper.thenOpen(link).then(function() {
// We pass the querySelectorGet method to use it within the webpage context
var row = this.evaluate(scrapDetails, querySelectorGet);
scrapedRows.push(row);
// Stats display
this.echo('Scraped row ' + scrapedRows.length + ' of ' + limit);
});
end++;
}
});
casper.then(function() {
fs.write('infos.json', JSON.stringify(scrapedRows), 'w')
});
casper.run( function() {
casper.exit();
});
At this point I probably have more questions than answers but let's try.
Is there a particular reason why you're using CasperJS and not Curl for example ? I can understand the need for CasperJS if you are going to scrape a site that uses Javascript for example. Or you want to take screenshots. Otherwise I would probably use Curl along with a scripting language like PHP or Python and take advantage of the built-in DOM parsing functions.
And you can of course use dedicated scraping tools like Scrapy. There are quite a few tools available.
Then the 'obvious' question: do you really need to have arrays that large ? What you are trying to achieve is not clear, I am assuming you will want to store the extracted links to a database or something. Isn't it possible to split the process in small batches ?
One thing that should help is to allocate sufficient memory by declaring a fixed-size array ie:
var theArray = new Array(1000);
Resizing the array constantly is bound to cause performance issues. Every time new items are added to the array, expensive memory allocation operations must take place in the background, and are repeated as the loop is being run.
Since you are not showing any code, so we cannot suggest meaningful improvements, just generalities.

Listen for click / hover on individual axis labels

I'm looking for a way to change the value (or format) for an individual series label when hovering it in anycharts.
Currently I'm only able to access the entire axis and I can find no getter method for individual labels so as to attach a listener.
xAxis.labels().listen('mouseOver', function(e) {
console.log(this, e.target);
});
This jsfiddle is as far as I got (see console log), this as well as the event.target reference the entire axis but not the label:
https://jsfiddle.net/robstarbuck/pbhd4b7L/9/
Indeed, there was a little bug with cache and format() function, our dev team made the fix, so please check the working sample:
var labelIndex = e.labelIndex;
var label = this.getLabel(labelIndex);
var value = xAxis.scale().ticks().get()[labelIndex];
label.format(value * 2);
https://jsfiddle.net/pbhd4b7L/13/ – it also shows how to work with tick values:
Currently it takes the js from branch, but this fix will be included in the upcoming release – 7.14.0 version (ETA: May 2017)
Our API is a little bit complicated here, but we're working hard to improve it. Does this what you're looking for?
var labelIndex = e.labelIndex;
var label = this.getLabel(labelIndex);
label.fontColor('red');
label.draw();
https://jsfiddle.net/pbhd4b7L/10/
This issue was fixed in the 7.14.0 release, use this code:
xAxis.labels().listen('mouseOver', function(e) {
var labelIndex = e.labelIndex;
var label = this.getLabel(labelIndex);
var value = xAxis.scale().ticks().get()[labelIndex];
label.format(value * 2);
label.fontColor('red');
label.draw();
});
with the latest version: https://jsfiddle.net/2t08ahkg/3/

Coffeescript Array Indexing

If I have an array of photos in coffeescript
photos = [ly.p1, ly.p2, ly.p3, ly.p4, ly.p5, ly.p6, ly.p7, ly.p8, ly.p9, ly.p10, ly.p11, ly.p12]
for photo, i in photos
photoMask = new Layer
How can I write my for loop so that the resulting photoMask objects are outputted as photoMask1, photoMask2, photoMask3 .. photoMask12 ?
EDIT: Further elaboration
Maybe the best way to explain this is what I am trying to do in psuedocode:
for photo, i in photos
photoMask[i] = new Layer
photoMask[i].addSubLayer(photo)
So ly.p1 would have a corresponding photoMask1. That way, I can access photoMask1 separately and independently.
While I agree to the commenters about this being a bit strange, you could use something like this:
photos = [ly.p1, ly.p2, ly.p3, ly.p4, ly.p5, ly.p6, ly.p7, ly.p8, ly.p9, ly.p10, ly.p11, ly.p12]
masks = {}
for photo, i in photos
photoMask = new Layer
masks["photoMask#{i}"] = photoMask
This will create dynamic keynames within the masks object. If you really need them globally (in the browser) you could do the same thing with the window object.
But without knowing what exactly you're trying to do, I wouldn't recommend any of the above.

Resources