|
(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)); |