views:

2171

answers:

4

My requirements are the following:

  • I've got a rich webpage that at a certain moment loads a bunch of html on a div, via AJAX.
  • The HTML I retrieve does have javascript (...)
  • The retrieved javascript contains $('document').ready( ... ) parts
  • I can not modify the retrieved javascript; it comes from an external lib
  • I've got a javascript function that is called when the AJAX is loaded. I'm trying to "trick it" into executing by doing:

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

That doesn't cut it, I'm afraid.

I've seen several responses on stackoverflow that "evade" this question by changing the code that is returned on the ajax (make it a function and call it after loading, or just remove the $(document).ready() ). I need to stress out that I can't change the retrieved code on this case.

+10  A: 

Afer some research i created a way to get it to work.

here is my test that shows it working: http://www.antiyes.com/test/test2.php

here is the relevant code:

<script type="text/javascript" charset="utf-8">

    Array.prototype.copy = function() // easy copy of an array
    {
        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 type="text/javascript" charset="utf-8">

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

</script>

then in the body I have:

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

basically what i did was add a function to jQuery that copies the readyList before it's cleared out, then it will be available to be used by you.

it looks like the code below doesnt work:

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

drop the quotes around document.

John Boker
Makes sense since document is an object and not an element. +1 for research.
Mark Schultheiss
John, you totally blew my mind with this one. This is definitively a +1 and correct answer! Just one minor comment: would you mind including the code on the answer, in addition to providing a link to the test page? This is too good to be lost if in two years you change your hosting :)
egarcia
@egarcia will do
John Boker
thanks a lot, john!
egarcia
Great job on this work-around; extremely useful. Also, very good job on explaining it and providing a working demo. Thank you.
Jessy Houle
+1  A: 

Just in case anyone needs it, I refined John's solution a bit so it could be used directly as an included javascript file.

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

Including this file after including jquery allows for triggering ready by invoking $.triggerReady(). Example:

<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>

By the way, I wanted to make it $(document).triggerReady(). If anyone is willing to share some advice on that, ill be appreciated.

egarcia
+1  A: 

We had the same problem and solved it another way.

Instead of

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

We used :

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

jQuery will trigger a "ready" event on the document as usual. When we load the content of a new div via ajax, we can write:

loadedDiv.trigger('ready')

And have all the initialization performed only on the div, obtaining what expected.

Simone Gianni
+1  A: 

Simone Gianni's Answer I think is the most elegant and clean.

and you can even simplify it to become even more easy to use:

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

So, now instead of using:

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

you can just use:

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

or:

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

This has the advantage of only applying the trigger on the div that's being updated.

Uoli