How to user modernizr to detect canvas support - modernizr

All I want to do is detect Canvas support in the browser. Modernizr's "Documentation" page is a thousand lines long, but doesn't seem to be able to explain feature detection simply (its main function), and rants about polyfills instead. Anyway, this:
Modernizr.canvas
Simply returns undefined instead of true or false. How can I get Modernizr to actually tell me if this feature exists in the browser or not?

Modernizr doesn't report false when things are not supported. It only reports true if they are, simply letting the fact that unsupported properties are undefined act as falsey value.
In the Firefox I'm on, for instance, Modernizr.canvas reports true. On an old Android version, it reports undefined, which in a conditional is equivalent to false:
if (Modernizr.canvas) {
// do canvasy things
} else {
// notify users that you need canvas, and their browser won't work
}
It does this for everything: if supported, it'll be true. If not, it'll not actually a property on the Modernizr object, and so calling will make the JS engine report undefined as per the JavaScript specs.

Related

Firefox 45 XUL/XPCOM - accessing webpage JS objects and functions from browser context

I am currently developing an app using Firefox 45 as a framework, which will access and control a surveillance camera. The camera has a built-in webserver and can be accessed on the local network using the IP address. I wanted to provide extended features not currently available in the camera's UI.
I chose FF 45 as it was the oldest version available which supports the code the camera code uses. I was trying to go for the most primitive version of FF as I could as the older versions are much less bloated, and it is also easier to manipulate the browser's native code on those older versions. Ultimately I will modify Firefox to turn it into a stand-alone app for the camera.
Perhaps some of you folks who have dealt with XUL Firefox in the past either developing addons or even contributing to native code might remember enough to help me out. I have written XUL addons in the past but none which were trying to access webpage JS. It appears MDN has now removed all of its XUL documentation (for a while they were hosting it as "obsolete content", but it appears like it is no longer available.)
Herein lies my issue. I am finding that I cannot directly access JS objects/functions on the camera page from the browser context, at least not how I have attempted. I have been trying to feel my way around using Scratchpad in browser context. Here is an example:
In scratchpad within the webpage content context, I can run:
// Code run in Scratchpad in camera webpage content context.
// ViewImage is a function within the camera webpage's code.
dump(window.ViewImage + "\n");
And I get output indicating ViewImage is accessible.
However, in Browser context:
// Code run in Scratchpad in browser context:
// Webpage is loaded in gBrowser.browsers[0].
function XXXXRun() {
let win = gBrowser.browsers[0].docShell.DOMWindow.window;
dump(win.ViewImage + "\n");
}
XXXXRun();
Output indicates "undefined". However, I can access DOM objects eg,
// Code run in Scratchpad in browser context:
// Webpage is loaded in gBrowser.browsers[0].
function XXXXRun() {
let win = gBrowser.browsers[0].docShell.DOMWindow.window;
dump(win.document.getElementById("some_id_unique_to_the_camera_page") + "\n");
}
XXXXRun();
Indicates the presence of an element with that ID.
It would seem to me that gBrowser.browsers[0].docShell.DOMWindow.window is equivalent to window of the page residing in gBrowser.browsers[0], but perhaps there is more to it than that. It seems I can get a reference to the webpage's window object in some capacity (eg, able to get references to DOM objects through win.document) but am restricted to a degree. I have even tried gBrowser.browsers[0].docShell.DOMWindow.window.document.defaultView to get a reference of the webpage's window object.
Here is an example of the code in the JS file downloaded from the camera:
function ViewImage() {
throw { "msg": "Don't NEW a singleton." };
}
EventListener.apply(ViewImage);
(function() {
ViewImage.refreshView = function() {
...
}
...
})();
I ultimately intend to modify the browser code rather than running an addon inside of it. I have successfully made modifications to the code already to add features to the camera UI which involve DOM manipulation. Eventually the UI will be radically altered where it will not appear like a browser at all. If someone has ever written a Firefox XUL addon which accomplishes accessing a webpage's objects, information on that would be a good start I'm sure. Or if someone knows how I can access the page's objects using Scratchpad in browser context, that would be better, as I could use the code directly.
UPDATE:
I tried implementing wrappedJSObject in my code, eg: let win = gBrowser.browsers[0].docShell.DOMWindow.window.wrappedJSObject;:
// Code run in Scratchpad in browser context:
// Webpage is loaded in gBrowser.browsers[0].
function XXXXRun() {
// Now using wrappedJSObject property:
let win = gBrowser.browsers[0].docShell.DOMWindow.window.wrappedJSObject;
// Now output indicates ViewImage is being accessed...
dump(win.ViewImage + "\n");
// ...also shows function ViewImage.sendCommand is present...
dump(win.ViewImage.sendCommand + "\n");
// ...however, running this function appears to do nothing:
win.ViewImage.sendCommand('SetImage', { "Image": {"bright":80}})
// ...yet running the same function from the webpage context in Scratchpad gives the expected behavior.
}
XXXXRun();
This seems to show I am accessing the object (prints out the function code in the console,) however, when running a function which is a property of the object from this context, the function runs, but does not pass parameters correctly :-/. If I run the same function from the webpage context, I get the expected results. I felt like I was just about there, but disappointed when the function didn't work properly :-/

What would prevent capybara/selenium from hovering over a visible element?

I am writing automation tests for a webpage. I can't share any specific details, so all I'm looking for is some general brain-storming to help me figure out what is causing the problem. A long-shot, I know, but I've become obsessed with this problem.
There is an element with id="troublesome" on the webpage. On manual testing, hovering over #troublesome will cause it to disappear and something else pops up in its place (as it should). I'm trying to verify that the pop-up occurs on hover using automation testing (Capybara, selenium driver, ruby). However, no matter what technique I use, hovering doesn't work.
troublesome is visible upon visiting the page. It is not cut off by screen size. Capybara has no trouble finding it and reading its text and attributes. i.e. A regular ol' find("#troublesome").text will return the correct text.
However, I cannot use Capybara to click on #troublesome without executing javascript.
i.e. find("#troublesome").click won't do anything (it won't throw any errors either). I must use find("#troublesome").execute_script("this.click()") to click on it.
But I don't need to click it. I just need to hover over it.
Using Capybara:
find("#troublesome").hover --> will not work. No errors thrown either. Test just continues until it fails because it fails to find the expected result. Telling ruby to sleep(however_many_seconds) doesn't help.
Using Selenium:
page.driver.browser.action.move_to(find("#troublesome").native).perform --> this doesn't work either. Again, no errors thrown.
Using trigger:
find("#troublesome").trigger(:mouseover) --> doesn't work because selenium driver doesn't support trigger (and I don't want to use another driver).
Using jquery:
Won't work. Website doesn't use jquery
Attempting to use javascript to force :hover to be true on element doesn't work:
mouseHover = 'var x = document.createEvent("MouseEvent");
x.initMouseEvent("mouseover", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
document.getElementById("troublesome").dispatchEvent(x);'
page.execute_script(mouseHover)
(I can change mouseOver to click, and it'll click though!)
Apparently, mouseover is not 'trusted' by browser (but click is), so kinda useless to have that as an option, isn't it?
I've tried all of the above by working within a within("#id") do... end block. Doesn't make a difference.
I've even tried unconventional means to get the mouse over #troublesome:
find("#troublesome").right_click --> the mouse will be DIRECTLY over #troublesome, right-click, and a menu will pop up RIGHT OVER the element!!!!!!
So CLEARLY, the mouse IS hovering over #troublesome during my automation test, yet it's not registering on the browser. The website is not bugged. Hovering works when I do it manually.
I can find other elements on the webpage and hover over them just fine. In fact, I've even tried putting the mouse over another element, then moving it from there to #troublesome like so:
page.driver.browser.action.move_to(find("#somethingElse").native, 1200, -50).perform
That doesn't work, but if I adjust the coordinates to a third element just below #somethingElse, this will trigger the third element's hover state, so clearly this strategy can work in principle and practice, yet not for #troublesome!
Note that #somethingElse and the 'third element' exist on a div that is at the same 'heirarchy' as the ancestor div of #troublesome.
There are iframes on the webpage, but #troublesome is not on the iframe.
There are random script tags inserted all over the body of the webpage. I don't know what those script tags are doing as I can't see the code.
#troublesome has become my Moby Dick.
This whale is driving me nuts. I've invested too much time into it already. I can't give up now or all those hours of toil would be for nothing.
Please help.
Thank you.
find("#troublesome").hover
page.driver.browser.action.move_to(find("#troublesome").native).perform
find("#troublesome").trigger(:mouseover)
mouseHover = 'var x = document.createEvent("MouseEvent");
x.initMouseEvent("mouseover", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
document.getElementById("myDiv").dispatchEvent(x);'
page.execute_script(mouseHover)
page.driver.browser.action.move_to(find("#somethingElse").native, 1200, -50).perform
No error messages other than standard capybara/rspec failure log because it failed to find the element that was supposed to pop up upon hovering over #troublesome
The problem you're running into is because the '.hoverme' element in your example at https://jsfiddle.net/pwo7zuL2/1/ has a size of 0x0 px (this is also why you couldn't click it). The size is 0x0 because it only contains absolute positioned elements which don't technically count when calculating the auto size of the parent. If instead of attempting to hover over the .hoverme element you hover over the visible absolute positioned child (which actually has size) of the element the hover will work correctly (which is what you are actually doing when you do it manually in your example).
find('#next').hover
I now know the problem, and I have a solution (albeit a hacky one).
The problem is due to an iframe which covers the full screen. This blocks selenium from being able to hover over #troublesome even though #troublesome is not within the iframe and #troublesome's z-index is set to a high number (thereby forcing it to be at the top layer).
Manual hovering works, but hovering with selenium fails. I believe this is a bug, so I have reported it on selenium's github.
One solution that works is to use javascript to force the iframe to shrink, then hover (which should work now), then use javascript to return the iframe to full screen (so as to not affect other aspects of the test).
shrink_frame = 'document.getElementById("#frame").setAttribute("style", "width: 100px; height 100px");'
page.execute_script(shrink_frame)
This is not an ideal solution because it is obviously not how a real user would interact with the webpage, but it's acceptable given that this is due to a selenium bug and that manual testing works.

How to support IE8 with breakpoint-sass and mobile first

I am using breakpoint-sass gem to handle media queries for mobile first responsive stylesheets.
I need to create a separate css file for IE8 (which does not support media queries), whereby I want to have all the styles, omitting the strings starting with #media ... { and the other one with closing bracket (because IE ignores everything that is in media query).
I'm using the following setup:
$breakpoint-no-queries: true;
$breakpoint-no-query-fallbacks: true;
The problem is, that to make this working I need each time to pass true into breakpoint() mixin. Is there a better way to achieve my goal? Or probably, is there any way to avoid this repetition and make $no-query: true to be permanent?
Taking a look at the No Query Fallbacks page, specifically the No Query Fallbacks | Separate Fallback File section, you can see that if you have set up your breakpoints using variables, you can add 'no-query' true' to breakpoint definitions, and then you don't need to pass it in to the Breakpoint mixin.
There is no way to tell Breakpoint that you would like all of your media queries to be output in your fallback code as we don't believe that to be a good practice; if your component has three of four breakpoints and only the last one will apply, only that one's code should be served. If you'd like to try to convince us otherwise, please file an issue for a new feature and we can discuss in the issue queue.

Why doesn't event.relatedTarget work with focusin/focusout event in Firefox?

I need to find the previously focused item in my focusin function. Here is an example code:
$('#id').on('focusin', function(event) {
//console.log(event.relatedTarget.nodeName); //doesn't work
}
I've done some research and while I've seen some people saying in posts that this only works with mouse events like mousedown etc., I've come across a few articles from reputable sources that have me believing this should work.
https://developer.mozilla.org/en-US/docs/DOM/event.relatedTarget Here Firefox specifically mentions how event.relatedTarget returns "which EventTarget is losing focus" in the 'focusin' event.
Firefox is the browser I am using for this.
http://www.w3.org/TR/DOM-Level-3-Events/#events-FocusEvent at this bookmark you can see that every FocusEvent has a readonly attribute called related target.
http://www.w3.org/TR/DOM-Level-3-Events/#event-type-focusIn Here they specifically state as well that the 'FocusEvent' has a property called 'relatedTarget' which is "event target losing focus (if any)."
So then what am I doing wrong here? It must be some kind of dumb syntax mistake or something. I cannot find the nodeName of event.relatedTarget.
Update: I can get it to work in IE using, but this won't work in Firefox???
$("#id").on('focusin', function(event) {
$('#textbox').text(event.relatedTarget.nodeName);
}
Although MDN mentions relatedTarget for the focusin /focusout events, unfortunately, no version of FireFox actually supports those two events. jQuery simply emulates them for you but due to lack of native support, you don't get relatedTarget on FF.
See compatibility info here or here.

Inspecting Firefox Components.interfaces.nsIDOMWindowUtils.screenPixelsPerCSSPixel value in Javascript Scratchpad

I am using Firefox Scratchpad to understand the scaling behavior that
results when the user types the CTRL-PLUS and CTRL-MINUS keys.
In Javascript Scratchpad, I'm evaluating a snippet of Javascript code that accesses the
Components.interfaces.nsIDOMWindowUtils.screenPixelsPerCSSPixel
property like this:
var util = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils);
util.screenPixelsPerCSSPixel
In Scratchpad typing CTRL-L after the last l in screenPixelsPerCSSPixel above results in an Exception:
Exception: The operation is insecure.
(Note that the current active Firefox tab is pointing to http://www.google.com).
The devtools.chrome.enabled flag is set to true in this
context, but that does not seem to matter as an Exception is still being thrown.
What do I need to do in order to get Javascript Scratchpad to display
that value?
This is intended only to be temporary to gain understanding during a
debug ritual. Set aside for now the obvious question of "Why is it a
security risk to show a scaling factor?". I'm only after getting at
the value from the confines of standard, and safe, Firefox controls
such as enabling/disabling about:config values that I can easily
undo later when I'm done.
Here is the answer I found:
Accessing the window variable from the Scratchpad scope whose
Environment (see its Environment menu) is set to Content yeilds one
type of object, while if Environment was set to Browser, a different
type of object is in play (CTRL-L on it in Scratch pad reports it is
of type ChromeWindow). The window.content object is the content
object relative to the ChromeWindow object.
The value of
....QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils).screenPixelsPerCSSPixel
relative to the window object (ChromeWindow) object returns
1, while calling it on the window.content shows something other
than 1 and show that scaling is involved.
(EDIT: I relocated the Javascript code that used to be here; see below.)
To demonstrate using the value, I've provided some sample Javascript in an answer to my other question at Finding top-level X Window x/y coordinates of CTRL-F text in Firefox

Resources