2015-11-09

New S1000D-related blog

I have started a new blog that focuses on my work and experiences related to S1000D. The blog can be followed at http://www.s1000d-developer.com/.

If there are any specific S1000D-related topics you would like me to address and/or discuss, feel free to contact me.

2015-11-05

Connecting to ActiveX control events in IE11 mode

I have had the unfortunate recent experience of trying to get a web-based application that uses a commercial ActiveX control to work in IE11. In previous versions of IE (10 and earlier), one can use the attachEvent() method to add a callback to an ActiveX control-defined event. In the application I am working on, a dynamic <object> element is constructed to instantiate the control on a page. Then, attachEvent() is used to add callbacks to the events provided by the control.

For example, if control represent a reference to the <object> node, the following is how I attached to an event:

control.addEvent('FileChanged', myfunc);

In IE11 standards (edge) mode, addEvent() is not available since it is non-standard, where MS states to use addEventListener() instead. Unfortunately, addEventListener() does not work with ActiveX control events.

After some searching around, it appears there exists a way to attach to ActiveX events by creating a function whose name is the ID of the control, followed by "::" and the event name. For example, if the ID of the control is "myAxId" (when using the <object>, the ID is specified by the id attribute of the element), and the event name is "FileChanged", you can do:

function myAxId::FileChanged() { ... }

There is also a way to use <script> tags to bind to ActiveX events (see https://stackoverflow.com/a/152724/719934).

The problem is these are static-based approaches and do not work well when ActiveX controls are instantiated dynamically. Therefore, based on on the approach used at https://stackoverflow.com/a/10557222/719934, I created the following generic JavaScript function for connecting to an ActiveX-defined event:

function connectToAXEvent(o, etype, func)
{
  if (o.attachEvent) {
    o.attachEvent(etype, func);
  } else {
    var id = o.id, f = func;
    eval('(function(){'+
      'function '+id+'::'+etype+'(){'+
        'f.apply(f,arguments);'+
       '}'+
    '})();');
  }
}

The parameter o is the DOM node for the ActiveX control (i.e. the DOM node for the <object> element that instantiates the control). The etype parameter is the name of the event to bind to. The func parameter is the function to be called when the event is triggered.

For cases where you may already have the ID, you can change the function so it takes an ID string vs the <object> node.

So far, the function has worked in all IE modes. Of course, the function is only invoked in IE browsing contexts since other browsers do not support ActiveX. I do find it ironic that IE11 edge mode, which attempts to be standards compliant requires the creation of a non-standard function identifier ("::" is not allowed in function names) to connect to an ActiveX event. It would have been nice if MS supported the use of addEventListener() for ActiveX events.