jQuery on Internet Explorer Mobile

Lately I’ve been trying to get jQuery working on IE Mobile 6.12 (IEm). Best I’ve managed is to mock up IEm versions of the subset of jQuery API methods that I needed for the project I’m working on. Below are my notes on the particular jQuery methods that presented challenges:

jQuery.clean()

There are a couple of challenges with constructing DOM elements from text:

  • DOM elements can only be manipulated when attached to the current document, before you call appendChild(), removeChild() etc. on an element it must be first attached to the current document. I used a scratch <div> element (set to display:none) to which all elements that were to be manipulated were attached for the duration of the manipulation
  • It is only possible to create element nodes, you cannot create text or any other kind of DOM nodes. Thus the following cannot be supported on IEm: $('Hello <i>World</i>'). The 'Hello ' text is not contained within a element node, and so cannot be handled on IEm.

find()

I only built support for a subset of this method’s functionality, namely: find element by id, find element by class name, find element by attribute value, and find elements by tag name. In all cases I could only produce reliable results by walking the DOM (which is known to be inefficient across all browsers).

The only way to traverse the IEm DOM is via the childNodes collection, firstChild, nextSibling etc. are not supported. Only element nodes are present in this collection, text within an element is accessed via the innerText property of an element and attributes are accessed via the getAttribute() method. the class attribute is accessible via the className property on an element. The tag name is accessible via the tagName property.

attr()

This method is used in two ways:

  • retrieve value of attribute
    • use getAttribute() method to retrieve value
  • set value of attribute
    • set the attribute directly e.g. anchor['href']='http://www.oracle.com'

css()

The css for an element be read and written via the element’s style property. e.g. e.style['display'] = 'none';

text()

The text of an element can be read and written via the element’s innerText property

ajax()

IEm supports the same ActiveX XMLHttpRequest (XHR) control as desktop IE, it is instantiated in the usual fashion. Note the IE XHR implementation will only create an XML DOM for responses if the content type is 'text/xml'. To work around this I manually parsed the responseText property if the XHR did not treat the response as XML. The same MSXML ActiveX object as is present on desktop IE is present on IEm.

bind(), change()

IEm does not support binding event handlers via javascript, the event handler must be specified via the relevant onevent attribute in the html. The set of events that are supported on the various HTML elements is very limited, e.g. the onclick event is not supported for <span> elements. When event handlers are invoked they do not receive an event argument, the window.event property found on desktop IE is not present either; the this value does point to the element which originated the event.

For static HTML defined in the html file itself you are left with no choice but write explicit event handlers in the HTML code itself, which is at odds with the jQuery’s principle of separating behaviour from presentation. You may not be able to use the full range of events found on other platforms and you will probably end up having to wrap elements in <div> tags in order to attach event handlers to them.

If you need to bind event handlers to HTML code constructed dynamically – via the $(...) method – then there is a workaround, its not pretty but it will work. By changing the behaviour of the jQuery.clean() method (which is responsible for constructing DOM elements from text), elements to which event handlers might be bound can be rewritten to include a unique id (if not already present) and an explicit event handler. So the following code: $('<a href="#">...</a>') would generate HTML looking something like this: 
<a href="#" id="jQuery.id.37" onclick="jQuery.dispatch('click','jQuery.id.37')">

The jQuery.dispatch() method is a jQuery extension method I defined. It is passed two arguments: the event type and the id of the element which originated the event. jQuery.dispatch() uses this information to lookup an internal associative array to find the event handler(s) bound to the particular event type on the element with the specified id and invokes the handler.

The implementation of the bind() method needs to change to associate the event type and the element’s id with the appropriate event handler in the same associative array that jQuery.dispatch() uses.

The change() method is used to either set the change event handler for an element or to generate an onchange event. It should be adapted to either call bind() or jQuery.dispatch() as appropriate.

7 thoughts on “jQuery on Internet Explorer Mobile

  1. Hey man…do you have any experience with IE Mobile and CSS? I’m starting a project and running into some basic problems with floating multiple elements. Any idea whether this is worth my time debugging, or whether I should whip out and code like it’s 1999?

    Any advice would be helpful. Thanks!

    -Nate

  2. Hi, I was in the middle of gutting my way through writing a dispatcher for use with jquery, any chance you would share yours? 🙂 I understand if not. Mail is gmail, ben dot clemens. Thanks…

    • @Ben here’s the gist of the dispatcher logic:

      JQuery.lookup = {}; //table to store event bindings

      JQuery.prototype = {
      ... // rest of JQuery prototype defns
      /* modified bind() impl
      * @param e The event type e.g. 'change'
      * @param fn The callback to be dispatched when event of type e is raised
      * Store the mapping from event e to handler fn in the internal JQuery.lookup() table for this element
      */
      bind: function(e,fn) {
      var id = this[0].id;
      if (id == "" || typeof id == 'undefined')
      throw ("To bind an event to a JQuery object, it must have an 'id' property.");
      var mappings = JQuery.lookup[id];
      if ( mappings == null ) {
      mappings = {};
      mappings[e]= fn;
      JQuery.lookup[id] = mappings;
      } else {
      mappings[e] = fn;
      }
      return this;
      },
      //bind a handler for the 'change' event or dispatch an 'onChange' event
      change: function(fn) {
      if ( fn ) {
      this.bind('change',fn);
      } else {
      var id = this[0].id;
      JQuery.dispatch('change',id, {target: this[0]});
      }
      return this;
      },
      ... // rest of JQuery prototype defns
      };

      JQuery.dispatch = function(e,id, event) {
      var mappings = JQuery.lookup[id];
      if ( mappings ) {
      var fn = mappings[e];
      if ( fn ) {
      elem = document.getElementById(id);
      var fix = {
      target: event.target ? event.target : event.srcElement
      };
      fn.call(elem, fix);
      }
      }

  3. Did you manage get a workable IEM jQuery? I am developing a mobile application and I am trying to decide whether it is worth trying to use jQuery. Would you be willing to share your subset jQuery API?

    • I don’t believe what I managed to get working was really sustainable, performance was pretty bad, and it probably leaked memory lots. Your only option for using JQuery on Windows Mobile is to wait for Windows Mobile 6.1.4 (not yet released). I’ve tested JQuery on that version and although the JQuery test suite fails, JQuery seems to work well enough. Sorry, I’m not in a position to share the code.

Comments are closed.