Подтвердить что ты не робот

Trigger $document.ready(так что код AJAX, который я не могу изменить, выполняется)

Мои требования следующие:

  • У меня есть богатая веб-страница, которая в определенный момент загружает кучу HTML в div через AJAX.
  • HTML, который я получаю, имеет javascript (<script>...</script>)
  • Загруженный javascript содержит $('document').ready( ... ) parts
  • Я не могу изменить полученный javascript; это происходит из внешнего lib
  • У меня есть функция javascript, которая вызывается при загрузке AJAX. Я пытаюсь "обмануть" его выполнение:

    function AjaxLoaded() {
      $('document').trigger('ready');
    }
    

Это не режет, боюсь.

Я видел несколько ответов о переполнении стека, которые "уклоняются" от этого вопроса, изменяя код который возвращается на AJAX (сделать его функцией и вызвать его после загрузки, или просто удалить $(document).ready()). Мне нужно подчеркнуть, что я не могу изменить полученный код в этом случае.

4b9b3361

Ответ 1

В некоторых исследованиях я создал способ заставить его работать.

вот мой тест, который показывает, что он работает: http://www.antiyes.com/test/test2.php

вот соответствующий код:

<script>
    // easy copy of an array
    Array.prototype.copy = function() {
        return [].concat(this);
    };

    // this function is added to jQuery, it allows access to the readylist
    // it works for jQuery 1.3.2, it might break on future versions
    $.getReadyList = function() {
        if(this.readyList != null)
            this.myreadylist =  this.readyList.copy();      
        return this.myreadylist;
    };

    $(document).ready(function() {
        alert("blah");
    });

</script>

<script>

    // this should be added last so it gets all the ready event
    $(document).ready(function() {
        readylist = $.getReadyList();
    });

</script>

то в теле я:

<input type="button" onclick="$(readylist).each(function(){this();});" value="trigger ready" />

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

похоже, что код ниже не работает:

function AjaxLoaded() {
    $(document).trigger('ready');
}

отбросить кавычки вокруг document.

Ответ 2

Так как jQuery readyList не отображается с версии 1.4 (обсуждаемый здесь), то прекрасные решения, описанные выше, не работают.

Посредством этого можно создать собственный готовый список, переопределив исходный метод jQuery. Это необходимо сделать до того, как загрузятся другие скрипты, которые используют оригинальный метод. В противном случае просто тот же код, что и Джон/Кикито:

// Overrides jQuery-ready and makes it triggerable with $.triggerReady
// This script needs to be included before other scripts using the jQuery-ready.
// Tested with jQuery 1.7
(function(){
var readyList = [];

// Store a reference to the original ready method.
var originalReadyMethod = jQuery.fn.ready;

// Override jQuery.fn.ready
jQuery.fn.ready = function(){
if(arguments.length && arguments.length > 0 && typeof arguments[0] === 'function') {
  readyList.push(arguments[0]);
}

// Execute the original method.
originalReadyMethod.apply( this, arguments );
};

// Used to trigger all ready events
$.triggerReady = function() {
  $(readyList).each(function(){this();});
};
})();

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

Ответ 3

На всякий случай, если кому-то это понадобится, я немного уточнил решение Джона, чтобы его можно было использовать непосредственно в качестве включенного файла javascript.

// jquery_trigger_ready.js
// this function is added to jQuery, it allows access to the readylist
// it works for jQuery 1.3.2, it might break on future versions
$.getReadyList = function() {
  if(this.readyList != null) { this.myreadylist = [].concat(this.readyList); }
  return this.myreadylist;
};

$(document).ready(function() {
  readylist = $.getReadyList();
});

$.triggerReady = function() {
  $(readylist).each(function(){this();});
}

Включение этого файла после включения jquery позволяет запускать готово, вызывая $.triggerReady(). Пример:

<html>
  <head>
    <title>trigger ready event</title>
    <script src="test2_files/jquery-1.js" type="text/javascript"></script>
    <script src="jquery_trigger_ready.js" type="text/javascript"></script>
  </head>
  <body>
    <input onclick="$.triggerReady();" value="trigger ready" type="button">
    <script type="text/javascript">
      $(document).ready(function(){
          alert("blah");
      });
    </script>
  </body>
</html>

Кстати, я хотел сделать это $(document).triggerReady(). Если кто-то захочет поделиться некоторыми советами по этому поводу, плохо оцените.

Ответ 4

У нас была та же проблема, и мы решили ее другим способом.

Вместо

$(document).ready(function () {
  $('.specialClass').click(....

Мы использовали:

$(document).bind('ready', function(event) {
  $('.specialClass', event.target).click(..

jQuery будет запускать "готовое" событие в документе, как обычно. Когда мы загружаем содержимое нового div через ajax, мы можем написать:

loadedDiv.trigger('ready')

И все инициализации выполняются только на div, получая ожидаемое.

Ответ 5

Симоне Джанни Ответ Я думаю, самый элегантный и чистый.

и вы можете даже упростить его, чтобы стать еще более простым в использовании:

jQuery.fn.loadExtended = function(url,completeCallback){
    return this.load(url,function(responseText, textStatus, XMLHttpRequest) {
        if (completeCallback !== undefined && completeCallback !== null) {
            completeCallback(responseText, textStatus, XMLHttpRequest);
        }
        $(this).trigger("ready");
    });
};

Итак, теперь вместо использования:

$(".container").load(url,function(responseText, textStatus, XMLHttpRequest) {
    $(this).trigger("ready");
});

вы можете просто использовать:

$(".container").loadExtended("tag_cloud.html");

или

$(".container").loadExtended("tag_cloud.html",function(){ 
    alert('callback function') 
});

Это имеет преимущество только при применении триггера на div, который обновляется.

Ответ 6

Если ваш новый загруженный HTML содержит элементы <script> и вы пытаетесь вставить его в основной HTML с чистым JS (element.innerHTML = newHTML), то обработчики $(document).ready в newHTML и упакованные функции, такие как (function() { /* some functions */ })();), не будут выполняться, потому что JQuery unbind 'ready' событие после первого запуска, и вы не можете запустить его повторно. PS. Но вы можете использовать $.holdReady(true) и запускать при необходимости.

Итак, попробуйте вставить код с помощью метода jquery, $(element).html(newHTML). Это решило аналогичную проблему для меня, кажется, jquery обрабатывать JS перед вставкой. Используя этот метод, вы также не увидите элементы <script> среди узлов DOM (например, в браузере Elements Inspector).