Hi, my name is Lee.
I'm a writer,
a developer and a technical trainer.
I create fixes and I fix headaches...
Welcome to my tech blog.

Category Archives: JavaScript

3Sep

Make a native build with Ext JS 5, Sencha Cmd 5 and Phonegap / Cordova with plugins.

With the release of Ext JS 5; we finally have Touch experience in the framework. So yes, you can start creating tablet applications.
Maybe you are now wondering, can I also package Ext JS 5 apps with Apache Cordova or Adobe Phonegap, so I can sell my app in the App Stores?
Well yes, you can!

Here are the steps I took; for porting my app with Cordova/Phonegap.
**note, instead of using the keyword phonegap, Cordova users may use the keyword cordova instead.
**note2: you will need to have the following dependencies installed: (Sencha Cmd, Node JS and Phonegap or Cordova)

There we go:

  1. Let’s generate a new Ext JS 5 app
    Browse with your terminal to your Ext JS 5 SDK folder.
    Run the following command:

    sencha generate app MyApp ../phonegapdemo

    Here we generate an Ext JS 5 demo app, in the phonegapdemo folder, which stands next to the downloaded extjs5 sdk folder.

  2. Open app.json
    Add the following code block:

        "builds": {
            "ios": { //build name
                "packager": "phonegap",
                "phonegap": {
                    "config": {
                        // Uncomment the line below and add the platform you wish to build for
                        "platform": "ios",
    
                        "remote": false,
                        "id": "com.domain.MyApp",
                        "name": "MyApp"
                    }
                }
            }
        },
    

    Here I’m adding a custom phonegap build for iOS. I used as a build name the keyword ios, a name i choose to recognize iOS builds, but incase you want to make for example Android builds, I could change it for android. In case of an Android I would also need to change the platform keyword.
    Note also the id property, which expects an id in reversed domain style; and name which should be the name of the Sencha App namespace.

    In case I want to build via the Phonegap cloud web service; I should set the property remote to true. Then, you will also need to create a local.properties file in the phonegapdemo folder; with the login details for build.phonegap.com:

    phonegap.remote.username=my@email.com
    phonegap.remote.password=mypassword
    
  3. Create a native build
    Back to your terminal, navigate to the phonegapdemo folder, and run the following command:

    sencha app build ios
    

    Note the keyword ios, that’s the build name which was set in app.json!

    Mac OSX users, might need to prefix with the word sudo.
    In case you are using Phonegap cloud webservice, it will now upload your app.
    In case of Phonegap local or Cordova, this command will now generate the following folderstructure like below.

    Instead of the command sencha app build, I could also use the command sencha app prepare; it would prepare the folderstructure as well.

    phonegapdemo
    – phonegap
    – – config.xml
    – – hooks
    – – platforms
    – – plugins
    – – www

    The www folder, will be the place, where a copy of your Sencha Ext JS 5 app will be located.
    The plugin folder will contain Device API plugins after installing those. (see the steps below, woot!)

  4. Enable the JS Phonegap/Cordova API
    Although you could build and run your application on a device by now; it might be handy when you enable the Phonegap/Cordova device API.
    For example, in case you need to install plugins, such as the inappbrowser plugin.

    Open in an editor phonegapdemo/index.html and add the following line, before the micoloader bootstrap.js script:

     <script type="text/javascript" src="cordova.js"></script>
    

    You might wonder, why I won’t add this cordova.js file to the js array in app.json.
    Not sure if I did it wrong, but I was running into sencha build errors because of that. Mind you, the cordova JavaScript
    file will be created while building the app; so it’s not available in the project root.

  5. Let’s build it (again)!
    sencha app build ios

    In case you are building with the PhoneGap cloud webservice, you can start scanning the QR code.
    Cordova or PhoneGap local users, can start opening the project file from the phonegapdemo/phonegap/platforms/<platform> folder,
    and build it via the developer toolkit.

Wait, let’s add another step, as a BONUS!
What about installing the inAppBrowser plugin, to make sure PhoneGap/Cordova will open your external hyperlinks in browser window within your app!
(That’s it’s what you want iOS user! Cause iOS ignores opening new browser windows. **grrrumbll!!!!**)
These steps are for PhoneGap Local / Cordova users:

  1. Edit config.xml
    You can find it here: phonegapdemo/phonegap/config.xml
    Now add the following line, (if not already available):

    <gap:plugin name="org.apache.cordova.inappbrowser"></gap:plugin>
    
  2. Install the plugin:
    Run from the command-line the following command, from the phonegapdemo/phonegap folder:

    phonegap plugin add org.apache.cordova.inappbrowser
    

    Again, Mac OSX users, you will need to have admin rights, so prefix with sudo.

    This command will add the plugin into the phonegapdemo/phonegap/plugins/ folder.

  3. How to open URLs
    Edit the demo app, and create a button, which will open an external URL in a separate browser.
    For example:

    phonegapdemo/app/view/main/Main.js

    Ext.define('MyApp.view.main.Main', {
        extend: 'Ext.panel.Panel',
        requires: [
            'MyApp.view.main.MainController',
            'MyApp.view.main.MainModel'
        ],
    
        xtype: 'app-main',
        
        controller: 'main',
        viewModel: {
            type: 'main'
        },
    
        padding: 20,
    
        layout: 'vbox',
        items: [{
            xtype: 'button',
            scale: 'large',
            text: 'Open Web Page',
            margin: 20,
            handler: 'openWebPage'
        }]
    });
    

    And note here, the magic: window.open().
    See below, the implementation in my viewcontroller:

    phonegapdemo/app/view/main/MainController.js

    Ext.define('MyApp.view.main.MainController', {
        extend: 'Ext.app.ViewController',
    
        requires: [
            'Ext.MessageBox'
        ],
    
        alias: 'controller.main',
    
        openWebPage : function(){
            var url = 'http://www.google.com';
            window.open(url, '_blank', 'location=no,EnableViewPortScale=yes'); 
        }
    });
    

    BAMMM!!! Build and Test your inAppBrowser, it should work!

Category: Cmd Cordova Ext JS ExtJS 5 Mobile Node JS Sencha
22May

Simple Techniques for Solving Common Sencha Coding Problems

Often when I’m teaching a Sencha Training class, students ask me to look at their apps because there’s a problem they don’t know how to fix. Since I didn’t write the code, it’s hard sometimes for me to give them a quick answer. However, I do have a set of simple techniques that filter out the most obvious problems.

In this tip, I’ll categorize a couple of most common problems and tackle them with some simple but effective strategies.

Problem: “I don’t see my data”

You are browsing through your app, but the data is not visible.
Often, this problem is easy to fix.

“Here, try this:”

First, try to inspect the Store. You can do this from the browser console by running:

Ext.getStore(‘MyStore’).load();

This returns the Store object. You can drill through the data config and see if the array length is greater than zero.

If there is data available, something probably went wrong with rendering. Consider these possible issues:

Do the data fields map the fields in the Model?

Is the data array empty? In your browser developer toolbar, hit the Network tab.
Do you get a status code 200? No? Then something went wrong with your request. Check your Model/Store proxy.

The request works correctly, but it still doesn’t display the data?
Verify whether the data you get back is valid. For example, when you are using JSON data, you can copy the data response from the browser network tab into http://jsonlint.com or http://jsonplint.com/. You can also use your own written test data too.

Problem: “I can’t build my app”

Sencha Cmd won’t build your app. Most of the time, Sencha Cmd gives a clear explanation of what’s going on, or what needs to be changed. However, every now and then, I see problems where Sencha Cmd won’t build. and the error description is not clear.
It might be that there is nothing wrong with your code. For example, your code runs perfectly on your local environment. It just won’t build.

“Here, try this:”

This trick is pretty radical, but most of the time it works.
Generate a new application with the same namespace from the command line:

sencha generate app App ../myapp

Next, copy over the app folder, and make sure you take the changes over from app.js.
Now try it again!

Problem: “Strange component-x behavior”

These types of problems are always the hardest ones.
For example, suddenly multiple scrollbars show up in your grid. Or, you see a tab panel with the wrong styling. Testing these kind of problems within your app can be time consuming. Not only do you have to navigate through your app to get to this problem, there can also be many reasons why it’s broken.

“Here, try this:”

A common problem-solving technique for developers is to isolate the problem into smaller, more manageable chunks.

Isolate the problem

Let’s generate a new application with Sencha Cmd, again with the same namespace.
Now, copy over the Class that contains the problems and test it.
Do you see the same bugs? You can try to solve it in this test app.
You can isolate it even further by trying to re-build your class from the ground up. Start with only the necessary code.

Did it work? There is nothing wrong with the framework, and there is nothing wrong with this Class. Something else must be wrong.

Switch to the default theme

Go back to your own app and try to switch to one of the Sencha default stylesheets. (Sencha Default StyleSheet in Sencha Touch, Neptune Theme in Ext JS)
Does it finally work? Then there is something wrong in your custom StyleSheet.
Is it still not working? At least now you know that your custom StyleSheet is correct. There might be something wrong with your nesting. Or maybe you used the wrong layout?

Query for Components

Do you have problems with querying for Components? You can easily query components from your browsers dev console:

Ext.ComponentQuery.query('button[action=”test”]');

Does it return an empty array? Then there you go! Or maybe it does return the components, but you made a timing mistake. That can often be the case when you’re working with callbacks. When your code is executed, the component may not be rendered on the screen.

Common Debugging Techniques

As a developer, you will often run into bugs and problems that you have to solve.
But hey, that’s what makes our jobs challenging, right?

Aside from the above mentioned techniques, there are also a couple of standard tricks. First of all, know the framework and know your tools. Read the API Docs (or even better, browse through the framework code).

Switch to one of the debugging frameworks. The advantage is that it often shows extra log messages, and you can directly read through the framework code.
For Sencha Touch projects, open app.json and change the framework temporarily:

"js": [
{
"path": "../touch/sencha-touch-all-debug.js",
"x-bootstrap": true
},

For Ext JS projects, open index.html and change the framework temporarily:


Your browser dev tools can help (Google Chrome or Firebug). Also, there are some handy plugins for developing Sencha code: Illuminations and App Inspector for Sencha.

Do you quickly want to prototype something? Try Sencha Fiddle.
There are great tools for testing available, such as Siesta.

And last but not least, if none of these techniques help you and you are staring at your code for hours (or even days)… take a break! Often, when you take a break and free your mind, you can solve it right away. Especially if you’ve made spelling mistakes or (case sensitive) typos that can cause hours of frustration because you just don’t see them.

Looking for more help? Check out one of the Sencha Ext JS and Sencha Touch training classes located around the world, or join an online class.

Category: Ext JS JavaScript Sencha Sencha Components Sencha Touch TDD
21Apr

Getting Started with Sencha Touch 2: Build a Weather Utility App (Part 3)

In this three-part Sencha Touch tutorial, you will build the Do I need my Umbrella? app, a simple utility app that loads weather information from a web service — worldweatheronline.com. Based on weather codes, this app can predict if you need your umbrella or not.

In this last part of the tutorial, we’ll talk about builds. You’ll use Sencha Cmd as well as PhoneGap/Cordova.

For the native app, you’ll use a native API for retrieving the location of the device, and you’ll port your app to a native mobile app with PhoneGap/Cordova for iOS, Android, BlackBerry10 or Windows Phone.

Note: If you want to test your app on an iOS, BlackBerry or Windows Phone device, you will need authorization keys and developer accounts. Also, if you use Cordova, you can’t build an iOS app in the Windows operating system, nor can you build a Windows app from within Mac OS X.

For reference, you can view Part 2 of this tutorial.

You can download the solution code from Part 2 of the tutorial — full solution.

This tutorial requires:

Optionally, you can install the following software to build apps locally:

  • XCode 5 (for building iOS app locally, for Mac OS X users only)
  • Android Developer Tools (Revisions 13+, for building Android apps locally)
  • Windows 8 Pro with Visual Studio 2012 Pro/Ultimate (for building Windows Phone apps locally, for windows users only)
  • Blackberry 10 Native SDK (for building BlackBerry 10 apps locally)

Creating a production build

With Sencha Cmd, you can create production and test build packages. The production build package compiles the Sass style sheet to production-ready (minified) CSS. It will also copy over your static images and build your JavaScript (Sencha Touch framework classes plus your own custom classes) into a single minified, concatenated file that’s small enough to easily download or cache the file. The production build will also include a cache manifest file to enable local caching.

The test package won’t contain this file. In the test build, the JavaScript and CSS files in the test package won’t be minified and therefore will be readable.

Weather App Tutorial

Let’s first create a production build of the Weather application. We’re not going to create a native build yet. In case you want to host the Weather App on your own server, you need to copy the production build folder over to your web server.

On the command-line enter the following command to generate a production build:

sencha app build production

or

sencha app build testing

Review the folder structure. This is the folder structure you can use on your web server, in case you decide to run the mobile application from an online URL.

Weather App Tutorial

Perhaps you noticed that the fonts are not copied into the build folder. We could copy this folder manually, or we could modify the build process. Let’s look into these options.

Sencha Cmd uses Apache Ant for the build processes. You can find all the internally used tasks in the hidden .sencha folder.

If you want to modify the build process yourself, you can open the build.xml file in the root of your application folder and add the following Ant task to the end of the file:

<target name="-after-build">
    <target name="build"
            depends="init,-before-build,-build,-after-build"
            description="Copy over the font/dinmu folder and remove temp files"></target>
 
    <copy todir="${basedir}/resources/css/stylesheets/fonts/dinmu" overwrite="true">
      <fileset dir="${basedir}/resources/sass/stylesheets/fonts/dinmu">
        <include name="**/*">
      </fileset>
    </copy>
    <copy todir="${build.dir}/resources/css/stylesheets/fonts/dinmu" overwrite="true">
      <fileset dir="${basedir}/resources/sass/stylesheets/fonts/dinmu">
        <include name="**/*">
      </fileset>
    </copy>
    <delete dir="${basedir}/${build.dir}">

Now build your application again:

sencha app build

You can test the production build with the following url: http://localhost/dinmu/production/Dinmu/

Native Device APIs

Do you want to run your application as a native app on your device? With tools such as Adobe PhoneGap and Apache Cordova, you can port your app to a hybrid app.

Once you have a hybrid app, you can use device APIs, such as geolocation. The geolocation object provides access to location data based on the device’s GPS sensor or inferred from network signals.

Open the following file with your editor: app/utils/Functions.js and inspect line 101:

Ext.device.Geolocation.getCurrentPosition({
   timeout: 5000,
   maximumAge: 10000,
   success: function(position) {
      var place = position.coords.latitude + "," + position.coords.longitude;
      Dinmu.utils.Functions.getWeather(place);
      Ext.Viewport.unmask();
   },
   failure: function() {
      Ext.Viewport.unmask();
      Ext.Msg.alert('Timeout', 'Can not retrieve position, please retry.');
   }
});

The Sencha Touch class: Ext.device.Geolocation() provides access to the native Geolocation API when running on a device. There are three implementations of this API:

This class will automatically select the correct implementation for the device your application is running on.

Before we will build the Do I need my umbrella (Dinmu) application, there are two more checks.

  • Prefix the request to api.worldweatheronline.com with the http protocol. You can find this request in app/utils/Functions.js on line 125.
  • Make sure you entered a valid API Key for the worldweatheronline.com web service. You can retrieve an API Key by registering at http://www.worldweatheronline.com

All set? That’s great. The only thing that’s left is building a native app with PhoneGap/Cordova.

Weather App Tutorial

Building a hybrid app

There are three products you can use to create a native app from a Sencha Touch code base:
Sencha Mobile Packager, Adobe PhoneGap, and Apache Cordova. All products are supported by the Sencha Device API which allows you to access hardware resources on devices.

Let me explain the differences between these three solutions:

Sencha Mobile Packager

Uses the packager.json to build iOS or Android build packages locally that can be distributed through the Android Marketplace or Apple App Store.

Adobe PhoneGap

Lets you use the PhoneGap Build cloud service to (remotely) package your apps and distribute them through the Android Marketplace, BlackBerry App World, Windows Phone Store or Apple App Store. It’s an easy solution, and you can test applications on your device by scanning a QR code. You can also build applications locally. It’s a commercial product, and the free version is limited to one private app.

Apache Cordova

Apache Cordova is a top-level project within the Apache Software Foundation. Cordova is the free, open-source, community-driven version of Adobe PhoneGap. Cordova lets you package apps locally and distribute them through the Android Marketplace, Blackberry App World, Windows Phone Store or Apple App Store.

Building packages locally via the command-line requires an installation of XCode, Android Developer Tools, BlackBerry 10 SDK or Windows 8 Pro with Visual Studio.

Building packages via PhoneGap build requires a (free) Adobe (PhoneGap Build) account: https://build.phonegap.com/apps

Note: We will use PhoneGap Build in this tutorial. If you would rather use Cordova, you can use the same commands as you see in the tutorial, but replace the word phonegap with cordova on the command-line.

Weather App Tutorial

Initialize a PhoneGap project

The first step in building a hybrid app is to issue the following command from your project’s directory to enable it:

sencha phonegap init <APP-ID> <APP-NAME>
  • The App ID follows this pattern: <REVERSED-DOMAIN>.<APP-NAME>.
  • Your application name should be the same value as the name property that you specified in your app.json file.

Note: If you want to port to an iOS app, you will need to make sure that the App Id is the same one that you registered in your Apple provisioning portal.

Here’s the command I used to enable PhoneGap support:

sencha phonegap init com.sencha.dinmu Dinmu

Note: Mac OS X users might need to prefix with sudo to get administrative rights.

This generated the following structure/files:

  • PhoneGap folder structure
  • phonegap.local.properties
  • config.xml

MyApp/phonegap

MyApp/phonegap contains the full PhoneGap file structure. If you used Cordova to initialize a project, the folder will be named cordova.

Weather App Tutorial

phonegap.local.properties

The phonegap.local.properties file contains the names of the platforms that you want when building locally. By default, it takes the local installed SDKs, for example:

phonegap.platforms=ios android blackberry10 wp8

When you run the phonegap init command, the property file also gives you settings for the Adobe PhoneGap remote packager. When you have a PhoneGap Build account, you can set up these additional settings:

phonegap.build.remote=true
# Username for PhoneGap Build
phonegap.build.remote.username={username}
# Password for PhoneGap Build
phonegap.build.remote.password={password}

When you leave the phonegap.build.remote property as false, you have to have one of the SDKs (XCode, Android Developer Tools, BlackBerry 10 SDK or Windows 8 Pro with Visual Studio) installed on your machine.

config.xml

The default Cordova/PhoneGap config.xml file contains metadata about your app. Let’s modify this file:

We will change the app name, app description and author information:

<name>Dinmu</name>
<description>
    Do I need my Umbrella today?
</description>
<author email="myemail@addres.com" href="http://www.mydomain.com">
    Your name
</author>

The next step is to enable the Geolocation plugin at startup, to retrieve the location via the device:

<preference name="EnableLocation" value="true"></preference>

Disable fullscreen mode, to show the status bar (battery indicator and time):

<preference name="fullscreen" value="false"></preference>

Let’s make sure the application supports connections to external urls. The weather application will connect to http://www.worldweatheronline.com. Therefore, we need to give access to either this URL or all external URLs. We can use the wildcard to allow all external connections:

<access origin="*"></access>

The last thing we’ll modify are the paths to the icons and loading images. By default Sencha Touch generated iOS icons and splash images. They can be found in the MyApp/resources folder.

When building apps for iPhones with retina displays (iPhone 5+), it’s important that you provide the correct splash screens with the required screen sizes. If not, your viewport may be resized incorrectly. For this example, we’ll stick to the PhoneGap splash screens. Feel free to replace them with your own splash screens.

<icon src="icon.png"></icon>
<icon src="resources/icons/Icon.png"></icon>
<icon gap:platform="ios" height="57" src="resources/icons/Icon.png" width="57"></icon> 
<icon gap:platform="ios" height="72" src="resources/icons/Icon~ipad.png" width="72"></icon> 
<icon gap:platform="ios" height="114" src="resources/icons/Icon@2x.png" width="114"></icon> 
<icon gap:platform="ios" height="144" src="resources/icons/Icon~ipad@2x.png" width="144"></icon> 
 
<gap:splash gap:platform="ios" height="480" src="res/screen/ios/screen-iphone-portrait.png" width="320"></gap:splash>
<gap:splash gap:platform="ios" height="960" src="res/screen/ios/screen-iphone-portrait-2x.png" width="640"></gap:splash>
<gap:splash gap:platform="ios" height="1024" src="res/screen/ios/screen-ipad-portrait.png" width="768"></gap:splash>
<gap:splash gap:platform="ios" height="768" src="res/screen/ios/screen-ipad-landscape.png" width="1024"></gap:splash>

For more information about possible settings in config.xml, check the PhoneGap documentation.

Creating the native build package

After initializing your application with PhoneGap or Cordova, it’s time to create a native build.
Run the following command from the command-line:

sencha app build -run native

Note: The -run argument makes sure your app will be loaded in an emulator that’s installed on your machine. Again, Mac OS X users might need to prefix with sudo to get administrative rights.

It will build the applications in the MyApp/cordova or MyApp/phonegap folder:

  • platforms/android/bin – Android .apk file
  • platforms/ios/build/ – iOS .app file
  • platforms/blackberry10/build/simulator – BlackBerry 10 .bar file
  • platforms/wp8/Bin/Debug – Windows Phone .xap file

Testing a native build

If you’re using PhoneGap Build, testing the application on Android devices will be very easy. Simply scan the QR code or download, drag and drop the .apk file on the memory card of your phone.

For iOS, you will need provisioning and code signing, which assures users that the app is from a known source and the app hasn’t been modified since it was last signed. Windows Phone developers and iOS developers will need a (paid) developer account.

Once you have an iOS developer account, you’ll need to set up a certificate, an identifier and a provisioning profile. For more information, see the Apple Developer Tools and Sencha Touch docs on Packaging Native iOS Applications.

When all is set, you can build the application with PhoneGap from the command-line interface:

sencha app build native

When you build for iOS, you might run into a build error because you need to code sign the iOS app. With PhoneGap Build, you’ll need to upload the *.p12 certificate and the *.mobileprovisioning mobile provisioning profile. After you’ve uploaded these two keys, you can unlock the keys and rebuild.

If you’re building the app locally, (PhoneGap remote=false or with Cordova), you can open: platforms/ios/Dinmu.xcodeproj from the phonegap or cordova folder, and maintain the build settings to code sign the application. Your developer identity should be in the Code signing identity list. If not, you probably need to go through the whole native provisioning process again.

Weather App Tutorial

Make sure your phone is hooked up to your Mac OS X, and build and run in XCode.

Congratulations, you’ve finished building a Sencha Touch utility app from scratch. If you’ve followed all three tutorials in this series, you’ve generated an application with Sencha Cmd and created all the views, models, stores and controllers for the Do I need my Umbrella? app. You’ve created a custom theme with Sass, and you’ve created a production build to host on a web server or built a hybrid app wtih Adobe PhoneGap/Cordova. With this workflow, you’re ready to build any app you like.

Did you like this series of tutorials? Join one of the (advanced) Ext JS and Sencha Touch Training courses. Take a look at the open courses located around the world or join an online class or check out my book that I wrote for O’Reilly: Hands-on Sencha Touch 2 by Lee Boonstra

Category: JavaScript Mobile Sencha Sencha Touch
7Apr

Getting Started with Sencha Touch 2: Build a Weather Utility App (Part 1)

Welcome at this series of blog posts: How to create a utility app with Sencha Touch and Sencha Cmd. Originally I wrote this tutorial for .NET magazine and afterwards I modified it for the Sencha Blog Site. Since I think it’s a good set of articles and you might have missed it. I will also post the 3 parts of the tutorial here, every week. Enjoy!

In this three-part Sencha Touch tutorial, you will build the Do I need my Umbrella app, a simple utility app that loads weather information from a web service — worldweatheronline.com. Based on weather codes, this app can predict if you need your umbrella or not.

In this tutorial, you will start with coding the app. The next tutorials will focus on creating a cool Sencha Touch theme and how to port your app to a native app with PhoneGap.

This tutorial requires:

  • Sencha Touch 2.3 or higher
  • Sencha Cmd 4.x
  • A modern browser
  • Editor

Here are some additional resources:
You can see the app itself up and running here.
The final code can be downloaded here.
There are some tutorial goodies you will need — controller and functions.

Generate and run the demo application

Let’s start by creating a sencha folder somewhere on your hard disk. Download the Sencha Touch 2.3 framework and extract it into the newly created sencha folder. Now, create the folder for your app, I’ve called it dinmu since that is shorter than the name “DoINeedMyUmbrella” but it’s up to you.

Now, open your command line (MS-Dos Prompt or Mac OS X Terminal), navigate to the Sencha framework folder: (cd sencha/touch-2.3.x folder) and run the following command to generate your Sencha Touch MVC folder structure:

sencha generate app -name Dinmu -path ../dinmu

This command generates the full MVC structure for your application: Do I need my Umbrella. It takes the namespace Dinmu, to prefix all your classes. Review the folder structure it has created.

Now it’s time to start your web server via the command line — use the path to your sencha folder. (If you would rather use your own Apache web server, you are free to start it and skip this step.) On Mac OS X, you might need permissions for executing the next command: if you run into permission errors, prefix the above command with sudo.

sencha fs web -p 80 start -map /path/to/sencha/folder/

This will start your built-in Jetty web server. You need your CLI window open to keep the server running, so it makes sense to open a new CLI window for the next commands.

Test your generated Sencha Touch app. Open your modern browser (such as Google Chrome or Safari) and run: http://localhost/dinmu. You should see the Sencha demo app interface with a bottom tab panel and two demo slides:

Weather App

The Data Package

In the next steps, you will generate the model which will define your data. There are a couple of settings you want to save in your app: id, city, country, units and geolocation. You will define these data settings as model fields. Sencha Cmd can scaffold this model for you. Run the following command from the dinmu folder on the command line:

sencha generate model Setting id,city,country,units,geo:boolean

This command generated the model for your application. It takes the classname Setting and one String with all the field names to define all the different fields. Let’s review your folder structure again.

Open app/model/Setting.js with your editor. Notice the namespace Dinmu.model.Setting is equal to app/model/Setting.js. This is your implementation of the Setting model; Sencha Cmd defined a Setting model class for you. It extends a model implementation from the Sencha Touch framework: Ext.data.Model and it contains all the fields and field types.

The field id, will define id’s for every model record in your application. To have it behave as a unique id, you will need to configure it. Before the fields array, configure an idProperty and an identifier.

idProperty: 'id',
identifier: 'uuid',

The logic for these unique IDs are in a Sencha class that we need to “import” into our app. We can use a requires for that, this requires the class Ext.data.identifier.Uuid.

requires: ['Ext.data.identifier.Uuid'],

The next step is to create some validations for our model. After the fields array, create a validations array. The array contains validation objects to validate whether the data for these fields is present:

validations: [{
    type: 'presence',
    field: 'city',
    message: "Please provide a city."
}, {
    type: 'presence',
    field: 'country',
    message: "Please provide a country."
}],

Since we want to save the local settings data to the device, the last step is to add a client proxy.

We will use localstorage. The localstorage proxy will make sure that all the data persists into the browser localstorage. Define the proxy object directly after the validations array:

proxy: {
    type: 'localstorage',
    id: 'weathersettings'
}

The View Components

The standard tabpanel interface that Sencha Cmd generates looks good, but it’s not what you need for a utility app. The Do I need my Umbrella app will need a carousel interface.

Open the code of app/view/Main.js in your IDE or text editor.

The current implementation of Dinmu.view.Main extends from the Sencha Touch Ext.tab.Panel class. It has a tabBarPosition property to add the tabs to the screen bottom.

We don’t need it, so remove tabBarPosition:bottom and change the extend to Ext.Carousel, to extend from the Sencha Touch Carousel class. From here, you can open your browser and run: http://localhost/dinmu. You should see the generated Sencha demo app. The tabpanel interface is replaced by a carousel interface. You can slide the views horizontally.

Let’s remove more default components. We won’t need the demo video, so let’s remove the Ext.Video from the requires array. We can also empty the items array, since we will replace it with two new items.

The first item object (container by default) has only the html property. This can be set to a placeholder text: Settings Form so you can code this later. The second item object has a property itemId: ‘mainview’ and a cls property (for styling) set to the value: textview. Also add a direction property, which will set the direction of the Carousel to ‘vertical’.

Ext.define('Dinmu.view.Main', {
    extend: 'Ext.Carousel',
    xtype: 'main',
    requires: [
        'Ext.TitleBar'
    ],
    config: {
        direction: 'vertical',
        items: [{
            html: 'Settings Form'
        },{
            itemId: 'mainview',
            cls: 'textview'
        }]
    }
});

Viewed in the browser, the app looks pretty basic. Let’s add a top titlebar and a bottom toolbar. Before the Settings Form object, create a new object. This object will get the xtype: ‘titlebar’ to add a new instance of Ext.TitleBar to the Viewport (the screen). Set a class name on the titlebar with the CSS class property: cls: ‘title’. Set a docked: ‘top’ property to stick this titlebar to the top of the screen. Set the title to: Do I need my Umbrella? with the title property:

{
    xtype: 'titlebar',
    cls: 'title',
    docked: 'top',
    title: 'Do I need my Umbrella?'
},

You will do the same for the bottom toolbar. This time the xtype is not titlebar but toolbar. The cls can be set to footer. Dock it to the bottom of the screen. Instead of the title property, the toolbar needs an html property. Set this to some copyright string. We will add an ui property which is set to light to create a lighter look and feel. Don’t forget to add Ext.Toolbar to the requires array in the top of the file, so the correct framework class will be loaded into the memory.

{
    xtype: 'toolbar',
    cls: 'footer',
    ui: 'light',
    docked: 'bottom',
    html: 'Powered by &copy; Sencha Touch'
},

The next step is to create some buttons in the top titlebar.

The titlebar should contain an items array, which contains two buttons. A back button, which will be displayed when you are on the settings screen, and a settings button which will be shown on the default screen. You don’t need to set the xtype to button, the default item of an Ext.TitleBar is a button. The back button, is by default hidden and it is left aligned in the titlebar. The settings button, shows an icon of a settings gear.

Confirm your code looks like this:

Ext.define('Dinmu.view.Main', {
    extend: 'Ext.Carousel',
    xtype: 'main',
    requires: [
        'Ext.TitleBar',
        'Ext.Toolbar'
    ],
    config: {
        direction: 'vertical',
        items: [
        {
            xtype: 'titlebar',
            cls: 'title',
            docked: 'top',
            title: 'Do I need my Umbrella?',
            items: [{
               cls: 'back',
               hidden: true,
               ui: 'back',
               action: 'back',
               align: 'left',
               text: 'back'
            },
            {
               iconCls: 'settings',
               action: 'settings',
               ui: 'plain',
               align: 'right'
            }]
        },
        {
            html: 'Settings Form'
        },{
            itemId: 'mainview',
            cls: 'textview'
        },
        {
            xtype: 'toolbar',
            cls: 'footer',
            ui: 'light',
            docked: 'bottom',
            html: 'Powered by &copy; Sencha Touch'
        }]
    }
});

Open your browser and run: http://localhost/dinmu. You should see a button with a gear in the right corner of the Ext.TitleBar.

Forms

Now, we can start with creating a form. You know what? Let’s generate this too.
Navigate to the dinmu folder on the command line and run the following to generate your Sencha Touch form:

sencha generate form SettingsView geo:toggle,units:select,city,country

Review the form class that has been scaffolded. Open app/view/SettingsView. The Dinmu.view.SettingsView class has an xtype set to settingsview. You can assign custom made classes to item arrays with the xtype property.

So let’s do so. Open Dinmu.view.Main (app/view/Main.js), find the settings item in your code. By default, if you don’t specify its xtype is set to container. You will need to refer to the new xtype: settingsview, so add xtype: ‘settingsview’ to the Main view code. You don’t need the placeholder html string anymore. Remove the html: settings property. Also don’t forget to add Dinmu.view.SettingsView to the requires array to make sure this class is loaded in memory.

To make it look better, you will add a fieldset to the Ext.form.Panel in the SettingsView. This fieldset contains the four new fields and the submit button. The fieldset will be a child of the formpanel and has its own children: the form fields and the button.

Create a second items array in the config object (after the title property). Nest the second items array as a child. The parent items array contains one fieldset xtype, with a title: ‘Your location’, and a line with instructions.

Make sure the child items array contains all the fields and the button.
Verify your code looks like this:

 
Ext.define('Dinmu.view.SettingsView', {
    extend: 'Ext.form.Panel',
    xtype: 'settingsview',
 
    config: {
        items:[{
            xtype: 'fieldset',
            title: 'SettingsView',
            instructions: 'In case you do not want the app to detect your location you can enter the city and country.',
            items: [
                {
                    name: 'geo',
                    xtype: 'togglefield',
                    label: 'Geo'
                },
                {
                    name: 'units',
                    xtype: 'selectfield',
                    label: 'Units'
                },
                {
                    name: 'city',
                    xtype: 'textfield',
                    label: 'City'
                },
                {
                    name: 'country',
                    xtype: 'textfield',
                    label: 'Country'
                },
                {
                    xtype: 'button',
                    text: 'Submit',
                    ui: 'confirm'
                }
            ]        
        }]
    }
});

Open your browser and run: http://localhost/dinmu. You should see the settings form with a title and some instructions. But there is something odd with the select unit field. It has no values.

Let’s add some values to the units selectfield.

Create an options array with two objects. One with the text: ‘Fahrenheit’ and a value: ‘f’ and one object with the text: ‘Celsius’ and the value: ‘c’.

The label GEO in the togglefield makes little sense. Change this label to: ‘ Auto detect?’ Since the text for this label takes much more space, we will set the labelWidth to ‘55%’. Set the value of the geo field to value: ‘1’ to enable geolocation by default.

Disable the units, city and country fields by adding disabled: true to all fields.

The button text, should be Refresh instead of Submit. Change this in the button component. Add a margin with the value ‘10 5’. Also add an action property to the button and set this to ‘refresh’. This way, we can reference the button later:

{
    xtype: 'button',
    text: 'Refresh',
    action: 'refresh',
    margin: '10 5'
    ui: 'confirm'
}

You might have noticed that the console outputs some warnings. The Ext.Loader, the mechanism that loads all the Sencha Touch framework classes in the correct order into memory, needs to load the classes that are used for the form fields. Create a requires array, (above the config object) and assign it the following strings:

requires: [
    'Ext.form.FieldSet',
    'Ext.field.Toggle',
    'Ext.field.Select',
    'Ext.field.Text',
    'Ext.Button'
],

You’ve finished the interface.

Here’s the complete code for the settingsview:

Ext.define('Dinmu.view.SettingsView', {
    extend: 'Ext.form.Panel',
    xtype: 'settingsview',
    requires: [
        'Ext.form.FieldSet',
        'Ext.field.Toggle',
        'Ext.field.Select',
        'Ext.field.Text',
        'Ext.Button'
    ],
    config: {
        items:[{
            xtype: 'fieldset',
            title: 'SettingsView',
            instructions: 'In case you do not want the app to detect your location you can enter the city and country.',
            items: [
                {
                    name: 'geo',
                    xtype: 'togglefield',
                    label: 'Auto Detect?',
                    labelWidth: '55%',
                    value: '1'
                },
                {
                    name: 'units',
                    xtype: 'selectfield',
                    options: [
                    {
                        text: 'Fahrenheit',
                        value: 'f'
                    },
                    {
                         text: 'Celsius',
                         value: 'c'
                    }],
                    label: 'Units',
            disabled: true
                },
                {
                    name: 'city',
                    xtype: 'textfield',
                    label: 'City',
                    disabled: true
                },
                {
                    name: 'country',
                    xtype: 'textfield',
                    label: 'Country',
                    disabled: true
                },
                {
                    xtype: 'button',
                    text: 'Refresh',
                    action: 'refresh',
                    margin: '10 5',
                    ui: 'confirm'
                }
            ]        
        }]
    }
});

But wait, what about the main view? Yes, you will dynamically inject this page with data. Therefore, you will need some logic to achieve this, so let’s start with creating a controller.

Weather App

Building The Controller

The controller will be the glue between the settings model (the app data) and the settings view. It will contain references to all view components and dispatch its events. Navigate to the dinmu folder and run the following command from the command line:

sencha generate controller Main

This command generates the Main controller. Open app/controller/Main.js with your editor. You will see a controller with an empty references object (refs) and an empty control object.

Next, let’s create references to all the view components, main, settingsview, the titlebar settings and back buttons and to the settings form fields and refresh button. The selectors are a bit CSS-like. Your code could look like this:

refs: {
    mainView: 'main',
    settingsView: 'settingsview',
 
    btnSettings: 'main button[action=settings]',
    btnRefresh: 'settingsview button[action=refresh]',
    btnBack: 'main button[action=back]',
 
    toggleGeo: 'settingsview togglefield',
    fieldCity: 'settingsview textfield[name=city]',
    fieldCountry: 'settingsview textfield[name=country]',
    fieldUnits: 'settingsview selectfield'
},

Now that you have references to all the view components that should contain events, you can add the controls.

control: {
    'btnRefresh': {
        tap: 'onRefresh'
    },
    'btnSettings': {
        tap: 'onSettingsBtnTap'
    },
    'btnBack': {
        tap: 'onBackBtnTap'
    },
    'toggleGeo': {
        change: 'onToggle'
    },
    'mainView': {
        activeitemchange: 'onCarouselChange'
    }
}

Before browser testing the events, you must hook the controller to app.js which is the MVC’s entry point. Open app.js, create a controllers array, right below the requires array and pass in the string ‘Main’ mapping the Main controller to the app/controller/Main.js file.

controllers: [
    'Main'
],

Now, we will add some logic. Go back to Dinmu.controller.Main and add the functions in the goodies-tutorial directory. You can find them in controller.txt.

Replace the launch function with the functions provided.

Setting Up Stores and Singletons

Stores encapsulate a client side cache of model objects. Stores can have a Proxy too, and also provide functions for sorting, filtering, grouping and querying the model instances (records) contained within it.

Our app needs a store to save all the user settings.

Unfortunately, you can’t generate stores with Sencha Cmd. Instead, let’s create a new file in the app/store folder called: Settings.js. Define a new class: Dinmu.store.Settings. This class extends all methods and properties from the Ext.data.Store class. In the config object, create a property called: model. It should connect to the Setting model. Also, the settings store should load automatically:

Ext.define('Dinmu.store.Settings', {
    extend: 'Ext.data.Store',
    requires: ['Dinmu.model.Setting'],
        config: {
            model: 'Dinmu.model.Setting',
            autoLoad: true
    }
});

Open controller/Main.js, in the config object create a stores array and add the Dinmu.store.Settings store to it:

stores: 'Dinmu.store.Settings',

Sometimes, it’s better to separate your business logic outside the MVC folders.

In the app folder, create a new folder utils. Create the file Functions.js, and define a class called: Dinmu.utils.Functions. This class has a property: singleton set to true. Now your class is a singleton, you cannot create more than one instance of it, but you can run the singleton methods from everywhere in your code:

Ext.define('Dinmu.utils.Functions', {
    singleton: true,
    //singleton methods here
});

Add Dinmu.utils.Functions to the requires array of the app.js file.

Open the snippet: functions.txt from the goodies-tutorial folder and copy all the functions into the utils/Functions.js file.

This snippet contains the functions you will need for requesting weather data from http://api.worldweatheronline.com/. If you would rather request and use your own API_KEY, you can edit it on top of the Functions.js by changing the String for property API_KEY. It also contains logic for requesting geolocation on the device and injecting data in the template on the mainview. If you are really interested in this logic, I left complete comments in the functions.txt file which describes exactly what is going on.

To test the logic, open Google Chrome Developer Tools and switch to the Console tab and enter the following line: Dinmu.utils.Functions.getWeather(‘London’) it should return a weather object for London and display some text in the mainview.

Finally the Do I need my Umbrella app is finished! Open your browser and run: http://localhost/dinmu. The next steps for improving your application would be to apply a theme and a production build. This is something I will discuss in the next Sencha Blog tutorial.

Weather App

If you found this tutorial helpful check out my book I wrote for O’Reilly:
Hands-on Sencha Touch 2!

Category: JavaScript Sencha Sencha Touch
17Dec

Upgrade Node JS from the CLI

First check your current version of Node JS:

$node -v
> v0.10.18

Clear your npm cache:

sudo npm cache clean -f

Install Node:

sudo npm install -g n

Upgrade to a later version (this step can take a while) You can specify a particular version like so:

sudo n 0.10.23

Or you can just tell the manager to install the latest stable version:

sudo n stable

Check the running version of Node to verify:

$node -v
> v0.10.23
Category: Node JS
11Nov

Always use semicolons in JavaScript

According to Javascript; the semicolon after a statement (for example a function), is optional.
However, it’s much better to end your line with a semicolon. A validator like JSLint for example, will throw a warning, even though
the browser won’t and accepts it.

See below, which strange things can happen when you won’t end your line with a semicolon.
Javascript errors because of the order of javascript functions mixed with jQuery plugins…
http://jsfiddle.net/bpsuW/11/

foo is a simple javascript function.
Baz is a simple self running jQuery plugin. (because of the parentheses surrounding it).

foo = function(){
alert("function 1"); 
}

(function(){
$.fn.Baz = function(opt){
alert("function 2");
}
})(jQuery)

See below the script, without strange javascript errors.
http://jsfiddle.net/bpsuW/10/

The answer is really logical.
Because there is no semicolon, the jQuery plugin (Baz) will directly execute, because of the parentheses.
Like it’s a parameter of the javascript function you wrote before. (foo), and then throws errors.
So:

foo(Baz)

When you mix your jQuery plugins with native javascript classes and functions in different orders; these kind of errors can happen.
This scenario above shows you why you should always end your statements with a semicolon.

Category: JavaScript
17Apr

Node Connect example

The example below can be easily replaced with Node Connect. Just with a few lines.
app.js

var http = require('http');
var path = require('path');
var fs = require('fs');
var extensions = { 
   ".html" : 'text/html', 
   ".css" : 'text/css', 
   ".js" : 'application/javascript',
   ".json" : 'application/javascript', 
   ".png" : 'images/png', 
   ".gif" : 'images/gif', 
   ".jpg" : 'images/jpeg' 
} 

http.createServer(function(req, res){ 
   var filename = path.basename(req.url) || 'index.html', 
      ext = path.extname(filename), 
      dir = path.dirname(req.url).substring(1), 
      localPath = __dirname + "/views/"; 

     //console.log(localPath); 
     if(extensions[ext]){
        localPath += (dir ? dir + "/" : "") + filename; 
        path.exists(localPath, function(exists){ 
           if(exists){ 
              getFile(localPath, extensions[ext], res) 
           } else { 
              res.writeHead(404); res.end();
           } 
        }); 
     }
}).listen(8000, '127.0.0.1'); 

getFile = function(localPath, mimeType, res){ 
   fs.readFile(localPath, function(err, contents){ 
   if(!err){ 
      res.writeHead(200, { 
         "Content-Type" : mimeType, 
         "Content-Length" : contents.length 
      }); 
      res.end(contents); 
   } else { 
      res.writeHead(500); 
      res.end(); 
   } 
});

Now install Connect:

$ sudo npm install connect

app.js

var connect = require("connect");
connect().use(connect.static(__dirname + "/views")).listen(8000);
Category: JavaScript Node JS
9Apr

Hello World with Node.js

See the example below for an easy Hello World example with Node.js. Create a Node.JS server and serve a hardcoded response, with content-type: “text/html”. And listen to localhost:8000 in your browser to see the result. In your project folder create an app.js file:

var http = require('http');
http.createServer(function(req, res){ 
   var html = BoilerplateHello World"; 
   res.writeHead(200, { 
      'Content-Type' : 'text/html', 'Content-Length' : html.length 
   }); 
   res.end(html);
}).listen(8000,'127.0.0.1');

With the above example you can’t create a real-life application. Let’s create an MVC folder structure in your project folder. By creating the following folders: “controller”, “model”, “views”. In the “views” directory, create here an index.html file. With the following content:

Then change your app.js file like the example below to retrieve the index.html file from the views folder:

var http = require('http');
var path = require('path');
var fs = require('fs');
http.createServer(function(req, res){ 
   var filename = path.basename(req.url) || 'index.html', 
   ext = path.extname(filename), 
   localPath = __dirname + "/views/"; 
   //console.log(localPath); 

   if(ext == ".html"){ 
      localPath += filename; 
      path.exists(localPath, function(exists){ 
         if(exists){ 
            getFile(localPath, res) 
         } else { 
            res.writeHead(404); 
            res.end(); 
         } 
       }); 
    }
}).listen(8000, '127.0.0.1'); 
getFile = function(localPath,res){ 
   fs.readFile(localPath, function(err, contents){ 
      if(!err){ 
         res.end(contents); 
      } else { 
         res.writeHead(500); 
         res.end(); 
      } 
});
Category: JavaScript Node JS
9Apr

Auto restart node after code changes

When you are sick and tired of restarting your node app in the terminal (CTRL+C) on every code change you make then you can automate this process. Actually it’s really simple. Install Nodemon via the package manager.

$ sudo npm install nodemon -p

When you want to check if it correctly installed and on which version you are running Nodemon:

$ nodemon -v
0.6.14

Is everything correctly set? You can start Nodemon, by typing the following command in the root of your current node project. For example:

$ nodemon app.js
9 Apr 20:15:23 - [nodemon] watching: /Users/lee/Projects/nodejs/www
9 Apr 20:15:23 - [nodemon] starting 'node app.js'
Category: JavaScript Node JS
2Apr

Installing Node and NPM on MAC OSX

Node.js is a platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

This assumes that Git is already installed and available on the command-line. Since the technology Node.js is quiet new, check at http://nodejs.org/ what the latest stable version of node.js is. For this example the latest version is v0.6.14. Open your terminal and start typing the following commands:

$ git clone git://github.com/joyent/node.git
$ cd node
$ git checkout v0.6.14
$ ./configure
$ make
$ sudo make install

Now Node.js is installed, you should also download the Node Package Manager. It’s no longer necessary to install npm separately, but if you want you can install this via the command-line as well. Use the following command:

$ curl http://npmjs.org/install.sh | sh

As an extra let’s also install MongoDB, is a large scalable high performance NoSQL database.

$ npm install mongojs
Category: Environment Node JS

Recent Posts

Recent Comments

Connect with me

Visit Us On TwitterVisit Us On FacebookVisit Us On LinkedinCheck Our Feed

Archives

Find me at: