PhantomJS: setContent not working when HTML has assets - html

This script works:
var page = require('webpage').create();
var html = '<h1>Test</h1><img>'; //works with page.setContent and page.content
//var html = '<h1>Test</h1><img src=".">'; //only works with page.content
page.setContent(html, 'http://github.com');
//page.content = html;
page.render('test.png');
phantom.exit();
but adding a src attribute to the img makes it fail silently (page.render returns false and no image is generated).
Setting page.content directly works in both cases but then relative URLs don't. The same thing happens with other tags that load a resource such as link. It doesn't matter whether the linked resource exists or not. Tested in 1.8.1 and 1.9.2.
Is this a bug or have I misunderstood the API?

You can not render webpage if it is not fully loaded.
When you are setting link or src to <img>, It will try to load image asynchronously.
So, it requires to wait for loading finished.
Try following code.
page.onLoadFinished = function(status) {
page.render('test.png');
phantom.exit();
};
page.setContent(html, 'http://github.com');

Related

HTML <a> Link href Doesn't Work with "Embedded Spaces" in a "Relative Path"

I have searched everywhere I can think of and can't find a single example of an "a" href which contains a relative path on localhost with embedded spaces.
I am trying to download a json file from my localhost located at "json/test file.json". If I rename the file to "json/test-file.json" then the link works fine. I have hundreds of json files and renaming them will break other applications.
I have also tried putting quotes around 'json/test file.json' and that does not work either.
Here is a simple tag that demonstrates the problem
<a id="download_json" href="json/test%20file.json" title="Download JSON" target="new" download>Download</a>
I have already tried encodeURI but that is a waste of time. If you can just hard code the path/file as shown above for testing with nothing fancy it would be helpful and avoid distractions.
This problem must have a very simple solution, I just can't seem to put my finger on it.
Any ideas will be deeply appreciated, Thank you for your time.
Finally found the answer. Problem only with Firefox Developers Edition
function downloadJSON(filename, dataObjToWrite){
const blob = new Blob([JSON.stringify(dataObjToWrite)], { type: "text/json" });
const link = document.createElement("a");
link.download = filename;
link.href = window.URL.createObjectURL(blob);
link.dataset.downloadurl = ["text/json", link.download, link.href].join(":");
const evt = new MouseEvent("click", {
view: window,
bubbles: true,
cancelable: true,
});
link.dispatchEvent(evt);
link.remove()
};

Chrome Extension local .gif not displaying

I am writing a chrome extension and injecting an image into the page. When I do this in my content script:
var loading_img = document.createElement('img');
var imgURL = chrome.extension.getURL("images/icon.png");
loading_img.src = imgURL;
document.body.appendChild(loading_img);
and I see my image as expected.
However, when I try to load a .gif image. Then the image doesn't load:
var loading_img = document.createElement('img');
var imgURL = chrome.extension.getURL("images/loading.gif");
loading_img.src = imgURL;
document.body.appendChild(loading_img);
I get a one of these:
However, if I inspect element and grab the src of the image element, chrome-extension://ofdomghnlpcpemcbmidihnbmojhnkhhf/images/loading.gif, and paste it into my browser window, then I can see the image just fine. Am I doing something wrong?
First, chrome.extension.getURL has been deprecated since Chrome 58, use chrome.runtime.getURL instead.
And second, you need to add your gif to web_accessible_resources inside your manifest.json like so:
"web_accessible_resources": ["images/loading.gif"],

Loading test image into canvas

I'm trying to test an AngularJS service that gets handed the ImageData from a canvas, does some pattern recognition, and returns the recognized patterns. I would like to write a unit test (not an E2E test), to build the service step by step. I fail to properly load a test-png image that I can draw onto a canvas, from which I then can extract the ImageData.
I would like to learn the proper way to solve my problem: Getting the ImageData object for a test-image in a unit test. What I am currently doing, using Karma, Jasmine 2, PhantomJS:
it('simple pattern', function (done) {
var canvas = angular.element('<canvas></canvas>')
var context = canvas[0].getContext("2d")
var src = 'test/images/3x3-bw-1star.png' // Not found by PhantomJS
var src2 = "app/images/yeoman.png" // Found.
var image = angular.element('<img src="' + src + '"/>')
image.onerror = function() { // Not called.
fail("Could not load image.")
done()
}
image.onload = function() { // Not called.
context.drawImage(image[0], 0, 0)
var imageData = context.getImageData(0, 0, image.width, image.height)
expect(starFinder.findStars(imageData)).toEqual(true)
done()
}
}
Problems with this code:
PhantomJS fails to load the test-image at src (404). The production image at src2 is correctly loaded. The path is correct, and I don't see any restriction to the "app" directory anywhere.
onload is never called. Probably, the event handler is attached to late, so when the angular.element call returns, the image is loaded already.
If I call onload manually, the context is undefined.
After #MarcoCI's (correct) suggestion, I thought I was seriously working on the wrong abstraction layer. Thus, I searched for a suitable image manipulation library, and stumbled upon Caman. I then refactored the service to accept a caman object. In the test, I create a Caman object using a canvas and the image URL. Which feels correct for what I want to do: Get an image and have it analyzed.
The 404 error for the test images can be resolved by adding the image to the list of files as served-but-not-included:
{pattern: 'test/images/*.png', watched: true, served: true, included: false}
and then setting the urlRoot.
urlRoot: 'base'
The loading and event handling is done by Caman.

How to embed MediaWiki page content into my site?

Our corporate wiki is Mediawiki. I have no problem to put iframe into my site to refer for some article on wiki.
But my own site have a lot of widgets and own style. I don't want to include Mediawiki navigation/search/login widgets, logo image.
Is it possible and how to get Mediawiki page contents without widgets (only article body)?
Yes, it is. You'll probably want to use the action=render url parameter, for example: http://en.wikipedia.org/w/index.php?action=render&title=Main_Page. Note that the stylesheets from the wiki aren't included, so you'll need to copy the relevant rules to your site's css files. See also this.
Thank waldir for answer!
After asking question I perform own research and end with code:
window.onload = function() {
httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState !== 4) {
console.log("Not ready, code: %o", httpRequest.readyState);
return;
}
if (httpRequest.status !== 200) {
console.log("Server error: %o", httpRequest.status);
return;
}
var json = JSON.parse(httpRequest.responseText);
console.log("json: %o", json);
var wiki = json.query.pages["1"].revisions[0]["*"];
console.log("wiki: %o", wiki);
var html = InstaView.convert(wiki);
console.log("html: %o", html);
document.getElementById('area').innerHTML = html;
};
var url = 'https://wiki.evil-company.com/api.php?action=query&prop=revisions&format=json&titles=Main_page&rvprop=timestamp|user|comment|content';
httpRequest.open('GET', url, true);
httpRequest.send(null);
}
Here I use https://github.com/cscott/instaview/blob/master/main.js project which is enhanced http://en.wikipedia.org/wiki/User:Pilaf to transform json output to HTML on browser side.
The reason for this code because our wiki is old or misconfigured and action=render is not available. But I trap into cross-domain scripting issue so I think that iframe with action=render is better solution.
See also How do you grab an article including the links in a usable format?
Another suggestion to use action=parse (http://en.wikipedia.org/w/api.php?action=parse&title=Linux) lead to warning:
You are looking at the HTML representation of the XML format.
HTML is good for debugging, but is unsuitable for application use.
Specify the format parameter to change the output format.
UPDATE
Perfect solution just append query action=render to any valid wiki URL like:
http://en.wikipedia.org/wiki/Linux?action=render

Google Chrome - download attribute of anchor tags

I've an extension which saves some files to the downloads folder. The code below is just for testing
//This lies in the background page of my extension
function fileTest(name) {
var a = document.createElement('a');
a.href = 'data:text/plain;base64,SGVsbG8gV29ybGQh'; //Hello World!
a.download = name + '.txt';
a.onclick = function (e) {console.log('[TEST] ' + name);return true;};
a.click();
}
window.onload = function() {
fileTest('test1');
fileTest('test12');
fileTest('test123');
}
only the first file "test1.txt" is saved to the disk, although the output of the console shows that there was 3 clicks
[TEST] test1
[TEST] test12
[TEST] test123
Is this an intentional limitation by the browser ? or there's something wrong with the code ?
When I run your code in a regular browsing session, I get a slide out notification (at the top of the window) that says
This site is attempting to download multiple files. Do you want to allow this?
So, yes, it is a security limitation of the browser to restrict downloads that are not user-initiated. You probably don't see the notification because the action is being performed by your background page.
The limitation seems to be one download per user action as demonstrated in this variant of your code:
window.onclick = function() {
fileTest('test1');
}
This will allow unlimited downloads, but only one download per click event.