/    Sign up×
Community /Pin to ProfileBookmark

Can’t change <img> src attribute reliably in IE

I googled the web, and searched here in @ webdeveloper, but I can’t find anything relevant. Perhaps someone can shed some light on this insanity. I’m a Java developer, and have considerably less experience with Javascript, so may be missing some well known quirk.

[b]Problem[/b]
The issue is that changing the ‘src’ attribute of an <image> tag, is making the image disappear, rather than change. Frustratingly, the problem only happens in IE; Gecko behaves as expected.

I have found two work arounds: one is to pop up an alert just after chainging ‘src’: the icon image correctly updates when the alert dialog is popped up (before dismissing it). The second is to use a callback with the ‘setTimeout’ method. The first is unacceptable, the second is, IMHO, simply ugly.

My best theory is that the thread which changes the ‘src’ value is the same one to update the UI, and it is dying before actually getting to update the view. I assuming that ‘setTimeout’s callback is invoked by a separate thread, which doesn’t die prematurely. The ‘alert’ workaround suggests a pause to let the UI update complete.

I’m hoping someone can point me in the right direction to do this cleanly, or simply point out that yes, this is (yet another) known bug in IE, or give me some more debugging hints — since I’m fresh out.

[B]Situation[/B]
The page I’m working on is going to have an expanding menu tree (much like a file system browser). I used the free ‘[URL=http://www.softcomplex.com/products/tigra_menu_tree/]Tigra Menu Tree[/URL]‘ for the menu. I’ve made some changes to customize it, and fix a bug, but what I use is pretty much what’s up there. I found a couple bugs in it, and was last updated in ’02, so the problem may or may not be there. It does seem to work on other pages though.

The menu items are represented as ‘TreeItem’ objects and display as a small image and some text, wrapped in an anchor tag, with an ‘onclick’ handler. ‘onclick’ invokes the ‘select’ method below:

[CODE]TreeItem.prototype.select = function (b_deselect) {
if (!b_deselect) {
var o_olditem = this.o_root.o_selected;
this.o_root.o_selected = this;
if (o_olditem) o_olditem.select(true);
}
var o_iicon = document.images[‘i_img’ + this.o_root.n_id + ‘_’ + this.n_id];
if (o_iicon) {
var item=this;
//setTimeout(function() { //workaround 2
o_iicon.src = item.get_icon();
//}, 0); //workaround 2
}

e(‘i_txt’ + this.o_root.n_id + ‘_’ + this.n_id).style.fontWeight = b_deselect ? ‘normal’ : ‘bold’;

this.upstatus();
//alert(“returning”);// workaround 1
return new Boolean(this.a_config[1]);
}

e=(document.all ? function(id){return document.all[id]} :
function(id){return document.getElementById(id)});[/CODE]

The return value is true if the menu item references a URL, false if not (this was the bug I fixed: I added the ‘new’, as IE didn’t like not having it; mentioned later). The “upstatus” method modifies the text in the statusbar.

Clicking the TreeItem link will (in IE) make the item’s icon dissappear, unless one of either the alert (workaround 1), or the setting of the timeout callback (workaround 2) is uncommented.

[B]The Trial (what I recall of it):[/b]
Earlier in the debugging process I wrapped the method code in a try/catch block and found that IE wanted the return to be “new Boolean…” not just “Boolean”, but that didn’t fix the image dissappearing. With that issue fixed, there are no exceptions being thrown from inside the method.

Another problem I had with the menu script was getting the “one item remaining” status in IE, and the tree never being built. I was able to get around that by preloading the images and only building the tree via callback when the images had all finished loading.

The ‘get_icon’ method [i]was[/i] simply building a string. I changed that to actually look up the preloaded Image object, and return it’s src value thinking that accessing the preloaded Image might help, but it didn’t.

I tried setting the ‘src’ attribute multiple times in succession, but that didn’t help.

I tried replacing the ‘alert’ with a busy loop which checks a new Date, to wait up to a minute, but that didn’t help.

I thought maybe there are too many items in the DOM for it to have time to refresh, but stripping out most of the HTML and cutting the menu to 2 items didn’t help.

Note that even though setting ‘src’ failed, the text of the item was bolded, so I know further code is executing.

Around here is when I came up with the ‘thread dying abruptly’ theory.

I’m guessing something is throwing an exception [i]after[/i] I’m setting the src attribute, so I tried adding a try/catch directly in the onclick, wrapping the call to ‘select’, but that didn’t help. It seems no exception is being thrown.

I’ve also tried using Microsofts Script Debugger. It locks up both itself and IE within moments of trying to execute the onclick callback. I don’t have MS Visual Studio (or whatever the latest supported debugging environment for js in IE is).

Is there a better way to find out what happens [i]after[/i] the method exits?

I tried to cut it down to a bare minium example of html and js, but so far I haven’t been able to build up a page from scratch that reproduces this.

[B]Environment[/B]
My env is WinXP SP2, IE 6, running Apache locally for testing, so network latency isn’t really an issue (though having to preload images was surprising).

If you’ve made it here, thanks, and apologies for the length. I did find the timeout workaround while writing, so there’s been benifit, even if the problem never ‘solved’! ?

to post a comment
JavaScript

8 Comments(s)

Copy linkTweet thisAlerts:
@FangMar 15.2006 — It appears, from your description, that [I]item.get_icon()[/I] is not returning the correctly formatted value or is locked in a loop.

Can we have a link to the page?

btw This is an overly complex menu that only works when JavaScript is enabled; not to be recommended.
Copy linkTweet thisAlerts:
@callistanauthorMar 15.2006 — It appears, from your description, that [I]item.get_icon()[/I] is not returning the correctly formatted value or is locked in a loop. Can we have a link to the page?[/quote]
That would be nice and easy to fix, but I'm confident [i]item.get_icon()[/i] is working correctly. The code works in Gecko browsers without workarounds, and IE can be made to work without changing [i]item.get_icon()[/i] or its results.

Sadly, putting the pages up on a server showed that the [i]setTimeout()[/i] hack only worked when being served from localhost, so I've removed that. I've put up 3 pages to view, where the js methods which update images are overridden in the html of the test pages.

Current site: http://www.windschange.org/maps

[I]setTimeout()[/I]: http://www.windschange.org/maps/test-timeout.html (works locally, but not over internet)

[I]alert()[/I]: http://www.windschange.org/maps/test-alert.html (works all the time)

btw This is an overly complex menu that only works when JavaScript is enabled; not to be recommended.[/QUOTE]
The page is a Google Maps Mashup, so if javascript isn't available, there's no point in being there. I'm open to suggestions on menu code, though this does what I need, is free and open, and is seemed less complex than others like it.
Copy linkTweet thisAlerts:
@gburcherJan 03.2007 — Did you ever find a reliable method for forcing the image to refresh in IE with a new src= value? I am having the same problem. On many other pages I change the img src value and have no problem. On this one page the image refresh is unpredicatable. As you noted, the image always refreshes when alert() is issued. That is not an acceptable hack - maybe something else to force the refresh consistently?
Copy linkTweet thisAlerts:
@james_costertonJan 12.2007 — After an hour or so hacking around I think I've found the answer. If you call a javascript function from an anchor href like:

href="javascript:SwapImage('myimg.jpg')"

this seems to work fine.

If you use the onclick="SwapImage('myimg.jpg')" with href="#" or href="javascript:void(0)", this will fail. Guessing the javascript:void(0) somehow kills the onclick call, even if you return true from the click handler.

This bug has been fixed in IE7. Another thing to bear in mind is IE6 seems to have dodgy support for progressive jpegs, so another gotch to look out for if things aren't showing up.

hth

James
Copy linkTweet thisAlerts:
@gburcherJan 12.2007 — Thanks for the reply. However, I am currently using the method that you suggest and still have a problem. I think one of the previous posts was on the right track with the theory that the thread updating the image display gets killed before it has time to perform the update.

In my case, the image click needs to perform a form submit and also swap the image source. I am returning a NO_CONTENT response so that the client browser does not otherwise refresh the content, other than me changing the image source. Here is pseudo code for what I am doing:

[CODE]<form name="myForm">
<a href="javascript:swapImage()"><img id="img1" src="image1.jpg"></a>
</form>
function swapImage()
{
document.getElementById("img1").src="image2.jpg";
document.myForm.submit();
}[/CODE]


When coded like this, the image display would not change consistently. Every now and then it would work, but not usually. I found that I could put the form submit inside a second javascript function and then force a delay like this:

[CODE]function swapImage()
{
document.getElementById("img1").src="image2.jpg";
setTimeout("submitForm()", 500);
}
submitForm()
{
document.myForm.submit();
}[/CODE]


With this code, the image display swaps every time. I think the form submit cuts off the image refresh thread before it finishes the job. Adding the delay ensures that the thread has time to finish before the submit(). Just my theory...

I would still be interested in a better solution than the forced delay. Feels like a hack.

GB
Copy linkTweet thisAlerts:
@bathurst_guyJan 12.2007 — I use <a href="#nogo" onclick="whatever">

Adding some text after the hash seems to top it from returning to the top of the page and doing what your describing.
Copy linkTweet thisAlerts:
@james_costertonJan 12.2007 — GB,

Not sure if this will help, but I normally use an IFRAME for fire and forget form posts (or to serve content back with a save dialog etc). This should leave your main page uninterupted by the submit.

Cheers

James

[CODE]
<iframe name="FormSubmitter" width="1" height="1" frameborder="no"></iframe>
<form name="myForm" target="FormSubmitter">
<a href="javascript:swapImage()"><img id="img1" src="image1.jpg"></a>
</form>
function swapImage()
{

document.getElementById("img1").src="image2.jpg";
document.myForm.submit();

}
[/CODE]
Copy linkTweet thisAlerts:
@SimonBorisSep 05.2008 — Hi everybody.

I had the same problem when changing src attribute using IE6.

And i have solved my problem and wanted to share this with all of you.

I was doing a for loop to change of bunch of thumbnail images like the following:

function changeThumbs(){

...

for(var i=0;i<a.length;i++){

...

img.src=a[i].url;

...

}

}



The images where disapering in ie6.

The code is good, the reason there was a render bug was that the function was called via an event (onclick) on a link tag (<a href="" onclick="changeThumbs()"... )



Once the action place on another tag (li in my case), no more bug.



I cant explain why the A tag (<a href...) was causing this bug on ie6, but once remove, it was working great.





Hope it will help some people.
×

Success!

Help @callistan spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 6.17,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @nearjob,
tipped: article
amount: 1000 SATS,

tipper: @meenaratha,
tipped: article
amount: 1000 SATS,

tipper: @meenaratha,
tipped: article
amount: 1000 SATS,
)...