1

I have the following jQuery to load status to a profile page using a ul with li status items. The each() takes items from a JSON callback and the load() is supposed to ensure that the image is available before the li is created:

(showpic() gives me a well-formed url to use.)

function showStatus(data){
var jsondata = $.parseJSON(data);
var testText = "";

$('#doNews').empty();
$('#doNews').append($('<ul/>', {"class": "newsList", id: "theNews"}));
$.each(jsondata, function(i, item){
    $('<img src="' + showpic(item[3]) + '" class="newsImage">')
    .load(function(){
        $(this)
            .appendTo($('#theNews'))
            .wrap($('<li>', {"class": "newsItem"}))
            .closest('li')
            .append(item[5])
      });
});

$("#statustext").val('');
}

the problem is that the status feed now seems to be written to the page in the order the images load. i.e., instead of being written according to the JSON item order, the li s are written in the order of loaded images (this has the effect of grouping status by user, not writing it out by date, as in the JSON).

So... how would I both write items in the JSON order and still wait for the img to load?

By the way, I looked at this qn: jQuery each() and load() ordering

and it seems to be on the right track, but when I tried using hide() and then show()inside the load() function, it never seemed to be called, and the img remained hidden. Please give me a simple example if this is the solution you suggest.

Thanks!

Community
  • 1
  • 1
grooble
  • 617
  • 1
  • 8
  • 27

1 Answers1

2

Either:

1) Maintain a counter & timeout, count the # of images to load at start, create the items as "hidden", countdown the number of unloaded as they load, then (when counter hits 0 or timer times out) display everything;

or:

2) Create the items as hidden, and show them in the 'load' event. Items will appear in arbitrary order, but will end up being correctly ordered.

Here's a possible example: your code isn't very clear as to what structure is being built & where appended, so this is just a rough (but clearly coded) outline.

Try using intermediate variables more, rather than vast fabulous jQuery constructions, in your own. It will help you debug it.

console.log('loading news items');
$.each( jsondata, function(i, item){ 
    console.log('  item', showpic(item[3]), item[5]);
    var img = $('<img src="' + showpic(item[3]) + '" class="newsImage" >');
    var element = img.wrap($('<li>', {"class": "newsItem", "style": "display:none;"}))
        .closest('li')
        .append(item[5]);
    element.appendTo( $('#theNews'));

    // when the IMG loads, find it's surrounding LI.. and show it.
    img.load( function(){
        console.log('  loaded', $(this).attr('src'));
        $(this).closest('li').show();
    });
    // put a timer & show it anyway after 8s, if img still hasn't loaded.
    element.delay( 8000).show(0);
});

You will also notice logging in the code. Logging is good software practice. Console.log is not available on IE, so you should eventually shim it or use a small library function of your own.

Fundamentally, you have to get away from adding to the DOM inside the 'load' event. That's what's causing the mis-ordering. Add to the DOM in the jsondata each() function, or in a separate well-structured bit of code that guarantees correct ordering.

Thomas W
  • 13,940
  • 4
  • 58
  • 76
  • So, can you walk me through this? The problem I had before was that if I didn't add to the DOM inside the load(), then it would be created before the pics loaded and I only had a few images instead of 20. Also looking at this answer: stackoverflow.com/questions/476679/… If I use preload(myImages), does it too have to go inside a load()? – grooble Jul 28 '13 at 04:47
  • I already said above, create the DOM elements as hidden (`style='display:none;'`) in your each() handler. Did you actually try it? – Thomas W Jul 28 '13 at 05:04
  • jQuery doesn't have a preload() function, and the hyperlink in your comment doesn't work. In this case I wouldn't see the applicability of pre-loading, as there is no point in time when you know what you need to load, _before you actually need to load it_. Thus, in your situation, there is no "pre". Walk you through this? How about you try yourself & post how far you get. This site is not about writing code for you. – Thomas W Jul 28 '13 at 05:08
  • http://stackoverflow.com/questions/476679/preloading-images-with-jquery Sheesh. No need to get shirty about it. My guess is this is one of those "easy when you know how" situations. And, in case you hadn't noticed, most *answers* on this site have code samples, not just vague explanatory text. I have been trying a lot of different things - posting here is very much a last resort. So getting back to the question, $.each(jsondata, function(i, item){ $('') creates a hidden img. How would I load it? Thank you. – grooble Jul 28 '13 at 05:28
  • Thx for the link & good that you are researching. Please see example code to adapt for your solution. – Thomas W Jul 28 '13 at 08:03