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
Related
I just wrote a chrome extension that replaces stock symbols designted with a $ before them with data from yahoo finance. I am running into some issues though based on how twitter loads the stream. I have the js set to run on document_end but twitter loads the stream after the DOM is ready. To get around this I just checked to see if a certain Element existed and then ran the scripts if it didnt just wait 500 ms and try again.
There seems to be an issue on the search pages as well possibly because the element I am checking has a different class I did not really look into the issue yet.
The other issue is it creates a mess when there are tons of symbols in one tweet might be related to the first issue but seems like it is inserting extra DOM elements.
the project is hosted on github would be awesome to get some feedback and possibly contributions.
https://github.com/billpull/Twitter-Ticker
The easiest way is to listen to DOMMutation events. Before the browser renders the tweet, you can capture this with DOMNodeInserted event.
As Chrome 18, MutationObservers are now implemented, it is fast, and doesn't fire to quickly so it is concise. DOM Mutation Observers is asynchronous and can fire multiple changes per call! It significantly improves performance of your mutations.
An example of using MutationObservers would be:
var observer = new MutationObserver(function onMutationObserver(mutations) {
mutations.forEach(function(mutationNode) {
// New Nodes added ... Deal with it!
});
});
observer.observe(historyContainerDOM, { childList: true, subtree: true });
I have added some comments to one of my open source extensions that talk about this, feel free to take what you want.
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.
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.
I can add or remove an event handler for a DOM node. Is it possible to find out all the registered events handlers of a given DOM node? I am referring to straight Javascript meaning no frameworks or toolkits like jQuery, dojo, Prototype, GWT, etc. If the answer is no, any reason why? Security issues?
I know this is an old question, but just in case, for chrome you can use getEventListeners
getEventListeners function
as mentioned here:
https://stackoverflow.com/a/17466308/538752
DOM Level 3 specifies eventListenerList - however, I'm not aware of any DOM implementation which supports this - or any other reliable way to list the event listeners. It seems to have been an oversight to this point.
This works for Chrome/Safari console:
getEventListeners(document.getElementByID('myElementId'));
Visual Event can show you which events are registered, but it only works with DOM level 0 attached events; the W3C level 2 implementation as well as the Internet Explorer proprietary method are not supported and/or cannot be retrieved.
If your interest is to discover some event, in order to disable it - I came here because of that - I recommend to use the Firebug extension, with Mozilla Firefox. Selecting the part of the document, you are interested in, look at the right panel, the Events tab: you will see all events, and can even disable them.
Also, in Google Chrome, please select the element and notice the number, it will show you $0 or any other number.
Then in console, type this code and press enter.
getEventListeners($0)
and then you will see the result. Please see the image below for more elaboration.
I faced the same problem, landed here, and didn't find an useful answer.
In case you can execute script before addEventListener calls from other parties, you might do something really dirty like:
var obj = something; // Your DOM element you want to watch
var beforeAddEvent = obj.addEventListener;
obj.addEventListener = function() {
// Do something with arguments here (like storing in an array)
// arguments[0]: event name
// arguments[1]: Listener function
// arguments[3]: eventual options passed
// If you don't call this, the event listener won't even be attached, it might be also useful in some case
beforeAddEvent.apply(obj, arguments);
};