Триггер $ document.ready (поэтому выполняется код AJAX, который я не могу изменить) - PullRequest
34 голосов
/ 10 февраля 2010

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

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

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

Боюсь, это не значит.

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

Ответы [ 5 ]

21 голосов
/ 10 февраля 2010

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

вот мой тест, который показывает, что он работает: 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 функцию, которая копирует readyList до его очистки, а затем он будет доступен для использования вами.

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

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

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

11 голосов
/ 14 ноября 2011

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

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

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

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

9 голосов
/ 14 февраля 2010

На всякий случай, если это кому-нибудь понадобится, я немного усовершенствовал решение Джона, чтобы оно могло использоваться непосредственно как включенный файл 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(). Если кто-то готов поделиться каким-то советом по этому поводу, я буду признателен.

6 голосов
/ 14 июля 2010

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

Вместо

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

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

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

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

loadedDiv.trigger('ready')

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

2 голосов
/ 08 сентября 2010

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

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

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

Преимущество этого метода заключается в том, что он применяет только триггер к обновляемому элементу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...