Sencha Inc. | HTML5 Apps

Blog

Discover Music with Sencha Touch 2!

May 23, 2012 | Jay Garcia

Guest Blog Post: Jay Garcia of Modus Create

Today, we are excited to announce the launch of another fine Sencha Touch 2.0 example application, Discover Music, which was designed and created by Modus Create, a Sencha partner.

Discover Music (http://discovermusic.senchafy.com) lets users browse and discover exciting new music from NPR Music, leveraging the power of NPR’s rich public APIs. It delivers an amazing experience and makes extensive use of the latest features in Sencha Touch 2, such as the new class system and MVC. To help readers find NPR affiliate stations close to them, Discover Music implements geolocation, a popular item in the HTML5 toolbox.

When looking at Discover Music, you’ll quickly get a sense that a lot of careful work went into the custom views that were developed for this application. From the very beginning, we wanted to demonstrate that Sencha Touch 2 makes it possible to develop an enticing and engaging application.

Before we get into the technical details on how this all works, we’ll take a quick look at the design aspects of this engaging application.

The Design

Discover Music is designed to be the perfect HTML5 companion app for fans of NPR Music. The Modus design team defined three core engagement principles for the app: immediacy, curation and discovery. These patterns have consistently been reinforced in several engagements Modus has done for publishers including Time, Inc. and Bloomberg.

The content structure and information architecture follows the music genre taxonomy provided by the NPR API and the app presents a 'music-zine' feel, randomly selecting a featured article as the ‘issue cover’ each time the app loads.

Each genre contains a lead story and 4-5 articles. The app is designed to allow a user to immediately start listening to an NPR interview while browsing featured stories by genre. While listening to stories, users can favorite stories to read later, tweet and favorite articles.

This app supports Artist, Song and Keyword search as well as location-based NPR affiliates lookup and local station streaming. When we were done with the design, we handed off the mockups to our dev team to make it a reality.

Here's an early design mockup that influenced the production application. (Chrome, Safari & iPad Only)

Constructing the application

Upon receiving the mockups, our development team began designing the architecture of the client-side code. To do this, we leveraged Sencha Touch MVC to arrange an architecture that looks like the following.

Here’s how it all works.

The application controller is the main hub for everything, including application-level events and serves as the launch pad for the application. Its main responsibility is the inclusion of the five sub controllers, Main, Article, Search, Favorites and Stations. Since the Main Controller is the central point for most of the user interaction, that’s where we’ll focus.

In order to fully understand how the application works, we’d like to encourage you to visit the application at http://discovermusic.senchafy.com. After you’ve spent some time with it, we’d like you to look at this diagram. It documents how the navigation is organized. This will help us as we go through the detailed description later on.

As we said before, the Main Controller is responsible for much more than any other controller in this application, and serves more or less as the backbone for a large portion of the app. The Main view extends Ext.Carousel and is responsible for managing almost all other views that do not require a data store. The exception to this rule is the Drawer and GenreToc views, which are driven by the central Genres data Store. All views that are managed by this controller have event bindings that allow the application to react to user input. An example of this is a user tapping on a “read and listen” button, which actually invokes a full view of the Article.

When the app bootstraps, the Main controller makes two decisions to invoke a remote load of the article data from the API. The app will use cached data, if present and if the cached data is less than a day old. If there’s no cached data or if the cached data is more than a day old, then a remote request is made to our NPR API Proxy. The result of that remote request is loaded into the Genres store, cached in localStorage and time stamped.


After the Genres store is loaded, the app bootstraps the UI, presenting the user with a random cover story via the ArticlePreview view.

The purpose of ArticlePreview is to act more or less as a cover for the entire application. From here, the user can read the article via the “Read & Listen” button or employ a single horizontal swipe to view the GlobalToc view.

From this screen, the user can tap on the featured story, or any story from one of the genres on the vertically scrollable sub area on the right. One thing you might notice is that the genres on the right are scrollable vertically, but lock horizontal scrolling. Setting up this type of interaction was extremely simple with Sencha Touch 2 and the new scrollable config.

Here’s the exact implementation of the sidebar:

{
    xtype      : 'container',
    itemId     : 'genres',
    cls        : 'global-toc-right-sidebar',
    width      : 350,
    scrollable : {
        direction     : 'vertical',
        directionLock : true
    }
}

If users elect not to tap on an article, they can use another horizontal swipe to reveal the GenreToc view, displaying the splash image for the first four articles in the genre set.

Again, we allow the user to select an article from here via a tap event, or to use a horizontal swipe to look at the articles in the set for this genre. The navigation will continue in a loop until the last article of the last genre is shown. The last two screens that are displayed are Favorites, then the search screen.

If you’ve gotten a chance to use this application on your tablet, you’ve probably noticed how fast it is. We’ve had a lot of folks ask us how exactly we got this application to perform as quickly as it does.

Sencha Touch 2 Performance

As we were rounding the corner to feature completion, we were absolutely impressed at how fast this application really is. In order to recognize how much of a major impact Sencha Touch 2 has on performance of this application, we want to point out that there are 64 cards in the Main carousel!

64 cards is a LOT for a carousel. But, Sencha Touch 2 manages performance like a champ! Here’s what the DOM looks like for a carousel. Notice how there are only three DIV elements with the class “x-carousel-item”.

Under the hood, the Carousel widget is only rendering three items in the DOM at any one time. This allows the Carousel to have nearly an infinite number of child items and perform at speeds that rival native. Truly amazing stuff being done in the browser by Sencha Touch 2!

Next, we’ll share some of our secrets with you on how we made it as responsive as possible outside the realm of the Sencha Touch 2 base widgets.

Secret #1: Custom views

The first secret to performance when it comes to Discover Music is that we generated our own custom views using a mixture of tpl and data with a pinch of event listeners. Sencha Touch 2 makes this process extremely easy to do.

For example, here’s the ArticlePreview class:

Ext.define('Music.view.ArticlePreview', {
    extend : 'Ext.Component',
    xtype  : 'articlepreview',
    config : {
        model : null,
        genre : null,
        cls   : 'music-article-preview',
        tpl   : [
            '<div class="music-article-image" style="background-image:url(http://src.sencha.io/1024/{image});">',
                '<div class="music-article-category music-article-{genreKey} animated fadeInLeft">',
                    '<h1>{genre}</h1>',
                '</div>',
                '<div class="music-article-title animated fadeInRight">',
                    '<div class="music-content-all">',
                        '<div class="music-article-title-bg music-article-title-content">',
                            '<div class="music-article-btn music-article-btn-{genreKey}">Read <em>&amp;</em> Listen</div>',
                            '<h2>{title}</h2>',
                        '</div>',
                    '</div>',
                '</div>',
            '</div>'
        ]
    },
    initialize : function() {
        this.callParent();
        this.registerEvents();
    },
    registerEvents : function() {
        var me = this;
 
        me.readAndListen = me.renderElement.down(".music-article-btn");
 
        me.readAndListen.on({
            scope      : me,
            tap        : 'showFullArticle',
            touchstart : 'onPress',
            touchend   : 'onRelease'
        });
        me.pressedCls = 'music-article-btn-pressed-' + this.getModel().get('genreKey');
    },
    onPress : function() {
        this.readAndListen.addCls(this.pressedCls);
    },
    onRelease : function() {
        this.readAndListen.removeCls(this.pressedCls);
    },
    showFullArticle : function() {
        this.fireEvent("readarticle", this.getModel());
    }
});

Implementations of this view simply need to create an instance and pass in a data object per the XTemplate specifications. Sencha Touch 2 merges the tpl with the data to produce the view with the event handlers already registered. You may also notice we used Sencha.io Src to resize the images in the tpl, so they fit an iPad sized device. Sencha.io Src is a seamless way to take an original image and resize it based on the device User-Agent or on a fixed sized for your application’s particular needs.

Secret #2: Using the Sencha SDK tools

Using Sencha SDK Tools is absolutely paramount to the loading performance of an application. Whenever we discuss Sencha Touch 2, the SDK tools are always part of our conversations; because, not only can you build lightweight custom versions of Sencha Touch 2, but the caching mechanism allows your HTML5 applications to load successively nearly instantaneously. To learn more about the SDK tools, we highly encourage you to read Jacky’s blog post at http://www.sencha.com/blog/behind-sencha-command-and-the-build-process/

Secret #3: Reducing data size & caching

When we first started developing this application, we used the native NPR API. After the first few screens were available for testing, we decided to see how it would work on a 3G network. We found that our custom builds of the prototype application were blazingly fast, but initial loads of data were slow. Why was this?

What we learned is that while the NPR API was great for us to use, the data being produced by the API was averaging 540 Kilobytes. Upon inspection of the NPR data, it dawned on us that the API was never designed for the mobile web. The size of the payload just didn’t make sense to run in mobile.

The only solution was to create an extremely fast proxy. We initially implemented a proxy in PHP but were dissatisfied with the response times. We considered Node.js, but due to its asynchronous nature, we decided to use SilkJS (http://silkjs.org), a lightweight server-side JavaScript technology that leverages Google’s V8 JavaScript engine.

SilkJS gave us the ability to easily create a proxy via cURL requests to the NPR API without having to worry about event loop. The results of this effort are shown architecture on the right.

The SilkJS servers are hosted on Amazon’s EC2 cloud, behind a load balancer for both speed and redundancy. Both SilkJS hosts are fed by the NPR API via cURL and are responsible for trimming more than 300KB out of the data package, bringing the average load to less than 200KB before being gzipped for transmission!

This data reduction was made possible by only sending the data that was required to display article information for the application.

After the data payload was reduced, we were able to further improve successive loads, not exceeding 24 hours, by caching the data in localStorage.

SilkJS also allowed us to create lightweight proxies for various issues surrounding the music delivery, such as plucking out an MP3 stream from a .pls or .m3u file for a seamless cross-browser, cross-device experience.

Conclusion

There you have it! Discover Music was designed to be an engaging, high performance HTML5 app. Sencha Touch 2 made it easy to accomplish our goal.

We thank Sencha for giving us the opportunity to develop this application. A github project has been created with the source code to allow you to see how we set things up and learn. It can be accessed via https://github.com/ModusCreateOrg/DiscoverMusic.

There are 9 responses. Add yours.

AwesomeBobX64

3 years ago

Awesome.

Jorge

3 years ago

This is very cool. Congrats!

Jay, I see that you used initialize to define your listeners. Any particular reason why you used initialize instead of defining listeners in config?

Jay Garcia

3 years ago

Jorge, that was most likely left over from debugging.

Simon Tomlin

3 years ago

Very impressive. Its a great looking web app and very impressed with the way you solved the data transmission issue for a non mobile api.

I even found an interesting article to listen to!

Mario Roy

3 years ago

Very nicely done Jay.  Congrats.

Ashley Coker

2 years ago

Awesome!  We will be sifting through the source code for use in our own apps - thanks guys!

Rao

2 years ago

Great work Jay & Co.!

Matt

2 years ago

Wow really sweet looking app. Nice clean looking interface. I like the idea of loading content on demand. Do you use the preload function in html5?

Vikram Bhaskaran

2 years ago

May I know which is the editor used in the video which provides auto-complete on Ext methods and definitions. I use Textmate but doesn’t have any autocomplete. As far as the video is concerned. Never knew the power of Sencha is this exhaustive.

Comments are Gravatar enabled. Your email address will not be shown.

Commenting is not available in this channel entry.