Ajax Bestiary: A Javascript Field Guide
 
Ajax Bestiary: A Javascript Field Guide
 
 

Entries Tagged as 'Javascript Frameworks'

Enyo released

Posted by Dave Mahon

HP is slowly open sourcing webOS. Yesterday, they released the Enyo framework with cross-browser support.

The heart of Enyo is the enyo.kind() method which dynamically generates a reusable page component which can be referenced in the global namespace like so:

enyo.kind({
    name: "Hello",
    kind: enyo.Control,
    components: [
        {name: "hello", content: "Hello From Enyo", ontap: "helloTap"},
        {tag: "hr"}
    ],
    helloTap: function() {
        this.$.hello.addStyles("color: red");
    }
};
 
// make two, they're small
new Hello().write();
new Hello().write();

At first glance, this seems like a lot of extra code to create a bit of color-changing text with a horizontal rule. However, you can also define custom properties, events and methods, which suddenly makes this an elegant way to create what jQuery calls plugins. Since you can also encapsulate other generated kinds, this could also be an interesting way of creating entire actors within a game.

While it’s not so performant as to empower, say, a first-person shooter, they do provide a simple demo of a game.

HTML5 Interactive Maps for Both Mobile and Desktop

Posted by Dave Mahon

When you think maps, you probably think Google or MapQuest, both of which have interactive maps that are really only optimized for desktop browsers. You have to jump out to a separate app for geo-interactivity (yes, that is an invented word).

That is perhaps why CloudMade released Leaflet, putting it under the BSD license.

As you would expect, it supports tile layers, polylines, markers, popups and image layers. However, it also has native support for panning and zooming on mobile browsers. It also uses CSS3, so you can stylize pins, popups and controls. It’s also fast – noticeably faster than Google Maps – though that is partially because its source data, OpenStreetMap, doesn’t contain quite as much data.

At this time, supports most desktop browsers well, but on mobile environments, it requires iOS 3+ or Android 2.2+.

Implementing a map is very straightforward:

// create a CloudMade tile layer
var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/YOUR-API-KEY/997/256/{z}/{x}/{y}.png',
    cloudmadeAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade',
    cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18, attribution: cloudmadeAttribution});
 
// initialize the map on the "map" div
var map = new L.Map('map');
 
// set the map view to a given center and zoom and add the CloudMade layer
map.setView(new L.LatLng(51.505, -0.09), 13).addLayer(cloudmade);
 
// create a marker in the given location and add it to the map
var marker = new L.Marker(new L.LatLng(51.5, -0.09));
map.addLayer(marker);
 
// attach a given HTML content to the marker and immediately open it
marker.bindPopup("A pretty CSS3 popup.<br />Easily customizable.").openPopup();

Leaflet generated map

Remote console for mobile web diagnosis

Posted by Dave Mahon

Remy Sharp has developed a tool for remotely debugging web pages. This works using code injection, so be very sure to keep it out of production environments. However, when you need to diagnosis issues remotely, say, because it’s on a mobile device, with limited console support, or because a client is reporting problems that you can’t repeat locally.

Implementing this is a snap!

:listen

This returns an UUID which you will need to insert into the page markup:

<script src="http://jsconsole.com/remote.js?FAE031CD-74A0-46D3-AE36-757BAB262BEA" type="text/javascript"></script>

From then on, calls to console.log() will return their output to your listening machine.

The really handy library has one more trick up its sleeve. You can specify the UUID to which you will listen.

:listen FAE031CD-74A0-46D3-AE36-757BAB262BEA

When the remote device loads the debugging module, you’ll see something like this in your console:

:listen FAE031CD-74A0-46D3-AE36-757BAB262BEA
Creating connection...
Connected to "FAE031CD-74A0-46D3-AE36-757BAB262BEA"
Connection established with Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-GB; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8

Incremental MD5 with AMD support

Posted by Dave Mahon

As we all know, MD5 is a fast hashing algorithm. While its numerous security holes make it undesirable for encryption, it is pervasive and convenient for quickly generating quasi-unique ID’s.

While JavaScript has no built-in support for hashing algorithms, this wheel has been re-invented a lot. So why discuss it here? Most implementations to date have littered the namespace with variables or offered poorer performance than their rivals.

SparkMD5 attempts to remedy this situation. Based on the JKM md5 implementation, it is fast. However, it also keeps namespace pollution to a minimum, with its use of closures and OOP.

In addition, it has two neat tricks up its sleeve.

First, you can incrementally hash strings:

var spark = new SparkMD5();
spark.append('Hi');
spark.append(' there');
var hexHash = spark.end();                    // hex hash
var rawHash = spark.end(true);                // OR raw hash

This is particularly handy for large strings, like what you might get using the FileReader API. Conveniently, Andre Cruz, the developer of SparkMD5, has included the code to do this in the GitHub README.

Second, it optionally supports Asynchronous Module Definition, which can reduce the initial load-time of pages and helps isolate your code from your markup. While AMD is certainly controversial, asynchronous loading of code does seem to be a prevailing trend.

TWSS: Naive Bayes Classifier and k-Nearest Neighbor library for NodeJS

Posted by Dave Mahon

TWSS is an acronym that stands for That’s What She Said, a joke frequently abused by the character Michael Scott on the US version of The Office. Why would anyone write a library that tells you whether or not "That’s what she said!" is an "appropriate" response to a given sentence? Frankly, I don’t know. However, during implementation, he created a generalized document NBC and k-NN tool that runs cleanly inside NodeJS.

In effect, with different training material, this is a powerful tool with an MIT license. Its also potentially very expandable.

So let’s see it in action.

Set the algorithm:

twss.algo = 'nbc';

Set the tolerance threshold:

twss.threshold = 0.5;
twss.is("You're hardly my first."); // false
 
twss.threshold = 0.3;
twss.is("You're hardly my first."); // true

Or, for your customized tool, return the probability:

twss.prob("The juice keeps coming out of the wrong hole!"); // 0.9961630818418142

How do we expand our algorithm selection? Look in /lib/twss.js:

var classify = {
  nbc: require('./classifier/nbc'),
  knn: require('./classifier/knn')
};

As you can see, adding algorithms is primarily a matter of a new file in the classifier subdirectory and adding a member element to the classify object. The new classifier must implement getTwssProbability() and isTwss().

However, you will have to lightly edit exports.probability() and exports.is() to recognize your custom algorithm.

UPDATE My apologies for the links to Wikipedia on the day of the SOPA blackout.

jQ.Mobi: Less compatible, but better performance

Posted by Dave Mahon

The plain reality is that the vast majority of mobile web traffic is on Android and iOS devices. BlackBerry users have, by and large, been so disappointed by the poor web experience out of the box that they tend not to go on the web. Windows smartphones are still a small slice of the mobile market, especially when you focus on 3G and LTE devices, which use the lion’s share of the traffic, at least until Nokia ramps up its smartphone production.

With that in mind, jQ.Mobi saw its first public release on Monday. Its developer, appMobi, calls it a beta.

The core engine and UI is 15KB gripped, which means that even when your user drops to EDGE, they’ll still have a good experience, since you still have 10KB leeway for images and markup. It is also optimized for simulating apps, including support for integration in tools like PhoneGap.

Further, it’s designed to make the interface as consistent as possible between Android and iOS devices, including fixed headers and footers and smooth CSS3 transitions. It’s not quite ready for tablet devices. If you watch the video, the interface during the Kindle Fire segment feels clunky, but they say they are working on tablet-optimized CSS.

In terms of syntax, jQuery users will feel at home. Still, be cautious with jQuery plugins, because while they should be run, many are still optimized for desktop environments and jQ.mobi is not intended for desktop use.

Loopy Optimizations

Posted by Dave Mahon

We all know that code optimization is important, especially when processing large quantities of data. It is also common knowledge that adding layers of code to loops reduces performance. Except this maxim doesn’t always hold when it comes to JavaScript in browsers and even native methods can vary wildly in performance. In fact, in almost all cases, Underscore, jQuery and YUI outperformed any of the native methods. Interestingly, the newest implementation for native looping, forEach, consistently trumped a traditional for (var i = 0; i < 2500; i++) loop.

I set up a testing framework that looped through a normal array instantiated like so:

var data = [];
var v = {}; //This value doesn't seem to affect performance at the data size I chose
 
for (var i = 0; i &lt; loops; i++) { //loops is defined elsewhere
   data.push(v);
}

I looped through this array using the following methods:

  • for loop
  • for … in … loop
  • forEach loop (not supported in IE9 Quirks Mode)
  • Prototype 1.7: Enumerable.each
  • jQuery 1.7.1: $.each
  • Underscore 1.2.3: _.each
  • YUI 3.1.4: YUI.each

Each loop was passed the value of the array element and returned immediately, like so:

//From the native for and for ... in ... tests
(function(el){return;})(data[i]);

I eventually settled upon an array of 2500 elements and running the test 200 times to collect a reasonable number of samples. These numbers were not chosen arbitrarily. Prototype would time out on Firefox at 5000 array elements and Safari seemed to have wildly varying results on each run of the suite with fewer than 200 samples. With 200 samples, the variance in mean time between runs became a few hundredths of a millisecond, not enough to be of consequence. Disturbingly, while Prototype froze the browser with 5000 array elements and 100 samples, it had no issue with 2500 elements and 200 samples. Even so, with some tests averaging less than a hundredth of a millisecond, we will soon require much larger data sets to get meaningful results at all, which may preclude the inclusion of Prototype (and even native methods!) in future tests.

All tests were run in a freshly launched browser on an updated operating system (either MacOS 10.7.2 or Windows 7 Home Premium) running on a MacBook Pro with a 2.53GHz Intel Core 2 Duo processor and 4GB of 1067MHz DDR3 RAM. Firefox had all add-ons disabled and Internet Explorer had the Developer Tools open (to switch between Standards and Quirks mode).

So let’s look at some charts!

Mac safari
This was certainly an interesting start to the process. YUI, Underscore and jQuery all clocked in at 0.005 ms. Prototype would prove to be faster than native methods, with the exception of forEach, on all browsers. Underscore was only be outperformed on IE 9 (32-bit, Standards Mode).

Mac chrome
Chrome was exceptional as well, with the traditional for loop actually running slower than for ... in .... This behavior was also seen on Chrome for Windows and Safari for Windows.

Since all of the major browsers are clearly pre-optimized for these libraries (as they themselves wrap the native looping language structures), let’s look at just the libraries:
Loop run times, by library
Here we can begin to see that Prototype really is behind its peers in loop performance. While we are talking fractions of a millisecond, our apps are growing larger by the day and this could become a serious issue.

Run times of non-prototypical libraries by browser
Hey! It looks like Firefox really is slow. Curiously, IE 9 is significantly faster, which flies in the face of most generalized JavaScript performance metrics.

Still, something looks odd about IE:
Run times by library and version of Internet Explorer 9
Your mileage varies wildly depending on whether you choose standards or quirks mode, and not always in obvious ways. In general, 64-bit is faster, but only marginally, and most people are not using it. (You have to explicitly launch it, as it is not the default, even on 64-bit Windows). Meanwhile, quirks mode apparently embeds some performance hacks. As a note to benchmark developers, this should be evidence enough that not all IE’s are the same and we need to start breaking down by rendering mode and compilation.

So far, we’ve seen the average times and most browsers are quite acceptable. What are the worst case scenarios?

Platform

Browser

Method

Max (ms)

Mean (ms)

Windows 7

IE 9.0.8112.16421 (64-bit IE 9 Quirks)

for

93

5.29

Windows 7

IE 9.0.8112.16421 (32-bit IE 9 Standards)

forEach

81

4.04

Windows 7

IE 9.0.8112.16421 (64-bit IE 9 Quirks)

for in

81

6.27

Windows 7

IE 9.0.8112.16421 (32-bit IE 9 Standards)

for in

76

9.87

Windows 7

IE 9.0.8112.16421 (64-bit IE 9 Standards)

for in

71

4.89

Windows 7

IE 9.0.8112.16421 (32-bit IE 9 Quirks)

for in

67

5.995

MacOS 10.7.2

Firefox 9.0.1

for in

55

1.885

Windows 7

Firefox 9.01

for in

52

6.055

Windows 7

IE 9.0.8112.16421 (32-bit IE 9 Quirks)

for

49

4.66

Windows 7

IE 9.0.8112.16421 (64-bit IE 9 Standards)

for

48

4.76

Windows 7

IE 9.0.8112.16421 (32-bit IE 9 Standards)

for

39

7.845

Windows 7

Chrome 16.0.912.75 m

for in

30

1.13

Windows 7

Chrome 16.0.912.75 m

for

26

1.315

MacOS 10.7.2

Chrome 16.0.912.75

for

23

1.175

MacOS 10.7.2

Chrome 16.0.912.75

for in

22

1.085

MacOS 10.7.2

Safari 5.1.2

for in

16

1

Windows 7

Firefox 9.01

jQuery

6

0.185

MacOS 10.7.2

Safari 5.1.2

for

5

0.52

MacOS 10.7.2

Firefox 9.0.1

for

5

0.7

Those averages hid some extreme variations within Internet Explorer. Fortunately, most of these are found using native language structures, which we know better than to use.

Learning Ext JS

Posted by Dave Mahon

I’m teaching myself Ext JS, but it’s not always the easiest framework to wrap your head around. That said, there is a wonderful site full of examples of specific techniques, not just API’s.

Saki's Ext Examples Page divides the examples into categories like Application Design > Complex Data Binding or Drag & Drop > Free Drag with State.

However, you don’t just get a monolithic example. You can run the example and see the source code divided by language. Be sure to check out the Details and Further Reading links in the lower-left pane.

Remember that Ext JS has been folded into the Sencha project and the examples are written to Ext JS 1/2, not 4, the current release. Sencha provides a set of current examples, albeit not as elegantly broken down for easy consumption. Those caveats aside, these examples can help you understand the structure and design of Ext JS, so it's still a worthy read for those of us coming from other libraries.

jQuery Mobile 1.0 Final

Posted by Dave Mahon

The long anticipated jQuery Mobile library has hit version 1.0 Final. With support for most mobile devices, it facilitates rapid development of mobile friendly sites.

Note that it does require jQuery 1.6.4 and the jQuery Mobile 1.0 CSS file, in addition to the jQuery Mobile 1.0 JavaScript file. This means that pages that use it will very likely exceed the 25KB limit of some very old phones, preventing the page from loading at all on them. That said, most phones sold since 2008 do not have this limitation, so it shouldn’t hinder you too much. Still, focus on keeping image assets, JS, CSS and HTML as optimized as possible, because mobile performance is still pretty slow for most users.

Also, it does require a number of custom attributes, so you will want to explore their Getting Started documentation.

The sound of music is silence and sometimes a click

Posted by Dave Mahon

HTML5 begat the AUDIO tag. Now that we have it, what do we do with it? And how do we accommodate older browsers?

Unfortunately, there are two incompatible standards and the W3C Audio Working Group "has not decided upon a specification".

The Web Audio API works on recent builds of Chrome and Safari. The API includes complex filters and allows developers to roll drum machines and visualizations. It’s active by default on Chrome 16, but not on Safari 5. Worse, Safari 5 reports that it is supported, but won’t run the samples to which I have linked. Adding insult to injury, it’s also slow and can randomly introduce skips and clicks.

Mozilla introduced the Audio Data API, but it only works in Firefox 4 and above. It’s also a very low level API and requires intermediate libraries to be truly useful for non-developer apps, of which there are a number. Like Google’s Web Audio, it’s slow and can randomly introduce skips and clicks.

Since these two technologies encompass only about half of web traffic, we clearly need fallback mechanisms.

There is SoundManager2 which uses both HTMl5 and Flash 8 or 9+ to bridge platforms. It relies on MP3/AAC/OGG/WAV sample files and supports panning, sampling and – most valuable – event support. Events like whileplaying and onposition make it easy to sync your audio and video. Beyond equalization, volume and start/stop positions, however, you can’t do much to filter the sound output.

You might also try Audiolet, which lets you generate your own waveforms in browser, giving you a full range of freedom, but it’s going to sound like 8-bit audio unless you use samples. (Hint: try combining it with MUSIC.js to make the most of that 8-bit arcade sound)

Then there is audiolib.js, which goes even lower than Audiolet and can operate server-side. It allows you to both manipulate and generate audio samples in PCM format, which it can then save for future use.

Audiolet starts quickly and is half the size of SoundManager2, but can click and skip, especially when the browser is scrolling or otherwise pre-occupied. SoundManager2 can bog down when playing too many sounds at once. Try activating +follow and then moving your mouse quickly over its Smashing Christmas Lights demo to see this in action.

Audiolib is extremely low level, but for generating short realistic waveforms, it is effective and fast, both client-side and server. Sadly, in Firefox 9 on my Mac, this example only plays the first bell while Safari 5 and Opera 11.6 played nothing at all. Chrome 16 played it correctly. However, when I had the page open in 3 browsers simultaneously, even though only one was generating noise, the load was causing skipping and clicking in Chrome. Your audio could easily suffer if the end user’s computer is otherwise busy.

In short, there is no good solution yet that is widely supported and flexible and performant, even within modern browsers.