Пользовательское событие ActiveX не может работать в IE11
Я обновил свой IE с 10 до 11 и обнаружил, что мое специальное событие ActiveX не может работать.
Причина в том, что IE11 больше не поддерживает attachEvent
, и мне кажется, что я должен использовать addEventListener
. Например, ранее я использовал
obj.attachEvent("onSelected", method1);
и теперь это
obj.addEventListener("onSelected",method1,false);
После изменения кода метод1 не может быть запущен. Я не знаю, как связать настраиваемое событие, которое реализовано в плагине ActiveX, с JS-методом и заставить его работать в IE11?
Ответы
Ответ 1
Единственным способом, который я нашел до сих пор для IE 11, является использование блоков for...event
script:
<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 вы должны поймать это исключение, а затем использовать другой метод.
Ответ 2
Изменяет код @Gerrit для работы анонимных функций, также он просто добавляет функции attachEvent обратно в IE 11 (и polyfill для не точечных браузеров, хотя и не проверен), поэтому можно использовать один и тот же код. Я рад, что нашел эту страницу. Я боялся, что мне придется делать это в VBScript или эмулировать более старую версию IE.
Поведение похоже на то же, что и в IE5.
Polyfill
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 : /*@[email protected]*/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>
Ответ 3
Основываясь на ответе 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);
Ответ 4
ActiveX был удален из браузера в IE10. Технология была старой и все более ненужной в мире HTML5.
Вы не упомянули, что делает плагин? Можно ли заменить его стандартным кодом?