0

I'm writing a rather complex AJAX driven menu with multiple levels that animate around allowing a user to navigate a complicated tree structure at some point I had to add a function that auto centers (vert and horz) the images associated with each item on the menu tree. In order to measure the images and position them accordingly I must first write them to a hidden div ("#tempHolder") once they .load() I can then get their dimensions, calculate my offsets and then write the images to the DOM in the appropriate place.

This all works A Okay in the standards compliant browsers but IE7-8 seem to only process the .load() command when they feel like it. (homepage the menu loads okay, first visit to a sub-page breaks the menu, refreshing said page fixes it again...etc.). I restructured my function to make the .load() declaration early because of the advice I read here (http://blog.stchur.com/2008/02/26/ie-quirk-with-onload-event-for-img-elements/) but that doesn't seem to have worked. I also added e.preventDefault because of a stackOverflow thread that said this might prevent IE from caching my load statements.

Here is the function causing the issues:

 if (this.imagePath != "") {

            runImage = function (imagePath, $itemEle) {

                var $itemEleA = $itemEle.find('a');
                var image = new Image();

                //$thisImage = $(image);

                $(image).load(function (e) {

                    //alert('image loaded')
                    $(image).evenIfHidden(function (element) {
                        //alert('even if hidden');
                        ////////////console.log($thisImage);
                        var elementWidth = element.width();
                        var elementHeight = element.height();

                        this.imageHeight = elementHeight;
                        this.imageWidth = elementWidth;


                        //alert('widthoffset = ' + widthOffset + 'imagewidth = ' + imageWidth + 'this.imageWidth = ' + this.imageWidth + 'elementWidth = ' + elementWidth);

                        var imagePaddingWidth = 230 - imageWidth;
                        var widthOffset = imagePaddingWidth / 2;
                        widthOffset = widthOffset + "px";

                        element.css("left", widthOffset);

                        var imagePaddingHeight = 112 - imageHeight;

                        if (imagePaddingHeight < 0) {
                            var heightOffset = imagePaddingHeight;
                            heightOffset = heightOffset + "px";

                            element.css("top", heightOffset);

                        }
                        if (imagePaddingHeight > 0) {
                            var heightOffset = imagePaddingHeight - 18;
                            heightOffset = heightOffset + "px";

                            element.css("top", heightOffset);
                        }

                    });

                     $(this).appendTo($itemEleA); 

                    e.preventDefault();
                    return image;
                });

                image.src = imagePath;

                //var tempvar = $itemEle.find('a');
                $(image).appendTo("#tempHolder");
            }

            this.image = runImage(this.imagePath, $itemEle);
        }

Since this is for a big client and the site is not yet live I can't show the site but I'll try to throw up some screen shots later.

Any help is greatly appreciated.

Chris
  • 31
  • 2
  • Still very interested in a solution, but I have a client review this afternoon and in the interest of keeping the my hair out of my hands and preserving some semblance of my sanity I have simply moved the measuring of images to the backend. The dimensions are now provided in the menus JSON feed subverting the issue entirely. – Chris Jun 16 '11 at 17:53
  • I have stopped using the load method on images as it is so inconsistent, this answer to a different SO question may prove useful..http://stackoverflow.com/a/3877079/825711 – box86rowh Nov 11 '12 at 12:50
  • window.onload=function(){ alert($('img').width()); } –  Sep 20 '11 at 14:42

1 Answers1

3

It is quite a common problem, and if the images are already in the cache some browsers (shall I say directly - IE?) fails to trigger load events on them. Hence there is a technique for a workaround.

// After this line of your code
image.src = imagePath;

// put this
if (image.complete || image.naturalWidth > 0) { // if image already loaded
    $(image).load(); // trigger event manually
}
mkilmanas
  • 3,395
  • 17
  • 27
  • Gave it a shot but it actually breaks worse (before it just failed to load images, now it fails to anything). Also to further expand on the issue a .load() function containing just alert('loaded'); will work every time in IE. but $(this).appendTo($itemEleA); will fail on the first refresh and every subsequent refresh. – Chris Jun 16 '11 at 16:10
  • Have you tried doing `appendTo` __before__ `image.src = ...`? Even though is seems insignificant, I can imagine how this could mess things up. – mkilmanas Jun 17 '11 at 11:37
  • Worked for me. Good to keep in mind that with this method that the load event may be fired multiple times on multiple browsers. – Maurice Dec 20 '12 at 09:56