curl-amd
Version:
curl.js is small, fast, extensible module loader that handles AMD, CommonJS Modules/1.1, CSS, HTML/text, and legacy scripts.
136 lines (121 loc) • 3.47 kB
JavaScript
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl domReady
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*/
/**
* usage:
* require(['ModuleA', 'curl/domReady'], function (ModuleA, domReady) {
* var a = new ModuleA();
* domReady(function () {
* document.body.appendChild(a.domNode);
* });
* });
*
* also: check out curl's domReady! plugin
*
* HT to Bryan Forbes who wrote the initial domReady code:
* http://www.reigndropsfall.net/
*
*/
(function (global, doc) {
var
readyState = 'readyState',
// keep these quoted so closure compiler doesn't squash them
readyStates = { 'loaded': 1, 'interactive': 1, 'complete': 1 },
callbacks = [],
fixReadyState = doc && typeof doc[readyState] != "string",
// IE needs this cuz it won't stop setTimeout if it's already queued up
completed = false,
pollerTime = 10,
addEvent,
remover,
removers = [],
pollerHandle,
undef;
function ready () {
completed = true;
clearTimeout(pollerHandle);
while (remover = removers.pop()) remover();
if (fixReadyState) {
doc[readyState] = "complete";
}
// callback all queued callbacks
var cb;
while ((cb = callbacks.shift())) {
cb();
}
}
var testEl;
function isDomManipulable () {
// question: implement Diego Perini's IEContentLoaded instead?
// answer: The current impl seems more future-proof rather than a
// non-standard method (doScroll). i don't care if the rest of the js
// world is using doScroll! They can have fun repairing their libs when
// the IE team removes doScroll in IE 13. :)
if (!doc.body) return false; // no body? we're definitely not ready!
if (!testEl) testEl = doc.createTextNode('');
try {
// webkit needs to use body. doc
doc.body.removeChild(doc.body.appendChild(testEl));
testEl = undef;
return true;
}
catch (ex) {
return false;
}
}
function checkDOMReady (e) {
var isReady;
// all browsers except IE will be ready when readyState == 'interactive'
// so we also must check for document.body
isReady = readyStates[doc[readyState]] && isDomManipulable();
if (!completed && isReady) {
ready();
}
return isReady;
}
function poller () {
checkDOMReady();
if (!completed) {
pollerHandle = setTimeout(poller, pollerTime);
}
}
// select the correct event listener function. all of our supported
// browsers will use one of these
if ('addEventListener' in global) {
addEvent = function (node, event) {
node.addEventListener(event, checkDOMReady, false);
return function () { node.removeEventListener(event, checkDOMReady, false); };
};
}
else {
addEvent = function (node, event) {
node.attachEvent('on' + event, checkDOMReady);
return function () { node.detachEvent(event, checkDOMReady); };
};
}
if (doc) {
if (!checkDOMReady()) {
// add event listeners and collect remover functions
removers = [
addEvent(global, 'load'),
addEvent(doc, 'readystatechange'),
addEvent(global, 'DOMContentLoaded')
];
// additionally, poll for readystate
pollerHandle = setTimeout(poller, pollerTime);
}
}
define(/*=='curl/domReady',==*/ function () {
// this is simply a callback, but make it look like a promise
function domReady (cb) {
if (completed) cb(); else callbacks.push(cb);
}
domReady['then'] = domReady;
domReady['amd'] = true;
return domReady;
});
}(this, this.document));