打印

BT9037: IE 中页面内 OBJECT 对象相对其他浏览器额外包含了其引入的 ActiveX 插件的部分私有属性

作者:陆远

标准参考

OBJECT 元素定义一个嵌入的对象。允许规定插入 HTML 文档中的对象的数据和参数,以及可用来显示和操作数据的代码。

对应到 DOM 中则为 HTMLObjectElement 对象,这个接口定义如下:

interface HTMLObjectElement : HTMLElement {
  readonly attribute HTMLFormElement form;
           attribute DOMString       code;
           attribute DOMString       align;
           attribute DOMString       archive;
           attribute DOMString       border;
           attribute DOMString       codeBase;
           attribute DOMString       codeType;
           attribute DOMString       data;
           attribute boolean         declare;
           attribute DOMString       height;
           attribute long            hspace;
           attribute DOMString       name;
           attribute DOMString       standby;
           attribute long            tabIndex;
           attribute DOMString       type;
           attribute DOMString       useMap;
           attribute long            vspace;
           attribute DOMString       width;
  // Introduced in DOM Level 2:
  readonly attribute Document        contentDocument;
};

关于 OBJECT 元素的详细信息,请参考 HTML 4.01 规范 13.3 Generic inclusion: the OBJECT element 中的内容。

关于 HTMLObjectElement 对象的详细信息,请参考 HTML 4.01 规范 1.6.5. Object definitions - Interface HTMLObjectElement 中的内容。

问题描述

IE 中页面内每一个 OBJECT 元素创建的对应 DOM 对象不完全是 W3C 规范中标准的 HTMLObjectElement 对象,这个对象额外包含了其引入的 ActiveX 插件的一些私有属性。而这些属性在非 IE 浏览器中均不存在。

造成的影响

由于对于 OBJECT 元素所对应的 DOM 对象 HTMLObjectElement,IE 和 Chrome、Safari 中的对象类型有本质区别,这将导致若直接访问 OBJECT 元素所引入的插件的私有属性,将仅在 IE 中可以正常返回,其他浏览器均会报错。

受影响的浏览器

IE6 IE7 IE8  

问题分析

分析以下代码:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<object id="A" classid="clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6" style="width:100px; height:100px;">
<param name="url" value="Kalimba.mp3" />
</object>
<script>
alert(document.getElementById("A"));
for (var i in document.getElementById("A")) {
document.write(i + '<br>');
}
</script>
</body>
</html>

上面代码通过 OBJECT 元素创建了一个 Media Player 插件,并使用 PARAM 元素引入了一个 MP3 文件。由于 Firefox 和 Opera 不支持这种方式,所以本文不考虑这两种浏览器。

这段代码在各浏览器中运行效果如下:

IE81 Chrome Safari
[Object] [HTMLObjectElement]

1. IE6 IE7 无法正确返回一个 DOM 对象的接口类型,如 DIV 元素,返回的只是 [Object] 而不是 [HTMLDivElement]。但在 IE8(S) 中开始支持同 Chrome、Firefox 一样返回一个 DOM 对象的实际接口类型。

在 IE8(S) 中没有返回预期的“HTMLObjectElement”。通过对这个对象的遍历,得到的 key 中,IE 比 Chrome、Safari 多了很多,如:URL、openState、playState、controls 等。这些都是用于控制 Media Player 的特殊属性或对象。且不属于 W3C 规范中定义的 HTMLObjectElement 对象。
所以在 IE 中,返回的 OBJECT 元素对应的 DOM 对象并不是 W3C 规范中的 HTMLObjectElement,而是 IE 对这个对象所扩展之后的私有对象类型。

下面继续看一个例子:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<object id="A" classid="clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6" style="width:100px; height:100px;">
<param name="url" value="Kalimba.mp3" />
</object>
<script>
alert(document.getElementById("A").url);
</script>
</body>
</html>

这段代码在各浏览器中运行效果如下:

IE Chrome Safari
XXXXXXXXXXXXXX/Kalimba.mp3 undefined

这里由于 IE 对应的 OBJECT 元素对应的 DOM 对象相比 HTMLObjectElement 多了很多其引入插件的私有属性,且这些属性的名称是和 OBJECT 元素内的 PARAM 元素的 name、value 属性相对应的。所以在 IE 中可以返回这些属性值(即由 PARAM 属性设置的 value 值)。
而在 Chrome Safari 中,由于 OBJECT 元素对应的 DOM 对象为标准的 HTMLObjectElement,并没有这些属性,所以返回了 undefined。

解决方案

ActiveX 技术为微软的专有技术,仅在Windows 下的 IE 浏览器中可以得到支持。
其他浏览器如 Firefox Opera 则不支持这项技术。
而 WebKit 内核的 Chrome Safari 则实现了有限支持,包括:Flash, Media Player, Director, QuickTime, RealAudio。其原理为将它们的在 Windows 系统中的 classid 与其对应的 Mime-Type 相关联,所以可以和 IE 一样仅仅通过 OBJECT 元素的 classid 属性创建出这些插件。但并不能支持由 IE 扩展的 OBJECT 元素对应的对象所扩展的属性及方法。
所以在开发跨浏览器的插件时,应为非 IE 浏览器提供更通用的 NPAPI 接口的对应插件,完成 ActiveX 插件相同的功能。

针对本文中所引用的 Media Player 插件,可以考虑使用 Flash,或者合理的利用 IE 对 Media Player 的支持及其其他浏览器对 HTML5 的新标签 VIDEO 与 AUDIO 的支持在不同浏览器中达到相类似的效果。

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Chrome 4.0.302.3 dev
Safari 4.0.4
测试页面: object.html
object_param.html
本文更新时间: 2010-07-15

关键字

OBJECT HTMLObjectElement param 插件