ObjectSwap:绕过IE中的ActiveX激活问题

Microsoft’s recent decision to change the way ActiveX objects are handled in Internet Explorer, following the patent law suit by EOLAS, has created a serious problem for the developer community.

在EOLAS提出专利诉讼之后,Microsoft最近决定更改Internet Explorer中处理ActiveX对象的方式,这对开发人员社区造成了严重的问题。

All ActiveX controls in Internet Explorer — including Flash and Shockwave — will need to be activated by a mouse click (or by hitting Tab and the Enter key) before the user can interact with the control. This is bound to impair the user experience of any web site that embeds Flash, and it’s up to the Flash and HTML developers to clean up the mess.

用户必须先通过鼠标单击(或通过单击Tab和Enter键)来激活Internet Explorer中的所有ActiveX控件(包括Flash和Shockwave),然后才能与控件进行交互。 这势必会损害嵌入Flash的任何网站的用户体验,并且Flash和HTML开发人员必须清理混乱。

可用的解决方案 (Available Solutions)

You can bypass the activation requirement by using an externally linked script, such as JavaScript, to embed the ActiveX content. Solutions are currently available for Flash, such as FlashObject and UFO.

您可以通过使用外部链接的脚本(例如JavaScript)来嵌入ActiveX内容,从而绕过激活要求。 当前可用于Flash的解决方案,例如FlashObjectUFO

These work well for embedding new Flash content using JavaScript. But what about existing object tags, which will need to be rewritten, or browsers with JavaScript disabled? These situations require an alternative solution.

这些对于使用JavaScript嵌入新的Flash内容效果很好。 但是,现有的对象标签(需要重写)或禁用了JavaScript的浏览器呢? 这些情况需要替代解决方案。

对象交换 (ObjectSwap)

The ObjectSwap solution presented in this article takes all these issues into account. It captures all existing object tags and replaces them with … themselves. This forces an automatic activation in Internet Explorer, while leaving other browsers alone. Similar solutions have been developed in parallel, but this article will concern itself only with ObjectSwap.

本文介绍的ObjectSwap解决方案考虑了所有这些问题。 它捕获所有现有的对象标记,并将它们替换为…本身。 这将强制在Internet Explorer中自动激活,同时不影响其他浏览器。 并行开发了类似的解决方案 ,但本文仅涉及ObjectSwap。

Although this solution was developed primarily with Flash in mind, it should also work with other ActiveX controls, such as Shockwave. The script affects all the object tags in the page, but the developer can choose to exclude a specific object by setting its class name to "noswap".

尽管此解决方案主要是为Flash开发的,但它也应与其他ActiveX控件(例如Shockwave)一起使用。 该脚本会影响页面中的所有对象标签,但是开发人员可以通过将其类名称设置为“ noswap”来选择排除特定对象。

Implementation

实作

ObjectSwap was written with a view to make implementation as easy as possible, with minimum disruption to existing code. The only change you need to make to your HTML page is to link the script in the <head> tag for every page that includes ActiveX objects, like this:

编写ObjectSwap的目的是使实现尽可能容易,并且对现有代码的干扰最小。 您需要对HTML页面进行的唯一更改是为每个包含ActiveX对象的页面在<head>标记中链接脚本,如下所示:

<script type="text/javascript" src="objectSwap.js"> </script>

Once you’ve done that, you can keep on using your favourite technique for embedding ActiveX content. For Flash, that means either the Adobe/Macromedia default setting using object/embed tags, or the standards-compliant technique that uses only the object tag (better known as Flash Satay).

完成此操作后,您可以继续使用自己喜欢的技术来嵌入ActiveX内容。 对于Flash,这意味着使用对象/嵌入标签的Adobe / Macromedia默认设置,或仅使用对象标签的标准兼容技术(更好地称为Flash Satay )。

Flash Detection

闪光检测

So far, so good. But since we’re already using JavaScript, why not avail ourselves of the opportunity to add some Flash Detection to the mix? We can achieve this by adding a new param definition to the Flash object, for example:

到目前为止,一切都很好。 但是,既然我们已经在使用JavaScript,为什么不利用这个机会在组合中添加一些Flash Detection? 我们可以通过向Flash对象添加新的参数定义来实现此目的,例如:

<param name="flashVersion" value="7" />

The script looks for this param and, if it exists, will transform the object into a div that displays the alternative content. This content is not generated by the script, but instead must already reside inside the object tag, and display alternative text, images, links to the Flash installer, and so forth. Internet Explorer normally ignores this content if Flash is present. This is also true for other browsers when you use the Flash Satay method, so you can simply add the content anywhere in the body of the object.

脚本将查找此param ,如果存在,它将将该对象转换为显示替代内容的div 。 此内容不是由脚本生成的,而是必须已经驻留在object标记内,并显示替代文本,图像,到Flash安装程序的链接等。 如果存在Flash,Internet Explorer通常会忽略此内容。 当您使用Flash Satay方法时,其他浏览器也是如此,因此您可以简单地将内容添加到对象主体中的任何位置。

On the other hand, if the object/embed method is used, gecko-based browsers like Firefox and Netscape will display the alternative content alongside the embedded movie. The solution is to enclose the content within HTML comments, which will be stripped by the script when the content is displayed. There should be a space or a line-break between the comment tags and content, to avoid conflicts with any IE conditional comments that happen to be inside the object tag:

另一方面,如果使用对象/嵌入方法,则基于壁虎的浏览器(如Firefox和Netscape)将在嵌入式电影旁边显示替代内容。 解决方案是将内容包含在HTML注释中,当显示内容时,脚本将剥离该内容。 注释标签和内容之间应该有空格或换行符,以避免与恰好在对象标签内的任何IE条件注释冲突:

<!--
<p>You need <a href= "http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash">Flash</a> to view this content.</p>
-->

Of course, you can also choose to ignore the Flash detection option, or use Adobe’s express installation for Flash 8 instead.

当然,您也可以选择忽略Flash检测选项,或改为使用Adobe的Flash 8快速安装。

Browser Support

浏览器支持

The activation issue of ActiveX objects affects only Internet Explorer, so most of the code will also affect only IE. However, the Flash detection code needs to work with other browsers as well. This means that the objectSwap function will be called for all browsers to perform the Flash detection service, if required, but will only execute the object swap on IE, leaving other browsers unaffected. This is all you need to know to start using the script. You can download the script and examples here.

ActiveX对象的激活问题仅影响Internet Explorer,因此大多数代码也将仅影响IE。 但是,Flash检测代码也需要与其他浏览器一起使用。 这意味着,如果需要,将为所有浏览器调用objectSwap函数,以执行Flash检测服务,但仅在IE上执行对象交换,而不会影响其他浏览器。 这就是开始使用脚本所需的全部知识。 您可以在此处下载脚本和示例

However, if you’d like to know more about how ObjectSwap works, the following sections will reveal the inner workings of the script.

但是,如果您想进一步了解ObjectSwap的工作原理,以下几节将介绍该脚本的内部工作原理。

这个怎么运作 (How It Works)

First, the script cycles through all the object tags in the HTML source code and retrieves their outerHTML values:

首先,脚本循环遍历HTML源代码中的所有对象标记,并检索它们的outerHTML值:

var objects = document.getElementsByTagName('object');
for (var i=0; i<objects.length; i++) {
 var o = objects[i];
 var h = o.outerHTML;

Since Internet Explorer does not include any of the object’s param tags in its outerHTML (or innerHTML), they need to be extracted separately into a string:

由于Internet Explorer在其outerHTML (或innerHTML )中不包含任何对象的param标签,因此需要将它们分别提取为字符串:

var params = "";
for (var j = 0; j<o.childNodes.length; j++) {
 var p = o.childNodes[j];
 if (p.tagName == "PARAM"){
    ....
   params += p.outerHTML;
 }
}

The generated "params" string is spliced into the outerHTML code:

生成的"params"字符串被拼接到outerHTML代码中:

var tag = h.split(">")[0] + ">";
var newObject = tag + params + o.innerHTML + " </OBJECT>";

And, finally, the new generated HTML replaces the original:

最后,新生成HTML替换了原始HTML:

o.outerHTML = newObject;

Hiding the Objects

隐藏对象

There are still a few things to be done. First of all, we want to prevent the objects from loading twice — once when they’re initiated in the HTML code, and again after they’re swapped. We achieve this by writing a new style sheet to the document before the page loads. The style uses display: none to take the objects out of the document flow, delaying their loading until the swap is complete:

还有几件事要做。 首先,我们希望防止对象加载两次-一次在HTML代码中启动对象时,以及在交换对象后再次加载。 我们通过在页面加载之前将新的样式表写入文档来实现此目的。 样式使用display:none将对象从文档流中移出,将其加载延迟到交换完成为止:

document.write ("<style id='hideObject'> object {display: none;} </style>");

After the swap, the style is disabled and the objects are allowed to load:

交换之后,将禁用样式,并允许加载对象:

document.getElementById("hideObject").disabled = true;

Detecting Flash

检测闪光

As it cycles through the parameter list for each object, the objectSwap function checks for the existence of the flashVersion param and, if it’s found, executes a Flash detection method:

在遍历每个对象的参数列表时, objectSwap函数会检查flashVersion参数是否存在,如果找到,则执行Flash检测方法:

if (p.name == "flashVersion") {
 hasFlash = detectFlash(p.value);

The method looks for Flash in two types of browsers. First, it checks whether the plugin is present in the navigator.plugins array, which applies to gecko-based browsers:

该方法在两种类型的浏览器中查找Flash。 首先,它检查插件是否存在于navigator.plugins数组中,该数组适用于基于壁虎的浏览器:

detectFlash = function(version) {
 if(navigator.plugins && navigator.plugins.length){
   var plugin = navigator.plugins["Shockwave Flash"];
   if (plugin == undefined){
     return false;
   }

If a plugin is found, the code still needs to check for the installed version. This is achieved by retrieving the third item in the plugin’s description property and checking it against the passed version parameter:

如果找到了插件,代码仍然需要检查安装的版本。 这是通过获取插件的description属性中的第三项并将其与传递的version参数进行比较来实现的:

var ver = navigator.plugins["Shockwave Flash"].description.split(" ")[2];
 return (Number(ver) >= Number(version))

Next, the script checks for the plugin in Internet Explorer. In JavaScript, it achieves this by trying to create a new Flash ActiveX object with the passed version. If JavaScript is unable to create the object, it will throw an exception, which is why the entire expression must be enclosed inside a try-catch block:

接下来,该脚本在Internet Explorer中检查插件。 在JavaScript中,它通过尝试使用传递的版本创建一个新的Flash ActiveX对象来实现此目的。 如果JavaScript无法创建该对象,它将抛出异常,这就是为什么整个表达式必须放在try-catch块内的原因:

} else if (ie && typeof (ActiveXObject) == "function") {
 try {
   var flash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + version);
   return true;
 }
 catch(e) {
   return false;
 }
}

Just in case some other browser has a different way of handling Flash, the method returns true at its end, as a safety net. If the browser doesn’t have the navigator.plugins array, and is not Internet Explorer, it will still try to display the Flash movie.

万一其他浏览器使用不同的Flash处理方式,该方法将在最后返回true,作为安全网。 如果浏览器没有navigator.plugins数组,并且不是Internet Explorer,它将仍然尝试显示Flash电影。

Back at the objectSwap method, if the script doesn’t find the correct version, the object’s id is retrieved (or a new one is assigned) and added to a queue:

回到objectSwap方法,如果脚本找不到正确的版本,则将检索对象的ID(或分配一个新的ID)并将其添加到队列中:

if (!hasFlash){
o.id = (o.id == "") ? ("stripFlash"+i) : o.id;
stripQueue.push(o.id);
Later on, the queue is passed to the stripFlash method:
if (stripQueue.length) {
 stripFlash(stripQueue)
}

Stripping Flash

剥离闪光

This method cycles through the ids in the queue and retrieves each object’s innerHTML:

此方法在队列中的ID之间循环,并检索每个对象的innerHTML

for (var i=0; i<stripQueue.length; i++){
 var o = document.getElementById(stripQueue[i]);
 var newHTML = o.innerHTML;

For the object/embed method, where the alternative content has been hidden from Firefox and Netscape with comments, regular expressions are needed to strip the comments from the innerHTML, so that the new content can be displayed in the browser:

对于object / embed方法,其中替代内容已从Firefox和Netscape中隐藏并带有注释,需要使用正则表达式从innerHTML删除注释,以便可以在浏览器中显示新内容:

newHTML = newHTML.replace(/<!--s/g, "");
newHTML = newHTML.replace(/s-->/g, "");

Another regular expression is used to neutralise the embed tag by replacing it with a span:

另一个正则表达式用于通过将span替换为embed标签来中和embed标签:

newHTML = newHTML.replace(/<embed/gi, "span");

In order to transform the object into a div, the easiest thing would have been to change the object’s outerHTML. However, that doesn’t work in Firefox; instead, a new div element is created and assigned the same innerHTML, id, and className as the object:

为了将对象转换为div,最简单的方法就是更改对象的outerHTML 。 但是,这在Firefox中不起作用。 而是创建一个新的div元素,并为其分配与对象相同的innerHTMLidclassName

var d = document.createElement("div");
d.innerHTML = newHTML;
d.className = o.className;
d.id = o.id;

Finally, the object is swapped for the new div:

最后,将对象交换为新的div

o.parentNode.replaceChild(d, o);

Initiating the ObjectSwap

启动ObjectSwap

ObjectSwap must be executed after all the objects have loaded, by binding the objectSwap function to the window.onload event. The catch is that other linked scripts in your page might have their functions bound to the same event; the last script to do so will override all the earlier bindings, causing the other scripts to fail. This is resolved by catching existing functions bound to the event, and calling them as well: 

Naturally, this will fail if following scripts use window.onload, so you must ensure that either this script comes last, or that the following scripts use a similar technique.

Conclusion
ObjectSwap offers a complete, one-step solution to the problem resulting from the decision by Microsoft as a result of the EOLAS law suit. A single JavaScript file linked from the <head> tag of your page is all you need to avoid Internet Explorer's activation requirement. What's more, you can take advantage of the situation and enhance the user experience by adding some simple Flash detection to your page.

翻译自: https://www.sitepoint.com/activex-activation-issue-ie/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值