1

On our website we draw a wiggly line using HTML canvas. Before the wiggly line is drawn, I measure the height of the page being loaded using the code at Measure height of element after content is fully loaded and then callback to my drawlines.js script which takes the dimensions of the finished area and draws the wiggly line.

This works fine in Chrome and Firefox but IE9 and 10 seem to intermittently fail to draw the lines on pages such as http://www.petersencreative.com/design. I can't see anything failing in the inspector so I'm at a loss as how to diagnose the problem, let alone fix it.

I appreciate this is a fairly specific problem, but would be really grateful of any pointers.

EDIT: When the code fails in IE, it only ever gets to Alert 0.

function watchForBottomDimension(element, callback) {
    var $element, images, loaded;

    // Get a jQuery wrapper for `element`
    $element = jQuery(element);
    alert('0');
    // Find the images within it that aren't loaded yet
    images = $element.find("img").filter(function(index, img) {
        return !img.complete;
    });

    // Find any?
    if (images.length === 0) {
        // No, we're done -- call the callback asynchronously for
        // consistency with the case below where we have to wait
        alert('1');
        setTimeout(done, 0);
    }
    else {
        // We're waiting for some images, do that
        loaded = 0;
        images.load(function() {
            // One of them loaded; was it the last one?
            if (++loaded === images.length) {
                // Yup, we're done
                alert('2');
                done();
            }
        }); 
    }

    // Handle completion
    function done() {
        var top, height, bottom;

        top = $element.offset().top; // Vert offset of element
        height = $element.outerHeight(true); // Height of element

        // Offset to bottom of element
        bottom = top + height;

        // Call the callback with the value

        callback(element, bottom);
    }
}

This function is within http://www.petersencreative.com/templates/320andup/js/drawlines.js

Pete

Community
  • 1
  • 1
Jeepstone
  • 2,591
  • 5
  • 22
  • 38
  • Have you been able to ensure that at the very least the callback is firing? The problem may not be with your code. – jmccarthy Aug 06 '13 at 15:58
  • Good thinking. I'll take a look now. – Jeepstone Aug 06 '13 at 16:01
  • Looks like it's not making it to the callback. I've added the js above. Alert 0 always fires, but it doesn't ever fire done(). Could it be where I'm checking for images that aren't loaded yet? – Jeepstone Aug 06 '13 at 16:10
  • 1
    Don't use `alert()` for debugging! It interferes with your debugging asynchronous operations. Use `console.log()` or the `debugger;` statement instead. Especially `console.log()` when you want the code to run as similarly as possible to the way it would without any debugging code. – Michael Geary Aug 06 '13 at 16:29
  • Point taken. I wonder if it's something to do with http://css-tricks.com/snippets/jquery/fixing-load-in-ie-for-cached-images/ The page often works if you reload it, it's just the first time you hit it? – Jeepstone Aug 06 '13 at 16:39
  • Think this is a IE image cache issue. If I console.log img.complete I normally get a string of true for each image, but when the script fails it's when I get a false even through the image is definitely there. – Jeepstone Aug 06 '13 at 17:04
  • Can you point to the specific JS file in that website has the image-detection code in it? – Michael Geary Aug 06 '13 at 17:13
  • The file that works out the size of the page and draws the lines is at http://www.petersencreative.com/templates/320andup/js/drawlines.js. This originally came to light as the bottom position of the lines can vary by up to 30px or so. There were circumstances where the lines were draw over the top of the page content so I needed to definitively know where the page ended. – Jeepstone Aug 07 '13 at 08:00

2 Answers2

1

Are you loading these images via <img> tags in the HTML source, or by dynamically creating them in JavaScript?

If they are in the HTML source you may have trouble.

If you're creating them in JavaScript, then you should be able to detect when they are loaded by setting the load handler for each Image before setting its src attribute:

var img = document.createElement( 'img' );
img.onload = function() { /* ... */ };
img.src = 'test.png';
element.appendChild( img );

or:

$('<img>')
    .load( function() {
        /* ... */
    })
    .attr( 'src', 'test.png' )
    .appendTo( $element );

Or for that matter you could use event delegation:

// Before loading any of the images
$(element).on( 'load', 'img', function() {
    /* ... */
});
// Now you can start creating and loading the image elements

When you set up the event handler first, should be called in all cases, even in IE with an already-cached image.

This also makes your load-detection code much more straightforward: You don't have to have special code to test for images that are already loaded, you simply rely on the load event for all of them.

Michael Geary
  • 28,450
  • 9
  • 65
  • 75
  • Hi Michael, thank you for your reply. The images are in the HTML source. I wonder if I might need to resort to some browser sniffing and then bypass the calculation and rely on the browser working it out correctly. – Jeepstone Aug 09 '13 at 08:48
0

I have since found a very useful js library that handles when IE has loaded images which is based on the work that Paul Irish did on the topic.

https://github.com/desandro/imagesloaded

Jeepstone
  • 2,591
  • 5
  • 22
  • 38