触发$ document.ready(所以我执行的AJAX代码无法修改)

时间:2010-02-10 15:35:07

标签: javascript jquery ajax

我的要求如下:

  • 我有一个丰富的网页,在某个时刻通过AJAX在div中加载一堆HTML。
  • 我检索的HTML确实有javascript(<script>...</script>
  • 检索到的javascript包含$('document').ready( ... )部分
  • 无法修改检索到的javascript;它来自外部库
  • 我有一个加载AJAX时调用的javascript函数。我试图通过这样做来“欺骗”执行:

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

这不会削减它,我害怕。

我在Stack Overflow上看到several responses通过更改AJAX上返回的代码来“回避”这个问题(将其作为一个函数并在加载后调用它,或者只是删除$(document).ready())。我需要强调的是,我不能在这种情况下更改检索到的代码。

6 个答案:

答案 0 :(得分:21)

在一些研究中,我创造了一种让它发挥作用的方法。

这是我的测试,显示它正常工作: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附近。

答案 1 :(得分:11)

由于jQuery readyList从1.4版开始未公开(讨论here),上面的好解决方案已经破解。

解决这个问题的方法是通过覆盖原始的jQuery-ready方法来创建自己的readyList。这需要在加载使用原始ready方法的其他脚本之前完成。否则只是与John / Kikito相同的代码:

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

我不确定是否建议覆盖ready方法。随意建议我。我自己还没有发现任何副作用。

答案 2 :(得分:9)

万一有人需要它,我稍微改进了John的解决方案,因此它可以直接用作包含的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()。如果有人愿意就此提出一些建议,那就不胜感激了。

答案 3 :(得分:6)

我们遇到了同样的问题并以另一种方式解决了。

而不是

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

我们用过:

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

jQuery将像往常一样在文档上触发“就绪”事件。当我们通过ajax加载新div的内容时,我们可以写:

loadedDiv.trigger('ready')

并且只在div上执行所有初始化,获得预期的内容。

答案 4 :(得分:2)

Simone Gianni的回答我认为这是最优雅和最干净的。

您甚至可以简化它以使其更易于使用:

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应用触发器。

答案 5 :(得分:0)

如果新加载的HTML包含<script>个元素,并且您尝试将其插入带有纯JS(element.innerHTML = newHTML的主HTML中,则newHTML的$(document).ready处理程序和包装的函数如({{ 1}}-将不会执行,因为JQuery在第一次触发后会取消绑定'ready'事件,并且您无法重复触发它。PS。但是您可以使用function() { /* some functions */ })();并在需要时触发。

因此,请尝试使用jquery方法插入代码$.holdReady(true)。这为我解决了类似的问题,似乎在插入之前jquery处理js。使用这种方法,您也不会在DOM节点中看到$(element).html(newHTML)元素(例如,在浏览器的Elements Inspector中)。