jQuery для Javascript-кода для document.ready [duplicate]

Я столкнулся с этой ошибкой, пытаясь щелкнуть какой-то элемент (или его наложение, мне все равно), а другие ответы не сработали для меня. Я исправил его, используя API-интерфейс elementFromPoint DOM, чтобы найти элемент, который Selenium хотел, чтобы я нажал на него:

element_i_care_about = something() loc = element_i_care_about.location element_to_click = driver.execute_script( "return document.elementFromPoint(arguments[0], arguments[1]);", loc['x'], loc['y']) element_to_click.click()

Надеюсь, это поможет кому-то!

1644
задан Peter Mortensen 24 April 2016 в 11:17
поделиться

22 ответа

Существует замена на основе стандартов, DOMContentLoaded, которая поддерживается более 98% браузеров , хотя не IE8:

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

Нативная функция jQuery намного больше сложнее, чем просто window.onload, как показано ниже.

function bindReady(){
    if ( readyBound ) return;
    readyBound = true;

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", function(){
            document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
            jQuery.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", function(){
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", arguments.callee );
                jQuery.ready();
            }
        });

        // If IE and not an iframe
        // continually check to see if the document is ready
        if ( document.documentElement.doScroll && window == window.top ) (function(){
            if ( jQuery.isReady ) return;

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

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

    // A fallback to window.onload, that will always work
    jQuery.event.add( window, "load", jQuery.ready );
}
1064
ответ дан Abhi Beckert 24 August 2018 в 06:02
поделиться

Недавно я использовал это для мобильного сайта. Это упрощенная версия Джона Ресига из «Pro JavaScript Techniques». Это зависит от addEvent.

var ready = ( function () {
  function ready( f ) {
    if( ready.done ) return f();

    if( ready.timer ) {
      ready.ready.push(f);
    } else {
      addEvent( window, "load", isDOMReady );
      ready.ready = [ f ];
      ready.timer = setInterval(isDOMReady, 13);
    }
  };

  function isDOMReady() {
    if( ready.done ) return false;

    if( document && document.getElementsByTagName && document.getElementById && document.body ) {
      clearInterval( ready.timer );
      ready.timer = null;
      for( var i = 0; i < ready.ready.length; i++ ) {
        ready.ready[i]();
      }
      ready.ready = null;
      ready.done = true;
    }
  }

  return ready;
})();
13
ответ дан AlienWebguy 24 August 2018 в 06:02
поделиться

Это было хорошим решением https://stackoverflow.com/a/11810957/185565 бедных. В одном из комментариев рассматривался счетчик для спасения в случае чрезвычайной ситуации. Это моя модификация.

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);
8
ответ дан Community 24 August 2018 в 06:02
поделиться

Представленные здесь решения setTimeout / setInterval будут работать только в определенных обстоятельствах.

Проблема проявляется особенно в старых версиях Internet Explorer до 8.

Переменные, влияющие на успех из этих setTimeout / setInterval решений:

1) dynamic or static HTML
2) cached or non cached requests
3) size of the complete HTML document
4) chunked or non chunked transfer encoding

исходный (собственный Javascript) код, решающий эту конкретную проблему, находится здесь:

https://github.com/dperini/ContentLoaded
http://javascript.nwbox.com/ContentLoaded (test)

это код, из которого jQuery команда построила свою реализацию.

2
ответ дан Diego Perini 24 August 2018 в 06:02
поделиться

Я просто использую:

setTimeout(function(){
    //reference/manipulate DOM here
});

И в отличие от document.addEventListener("DOMContentLoaded" //etc, как в самом верхнем ответе, он работает еще в IE9 - http://caniuse.com/# search = DOMContentLoaded указывает только на IE11.

Например, перейдите в https://netrenderer.com/index.php , выберите Internet Explorer 9 из в раскрывающемся списке введите https://dexygen.github.io/blog/oct-2017/jekyll/jekyll-categories/liquid-templates/2017/10/22/how-jekyll-builds-site-categories.html. и нажмите «Render», и вы увидите что-то похожее на скриншот внизу этого сообщения.

См. следующий код Javascript, который я использую в заголовке, чтобы манипулировать стилем Jekyll «хакер» по своему вкусу - в частности, вы можете ссылаться на блок if (location.pathname !== rootPath), чтобы увидеть, как я вставляю ссылки Home и Blog Home, которые отображаются IE9 на сайт NetRenderer.

Интересно, что я наткнулся на это решение setTimeout в 2009 году: Проверяет готовность переполнения DOM? , который, вероятно, мог быть сформулирован немного лучше, как я подразумевал под используя более сложные подходы к различным схемам.

setTimeout(function() {//delay execution until after dom is parsed
    var containerEls = document.getElementsByClassName('container');
    var headingEl = containerEls[0].getElementsByTagName('h1')[0];
    var headerEl = document.getElementsByTagName('header')[0];
    var downloadsSectionEl = document.getElementById('downloads');
    var rootPath = "/";
    var blogRootPath = "/blog/";

    containerEls[0].style.maxWidth = '800px';
    containerEls[1].style.maxWidth = '800px';
    headingEl.style.margin = '0';
    headerEl.style.marginBottom = '7px';
    downloadsSectionEl.style.margin = '0';

    if (location.pathname !== rootPath) {
        downloadsSectionEl.appendChild(generateNavLink('Home', rootPath));
        if (location.pathname !== blogRootPath) {
            downloadsSectionEl.appendChild(document.createTextNode(' | '));
            downloadsSectionEl.appendChild(generateNavLink('Blog Home', blogRootPath));
        }
    }

    function generateNavLink(linkText, hrefPath) {
        var navLink = document.createElement('a');
        var linkTextNode = document.createTextNode(linkText);
        navLink.setAttribute('href', hrefPath);
        navLink.appendChild(linkTextNode);
        return navLink;
    }
});

3
ответ дан George Jempty 24 August 2018 в 06:02
поделиться
function onDocReady(fn){ 
    $d.readyState!=="loading" ? fn():document.addEventListener('DOMContentLoaded',fn);
}

function onWinLoad(fn){
    $d.readyState==="complete") ? fn(): window.addEventListener('load',fn);
} 

onDocReady обеспечивает обратный вызов, когда HTML dom готов к полному доступу / анализу / манипуляции.

onWinLoad обеспечивает обратный вызов, когда все загружено (изображения и т. д.)

  • Эти функции можно вызвать, когда захотите.
  • Поддерживает несколько «слушателей».
  • Будет работать в любом браузере.
0
ответ дан Jakob Sternberg 24 August 2018 в 06:02
поделиться

Этот подход является самым коротким способом, о котором я могу думать.

Решение, основанное на событии DOMContentLoaded, работает только в том случае, если сценарий загружен перед документом, тогда как предложенная здесь ленивая проверка обеспечивает выполнение кода всегда, даже в сценариях, загруженных динамически позже, точно так же, как документ JQuery готов.

Этот код совместим со всеми браузерами (включая некоторые устаревшие, вплоть до IE6 и Safari для Windows).

(function ready() {
    if (!document.body) {setTimeout(ready, 50); return;}
    // Document is ready here
})();
0
ответ дан Javier Rey 24 August 2018 в 06:02
поделиться

Для IE9 +:

function ready(fn) {
  if (document.readyState != 'loading'){
    fn();
  } else {
    document.addEventListener('DOMContentLoaded', fn);
  }
}
0
ответ дан Joaquinglezsantos 24 August 2018 в 06:02
поделиться

Попробуйте следующее:

function ready(callback){
    if(typeof callback === "function"){
        document.addEventListener("DOMContentLoaded", callback);
        window.addEventListener("load", callback);
    }else{
        throw new Error("Sorry, I can not run this!");
    }
}
ready(function(){
    console.log("It worked!");
});
0
ответ дан Judah rogan 24 August 2018 в 06:02
поделиться

Этот кросс-браузерный код вызовет функцию после готовности DOM:

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

Вот как это работает:

  1. Первая строка domReady вызывает метод функции toString для получения строкового представления функции, которую вы передаете, и переносит ее в выражение, которое сразу вызывает функцию.
  2. Остальная часть domReady создает элемент сценария с выражением и добавляет его в body документа.
  3. Браузер запускает теги сценариев, добавленные к body после готовности DOM.

Например, если вы это сделаете: domReady(function(){alert();});, следующее добавляется к элементу body:

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

Обратите внимание, что это работает только для пользовательских функций. Следующие действия не будут выполняться: domReady(alert);

4
ответ дан Max Heiber 24 August 2018 в 06:02
поделиться

Ответ jQuery был очень полезен для меня. С небольшим количеством исправлений он хорошо меня удовлетворил. Я надеюсь, что это поможет кому-то еще.

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 )
}
11
ответ дан Miere 24 August 2018 в 06:02
поделиться

Как насчет этого решения?

// 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();
};
3
ответ дан mike 24 August 2018 в 06:02
поделиться

Вот что я использую, это быстро и охватывает все базы, которые я думаю; работает для всего, кроме IE & lt; 9.

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

Кажется, что они улавливают все случаи:

  • срабатывает немедленно, если DOM уже готов (если DOM не является " загрузка ", но либо" интерактивный ", либо" полный ")
  • , если DOM по-прежнему загружается, он устанавливает прослушиватель событий, когда DOM доступен (интерактивный).

Событие DOMContentLoaded доступно в IE9 и во всем остальном, поэтому я лично считаю, что это нормально использовать. Перепишите объявление функции стрелки в обычную анонимную функцию, если вы не переставляете свой код с ES2015 на ES5.

Если вы хотите дождаться загрузки всех ресурсов, все изображения отображаются и т. Д., То используйте window.onload вместо этого.

1
ответ дан Olemak 24 August 2018 в 06:02
поделиться

Кросс-браузер (старые браузеры тоже) и простое решение:

var docLoaded = setInterval(function () {
    if(document.readyState !== "complete") return;
    clearInterval(docLoaded);

    /*
        Your code goes here i.e. init()
    */
}, 30);

Отображение оповещения в jsfiddle

9
ответ дан Pawel 24 August 2018 в 06:02
поделиться

Редактирование редактирования @duskwuff для поддержки Internet & nbsp; Explorer & nbsp; 8 тоже. Разница - это новый вызов функционального теста регулярного выражения и setTimeout с анонимной функцией.

Кроме того, я установил тайм-аут на 99.

function ready(f){/in/.test(document.readyState)?setTimeout(function(){ready(f);},99):f();}
184
ответ дан Peter Mortensen 24 August 2018 в 06:02
поделиться

Этот вопрос задавался довольно давно. Для любого, кто только видит этот вопрос, теперь есть сайт под названием «вам может не понадобиться jquery» , который ломается - по уровню поддержки IE требуется - все функции jquery и предоставляет некоторые альтернативные, более мелкие библиотеки .

Готовый сценарий документа IE8 в соответствии с вам может не понадобиться 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();
        });
}
67
ответ дан RevanthKrishnaKumar V. 24 August 2018 в 06:02
поделиться

Редактировать:

Ниже приведена жизнеспособная замена для jQuery ready

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

Взято из https://plainjs.com/javascript/events/running-code -when-the-document-is-ready-15 /


Поскольку принятый ответ был очень далек от завершения, я сшил вместе «готовую» функцию, такую ​​как jQuery.ready() на jQuery 1.6.2 source:

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

Как использовать:

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

Я не уверен, насколько функциональен этот код, но он отлично работал с моими поверхностными тестами. Это потребовалось довольно долгое время, поэтому я надеюсь, что вы и другие могут извлечь из этого выгоду.

PS: Я предлагаю компилировать его.

Или вы можете использовать http://dustindiaz.com/smallest-domready-ever :

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

или встроенная функция, если вам нужно только поддерживать новые браузеры (в отличие от jQuery ready, это не будет работать, если вы добавите это после загрузки страницы)

document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})
290
ответ дан Timo Huovinen 24 August 2018 в 06:02
поделиться

Если вам не нужно поддерживать очень старые браузеры, это способ сделать это, даже если ваш внешний скрипт загружен атрибутом async :

HTMLDocument.prototype.ready = new Promise(function(resolve) {
   if(document.readyState != "loading")
      resolve();
   else
      document.addEventListener("DOMContentLoaded", function() {
         resolve();
      });
});

document.ready.then(function() {
   console.log("document.ready");
});
1
ответ дан user4617883 24 August 2018 в 06:02
поделиться

Вот самый маленький фрагмент кода для проверки готовности DOM, который работает во всех браузерах (даже IE 8):

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

См. этот ответ .

8
ответ дан Community 24 August 2018 в 06:02
поделиться

Функция готовности в jQuery делает несколько вещей. Честно говоря, я не вижу, чтобы это заменило его, если у вас не было удивительно небольшой выход с вашего сайта. jQuery - довольно маленькая библиотека, и она обрабатывает всевозможные кросс-браузерные вещи, которые вам понадобятся позже.

В любом случае, здесь мало смысла публиковать его, просто откройте jQuery и посмотрите по методу bindReady.

Он начинается с вызова либо document.addEventListener("DOMContentLoaded"), либо document.attachEvent('onreadystatechange') в зависимости от модели события и продолжается оттуда.

0
ответ дан Judah rogan 24 August 2018 в 06:02
поделиться

Если вы загружаете jQuery у основания BODY, но возникают проблемы с кодом, который записывает jQuery (& lt; func>) или jQuery (document) .ready (& lt; func>), проверьте jqShim в Github.

Вместо того, чтобы воссоздать свою собственную функцию готовности документа, она просто удерживает функции до тех пор, пока не будет доступна jQuery, а затем продолжит работу с jQuery, как ожидалось. Точка перемещения jQuery в нижней части тела - это ускорить загрузку страницы, и вы все равно можете выполнить ее, вставив jqShim.min.js в начало вашего шаблона.

В итоге я написал это кода, чтобы переместить все сценарии в WordPress в нижний колонтитул, и только этот код прокладки теперь находится прямо в заголовке.

184
ответ дан Peter Mortensen 24 August 2018 в 06:02
поделиться

Решение для бедных:

var checkLoad = function() {   
    document.readyState !== "complete" ? setTimeout(checkLoad, 11) : alert("loaded!");   
};  

checkLoad();  

View Fiddle

Добавил этот, немного лучше, я предполагаю, собственный объем и нерекурсивный

(function(){
    var tId = setInterval(function() {
        if (document.readyState == "complete") onComplete()
    }, 11);
    function onComplete(){
        clearInterval(tId);    
        alert("loaded!");    
    };
})()

Показать Fiddle

67
ответ дан RevanthKrishnaKumar V. 24 August 2018 в 06:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: