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

Entries Tagged as 'Javascript Frameworks'

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.

Gantt charts made easier, with ideas for improvements

Posted by Dave Mahon

Tait Brown has released an interesting jQuery extension for generating Gantt charts.

The most recent version adds support for local as well as JSON data sources and improves standard compliance while reducing the likelihood of CSS rule collisions.

One of the very first comments to the tumblr announcement was from jh asking, “Is it possible to represent dependencies among tasks?” This is an important Gantt chart feature, but not one that seems implemented – yet.

Using the live demo, I was able to inject a simple snippet between div.bar.ganttGreen and div.fn-label:
<div style="border-left: 1px solid #000; border-bottom: 1px solid #000; margin-top:-18px;height:30px; width:1px;"></div>

This produces a small black line to represent the relationship. While an arrow would be nicer, there is not enough space to represent it cleanly. I’m also using border-left and border-bottom so that it can eventually show relationships that don’t start and end at the same time.

Obviously, this is incomplete.

We will need to find a way to represent the relationship with another bar in the data. Each one is rendered by fillBars(), which simply iterates over the data property of the passed object, calling createProgressBar(). Presumably, we could add a parent property and use the array index of the parent bar as the value of parent.

We would still, however, need to calculate the relative positions of the bars, which will require a store of the row ID’s for each bar, so that we can test for visibility and horizontal and vertical positions.

These are not trivial changes, but they’re not insurmountable.

Hovercard – tooltips on steroids

Posted by Dave Mahon

Hovercard is a jQuery plugin that lets you hover what amounts to a tooltip. Except unlike your normal tooltip, this one supports event callbacks and lets you use arbitrary HTML and use as much space as you need.

They also provide support for Twitter and Facebook integration out of the box!

Suggested uses include virtual business cards, price comparisons and editing in place. Personally, my mind leaps to a web-based implementation of Civilization – it’s instant feedback on any cell in the world.

Check out their sample screenshot and imagine what you could do with it.
Hovercard Sample Screenshot

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.

Unexpected call to method or property access

Posted by Dave Mahon

If you’ve ever used jQuery’s append or prepend methods in IE8 with complex HTML fragments, you’ll probably recognize this message. I ran into it very recently when I was loading relatively simple HTML containing a relatively complex script into a modal window.

Naturally, the bug only occurred in Internet Explorer and the failure happened at line 4 of this block:
append: function() {
return this.domManip(arguments, true, function( elem ) {
if ( this.nodeType === 1 ) {
this.appendChild( elem );
}
});}

This seems like the least likely point of failure imaginable, but there was the error preventing the rest of the script from executing.

I found plenty of theories. There were some recurring themes though.

First, it is critical that you append well-formed HTML or the browser may justifiably fail. I tested mine fragment by wrapping it in some very basic HTML, HEAD and BODY tags with a DOCTYPE declaration and feeding it to the W3C Validator. That, unfortunately, did not work.

I disregarded the theories about buttons, because I had other scripts that referenced buttons and they worked fine.

One commenter (zmonteca) in the jQuery forums mentioned, “DispHTMLCommentElement,” which got me thinking. What exactly were this and elem and the moment of failure? After adding this to the Watch variables, I saw the problem. At some point in the loop, this became the SCRIPT element and elem became the DIV. Infuriatingly, at earlier iterations, the same nodes were in the correct order!

Now it all made sense. Both are valid HTML DOM nodes of type 1 (element), but it makes no sense to the browser to embed a DIV inside of a SCRIPT, just as you wouldn’t embed a BUTTON inside of an IMG. It would be downright… unexpected!

So the morals of the story are

  1. Always write clean, valid markup
  2. Be comfortable performing stack traces
  3. Really understand not just JavaScript, but HTML as well

Oh, and are you’re wondering how I dealt with the situation? I’ll own up to introducing a hack-ish patch to my copy of jQuery 1.7. I simply checked the tagName property of this and if it is SCRIPT, I reverse this and elem. This particular project is unlikely to have dynamically loaded OBJECT tags, so this seemed the fastest, cleanest way to deal with a bad issue when the markup itself validated.

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.

Underscore.js: jQuery without the DOM

Posted by Dave Mahon

DocumentCloud bills Underscore as “the tie to go along with jQuery’s tux,” but I think that this description is misleading.

In less than 4KB, and without manipulating object prototypes, it provides a superset of jQuery’s set manipulation, fills the gaps in IE’s implementation of arrays, types variables correctly and provides several other neat tricks.

Neat tricks, you say? How about automatically changing the value of this when you call a function? Or providing a very simple templating engine? Or elegantly handling variable name conflicts? Those would be the bind(), template() and noConflict() methods, respectively.

To top it all off, it uses native methods, in browsers that support it, and offers both object-oriented and functional coding support.

With no dependencies, a tiny footprint, and a huge punch, it’s a powerful tool at your disposal.

jQuery UI fixes: z-index and modals

Posted by Dave Mahon

jQuery UI is useful, but several of its widgets suffer from an annoying bug by design. If you never deal with simulated modal windows then you’ll never even experience it, but if you try to use an autocomplete or datepicker widget within a simulated modal window, you’ll find the dynamically generated DIV’s behind the modal.

You might try hardcoding a very high z-index to compensate for this, but it’s not terribly flexible, especially within a complicated third-party template.

That is why I now use this snippet in the beforeShow (date picker) or open (autocomplete) events, acquired from sources I no longer recall, to fix it.

function(input, inst) {
  var zMax = 1;
  $(input).parents().each(function(){
    zMax = Math.max(zMax, $(this).css('z-index'));
  });

  setTimeout(
    function() {
      $('.ui-datepicker .ui-autocomplete').css('z-index', zMax + 1);
    },
    300
  );
}

Sadly, the use of setTimeout() is necessary, because the event fires before the markup is appended to the DOM. You may be able to cut it down to about 150 ms, but that can sometimes fail in IE on slow machines.

Accounting.js A handy formatting library for numbers and finance

Posted by Don Albrecht

Today I stumbled across a handy little javascript framework called accounting.js.  Like the handy date.js library.  It focuses ongoing one thing extremely well. Convert numbers between simple strings of digits into nicely formatted easily readable strings.

it has just a few functions.

formatMoney()

by default, format the string to USD with 2 decimal places, comma separation at the thousands and a $ sign.  Optional params of [currencySymbol], [precision], [thousands separator], [decimal separator].

formatColumn()

just like formatMoney, but it takes an array of values and white space pads their conversions to the same length.

unformat(string)

parse a given number formatted string and return its numerical value.

Joss Crowcroft’s Original Blog Announcment is here:

http://www.josscrowcroft.com/2011/code/my-weekend-project-accounting-js/

And the GitHub site is here:

https://github.com/josscrowcroft/accounting.js