If you have finished reading the “Setup Sencha Touch 2.1 with Sencha Cmd for PhoneGap 2” tutorial, you may want to create an app of your own. Lets do it now and create a mobile stop watch app using Sencha Touch 2.1





 

Step 1: Edit the main view and add a new panel

1.1 First cd in the root of the application

 
$ cd /sandbox/appSrc/Demo

1.2 If you open the app.js file, you will notice there is one view namely ‘Main’ already defined.

 
views : ['Main']

1.3 Lets open the view file and see what is inside.

 
$ vi /sandbox/appSrc/Demo/app/view/Main.js

In the Main.js view file, we see the “Main view” is defined as a tab.Panel and it contains 2 items.  One is the “Welcome” page and the other is the “Get Started” page.   Lets remove the ‘Get Started’ page.  Then add a new “Simple Stop Watch” page and asks the Main view to load the “Simple Stop Watch” page, as follow:

Load the stop watch view(note the Ext.Video is removed”, that was for the “Get Started” view)

 
requires: [
        'Ext.TitleBar',
        'demo.view.StopWatch'
]

Add a new view

{
    title: 'StopWatch',
    iconCls: 'action',
    xtype: 'stopwatch'
}

 

and here is the complete “Main.js” file:

 
Ext.define('demo.view.Main', {
    extend: 'Ext.tab.Panel',
    xtype: 'main',
    requires: [
        'Ext.TitleBar',
        'demo.view.StopWatch'
    ],
    config: {
        tabBarPosition: 'bottom',

        items: [
        {
            title: 'Welcome',
            iconCls: 'home',

            styleHtmlContent: true,
            scrollable: true,

            items: {
                docked: 'top',
                xtype: 'titlebar',
                title: 'Welcome to Sencha Touch 2'
            },

            html: [
                "You've just generated a new Sencha Touch 2 project. What you're looking at right now is the ",
                "contents of <a target='_blank' href=\"app/view/Main.js\">app/view/Main.js</a> -     edit that file ",
                "and refresh to change what's rendered here."
            ].join("")
        },
        {
            title: 'StopWatch',
            iconCls: 'action',
            xtype: 'stopwatch'
        }
        ]
    }
});

Note:  since the Main page is defined as a tab.Panel, the “Welcome” and “Simple Stop Watch” pages are actually panels.

Step 2: Lets create the stop watch panel

2.1 create a StopWatch.js file in the  app/view folder

 
$ vi /sandbox/appSrc/Demo/app/view/StopWatch.js

2.2 cut and paste the following:

 
Ext.define("demo.view.StopWatch", {
    extend: 'Ext.Panel',
    requires: [
        'Ext.TitleBar'
    ],
    xtype: 'stopwatch',

    config: {
        title: 'Simple Stop Watch',
        iconCls: 'time',
        layout: {
        type: 'vbox',
        pack: 'center',
        align: 'center'
    },
    items: [
    {
        xtype: 'titlebar',
        title: 'Simple Stop Watch',
        docked: 'top'
    },
    {
        xtype: 'panel',
        layout: {
        type: 'vbox',
        pack: 'center',
        align: 'center'
    },
        flex: 5,
        items: [
        {
            xtype: 'panel',
            id: 'stopWatchPanel',
            cls: 'stopWatchPanel',
            html: '00:00:00'
        }
        ]
    },
    {
        xtype: 'panel',
        flex: 1,
        layout: 'hbox',
        defaults: {
            xtype: 'button',
            ui: 'round',
            action: 'stopWatchButton',
            cls: 'stopWatchButton'
    },
            items: [ { text: 'Start' }, { text: 'Stop' }, { text: 'Reset' } ]
    }
    ]
    }
});

2.2.1 Basically, we have just created a panel in a vertical layout (vbox type) and within this panel, we have 3 subpanels, (1) a title bar (2) a middle panel that shows the time (3) a bottom panel to hold 3 buttons

2.2.1.1  (1) title bar
Yes, so simple, a titlebar called “Simple Stop Watch” and is docked at the top

 
{
    xtype: 'titlebar',
    title: 'Simple Stop Watch',
    docked: 'top'
}

2.2.1.2 (2) middle panel
Here we use a vertical layout again for two panels, and the contents are centered in the middle.
And the first subpanel is identified as “stopWatchPanel” (tag with id) and will be styled in css with the same name (class name).
The html text is default to “00:00:00”.

{
    xtype: 'panel',
    layout: {
        type: 'vbox',
        pack: 'center',
        align: 'center'
    },
    flex: 5,
    items: [
    {
        xtype: 'panel',
        id: 'stopWatchPanel',
        cls: 'stopWatchPanel',
        html: '00:00:00'
    }
    ]
}

2.2.1.3 (3) bottom panel
Here I am using a horizontal layout to place 3 buttons. Defaults section is there to apply what inside to all the items followed. So the items are all “button”, with a “round” ui, and they have a “action” named “stopWatchButton” (this will be used in the controller which we will define next) and will be styled in css with the class name “stopWatchButton”

 
{
    xtype: 'panel',
    flex: 1,
    layout: 'hbox',
    defaults: {
    xtype: 'button',
    ui: 'round',
    action: 'stopWatchButton',
    cls: 'stopWatchButton'
},
    items: [ { text: 'Start' }, { text: 'Stop' }, { text: 'Reset' } ]
}

step 3: Now create the stop watch controller

3.1 Lets tell the app we have a new controller

$ vi /sandbox/appSrc/Demo/app.js

and add the following (lets add it before the “Main” view):

controllers: [ 'StopWatchController' ],
views : ['Main']

3.2 create a “StopWatchController.js” file in the app/controller folder

$ vi /sandbox/appSrc/Demo/app/controller/StopWatchController.js

3.2.1 cut and paste the following code:

Ext.define("demo.controller.StopWatchController",{
	extend: 'Ext.app.Controller',

	config: {
		statics: {
			stopWatchInt: undefined
		},
		refs: {
			stopWatchPanel : 'stopWatch #stopWatchPanel'
		},
		control: {
			'button[action="stopWatchButton"]' : {
				tap: function(swButton) {
				    var actionType = swButton.getText();

				    function updateStopWatch(watchObj) {
				    	var elapseTime;
				    	var minSec = watchObj.getHtml().split(":");
				    	var min  = parseInt(minSec[0],10);
				    	var sec  = parseInt(minSec[1],10);
				    	var msec = parseInt(minSec[2],10);

				    	msec++;
				    	if ( msec == 10 ) { sec++; msec = 0; }
				    	if ( sec  == 60 ) { min++;  sec = 0; }

				    	elapseTime  = (min  < 10) ?  "0" + min  : min;
				    	elapseTime += (sec  < 10) ? ":0" + sec  : ":" + sec;
				    	elapseTime += (msec < 10) ? ":0" + msec : ":" + msec;

				    	watchObj.setHtml(elapseTime);
				    }

					switch(actionType) {
					case "Start": 
						var thisScope = this;
						if ( self.stopWatchInt != undefined ) { clearInterval(self.stopWatchInt); }
                        stopWatchInt = setInterval(function() {
                        	updateStopWatch(thisScope.getStopWatchPanel());
                        }, 100);
						break;
					case "Stop":
						clearInterval(stopWatchInt);
						stopWatchInt = undefined;
						break;
					case "Reset":
						clearInterval(stopWatchInt);
						stopWatchInt = undefined;
						this.getStopWatchPanel().setHtml("00:00:00");
			            break;
					}
				}
			}
		}
	}
});

3.2.1.1 Lets go over the Sencha Touch piece. Here I define a static variable to hold the integer the Javascript setInterval function returns. This integer will be used to determine if a stop watch is already defined and clear it when we need to reset the stop watch.

 

3.2.1.2 The refs section. In here, we have a JQuery type of selector, “stopWatch #stopWatchPanel”. The first “stopWatch” refers to the stopWatch view. While the “#stopWatchPanel” refers to the “stopWatchPanel id” defined in the stopWatch view. And we will refer to this selection as “stopWatchPanel” in this controller. One cool feature with Sencha Touch is that, whatever defined in the refs sections, automatically, it will provide you with a getter and setter methods. In our case, Sencha Touch gives us a “getStopWatchPanel()” and a “setStopWatchPanel()” methods to manipulate the stopWatchPanel object.

refs: {
	stopWatchPanel : 'stopWatch #stopWatchPanel'
}

3.2.1.3 Within the “control” section is where the actions are taking place. Here we tell the controller what to do when a button with an action variable set to “stopWatchButton” is “tapped”.   As you have observed, when the button is tapped, whatever inside of tap: function(swButton) {} will be executed.

control: {
	'button[action="stopWatchButton"]' : {
		tap: function(swButton) {
		...
		}
	}
}

Step 4: Add CSS styling

4.1 In step 2, we declare 2 classes for CSS, namely “stopWatchPanel” and “stopWatchButton”.

    {
        xtype: 'panel',
        id: 'stopWatchPanel',
        cls: 'stopWatchPanel',
        html: '00:00:00'
    }

and

    {
        xtype: 'panel',
        flex: 1,
        layout: 'hbox',
        defaults: {
            xtype: 'button',
            ui: 'round',
            action: 'stopWatchButton',
            cls: 'stopWatchButton'
    }

Lets style them a bit by adding the following to the style section of the index.html page.

$ vi /sandbox/appSrc/Demo/index.html

Add to within the style tag

        .stopWatchPanel {
        	font-style: 'bold';
        	font-size: 5em;
        }
        .stopWatchButton {
         	margin: 0.25em;
        	padding:0.75em;
        }

 

Step 5: Mission accomplished. Lets test

timer