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

Entries Tagged as 'Misc Toolkits'

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.

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.

Bring HTML5 and ECMAScript 5 to a browser near you

Posted by Dave Mahon

Unless you develop in-house sites for companies that have standardized on a very modern browser, you’re stuck developing sites for IE8 and even IE7. (Heaven help you if you’re still developing for IE6).

How then do you access some of the powerful features of ECMAScript or the contextual tags of HTML5 without having to write layer upon layer of fallbacks?

Your fellow JavaScript developers have produced shims to emulate most of this functionality, even in environments where Chrome Frame isn’t viable.

The html5shiv project is still under active development. It not only adds support for HTML5 contextual tags, it sets their default styling and makes them print in IE8 and below. Naturally, their canvas element is not going to have the behaviors you see in other browsers, but at least you can get away with a single set of markup and fewer CSS rules.

The es5-shim project is also under active development. It alters prototypes of native objects, so I wouldn’t combine it with prototype.js. This library also has the benefit of being well documented – including what does and does not differ from the specification. Heed the cautions from Kris Kowal, its author, though:

“As closely as possible to ES5″ is not very close. Many of these shims are intended only to allow code to be written to ES5 without causing run-time errors in older engines. In many cases, this means that these shims cause many ES5 methods to silently fail. Decide carefully whether this is what you want.

Event-driven development with Backbone

Posted by Dave Mahon

Do you really care if the user clicks an option inside of a SELECT? In most cases, it’s only a means to the end of getting the new value. So why is your change event handler sending data to the server and modifying the DOM? This leads to spaghetti code, violation of DRY and ever more expensive maintenance costs as your app’s interface evolves.

Thus was born Backbone, an extension of underscore, with default support for jQuery, and with a bit of editing, support for MooTools.

So let’s say you’re Amazon and you’re trying to find a way to comply with the legal requirements in some states that say affiliate sold items are subject to sales tax. This is complex and you probably only want to get the most relevant data as late in the process as possible. Backbone makes it surprisingly easy.

Bind to a change event on our data object:

var destination = new Backbone.Model();

_.extend(destination, {state: null});

var order = {
  subtotal: 100,
  tax: 0,
  total: 100
};

//underscore makes it easy to pseudo-subclass
_.extend(order, new Backbone.View());

destination.bind( "change", function() {
  //Pass null in the first parameter to save all model properties
  destination.save(null, {
    success: function(model, reps, xhr){
      //Apply the tax rate
      order.total = order.subtotal + order.subtotal * xhr.taxrate;

      //Update display. Note that this is a no-op by default and
      //you should define it as needed elsewhere.
      order.render();
    }
  } );
} );

Now for our event handler on the SELECT. Note that I’m using jQuery, but you could use any library (or none at all).

$("#state").change( function() {
  //Do whatever pre-processing is required
  var v = $(this).val();

  //This could be generalized very easily
  destination.set({
    state: v
  });
} );

Thoughts on Google’s Native Client platform?

Posted by Dave Mahon

Steven Shankland, over at CNET, has written an interesting piece about Google’s NaCl (yes, chemistry geeks, that is the formula for table salt). Overall, it’s a fairly balanced review.

On the one side, we get all of the benefits of WebKit, but with the performance of a compiled native application. In theory, that then allows us to write a knock-off of Photoshop and make it cross-platform, with easy electronic distribution.

On the other side, it’s not so cross-platform that it works on mobile devices and it does splinter development efforts. It only works on x86 CPU’s to date and it requires a browser plug-in API, which already dates it, since IE10′s Metro version will be plug-in-free.

Finally, Google and Mozilla both offer competing engines. Google’s Dart is intended to supplant JavaScript while Mozilla’s IonMonkey will further improve compiler performance.

Overall, if you’re willing to venture into relatively uncharted territory, have significant say in your deployment environment, and need as much performance as possible, this is an intriguing initiative. I just wonder how many of us developers fall into that bucket.

Moment.js: The successor to Date.js

Posted by Dave Mahon

We’ve discussed Date.js before. It is an amazing library that makes date manipulation simple. On their home page, perhaps the most elegant line of code is (3).days().ago();

There is a downside though – it’s abandoned. Its last full release was November 2007 and code was last committed May 2008. Moment.js, on the other hand, is still under active development.

It also has integrated support for NodeJS, but what’s particularly cool about it is the emphasis on human-friendly times. The from() and fromNow() methods will return strings like “in 5 days” or “a year ago”, while the format() method can simply be passed “LL” to display a localized date, without the time, simplifying development.

It also adds a diff() method, quickly returning the difference between two moment objects, but in units of your choice.

That said, there are some things it doesn’t do that Date.js does. The comparison methods like compareTo() and equals() are nowhere to be seen, although you could certainly use diff() to emulate them.

Likewise, hasDaylightSavingTime() can quickly be rewritten as

return moment({month: 0, day: 1}).getTimezoneOffset() !=
moment({month: 6, day: 1}).getTimezoneOffset();


which is actually more succinct than the Date.js implementation.