A few weeks ago, I launched a new blog called Badass JavaScript (http://badassjs.com). It showcases an awesome piece of JavaScript code every day. So far, it has been a success! Here are some of the awesome things that have been showcased so far:

  1. Barcode Scanning In JavaScript
  2. Music Notation with HTML5 Canvas
  3. TypeSet: An implementation of the TEX Line Breaking Algorithm in JavaScript
  4. Realtime Video to ASCII Converter In JavaScript
  5. The Aves Engine: High Performance Games In JavaScript
  6. Sencha Touch: A Cross Platform HTML5 Mobile Application Framework

Check it out!


At Google I/O last week, Google announced that it would be open sourcing what it calls the WebM video codec. Immediately, there was talk about this “open” codec becoming the video format of the web, with browsers like Firefox and Opera jumping on the bandwagon as fast as they could. While I think that it is great to have an open codec, not encumbered by patents, and that anyone can produce and consume freely, I also think that we are already so entrenched with h.264 video that it will be almost impossible to just “switch” to this new codec. Here is why all of the hype around this codec is unfounded:

  1. h.264 is already available nearly everywhere – h.264 video is viewable on nearly all devices. It is available on both Mac and Windows computers with no installation necessary, on nearly every mobile device including the iPhone, iPad, and even Android devices. This ubiquity will make it hard to compete with.
  2. Lack of hardware decoders – there are hardware decoders for h.264 video in almost every mobile device, and even some laptops and desktops. This makes decoding h.264 video very fast, and uses less CPU cycles than a software decoder would, while raising the battery life considerably. The reason that you can watch a movie for 10 hours straight on an iPad is because the hardware decoder for the h.264 video uses very little power. So why can’t these devices just add a WebM hardware decoder? First of all such a chip doesn’t exist yet, but more importantly, there probably isn’t the room for two decoders in today’s already cramped devices. For instance, all of the video in Apple’s iTunes store is encoded using h.264, and thus they need the h.264 decoding chips in their devices. They are not going to add a second chip just unless several major content producers switch their videos to WebM with no h.264 fallback.
  3. Lack of encoders – applications that produce video content do not export WebM video, but they do export h.264. This can be consumer grade applications like iMovie or Windows Movie Maker, or professional applications like Final Cut. Of course, you can get a converter, but that adds an additional step that, depending on how long your video is, could take a long time (video conversions are slow). Also, depending on browser support, they may need to produce a WebM version, an h.264 version, as well as a Flash version. I don’t think that content producers are going to want to do this, just so that their videos can be in an “open” format.
  4. Patents – Apple and Microsoft both have patents in h.264 video, and they probably don’t want to lose their investment to an open source codec. In the case of Apple, they also have millions of videos that they sell in the h.264 format. They aren’t just going to convert it to WebM overnight.
  5. Content producers will not want to switch – content producers have just begun switching to h.264 and away from Flash so that they can gain support on mobile devices that don’t support Flash, like the iPhone. They won’t want to switch video formats yet again. There isn’t a compelling reason for them to switch – h.264 is supported everywhere, and where it isn’t (like Firefox) they can provide Flash fallback (which plays h.264). One format everywhere.

Question of Openness

While Google touts WebM as “open for anyone to implement and improve,” h.264 is open as well – it just isn’t free. According to Engadget:

Although H.264 is an open standard, in that it was developed by a consortium of companies and anyone can make and sell an encoder or decoder, it’s not free — you’ve got to pay for a royalty fee to use it, and the rates are set by the MPEG-LA, which collects payments and distributes them to its members.

It seems to me that whenever something is touted as “open,” it immediately gets all sorts of hype. Open has become a buzzword like Ajax was a few years ago. It seems that everything open is automatically “better,” and I think that this is wrong. I think that instead of assuming the superiority of an “open” product, we should instead be treating it like any other product, letting the best format win. Mozilla doesn’t really have to pay the royalties for including h.264 support in Firefox because they could just as easily shell out this task to the operating system, which already supports the playback of h.264 video and pays the royalties. While I understand the concerns that Mozilla has with using a closed video format, I don’t think that this should stop them from using the defacto standard for video that h.264 has become.

Bottom Line

Big companies have a lot of money in h.264 video which is already ubiquitously available, easy to encode, and fast to decode with low powered hardware decoders. Content producers have already invested time and money in switching away from Flash to h.264 and will not want to invest more time and money in order to switch to WebM. h.264 has become the defacto standard for video, and I just don’t see this changing overnight. This is why I think that the WebM video codec, as much as it is hyped, will fail.


jQuery has a function called empty, which removes all child elements from a given element. Internally, empty is used in the html function, and many other places. Speed is an important thing to web application developers which I have blogged about in the past. In my case, I was writing a highly dynamic app with jQuery, and the empty function was a performance bottleneck for me since the element I was emptying often contained over 500 children.

The implementation of jQuery’s empty function is fairly simple: iterate through all of the elements children and remove them one by one. As I have written about before, every time you modify the DOM so that the layout changes, the browser must reflow and repaint. Thus when jQuery iterates over all of the child nodes removing them one by one, the browser must reflow after each removal. This can be slow if you are dealing with a lot of elements.

How can we make this faster?

I initially thought that it would be faster to set the element’s innerHTML property to “” than to iterate, and I was right in most circumstances. Unfortunately, there are problems using innerHTML such as it being impossible to set the innerHTML of a table row in IE, which jQuery solves in the jQuery.html function. Using jQuery.html(“”) turned out to be faster than jQuery.empty() in all browsers except Firefox.

After a little digging, and a lot of performance testing, I had a method that was much faster than jQuery.empty() – in some cases up to 10x the speed. Here is the method:

jQuery.fn.removeAll = function() {
	this.each(function() {
		var newEl = this.cloneNode(false);
		this.parentNode.replaceChild(newEl, this);

		//Copy back events if they haven't been copied already by IE
		if(jQuery.support.noCloneEvent) {
			cloneCopyEvent($(this), $(newEl));
		}
	});
};

This function loops through all of the selected jQuery objects, and removes the children from all of them. Rather than iterating over all of the children in order to remove them, we simply clone the parent with deep clone set to false. This means that the parent element will be cloned but not the child elements. Once we have this clone in memory, we simply replace the existing element with the new element thereby removing all of the children. Unfortunately, in W3C compliant browsers cloneNode does not clone events attached to the original element along with the element itself, so we have to copy them back over. IE copies them over with cloneNode automatically, and luckily jQuery has a flag that lets us no whether the elements haven’t been copied over, in the form of jQuery.support.noCloneEvent. I’m using the internal jQuery function cloneCopyEvent to copy the events over.

The Benchmarks

I created several charts detailing the performance increases in various browsers. All of the tests were done on the same machine with the latest versions of each of the 4 major browsers and the latest beta of jQuery 1.4. As an interesting side note, IE and Firefox are far faster than the Webkit based browsers Chrome and Safari at removing elements from the DOM. This is interesting because both of those browsers are known for their speed. Here are the charts. I’ve created an overview chart and a breakdown by browser. Click to download a PDF.

Summary: This implementation of jQuery.empty can be over 10 times faster than the version included with jQuery beta 1.4.

I will be submitting this as a patch to the jQuery team, so you may see this code in jQuery sometime in the future!


I posted recently about a drag and drop plugin that I had created in the name of performance, but this was not the only performance bottleneck that I had to overcome in my application. As I said before, my application has two lists, one of which depends on the selection of the other for its content. Whenever the selection of the first list changes, the content of the other list updates, often with several hundred items. As I said before, one of the performance issues that I had, was the time it took to bind event listeners to all of those DOM elements for drag and drop. I solved this though event delegation. This change dramatically increased performance, but additional optimizations were still needed. Unfortunately, the issues were mostly beyond my control since the DOM was the source of the problem. Here is my original code.

$("#first-list li").live("mousedown", function() {
    $("#second-list").empty();

    $.each(content, function(i) {
        $("<li>").text(this.name).appendTo("#second-list");
    });
});

As this code shows, every time a user clicks on a list item in the first list, all of the items in the second list were removed using the jQuery.empty() function, and all of the items in the content array are appended to the second list.

So why is this slow?

This looks like pretty normal jQuery code and it works great until you have a lot of elements to append all at once. The reason that appending elements is slow, is because the browser must reflow the entire page every time an element is appended. Reflowing is the process that the browser’s layout manager goes through every time something changes size, or is added or removed from the page. During the process, the browser must recalculate the position and size of all of the elements on the page and then repaint it. Since reflowing occurs after appending each individual item to the DOM, performance can really take a hit.

The solution

The solution to this problem is to force the browser to reflow only once, and an unfortunate side effect is less simple looking code.

$("#first-list li").live("mousedown", function(e) {
    var html = [],
        len = content.length,
        i = 0;

    for(var j=0; j<len; j++) {
        html[i++] = "<li>";
        html[i++] = content[j].name;
        html[i++] = "</li>";
    }

    $("#second-list").html("<div>" + html.join('') + "</div>");
});

In this code, instead of using jQuery to create and append elements to the DOM, we actually create a long string of all of the elements that we want to append in memory, and then set it as the innerHTML of the second list. I have further optimized the code so that it actually creates an array of strings and then joins them, which is faster than doing string concatenation in most browsers. I have also wrapped all of the list items in a single DIV, which speeds up the browser because it can insert the elements as a block instead of individually.

So how does this perform?

Appending elements all at once performs much better than using jQuery to append the elements as they are being created, which would be expected. In my informal tests appending 500 elements, the grouped performance is often double the individual speed.

Conclusion

Performance is a very big issue if you are writing large scale applications, and it is unfortunate that the browser platform is slow in such a key area. That is why hacks like this exist: to artificially make things faster. It is my hope that browser makers will step up to the plate and make one of the most important parts of the browser faster for programmers, and most importantly for users. Until then however, we as developers need to get around these performance issues so that the experience that users have with web applications is a positive one. Performance is one of the final hurdles of browser based apps which I firmly believe are the future of computing.


JavaScript drag and drop is a difficult task to achieve, and luckily libraries such as jQuery UI help make the task easier. Unfortunately however, all of the drag and drop libraries that I found did not use event delegation. Event delegation is a technique used to make JavaScript libraries perform better by only registering one event handler of each type for the whole document, rather than for each individual element. Besides providing pages with a speed boost, event delegation has the added benefit of working automatically on new elements added to the page. If, for instance, I had created a click handler on all of the DIVs when the page first loaded, and then added another DIV later using JavaScript, that new DIV would automatically respond to click events using the handler I had set up when the page was loaded since you don’t need to register a new event listener. Event delegation is a fairly complex issue, but it is easier than you might think. If you are interested in learning more about event delegation, you should check out this Sitepoint article on the topic.

Recently, I was writing a pretty complex application using jQuery, and I was using jQuery UI to do the drag and drop. I had a fairly small test data set of 30 or 40 items, but when I was just about ready to go live and was testing the app with a larger data set of 500 – 600 items, things started performing very slowly. Every time a user clicked on an item in one list, all of the items in the second list needed to change, and because jQuery UI doesn’t use event delegation, things were taking a long time. It turns out that binding event listeners to 600 list items takes almost 2 seconds on my system, and this was simply not acceptable for the application that I was building.

I searched and searched, and could not find a drag and drop library similar to jQuery UI’s that used event delegation. So, long story short, I decided to write my own. Since I was writing this for a specific application, I only added the features that I was using from jQuery UI, but most of the function and property names are the same. It doesn’t nearly have all of the options that jQuery UI provides, but I can see it getting there in the future, as I need the features. Since writing a cross browser drag and drop library from scratch is not the most fun experience, I am posting this library to the web so that you can use it. If you’d like to add features, take a look at the source (it’s less than 200 lines!) and feel free to do so.

Examples:

This library is designed to be a drag AND drop library, meaning that elements that are dragged need to be dropped somewhere. This means that when you drop an element where it isn’t allowed to drop, the element will just slide back to it’s starting position. This isn’t a library for simply changing the position of elements at this point, but it could be in the future.

To make an element draggable or droppable, you just call the respective method on any jQuery object. For example:

$(".draggable").draggable();
$(".droptarget").droppable();

The options that you can use in the draggable plugin are in the table below.

Name Description Default
draggingClass
The class that will be applied to helper elements while dragging
dragging
helper
A function that returns an element to be used as the dragging helper (the element shown to the user while dragging). A function is passed into the helper option allowing you to set an option temporarily (just for the current drag). Clone draggable
distance
The distance the user needs to drag from the draggable element before the helper element becomes visible. Useful for elements that can be both clicked and dragged as this prevents drag operations until the user really wants to drag.
0
cursorAt
The position at which the mouse cursor will always appear during a drag. Useful for helpers with a dramatically different size than the draggable element. Pass in an object with optional properties top and left which are positions of the cursor relative to the helper element. Mousedown position


The options for the droppable plugin are in the table below.

Name Description Default
hoverClass
The class that will be applied to the drop target when an acceptable droppable is over the target.
draghovered
accept
A jQuery selector that describes the elements that may be dropped on the target Any element
drop
A function to be called when a drop event occurs. An object will be passed into the function with some data about the drop, including: helper: the helper element, draggable: the draggable element, and position: the absolute position of the mouse cursor relative to the page when the drop occurred. None


As I stated above, this is a preliminary release, and more options will be added in the future. Here is a test page showing some examples using the options above. As a side note, the time taken to run the code in my app is now just 20ms (down from 2 seconds), since the drag and drop code doesn’t even need to be run!

You can download the jQuery plugin here. Have fun!


I recently had an article published over on the Themeforest blog about achieving cross browser @font-face support. Check it out at http://blog.themeforest.net/tutorials/how-to-achieve-cross-browser-font-face-support/


This is a repost from CSS-Tricks, where I have been working with Chris Coyier to create The Printliminator.

I had this idea when I was at a lyrics site trying to print out some lyrics. The page didn’t have a good print stylesheet and was full of all kinds of crap. I copied the source code and made a local version of the site and dumped some simple jQuery stuff in there to make it so any thing I clicked on was eliminated from the page. Turns out it’s the current version of the DOM that gets sent to the printer, so I could eliminate things at will and have them not print. Cool!

After the idea was in place, I went back and forth with Devon Govett turning it into a more full-featured bookmarklet. The current iteration has click-to-remove elements, with a really cool feature of option-clicking to remove everything except the selected element. There are more features, and I think the video explains it better than I can with words:

To grab it, head over to the demo page and drag the bookmarklet link into your bookmarks bar. Click it on any page to activate.

DesignFloat

If you subscribe to a lot of RSS feeds, you know how annoying it is when the link from an article goes to a landing page where you have to click again to get to the real article.  I decided that I’d had enough of these feeds this morning, and I set out to “fix” them.  One way to do this, is with Yahoo Pipes.  Yahoo Pipes allows you to mash up feeds in different ways, and output a feed that you and others can subscribe to.

Yahoo Pipes is a web app, and since it’s a Yahoo product, you’ll need to have a Yahoo account in order to save the Pipe.  Once you sign in, click the “Create a pipe” button.  Now, you’ll have a blank Pipe, to which you can add the various modules in the left-hand sidebar.

Pipes- editing pipe

First, we need an input feed.  I’m going to use the DesignFloat RSS feed.  First, drag the Fetch Feed module from the Sources section onto the main area.  Enter the URL of the RSS feed into the URL field.  Next we’ll need the Loop module from the Operators section.  Drag the String Builder module from the String section inside the loop.  This is where we will be using YQL, or the Yahoo Query Language.  YQL is a powerful, SQL like language for querying for data within webpages.  We’ll need to load that landing page, and query the HTML on the page for the link to the real article.  In order to do this, we’ll be using a script posted on the YQL blog, which makes it possible to query HTML pages based on CSS selectors.  So, in our String Builder, enter the following command (press the + button for each new line):

use ‘http://yqlblog.net/samples/data.html.cssselect.xml’ as data.html.cssselect;

select * from data.html.cssselect where url=”

item.link

” and css=”.toptitle h1 a”

If you are using a different feed, you’ll need a different CSS selector (in the last line).  I found mine by using Safari’s web inspector, but you could also use Firebug, or IE8′s new Developer Tools.

Picture 3

Then select “assign results to item.link” in the bottom of the Loop module.

Picture 4

Next, we’ll need another loop module, with a YQL query (in the Sources section) in order to actually run the YQL query.  For the query field, select item.link, and make sure that the Env URL field is blank.  Finally, select “assign first results to item.link” at the bottom of the loop module.

Picture 5

The last module that we need to add, is the Create RSS module.  All we need to do here, is set Link to item.link.a.href.  Finally, you just need to connect all of the modules, and save the feed.  If you click “Run Feed” at the top of the screen, you should see a nice feed which links to the original articles, rather than the landing page.

Pipes- editing 'DesignFloat'

You can try out the feed that I created here.

I came up with a little trick to run multiple instances of Firefox simultaneously on a Mac. The following assumes that the instance of Firefox that you want to set up, is located at /Applications/Firefox.app.

Create a Profile

First you must create a profile for your new instance of Firefox. In a Terminal window, enter the following command:

/path-to/Firefox.app/Contents/MacOS/firefox-bin -Profilemanager

This will open the profile manager. Create a new profile for your new instance. Name it something you can remember like “Firefox 2.”
Profile Manager

Make it Auto-launch

You could just uncheck the “Don’t ask at startup” option, and every time that you launched any version of Firefox, you would need to choose a profile that wasn’t already in use. But, what we really want is to make them auto-launch.

Open up the Finder, and navigate to where the instance of Firefox that you want to set up is located.  Right-click the icon, and select “Show Package Contents” from the context menu. In the resulting Finder window, navigate to Contents/MacOS and rename firefox-bin to firefox-bin1.

In your favorite text editor, create a new file and paste the following code into it.

/Applications/Firefox.app/Contents/MacOS/firefox-bin1 -P ProfileName &

Change “ProfileName” to the name of the profile you created in the first step.

Save the file as /Applications/Firefox.app/Contents/MacOS/firefox-bin with no extension. To make the file executable, run the following command in the Terminal:

chmod +x /Applications/Firefox.app/Contents/MacOS/firefox-bin

Conclusion

You should now be able to run multiple versions of Firefox simultaneously without choosing a profile. Remember: You must set up a profile for each instance that you are going to run!

Happy browsing!

There are a few CSS features that Microsoft pioneered and has had available to developers in Internet Explorer for a long time now. One of those features is the text-overflow property, which is now in CSS3 and has implementations in Safari, and Opera. Firefox still does not support this feature, but I have heard that it will in Firefox 3.1.

Here is a rundown of what the property does. When text overflows an element’s box, the text-overflow property helps leave a visual hint to the user that there is more text. When a value of ellipsis is used, three dots will be shown before the text is clipped by overflow: hidden.

Lorem ipsum dolor sit amet, c…

I wanted to be able to use this feature in all browsers, so I wrote a small jQuery plugin in order to support Firefox. You can download the plugin here. To use, just call ellipsis() on a jQuery object. For example:

$("span").ellipsis();

There is one option available, which is simply a boolean specifying whether or not to update the text when the size of the element changes. This is useful if the width of the element is a percent, or if you change it via javascript (although I wouldn’t recommend animation).

If you pass false or nothing at all, the text will remain static. If you know that the width of the element will not be changing, do not pass true. If you do, performance of the browser will decrease unnecessarily.

You can see a test page with the plugin here. The plugin will not do anything if you are not using Firefox.

If you are interested, take a look at the code. If you have a better solution that I have overlooked, or you can make it faster please comment here to let me know!

Update: Based on comments on Ajaxian, the plugin now no longer uses $.browser.mozilla, and instead uses feature testing.

Update: Based on Jimmie’s comment, the plugin should now work correctly with different fonts.

Next Page »

Follow

Get every new post delivered to your Inbox.