printing protovis output (programmatically) - javascript

I'm pondering switching to protovis for visualizations. One thing that keeps me skeptical however - since protovis creates its output as a div in a browser, I wonder if there is any at least semi-automatic way for me to create a bunch of images at once without opening each one and pressing "print" manually.
So the question would be:
do you think I can use a browserless JS engine like V8 to execute the code and print the result?
can I automate opening and printing within a browser?
is there another way to get automated images from protovis?
Thanks,
Nicolas

Have a look at this Google Groups thread about this very topic.

Check out http://www.phantomjs.org/
It is a headless browser.
It can do exactly what you want :
http://code.google.com/p/phantomjs/wiki/QuickStart#Rendering
rasterize.js:
if (phantom.state.length === 0) {
if (phantom.args.length !== 2) {
console.log('Usage: rasterize.js URL filename');
phantom.exit();
} else {
var address = phantom.args[0];
phantom.state = 'rasterize';
phantom.viewportSize = { width: 600, height: 600 };
phantom.open(address);
}
} else {
var output = phantom.args[1];
phantom.sleep(200);
phantom.render(output);
phantom.exit();
}
An example to produce the rendering of the famous Tiger (from SVG):
phantomjs rasterize.js http://ariya.github.com/svg/tiger.svg tiger.png

Related

Modern or Non-deprecated way to detect flash player with js/jquery?

First of all, sorry for ressurrecting this question here.
I've been trying for two days how to reach this job using javascript/jquery and i think i've read all stack overflow and other blogs posts about that, so please, don't mark it as duplicated because I can't use out-dated scripts from 2012 now in 2017.
I've a single page that redirects to a third party e-learning platform where some content needs flash to work. Many users don't care about which software is installed on their machines (what a new, huh) so i need to detect it and show the tipical message "please install/update flash player clicking here", but i cannot find a "modern" script/way to do this, in any place, simplified, if possible.
All scripts i've tried are deprecated or returns false in all browsers, even i've newest version of flash installed and active.
Anny help will be appreciated (except links to older posts or scripts that don't work nowadays, obviously).
Thanks a lot!
There is a simple way to check for Flash since all the installed and enabled plugins will be listed in navigator.plugins;
Note that if a plugin is installed, but not enabled, it will not be detected in the navigator.plugins array. There is NO way to detect this using Javascript (this Question which confirms the same).
Having said that, use the following function isFlashEnabled(); to detect Flash :
<html>
<script>
if(isFlashEnabled())
{ document.write('Flash is installed (but may need to be enabled)'); }
else { document.write('Flash is either not installed or disabled'); }
function isFlashEnabled()
{
var flash = navigator.plugins.namedItem('Shockwave Flash');
if (!flash) { return 0; }
else { return 1; }
}
</script>
<body> <embed src="https://www.w3schools.com/tags/helloworld.swf"> </body>
</html>
You can get an array which contains all installed plugins of a browser like this:
var plugins = navigator.plugins;
Then you can then check if the array contains the flash plugin.
From https://developer.mozilla.org/de/docs/Web/API/NavigatorPlugins/plugins:
function getFlashVersion() {
var flash = navigator.plugins.namedItem('Shockwave Flash');
if (typeof flash != 'object') {
// flash is not present
return undefined;
}
if(flash.version){
return flash.version;
} else {
//No version property (e.g. in Chrome)
return flash.description.replace(/Shockwave Flash /,"");
}
}

Phantomjs: take screenshot of the current page?

I'm trying to use Phantomjs to capture a screenshot from the same page that the user is on.
For example, A user is on my-page.html and has made some changes to the elements of this page, now I need to take a screenshot of an element (DIV) inside this page (my-page.html) and save it.
I found a few examples of Phantomjs and php which I tested and worked on my server and it stores the image on my server too BUT all of the examples I found are for taking screenshots of external pages/URLs and not the 'current page'.
This is fairly a straight forward process in Html2canvas but the quality of the produced image is not good at all so I decided to use Phantomjs to produce higher quality screenshots AND also it allows me to zoom in on the page.
Here is a simple example of using Phantomjs for taking screenshot of External URL's:
var system = require("system");
if (system.args.length > 0) {
var page = require('webpage').create();
page.open(system.args[1], function() {
//viewportSize being the actual size of the headless browser
page.viewportSize = { width: 3000, height: 3000 };
//the clipRect is the portion of the page you are taking a screenshot of
page.clipRect = { top: 0, left: 0, width: 3000, height: 3000 };
page.zoomFactor = 300.0/72.0;
var pageTitle = system.args[1].replace(/http.*\/\//g, "").replace("www.", "").split("/")[0]
var filePath = "img/" + pageTitle + '.png';
page.render(filePath);
console.log(filePath);
phantom.exit();
});
}
Could someone please let me know if this is possible at all?
EDIT (Answer to my own question),
it turns out that you cannot take a screenshot of the current page if the page's elements have been edited by the user on the live basis. the only screenshots you can take with phantomjs is a bare bone of the page.
Reason: phantomjs is a headless browser and uses QtWebKit which runs on the server and it is not a javascript library same as html2canvas.
Explained and experienced by others HERE:
Another use case that is an issue for a project I’m working on is that you need drag and drop. Headless drivers have some basic functionality, but if you need to be able to set precise coordinates you’re stuck with Selenium.
For taking screenshot of current page you must pass the correct URL to Phantom script
Syntax :
phantomjs <"Phantom code url(as in documentation report.js)"> <"page url of which you want to take scrrenshot"> <"result saving url">
Now assuming you are passing correct URL :
In my case I was unable to take screenshot of my page as there was a spring security annotation to it, so it was not letting me to proceed so Please check for any security you added to your page if yes then remove it and then try again.
If case 1 does not apply to you surely there is an problem with URL you are passing please double check it.
Please let me know if problem still persist please post any errors(if occurring) you are getting.

Acrobat's "This file is already open" message

This is a really strange one. Our company has has an InDesign script that, near the end, calls Acrobat (by way of Applescript) to open a PDF file, replace a page in it, then save the file and close it. We've been using this script for over a year and a half now with no issues on 8 of the 9 computers we have. That last one, however, is giving me an odd message when it tries to open and save the file.
To be clear, all 9 computers are Macs, all running OS X 10.9.5 Mavericks. The script is on a central server, so they're all using the same file:
var unlockCover2014 = app.trustedFunction(function (fName, fPrefix)
{
app.beginPriv();
var folderPrefix = fName.match(/^.*?(?=JOBS)/);
console.println("fName is " + fName);
console.println("folderPrefix is " + folderPrefix);
var myDoc = app.openDoc(folderPrefix + "Product Templates/ProofCoverNew/proof_cover_2014.pdf");
myDoc.replacePages(0, fName, 0, 0);
myDoc.saveAs(fName);
myDoc.closeDoc(true);
app.endPriv();
});
This file is stored in the correct folder to be a Folder-level script. 8 of the computers work through this without any trouble whatsoever. The 9th, however, puts this into Acrobat's Javascript console:
fName is /ArtDept/ArtDept/JOBS/425000-425999/425000 Folder/425000_cover.pdf
folderPrefix is /ArtDept/ArtDept/
RaiseError: This file is already open.
Doc.saveAs:9:
===> This file is already open.
I do not understand why this computer, alone, thinks that the PDF files are open already. The problem that arises from this is that, when the main InDesign script is done running, two documents are still open in Acrobat, and the one it's supposed to save does not get saved.
Any ideas about what's going on here?
I did finally discover what the problem was. I feel a bit silly about how (almost) obvious it is, but perhaps it might help others in my situation.
I disabled the line in the main InDesign script that was calling Acrobat, figuring I'd come back to that problem later after I dealt with some other issues. When I did so and ran the main script again, I discovered that Acrobat does, in fact, already open up a copy of that cover sheet PDF sometime during the execution of the main script! I was shocked, at first, but then I did a headdesk when I quickly realized the cause:
InDesign on this computer is set, by default, to automatically open a PDF after exporting it.
So, I just added a short line to the part of my code that sets the PDF Export Preferences to turn that feature off:
with (app.pdfExportPreferences)
{
pageRange = proofRange;
if (multiColor) pageRange = colorTable.toString();
useSecurity = true;
disallowChanging = true;
disallowCopying = false;
disallowDocumentAssembly = true;
disallowExtractionForAccessibility = false;
disallowFormFillIn = true;
disallowHiResPrinting = false;
disallowNotes = true;
disallowPlaintextMetadata = true;
disallowPrinting = false;
changeSecurityPassword = "(NOPE)";
viewPDF = false;
}
It's the viewPDF line at the end. (Sorry, I don't think I can highlight it with markdown.) I do feel silly that I overlooked such a semi-obvious cause, but I hope this might help someone else who is experiencing a similar issue. Thanks for trying to help anyway, #Loic.
Is it possible that the Acrobat script is ran while InDesign has not totally ended writing the PDF File if this is what we are talking about ? Or maybe there are some network latencies that make the file not reachable for the moment.
I would advice using a delay to (in)validate that theory.
delay 3
On another end, why do you need to replace file. I mean can't this be thought in InDesign Scripting Scope only ? Just curious.

Powershell Scroll down a webpage / Powershell Screenshot

How to open a webpage in powershell and scroll down.
Actually I am making a script which will do a network report on its own and give me a screenshot which I want. I can open the webpage and start the test with my script, but I want my script to scroll down so that the correct screenshot could be taken. Please Help.
To be precise, I want my script to open a website called testmy.net and do a network report. I want to take the screenshot of just the report and crop everything else. I would really appreciate any help.
Q) How do I scroll down a webpage in PS? I open the website and I want to scroll down?
Q) How do I take a screenshot of only a particular thing?
(After some research I got some part which could take a screenshot of the whole desktop)
I have attached the screenshot of exact thing I need.
Script Starts Here:
$ie = new-object -comobject InternetExplorer.Application -property `
#{navigate2="http://testmy.net/SmarTest/combinedAuto"; visible = $true}
# Wait for the page to finish loading
$ie.fullscreen = $true
do {sleep 5} until (-not ($ie.Busy))
# Take A ScreenShot (Script taken from Stackflow)
[Reflection.Assembly]::LoadWithPartialName("System.Drawing")
function screenshot([Drawing.Rectangle]$bounds, $path) {
$bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
$graphics = [Drawing.Graphics]::FromImage($bmp)
$graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
$bmp.Save($path)
$graphics.Dispose()
$bmp.Dispose()
}
$bounds = [Drawing.Rectangle]::FromLTRB(0, 0, 1000, 900)
screenshot $bounds "C:\screenshot.png"
I think you're looking for really quick and dirty. If that's true, and you don't mind ugly, try using SendKeys.
$ie = new-object -comobject InternetExplorer.Application -property `
#{navigate2="http://testmy.net/SmarTest/combinedAuto"; visible = $true}
# Wait for the page to finish loading
$ie.fullscreen = $true
do {sleep 5} until (-not ($ie.Busy))
[System.Windows.Forms.Cursor]::Position = New-Object system.drawing.point(700,700)
[System.Windows.Forms.SendKeys]::SendWait({DOWN 10})
# Take A ScreenShot (Script taken from Stackflow)
[Reflection.Assembly]::LoadWithPartialName("System.Drawing")
function screenshot([Drawing.Rectangle]$bounds, $path) {
$bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
$graphics = [Drawing.Graphics]::FromImage($bmp)
$graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
$bmp.Save($path)
$graphics.Dispose()
$bmp.Dispose()
}
$bounds = [Drawing.Rectangle]::FromLTRB(0, 0, 1000, 900)
screenshot $bounds "C:\tmp\screenshot.png"
Keep messing around with the number of down arrows you send until it's right -- so edit {DOWN 10}.
NOTE: Chirishman says that you need to have two squiggle brackets around DOWN 10 -- {{DOWN 10}}. The version above almost certainly worked verbatim on my box at the time of writing, but ymmv.
Scared you're going to have enough timing issues that you eventually go back and use another tool, however. How many of these do you have to take?
Note that I did change the URL to espn.com while testing. Not sure what's going on at yours -- a speed test? Seemed to load about three different pages.
The COM object actually has a scroll control
$HWND = ($objIE = New-Object -ComObject InternetExplorer.Application).HWND
[int]$targetHorizontalScroll = 0
[int]$targetVerticalScroll = 100
[string]$uri = "https://www.test.com"
$objIE.Navigate($uri)
[sfw]::SetForegroundWindow($HWND) | Out-Null
#Omit the next line if running as administrator. Else, see below comment for a link
$objIE = ConnectIExplorer -HWND $HWND
$objIE.Document.parentWindow.scroll($targetHorizontalScroll,$targetVerticalScroll)
This is a much more controlled and repeatable method than sendkeys. When using SendKeys the amount of pixels which you scroll is dependent on the window size, where in this code you scroll an absolute number of pixels, regardless of window size.
My code also uses the ConnectIExplorer function from the answer here:
PowerShell IE9 ComObject has all null properties after navigating to webpage
Which fixes an issue with Protected Mode interfering with scripting of IE Com objects when the script is to be run without elevated permissions.
For convenience, that function by user #bnu is also reproduced here:
function ConnectIExplorer() {
param($HWND)
$objShellApp = New-Object -ComObject Shell.Application
try {
$EA = $ErrorActionPreference; $ErrorActionPreference = 'Stop'
$objNewIE = $objShellApp.Windows() | ?{$_.HWND -eq $HWND}
$objNewIE.Visible = $true
} catch {
#it may happen, that the Shell.Application does not find the window in a timely-manner, therefore quick-sleep and try again
Write-Host "Waiting for page to be loaded ..."
Start-Sleep -Milliseconds 500
try {
$objNewIE = $objShellApp.Windows() | ?{$_.HWND -eq $HWND}
$objNewIE.Visible = $true
} catch {
Write-Host "Could not retreive the -com Object InternetExplorer. Aborting." -ForegroundColor Red
$objNewIE = $null
}
} finally {
$ErrorActionPreference = $EA
$objShellApp = $null
}
return $objNewIE
}
Also it is worth noting that #ruffin's answer contains an error. As written it will type "DOWN 10" instead of sending the down arrow ten times (and accidentally scroll down slightly because it includes a spacebar press). This can be fixed with a second set of curly brackets like so:
[System.Windows.Forms.SendKeys]::SendWait({{DOWN 10}})

Platform-Independent JS->Native Bridge?

I'm currently working on an app that aggressively uses webviews on both iOS and Android to render content, with native chrome surrounding it. I want to be able to control this chrome via javascript methods.
Android Webview has addJavascriptInterface which allows this to happen, but iOS does not have this facility. I've already checked out the SO answer at iOS JavaScript bridge, and this has usefuleinformation, but It's iOS-only; optimally the same underlying web code could power the callbacks on both Andorid and iOS devices.
I'm wondering if something like PhoneGap or Appcelerator provides a way to do this simply; however I don't need their core product (providing a native experience via underlying html/css/js) and I dont even know if what I need is included in their package.
Thanks for any info!
I would say that the best way would be to do it yourself, combining those two examples:
function nativeDoStuff() {
if (androidbridge != null {
androidbridge.doStuff();
}
else {
//construct url
window.location = "myiphonescheme://dostuff";
}
come to think of it, if you're feeling ambitious you could code up a quick javascript object to do it for you:
function NativeAppBridge () {
function runMethod(methodName, params) {
if (androidbridge != null {
// If the android bridge and the method you're trying to call exists,
// we'll just call the method directly:
if (androidbridge[methodName] != null) {
androidbridge[methodName].apply(this, params);
}
}
else {
// building the url is more complicated; best I can think
// of is something like this:
var url = "myiphonescheme://" + methodName;
if (params.length > 0) {
url += "?"
var i = 0;
for (param in params) {
url += "param" + i + "=" + param;
++i;
if (i < params.length) {
url += "&";
}
}
}
}
}
}
Using it would then be as simple as:
var bridge = new NativeAppBridge();
function onClick() {
bridge.runMethod("doStuff", null);
}
Be aware that I coded this off the top of my head and don't have time to test, at the moment - but I think it should work well enough, provided I didn't make any major mistakes
You can try the XWebView project if you plan to use WKWebView
You can use phonegap plugins to do it. They provide an excelent way to communicate between their webview and your native layer.
Here you can see how to create one!
And my personal opinion on the subject: I've been using phonegap for a while and if you are on webviews, I strongly suggest you to rethink the way you're doing stuff and move to a mobile web platform. You probably can save a lot of time.
The way I see it, the great disadvantage on using this is you are creating a webpage instead of a mobile app. You cant use native components and your app gets less responsive. As you are already on webviews, I believe you can only find benefits on these platforms.

Categories

Resources