JavaScript Array Performance Oddities (Characteristics)

Update: We've added Opera 10.50 tests and rerun all tests on a MacBook Pro. Further links to the code and the running tests have been added.

When working with a programming language we often make assumptions about the performance of certain language constructs. However, as good engineers we know that whenever we make performance assumptions without measurement we drown a kitten.

When working with JavaScript arrays two independent assumptions are prevalent:

  1. They behave like C/Java arrays. Iteration over the contents and accessing data by index is fast - deleting entries and extending the size is expensive.
  2. They behave like JavaScript objects. Iteration over the contents and accessing data by index is slow - deleting entries and extending the size is fast.

It turns out that depending on the context both assumptions can be true or wrong. More on this later.

JS Arrays

Arrays are one of JavaScript's core data structures. However, arrays in JavaScript are a totally different beast than arrays in most other languages. In JavaScript arrays are a special case of objects. In fact they inherit from Object.prototype, which also explains why typeof([]) == "object". The keys of the object are positive integers and in addition the length property is always updated to contain the largest index + 1. This supports the second assumption (array == object).

Our Use Case

In our use case we wanted to improve our custom event layer. We store the list of event listeners in an array like this.

listeners.push({
  id: id,
  callback: callback,
  context: self
});

Working with the array is quite efficient but removing items by id is a linear operation. Since arrays are just special cases of objects we thought that rewriting the code to use objects should speed up deletions but maintains all other performance characteristics:

listeners[id] = {
  callback: callback,
  context: self
}

The somewhat unexpected result was that while deletions became faster the overall performance became much worse.

Array vs. Object

So while Arrays and Objects are conceptual almost the same, most JavaScript engines treat them very differently.

var ar = [];
for (var i = 0; i < 500000; i++) {
  ar[i] = i;
};
 
var map = {};
for (var i = 0; i < 500000; i++) {
  map[i] = i;
};

These two loops are almost identical but the first one can be up to 200 times faster (Firefox 3.6) than the second one.

So we know that arrays are treated differently by the JavaScript engines but under which circumstances do the optimizations kick in? To test this we kept the first loop but added the following statements before the loop:

  1. ar[10] = 10; // use the array as a small sparse array
  2. ar[50000000] = 10; // use the array as a huge sparse array
  3. ar.monkey = 10; // treat the array as an object

In addition we tested the same code but initializing the array backwards (counting down from 500,000),  the first time without any modifications and the second time initializing the array with new Array(500000) instead of []. The constructor parameter to Array is supposed to give the JavaScript engine a hint about the expected array size. Here is the outcome of the test runs across various browsers:

Array initialization

The tests code is available on Github. Click here to run the tests locally.

Analysis

The first observation is that there are huge differences between the browsers. The second observation is that depending on the context arrays are either extremely fast or as slow as objects.

  • WebbKit: In WebKit there is a huge difference between objects and arrays. Further it is the only one which can optimize the huge sparse array case. WebKit on the other hand doesn't like the reverse case at all. To me this looks like a bug in the implementation.
  • Chrome 5 (V8): The V8 JavaScript engine of Chrome does an amazing job. With the exception of the huge sparse array case, all tests took almost the same time. From a performance point of view there is almost no difference between objects and arrays.
  • FireFox: We have tested two FireFox versions. Firefox 3.0 with the old SpiderMonkey engine and FireFox 3.6 with the tracing JIT TraceMonkey. The characteristics of both are very similar with FireFox 3.6 being a lot faster. If the array is used purely as array, Firefox 3.6 is the absolute winner. In all other cases performance degrades to the much slower object case.
  • Opera: Since Opera 10.50 has a completely new JavaScript engine we've tested both Opera 10.50 beta and the current stable version 10.10. Both versions show a very different performance characteristic, which shows how much the JavaScript engine has changed. In Opera 10.10 there is almost no difference between objects and arrays. This indicates that Opera does not have any special optimizations for arrays. The overall performance is pretty decent. Opera 10.50 is a huge improvement. The performance is similar to V8 and the common tasks are even faster than on V8. Like V8 it has a peak in the huge sparse array test. (more...)

HTTP Redirects and Loss of Fragment Identifiers

Have you tried a demo URL like http://demo.qooxdoo.org/devel/demobrowser/#widget~Label.html lately? We use fragment identifiers (or anchors, if you prefer) to select specific demos within the Demobrowser, as the widget/Label demo in this case. Those URLs can be bookmarked, sent around, and appear in the browser's history so you can go back and forth between them using your browser's history navigation devices.

After we have off-loaded our demo subdomain to a different port, the main web server redirects requests for demo URLs to that port, and the client fetches the application from the new location. But as it turns out, some browser don't keep the fragment identifier across the redirect. While Firefox3 and Opera9.6 handle fragments just fine, IE7 and Safari4 choose to forget the fragment after the redirect, so you end up with the Welcome page in the Demobrowser instead of the Label demo. Funnily, all browsers send the request URL without the fragment id, so there is no difference here, and consequently there is no way of dealing with the fragment on the server.

I did a bit of research on the Internet, but there doesn't seem to be much concern about this behaviour. There is an hopelessly expired RFC draft which at least addresses the issue. But apart of that there is not much discussion which appears odd to me. I figure it would be a quite common situation where you have a large document with several anchors, and then the document might get relocated on the server. Now all URLs specifying one of those anchors would put you at the top of the document in half of the browsers, which is a serious loss of information.

qooxdoo strong in Taskspeed benchmark

Together with the release of Dojo 1.3 information was disclosed about Taskspeed, a new JavaScript library benchmark test. Taskspeed is created and maintained by Dojo's project lead Peter Higgins and is based on the well-known Slickspeed benchmark for CSS selector engines. Taskspeed now compares DOM manipulation performance of various JavaScript frameworks. The first published results see Dojo as a clear winner, leaving MooTools, jQuery and Prototype behind. It's interesting to note that the respective framework developers/authors supplied the tests for their own library, so the code should reflect the best practice and coding style for each library.

Taskspeed Firefox 3 results

Taskspeed Firefox 3 results

Taskspeed IE7 results

Taskspeed IE7 results

Of course, we wanted to know how qooxdoo compares in this "framework-neutral" test suite. qooxdoo's own DOM layer is not too old, it was released in August 2008 with qooxdoo 0.8 by splitting out all cross-browser code from the widget system. The last missing pieces were a CSS selector engine and a nice way to work with collections of elements. Both features were added to the qooxdoo 0.8.2 release that shipped only four weeks ago. While we were quite confident, we did not really know what to expect. But after complementing Taskspeed with the qooxdoo tests and looking at the results we were stunned. The results indicate that qooxdoo is on par with the fastest framework (Dojo 1.3) on most browsers except IE. On IE qooxdoo is by far the fastest framework.

Across browsers and frameworks, qooxdoo gained the highest ranks on all versions of IE (i.e. 6, 7 and 8), and made its lowest mark coming out third on Firefox 3.0. This exceptional IE performance also leads to the best overall score. The IE results are a big surprise and we'll try to investigate, what we do different (better) than all the other JavaScript libraries.

As always performance tests should be taken with a grain of salt. It's hard to judge whether all implementations are really equivalent. For example in the jQuery tests John Resig implemented all tests in a pure jQuery way. There are obvious optimizations he consciously omited, but it apparently reflects the genuine jQuery coding style. There is no official qooxdoo way to work with the DOM yet, so we modeled our tests closely after the Dojo and jQuery tests. Please note that the current tests don't run on a vanilla qooxdoo 0.8.2, but on the latest trunk. That's because the tests exposed two bugs in the framework, which had to be fixed. Most importantly however, no code was changed in the qooxdoo repository to make it perform better in the Taskspeed test suite.

Analysis

So why does qooxdoo perform so well compared to other frameworks?

  1. We build a GUI-toolkit on top: Our requirements for a DOM layer are different than those of pure DOM toolkits like jQuery, Prototype or MooTools. We build a whole GUI toolkit on top of the DOM layer and DOM performance is the weakest link in the chain. If DOM operations are slow, the whole widget stack is slow. For this reason we try to keep our DOM layer as thin as fast as possible. We do just enough to cover all cross-browser issues, but not much more. In qooxdoo 0.8 we use it mostly as an internal API to build our widgets. We had no incentive to add any syntactic sugar or convenience API which could have slowed things down.
  2. Sizzle: For the GUI toolkit we have no use for a CSS selector engine. For this reason we were probably the last JavaScript framework to add this feature to its feature list. We always intended to adopt an existing engine and John Resig's excellent Sizzle engine was a perfect match. Since Taskspeed requires the use of CSS selectors in a couple of tests, our good performance is in part due to Sizzle's good performance. Since the latest jQuery 1.3.2 has an identical Sizzle implementation but is rather slow in Taskspeed, there's obviously much more than pure selector speed.
  3. Collection API: This is the final link, which connects Sizzle with qooxdoo's procedural DOM API. The idea behind the Collection API is to convert the result of a Sizzle query into a collection instance, which provides all the chaining goodness of jQuery. The methods offered by the collection API match most of the jQuery API and map directly to our existing DOM layer. One trick used there is to subclass the native JavaScript array. This way we can conveniently access the elements matched using array accessors, and we can leverage native Array methods like filter, indexOf or map if available.

We plan to position qooxdoo's DOM level API as a standalone part of the qooxdoo framework. These results show that we have a good base and encourage us to move forward in this direction.

Please help the Taskspeed team to collect more data by running the tests yourself and submitting the results when asked for in a confirmation box.

Chrome – a browser designed for qooxdoo

"Google will release a browser" that was the news of the day. But what does this mean for qooxdoo? Judging just by reading the available information (before the release) it seems to be the browser we as JavaScript developers have been waiting for.

But wait a minute. A state of the art browser is nothing one can build over night. Not even Google can do this. Remember how long it took for the Mozilla team to create a somewhat decent bowser after being open sourced? The same is true for Safari. The first Safari basically sucked. Safari 2 was usable to surf the web but to run qooxdoo it had too many bugs and too poor JavaScript performance. Now Google tells us they have a brand new web browser, which is meant to raise the bar for all other web browsers. Normally I wouldn't expect much from a completely new web browser still in its beta stage but hey this is Google and they promise a lot. So of cause I had to download and test it.

I'm impressed

To make things short: "I'm impressed!". They really deliver what they promise. Chrome is really fast, the rendering is correct and I even like the UI. But the best is it runs qooxdoo without any modifications.

Chrome running the qooxdoo 0.8 demo browser

Chrome running the qooxdoo 0.8 demo browser

Granted they use the WebKit rendering engine, which we support, but most other parts of the browser (including the JavaScript interpeter) are new and could not be tested with qooxdoo before. Even gmx.com, a fairly large qooxdoo 0.7 application, runs without any problems.

Chrome running gmx.com

Chrome running gmx.com

Pushing browser technology

Its nice to see qooxdoo running smooth and fast in Chrome but what really matters to me is that this browser raises the bar for the other browser manufacturer technologically.

Finally JavaScript is getting some love. After WebKit's SquirrelFish and Mozilla's TraceMonkey Chrome's interpreter V8 is the third JavaScript interpreter within a very short period of time, which promises way better JavaScript performance. Good JavaScript performance is one of the key prerequisites to write even more feature rich web applications. Technically I should not call them interpreter as at least TraceMonkey and V8 use just in time compiling (JIT) but I'm used to use this term so I'll stick with it for the moment. Cool about V8 is not only the technology but also that they have released the source on the same day as the browser. Its under the BSD license, which basically means that everyone who wants to embed this interpreter is free to do so.

The second ground breaking feature is threaded browsing. In February Thomas has written a nice article about why Firefox should support one JavaScript interpreter per tab. Now a few months later Chome is here and does exactly that. Isolating the tabs from each other and especially the JavaScript interpreter in the different tab is a real killer feature to me. This is a feature your parents and grand parents have waited for - of cause without knowing it :-) There should be no reason that the UI of the whole browser freezes just because some badly written JavaScript code is running. With Chrome we see that at least Google can do better. My hope and my prediction is that we'll see this in Firefox and Safari in the not so far future as well. I'm not so sure about the Internet Explorer though. Maybe in the year 2012 in IE9.

Developer Friendly

To make a browser successful, tooling is a critical aspect. Anyone who ever had to debug JavaScript in IE6 and got the infamous "Undefined is null or not an object" error with no indication where the error happened knows what I am talking about. There is a huge difference between a browser, which can run AJAX applications and a browser which can be used to write AJAX applications. Fortunately the Google guys are tech guys and they stuffed a lot of interesting developer tools into Chrome. So Chrome definitely is a browser, which can be used to write AJAX applications.

Chome developer tools

Chome developer tools

Chrome developer features:

  • A process monitor, which shows how much memory, CPU and bandwidth is consumed by each tab
  • A stripped down version of WebKit's DOM inspector. Here is still room for improvements but is good to see this in the first beta release
  • A command line JavaScript debugger. This one is really geeky. I haven't yet figured out how to use this beast. Maybe I just wait for the GUI.
  • Gears is included

All in all I must say I'm more than impressed by Chrome. One can see that Google has written this browser with web applications like GMail in mind and what is good for GMail is clearly good for qooxdoo as well. The 'beta' label is probably only there because people expect this from Google. I've seen worse browsers marked as a stable release. My only gripe with Chrome right now is that its not yet available for the Mac.

I encourage everyone to download and test it - if you like it install it on your mother's computer :-)

Have fun

Update

I have to apologize to the Internet Explorer team. I said that I don't expect them to run the browser tabs in different threads. In fact IE 8 already has this feature. It was just slipped under my radar. I guess this is because they marked it mainly as a security feature. Thanks Markus for correcting me. Whether a browser isolates JavaScript execution can easily be tested by typing this URL javascript:while(1) {} in the location bar.

Working with text selection

Last week I started to implement a (still basic) low-level Text Selection API which especially the high-level form widgets like TextField and TextArea can make use of.

As some of you might already know working with the native Selection and Range / TextRange objects is not one of the things a developer dreams of :-)

However, looking at the basic implementation one thing is quite amazing. Besides a little tweak for Opera three (Gecko, Safari and Opera) of the four major browsers share the same implementation.
Sure there will be some more differences to encounter when the development of this low-level layer moves on, but the start looks quite promising.

Keyhandling for Safari 3.1 fixed

With the recent release of Safari 3.1 the WebKit team has completely reworked the handling of key events. John Resig has an interesting blog article with some details. Safari 3.1 now behaves pretty much like Internet Explorer and is in general much more sane than before. For instance, all those strange key codes larger than 64000 for special keys are gone and finally modifier keys like "shift" and "control" fire key events as well. Interestingly, Safari is now the first browser to support the key identifier property defined in the DOM level 3 event specification. In qooxdoo we already emulate this property in key events for quite some time now, and it really helps to simplify key handler code in our widgets.

Unfortunately, this change in Safari 3.1 broke the existing qooxdoo key event handler. But it is already fixed and available in our subversion repository for legacy_0_7_x branch and trunk. The fix was basically to detect the current WebKit version and use the existing Internet Explorer key handler code also for Safari 3.1 and above. Since all browser quirks are handled separately this was a pretty simple fix. Of course, it will be part of the next minor release 0.7.4 as well as the final 0.8. If you need Safari 3.1 support now, please checkout the latest version from the legacy_0_7_x branch.

Rounded borders – and how to do it in IE

In qooxdoo 0.8 we will introduce the concept of widget decorators. This has already been described in an earlier blog article. Decorators allow a widget's background to be styled independent of the widget's content. To demonstrate the flexibility of the decorator concept I have written a decorator, which uses native CSS rounded borders in Firefox and Safari/Webkit and emulates the same behavior in Internet Explorer. The screenshot shows the same qooxdoo 0.8 application in Internet Explorer 7, Firefox 3 Beta 3, WebKit r30082 and Firefox 2.0.11.

Rounded borders screen shot

The widget shown in the screen shots is generated by the following snippet of qooxdoo code:

 
doc = new qx.ui.root.Application(document);
 
var border = new qx.ui.decoration.RoundedBorder().set({
  radius: [10, 20, 30, 40],
  width: [3, 10, 20, 5],
  color: ["red", "green", "yellow", "blue"],
  backgroundColor: "gray"
});
 
doc.add(new qx.ui.basic.Label().set({
  html: qx.bom.client.Engine.NAME,
  decorator : border,
  width: 140,
  height: 100,
  padding: 20
}), 10, 10);

I think the most interesting question is about the IE implementation. Since IE has no native CSS rounded border support, the borders must be rendered using a different technique. A common approach is to render the borders using pixel-sized DIV elements like e.g. RUZEE.Borders does. We have used a different and in my opinion much more powerful approach.

We use VML to render the background including the border. The VML code is dynamically created and inserted into the decoration DIV using plain innerHTML. Since the decorator is informed about size changes by the qooxdoo layout engine, it can update its borders accordingly. The rendering quality is amazing and looks pretty much like the best native browser implementation of Firefox 3. This is the code automatically generated and applied by qooxdoo:

 
<style>v\: * { behavior:url(#default#VML);display:inline-block }</style>
 
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
<div style="left: 10px; width: 140px; position: absolute; top: 10px; height: 100px">
<div style="z-index: 10; left: 25px; width: 85px; position: relative; top: 23px; height: 37px" usehtml="true">mshtml</div>
<div style="z-index: 5; left: 0px; position: absolute; top: 0px">
    <v:group style="left: 0px; width: 140px; position: absolute; top: 0px; height: 100px; antialias: true" coordsize = "140,100">
    <v:shape style="width: 140px; height: 100px" coordsize = "140,100" fillcolor = "gray" path = " m10,1 ns l120,1 qx139,20 l139,70 qy110,99 l40,99 qx1,60 l1,10 qy10,1 x e"></v:shape>
    <v:shape style="width: 140px; height: 100px" coordsize = "140,100" fillcolor = "red" path = " m10,3 ns at5,3,15,13,10,3,5,3 wa0,0,20,20,0,0,10,0 wa100,0,140,40,120,0,140,0 at110,3,130,23,130,3,120,3 x e"></v:shape>
    <v:shape style="width: 140px; height: 100px" coordsize = "140,100" fillcolor = "green" path = " m130,13 ns at110,3,130,23,130,13,130,3 wa100,0,140,40,140,0,140,20 wa80,40,140,100,140,70,140,100 at110,60,130,80,130,80,130,70 x e"></v:shape>
    <v:shape style="width: 140px; height: 100px" coordsize = "140,100" fillcolor = "yellow" path = " m120,80 ns at110,60,130,80,120,80,130,80 wa80,40,140,100,140,100,110,100 wa0,20,80,100,40,100,0,100 at5,40,45,80,5,80,25,80 x e"></v:shape>
    <v:shape style="width: 140px; height: 100px" coordsize = "140,100" fillcolor = "blue" path = " m5,60 ns at5,40,45,80,5,60,5,80 wa0,20,80,100,0,100,0,60 wa0,0,20,20,0,10,0,0 at5,3,15,13,5,3,5,8 x e"></v:shape>
    </v:group>
  </div>
</div>
 

Generated HTML for Internet Explorer

The first two lines are required to enable VML support and are only added once into a page. Note that only one of the DIV elements contains VML code. The rest is typical HTML code generated by the qooxdoo GUI toolkit, which does all the layouting itself, just using JavaScript. It consists of a couple of nested, absolutely positioned DIV elements with the appropriate CSS styles applied.

The code for Firefox is much simpler and just sets the browser-specific CSS styles:

 
<div style="position: absolute; z-index: 0; left: 10px; top: 10px; width: 140px; height: 100px;">
<div style="position: relative; z-index: 10; left: 25px; top: 23px; width: 85px; height: 37px;">gecko</div>
<div style="border-style: solid; border-color: red green yellow blue; border-width: 3px 10px 20px 5px; z-index: 5; position: absolute; left: 0pt; top: 0pt; -moz-box-sizing: border-box; width: 100%; height: 100%; background-color: gray; -moz-border-radius-topleft: 10px; -moz-border-radius-topright: 20px; -moz-border-radius-bottomright: 30px; -moz-border-radius-bottomleft: 40px;"></div>
</div>
 

Generated HTML for Firefox

Native browser support

The quality of rounded border implementations differ a lot between browsers. The CSS3 draft defines the property border-radius and a property for each corner like border-top-left-radius. These properties take two values, one for the horizontal radius and one for the vertical radius. That way it is possible to define (quarter-)elliptical borders. If only a single value is given, the border is (quarter-)circular.

Current browser implementations

  • Firefox 2: Firefox supports only circular borders. Border definitions always take a single parameter - the radius. The CSS property is called -moz-border-radius and -moz-border-radius-topleft, respectively. -moz-border-radius supports the CSS shorthand mode. If only one parameter is given, the radius of all four border is identical. If four parameters are defined, the radius for all four corners is set individually. The rendering quality is very poor since Firefox 2 does not use anti-aliasing to render the border (cf. screen shot).
  • Firefox 3: The same as Firefox 2 but borders are rendered using anti-aliasing, which looks much better (thanks to the Cairo 2D graphics library).
  • Safari/WebKit: The CSS property names differ from the W3C spec (-webkit-border-radius and -webkit-border-top-left-radius). Besides that, WebKit implements pretty much the CSS3 standard. Rendering looks fine as long as all border widths are equal. If they differ, the rendering looks quite ugly (cf. screen shot). This has already been reported in the WebKit Bugzilla and hopefully is going to be fixed soon.
  • Opera: Opera also does not support CSS rounded borders but there is a description online on how to emulate them using SVG backgrounds.
  • Internet Explorer: No native support either. I suppose the VML approach presented here works only well in the controlled environment of the qooxdoo widget toolkit, but I may be proved wrong.

Adobe AIR powered API viewer

Adobe AIR is a new system to allow typical web applications to better integrate in the desktop. This includes access to file system resources, a local SQL database, and a controlable chrome for the "browser" window and some other goodies. The whole thing uses Webkit to render HTML pages. This is a great choice -- for qooxdoo based applications Webkit currently easily outperforms the other engines.

I have integrated AIR into the build system (trunk only). For a small demonstration I have created an AIR based API-Viewer of the current trunk. This can be used as an offline application. Including all API data the download is about 700 KB which is really small. (I had to zip the download again because of security limitations features of wordpress.)

In the current trunk each skeleton based application can be converted to an AIR application easily. Just execute "make air" in the root folder of your application. Unfortunately this feature required changes in a lot of files. This will be a trunk-only feature for now and will not be backported to legacy_0_7_x.

EDIT
(Removed the screenshot and the Air-based Apiviewer download, as both are no longer available).

Key Event Nightmare – Resolved

Since the 0.6.3 release, qooxdoo includes a complete rewrite of the key event handling layer. The old one was basically a wrapper for each browsers native key event handler. It fixed many cross-browser issues but nonetheless the differences between browsers were still visible to the application developer. The new key handler aims to unify key event handling across all supported browsers (Internet Explorer, Firefox, Opera, Safari) so that qooxdoo application developers always see the same behavior. This ambitious task turned out to be harder than expected...

Key events are one area of web browser functionality where standardization has not yet taken place. Although there is a W3C draft for keyboard events, it is more or less useless because no browser currently implements it. Even if it would be implemented, it would not solve all problems, because the standard is still incomplete. Pretty sad. For example, it has no concept of repeated key events which are fired repeatedly while the key is held down.

At first glance key event handling doesn't look so different across browsers. All major browsers support the three key events keydown, keypress, keyup and all key event objects have a keyCode property and properties for the modifier keys altKey, shiftKey, ctrlKey, metaKey. Unfortunately, under the hood all browsers behave quite different. Even the same browser can behave different on different platforms, e.g. Firefox under MS Windows and Mac OS X, respectively.

Key event handling is so challenging because of (at least) the following five shortcomings:

  1. Key code vs. Char code: Key events return codes for the actual key that is pressed (the key code) and the character that will be printed on screen (char code). Theses codes are represented as numbers and it is sometimes hard to figure out if a given code is to be understood as a key code or rather a char code. This is a severe problem because some numbers can be interpreted as either key code or char code. For example in key press events in Opera it cannot be decided whether the returned code is a key code or a char code.
  2. Keys that require shift on some keyboard layout: The key code of keys that require the shift key on some keyboard layouts are not reliable. The key code which is generated depends on the current language-specific keyboard layout of the user. The key “#” for example can be reached on a German keyboard layout without the shift key and generates the key code 35, while the same character composed with Shift+3 on an American layout produces a key code of 51.
  3. Repeated key events: If the user keeps pressing a key the browsers fires some events repeatedly. Normally, only the keypress event is expected to be repeated, but no other events. Under Windows however, both Internet Explorer and Firefox repeat the keydown event as well.
  4. Incomplete event sequences: Not every browser fires for every key the complete event sequence of keydown, keypress and keyup. Internet Explorer does not fire keypress events if the corresponding key is non-printable (i.e. function key F1). Firefox does not fire keypress events for modifier keys (i.e. Ctrl or Alt) and Safari does not fire any key events for modifier keys at all.
  5. Char code only reliable in keypress events: Only Safari sets the char code also in keyup and keydown events. The good news is that the character code in keypress events is reliable and always represents the Unicode number of the character that would be printed on the screen.

qooxdoo's new key handler solves most of above challenges by browser specific key handlers which differentiate between key and char codes and normalize the event sequence. This means for example that repeated keydown events in Internet Explorer are intercepted and passed on as keypress events and that the missing keypress events for special keys are synthesized if the corresponding keydown event is detected. To simplify the programming interface for qooxdoo developers we chose the W3C draft for orientation and implemented their keyIdentifier property. The keyIdentifier maps the key codes to a (human readable) key identifier strings. To prevent the developer from accidentally using keys which seem to be working in one browser but might not work in another, we introduced a white list of keys which can be detected reliably with the new key handler.

Unfortunately, a completely unified key handler is still not possible with today's browsers. Issues like the ambiguity of Opera's key code in keypress events or Safari not firing any key events for modifier keys can only be solved by the browser manufacturers/programmers. Nonetheless, we think that we came pretty close to the, to our knowledge, best possible solution and can offer one of the most advanced key event handlers out there.

For more detailed information you may consult the corresponding documentation of qooxdoo's new key handler and the following sources:

Safari support for qooxdoo coming

Safari support for qooxdoo is coming along nicely. qooxdoo support for the nightly build of WebKit is near to complete. Most demos and examples are working, including the API viewer . The screenshot shows the “At a Glance” example running in WebKit. Safari 2.0.4 shipped with the current OS X 10.4 is usable but still has some rendering issues.

WebKit - "At a Glance" example WebKit - API viewer

For the next qooxdoo release we plan to fully support WebKit, which hopefully builds the basis for the next major release of Safari shipped with the upcoming OS X 10.5. We decided to target WebKit because of its improved standard support and its dramatically faster JavaScript engine. Some qooxdoo examples are up to seven times faster using WebKit compared to Safari 2. Even if we would fully support Safari 2, it will never be a good platform for big JavaScript applications.

Next Page »
 

Control

 

Categories:

Archives:

 
SourceForge.net Logo

Bad Behavior has blocked 523 access attempts in the last 7 days.