четверг, 10 июля 2008 г.

Attaching/deattaching DOM elements in IE

Today I've faced an interesting issue with attaching and deattaching DOM elements in Internet Explorer.

The issue was around the creation of so called Thumbnail Bar component: visual representation of photo strip which supports scrolling with buttons:
All thumbnails to be displayed are loaded and stored in the array. Initially each thumbnail was represented by separate object, defined as follows:

ThumbnailBar.prototype.Thumbnail = function(imageAttachment) {
this.imageAttachment = imageAttachment;

this.containerElement = document.createElement("div");
this.containerElement.className = "eyestride-Thumbnail";

this.imageElement = document.createElement("img");
this.imageElement.src = imageAttachment.image.thumbnailFile.url;
this.containerElement.appendChild(imageElement);
}

So, thumbnail instance held a reference to container element and then used this reference to attach thumbnail container to Thumbnail Bar's image container. Each time Thumbnail Bar needs to be refreshed, inner HTML of imageContainerElement is first cleared:

this.imageContainerElement.innerHTML = "";

...

for (var i = startPosition; i < endPosition; ++i) {
this.imageContainerElement.appendChild(this.thumbnails[i].domElement);
}

Code works fine in Mozilla Firefox but refuses to work properly in Internet Explorer. In Internet Explorer appending of child div element (see containerElement in Thumbnail) actually works, but image is appended only once. So, if container element of Thumbnail was removed by clearing innerHTML of imageContainerElement the link between div and img is lost: div is appended without its child elements.

In order to fix this I've stored two references in Thumbnail: one for div and another for img, then added a method which performs attaching of thumbnail to specific container, in such a way:

EyeStride.UI.Viewer.ThumbnailBar.prototype.Thumbnail = function(imageAttachment) {
this.imageAttachment = imageAttachment;

this.containerElement = document.createElement("div");
this.containerElement.className = "eyestride-Thumbnail";

this.imageElement = document.createElement("img");
this.imageElement.src = imageAttachment.image.thumbnailFile.url;

this.attachTo = function(domElement) {
domElement.appendChild(this.containerElement);
this.containerElement.appendChild(this.imageElement);
}
}

...

for (var i = startPosition; i < endPosition; ++i) {
this.thumbnails[i].attachTo(this.imageContainerElement);
}

Another solution for the problem is to clear the contents of
imageContainerElement not by setting empty string for innerHTML property, but using removeChild method to remove elements from the image container, one by one. This solution works in both browsers too.

Комментариев нет: