(function() {

var reFeaturedMethod = new RegExp('^function|object$', 'i');

var isHostMethod = function(o, m) {
	var t = typeof o[m];
	return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown');
};

var W = this, D = this.document;

if(D) {
	var domReadylisteners = [], domReadyDone = false, domReadyIsDone, domReadyListener, addDomReadyListener,
		canAddDocumentReadyListener = isHostMethod(D, 'addEventListener'),
		canAddWindowLoadListener = isHostMethod(this, 'addEventListener'),
		canAttachWindowLoadListener = isHostMethod(this, 'attachEvent');
	
	if(D && (canAddDocumentReadyListener || canAddWindowLoadListener || canAttachWindowLoadListener)) {
		domReadyIsDone = function() {return domReadyDone;};
		W.domReadyIsDone = domReadyIsDone;
		
		domReadyListener = function() {
			if(!domReadyDone) {
				domReadyDone = true;
				var i = domReadylisteners.length;
				var m = i - 1;
				while(i--) {domReadylisteners[m - i]();}
			}
		};
		W.domReadyListener = domReadyListener;
		
		addDomReadyListener = function(fn) {
			if(!domReadylisteners.length) {
				if(canAddDocumentReadyListener) {
					D.addEventListener('DOMContentLoaded', domReadyListener, false);
				}
				if(canAddWindowLoadListener) {
					W.addEventListener('load', domReadyListener, false);
				} else {
					if(canAttachWindowLoadListener) {
						W.attachEvent('onload', domReadyListener);
					}
				}
			}
			domReadylisteners[domReadylisteners.length] = fn;
			return true;
		};
		W.addDomReadyListener = addDomReadyListener;
	}
}

})();