//
archives

javascript

This tag is associated with 6 posts

JSON/JavaScript and large 64 bit integer values

JavaScript represents all numbers internally as 64 bit floating point values (see the ECMAScript spec here). This means JavaScript runtimes are not able to handle integer values larger than 9007199254740992 (2^53).

Note that all the positive and negative integers whose magnitude is no greater than 2^53 are representable in the Number type

Where this often causes problems is when a numeric JSON value is parsed by a JavaScript runtime, and the numeric value was generated by a system that does support 64bit (or larger) integers (e.g. Java or a database), and the actual value happens to exceed 2^53. The JavaScript runtime will (on FireFox and Chrome at least) round the value down, rather than reporting an error.

Probably fair to say that nearly all the time large 64 bit values are being used, they are being used as unique identifiers (as opposed to an outright measure of some quantity). In this case the usual workaround is to convert the numeric value to a string before converting it to JSON.

So if you’re transporting integer values over JSON you need to double check if the values can exceed the +/-2^53 range that JavaScript supports

View JSON in Firefox

I’ve found JSONView to be an extremely useful add-on for FireFox when developing with JSON based APIs. Its like a JSON equivalent of the XML viewing capabilities built into Firefox. Highly recommended.

Intercepting HTTP requests with JavaScript

If you are building an offline capable application, then I would posit that at some level in your client architecture you are going to need a Proxy. On one side of the Proxy will sit your presentation logic, on the other side will sit your business logic. When operating in online mode this Proxy will pass requests on to the remote server, when operating in offline mode the Proxy will redirect requests to some local implementation of business logic that provides a facsimile of the remote server’s behaviour.

For browser based applications, I feel a desirable place to position such a Proxy is at the browser’s HTTP interface. Implementing a Proxy at this level means that all means of initiating HTTP requests from within a browser can be proxied.  Indeed Google Gears takes exactly this approach, providing a ResourceStore into which resources can be cached, Gears then intercepts all HTTP requests made by the browser and if it detects a matching HTTP GET request for a stored resource, serves the cached version of the resource from the ResourceStore. This provides a means for an application to provide the static data it needs to ‘read’ when offline, but what about data the application needs to ‘write’ when offline? What about ‘read’ data that is constructed on the fly, for example the results of a query?

My colleague, Nikunj Mehta has just released a draft specification (I helped review this specification and I also helped build an implementation of an earlier incarnation of the specification) that aims to address these scenarios. BITSY specifies a means for browser based applications to provide JavaScript based callbacks to be called whenever a HTTP request is made by the browser. Applications can implement whatever logic they require in these callbacks, for example to mimic the behaviour of a remote server, or store data for later propagation to the server (when connectivity is resumed), or some blend of these behaviours. Similar to Gear’s ResourceStore, BITSY also specifies a DataCache to provide offline resource storage.

Debugging JavaScript on Internet Explorer Mobile

I was recently asked how I debug JavaScript code executing on Internet Explorer Mobile. First things first you need to configure Internet Explorer Mobile to show JavaScript Errors. As noted here you need to:

Change the Registry setting “HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main” and Create a new DWORD key under Main with the name “ShowScriptErrors“. Set dword value of 1

There are (at least) two ways to change registry settings on a Windows Mobile device/emulator. Firstly you can use the Remote Registry Editor (Start|Microsoft Visual Studio 2005|Visual Studio Remote Tools) that comes with Visual Studio. Alternatively you can install a registry editing application on the device, for example PHM Registry Editor.

Once you’ve restarted Internet Explorer Mobile it should start showing JavaScript errors. This and good old alert() are really all the tools you have at your disposal to do debugging. There is no way (that I know off) to attach to the JavaScript engine running on the Windows Mobile device and do remote debugging. In fact this is a problem for most if not all embedded browsers. 

One thing you can do is leverage XMLHttpRequest (XHR) to log messages to a remote server, sometimes useful when you need to log more information than will easily fit in an alert() dialog box on a cramped Windows Mobile display.

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.

Internet Explorer Mobile and JavaScript Content Type

Internet Explorer Mobile (at least version 6.12) will only parse JavaScript files served with a content type of ‘text/javascript’. Use other content types (e.g. ‘application/javascript‘) and IEm may silently ignore the file, and not parse it. The whole area of the ‘proper’ content type for javascript files seems to be a bit of a quagmire.

Twitter

The views expressed on this blog are my own and do not necessarily reflect the views of my employer.

Archives

Follow

Get every new post delivered to your Inbox.

Join 93 other followers