Sencha Touch BDD series from Pivotal Labs

A great series of blog posts on Behavior Driven Development(BDD) with Sencha Touch. Covers BDD with Jasmine Javascript tests to test Sencha Touch models, stores and controllers. Covers mocking and also running tests via phantom.js.

Thanks pivotal labs

Goodbye Google Reader, Hello Feedly

Feedly LogoOn the 1st of July Google Reader will shut it’s doors.  No more Google Reader.

Feedly.com has emerged as it’s successor claiming 3 million new users in the 2 weeks after the closure announcement.

Visitors to Feedly.com can transfer their Google Reader RSS feeds to Feedly simply by signing in. A painless process.

Feedly makes the bold claim of seamless transfer once Google Reader is unplugged.

Feedly.com comes in several flavours:

  • Desktop
  • iOS app
  • Android app
  • plus several other mobile platforms

The mobile user experience is where Feedly shines in comparison to Google Reader  offerings.

So if you are looking for a safe place for your Google Reader feeds, try feedly.com

Tutorial 3: Sencha Weather App – add 2 tab panels with List component, itemTpl

SenchaTouch_Preview

  • In tutorial 1 we created the sample Sencha Touch App
  • In tutorial 2 we edited the sample app to contain 2 tab panels.

In this tutorial 3 we will finish the 2 tab panels.

  • List component
  • Attached to the store
  • itemTpl

List Component

A list of items, with touch swipe of scrolling.

Store

A sencha touch store is the data source of you objects. These could be stored in HTML5 Local storage, memory or proxied to web servies.

The list component allows us to easily attached a store to a list. This allows us to populate the list items for a data source. This is all sorts of powerful.

itemTpl

We want to style each list of our List Component with our own HTML template. This is there the itemTPL comes in. As you can guess it’s the item template for the list component.

Ext.define('WeatherApp.view.Weather', {
    extend:'Ext.List',
    xtype:'weather',

    /* Configure the tab here */
    config:{
        title:'Weather', //title on the tab button
        iconCls:'locate', //icon on the tab button

        disableSelection: true,

        /* attach this list component to the weather store */
        store:'Weather',

        /* create a title bar for the tab panel */

        items: [
            {
                docked: 'top',
                xtype:'toolbar',
                title:'Weather',
                id: 'mainToolbar',
                cls: '',
                items: [

                    { xtype: 'spacer' },
                    {
                        xtype: 'button',
                        cls: 'refreshWeather',
                        iconCls: 'refresh',
                        id: 'refreshWeather'
                    }

                ]
            }
        ],

        /* markup for the data returned from the store */
        itemTpl:Ext.create('Ext.XTemplate',
            '</pre>
<div>',
 '
<h2>{name}, {[values.sys.country]}</h2>
',
 '
Time: {[this.timeFormat(new Date())]}

',
 '
Weather: {[values.weather[0].description]}

',
 '<img alt="" src="' + WeatherApp.app.openweatherimages + '{[values.weather[0].icon]}" />',

 '
Temperature: {[values.main.temp]} ℃

',
 '
Humidity: {[values.main.humidity]} %

',
 '
Min Temp: {[values.main.temp_min]} ℃

',
 '
Max Temp: {[values.main.temp_max]} ℃

',
 '</div>
<pre>',
            {
                timeFormat:function (date) {

                    var days = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'];
                    var newDate = date;

                    return days[newDate.getDay() - 1] + " "
                            + newDate.getHours() + ":"
                            + newDate.getMinutes() + ":"
                            + newDate.getSeconds();
                }
            }
        )
    },

    initialize:function () {
        this.callParent();
    }

});

Points of interest:

The Weather Store that supplies the List Component.

The placeholders in the itemTpl I.E. {name)

The next step for us:

  • We need to get the Weather Data from somewhere. We’ll sign up for the free Open Weather Map API
  • Create the Model to describe the data return the from Open Weather Map API
  • Create the Store to hold the above modelled objects.

Stay tuned for Tutorial 4.

CODE HERE:

You can clone to the branch and browse to the app to see the two tabs in action.

https://github.com/jamiegood/WeatherApp/tree/TwoPanelTabs

Tutorial 2: Sencha Weather App – add 2 tab panels

In the first tutorial we created a simple Sencha Touch application using the Sencha CMS tools.This gave us a sample working application to explore.  Now we will update this, removing what is not necessary all the while keeping with the MVC pattern.

Plan:

  1. Create 2 tab panels
  2. One which is eveualtyy show the weather report.
  3. The second for a ‘settings’ type page.

1. Create the Main view to hold the tab panels

/*
This file is generated and updated by Sencha Cmd. You can edit this file as
needed for your application, but these edits will have to be merged by
Sencha Cmd when it performs code generation tasks such as generating new
models, controllers or views and when running "sencha app upgrade".

Ideally changes to this file would be limited and most work would be done
in other places (such as Controllers). If Sencha Cmd cannot merge your
changes and its generated code, it will produce a "merge conflict" that you
will need to resolve manually.
*/

// DO NOT DELETE - this directive is required for Sencha Cmd packages to work.
//@require @packageOverrides

//
Ext.Loader.setPath({
    'Ext': 'touch/src',
    'WeatherApp': 'app'
});
//

Ext.application({
    name: 'WeatherApp',

    requires: [
        'Ext.MessageBox'
    ],

    views: [
        'Main',
        'About',
        'Weather'
    ],

    icon: {
        '57': 'resources/icons/Icon.png',
        '72': 'resources/icons/Icon~ipad.png',
        '114': 'resources/icons/Icon@2x.png',
        '144': 'resources/icons/Icon~ipad@2x.png'
    },

    isIconPrecomposed: true,

    startupImage: {
        '320x460': 'resources/startup/320x460.jpg',
        '640x920': 'resources/startup/640x920.png',
        '768x1004': 'resources/startup/768x1004.png',
        '748x1024': 'resources/startup/748x1024.png',
        '1536x2008': 'resources/startup/1536x2008.png',
        '1496x2048': 'resources/startup/1496x2048.png'
    },

    launch: function() {
        // Destroy the #appLoadingIndicator element
        Ext.fly('appLoadingIndicator').destroy();

        // Initialize the main view
        Ext.Viewport.add(Ext.create('WeatherApp.view.Main'));
    }

});

See the highlighted lines above for the changes.
Create the main view file – app/view/Main.js

Ext.define('WeatherApp.view.Main', {
    extend:'Ext.tab.Panel',
    xtype:'main',

    config:{

        tabBarPosition:'bottom',
        defaults:{
            styleHtmlContent:true
        },
        items:[
            {
                xtype: 'weather'
            },
            {
                xtype:'about'
            }
        ]
    }
});

This view extends the Sencha Touch component, the Tab Panel. Take note of:

  • xtype: this is a shortcut we will use to refer to this Main view. Note that we have already referenced the ‘main’ xtype in our app.js above.
  • The config parameter: This is the configuration for the Panel Component – importantly not the individual panels.
    A huge amount of configuration options exist. Refer the the Sencha Touch API and the Sencha Touch Examples that are downloaded with the Sencha Touch SDK.
  • Components often have required config parameters that must be set.  The above are the minimum required for the Ext.tab.panel component.

Step 2: Create A view for the About Tab panel

See Items in the app/view/Main.js – theses will be an array of the tabs themselves. If I have 3 items there we would have 3 tab panels.

Our second tab item is referenced by an xtype ‘about’. Think of an xtype as a shortcut to the About view.  We’ll start with that as it’s simpler than the Weather view 🙂

Firstly we have the views already added out our app.js. Lines 30 – 33 above. Good times.

We’ll need to create a view file – app/view/About.js

We’ll keep it simple for now and just have some text.

Ext.define('WeatherApp.view.About', {
    extend: 'Ext.Container',
    xtype: 'about',

    /* Configure the tab here */
    config: {
        title: 'About',
        iconCls: 'settings',

        /* Create a title bar for the tab panel */
        items: {
            docked: 'top',
            xtype: 'titlebar',
            title: 'About'
        }
    },

    /*contents of tab */
    html: 'The about page'

});
so whats happening here? Notice the following:
This view extends Ext.container component – this is a general component. Fine if you just want to add some text like we have here.
Xtype is ‘about’. We are giving this component a shortcut name called ‘about’. The Main view pulls in this view via this xtype.
More config for the Ext.tab.panel.
Items again for the panel, this time using a built in xtype for a titlebar component.
Again the the Sencha API is your best bet for figuring out about these little have very powerful configuration components.
Ignore the other config for now. The are default parameters to be cover in a latter tutorial (I hope).

Step 3: Create a View for the Weather Tab panel

Create a app/view/Weather.js view for the ‘Weather’ xtype referenced from your Main view.

Ext.define('WeatherApp.view.Weather', {
    extend:'Ext.List',
    xtype:'weather',

    /* Configure the tab here */
    config:{
        title:'Weather', //title on the tab button
        iconCls:'locate', //icon on the tab button

        disableSelection: true,

        /* attach this list component to the weather store */
        store:'Weather',

        /* create a title bar for the tab panel */

        /*
items:{
docked:'top',
xtype:'titlebar',
title:'Weather'
},
*/

        items: [
            {
                docked: 'top',
                xtype:'toolbar',
                title:'Weather',
                id: 'mainToolbar',
                cls: '',
                items: [

                    { xtype: 'spacer' },
                    {
                        xtype: 'button',
                        cls: 'refreshWeather',
                        iconCls: 'refresh',
                        id: 'refreshWeather'
                    }

                ]
            }
        ],

        /* markup for the data returned from the store */
        itemTpl:Ext.create('Ext.XTemplate',
            '<div class="">',
            '<h2>{name}, {[values.sys.country]}</h2>',
            '<p>Time: {[this.timeFormat(new Date())]}</p>',
            '<p>Weather: {[values.weather[0].description]}</p>',
            '<img src="' + WeatherApp.app.openweatherimages + '{[values.weather[0].icon]}"/>',

            '<p>Temperature: {[values.main.temp]} ℃</p>',
            '<p>Humidity: {[values.main.humidity]} %</p>',
            '<p>Min Temp: {[values.main.temp_min]} ℃</p>',
            '<p>Max Temp: {[values.main.temp_max]} ℃</p>',
            '</div>',
            {
                timeFormat:function (date) {

                    var days = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'];
                    var newDate = date;

                    return days[newDate.getDay() - 1] + " "
                            + newDate.getHours() + ":"
                            + newDate.getMinutes() + ":"
                            + newDate.getSeconds();
                }
            }
        )
    },

    initialize:function () {
        this.callParent();
    }

});

Suddenly it’s become a lot more complicated.

Points of interest that we spoken about already

Again this view extends a component, a new component called List. Can you imagine what that does?

  • xtype is ‘Weather’. This component is included in the Main.js view via this xtype
  • Config parameter for configuring this tab
  • An Items parameter that has something to do with a toolbar at the top of the View

New stuff:

  • A store called Weather
  • The list component
  • itemTpls

We’ll cover all this in the next tutorial.

Code here:

You can clone to the branch and browse to the app to see the two tabs in action.

https://github.com/jamiegood/WeatherApp/tree/TwoPanelTabs

Tutorial 1: Developing Weather Mobile Web App with Sencha Touch

Introduction:

The world needs yet another weather app. So let’s build it.

We’ll will use the Sencha Touch JavaScript framework to create the mobile web app. Over the course of several bite sized tutorials we will add need features and explore the framework.

  • Tabbed views
  • Weather information for the current date for a selected location
  • An about page
  • Possibly a weather map if we make it that far 🙂

For this tutorial we will re-create the simple getting started app.

And go from there.

Git repo

Prerequisites:

Getting Started App

We will use Sencha CMD tool to create the basic Getting Started App.

In your terminal go to the directory where you  previously downloaded Sencha CMD

$ cd /Downloads/sencha-touch-2.2.0-commercial/touch-2.2.0/
$ sencha generate app WeatherApp /www/WeatherApp

where WeatherApp is a name to give your application and /www/WeatherApp is location where the Getting Started app will be placed.

Ok right now if you browse to your app location: along the lines of http://localhost/weatherap.

Hopefully if all went well then you’ll see the helpful Getting Started App.

Look over the generated app. It’s small but gives an overview of MVC with sencha touch.

And we’ll leave it there for the first tutorial.

In the next tutorial we’ll edit the getting started app and create the tab panels for the interface of our Weather App.

Code here:

https://github.com/jamiegood/WeatherApp/tree/GettingStartedApp

The Way of Testivus

20130309-122023.jpgIf you write code, write tests.
Don’t get stuck on unit testing dogma.
Embrace unit testing karma.
Think of code and test as one.
The test is more important than the unit.
The best time to test is when the code is fresh.
Tests not run waste away.
An imperfect test today is better than a perfect test someday. An ugly test is better than no test.
Sometimes, the test justifies the means.
Only fools use no tools.
Good tests fail.

The Way Of Testivus