Anatomy of a Sencha Touch 2 App

March 19, 2012 by Ed Spencer · 10 Comments 

At its simplest, a Sencha Touch 2 application is just a small collection of text files – html, css and javascript. But applications often grow over time so to keep things organized and maintainable we have a set of simple conventions around how to structure and manage your application’s code.

A little while back we introduced a technology called Sencha Command. Command got a big overhaul for 2.0 and today it can generate all of the files your application needs for you. To get Sencha Command you’ll need to install the SDK Tools and then open up your terminal. To run the app generator you’ll need to make sure you’ve got a copy of the Sencha Touch 2 SDK, cd into it in your terminal and run the app generate command:

sencha generate app MyApp ../MyApp

This creates an application called MyApp with all of the files and folders you’ll need to get started generated for you. You end up with a folder structure that looks like this:

st2-dir-overview

This looks like a fair number of files and folders because I’ve expanded the app folder in the image above but really there are only 4 files and 3 folders at the top level. Let’s look at the files first:

  • index.html: simplest HTML file ever, just includes the app JS and CSS, plus a loading spinner
  • app.js: this is the heart of your app, sets up app name, dependencies and a launch function
  • app.json: used by the microloader to cache your app files in localStorage so it boots up faster
  • packager.json: configuration file used to package your app for native app stores

To begin with you’ll only really need to edit app.js – the others come in useful later on. Now let’s take a look at the folders:

  • app: contains all of your application’s source files – models, views, controllers etc
  • resources: contains the images and CSS used by your app, including the source SASS files
  • sdk: contains the important parts of the Touch SDK, including Sencha Command

The app folder

You’ll spend 90%+ of your time inside the app folder, so let’s drill down and take a look at what’s inside that. We’ve got 5 subfolders, all of which are empty except one – the view folder. This just contains a template view file that renders a tab panel when you first boot the app up. Let’s look at each:

Easy stuff. There’s a bunch of documentation on what each of those things are at the Touch 2 docs site, plus of course the Getting Started video with awesome narration by some British guy.

The resources folder

Moving on, let’s take a look at the resources folder:

st2-dir-resources

Five folders this time – in turn:

  • icons: the set of icons used when your app is added to the home screen. We create some nice default ones for you
  • loading: the loading/startup screen images to use when your app’s on a home screen or natively packaged
  • images: this is where you should put any app images that are not icons or loading images
  • sass: the source SASS files for your app. This is the place to alter the theming for your app, remove any CSS you’re not using and add your own styles
  • css: the compiled SASS files – these are the CSS files your app will use in production and are automatically minified for you

There are quite a few icon and loading images needed to cover all of the different sizes and resolutions of the devices that Sencha Touch 2 supports. We’ve included all of the different formats with the conventional file names as a guide – you can just replace the contents of resources/icons and resources/loading with your own images.

The sdk folder

Finally there’s the SDK directory, which contains the SDK’s source code and all of the dependencies used by Sencha Command. This includes Node.js, Phantom JS and others so it can start to add up. Of course, none of this goes into your production builds, which we keep as tiny and fast-loading as possible, but if you’re not going to use the SDK Tools (bad move, but your call!) you can remove the sdk/command directory to keep things leaner.

By vendoring all third-party dependencies like Node.js into your application directory we can be confident that there are no system-specific dependencies required, so you can zip up your app, send it to a friend and so long as she has the SDK Tools installed, everything should just work.

Hopefully that lays out the large-scale structure of what goes where and why – feel free to ask questions!

What do you want from Sencha Touch 2.1?

March 14, 2012 by Ed Spencer · 13 Comments 

Disclaimers: this is the most unofficial, non-Sencha-backed poll of all time. There’s no guarantee we’ll ever do any of it, yada yada.

Touch 2.0 went GA last week to easily the best product launch reception I’ve seen. It was great and the feedback’s wonderful but honeymoons are boring – I want to know what’s wrong with it :)

So, what do you want to see in Sencha Touch 2.1? I asked on Twitter just now and got a bunch of responses so here are some ideas. Even if what you want is on this list already drop a reply in the comments so I know more than one person cares about it:

touch-2-1-requests

We do of course have a few ideas up our sleeves too, but why spoil the surprise?

Sencha Touch 2 GA Released!

March 6, 2012 by Ed Spencer · 3 Comments 

The last few months have flown by faster than almost any before them. The first Sencha Touch 2 release went out in October as a Developer Preview, coinciding with SenchaCon 2011, sparking a huge wave of interest from all over the HTML5 community. Today marks the GA release of Sencha Touch 2.0.0, and we couldn’t be happier with how far we’ve come.

See the announcement on sencha.com

It was only 18 months ago that we released the first version of Sencha Touch 1. It ushered in a brave new world, bringing tried and true approaches from the desktop together with the exciting new capabilities of the mobile web. But it was, to many of us, very much a version 1 product. ST2 is as big a step up from ST1 as ST1 was from everything that went before it.

Similar themes, great execution

For me, there are three core themes that go into any game-changing software release: Performance, Stability and Ease of Use. These themes come up again and again, especially for products at the bleeding edge of what’s possible. With the mobile web, each year can bring game changing developments – that’s one of the reasons developing Sencha Touch is so exciting.

Touch 2 really nails all of those themes. Performance was definitely the top priority of the three, and I think we’ve been able to permanently alter expectations of what web apps can do with the improvements we’ve made. Not only do apps feel much faster when you use them, today’s announcement on the incredible new fast startup performance is game changing in itself. It’s amazing how fast ST2 apps start up now, it really changes how they’re used when they consistently boot in a couple of seconds.

Stability is not sexy. It’s not a particularly great marketing ploy but it’s really important. Having a weekly release cycle and a huge developer community has really helped enable a fast turnaround on finding, fixing and verifying bugs. Lately new bug reports have been trickling in so slowly we almost wish there were more of them. Almost.

Oddly, documentation is something that’s really close to my heart. Back when I joined Sencha, improving the Ext JS docs was a prime concern and I think we took it up several notches between Ext JS 3 and 4. But that’s nothing compared to what we’ve done between Sencha Touch 1 and 2. As well as using the awesome new documentation app from Ext JS, we’ve added a ludicrous amount of new content including 35 brand new guides (up from zero) and way more examples than ever before.

We’ve also been creating new screencasts, augmenting the awesome material Drew Neil creates. For the Touch 2 GA release I created this 30 minute getting started video that covers everything from generating an app all the way through to packaging it for native app stores. This is the sort of material I always wished I had when I was first learning Ext JS:

Getting Started with Sencha Touch 2 from Sencha on Vimeo.

These take a lot of time to produce so if you like this sort of thing make sure you drop a comment here or on the sencha.com blog so I know to create more. I try to record them in a single take so you know there’s no magic going on behind the scenes – I think it shows it’s all real but it involves a lot of takes :)

Step One

All of the hard work to date has been to ship 2.0.0 – the first stable 2.x release. 2.0 itself is a step change over what went before it but there are already some incredible things lined up for the next few releases. Over the next couple of months we’ll continue to polish, optimize and act on the wonderful feedback you guys are providing, but first I think we’ve earned a break!

Building a data-driven image carousel with Sencha Touch 2

February 11, 2012 by Ed Spencer · 21 Comments 

This evening I embarked on a little stellar voyage that I’d like to share with you all. Most people with great taste love astronomy and Sencha Touch 2, so why not combine them in a fun evening’s web app building?

NASA has been running a small site called APOD (Astronomy Picture Of the Day) for a long time now, as you can probably tell by the awesome web design of that page. Despite its 1998-era styling, this site incorporates some pretty stunning images of the universe and is begging for a mobile app interpretation.

We’re not going to go crazy, in fact this whole thing only took about an hour to create, but hopefully it’s a useful look at how to put something like this together. In this case, we’re just going to write a quick app that pulls down the last 20 pictures and shows them in a carousel with an optional title.

Here’s what it looks like live. You’ll need a webkit browser (Chrome or Safari) to see this, alternatively load up http://code.edspencer.net/apod on a phone or tablet device:

The full source code for the app is up on github, and we’ll go through it bit by bit below.

The App

Our app consists of 5 files:

index.html, which includes our JavaScript files and a little CSS
app.js, which boots our application up
app/model/Picture.js, which represents a single APOD picture
app/view/Picture.js, which shows a picture on the page
app/store/Pictures.js, which fetches the pictures from the APOD RSS feed

The whole thing is up on github and you can see a live demo at http://code.edspencer.net/apod. To see what it’s doing tap that link on your phone or tablet, and to really feel it add it to your homescreen to get rid of that browser chrome.

The Code

Most of the action happens in app.js, which for your enjoyment is more documentation than code. Here’s the gist of it:

/*
* This app uses a Carousel and a JSON-P proxy so make sure they're loaded first
*/
Ext.require([
    'Ext.carousel.Carousel',
    'Ext.data.proxy.JsonP'
]);

/**
* Our app is pretty simple - it just grabs the latest images from NASA's Astronomy Picture Of the Day
* (http://apod.nasa.gov/apod/astropix.html) and displays them in a Carousel. This file drives most of
* the application, but there's also:
*
* * A Store - app/store/Pictures.js - that fetches the data from the APOD RSS feed
* * A Model - app/model/Picture.js - that represents a single image from the feed
* * A View - app/view/Picture.js - that displays each image
*
* Our application's launch function is called automatically when everything is loaded.
*/
Ext.application({
    name: 'apod',
    
    models: ['Picture'],
    stores: ['Pictures'],
    views: ['Picture'],
    
    launch: function() {
        var titleVisible = false,
            info, carousel;
        
        /**
* The main carousel that drives our app. We're just telling it to use the Pictures store and
* to update the info bar whenever a new image is swiped to
*/
        carousel = Ext.create('Ext.Carousel', {
            store: 'Pictures',
            direction: 'horizontal',
            
            listeners: {
                activeitemchange: function(carousel, item) {
                    info.setHtml(item.getPicture().get('title'));
                }
            }
        });
        
        /**
* This is just a reusable Component that we pin to the top of the page. This is hidden by default
* and appears when the user taps on the screen. The activeitemchange listener above updates the
* content of this Component whenever a new image is swiped to
*/
        info = Ext.create('Ext.Component', {
            cls: 'apod-title',
            top: 0,
            left: 0,
            right: 0
        });
        
        //add both of our views to the Viewport so they're rendered and visible
        Ext.Viewport.add(carousel);
        Ext.Viewport.add(info);
        
        /**
* The Pictures store (see app/store/Pictures.js) is set to not load automatically, so we load it
* manually now. This loads data from the APOD RSS feed and calls our callback function once it's
* loaded.
*
* All we do here is iterate over all of the data, creating an apodimage Component for each item.
* Then we just add those items to the Carousel and set the first item active.
*/
        Ext.getStore('Pictures').load(function(pictures) {
            var items = [];
            
            Ext.each(pictures, function(picture) {
                if (!picture.get('image')) {
                    return;
                }
                
                items.push({
                    xtype: 'apodimage',
                    picture: picture
                });
            });
            
            carousel.setItems(items);
            carousel.setActiveItem(0);
        });
        
        /**
* The final thing is to add a tap listener that is called whenever the user taps on the screen.
* We do a quick check to make sure they're not tapping on the carousel indicators (tapping on
* those indicators moves you between items so we don't want to override that), then either hide
* or show the info Component.
*
* Note that to hide or show this Component we're adding or removing the apod-title-visible class.
* If you look at index.html you'll see the CSS rules style the info bar and also cause it to fade
* in and out when you tap.
*/
        Ext.Viewport.element.on('tap', function(e) {
            if (!e.getTarget('.x-carousel-indicator')) {
                if (titleVisible) {
                    info.element.removeCls('apod-title-visible');
                    titleVisible = false;
                } else {
                    info.element.addCls('apod-title-visible');
                    titleVisible = true;
                }
            }
        });
    }
});
view raw APOD-app.js This Gist brought to you by GitHub.

This is pretty simple stuff and you can probably just follow the comments to see what’s going on. Basically though the app.js is responsible for launching our application, creating the Carousel and info Components, and setting up a couple of convenient event listeners.

We also had a few other files:

Picture Model

Found in app/model/Picture.js, our model is mostly just a list of fields sent back in the RSS feed. There is one that’s somewhat more complicated than the rest though – the ‘image’ field. Ideally, the RSS feed would have sent back the url of the image in a separate field and we could just pull it out like any other, but alas it is embedded inside the main content.

To get around this, we just specify a convert function that grabs the content field, finds the first image url inside of it and pulls it out. To make sure it looks good on any device we also pass it through Sencha IO src, which resizes the image to fit the screen size of whatever device we happen to be viewing it on:

/**
* Simple Model that represents an image from NASA's Astronomy Picture Of the Day. The only remarkable
* thing about this model is the 'image' field, which uses a regular expression to pull its value out
* of the main content of the RSS feed. Ideally the image url would have been presented in its own field
* in the RSS response, but as it wasn't we had to use this approach to parse it out
*/
Ext.define('apod.model.Picture', {
    extend: 'Ext.data.Model',
    
    config: {
        fields: [
            'id', 'title', 'link', 'author', 'content',
            {
                name: 'image',
                type: 'string',
                convert: function(value, record) {
                    var content = record.get('content'),
                        regex = /img src=\"([a-zA-Z0-9\_\.\/\:]*)\"/,
                        match = content.match(regex),
                        src = match[1];

                    if (src != "" && !src.match(/\.gif$/)) {
                        src = "http://src.sencha.io/screen.width/" + src;
                    }
                    
                    return src;
                }
            }
        ]
    }
});
view raw APOD-model.js This Gist brought to you by GitHub.

Pictures Store

Our Store is even simpler than our Model. All it does is load the APOD RSS feed over JSON-P (via Google’s RSS Feed API) and decode the data with a very simple JSON Reader. This automatically pulls down the images and runs them through our Model’s convert function:

/**
* Grabs the APOD RSS feed from Google's Feed API, passes the data to our Model to decode
*/
Ext.define('apod.store.Pictures', {
    extend: 'Ext.data.Store',
    
    config: {
        model: 'apod.model.Picture',
        
        proxy: {
            type: 'jsonp',
            url: 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://www.acme.com/jef/apod/rss.xml&num=20',
            
            reader: {
                type: 'json',
                rootProperty: 'responseData.feed.entries'
            }
        }
    }
});
view raw APOD-store.js This Gist brought to you by GitHub.

Tying it all together

Our app.js loads our Model and Store, plus a really simple Picture view that is basically just an Ext.Img. All it does then is render the Carousel and Info Component to the screen and tie up a couple of listeners.

In case you weren’t paying attention before, the info component is just an Ext.Component that we rendered up in app.js as a place to render the title of the image you’re currently looking at. When you swipe between items in the carousel the activeitemchange event is fired, which we listen to near the top of app.js. All our activeitemchange listener does is update the HTML of the info component to the title of the image we just swiped to.

But what about the info component itself? Well at the bottom of app.js we added a tap listener on Ext.Viewport that hides or shows the info Component whenever you tap anywhere on the screen (except if you tap on the Carousel indicator icons). With a little CSS transition loveliness we get a nice fade in/out transition when we tap the screen to reveal the image title. Here’s that tap listener again:

/**
* The final thing is to add a tap listener that is called whenever the user taps on the screen.
* We do a quick check to make sure they're not tapping on the carousel indicators (tapping on
* those indicators moves you between items so we don't want to override that), then either hide
* or show the info Component.
*/
Ext.Viewport.element.on('tap', function(e) {
    if (!e.getTarget('.x-carousel-indicator')) {
        if (titleVisible) {
            info.element.removeCls('apod-title-visible');
            titleVisible = false;
        } else {
            info.element.addCls('apod-title-visible');
            titleVisible = true;
        }
    }
});

The End of the Beginning

This was a really simple app that shows how easy it is to put these things together with Sencha Touch 2. Like with most stories though there’s more to come so keep an eye out for parts 2 and 3 of this intergalactic adventure.

Like Android? Help us fix it

February 6, 2012 by Ed Spencer · 4 Comments 

Near the end of last week’s Sencha Touch 2 beta release blog post there was an appeal to the community to help raise awareness of a nasty flashing issue with Android 4.x phones. Every time you tried to use an animation on a web page the browser would flash, wait a bit, then finally perform the animation.

We filed a ticket on this about a week ago and thanks to your help (over 300 of you starred the issue), got a prompt response from the Android team with a fix for the flashing issue.

Getting it Right

However, that’s only half the story. While the ugly flash is gone, animation performance on Android 4.x phones is still unacceptable. As it stands a 2 year old device running Android 2.x easily outruns the top of the range devices today running 4.x.

We really want to have excellent support for all Android devices. While 4.x accounts for only 1% of all Android phones today, that number is only going to go up. And when it does, we want to be ready to ship fast, fluid, beautiful apps onto it.

So we’ve created a new ticket with reduced, reproducible test cases and filed it to the bug tracker. We’ll continue to give the Android team as much support as we can in order to resolve this quickly, but once again we’ll need your help.

In fact all we need is a few seconds of your time. Just open the ticket and click the star at the top left. That’s all we need – it tells the Android team just how many people care about this issue and will help them prioritize it accordingly.

If you want to help out more, take a moment to add a comment to the ticket outlining your own experiences with this issue, like the m.lanyrd.com developer did. Highlighting specific cases where you’ve had problems will really help.

Thanks!

Helping raise awareness of this issue will help everyone who uses or develops for Android devices on the web, and enables technologies like Sencha Touch to deliver slick, immersive apps without resorting to rewriting your app for each platform. We appreciate your help!

Star the issue now

Next Page »