-
-
Save adamhotep/7c9068f2196326ab79145ae308b68f9e to your computer and use it in GitHub Desktop.
A utility function, for userscripts including Greasemonkey, that detects and handles AJAXed content.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*--- waitForKeyElements(): A utility function, for Greasemonkey scripts, | |
that detects and handles AJAXed content. | |
Original: https://gist.github.com/BrockA/2625891 | |
Non-jQuery version by: Adam Katz, | |
https://gist.github.com/adamhotep/7c9068f2196326ab79145ae308b68f9e | |
License: CC BY-NC-SA 4.0 (*not* GPL-compatible) | |
changes made by Adam Katz (tracked by adamhotep's github gist) are | |
also licensed GPL v2+ (but note the CC BY-NC-SA prevents commercial use) | |
License via https://gist.github.com/BrockA/2625891#gistcomment-1617026 | |
Usage example: | |
// ==UserScript== | |
// … | |
// @require https://git.io/waitForKeyElements.js | |
// ==/UserScript== | |
waitForKeyElements ( | |
"div.comments", | |
commentCallbackFunction | |
); | |
//--- Page-specific function to do what we want when the node is found. | |
function commentCallbackFunction (elem) { | |
elem.innerHTML = "This comment changed by waitForKeyElements()."; | |
} | |
*/ | |
function waitForKeyElements ( | |
selectorTxt, /* Required: The querySelector string that | |
specifies the desired element(s). | |
*/ | |
actionFunction, /* Required: The code to run when elements are | |
found. It is passed the matched element. | |
*/ | |
bWaitOnce, /* Optional: If false, will continue to scan for | |
new elements even after the first match is | |
found. | |
*/ | |
iframeSelector /* Optional: If set, identifies the iframe to | |
search. | |
*/ | |
) { | |
var targetNodes, btargetsFound; | |
//--- Additionally avoid what we've found | |
var selectorClean = selectorTxt.replace(/(,)|$/g, ":not([wfke_found])$1"); | |
if (typeof iframeSelector == "undefined") | |
targetNodes = document.querySelectorAll(selectorClean); | |
else { | |
targetNodes = []; | |
var iframe = document.querySelectorAll(iframeSelector); | |
for (var i = 0, il = iframe.length; i < il; i++) { | |
var nodes = iframe[i].querySelectorAll(selectorClean); | |
if (nodes) targetNodes.concat(Array.from(nodes)); | |
} | |
} | |
if (targetNodes && targetNodes.length > 0) { | |
btargetsFound = true; | |
//--- Found target node(s). Go through each and act if they are new. | |
for (var t = 0, tl = targetNodes.length; t < tl; t++) { | |
if (!targetNodes[t].getAttribute("wfke_found")) { | |
//--- Call the payload function. | |
var cancelFound = false; | |
try { | |
cancelFound = actionFunction (targetNodes[t]); | |
} | |
//--- Log errors to console rather than stopping altogether | |
catch (error) { | |
var name = actionFunction.name; | |
if (name) | |
name = 'in function "' + name + '":\n'; | |
console.log ("waitForKeyElements: actionFunction error\n" | |
+ name + error); | |
} | |
if (cancelFound) | |
btargetsFound = false; | |
else | |
targetNodes[t].setAttribute("wfke_found", true); | |
} | |
} | |
} | |
else { | |
btargetsFound = false; | |
} | |
//--- Get the timer-control variable for this selector. | |
var controlObj = waitForKeyElements.controlObj || {}; | |
var controlKey = selectorTxt.replace (/[^\w]/g, "_"); | |
var timeControl = controlObj [controlKey]; | |
//--- Now set or clear the timer as appropriate. | |
if (btargetsFound && bWaitOnce && timeControl) { | |
//--- The only condition where we need to clear the timer. | |
clearInterval (timeControl); | |
delete controlObj [controlKey] | |
} | |
else { | |
//--- Set a timer, if needed. | |
if ( ! timeControl) { | |
timeControl = setInterval ( function () { | |
waitForKeyElements ( selectorTxt, | |
actionFunction, | |
bWaitOnce, | |
iframeSelector | |
); | |
}, | |
300 | |
); | |
controlObj [controlKey] = timeControl; | |
} | |
} | |
waitForKeyElements.controlObj = controlObj; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In my first revision, I credited the original author, noted the license, and incorporated changes from EnterTheNameHere's first (and currently only) revision (#5), which uses
try/catch
exception handling in case there is a problem with the function provided towaitForKeyElements()
to act on.I've also created https://git.io/waitForKeyElements.js for easier loading in userscripts.