[Javascript] $ (documento) .equivalente sin jQuery


Answers

Editar:

Aquí hay un reemplazo viable para jQuery listo

function ready(callback){
    // in case the document is already rendered
    if (document.readyState!='loading') callback();
    // modern browsers
    else if (document.addEventListener) document.addEventListener('DOMContentLoaded', callback);
    // IE <= 8
    else document.attachEvent('onreadystatechange', function(){
        if (document.readyState=='complete') callback();
    });
}

ready(function(){
    // do something
});

Tomado de https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/

Como la respuesta aceptada estaba muy lejos de completarse, jQuery.ready() función "lista" como jQuery.ready() basada en la fuente de jQuery 1.6.2:

var ready = (function(){

    var readyList,
        DOMContentLoaded,
        class2type = {};
        class2type["[object Boolean]"] = "boolean";
        class2type["[object Number]"] = "number";
        class2type["[object String]"] = "string";
        class2type["[object Function]"] = "function";
        class2type["[object Array]"] = "array";
        class2type["[object Date]"] = "date";
        class2type["[object RegExp]"] = "regexp";
        class2type["[object Object]"] = "object";

    var ReadyObj = {
        // Is the DOM ready to be used? Set to true once it occurs.
        isReady: false,
        // A counter to track how many items to wait for before
        // the ready event fires. See #6781
        readyWait: 1,
        // Hold (or release) the ready event
        holdReady: function( hold ) {
            if ( hold ) {
                ReadyObj.readyWait++;
            } else {
                ReadyObj.ready( true );
            }
        },
        // Handle when the DOM is ready
        ready: function( wait ) {
            // Either a released hold or an DOMready/load event and not yet ready
            if ( (wait === true && !--ReadyObj.readyWait) || (wait !== true && !ReadyObj.isReady) ) {
                // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
                if ( !document.body ) {
                    return setTimeout( ReadyObj.ready, 1 );
                }

                // Remember that the DOM is ready
                ReadyObj.isReady = true;
                // If a normal DOM Ready event fired, decrement, and wait if need be
                if ( wait !== true && --ReadyObj.readyWait > 0 ) {
                    return;
                }
                // If there are functions bound, to execute
                readyList.resolveWith( document, [ ReadyObj ] );

                // Trigger any bound ready events
                //if ( ReadyObj.fn.trigger ) {
                //    ReadyObj( document ).trigger( "ready" ).unbind( "ready" );
                //}
            }
        },
        bindReady: function() {
            if ( readyList ) {
                return;
            }
            readyList = ReadyObj._Deferred();

            // Catch cases where $(document).ready() is called after the
            // browser event has already occurred.
            if ( document.readyState === "complete" ) {
                // Handle it asynchronously to allow scripts the opportunity to delay ready
                return setTimeout( ReadyObj.ready, 1 );
            }

            // Mozilla, Opera and webkit nightlies currently support this event
            if ( document.addEventListener ) {
                // Use the handy event callback
                document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
                // A fallback to window.onload, that will always work
                window.addEventListener( "load", ReadyObj.ready, false );

            // If IE event model is used
            } else if ( document.attachEvent ) {
                // ensure firing before onload,
                // maybe late but safe also for iframes
                document.attachEvent( "onreadystatechange", DOMContentLoaded );

                // A fallback to window.onload, that will always work
                window.attachEvent( "onload", ReadyObj.ready );

                // If IE and not a frame
                // continually check to see if the document is ready
                var toplevel = false;

                try {
                    toplevel = window.frameElement == null;
                } catch(e) {}

                if ( document.documentElement.doScroll && toplevel ) {
                    doScrollCheck();
                }
            }
        },
        _Deferred: function() {
            var // callbacks list
                callbacks = [],
                // stored [ context , args ]
                fired,
                // to avoid firing when already doing so
                firing,
                // flag to know if the deferred has been cancelled
                cancelled,
                // the deferred itself
                deferred  = {

                    // done( f1, f2, ...)
                    done: function() {
                        if ( !cancelled ) {
                            var args = arguments,
                                i,
                                length,
                                elem,
                                type,
                                _fired;
                            if ( fired ) {
                                _fired = fired;
                                fired = 0;
                            }
                            for ( i = 0, length = args.length; i < length; i++ ) {
                                elem = args[ i ];
                                type = ReadyObj.type( elem );
                                if ( type === "array" ) {
                                    deferred.done.apply( deferred, elem );
                                } else if ( type === "function" ) {
                                    callbacks.push( elem );
                                }
                            }
                            if ( _fired ) {
                                deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
                            }
                        }
                        return this;
                    },

                    // resolve with given context and args
                    resolveWith: function( context, args ) {
                        if ( !cancelled && !fired && !firing ) {
                            // make sure args are available (#8421)
                            args = args || [];
                            firing = 1;
                            try {
                                while( callbacks[ 0 ] ) {
                                    callbacks.shift().apply( context, args );//shifts a callback, and applies it to document
                                }
                            }
                            finally {
                                fired = [ context, args ];
                                firing = 0;
                            }
                        }
                        return this;
                    },

                    // resolve with this as context and given arguments
                    resolve: function() {
                        deferred.resolveWith( this, arguments );
                        return this;
                    },

                    // Has this deferred been resolved?
                    isResolved: function() {
                        return !!( firing || fired );
                    },

                    // Cancel
                    cancel: function() {
                        cancelled = 1;
                        callbacks = [];
                        return this;
                    }
                };

            return deferred;
        },
        type: function( obj ) {
            return obj == null ?
                String( obj ) :
                class2type[ Object.prototype.toString.call(obj) ] || "object";
        }
    }
    // The DOM ready check for Internet Explorer
    function doScrollCheck() {
        if ( ReadyObj.isReady ) {
            return;
        }

        try {
            // If IE is used, use the trick by Diego Perini
            // http://javascript.nwbox.com/IEContentLoaded/
            document.documentElement.doScroll("left");
        } catch(e) {
            setTimeout( doScrollCheck, 1 );
            return;
        }

        // and execute any waiting functions
        ReadyObj.ready();
    }
    // Cleanup functions for the document ready method
    if ( document.addEventListener ) {
        DOMContentLoaded = function() {
            document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
            ReadyObj.ready();
        };

    } else if ( document.attachEvent ) {
        DOMContentLoaded = function() {
            // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", DOMContentLoaded );
                ReadyObj.ready();
            }
        };
    }
    function ready( fn ) {
        // Attach the listeners
        ReadyObj.bindReady();

        var type = ReadyObj.type( fn );

        // Add the callback
        readyList.done( fn );//readyList is result of _Deferred()
    }
    return ready;
})();

Cómo utilizar:

<script>
    ready(function(){
        alert('It works!');
    });
    ready(function(){
        alert('Also works!');
    });
</script>

No estoy seguro de cuán funcional es este código, pero funcionó bien con mis pruebas superficiales. Esto llevó bastante tiempo, así que espero que usted y otros puedan beneficiarse de ello.

PD .: Sugiero compiling .

O puede usar http://dustindiaz.com/smallest-domready-ever :

function r(f){/in/.test(document.readyState)?setTimeout(r,9,f):f()}
r(function(){/*code to run*/});

o la función nativa si solo necesita admitir los navegadores nuevos (A diferencia de jQuery listo, esto no se ejecutará si agrega esto después de que la página se haya cargado)

document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})
Question

Tengo un script que usa $(document).ready , pero no usa nada más de jQuery. Me gustaría aclararlo quitando la dependencia de jQuery.

¿Cómo puedo implementar mi propia funcionalidad $(document).ready sin usar jQuery? Sé que usar window.onload no será el mismo, ya que window.onload después de que se hayan cargado todas las imágenes, marcos, etc.




In short, instead of the $(document).ready() used in jQuery, we can use a JavaScript method:

<script>
    document.addEventListener("DOMContentLoaded", function_name, false);
    function function_name(){
        statements;
    }
</script>

Thus, when the page is ready ie DOMContentLoaded only then the function function_name() will be invoked.




Esta pregunta fue hecha hace mucho tiempo. Para cualquiera que solo esté viendo esta pregunta, ahora hay un sitio llamado "puede que no necesite jquery" que se descompone, por nivel de soporte de IE requerido, toda la funcionalidad de jquery y proporciona algunas bibliotecas alternativas más pequeñas.

Esquema listo para documentos de IE8 según usted puede ser que no necesite jquery

function ready(fn) {
    if (document.readyState != 'loading')
        fn();
    else if (document.addEventListener)
        document.addEventListener('DOMContentLoaded', fn);
    else
        document.attachEvent('onreadystatechange', function() {
            if (document.readyState != 'loading')
                fn();
        });
}



Encontramos una implementación de navegador cruzado rápida y sucia que puede hacer el truco para la mayoría de los casos simples con una implementación mínima:

window.onReady = function onReady(fn){
    document.body ? fn() : setTimeout(function(){ onReady(fn);},50);
};



Esto es lo que uso, es rápido y cubre todas las bases, creo; funciona para todo excepto IE <9.

(() => { function fn() {
    // "On document ready" commands:
    console.log(document.readyState);
};  
  if (document.readyState != 'loading') {fn()}
  else {document.addEventListener('DOMContentLoaded', fn)}
})();

Esto parece captar todos los casos:

  • se dispara inmediatamente si el DOM ya está listo (si el DOM no está "cargando", sino que es "interactivo" o "completo")
  • si el DOM aún se está cargando, configura un detector de eventos para cuando el DOM esté disponible (interactivo).

El evento DOMContentLoaded está disponible en IE9 y todo lo demás, así que personalmente creo que está bien usar esto. Vuelva a escribir la declaración de función de flecha en una función anónima normal si no transporta su código de ES2015 a ES5.

Si desea esperar hasta que se carguen todos los activos, se muestren todas las imágenes, etc., utilice window.onload en su lugar.




Aquí está el fragmento de código más pequeño para probar DOM listo que funciona en todos los navegadores (incluso IE 8):

r(function(){
    alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}

Vea esta answer .




function onDocReady(fn){
    (function c(){document.readyState!=="loading"?fn():setTimeout(c,9)})();
}   

function onDocLoad(fn){
    (function c(){document.readyState==="complete"?fn():setTimeout(c,30)})();
}    

onDocReady provides a callback when the HTML dom is ready to fully access/parse/manipulate.

onDocLoad provides a callback when everything has loaded (images etc)

  • These functions can be called whenever you want.
  • Supports multiple "listeners".
  • Will work in any browser.



Yo uso esto:

document.addEventListener("DOMContentLoaded", function(event) { 
    //Do work
});

Nota: Esto probablemente solo funcione con los navegadores más nuevos, especialmente estos: http://caniuse.com/#feat=domcontentloaded




La respuesta jQuery fue bastante útil para mí. Con un poco de refrigerio, satisfizo mis necesidades. Espero que ayude a los demás.

function onReady ( callback ){
    var addListener = document.addEventListener || document.attachEvent,
        removeListener =  document.removeEventListener || document.detachEvent
        eventName = document.addEventListener ? "DOMContentLoaded" : "onreadystatechange"

    addListener.call(document, eventName, function(){
        removeListener( eventName, arguments.callee, false )
        callback()
    }, false )
}



La función lista en jQuery hace varias cosas. Francamente, no veo el punto de reemplazarlo a menos que tenga un rendimiento increíblemente pequeño en su sitio web. jQuery es una biblioteca bastante pequeña, y maneja todo tipo de cosas de navegador cruzado que necesitarás más adelante.

De todos modos, no tiene mucho sentido publicarlo aquí, solo abre jQuery y mira el método bindReady .

It starts by calling either document.addEventListener("DOMContentLoaded") or document.attachEvent('onreadystatechange') depending on the event model, and goes on from there.




If you are loading jQuery near the bottom of BODY, but are having trouble with code that writes out jQuery(<func>) or jQuery(document).ready(<func>), check out jqShim on Github.

Rather than recreate its own document ready function, it simply holds onto the functions until jQuery is available then proceeds with jQuery as expected. The point of moving jQuery to the bottom of body is to speed up page load, and you can still accomplish it by inlining the jqShim.min.js in the head of your template.

I ended up writing this code to make moving all the scripts in WordPress to the footer, and just this shim code now sits directly in the header.




Este código de navegador cruzado llamará a una función una vez que el DOM esté listo:

var domReady=function(func){
    var scriptText='('+func+')();';
    var scriptElement=document.createElement('script');
    scriptElement.innerText=scriptText;
    document.body.appendChild(scriptElement);
};

Así es como funciona:

  1. La primera línea de domReady llama al método toString de la función para obtener una representación de cadena de la función que pasa y la envuelve en una expresión que llama inmediatamente a la función.
  2. El resto de domReady crea un elemento script con la expresión y lo agrega al body del documento.
  3. El navegador ejecuta etiquetas de secuencia de comandos anexadas al body después de que el DOM esté listo.

Por ejemplo, si haces esto: domReady(function(){alert();}); , lo siguiente se agregará al elemento del body :

 <script>(function (){alert();})();</script>

Tenga en cuenta que esto funciona solo para las funciones definidas por el usuario. Lo siguiente no funcionará: domReady(alert);




¿Qué tal esta solución?

// other onload attached earlier
window.onload=function() {
   alert('test');
};

tmpPreviousFunction=window.onload ? window.onload : null;

// our onload function
window.onload=function() {
   alert('another message');

   // execute previous one
   if (tmpPreviousFunction) tmpPreviousFunction();
};



This was a good https://.com/a/11810957/185565 poor man's solution. One comment considered a counter to bail out in case of emergency. This is my modification.

function doTheMagic(counter) {
  alert("It worked on " + counter);
}

// wait for document ready then call handler function
var checkLoad = function(counter) {
  counter++;
  if (document.readyState != "complete" && counter<1000) {
    var fn = function() { checkLoad(counter); };
    setTimeout(fn,10);
  } else doTheMagic(counter);
};
checkLoad(0);



Coloque su <script>/*JavaScript code*/</script> justo antes de la etiqueta de cierre </body> .

Es cierto que esto podría no ser adecuado para todos, ya que requiere cambiar el archivo HTML en lugar de simplemente hacer algo en el archivo JavaScript a la fecha. document.ready , pero aún así ...






Links