Skip to content

Instantly share code, notes, and snippets.

@A
Forked from mistakster/gist:4193053
Last active December 16, 2015 18:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save A/5476898 to your computer and use it in GitHub Desktop.
Save A/5476898 to your computer and use it in GitHub Desktop.
onAvailable: Executes the supplied callback when the item with the supplied id is found.
(function (window, document) {
function onLoad(callback) {
if (document.readyState === "complete") {
setTimeout(callback, 1);
} else if (document.addEventListener) {
window.addEventListener("load", callback, false);
} else {
window.attachEvent("onload", callback);
}
}
var isReady = false;
onLoad(function () {
isReady = true;
});
/**
* Milliseconds between retries
*/
var POLL_INTERVAL = 20;
/**
* Number of attempts to locate element
*/
var POLL_RETRIES = 2000;
var interval = null,
listeners = [],
pollRetries;
/**
* Polls the DOM for an element matching the supplied id and fires the
* associated callback method
*/
function checkAvailable() {
var i, l, listener, el, missed = 0;
for (i = 0, l = listeners.length; i < l; i++) {
listener = listeners[i];
if (listener) {
el = document.getElementById(listener.id);
/**
* If the DOM element is found, execute callbacks for all related
* onAvailable listeners. If the DOM is ready or the next sibling
* is detected, execute callbacks for all onContentReady listeners.
*/
if (el && (!listener.checkContent || (listener.checkContent && (el.nextSibling || el.parentNode.nextSibling || isReady)))) {
try {
listener.callback.call(el, listener.obj);
} catch (ex) {
console.error(ex);
}
listeners[i] = null;
} else {
missed++;
}
}
}
pollRetries--;
if (missed === 0 || pollRetries <= 0) {
interval = window.clearInterval(interval);
if (listeners.length) {
listeners.splice(0, listeners.length);
}
}
listener = el = null;
}
/**
* NOTE: If element is last the child of its parent node, include at
* least one character of whitespace or onContentReady will not fire
* until DOMReady.
*/
/**
* Executes the supplied callback when the item with the supplied
* id is found. This is meant to be used to execute behavior as
* soon as possible as the page loads. If you use this after the
* initial page load it will poll for a fixed time for the element.
* The number of times it will poll and the frequency are
* configurable. By default it will poll for 40 seconds at a rate
* of 50 times per second.
*
* <p>The callback is executed with a single parameter:
* the custom object parameter, if provided.</p>
*
* @param {String} id id of element to look for
* @param {Function} callback method to execute when element is found
* @param {Object} [obj] optional object to passed as parameter to callback
* @param {Boolean} [checkContent] check child node readiness (onContentReady)
*/
function onAvailable(id, callback, obj, checkContent) {
pollRetries = POLL_RETRIES;
listeners.push({
id: id,
callback: callback,
obj: obj,
checkContent: !!checkContent
});
if (!interval) {
interval = window.setInterval(checkAvailable, POLL_INTERVAL);
}
}
window.onAvailable = onAvailable;
}(window, document));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment