3

Using jquery, I am swapping some content in a web page by use of jquery's .load() function. I want to trigger an event immediately once the content has actually been loaded, but not before and not after. I'm up for any graceful solution! Why? In this instance, I'm doing the old "fade out, swap content, fade in" approach. My problem? I want to fade back in AS SOON AS the new content is loaded.

Caveats:

  • Using a callback function as in $('#object').load(url, callback) triggers as soon as .load() function successfully executes (before the content is actually loaded). Useless here.
  • Using a timed delay for fading back in is not a graceful solution. Very "clunky", especially for those with faster Internet connectivity.
  • JavaScript's onload event trigger does not work, as the element that .load() is altering has already loaded into the HTML DOM.
  • jquery's .ready() function also does not work, as the actual element is already loaded.
  • I do not want to create an onload or .ready() sub-container element, because that's a workaround for what I'm actually trying, though it might be as graceful or more.

How can I fire a function when (and only when) the new .load() content is finally loaded, just like JavaScript's onload event does? Thanks much.

EDIT As it turns out, the jquery .load() function is working flawlessly, and I'm approaching this wrong.

  • Once the .load() function completes successfully, it calls any "callback" function included by the programmer, just like any other jquery function that accepts a callback as one of its "arguments".
  • The .load() function is complete once it either errors or successfully begins the HTML replacement and loading of new content, but that is IT! The content will then take however long it takes to load, but your .load call is already complete before that. Therefore, expecting the callback to run after the .load content has loaded will only disappoint you. ;)

I hope others can learn from this just as I did, including those who thought what I thought was the case. Proof: as stated in the jquery ajax .load page, the callback is executed when the request completes, not when the load completes. Eureka. Whoops. /EDIT

rgettman
  • 176,041
  • 30
  • 275
  • 357
Slink
  • 353
  • 1
  • 4
  • 14
  • Guide me, oh gurus. I hope my diligence pleases you. I really tried to cover all the angles, but I'm brand new to jquery as of this week, and I'm rather novice with JavaScript. Thank you! – Slink Jul 20 '12 at 23:51
  • The documentation for .load() in jQuery says: If a "complete" callback is provided, it is executed after post-processing and HTML insertion has been performed. What are you seeing that indicates it is not working as documented? – MichaC Jul 21 '12 at 00:03
  • Thanks for bringing that to my attention. It still seems like the callback is firing before the new HTML content is successfully replaced. This is easily tested with a JavaScript `alert("debug")` callback, which I tried. I might have to take a second look, but IIRC, before the browser shows the updated content, the callback fires. – Slink Jul 22 '12 at 02:15

3 Answers3

1

Try using a different method rather than load(), I would suggesting using get(). Something like this may be more useful to you...

var jqxhr = jQuery.get(url,vars);

jqxhr.success(function(data){
    # This will only be called once the remote content has been loaded in
    # The data will then be stored in the data param and can be used within your site
});

jqxhr.error(function(data){
    # Something went wrong, never mind lets just handle it gracefully below...
});

I hope this is a solution to your problem!

For more information see http://api.jquery.com/jQuery.get/

I have quickly created this function below that may be of help to you... its not refined!

jQuery.fn.loadNewData = function() {

    var object = jQuery(this);
    var jqxhr = jQuery.get(arguments[0]);

    // check for success
    jqxhr.success(function(data) {
        // load the data in
        object.html(data);
    });

    jqxhr.error(function(){
        alert('Failed to load data');
    });
}

Using this you can call how similarly to how you would call the load() function.

jQuery('#object').loadNewData(url);
Chris
  • 1,939
  • 1
  • 19
  • 38
  • It is worth adding though that you will of-course need to add some bits in here to replace the existing contents of your content box. This can be easily achieved by using jQuery('#object').html(data); Using this method you can also add some sort of fancy fade to it so the content doesnt load in a 'clunky' way. – Chris Jul 21 '12 at 00:00
  • Okay. Looks really good. Gonna check it out. Also, my original approach doesn't seem to work with Opera. Hmmm... Thanks. – Slink Jul 22 '12 at 02:13
  • Great, I have modified the function slightly above so it works properly now if you want to use it! I hope this provides a good solution for you! – Chris Jul 22 '12 at 07:43
  • Thanks. I'm starting to think I should just be using an ` – Slink Jul 23 '12 at 17:42
  • 1
    Nevermind that — ` – Slink Jul 23 '12 at 20:07
0

I think you might be misinterpreting what you are seeing. Depending on the browser you are using you won't see the new elements in the browser if you pop up an alert in the callback because it won't rerender the DOM until you cede control back to the browser. That doesn't mean you can't grab the new elements from the DOM and start fading them in. Take the following jsfiddle: http://jsfiddle.net/ttb55/8/ in Chrome it will show the first div when the second alert is up, then fade in the second div. In IE it won't show the first div when the second alert is up, this is the state I think you are in after load during the callback, but it still works once you hit ok because everything was in the DOM as promised.

MichaC
  • 2,834
  • 2
  • 20
  • 20
  • I definitely considered that, and I promise that the callback is *not* waiting for the new content to finish loading. The .load callback is firing as soon as the command is complete, which is apparently before the external HTML content actually loads (a separate concern). This would be difficult to demonstrate without accessing using a slow IP connection. I will PM you and whoever else wants it with my own example (please don't share the URL - I don't want it posted.) Thanks! – Slink Jul 23 '12 at 18:42
  • Also: Frankly, I think I'm using the wrong approach, as the other answer said. ;) Also, your jsfiddle example is not applicable, as you aren't using the `.load` funciton! :) I understand how the callback is supposed to fire AFTER the original function is complete, which is exactly what the `.load` function *is* doing: completing *before* the new external HTML content has finished loading, which is a separate event. // I think my best approach is to simply fade the current element, replace it with a new ` – Slink Jul 23 '12 at 18:44
  • Oops, no PM system here: I'd have to make a fiddle and share it for example, but IDK if `.load` will work from jsfiddle! :-/ – Slink Jul 23 '12 at 18:49
  • That's why I didn't end up using .load in my example :), I just looked in load to see what it used to load up the HTML (.html) and used that to create the fiddle to demonstrate my point. I'm looking at the implementation of .load in jQuery, and it definitely doesn't call the callback until after it loads the HTML. However, I see that you found a solution to your problem so I won't worry about investigating further. – MichaC Jul 23 '12 at 23:07
0

Upon reading the jQuery docs pages for jQuery.get() and jQuery.load(), the callback argument is quoted as the following:

"A callback function that is executed if the request succeeds."

Let me stress the terms "request" and "succeeds". The request may succeed, but that does not mean that the content is loaded. Same problem as .load() — the functions aren't built the way I was thinking.

If I want to trigger an event once the new content finally loads, I'll need to take a different approach.

  • I could use the JS onload event, and trigger it by completely replacing an HTML element (having the replaced code contain an onload property). EDIT: Note that using HTML iframe elements is pretty awful, primitive, and "clunky". I just need to find a better way to trigger a function as soon as loading the new content finishes.
  • Also, I could use jQuery to check the .ready() state of new content, but ("AFAIK" / as far as I know) that will only work if the checked content is a new HTML element, not a preexisting HTML element whose interior content is changed. The jQuery .ready() status of any preexisting element will (AFAIK) already be shown as "ready" despite if new content is loading. Perhaps I am wrong about this, and I would like to be corrected if so.

Unless otherwise notified, this answer will be marked as the correct one. The original question was mistaken that .load() was all I needed. Cheers!

Slink
  • 353
  • 1
  • 4
  • 14
  • OH MAN, all I had to do was to include a script in the content to be loaded, and the script executes. Example: ``. It works so far... – Slink Jul 23 '12 at 20:16
  • I would still recommend the best way to do this would be to use `.get()` The method you have stated above isn't really best practise and doesn't need to be done. Instead of the `success` callback you can use the `complete` callback which will execute once the request has completed. From my experience, the `success` callback always contains the required data. The above function has been tested and worked when I was testing it. +1 for iFrames being primitive and clunky though, it's not modern development at all! – Chris Jul 24 '12 at 10:17