I'm trying to write a Greasemonkey script that alters keywords in Twitter posts. Trouble is, the content is "late loading" and is added to at the users request.
If I were adding event listeners to the added elements, I could use JQuery's delegate()
. As I simply want to change the content when it loads, this doesn't appear to be appropriate.
Mutation Events seem to fit the bill. They are Gecko specific, but this doesn't matter much for a Greasemonkey script. Problem is, they have been depreciated and for a set of very good reasons.
Of course I could use a timer and poll the DOM at regular intervals, but this just seems icky.
How can I detect additions to the DOM and react to the inserted elements?
If you want to detect AJAX-created nodes your options (besides Mutation events which you are wise to rule out) are:
- Polling with an interval or timer.
- Trying to hook into the page's AJAX requests (if any).
- Splicing into, hijacking, or replacing the page's javascript.
I've done all of these at one time and all but one have major drawbacks:
- Splicing into the page's javascript is not always easy (especially with anonymous functions), usually requires complicated deconstruction of that code, and is brittle as heck. A page's javascript changes without notice.
- Hooking into the page's AJAX requests can sometimes be pretty easy, but transferring the information across the sandbox barrier usually makes it more trouble than it's worth.
- Polling works darn well in practice, is simple to implement, and usually low cost.
I recommend you use the waitForKeyElements() utility and be done with it.
It's very easy to use. For example:
// ==UserScript==
// @name Highlight good comments
// @include http://SOME_SITE/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// ==/UserScript==
function highlightGoodComments (jNode) {
if (/beer/i.test (jNode.text () ) ) {
jNode.css ("background", "yellow");
}
}
waitForKeyElements ("#userBlather div.comment", highlightGoodComments);