Moundz and Sencha Touch
Moundz and Sencha Touch
===
Moundz and Sencha Touch
By now, you should be feeling pretty comfortable integrating frameworks into Moundz. Integrating Sencha will be a little different from our previous experiences due to the way Sencha libraries function.
The first part of this process is to call Ext.setup within our MOUNDZ module to properly initialize our Sencha Touch application:
MOUNDZ = (function() { ...
Ext.setup({ onReady: function() {
module.init();
return module; })();
In this case, we are simply telling Sencha Touch that, when it is properly initialized, we want to execute the init function of our MOUNDZ module. In addition to the onReady handler defined in the preceding code, the Ext.setup function can take parameters that can be used to configure the look and feel of the application and device integration for various platforms. More details on the setup function can be found in the Sencha Touch documentation, at http://dev.sencha.com/deploy/touch/docs/?class=Ext.
From this point, we then proceed to update our initScreen function to create the main Ext.Panel that will be used to drive our application.
MOUNDZ = (function() { // initialize variables
CHAPTER 11: Mobile UI Frameworks Compared
var mainPanel = null, ... posWatchId = 0;
function initScreen() { mainPanel = new Ext.Panel({
id: 'mainPanel', layout: 'card',
dockedItems: [ createHeader(), createFooter()
fullscreen: true, ui: 'light', defaults: {
scroll: false },
items: [{ xtype: 'map', id: 'main_map'
}, { xtype: 'sheet', id: 'details_panel', style: 'color: white'
listeners: {
cardswitch: function(container, newCard, oldCard, index, animated) {
var backButton = Ext.getCmp('goback'); if (backButton) {
backButton[index === 0 ? 'disable' :
'enable'].apply(backButton);
} // if
Download from Wow! eBook <www.wowebook.com>
}); } // initScreen ...
var module = { ... };
Ext.setup({ onReady: function() {
module.init();
return module; })();
In this code, we update the initScreen function to create the main panel for the application. We are creating an Ext.Panel that will be used to hold the two pages for our application. The first of these pages is the map control, and the second is a details panel
CHAPTER 11: Mobile UI Frameworks Compared
that we will show the resource information on—you can see the pages defined in the items array of the panel definition.
At this point, it is worth noting that Sencha Touch actually provides a map control for embedding a Google map into our UI. This is definitely going to come in handy, as the map integration has been problematic in most of the previous frameworks.
Additionally, note the two function calls that are embedded within the dockedItems array. This is where we will create our top and bottom toolbars for our application layout.
Let’s now take a look at the createHeader function that is used to create the application header:
function createHeader() { return new Ext.Toolbar({ dock: 'top', ui: 'light', defaults: {
iconMask: true
}, layout: {
pack: 'justify'
}, items : [{
xtype: 'button', text: 'Back', ui: 'back', id: 'goback', disabled: true, handler: function(button, event) {
Ext.getCmp('mainPanel').setCard(0); } }, {
xtype: 'spacer' }, {
xtype: 'panel', html: '<h1>Moundz</h1>'
xtype: 'spacer'
}] }); } // createHeader
You can probably see in this code that the process of creating a header in Sencha is not as easy as in some other frameworks. The payoff is some extra robustness when it comes to rendering the display, but for some people the cost is too high. Additionally, the learning curve with Sencha is probably a little steeper than with other frameworks, purely due to the amount of functionality it offers.
CHAPTER 11: Mobile UI Frameworks Compared
NOTE: Due to the complexity of the Sencha Touch framework, we won’t be able to explain all of the components in detail. We will, however, endeavor to provide a feel for how the framework operates and put you on the path to finding out more and being able to explore the framework on your own.
One of the most important things to be aware of is the use of xtype to define UI elements. This is similar in many respects to the way jQuery Mobile uses the data-role attribute in the HTML to specify the kind of UI element that should be created.
UNDERSTANDING OBJECT INITIALIZATION IN SENCHA TOUCH
The main thing to get your head around when using the xtype attribute (as we did in the previous code sample) is that it is essentially interchangeable with manually creating its relevant class and referencing that variable. This is one of the quite clever aspects of the Sencha Touch approach, and it does create some interesting possibilities.
While it may take a while to digest and understand, there is a very fluid mapping between the object definitions using object literals and xtypes and their more formal definitions. For an example, take a moment to review the Ext.Toolbar reference at the following URL:
http://dev.sencha.com/deploy/touch/docs/?class=Ext.Toolbar You should start to see the relationship between the preceding definition and the attributes in the
Ext.Toolbar class. Try another one—this time Ext.Button: http://dev.sencha.com/deploy/touch/docs/?class=Ext.Button Notice that, if we were to create a new Ext.Button object, it would accept a number of configuration
options, and this would include items such as text and disabled. These are defined in the preceding object literal definition.
To demonstrate the point, let’s quickly refactor the createHeader function to first define an Ext.Button class and then include the object in our definition of the Ext.Toolbar:
function createHeader() {
var backButton = new Ext.Button({ text: 'Back', ui: 'back', id: 'goback', disabled: true, handler: function(button, event) {
Ext.getCmp('mainPanel').setCard(0); } });
return new Ext.Toolbar({ dock: 'top', ui: 'light', defaults: {
iconMask: true },
CHAPTER 11: Mobile UI Frameworks Compared
layout: {
pack: 'justify'
}, items : [backButton, {
xtype: 'spacer' }, {
xtype: 'panel', html: '<h1>Moundz</h1>'
xtype: 'spacer'
}] }); } // createHeader
What we have done in this code is equivalent to the earlier code. Hopefully, this gives a bit of insight as to the different ways in which UI elements can be defined in Sencha Touch.
With the createHeader function complete, we now just need to implement the createFooter function to finish off the basic layout of our application.
function createFooter() { return new Ext.Toolbar({ dock: 'bottom', ui: 'light', layout: {
pack: 'justify'
}, items: [{
xtype: 'button', text: 'Previous', handler: function(button, evt) {
activateMarker(markers[markerIndex - 1]); } }, {
xtype: 'button', id: 'btnResource', text: 'Resource Title', handler: function(button, evt) {
mainPanel.setActiveItem(1); } }, {
xtype: 'button', text: 'Next', handler: function(button, evt) {
activateMarker(markers[markerIndex + 1]); }
}] }); } // createFooter
In this code, we create another Ext.Toolbar that is set to dock at the bottom of the screen. For the toolbar items, we specify three buttons, one each for moving forward and back, and another to take us to the resource details page.
CHAPTER 11: Mobile UI Frameworks Compared
Each of the buttons is assigned appropriate event handlers, the Next and Previous buttons activate the appropriate markers in the marker list, and the button that will display the resource title takes the user to the details screen when it is clicked.
All being well, a screen similar to the one in Figure 11–19 should be displayed.
Figure 11–19. The initial display of our UI in Sencha Touch actually displays a map—impressive. As you can see, we have an application laid out with a mapping control appropriately
sized to the screen. So, while we had to do some extra work to get the UI set up, the inclusion of the mapping control into Sencha Touch has made life easy here. We now need to move on to initializing the map with the appropriate location and get some markers displayed on the map.
To have the map display integrate with our existing Moundz application code, we need to make some modifications to the gotoPosition function.
function gotoPosition(position, zoomLevel) { // define the required options var myOptions = {
zoom: zoomLevel ? zoomLevel : DEFAULT_ZOOM, center: position, mapTypeControl: false, streetViewControl: false, mapTypeId: google.maps.MapTypeId.ROADMAP
/* // initialize the map map = new google.maps.Map(
document.getElementById("map_canvas"),
CHAPTER 11: Mobile UI Frameworks Compared
myOptions); */
// save a reference to the map control map = Ext.getCmp('main_map').map;
// set the options of the map map.setOptions(myOptions);
} // gotoPosition In the preceding code, we do three things:
1. We comment out the previous code that created a Google map control for us; this is no longer required, since Sencha Touch has created one for us.
2. We get a reference to the map that Sencha Touch has created, and we save that to the map variable that is part of the MOUNDZ module. As we use this variable in other function calls, our existing functionality should just work.
3. We update the options of the map to match the options we would have provided if we had created the map ourselves.
Once this is done, you should get a display similar to the one shown in Figure 11–20.
Figure 11–20. Our Sencha Touch version of Moundz now displays markers. We now just need to make some changes to functions within the MOUNDZ module to
synchronize our application state with the UI controls. We will start with the activateMarker function:
MOUNDZ = (function() {
CHAPTER 11: Mobile UI Frameworks Compared
// initialize constants var DEFAULT_ZOOM = 8,
GEOMINER_MOUNDZ_URL = 'http://api.geominer.net/v1/moundz';
// initialize variables var geominer = null,
... markerIndex = 0, posWatchId = 0;
/* private functions */
function activateMarker(marker) { // iterate through the markers and set to the inactive image for (var ii = 0; ii < markers.length; ii++) {
markers[ii].setIcon('img/pin-inactive.png'); } // for
// update the specified marker's icon to the active image marker.setIcon('img/pin-active.png');
Ext.getCmp('btnResource').setText(marker.getTitle()); Ext.getCmp('details_panel').update(markerContent[marker.getTitle()]);
// update the marker navigation controls markerIndex = getMarkerIndex(marker);
} // activateMarker
Interestingly, the activateMarker function has actually been simplified using Sencha Touch here. We simply set the text of the middle button using the setText method of the button, and call the update method of the details_panel to supply the appropriate content to the details page.
Additionally, we assign the current marker index to the new module variable markerIndex, which will allow the buttons that we defined in the createFooter function to switch between the various resource locations.
Once this is done, we can navigate through the markers using the navigation buttons, and display the details for a resource by clicking the resource information button in the footer.
There we have it—a Sencha Touch version of our Moundz application, as shown in Figure 11–21.
CHAPTER 11: Mobile UI Frameworks Compared
Figure 11–21. The final Sencha Touch version of our Moundz application