I recently enjoyed the opportunity to help Grooveshark reinvent their web interface. There are many things I could say about this project, but if I were limited to a summary statement it would be that we stood on the shoulders of one giant open source community.
This post is my thanks to the authors and contributors of the software used. We probably could have done it without you, but I'm sure glad we didn't have to!
Yehuda Katz recently quipped that jQuery is becoming the standard library of the web. And why shouldn't it? It makes otherwise arduous DOM manipulation a breeze, its API is mature, and it has been proven on major production sites.
In fact, Grooveshark had already chosen jQuery as a component before I joined the party. I didn't complain :)
You may not notice jQuery UI in the mix at first glance, but it's in there.
The only widgets used were Autocomplete, Slider, and Datepicker, but we employed a bevy of its other features. It drives all drag and drop interaction on the site as well as enabling the use of another big component: SlickGrid (see below).
One of jQuery UI's greatest advantages (besides its use of jQuery, of course) is that you can pick and choose just what you need. Page load speed was another driving force of the rewrite, so this was paramount for us.
JMVC has a boatload of features (code generation, dependency resolution, documentation, etc.), but we ended up building just upon the core functionality it exposes. At its base is John Resig's Simple Class inheritance, which is key. From there JMVC provides base Model and Controller classes from which you inherit. JMVC controllers are great and with full fledged classical inheritance at our disposal we could extend it to fit all of our needs.
JMVC's default templating engine is EJS, which will look familiar to Ruby/Rails developers. Its similarity to vanilla HTML made it attractive right out of the gate (again, for developer accessibility) and powerful features like partials and view helpers means it can handle just about anything.
A huge component of Grooveshark is the grid. Almost every content page has it, and it is busting at the seams with features (sorting, arbitrary row rendering, drag and drop, keyboard navigation, etc.).
Features aside, the main thing the grid needs is to perform well with thousands of rows. Thankfully, SlickGrid had crossed my radar a few months before the project began. Its adaptive virtual scrolling allows it to scale to hundreds of thousands of rows without losing responsiveness.
The library was a joy to work with. You should definitely check it out if you have advanced grid needs.
Grooveshark is a single page application with many "pages" inside it. These pages have pretty URLs nested behind a hash (#) tag. We needed to preserve all of the publicly available URLs while providing back button and history support. Originally, we looked to Sammy JS for this functionality.
Sammy worked great for awhile, but we had some issues with back button support on older browsers. Also, Sammy provides a ton of functionality and we were only using a smidgeon of it. Instead, we switched to Ben Alman's Hashchange plugin and never looked back. It works great and has a small footprint.
Performance is a big deal to the Grooveshark team. We use local storage to persist user settings and libraries so they won't have to wait on the server to load up the application when they return. Store.js is a local storage wrapper that consolidates all the browser quirks into a single API. Awesome stuff.
Grooveshark currently supports switching between 17 languages. When the language is switched all localized elements on the page (and future elements) need to be swapped out. Our localization technique started with the jquery-localize plugin. We ended up extending it quite a bit to support some advanced string localizations, but the plugin definitely gave us a jumping off point.
Those are the big pieces of the application, but there are other players that are worth mentioning:
- PubSub — communicating between disparate sections of the app
- jquery.hotkeys — keyboard shortcuts ftw
- jjmenu — context menus
- JSON — pretty much the best thing ever, duh
- Underscore — not used directly, but we yoinked a few functions from it
- Yaml — dependency management and configuration
- Rake — build and deploy routines
- JSLint — keep our codes pretty
- Smusher — optimize images without installing ImageMagick
If you authored or contributed to any of the projects listed above: THANKS!!
If you are interested in any of them or have questions about how we implemented other pieces of the application, please do ask.