from : http://w3help.org/zh-cn/causes/HO2009
标准参考
MAP 和 AREA 元素通常组合起来使用为图片要设置一个超链接区域。使用时将 IMG 元素的 "usemap" 属性1关联到一个 MAP 元素上,这个 MAP 元素的 "name" 属性值要与 IMG 元素的 "usemap" 属性值相同。AREA 元素嵌入在 MAP 元素中,用来指定该图片中超链接区域的形状 ("shape") 、所处位置 ("coords")、链接地址 ("href") 等。
HTML4.01 规范中对 AREA 元素的 "shape" 和 "coords" 属性的描述如下:
- shape:可取值为 default | rect | circle | poly,用来指定超链接区域的形状。
- default:将整个图片定义为超链接区域;
- rect:定义一个矩形超链接区域;
- circle:定义一个圆形超链接区域;
- poly:定义一个多边形超链接区域;
- coords:用来指定超链接区域在屏幕上的位置和形状,确定位置的坐标值和坐标值的书写顺序由所设定的形状来决定,确定位置与形状的可能性组合如下
- rect:left-x,top-y,right-x,bottom-y ,通过两个点来确定一个矩形的左上角与右下角的坐标,从而确定一个矩形区域;
- circle:center-x, center-y, radius ,通过一对坐标值确定一个点,并以这个点为圆心,"radius" 值为半径确定一个圆形的超链接区域,当 "radius" 值为百分数时,依照被关联对象的 min(width,height)计算出半径的数值;
- poly:x1, y1, x2, y2, ..., xN, yN ,每两个为一对坐标用来确定一个点,当这些点的坐标值不全相同时,以第一个点为该多边形的起始点,最后一个点为多边形的终点,将这些点连接起来围成一个多边形;
关于 MAP 和 AREA 元素的更多内容,请参考 CSS2.1 规范 13.6.1 Client-side image maps: the MAP and AREA elements 中的内容。
注 1:要关联 MAP 元素的 IMG 元素的 "usemap" 属性值必须以 "#" 开头并且加上要关联的 MAP 元素的 "name" 属性值。
问题描述
MAP 元素会影响指向 MAP 的元素,其父元素 A 元素的默认链接行为。
IE6 IE7 IE8 中,产生自 MAP 元素的事件冒泡路径,不依赖 MAP 本身所处的元素嵌套规则,他会执行到引向 MAP 的元素嵌套结构中。
造成的影响
页面无法按照预期结果执行导航,并且意外的触发原本不应在事件冒泡路径上的事件处理程序。
受影响的浏览器
所有浏览器 |
---|
问题分析
1. 对 A 元素默认链接行为的阻止
分析以下代码:img-map.html
<a href="http://www.google.com" target="_blank"> <img src="Chrome1.png" usemap="#Map1" style="border:none" /> text </a> <map name="Map1"></map>
A 元素链接到 Google 站点,元素内嵌套 IMG 标签,此图片使用 "usemap" 属性关联到名为 "Map1" 的 MAP 元素中。
分别点击 A 元素的图片区域及文本区域,各浏览器实际结果处理如下:
IE6 IE7 IE8 | Firefox Chrome Safari Opera | |
---|---|---|
点击图片区域 | 失效 | 有效 |
点击文本区域 | 有效 | 有效 |
可见,在 IE6 IE7 IE8 中,如果 A 元素内带有使用 usemap 属性关联了 MAP 元素的 IMG 元素,将导致超链接中该图片区域默认行为失效。
2. MAP AREA 元素的事件冒泡机制差异
分析以下两组代码:map-area_event_bubble.html
<script> function clicked(i, o) { document.getElementById('info' + i).innerHTML += o.tagName + ' Tag Clicked.<br />'; } </script> <div> MAP 位于 A 之外,请点击图片:<br /> <a href="#" οnclick="clicked(1, this)"> <img src="Chrome1.png" border="0" usemap="#Map1" οnclick="clicked(1, this)" /> </a> <map name="Map1" οnclick="clicked(1, this)"> <area shape="rect" coords="0,0,90,90" οnclick="clicked(1, this)"> </map> </div> <div id="info1"></div> <br /> <div> MAP 位于 A 之内,请点击图片:<br /> <a href="#" οnclick="clicked(2, this)"> <img src="Chrome1.png" border="0" usemap="#Map2" οnclick="clicked(2, this)" /> <map name="Map2" οnclick="clicked(2, this)"> <area shape="rect" coords="0,0,90,90" οnclick="clicked(2, this)"> </map> </a> </div> <div id="info2"></div>
两组代码中均为 AREA MAP A IMG 元素写入内联 "click" 事件,第一组为 MAP 标签没有嵌套在 A 标签内情况,第二组为 MAP 标签嵌套在 A 元素内情况。
根据浏览器事件冒泡机制,点击 AREA 元素,在触发完成自身的 "click" 事件后,AREA 元素的父级元素直至到视口元素为止,都会依次触发他们的 "click" 事件。因此根据规范描述,第一组元素应会根据元素嵌套关系,实现事件冒泡机制,依次触发 AREA MAP 元素的 "click" 事件。而第二组则是,依次触发 AREA MAP A 元素的 "click" 事件。
尝试点击 AREA 元素,各浏览器实际结果处理如下:
IE6 IE7 IE8 | Firefox Chrome Safari Opera | |
---|---|---|
MAP 位于 A 之外 | AREA Tag Clicked. MAP Tag Clicked. IMG Tag Clicked. A Tag Clicked. | AREA Tag Clicked. MAP Tag Clicked. |
MAP 位于 A 之内 | AREA Tag Clicked. MAP Tag Clicked. IMG Tag Clicked. A Tag Clicked. | AREA Tag Clicked. MAP Tag Clicked. A Tag Clicked. |
可见,IE6 IE7 IE8 中即使 MAP 元素没有嵌套在 A 元素内,其事件冒泡机制依然会通过 IMG 元素关联起来,这显然是个不符合事件冒泡机制的实现扩展。
而其他浏览器则是严格根据元素实际嵌套关系产生事件冒泡。
3. MAP AREA 标签对 A 标签的默认行为支持差异
结合之前的第一和第二点差异,我们构造出如下两组用例:
<script> function clicked(i, o) { document.getElementById('info' + i).innerHTML += o.tagName + ' Tag Clicked.<br />'; } </script> <div> MAP 位于 A 之外,请点击图片:<br /> <a href="http://www.google.com" οnclick="clicked(1, this)" target="_blank"> <img src="Chrome1.png" border="0" usemap="#Map2" /> </a> <map name="Map2"> <area shape="rect" coords="0,0,90,90" οnclick="clicked(1, this)"> </map> </div> <div id="info1"></div> <br /> <div> MAP 位于 A 之内,请点击图片:<br /> <a href="http://www.google.com" οnclick="clicked(2, this)" target="_blank"> <img src="Chrome1.png" border="0" usemap="#Map1" /> <map name="Map1"> <area shape="rect" coords="0,0,90,90" οnclick="clicked(2, this)"> </map> </a> </div> <div id="info2"></div>
第 1 组代码中,MAP 处于 A 标签外,第 2 组 MAP 处于 A 标签内。
两组代码中均使用, A 元素嵌套 IMG 和 MAP 元素,IMG 元素使用 "usemap" 属性指向 MAP 元素, MAP 中使用 AREA 元素创造出足以覆盖 IMG 区域的链接区。
根据之前说明可知,在第 2 组用例中,点击图片区域,会先触发 "AREA" 元素的 "click" 事件。然后根据事件冒泡机制,会使父元素 A 也产生 "click"。A 元素内存在 "href" 属性并链接到 Google 首页上,被点击后应将该页导航到 Google。
运行用例,来看不同的浏览器中的表现结果汇总如下:
IE6 IE7 IE8 | Firefox | Chrome Safari Opera | |
---|---|---|---|
第 1 组 | A 元素导航失效 | 事件冒泡不会到达 A 元素,不产生导航行为。 | 事件冒泡不会到达 A 元素,不产生导航行为。 |
第 2 组 | A 元素导航失效 | A 元素导航失效 | 导航到 Google |
根据上表可见:
- IE6 IE7 IE8 中由于文章最开始说明的,如果 A 标签内包含有使用 MAP 的 IMG 标签,将导致 A 链接整体失效;
- Firefox 中,即使点击事件冒泡到 A 标签中,也不会触发 A 标签的默认导航行为发生;
- Chrome Safari Opera 均处理正常。
解决方案
- 注意 MAP 标记与其他标记的嵌套关系,IE6 IE7 IE8 中的 MAP 冒泡机制是根据指向 MAP 标记的标记位置决定的。如果期望所有浏览器冒泡路径基本一致,可以将 MAP 标记放在引用 MAP 的标记的兄弟级别。
- 注意 A 标记的默认导航行为触发限制,即使标签嵌套一致,点击事件冒泡路颈 A 标记,也不会在 IE6 IE7 IE8 Firefox 中触发浏览器默认行为产生导航。可以利用 A 标记也会执行点击事件冒泡的特性,使用 A 标记的 "click" 事件代替 "href" 属性执行页面跳转工作。