Book Image

Instant Sencha Touch

By : Hiren Dave
Book Image

Instant Sencha Touch

By: Hiren Dave

Overview of this book

Sencha Touch, a high-performance HTML5 mobile application framework, is the cornerstone of the Sencha HTML5 platform. Built for enabling world-class user experiences, Sencha Touch is the only framework that enables developers to build fast and impressive apps that work on iOS, Android, BlackBerry, Kindle Fire, and more. Instant Sencha Touch is a practical hands on guide that provides you with all you need to explore the Sencha Touch framework and start building high performance, cross platform mobile applications with rich user interfaces. It also covers native deployment of Sencha Touch applications on various platforms. Instant Sencha Touch is a step-by-step guide that will explain you everything from downloading Sencha Touch SDK to setting up the development environment, and building applications. You will start with a quick overview of the Sencha Touch and work your way through understanding the class structure, and basic components and layouts of the Sencha Touch. You will also cover interesting features like animations, adaptive layout, data packages, local storage support, and so on. You will also see how to build your own theme and styles and deploy Sencha Touch app as native apps. You will also learn about MVC architecture for building Sencha Touch applications. Finally you will take a look at the Phonegap (Cordova) build and Cordova SDK to deploy Sencha Touch application as native application.
Table of Contents (6 chapters)

Top 12 features you need to know about


In this section we will see some of the top features of the Sencha Touch framework that you should know in order to build a Sencha Touch application.

Animations

Animations will enhance your application's user interface. They will make it lively. Sencha Touch supports some default animations; you can use them to show your animated views. The following are the animation values supported by Sencha Touch:

  • fade

  • cube

  • flip

  • pop

  • slide

  • wipe

Sencha Touch has the Ext.Anim class using which we can run these animations. For example, refer to the following code snippet:

Ext.Anim.run(comp, slide, {
    out: false,
    autoClear: true
});

In the preceding code snippet, comp is the component that we want to animate, and slide is the type of animation. We can control animations with some configs.

Also, we can apply animation using the animateActiveItem function of the container or panel. For example, refer to the following line of code:

panel. animateActiveItem(item,{ type: 'slide', direction: 'right', duration:2000});

The preceding line of code will show the item with slide pointing to the right direction. We can also control the navigation time with the number of milliseconds in config. Also, animation can be applied to show an overlay.

panel.show({ type: 'slide', direction: 'right', duration:2000});

The preceding line of code will show the overlay panel with slide pointing to the right direction. In the same way, we can use other navigation. The slide navigation is used by many components such as the navigation view and the nested list. We don't need to specify it.

Adaptive layouts

Sencha Touch's layout engine is quite powerful to make an adaptive layout. It responds to events such as load and orientation change, and adjusts itself quickly. So we don't have to worry about a device's variable width and height; it will automatically adjust itself in any of the devices and in any orientation. We can also bind events such as orientation change, and do manual adjustments if necessary. As we saw in the previous section, we can take advantage of adaptive layout with the flex config, and arrange the components horizontally or vertically or create some complex layout. To take the maximum advantage of adaptive layout, we don't assign any height or width to Sencha Touch components unless it's necessary, and it will automatically adjust itself. Any component with the flex config will automatically adjust its height and width according to the parent container and relative to other components. The flex config can also be mixed with absolute dimensions.

Sencha Touch component queries

A component query is a powerful way to search for components. It can search for components from Ext.ComponentManager, a container, a panel, or DOM. There are various ways to find components. If you are looking for a specific type of component, we can use xtype to search for the component. For example, refer to the following line of code:

container.query('panel');

Or:

container.query('.panel');

The preceding line of code will return all the panels from the specified container in an array. We can search for more than one xtype at a time. For example, refer to the following line of code:

container.query('panel, gridpanel, tabpanel');

In the same way, we can use any xtype attribute to search for components. Another way to search for components is with id or itemId. For example, refer to the following line of code:

panel.query('#myitem');

It will return all the components that have id or itemId as myitem. While searching with id or itemId, we have to add # as a prefix, otherwise it will not be able to search. We can also search for components with attributes. For example, refer to the following line of code:

container.query('panel[title="MyTitle"]');

The preceding line of code will return all the panels from the specified container in an array that has the title MyTitle. In the same way, we can also search with other configs and attributes.

We can also find inner components for any particular component. For example, refer to the following lines of code:

container.query('#myPanel panel');
container.query('#myPanel > panel');

The first line in the preceding code snippet will display all the panels from the component that has the ID myPanel, and the second line of the example code snippet displays only the direct children of the type panel for the component that has the ID myPanel. So the component queries are used to find any components from your application.

Event handling

Most of the Sencha Touch applications are interactive applications. This means that all the components should respond to user events such as touch, swipe, tap, and so on. When an event occurs, we have to take some action. So, it's normally an execution of code when the event occurs. Normally, we execute a function as an action of an event; we call it an event handler. There are two ways in which Sencha Touch can invoke some actions on events as follows:

  • Event bindings

  • Controller actions

We will see controller actions in a later section when we will go through the details of the MVC structure. In this section we will see how we can bind events. We should only use event binding when an event and its handler code are available in a single view and do not depend on other views or components in an application. This means that the scope of event handlers is limited to a single view file. So in this case, the declaration of events and events handlers is in a single file, and it cannot be accessed outside that view. So event binding listens to a particular event to be fired and then invokes a function in the same file. The function is called with a certain number of parameters depending on a specific event. For example, create a new folder with the name event-binding0-demo in your local web server and copy all the resources to it as mentioned in the previous section. Create an app.js file and add the following code snippet to it:

Ext.application({
  name: 'EventBindingDemo',
    launch: function () {
        var panel = Ext.create('Ext.Panel', {
           fullscreen: true,
           items: [{
           xtype: 'button',
           text: 'Tap Me',
           listeners: {
              tap: function(button){
              Ext.Msg.alert('Tap', 'Button Tapped');
              }
           }
           }]
        });
        Ext.Viewport.add(panel);
    }
});

The preceding code snippet will create a button, and when you tap on it, it will show an alert message. listeners is the config for any component to add event handlers. In the preceding code snippet, tap is the event and function is the handler, which will be invoked when the event is fired. You can add more than one event handler in the listeners config for a single component. For example, refer to the following code snippet:

listeners: {
    tap: function(){
    },
    painted: function(){
    }
}

In the preceding code snippet, we bind two events for a button: tap and painted. The respective functions will be invoked when the respective events would be fired. In all the cases of event bindings, listeners will be invoked in the scope of the parent container. So, the this keyword in the respective handler function refers to a component on which the handler method is defined.

Sencha Touch charts

Sencha Touch charts present data to users in various chart formats, and allow users to interact with them through various gestures such as zoom in and zoom out. Built on HTML5, Touch charts will run on any mobile or tablet device. Touch charts also use adaptive layouts to support any width and height of mobile devices, and support both landscape and portrait orientation. Chart legends are also generated based on the available width and height. If there is not much space, legends are displayed as a slide-out menu. In case of enough width, they are displayed inline. We can also configure types of interactions with charts. For example, in a mobile a user can rotate a pie chart, or in a bar chart a user can tap on the bar to view information, or a user can zoom in or zoom out. These interactions are configurable. Touch charts directly work with Sencha Touch's data packages. So you can configure a store for charts and configure a field of charts to be displayed on the respective axes of the chart. You can configure a number of axes and legends for the charts. Chart styling can also be applied with normal SASS styling that we will see in a later section. Let's see a simple example of a chart. Create a new folder chart-demo in the web server and copy all the Sencha Touch resources there. Add the following code to the app.js file:

Ext.application({
  name: 'ChartDemo',
    launch: function () {
        var chart = new Ext.chart.Chart({
           store: {
              fields: ['month', 'revenue'],
              data: [
                 { month:'Jan', revenue:100},
                 { month:'Feb', revenue:150},
                 { month:'Mar', revenue:200},
                 { month:'Apr', revenue:50},
                 { month:'May', revenue:45},
                 { month:'Jun', revenue:100},
                 { month:'Jul', revenue:140}
                ]
                },
           axes: [{
               type: 'numeric',
               position: 'left',
               title: {
                  text: 'Revenue',
                  fontSize: 15
               },
               fields: 'revenue'
            }, {
               type: 'category',
               position: 'bottom',
               title: {
                  text: 'Month',
                  fontSize: 15
               },
               fields: 'month'
            }],
            series: [{
               type: 'bar',
               xField: 'month',
               yField: 'revenue',
               style: {
                  fill: 'blue'
               }
            }]
         });
         Ext.Viewport.setLayout('fit');
         Ext.Viewport.add(chart);
    }
});

When you run this code you will see a bar chart. There are two important configurations for any chart: axes and series. axes defines the number of axes, title, and type of axes, and series defines the type of chart. We can define more than one series in a single chart. Depending on series, the particular configuration is applied. The following are various series supported by Touch charts:

  • Area

  • Bar

  • Cartesian

  • Gauge

  • Line

  • Pie

  • Polar

  • Radar

  • Scatter

  • Series

To show a legend for charts, we can add the legend config and define its position. Legends are useful when you have more than one series in your chart.

legend: {
position: 'bottom'
}

Interactions can be added with the interactions configs. The following are the types of interactions we can add in charts:

  • ItemInfo

  • PanZoom

  • Rotate

  • CrossZoom

  • ItemHighlight

  • RotatePie3D

All the interactions have a callback function that will be invoked when interaction events are fired with some parameters. For example, refer to the following code snippet:

interactions: [{
  type: 'iteminfo',
  listeners: {
    show: function(me, item, panel) {
      panel.setHtml('Revenue is $' + item.record.get('revenue'));
    }
  }
}]

After adding the preceding interactions config, when you tap on any bar of the chart, it will show an overlay panel with some HTML. In the same way, any other interaction can be added to the chart using the callback function. Sencha Touch charts can be rendered only in the fit layout, so make sure that your chart container has the fit layout.

Offline support

As Sencha Touch is built for mobile devices, sometimes it's necessary to have offline support in any application because it might be possible that there isn't any network connection in your mobile device, or there is a special requirement for the application to store data offline. This is like a shopping cart, where we need to preserve items added to the cart till the order is placed. So, it's good to have offline support in your application so that it can run with the network connection once loaded. Sencha Touch supports offline capability with HTML5 local storage. HTML5 local storage is a key-value pair storage, so it will automatically serialize or deserialize data while adding or retrieving data from it. Sencha Touch has the localstorage proxy using which we can store data offline. For that, you have to define a store with the localstorage proxy. We already saw in the earlier sections that we can either define a proxy with a model or a store. Check out the following example:

Ext.define('OfflineModel', {
    extend: 'Ext.data.Model',
    config: {
        fields: ['id', 'name'],
        proxy: {
            type: 'localstorage',
            id  : 'offlineproxy'
        }
    }
});

The preceding code snippet will create a model with the localstorage proxy and some fields. Here, it's necessary to add a unique ID field in the model, and that will be used as the key while storing data in a local storage. If we don't add it, it will automatically create a field internally. Now let's create a store with the created model.

var store = Ext.create('Ext.data.Store', {
    model: 'OfflineModel'
});

The preceding code snippet will create a store with an offline model. Now let's see how it works with HMTL5 local storage.

store.add({name: 'John Smith'});
store.sync();

The preceding code snippet first adds an item in the store and then uses the sync() function. It will add data to HTML5 local storage only when the sync() function is called. So it's necessary to sync the store after any changes. We are not passing an ID, so it will automatically generate a new ID and encode it for local storage. Also, when the application loads or is refreshed, we should use the load() method to load data to the store. The localstorage proxy only works with WebKit browsers, so that could be one disadvantage. Using offline support, our app can work offline and continue storing data offline, and we can build the architecture to synchronize data with the server based on network availability. When you clear the cache of your browser, this data would be removed or you can clear all the data with the localStorage.clear() method.

Fetching remote data with Ajax

Sencha Touch provides users with the Ext.Ajax class to fetch remote data from the server to your applications. Using this class, you can send Ajax requests to the same domain on which your application is hosted. Requests to other domains are blocked. Refer to the following code snippet of a simple Ajax request:

Ext.Ajax.request({
    url: 'myUrl',
    method: 'POST',
    params: {
    },
    success: function(response) {
        
    },
    failure: function(response){

    }
});

The preceding code snippet shows a simple Ajax request. success and failure are callback functions. Based on the response of the Ajax request, the respective callback function would be invoked. Data returned from the server is a response object. You can use the Ext.decode function if the server returns JSON data. You can specify the method of the Ajax request and pass any data to the server with the params config, or if you want to send JSON data back to the server, you can use the jsonData config.

The MVC structure

Sencha Touch supports MVC architecture that reduces the development time and improves the application's performance. Also, it's very easy to add new features to the application while using MVC. There are several components of MVC.

Model

Model defines the entities of the application. It manages the data and behavior of the entity. Sencha Touch has a base class, Ext.data.Model, which we can extend to create our own model. We used a model to define some fields or custom fields for entities. For example, refer to the following code snippet:

Ext.define('AppName.model.Employee', {
    extend: 'Ext.data.Model',
    config: {
        fields: [
   {
        type: 'int',
        name: 'employee_id'
   },
   {
        type: 'string',
        name: 'employee_name'
   },
   {
        type: 'number',
        name: 'gross_salary'
   },
   {
        type: 'number',
        name: 'allowance'
   },
   {
        type: 'number',
        name: 'net_salary',
        convert: function(value, record){
           return record.get('gross_salary') + record.get('allowance');
        }
   }
        ]
    }
});

This code snippet defines an employee model with some fields. We can define the type and name of the field. Refer to the net_salary field, which is a custom field. We have defined the custom function to create a value for it.

View

Views are the UI components of the application. The end user directly interacts with them. All the actions of users are passed to controllers. Views are defined by extending the base Sencha Touch classes. Each view class defines the necessary configs and functions for the view. For example, refer to the following code snippet:

Ext.define('AppName.view.MyView', {
    extend: 'Ext.Panel',
    layout: 'fit',
xtype :'customxtype',
    config: {
    flex: 1,
    items: [
        {
              xtype: 'panel',
              items: []
        }
    ]
    }
});

This code snippet defines a view by extending the Ext.Panel class. It defines all the configs for the panel. We can also define the custom xtype attribute for the view that can be used to reference the view in the controller.

Controller

Controller is the most crucial part of the MVC architecture. It defines the event handlers for all the events of the application. It can have references of the views and can show or change the views. All the business logic is written in controllers. Extending the base Ext.app.Controller function creates a controller class.

Ext.define('AppName.controller.MyController',{
    extend : 'Ext.app.Controller',
    config : {
        refs : {
            customxtype: 'customxtype'
        }
    },
    init : function() {
        this.control({
            customxtype: {
          }
        });
    }
});

This code snippet will create a controller. The refs config is used to add references to the views and other components. The init function will be invoked when a controller is initialized, and this.control({ }) is used to add actions for the various events.

Store

Store is used to store and retrieve data from the remote services. Sencha Touch has the Ext.data.Store base class, which can be used to extend and create a user-defined class. Store has functions for filtering and sorting. This store binds various data view components such as Ext.dataview.DataView or Ext.List. For example, refer to the following code snippet:

Ext.define('AppName.store.MyStore', {
    extend: 'Ext.data.Store',
    config: {
    autoLoad: true,
        model: 'AppName.model.MyModel',
        storeId: 'myStoreId'
    }
});

The preceding code snippet will create a store with a model and other configs.

A sample application

In this section we will build a sample application with the MVC structure. First, we will see how to configure your application for that. We specify all the controllers, models, stores, and views in the application config. First of all, create the mvc-demo folder in your web server and copy all the Sencha Touch resources to it. Check out the following steps to start developing a sample application:

  1. Create a folder named mvc-demo.

  2. Create a folder in mvc-demo and name it app.

  3. Create the following four folders inside the app folder:

    • model

    • view

    • controller

    • store

We will build a simple application to manage contacts. This application will first display a list of contacts when it's launched. A user can select a contact to view the details. First of all, create the app.js file and add the following code to it:

Ext.application({
  name: 'Contacts',
  models: ['Contact'],`
  stores: ['ContactsStore'],
  views: ['MainView', 'ContactList', 'ContactView'],
  controllers: ['ApplicationController'],
    launch: function () {
        Ext.Viewport.add(Ext.create('Contacts.view.MainView'));
    }
});

This code snippet will create the Contacts application. Here we have specified the following four new configs in the application.

  • models

  • stores

  • views

  • controllers

Here we specify the names of all the models, views, stores, and controllers. Ext.Loader will load all the files from the respective folders. Ext.Loader always works with a predefined path. It always assumes that all the models specified here will be available in the app/model folder with the respective filenames. That's why it's very important to give an exact name to files and folders. Now let's create a model. Create a new file with the name Contact.js in the app/model folder and add the following code to it:

Ext.define('Contacts.model.Contact', { 
  extend: 'Ext.data.Model',
    config: {
        fields: [{
          name: 'id',
          type: 'int'
         },{
          name: 'name',
          type: 'string'
         },{
          name: 'email',
          type: 'string'
         },{
          name: 'phone',
          type: 'string'
         }],
        idProperty: 'id'
  }
});

The preceding code snippet will define a contact model by extending the Ext.data.Model class with some fields specified in the fields config. Now create a new file with the name ContactsStore.js in the app/store folder and add the following code to it:

Ext.define('Contacts.store.ContactsStore', {
  extend : 'Ext.data.Store',
  config: {
    model: 'Contacts.model.Contact',
    autoLoad:true,
    data: [{
      id: 1,
      name: 'John Smith',
      email: '[email protected]',
      phone: '8503985763'
    },{
      id: 2,
      name: 'Marcus Anthonsen',
      email: '[email protected]',
      phone: '2374923874'
    },{
      id: 3,
      name: 'Matt Yang',
      email: '[email protected]',
      phone: '3473264764'
    },{
      id: 4,
      name: 'Martin  Raymond',
      email: '[email protected]',
      phone: '3845738457'
    },{
      id: 5,
      name: 'Hung Luu',
      email: '[email protected]',
      phone: '3483478374'
    }],
    proxy: {
      type: 'memory'
    }
  }
});

The preceding code snippet will create a store by extending the Ext.data.Store class with some predefined data in the store. Now we will create our main view. Create a new file in the app/view folder with the name MainView.js and add the following code to it:

Ext.define('Contacts.view.MainView', {
    extend : 'Ext.Panel',
    xtype : 'mainview',
    config : {
        layout : 'card',
        items : [{
        xtype: 'contactlistpanel'
    }]
    }
});

This code will create a main view of the application by extending the Ext.Panel base class. We have added an item in the main view at the start. Note that the xtype attribute of this view is specified as mainview. It is a user-defined xtype attribute. Now let's create a child view. Create a new file named ContactList.js in the app/view folder and add the following code to it:

Ext.define('Contacts.view.ContactList', {
    extend : 'Ext.Panel',
    xtype : 'contactlistpanel',
    config : {
    layout: 'fit',
        fullscreen: true,
        items: [{
           xtype: 'toolbar',
           docked: 'top',
           title: 'Contacts'
    },{
           xtype: 'list',
           itemId: 'contactlist',
           id: 'contactlist',
           itemTpl: '{name}',
           onItemDisclosure: true,
           store: 'ContactsStore'
    }]
    }
});

This code will create our list with all the contacts. This view has a toolbar and a list as items. We have used this view's xtype attribute to add it to MainView. This view will display a list of all the contacts with the names. We can change the template the way we want. Now we will display the details of a specific contact that is selected from the list. For this, we have to create a separate view, and we will control that view from the controller. Create a new file with the name ContactView.js in the app/view folder and add the following code to it:

Ext.define('Contacts.view.ContactView', {
    extend : 'Ext.Panel',
    xtype : 'contactview',
    config : {
        layout : 'fit',
        items : [{
           xtype: 'toolbar',
           itemId: 'contactViewTopToolbar',
           docked: 'top',
           items: [{
              xtype: 'button',
              ui: 'back',
              text: 'Back',
              itemId: 'btnBackContactView',
              id: 'btnBackContactView'
           }]
    },{
           xtype: 'panel',
           itemId: 'contactpanel',
           id: 'contactpanel',
           tpl: new Ext.XTemplate('<h4>Name : {name}</h4><h4>Email : {email}</h4><h4>Phone : {phone}</h4>')
    }]
    }
});

The preceding code snippet will create a panel with a toolbar and a panel that has a template defined with the tpl config to show the details of the contact. In this code snippet, we have used the ui config with a button. Sencha Touch has some predefined user interfaces for some of the components. The ui config will define the look and feel of the components. Now let's create a controller. Create a new file with the name ApplicationController.js in the app/controller folder and add the following code to it:

Ext.define('Contacts.controller.ApplicationController',{
  extend : 'Ext.app.Controller',
    config : {
       refs : {
          mainView: 'mainview',
          contactListPanel: 'contactlistpanel',
          contactList: '#contactlist',
          contactView: 'contactview',
          btnBackContactView: '#btnBackContactView'
    }
  },
    init : function() {
        this.control({        
          contactList: {
             select: 'onContactSelect'
          },
          btnBackContactView: {
             tap: 'goBackToContactList'
          }
    });
  },
  onContactSelect: function(list, record){
    if(!this.contact){
          this.contact = Ext.create('Contacts.view.ContactView');
    }
    this.getMainView().animateActiveItem(this.contact, {type: 'slide', direction: 'left'});
    this.contact.query('#contactpanel')[0].setData(record.data);
  },
  goBackToContactList: function(button) {
    this.getMainView().animateActiveItem(this.getContactListPanel(), {type: 'slide', direction: 'left'});
  }
});

The preceding code snippet will create a controller with the necessary references and event handlers. Please check the refs config of the controller. We have added references of our view with the xtype attributes and itemId. The reference with xtype is added with the name of the xtype attribute, while the reference with itemId is added with the # prefix. This is how we can add a reference to the view or items of the views with xtype, itemId, or id in the controller. Sencha Touch generates a getter function for each reference we have added. For example, to get an active instance of mainview, we can use the getMainView() function. We can also add a reference with a component query. For example, refer to the following line of code:

Panel: '#myPanel panel'

This line of code will add a reference of the child panel item of panel with the item ID mypanel.

The this.control section defines the actions or event handlers for the user events. We use the reference we added in the refs section to define events and event handlers to it. For example, refer to the following code snippet:

contactList: {
select: 'onContactSelect'
}

Here we have added a select event, and the event handler is the onContactSelect function. Here, onContactSelect should be available in the same controller file. This way we can define more than one event and handlers for a single component. Here all the functions execute in the scope of the controller. So this keyword always returns an instance of the controller. So in the preceding code snippet, onContactSelect will be invoked with some params when the user selects any record in the list. When a user selects any record, we create a contact view panel if it's not already created, and set the data for the template so that it will display details of the selected contact. The user can go back to the list again by tapping on the back button in this view. goBackToContactList is the function executed when the user taps on the back button. Here we have used the animateActiveItem function to show the view with animation. So in this way, we can add a number of references to views in controllers and define event handlers for the components in controller files.

Theming in Sencha Touch

In this section we will see how to create a custom theme in Sencha Touch using SASS. Sencha Touch uses SASS to create a new theme.

What is SASS?

Syntactically Awesome Stylesheets (SASS) is the CSS preprocessor. It will take a piece of code in a different syntax and convert it to the target syntax. In the case of Sencha Touch, it takes the .scss file and converts it into CSS files. So with very less effort, you can generate a CSS. SASS is a Ruby package so you need Ruby to run it. Mac and Linux have Ruby runtime by default, but in Windows you have to install it. On Mac, open the terminal and run the following command:

$ sudo gem install sass

This will install SASS. Now let's understand a few terms in SASS.

Variables

SASS supports dynamic variables (used to hold some values) that you frequently use in CSS, such as the base color hex value. For Sencha Touch, we have some predefined variables for all the controls that you can find in the API documentation, as shown in the following screenshot:

Mixins

They allow users to create re-usable blocks of CSS to be used with the @include constructor. Sencha Touch also has predefined mixins for each component that you can find in the API document as shown in the following screenshot:

Compass is used to compile the .scss file in the case of Sencha Touch. Run the following command in the terminal:

sudo gem install compass --pre

So to create a custom theme for Sencha Touch, we have to create a new .scss file with all the variables declared in it, and then we compile it with Compass; it will generate a CSS for us. You can find the existing .scss files in the resources/sass folder. Here you can create a new .scss file by using variables defined in the API document. The following is an example of a .scss file. Save it inside the resources/sass folder with the name custom.sass.

$base-color: #f7f7f7;
$toolbar-base-color: $base-color !default;
@import 'sencha-touch/default';
@import 'sencha-touch/default/all';

In the preceding command lines, we have defined the base color for the whole app and the base color for the toolbar. You can define as many variables as you want in a single .scss file, but the variables should be valid and should have valid values assigned to them. The last two statements in the preceding command line will import default values for the rest of the variables, which are not defined here in the file. So we don't need to define all the variables here. Just define what you want to change.

Once the .scss file is created, you have to compile it. Go to the terminal and navigate to the resources/sass folder where you have the custom.scss file. Run the following command in the terminal:

Compass compile

It will generate a custom.css file in the resources/css folder. You can attach this CSS file instead of the default CSS file, and it will show the new colors and a new theme.

Native packaging of Sencha Touch applications

When we build an application in Sencha Touch, it is normally a web application, which can run in the browser. Since Sencha Touch works on different platforms, we can wrap a Sencha Touch application using some native wrappers and convert it to a native application. Sencha Touch mimics the look and feel of a native application. There are many native wrappers available for it. For example, Sencha Touch has its own native packaging tool; we can use it to package apps for Android and iOS platforms. For other platforms, we have to use Apache Cordova, formerly known as PhoneGap. Its native wrapper supports various platforms such as Android, iOS, BlackBerry, and Windows. It contains various plugins and APIs to use hardware such as a camera, GPS, and an SD card. There are two ways to use Apache Cordova as follows:

  • Using PhoneGap Build

  • Using SDK

Using PhoneGap Build

PhoneGap Build is a Cloud-based build process to build and package apps for various platforms. To build your own applications, upload your Sencha Touch applications on your PhoneGap build account, select the platforms, and trigger the build. In a very short period of time, you get your deployable files. For an iOS build, we need the provisioning profile and developer certificate that we will see in a later section. For this, you have to register at http://build.phonegap.com. Once you are signed in, you can create a new application and upload the source files.

Once the source file is uploaded, you can configure application icons, names, version descriptions, and so on.

After that, you can trigger the build by selecting various platforms and it will generate the deployable units for each platform.

Using SDK

Apart from PhoneGap build, we can use the Cordova SDK to build native applications. Cordova has an SDK for each single platform that we can use with the respective IDEs such as Xcode or Eclipse to build the native application. For that, first you have to download SDK from the Web. For this example, we are using Cordova 1.5 for the iOS as it creates a new template in your Xcode, and you can directly create an application from it. Other versions are using command-line tools, and that is a bit difficult to start. So select PhoneGap 1.5 from its download site and install SDK for iOS. Now open Xcode and create a new project; you should see a new template named Cordova-based Application as shown in the following screenshot:

It will create a new project for you. Initially, there is no www folder here. So when you run the application, it will give you an error, but it will generate the www folder inside your app folder. Now right-click on the project in Xcode, click on the Add Files option, and add the www folder created inside the project folder. It contains the Phonegap-1.5.0.js file and the index.html page. Phonegap-1.5.0.js is the file that contains all the classes of PhoneGap. It also contains the plugins that are necessary to interact with the hardware and utilize the functionalities for PhoneGap. This file is necessary to include your Sencha Touch's app.js file and other files in the index.html file. Copy your app folder and other resources here and run the app again; you will see your Sencha Touch application running as a native application. Now the www folder contains all our web assets. This is the starting point for our application. It will also create an icon of the app. Once you run, it will run the application in the simulator. To test it in a real device, you need an Apple developer account and you will have to add the developer certificate and create a provisioning profile. Apple allows you to test the application in 100 test devices. So you also have to register your devices in the Apple developer account. For that, you need the UDID of the device that you can get by connecting your device with the system and check it with iTunes. Once you have registered your devices, create a provisioning profile that will include your developer certificates and device information. You have to use this profile in your device before loading the application in any device. To generate a certificate, you first have to create a certificate-signing request. For this, open a key chain by navigating to Applications | Utilities. After that, navigate to Certificate Assistant | Request a Certificate from Certificate Authority. It will show you the Certificate Assistant window. Enter your name, e-mail address, and choose the option Save to Disk. It will save your certificate-signing request to your disk. Now go to your Apple developer account and generate a new certificate by uploading this request.

Once your certificate is ready, you have to create an app ID, register your devices, and generate a provisioning profile. Refer to the following screenshot:

Now download the certificate and the provisioning profile from the account, load it in the device using iTunes, and run the application by connecting the device to your system.

In the same way, we can use this SDK to build projects for other platforms such as Android. For Eclipse, first create an Android application project. Create two new folders in your app, assets/www, and libs folders. Now copy the Cordova JAR files from the SDK you downloaded to the libs folder. Once it's done, we have to configure the build path. For that, right-click on your project and navigate to Build Path | Configure Build Path. Make sure that the Cordova JAR file is included here, otherwise add it.

Once it's done, copy the Cordova.js file from the SDK to the assets/www folder. Now go to your main activity class in the src folder and add the following code to it:

import org.apache.cordova.*;

public class MainActivity extends DroidGap {

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.loadUrl("file:///android_asset/www/index.html");
  }
}

Also, create an index.html file in the assets/www folder and add a reference to your Sencha Touch files and resources along with the Cordova.js file. Open the AndroidManifest.xml file and add the following code before the <application> tag:

<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />

Now compile and run the application and it will run as a native Android application. You can also test this application by connecting your device to your system.

Accessing hardware and native APIs

When we deploy a Sencha Touch application as a native application, we can use some native APIs provided by Sencha to access the hardware of your device. This is one of the major benefits of native packaging of the application. For this, we have a class in Sencha Touch called Ext.device. This class is not actually an API, but it's just a wrapper and can be used to access native APIs provided by Cordova, other third-party solutions, or APIs provided by the Sencha Native packager. As of now, there are four classes in the Ext.device class as follows:

  • Ext.device.Connection

  • Ext.device.Notification

  • Ext.device.Orientation

  • Ext.device.Camera

Since these native APIs only work when your application is packaged for native deployment, it's not a part of the Sencha Touch build. You have to add them separately using the Ext.require class.

Ext.require('Ext.device.Connection');

Ext.application({
    name: 'DemoApplication'
});

After that you can use it. For example, refer to the following code snippet:

if (Ext.device.Connection.isOnline()) {
    Ext.Msg.alert('Connection Available');
} else {
    Ext.Msg.alert('No Connection Available');
}

There are a number of plugins developed for Cordova using which you can access other native APIs that do not exist in the Ext.device class. These plugins are composed of a single JavaScript interface for all the platforms and a respective native interface for each single platform. To create your own plugin for Cordova, you have to create a native interface for a particular platform, and create a common JavaScript interface that will be used to invoke native functions.

Thus, in this section, we learned everything we need to know to build real-time applications using Sencha Touch.