ActiveX自定义事件无法在IE11上运行

时间:2013-07-16 08:15:56

标签: internet-explorer activex internet-explorer-11

我将IE从版本10升级到11,发现我的ActiveX自定义事件无法正常工作。

原因是IE11不再支持attachEvent,似乎我必须使用addEventListener。例如,之前我使用过

obj.attachEvent("onSelected", method1); 

现在,它是

obj.addEventListener("onSelected",method1,false); 

更改代码后,无法触发方法1。我不知道如何将自定义事件(在ActiveX插件中实现)绑定到JS方法并使其在IE11上运行?

4 个答案:

答案 0 :(得分:13)

我目前为IE 11找到的唯一方法是使用for...event脚本块:

<script for="myActiveX" event="onSelected(param1, param2)">
  method1(param1, param2);
</script>
<object id="myActiveX" ...></object>

这两个元素也可以使用JavaScript动态创建。您只需确保使用for方法设置setAttribute属性:

var handler = document.createElement("script");
handler.setAttribute("for", "myActiveX");
handler.event = "onSelected(param1, param2)";       
handler.appendChild(document.createTextNode("method1(param1, param2);"));
document.body.appendChild(handler);

var activeX = document.createElement("object");
activeX.id = "myActiveX"; 
activeX.codebase = "foobar.cab";
activeX.classid = "CLSID:123456789-1234-1234-1234-123456789012";
document.body.appendChild(activeX);

较早的IE版本(IE 8及更早版本)不喜欢上述代码。对于这些旧版浏览器,您必须使用codebase方法传递for参数和createElement参数:

var handler = document.createElement('<script for="myActiveX">');
...
var activeX = document.createElement('<object classid="CLSID:123456789-1234-1234-1234-123456789012">');

较新的浏览器在遇到此代码时会抛出异常,因此为了支持所有IE版本,您必须捕获此异常,然后使用其他方法。

答案 1 :(得分:2)

修改@Gerrit代码以适用于匿名函数,它也只是将attachEvent功能添加回IE 11(对于非ie浏览器的polyfill,虽然未经过测试),因此可以使用相同的代码。我很高兴找到了这个页面。我担心我必须在VBScript中执行此操作或模拟旧版本的IE。

行为似乎与IE5一直相同。

填充工具

if (!window.attachEvent) {
  window.attachEvent = Element.prototype.attachEvent = function (ename, efunction) {
    if (typeof efunction !== 'function') {
      throw new TypeError('Element.prototype.attachEvent - what is trying to be attached is not callable');
    }

    // We got to append somewhere
    var _body = document.getElementsByTagName('body')[0];

    // Get IE Version
    var msie = (function() {
        if (typeof document === "undefined") return false;
        var v = 3, div = document.createElement('div'), a = div.all || [];

        while (div.innerHTML = '<!--[if gt IE '+(++v)+']><br><![endif]-->', a[0]); 

        var _detection = v > 4 ? v : /*@cc_on!@*/false;

        var _version = _detection === true ? 10 : (!(window.ActiveXObject) && "ActiveXObject" in window) === true ? 11 : _detection;

        return _version;

    }());

    // Fix ActiveX not working
    if (msie == 11) {
      var _params = efunction.toString().match(/(\(.*\))\ *{/)[1];
      var _funcName = efunction.toString().match(/^function\s?([^\s(]*)/)[1];
      var _fixAnon = false;

      // Allow for anonymous functions
      if (_funcName == "") {
        _fixAnon = true;
        console.warn('Function name not found. Autogenerating');
        _funcName = "autogenFunction" + Math.floor(Math.random()*9999).toString()
        var _handleFunctionality = "{ var privateFunc = " + efunction.toString() + "; privateFunc.apply(" + _funcName + ", arguments); }";
      }

      // Only one script for|event can be used. Make sure there isn't one already
      var _query = 'script[for=' + this.id + '][event=' + ename + ']';
      var _handle = document.querySelectorAll(_query);
      var _handleFunc = _funcName + _params + ';';

      if (_fixAnon) {
        var _newFuncName = _funcName + _params;
        var _newFunction = "function " + _newFuncName + " " + _handleFunctionality;
        var _newHandle = document.createElement('script');
        _newHandle.type = "text/javascript";
        _newHandle.appendChild(document.createTextNode(_newFunction));
        _body.appendChild(_newHandle);
      }

      // If script for|event exists, reuse it
      if (_handle.length != 0) {
        _handleFunc += _handle[0].textContent;
        _body.removeChild(_handle[0]);
        delete _handle[0];
      }
      _handle = document.createElement('script');
      _handle.setAttribute("for", this.id);
      _handle.event = ename;
      var _handleText = document.createTextNode(_handleFunc);
      _handle.appendChild(document.createTextNode(_handleFunc));
      _body.appendChild(_handle);
    }
    var _event = ename.substr(0,2) == "on" ? ename.substr(2) : ename;

    // Polyfill for non ie browsers
    if (window.addEventListener) this.addEventListener(_event, efunction, false);
  }
}

使用我的ActiveX对象的示例

<script type="text/javascript">
function MyObject_ObjectEvent() {
console.log('I am watching traditionally');
}
var _elem = document.getElementById('MyObject');
_elem.attachEvent('ObjectEvent', function () { console.log('I am watching anonymously') });
_elem.attachEvent('ObjectEvent', MyObject_ObjectEvent);
</script>

答案 2 :(得分:1)

根据kayahr的回答,我创建了一个在IE 11中进行事件注册的函数。 非常感谢你!它对我有用!

这是我的代码(不能作为_functionCallback参数使用匿名函数):

function AttachIE11Event(obj, _strEventId, _functionCallback) {
        var nameFromToStringRegex = /^function\s?([^\s(]*)/;
        var paramsFromToStringRegex = /\(\)|\(.+\)/;
        var params = _functionCallback.toString().match(paramsFromToStringRegex)[0];
        var functionName = _functionCallback.name || _functionCallback.toString().match(nameFromToStringRegex)[1];
        var handler;
        try {
            handler = document.createElement("script");
            handler.setAttribute("for", obj.id);
        }
        catch(ex) {
            handler = document.createElement('<script for="' + obj.id + '">');
        }
        handler.event = _strEventId + params;
        handler.appendChild(document.createTextNode(functionName + params + ";"));
        document.body.appendChild(handler);
    };

您必须使用浏览器嗅探,您的代码必须看起来像

if(BrowserDetect.browser == "IE" && BrowserDetect.version >= 11)
   AttachIE11Event(obj, "onSelected", method1);
else if(obj.attachEvent)
   obj.attachEvent("onSelected", method1);
else if(obj.addEventListener)
   obj.addEventListener("onSelected", method1);

答案 3 :(得分:-6)

ActiveX已从IE10中的浏览器中删除。在HTML5世界中,这项技术已经陈旧且越来越不必要了。

你没有提到插件正在做什么?它现在可以用标准代码替换吗?