PhantomJS / CasperJS Canvas selector - html

Using PhantomJS V 1.8.1
Thanks in advance.
I am trying to run some tests on a website that I am developing which is using backbone.js.
One of my tests involve checking to see if a Canvas is present and clicking on it. My problem is that whatever selector I use to get the Canvas Element I cannot get the selector to find it. I use the same CSS selector in Google Chrome when viewing the page and all is OK. At first I thought that the issue may have been due to the element not being present on the page but other elements which are inserted with the canvas are present so I am 99% sure that this is not the problem.
The selectors I have tried to use are:
document.querySelectorAll('#idOfCanvas');
document.querySelectorAll('canvas#idOfCanvas');
Also if I use .classClassName:nth(1) to select the tyre selector, it still fails to work (works in Google Chrome though as does the other examples provided)
The canvas has a class name which is picked up by the selector by I would rather not use a class selector.
Any help would be much appreciated.
Cheers :)
Also
Like I mentioned I am almost certain that the Canvas exists as the container div for it exists. Also I have four elements on the page with the same className (two of which are canvases) and four elements are being returned when I run
return document.querySelectorAll('.className').length = 4;

Assuming you have something like this:
<canvas id="idOfCanvas"></canvas>
This should work:
canvas = document.getElementById("idOfCanvas");
// or
canvas = document.querySelector("#idOfCanvas"); // Only get the first match, ID's should be unique, any way.;
// or
canvas = document.querySelectorAll("#idOfCanvas")[0];
// or
canvas = document.getElementsByTagName("canvas")[0]; // Get the first <canvas> element.
However, you'll have to make sure your canvas element is actually loaded when the script is executed. Have a look at this onload tutorial, for example.

Try this :
canvas = document.getElementById(#IdOfCanvas:nth-child(1));

Related

Downloading a dynamically generated SVG file from the browser

If I create an image using HTML SVG element, can I then offer this as an SVG file download to the user. For example I may want to load an SVG image, apply some basic transformations to it, add some text, then let the user download the result as a vector image.
Is that possible? I have been doing something similar with Canvas but have been struggling creating a vector image. I wasn't aware that SVG elements were so versatile when I cam across them this morning but if I can do the above it would be great.
Simple solution using a data URI:
var svg_root = document.getElementById('your_svg_root_element_here');
var svg_source = svg_root.outerHTML;
var svg_data_uri = 'data:image/svg+xml;base64,' + btoa(svg_source);
var link = document.getElementById('anchor_element');
link.setAttribute('href', svg_data_uri);
Although it worked, when clicking on the link, the browser stalled for a few seconds.
This seems to be the simplest solution and should be compatible with all modern browsers. However, it has some noticeable overhead. If someone else knows a different solution (maybe using blobs or something similar), please add here as another answer!

Example of Click Map is not working for me

Sorry by this dummy question! :D
I´m trying to make a clickable map with html5 canvas element, I find this good example: http://www.rubydesigner.com/blog/click-map-using-html5-canvas
But when a download it (CTRL+S) from Chrome it doesnt work. It download the html page and files folder with the JS a images, I checked the path to the images, but still the map doesnt appear. What is the problem?
UPDATE
Initial assumption about CORS turns out to not be the case here.
The code seemed to work in Chrome and although CORS typically is the cause when downloading files and using canvas with local (file://) file references. As localhost is used here via XAMMP this won't be the cause and it turns out there are more than one bugs in the online code.
Specifically the way it calculates the coordinates for the mouse:
var datapos = ((e.offsetY-2) * 300 * 4) + ((e.offsetX-1) * 4);
This will result in a NaN value due to offsetX/Y which of course cannot be used for any index.
The more appropriate way is something like this, here also compensating for canvas offset:
var rect = map_wrapper.getBoundingClientRect();
var datapos = ((e.clientY - (rect.top |0)) * 300 * 4) +
((e.clientX - (rect.left|0)) * 4);
However, I have never came across a floating point position for an element which seem to be case here (rect.top shows a float value in my browser, another little surprise) and therefor I am forcing the value to integer here (normally not necessarily.. I didn't dig deep into this). As debugging the whole code is a bit out of the scope here I will leave it with that and to OP to locate other bugs.
Correcting the position will at least give a usable index for the pixel array which in turn will return a valid (not necessarily correct it turns out, which leave checking of image, tolerane in case gamma/color correction is applied....) value for the red component (still issues when testing but as said, it's a bit out of the scope to do a full debug and correction).
Hopefully this can lead you to where the other errors are. I did not go through the html etc.

html div nesting? using google fetchurl

I'm trying to grab a table from the following webpage
http://www.bloomberg.com/markets/companies/country/hong-kong/
I have some sample code which was kindly provided by Phil Bozak here:
grabbing table from html using Google script
which grabs the table for this website:
http://www.airchina.com.cn/www/en/html/index/ir/traffic/
As you can see from Phil's code, there is alot of "getElement()" in the code. If i look at the html code for the Air China website. It looks like it's nested four times? that's why the string of .getElement?
Now I look at the source code for the Bloomberg page and its is load with "div"...
the question is can someone show me how to grab the table from this the Bloomberg page?
and just a brief explanation of the theory also would be useful. Thanks a bunch.
Let's flip your question upside down, and start with the theory. Methodology might be a better word for it.
You want to get at something specific in a structured page. To do that, you either need a way to zap right to the element (which can be done if it's labeled in a unique way that we can access), OR you need to navigate the structure more-or-less manually. You already know how to look at the source of a page, so you're familiar with this step. Here's a screenshot of Firefox Inspector, highlighting the element we're interested in.
We can see the hierarchy of elements that lead to the table: html, body, div, div, div.ticker, table.ticker_data. We can also see the source:
<table class="ticker_data">
Neat! It's labeled! Unfortunately, that class info gets dropped when we process the HTML in our script. Bummer. If it was id="ticker_data" instead, we could use the getElementByVal() utility from this answer to reach it, and give ourselves some immunity from future restructuring of the page. Put a pin in that - we'll come back to it.
It can help to visualize this in the debugger. Here's a utility script for that - run it in debug mode, and you'll have your HTML document laid out to explore:
/**
* Debug-run this in the editor to be able to explore the structure of web pages.
*
* Set target to the page you're interested in.
*/
function pageExplorer() {
var target = "http://www.bloomberg.com/markets/companies/country/hong-kong/";
var pageTxt = UrlFetchApp.fetch(target).getContentText();
var pageDoc = Xml.parse(pageTxt,true);
debugger; // Pause in debugger - explore pageDoc
}
This is what our page looks like in the debugger:
You might be wondering what the numbered elements are, since you don't see them in the source. When there are multiples of an element type at the same level in an XML document, the parser presents them as an array, numbered 0..n. Thus, when we see 0 under a div in the debugger, that's telling us that there are multiple <div> tags in the HTML source at that level, and we can access them as an array, for example .div[0].
Ok, theory behind us, let's go ahead and see how we can access the table by brute-force.
Knowing the hierarchy, including the div arrays shown in the debugger, we could do this, ala Phil's previous answer. I'll do some weird indenting to illustrate the document structure:
...
var target = "http://www.bloomberg.com/markets/companies/country/hong-kong/";
var pageTxt = UrlFetchApp.fetch(target).getContentText();
var pageDoc = Xml.parse(pageTxt,true);
var table = pageDoc.getElement()
.getElement("body")
.getElements("div")[0] // 0-th div under body, shown in debugger
.getElements("div")[5] // 5-th div under there
.getElement("div") // another div
.getElement("table"); // finally, our table
As a much more compact alternative to all those .getElement() calls, we can navigate using dot notation.
var table = pageDoc.getElement().body.div[0].div[5].div.table;
And that's that.
Let's go back to that pinned idea. In the debugger, we can see that there are various attributes attached to elements. In particular, there's an "id" on that div[5] that contains the div that contains the table. Remember, in the source we saw "class" attributes, but note that they don't make it this far.
Still, the fact that a kindly programmer put this "id" in place means we can do this, with getDivById() from that earlier question:
var contentDiv = getDivById( pageDoc.getElement().body, 'content' );
var table = contentDiv.div.table;
If they move things around, we might still be able to find that table, without changing our code.
You already know what to do once you have the table element, so we're done here!

Stop img tags from flickering when re-rendering with JavaScript

Our web app is built entirely in JS.
To make it snappy we cache resources (models) between page views and reload the resource when you view a page.
Our flow is like this:
The user is in ViewA
The user switches to ViewB
We use the cached resource to render ViewB
We start a fetch for resource
When the resource is fetched we render again
This has a nasty drawback of causing <img> tags to flicker, ever if they are the same.
The problem is that Backbone.js, which we use, doesn't tell us if anything changed when fetching a collection, just that it was fetched.
Here's a quick demo of what I mean: http://jsfiddle.net/p7DdG/
It only happens in webkit and with <img> tags, not with background images as you can see.
We think it's kinda ugly to use background-image instead of a proper img tag.
Is there any solution to this?
The problem is gone in Chrome 19, problem solved :)
Not knowing exactly how the URL of each image is being built I'm not certain this will work, but could you check the src attribute of each image tag against the one you are replacing it with before doing the replace?
e.g.
var newImageSrc = "http://www.google.com/intl/en_com/images/srpr/logo3w.png";
if (newImageSrc != $("img").attr("src")) {
$('img').replaceWith('<img src="'+newImageSrc +'">');
}
Alternatively - load the image offscreen, and attach an event handler to the onload event of the image, which moves the image to the current image's parent tag, and remove the old one.
e.g.
var oldImage = $("#oldImageId");
var newImageSrc = "http://www.google.com/intl/en_com/images/srpr/logo3w.png";
var newImage = new Image();
$(newImage).load(function (event) {
$(oldImage).parent().append(newImage);
$(oldImage).detach();
});
$(newImage).attr("src", newImageSrc);
I ran into the same problem and noticed that sometimes images do flicker and sometimes don't. Even in latest Chrome (v33 as of now).
For posterity, flickering happens with uncached images.
In my case, Cache-Control: public, max-age=31536000 totally eliminated it.

Get Flex app's position on a web page?

Is it possible to get the x,y coordinates of a Flex app within an HTML page? I know you can use ExternalInterface.ObjecID to get the "id attribute of the object tag in Internet Explorer, or the name attribute of the embed tag in Netscape" but I can't seem to get past that step. It seems like it should be possible to get a handle on that embed object. Any suggestions?
Thanks.
I think the easiest thing to do is to include some kind of JavaScript library on the HTML page, say jQuery, and use it's functions for determining the position and size of DOM nodes. I would do it more or less like this:
var jsCode : String = "function( id ) { return $('#' + id).offset(); }";
var offset : Object = ExternalInterface.call(jsCode, ExternalObject.objectID);
trace(offset.left, offset.top);
Notice that this is ActionScript code, but it runs JavaScript code through ExternalInterface. It uses jQuery and in particular its offset method that returns the left and top offset of a DOM node.
You could do without jQuery if you looked at how the offset method is implemented and included that code in place of the call to jQuery. That way you wouldn't need to load jQuery in the HTML and the Flex app would be self-contained. The reason I suggest to use a library like jQuery is that browsers do these things differently. I'm not sure if calculating offsets is very different from browser to browser, but it doesn't hurt to be insulated from browser differences.
The JavaScript in my example is an anonymous function so that the ID of the embed/object tag can be passed in to it as a parameter to ExternalInterface.call, but you could just use string concatenation if you want:
var jsCode : String = "$('#' +" + ExternalInterface.objectID + ").offset()";
var offset : Object = ExternalInterface.call(jsCode);
That would work too, I just think the first version is more elegant.
If you are trying just to measure where it's at within a page as the external user the only thing that pops into my mind is a Firefox extension called MeasureIt I've used it occasionally for various measuring on web pages.
Are you trying to do this programmatically from within the embedded page itself and if so which langauge?