Blog

IE9 will support border-radius natively (yay!), but that still leaves all those users with an earlier version of IE in a world filled with dangerous sharp corners and no relief in sight. There are a ludicrous number of different scripts that have been created to try to solve this problem, but each and every one has one (or often several) of these fatal flaws:

  1. Requires style information to be resupplied in JavaScript
  2. Generates a huge number of DOM elements
  3. Creates corners that are not anti-aliased
  4. Unmaintainable, unreadable, or just plain bad code
  5. Inadequate documentation
  6. Requires additional plugins or images
  7. Breaks support for background-image/background-repeat
  8. Breaks direct descendant selectors
  9. Breaks in IE8
  10. Causes severe memory leaks due to circular references

So, I decided to come up with something better. RoundRect is a new, MIT licensed library (based loosely on the DD_roundies 0.0.2a source) that uses VML to provide a zero-configuration, nearly-fully-featured implementation of border-radius in IE. It still has some rough edges and comes with its own list of caveats (check the link for more info), but it does more, works better, and is better written than any other library that I’ve come across for creating round rectangles in IE. Check it out!

A major issue with large web applications is the difficulty in generating meaningful error reports for problems that occur on end-users’ machines. While debugging web apps during development has become exceedingly easy thanks to the great developer tools that Web browser manufacturers provide (and Firebug ;)), the task of automatically retrieving a stack trace from a remote machine is still painfully elusive.

Today, I’ve finished initial work on a small project that I am already using on an upcoming application to help alleviate this problem; I hope that it can help you too. Based on the hard work of Andrey Tarantsov, TraceKit is a JavaScript library that automatically normalizes and exposes stack traces for unhandled exceptions across the 5 major browsers: IE, Firefox, Chrome, Safari, and Opera.

TraceKit leverages native browser support for retrieving stack traces from Error objects where available, and squeezes out as much useful information as possible from browsers that don’t. It integrates neatly with jQuery, automatically wrapping all of your event handlers and AJAX callbacks so that you get the most useful stack information possible across the widest range of browsers without needing to tediously wrap everything yourself.

Finally, it attempts to extend support for column-level granularity of the top-most frame to all browsers, in order to allow you to debug even minified JavaScript. This does not work perfectly, and won’t until all browser manufacturers are exposing good stack trace information, but it ought to be more useful than nothing.

At under 8kB minified, and 3kB minified + gzipped, TraceKit should be suitable for any project that needs to be able to send back stack traces for error reporting and analysis. The best software is software that doesn’t generate any unhandled exceptions; I hope TraceKit helps you achieve that goal.

Get TraceKit on GitHub

I have been spending some time in jQuery chat lately, and something that comes up fairly often is the desire to repeat an action every n milliseconds. “No problem”, many will say. “Just use setInterval.” I consider this to be terrible advice.

Reason #1: setInterval ignores errors.

setInterval has a nasty habit of not paying any attention to whether or not the code it calls generates errors. This means that if, for some reason, an error occurs in part of the code that is called by setInterval, it will continue to call that code over and over again. Demo

Reason #2: setInterval does not care about network latency.

Let’s say you are polling a remote server for any new data on a fixed interval using AJAX. (Note: If you are doing this, you are probably doing it wrong; use backoff polling instead.) For some reason (server overload, temporary network connectivity loss, Slashdot effect, satellite/dial-up user, whatever), these requests are taking longer to complete than you thought they would. setInterval doesn’t care. It will continue firing those requests off, over and over again, until your client’s network queue is filled up with AJAX calls. Demo

The solution is simple: setTimeout

Instead of using setInterval, make the function call itself using setTimeout at an appropriate moment. In both of the above demos, function a does it wrong using setInterval, and function b does it more properly with setTimeout.

But what if I absolutely need the event to occur at the same interval every time?

If you want to ensure that your events are occurring on an ‘even’ interval, you can calculate the difference between your intended delay and the amount of time the last call took to complete and adjust your setTimeout delay appropriately. It is important to note, however, that JavaScript timers are not high-precision. You will never ever get absolutely even intervals, even if you use setInterval, for a variety of reasons (garbage collectors, the fact that JavaScript is single-threaded, solar flares, etc.). In addition, all current browsers will clamp the minimum timeout value to somewhere between 4ms and 15ms. So don’t worry too much about the difference!

ECMAScript revision 5 adds native support for ISO-8601 dates in the Date.parse method, but many browsers currently on the market (Safari 4, Chrome 4, IE 6-8) do not support it. Today, I wrote a simple duck punching replacement for Date.parse that will provide support for ISO-8601 strings if the native browser does not:

/**
 * Date.parse with progressive enhancement for ISO-8601
 * © 2010 Colin Snover <http://zetafleet.com>
 * Released under MIT license.
 */
(function () {
    'use strict';
    var origParse = Date.parse;
    Date.parse = function (date) {
        var timestamp = origParse(date), minutesOffset = 0, struct;
        if (isNaN(timestamp) && (struct = /(\d{4})-?(\d{2})-?(\d{2})(?:[T ](\d{2}):?(\d{2}):?(\d{2})(?:\.(\d{3,}))?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?))/.exec(date))) {
            if (struct[8] !== 'Z') {
                minutesOffset = +struct[10] * 60 + (+struct[11]);
                
                if (struct[9] === '+') {
                    minutesOffset = 0 - minutesOffset;
                }
            }
            
            timestamp = Date.UTC(+struct[1], +struct[2] - 1, +struct[3], +struct[4], +struct[5] + minutesOffset, +struct[6], +struct[7].substr(0, 3));
        }
        
        return timestamp;
    };
}());

This has been tested in Firefox 3.6, Safari 4, Chrome 4, Opera 10.50, and Internet Explorer 8. To the best of my knowledge, it supports all valid permutations of the ISO-8601 calendar dates and calendar dates with time syntax, so go crazy and parse some dates!

n.b. yes, I am aware that there are at least two other implementations of this on the Web; they are not nearly as efficient, they do not support all ISO-8601 dates, and they do not provide seamless support via the native Date.parse method.

MongoDB is totally unsuitable for anything that requires ACID—but for things that don’t, it is unbelievably awesome. It’s even me that excited “kid in a candy store” feeling which (being a jaded software engineer) I haven’t experienced in a long time. It’s amazingly fast and seems to be smartly written, providing the perfect balance between schemaless document storage and powerful querying capabilities.

I can’t give enough kudos to its rockstar developers for being incredibly responsive to user feedback, too. I reported a bug about an assertion failure I was experiencing, and in 2 days, it was fixed. Two days! By way of comparison, I’ve been waiting upwards of two years for some bugs in Zend Framework that cause database failures to be patched (despite providing patches).

MongoDB even has an automated nightly build system, so it’s stupidly easy to test out the latest features and fixes. I’m certainly interested to see what it can get up to in production (especially its auto-sharding, since distributed clusters have typically been a big headache for me in MySQL) but so far during testing it’s been sheer joy to work with.