The note at the bottom of this Mozilla wiki page currently says: "Using canvas.drawWindow() while handling a document's onload event doesn't work. In Firefox 3.5 or later, you can do this in a handler for the MozAfterPaint event to successfully draw HTML content into a canvas on page load." Which is fine, except that I tried it in Firefox 3.6.6 and it did work, leading me to believe that perhaps it used to not work, due to some bug which has since been fixed. I'd rather not use MozAfterPaint since it won't work in versions earlier than 3.5. Is there an important reason not to use the "load" event, and if so what can I do instead that will be compatible with older versions of Firefox?
EDIT: This is how my code works. In the init() function of my extension, I call gBrowser.addEventListener("load", MyExtension.onPageLoad, true); Then MyExtension.onPageLoad is essentially:
onPageLoad : function(e) {
var win = e.originalTarget.defaultView;
// create an html:canvas, adjust its size, etc. following the example of the "TabPreview" extension
var ctx = canvas.getContext("2d");
ctx.drawWindow(win, 0, 0, w, h, "rgb(255, 255, 255");
// add the canvas to the DOM
},
I expect it's not a case of won't work "at all", but rather a case of won't work "correctly".
Traditionally, onload ran when the html of the page was finished loading. The CSS and scripting would happen later, or possibly at the same time 1.
This is why the MozAfterPaint was introduced. It lets you inject code after Gecko has enough information to render the page.
You might be able work around the absence of MozAfterPaint, by listening for DOM mutation events. It's not as clean, but I think it will work if you use it to clear and reset a 100-200 ms tineout. That shouldn't cause too much of a performance hit. When the timeout finally expires you know the page has been stable for at least that long.
[1] I spent a week chasing a global variable that went from undefined to defined during the execution of the onload handler. It turned out to be a script tag pulled in a JS file that had some top-level code and it was executing in parallel with the onload handler.
Looks like the Mozilla documentation is wrong, and it is okay to call canvas.drawWindow() from the "load" event.
Related
For detecting when an image has completed downloading which method should I use?
image.onload = function () {}
or
image.addEventListener("load", function () {} );
onload:
Supports only a single listener.
Works in all browsers.
You unbind the event handler by clearing the onload property.
addEventListener:
Supports multiple listeners.
Doesn't work in older IE browsers (they use attachEvent).
You unbind the listener with removeEventListener() which requires info identifying the original eventListener.
If addEventListener is supported and you only need one listener, then you can use either.
If it's a simple self-contained piece of code that nobody else will be messing with then, there's no issue with using onload. If it's a more complex piece of software that other developers may mess with and any kind of extensibility is desired and you have cross browser support for event listeners, then addEventListener() is more flexible and is probably more desirable.
image.addEventListener("load", function() {} ); will not work on all browsers, but assuming you have a backup and use image.attachEvent("onload", function() {})
if(image.addEventListener) { image.addEventListener("load",function() {}); }
else { image.attachEvent("onload", function() {}); }
This will have the benefit that you are not overriding any onload event that already exists on the image, and that your onload event will not be overridden by any other code.
Directly modifying the "onload" attribute of a DOM Element is usually not recommended just because you may think "Hey, I can save a couple lines of code by setting it, and I only need one listener, so I'll just set it rather than using addEventListener/attachEvent" - but it invariably leads to "Well what if I need to add something else later?"
For this reason javascript developers usually use a library to attach events, so you can add the listener confidently with one line of code and it will work in all browsers.
try
if(image.complete){
//....
}
Both, Image.complete as well as image.onload don't seem to work in Webkit, at least the version on my mobile. They return false infinitely. It works in opera though, so the code may be ok.
Therefore I am currently using a trick that works at least in opera and webkit. I have a 1x1 pixel placeholder image ready. Now I set the src to the to be loaded image and (usually a bad practice, but this is a game that cannot start without that image) I go into a loop that updates some "loading" splashscreen gfx, but basicly just checks the width of the image, whether the image.width is bigger than 1 pixel.
Like I said, tested only with opera and webkit. I use it to load an atlas image and copy the containing tiles to individual images over a canvas. Once finished, the src of the atlas image is set back to the 1x1 placeholder, so it can be used that way again. For complete savity, one should also wait until the placeholder is 1 pixel in width again, before reuseing it that way.
const handleImage=()=>{}
image.addEventListener("load",handleImage); //adding a eventListener
image.removeEventListener("load",handleImage); //removeing a eventListener
I'm developing a Chrome plugin. It injects a class name to every tag.
I have some problems with webpages such as facebook in which content is loaded afterwards when you scroll down.
I'd like to know if there a way to check if new content is loaded.
By now the only solution I could find is a
setInterval(function() {
Thanks.
There is a DOMSubtreeModified event (source) that Chrome supports - see this answer for details. Your code should look something like this:
document.addEventListener('DOMSubtreeModified', function() {
$("*:not(.my_class)").addClass('my_class');
}, true);
As Konrad Dzwinel said, you can use some Mutation Event listener
document.addEventListener("DOMSubtreeModified", methodToRun);
But note that the Mutation Events are performance hogs which can't really be tamed well (they fire too often and slow down the page a lot). Therefore, they have been deprecated over a year ago and should be used only when really needed. However, they work.
If you want this for a Chrome extension, you could use the new and shiny Mutation Observers from DOM Level 4 (follow the links there, they explain a lot!). Where DOMSubtreeModified fired a thousand times, MutationObserver fires only once with all the modifications contained and accessible.
Works for (as of 2012/06):
Chrome 18+ (prefixed, window.WebKitMutationObserver)
Firefox 14+ (unprefixed)
WebKit nightlies
I'm trying to debug some JavaScript, I want to find out what code gets executed when I hover over a certain div element (I've got no idea which bit of code, because there's no direct 'onmouseover' - I think there's a jQuery selector in place somewhere?).
Usually I'd use the "Break All" / "Break On Next" facility provided by Developer Tools / Firebug, but my problem is that other code (tickers, mouse movement listeners etc.) immediately gets caught instead.
What I'd like to do is tell the debugger to ignore certain JavaScript files or individual lines, so that it won't stop on code I'm not interested in or have ruled out. Is there any way to achieve that in IE (spit, spit!) - or could you suggest a better approach?
In FireFox this feature is called "Black boxing" and will be available with FireFox 25. It let's do exactly what you where looking for.
This feature was also introduced to Chrome (v30+) although it's tougher to find/configure. It's called "skip through sources with particular names" and Collin Miller did an excellent job in describing how to configure it.
Normally I'm for putting answers and howtos here instead of links but it would just end in me copying Collin's post.
Looks like you're looking for Visual Event.
You might want to take a look at Paul Irish's Re-Introduction to the Chrome Developer Tools, in particular the Timeline section (starts around 15 minutes into the video.)
You can start recording all javascript events - function executions (with source lines etc) and debug based on what events fired. There are other really handy debugging tools hiding in that google IO talk that can help you solve this problem as well.
If you're pretty sure it's a jQuery event handler you can try to poke around with the jQuery events.
This will overwrite all the click handlers (replace with the type you're interested in) and log out something before each event handler is called:
var elem = document.body; // replace with your div
// wrap all click events:
$.each($._data(elem).events.click, function(i, v) {
var h = v.handler;
v.handler = function() {
// or use 'alert' or something here if no Dev Tools
console.log('calling event: '+ i);
console.log('event handler src: '+ h.toString());
h.apply(h, arguments);
};
})
Then try calling the event type directly through jQuery to rule out that type:
$('#your_div').click()
You can use JavaScript Deobfuscator extension in Firefox: https://addons.mozilla.org/addon/javascript-deobfuscator/. It uses the same debugging API as Firebug but presents the results differently.
In the "Executed scripts" tab it will show you all code that is running. If some unrelated code is executing as well it is usually easy enough to skip. But you can also tweak the default filters to limit the amount of code being displayed.
If using are using IE 7.0 onwards, you should have developer toolbar from where you can debug. Just use breakpoint where you need, rest of the code will not stop.
Alternatavely you can define other applications like Interdev/ Visual Studio.net for debugging purpose too.
I am currently building a corporate website for a customer that uses custom fonts extensively.
On jQuerys DOM-ready I am doing placement calculations to figure out where some pop-up menus with dynamic width and height should be placed based on their dynamic contents.
These calculations fail, since DOM-ready is fired before font-face is applied, and thus widths and heights are incorrect.
Right now (for the prototype) i am doing the calculations 500ms after DOM-ready to alleviate this problem, but this can't go into production for obvious reasons.
The problem has been observed in latest Firefox and chrome. IE 8 doesn't seem to have the problem, but then DOM-ready fires fairly late, so the delay is kind of built in I guess :)
Waiting for the load event is not an option, so my question to you is this:
Is there a reliable cross-browser way to detect when font-face has been applied?
I found a solution after wondering why IE doesn't suffer from this problem.
Firefox and Chrome/Safari triggers the DOMContentLoaded event before font-face is applied, thus causing the problem.
The solution is to not listen for DOMContentLoaded but instead go oldschool and listen to onreadystatechange and wait until the document.readyState === 'complete' which is always triggered after font-face is applied (as far as I can tell by my tests) - which is of course what always happens in IE since it doesn't support DOMContentLoaded.
So basically you can roll-your-own event in jQuery called fontfaceapplied - maybe it should be built in ;)
document.onreadystatechange = function() {
if (document.readyState === 'complete')
$(document).trigger('fontfaceapplied');
};
Funny fact: Opera does it right and waits to trigger DOMContentLoaded until font-face is applied.
ES6 update:
The question post is for many years ago which the IEs version 8 and earlier were still alive and even Ecmascript version 6 was not released, but now you can write callbacks on document.fonts events. eg:
document.fonts.onloadingdone = () => {
// do something after all fonts are loaded
};
For more information see this post.
Setting the function to trigger after a timeout of 200ms solves this issue when using Google Fonts.
There's a noticeable jump, but there usually is for equal heights stuff, for the purists this might not be perfect but it works cross browser.
I am trying to understand an issue where event-listener registration on plugins doesn't work in Opera unless I delay them.
In particular, this doesn't work:
document.onload = function() {
plugin.addEventListener("foo", function() { alert('onFoo'); }, false);
}
while delaying the addEventListener() call somewhat through e.g. an alert() does:
document.onload = function() {
alert('onload()');
plugin.addEventListener("foo", function() { alert('onFoo'); }, false);
}
It seems that plugins are only loaded after document.onload.
As a non-web-developer, am I missing something simple here? Or is this a known Opera problem with a common work-around?
in general the timing of plugin initialisation, script execution and document event handling isn't well specified, meaning browsers are likely to do different things.
In this case it sounds like you need to make sure the plugin is initialised before you add the listener. One way to do that would be to check for a property the plugin will define (for example, if it was a Flash plugin you could check if PercentLoaded was defined to see if it is ready for scripting.) If not ready for scripting, you could use a timeout to try again a little bit later.
At Opera we've been trying to align with the majority of the other browsers in this area recently, and Opera 10.50 may be working better for you. I'm not sure if we have things fully under control yet though - it would be interesting to hear from you whether behaviour changed in 10.50.
We have further improved handling of this in Opera 10.60, so that behavior is much closer to the other browsers wrt. plug-in initialization and script readyness. I believe the original approach should work now.
I don't know much about Opera but have you tried using jquery's ready function? It's purpose is to add a function you want executed once the DOM is fully loaded and it should work cross browser.
$(document).ready(function() {
plugin.addEventListener("foo", function() { alert('onFoo'); }, false);
});
More info about the ready function can be found here