/*!

* onDomReady.js 1.4.0 (c) 2013 Tubal Martin - MIT license
*
* Specially modified to work with Holder.js
*/

function _onDomReady(win) {

//Lazy loading fix for Firefox < 3.6
//http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
if (document.readyState == null && document.addEventListener) {
    document.addEventListener("DOMContentLoaded", function DOMContentLoaded() {
        document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false);
        document.readyState = "complete";
    }, false);
    document.readyState = "loading";
}

var doc = win.document,
    docElem = doc.documentElement,

    LOAD = "load",
    FALSE = false,
    ONLOAD = "on"+LOAD,
    COMPLETE = "complete",
    READYSTATE = "readyState",
    ATTACHEVENT = "attachEvent",
    DETACHEVENT = "detachEvent",
    ADDEVENTLISTENER = "addEventListener",
    DOMCONTENTLOADED = "DOMContentLoaded",
    ONREADYSTATECHANGE = "onreadystatechange",
    REMOVEEVENTLISTENER = "removeEventListener",

    // W3C Event model
    w3c = ADDEVENTLISTENER in doc,
    _top = FALSE,

    // isReady: Is the DOM ready to be used? Set to true once it occurs.
    isReady = FALSE,

    // Callbacks pending execution until DOM is ready
    callbacks = [];

// Handle when the DOM is ready
function ready( fn ) {
    if ( !isReady ) {

        // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
        if ( !doc.body ) {
            return defer( ready );
        }

        // Remember that the DOM is ready
        isReady = true;

        // Execute all callbacks
        while ( fn = callbacks.shift() ) {
            defer( fn );
        }
    }
}

// The ready event handler
function completed( event ) {
    // readyState === "complete" is good enough for us to call the dom ready in oldIE
    if ( w3c || event.type === LOAD || doc[READYSTATE] === COMPLETE ) {
        detach();
        ready();
    }
}

// Clean-up method for dom ready events
function detach() {
    if ( w3c ) {
        doc[REMOVEEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE );
        win[REMOVEEVENTLISTENER]( LOAD, completed, FALSE );
    } else {
        doc[DETACHEVENT]( ONREADYSTATECHANGE, completed );
        win[DETACHEVENT]( ONLOAD, completed );
    }
}

// Defers a function, scheduling it to run after the current call stack has cleared.
function defer( fn, wait ) {
    // Allow 0 to be passed
    setTimeout( fn, +wait >= 0 ? wait : 1 );
}

// Attach the listeners:

// Catch cases where onDomReady is called after the browser event has already occurred.
// we once tried to use readyState "interactive" here, but it caused issues like the one
// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
if ( doc[READYSTATE] === COMPLETE ) {
    // Handle it asynchronously to allow scripts the opportunity to delay ready
    defer( ready );

// Standards-based browsers support DOMContentLoaded
} else if ( w3c ) {
    // Use the handy event callback
    doc[ADDEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE );

    // A fallback to window.onload, that will always work
    win[ADDEVENTLISTENER]( LOAD, completed, FALSE );

// If IE event model is used
} else {
    // Ensure firing before onload, maybe late but safe also for iframes
    doc[ATTACHEVENT]( ONREADYSTATECHANGE, completed );

    // A fallback to window.onload, that will always work
    win[ATTACHEVENT]( ONLOAD, completed );

    // If IE and not a frame
    // continually check to see if the document is ready
    try {
        _top = win.frameElement == null && docElem;
    } catch(e) {}

    if ( _top && _top.doScroll ) {
        (function doScrollCheck() {
            if ( !isReady ) {
                try {
                    // Use the trick by Diego Perini
                    // http://javascript.nwbox.com/IEContentLoaded/
                    _top.doScroll("left");
                } catch(e) {
                    return defer( doScrollCheck, 50 );
                }

                // detach all dom ready events
                detach();

                // and execute any waiting functions
                ready();
            }
        })();
    }
}

function onDomReady( fn ) {
    // If DOM is ready, execute the function (async), otherwise wait
    isReady ? defer( fn ) : callbacks.push( fn );
}

// Add version
onDomReady.version = "1.4.0";
// Add method to check if DOM is ready
onDomReady.isReady = function(){
    return isReady;
};

return onDomReady;

}

module.exports = typeof window !== “undefined” && _onDomReady(window);