How do I get JavaScript-generated image maps to work with Internet Explorer?
I'm using javascript to generate a high resolution grid for an image that I generated on a web server. The high-resolution grid is composed of a 'map' element with hundreds of 'area' child elements. Each 'area' element has onmouseover attribute that causes the display of a popup box.
After assigning the map to the img (via the usemap attribute), Internet explorer ignores the 'onmouseover' attribute of the area elements that I added via javascript.
The behavior is not caused by syntactical variations between IE and other browsers. A static map behaves correctly. Only the elements that I add dynamically to an existing image map fail to fire their corresponding mouse-over events.
How can I get IE to fire the mouse-over event for the added 'area' elements?
function generate_image_map ( img ) {
var tile_width = 8;
var tile_height = 10;
var plotarea_left = 40;
var plotarea_top = 45;
var column_count = 100;
var row_count = 120;
var img_id = YAHOO.util.Dom.getAttribute(img, "id");
var img_map_id = YAHOO.util.Dom.getAttribute(img, "usemap");
var original_map = YAHOO.util.Selector.query(img_map_id)[0];
var area_nodes = YAHOO.util.Selector.query("area", original_map);
var last_node = area_nodes[area_nodes.length - 1];
for (var y = 0; y < row_count; y++) {
var top = Math.round(plotarea_top + (y * tile_height));
var bottom = Math.round(plotarea_top + (y * tile_height) +
tile_height);
for (var x = 0; x < column_count; x++) {
var left = Math.round(plotarea_left + (x * tile_width));
var right = Math.round(plotarea_left + (x * tile_width) +
tile_width);
var area = document.createElement("area");
YAHOO.util.Dom.setAttribute(area, "shape", "rect");
YAHOO.util.Dom.setAttribute(area, "onmouseover",
"alert('This does not appear in IE')"
);
var coords = [
left, top,
right, bottom
];
YAHOO.util.Dom.setAttribute(area, "coords", coords.join(","));
YAHOO.util.Dom.in开发者_StackOverflow中文版sertBefore(area, last_node);
}
}
}
Solved.
I've concluded that internet explorer doesn't add appropriate event processing to the dynamically generated area elements. Whereas the original area elements will fire mouse-over events, the dynamically added elements do not. The following code adds mouse-over events to the dynamically added area elements:
if (YAHOO.env.ua.ie > 0) {
YAHOO.util.Event.addListener(original_map, "mousemove", function (e) {
var area = YAHOO.util.Event.getTarget(e);
var mouseover = YAHOO.util.Dom.getAttribute(area, "onmouseover");
if (mouseover !== null) {
eval("(function() {" + mouseover + "})();");
}
});
}
The mouse-over events now fire as expected, and my dynamically generated image map behaves like a static one in IE.
Where in the days of IE4 and NS4, IE was always the forgiving browser that swallowed all kinds of our little developing mistakes, it seems that at least for this IMG, MAP and AREA functionality the tables are turned.
Creating and adding an image with map with area dynamically via createElement and appendChild, FireFox works first time and IE not (Now end 2012 Win7 IE9!).
After all checking, tweaking and tuning IE still would not work. The only solution I could find that work for both FF and IE was by feeding innerHTML with what you'd normally type in the body.
I thought great! at least solution that works for both, but a minute later I couldn't stand it, because I'm on this - by the book createElement and appendChild route - by with I like to consistently create documents.
I started out with the createElement and appendChild code for FF next to innerHTML code for IE. Then I moved the IMG tag from innerHTML to createElement and appendChild route. It didn't work anymore for IE and started trying and trying. Then I did the same for the other tags and after trying the whole afternoon, and eventually I discovered the complete but narrow path for IE.
For image creation:
//USE THIS:
img = new Image(width, height);
//DOES NOT WORK:
img = document.createElement('IMG');
img.width = width;
img.height = height;
//DOES NOT WORK:
img = new Image();
img.width = width;
img.height = height;
further assign props like .src as usual.
Use camel-case properties in script
//USE THIS:
img.useMap = '#myMap';
//DOES NOT WORK:
img.usemap = '#myMap';
HTML props are case in-sensitive, but in script they are case sensitive.
And this is an undocumented, very funny (not!), for MS just to stuppid bug/quirck, that is still in this IE9 after having the MAP tag build in since IE4. Anyway...
//USE THIS:
map = document.createElement('MAP');
map.id = "myMap";
map.name = "myMap";
//DOES NOT WORK:
map = document.createElement('MAP');
map.name = "myMap";
In HTML IE uses the .name property, but in script IE uses the .id property. In case you use FF and IE code forking, I'd still keep the .name prop in the IE code in case MS fixes it.
Finally, here is a working piece of code for IE and FF using the createElement and appendChild route, yes!:
document.write('<INPUT type="button" value="Dynamic Image Map" onclick="dynamicImageMap(32, 64)">');
function dynamicImageMap(ox, oy)
{
var a, b, map, img, div, s;
a = document.createElement('AREA');
a.shape = 'rect';
a.coords = '128,0,250,128';
a.noHref = true;
b = document.createElement('AREA');
b.shape = 'rect';
b.coords = '0,128,128,250';
b.noHref = true;
map = document.createElement('MAP');
map.id = "myMap";
map.name = "myMap";
map.onclick = function(){ alert('myMap'); }
map.appendChild(a);
map.appendChild(b);
img = new Image(250, 250);
img.src = 'http://www.vectortemplates.com/raster/batman-logo-big.gif';
img.border = 0;
img.useMap = '#myMap';
div = document.createElement('DIV');
s = div.style;
s.position = 'absolute';
s.left = ox +'px';
s.top = oy +'px';
s.width = '250px';
s.height = '250px';
s.overflow = 'hidden';
s.visibility = 'inherit';
div.appendChild(map);
div.appendChild(img);
document.body.appendChild(div);
}
The image map areas makes the lower-left and higher-right quarters of the image hot for clicking. Replace the image src with an existing image src in case it doesn't exist/work anymore.
Goodluck and Have Phun!
精彩评论