Author: Jamie
Do not believe in anything simply because you have heard it.
Do not believe in anything simply because it is spoken and rumoured by many.
Do not believe in anything simply because it is found written in your religious books.
Do not believe in anything merely on the authority of your teachers and elders.
Do not believe in traditions because they have been handed down for many generations.
But after observation and analysis, when you find that anything agrees with reason and is conducive to the good and benefit of one and all, then accept it and live up to it.
Gautama Buddha
Tutorial 4: Sencha Weather App – OpenWeatherMap Api + Model + Store
Register on OpenWeatherMap
OpenWeatherMap provides a handy api for guess what? That’s right weather reports. Follow the steps to register and get a URL endpoint.
- Register at: http://openweathermap.org/API
- Click Free API
- Click ‘more’ under ‘Get Current Weather Data’
This is the default example:
api.openweathermap.org/data/2.5/weather?q=London,uk
We have some options to format the data coming back:
api.openweathermap.org/data/2.5/weather?units=metric&q=Dublin, IE
See the JSON response with Dublin related weather reports. This will do for the moment.
Next add the weather API to our Sencha app.
In keeping with best practice we will add this configuration to the app.js in our app root. Seems like a good place of it.
In time I will want to make the location configurable so I’ve broken into two variables. Plus a variable for the location of the images the openweathermap kindly provide.
/* configuration openweathermap API */ weatherAPI: 'http://api.openweathermap.org/data/2.5/weather?units=metric&q=', defaultCountry: 'Dublin,ie', openweatherimages: 'http://openweathermap.org/img/w/',
Model
The model will describe the shape of the data. We’ll shape the data we get back from the above URL.
1) Create the model file app/model/Weather.js
The names on the field array are taken form the JSON response.
Ext.define('WeatherApp.model.Weather', { extend: 'Ext.data.Model', config: { fields: ['name', 'main', 'country', 'sys', 'weather'] } });
API JSON response:
{"coord":{"lon":-6.26719,"lat":53.34399},"sys":{"country":"IE","sunrise":1372132698,"sunset":1372193845},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}],"base":"global stations","main":{"temp":18.4,"humidity":58,"pressure":1028,"temp_min":18,"temp_max":18.89},"wind":{"speed":4.63,"gust":4.63,"deg":247},"clouds":{"all":80},"dt":1372179878,"id":2964574,"name":"Dublin","cod":200}
Our model object will have attributes name, main, country, sys, weather. We can pull the data from the object via these attributes.
But we need to get the data in to the model in the first place. Enter stores.
Oh yes, we’ll need to add our model to our app.js, as we previously did with views.
A store for Weather
In the previous tutorial we hooked up a view to the Weather store. But we didn’t create the store. We’ll do that now:
app/store/Weather.js
Ext.define('WeatherApp.store.Weather', { extend: 'Ext.data.Store', config: { model: 'WeatherApp.model.Weather', //autoLoad: true, proxy: { type: 'jsonp', url : WeatherApp.app.weatherAPI + WeatherApp.app.defaultCountry, reader: { type: 'json' } } } });
THE NEXT STEPs FOR US:
- A new tab panel for location
- An input field to allow the user to enter a location.
- Model and store to save the location to local storage.
- A controller to manage the interactions between the view and the store.
CODE HERE:
https://github.com/jamiegood/WeatherApp/tree/InputWeatherLocation
Sencha Touch BDD series from Pivotal Labs
A great series of blog posts on Behavior Driven Development(BDD) with Sencha Touch. Covers BDD with Jasmine Javascript tests to test Sencha Touch models, stores and controllers. Covers mocking and also running tests via phantom.js.
- http://pivotallabs.com/sencha-touch-bdd-part-1/
- http://pivotallabs.com/sencha-touch-bdd-part-2/
- http://pivotallabs.com/sencha-touch-bdd-part-3/
- http://pivotallabs.com/sencha-touch-bdd-part-4-phantomjs/
- http://pivotallabs.com/sencha-touch-bdd-part-5-controller-testing/
Thanks pivotal labs
Goodbye Google Reader, Hello Feedly
On the 1st of July Google Reader will shut it’s doors. No more Google Reader.
Feedly.com has emerged as it’s successor claiming 3 million new users in the 2 weeks after the closure announcement.
Visitors to Feedly.com can transfer their Google Reader RSS feeds to Feedly simply by signing in. A painless process.
Feedly makes the bold claim of seamless transfer once Google Reader is unplugged.
Feedly.com comes in several flavours:
- Desktop
- iOS app
- Android app
- plus several other mobile platforms
The mobile user experience is where Feedly shines in comparison to Google Reader offerings.
So if you are looking for a safe place for your Google Reader feeds, try feedly.com
Tutorial 3: Sencha Weather App – add 2 tab panels with List component, itemTpl
- In tutorial 1 we created the sample Sencha Touch App
- In tutorial 2 we edited the sample app to contain 2 tab panels.
In this tutorial 3 we will finish the 2 tab panels.
- List component
- Attached to the store
- itemTpl
List Component
A list of items, with touch swipe of scrolling.
Store
A sencha touch store is the data source of you objects. These could be stored in HTML5 Local storage, memory or proxied to web servies.
The list component allows us to easily attached a store to a list. This allows us to populate the list items for a data source. This is all sorts of powerful.
itemTpl
We want to style each list of our List Component with our own HTML template. This is there the itemTPL comes in. As you can guess it’s the item template for the list component.
Ext.define('WeatherApp.view.Weather', { extend:'Ext.List', xtype:'weather', /* Configure the tab here */ config:{ title:'Weather', //title on the tab button iconCls:'locate', //icon on the tab button disableSelection: true, /* attach this list component to the weather store */ store:'Weather', /* create a title bar for the tab panel */ items: [ { docked: 'top', xtype:'toolbar', title:'Weather', id: 'mainToolbar', cls: '', items: [ { xtype: 'spacer' }, { xtype: 'button', cls: 'refreshWeather', iconCls: 'refresh', id: 'refreshWeather' } ] } ], /* markup for the data returned from the store */ itemTpl:Ext.create('Ext.XTemplate', '</pre> <div>', ' <h2>{name}, {[values.sys.country]}</h2> ', ' Time: {[this.timeFormat(new Date())]} ', ' Weather: {[values.weather[0].description]} ', '<img alt="" src="' + WeatherApp.app.openweatherimages + '{[values.weather[0].icon]}" />', ' Temperature: {[values.main.temp]} ℃ ', ' Humidity: {[values.main.humidity]} % ', ' Min Temp: {[values.main.temp_min]} ℃ ', ' Max Temp: {[values.main.temp_max]} ℃ ', '</div> <pre>', { timeFormat:function (date) { var days = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']; var newDate = date; return days[newDate.getDay() - 1] + " " + newDate.getHours() + ":" + newDate.getMinutes() + ":" + newDate.getSeconds(); } } ) }, initialize:function () { this.callParent(); } });
Points of interest:
The Weather Store that supplies the List Component.
The placeholders in the itemTpl I.E. {name)
The next step for us:
- We need to get the Weather Data from somewhere. We’ll sign up for the free Open Weather Map API
- Create the Model to describe the data return the from Open Weather Map API
- Create the Store to hold the above modelled objects.
Stay tuned for Tutorial 4.
CODE HERE:
You can clone to the branch and browse to the app to see the two tabs in action.
Tutorial 2: Sencha Weather App – add 2 tab panels
In the first tutorial we created a simple Sencha Touch application using the Sencha CMS tools.This gave us a sample working application to explore. Now we will update this, removing what is not necessary all the while keeping with the MVC pattern.
Plan:
- Create 2 tab panels
- One which is eveualtyy show the weather report.
- The second for a ‘settings’ type page.
1. Create the Main view to hold the tab panels
/* This file is generated and updated by Sencha Cmd. You can edit this file as needed for your application, but these edits will have to be merged by Sencha Cmd when it performs code generation tasks such as generating new models, controllers or views and when running "sencha app upgrade". Ideally changes to this file would be limited and most work would be done in other places (such as Controllers). If Sencha Cmd cannot merge your changes and its generated code, it will produce a "merge conflict" that you will need to resolve manually. */ // DO NOT DELETE - this directive is required for Sencha Cmd packages to work. //@require @packageOverrides // Ext.Loader.setPath({ 'Ext': 'touch/src', 'WeatherApp': 'app' }); // Ext.application({ name: 'WeatherApp', requires: [ 'Ext.MessageBox' ], views: [ 'Main', 'About', 'Weather' ], icon: { '57': 'resources/icons/Icon.png', '72': 'resources/icons/Icon~ipad.png', '114': 'resources/icons/Icon@2x.png', '144': 'resources/icons/Icon~ipad@2x.png' }, isIconPrecomposed: true, startupImage: { '320x460': 'resources/startup/320x460.jpg', '640x920': 'resources/startup/640x920.png', '768x1004': 'resources/startup/768x1004.png', '748x1024': 'resources/startup/748x1024.png', '1536x2008': 'resources/startup/1536x2008.png', '1496x2048': 'resources/startup/1496x2048.png' }, launch: function() { // Destroy the #appLoadingIndicator element Ext.fly('appLoadingIndicator').destroy(); // Initialize the main view Ext.Viewport.add(Ext.create('WeatherApp.view.Main')); } });
See the highlighted lines above for the changes.
Create the main view file – app/view/Main.js
Ext.define('WeatherApp.view.Main', { extend:'Ext.tab.Panel', xtype:'main', config:{ tabBarPosition:'bottom', defaults:{ styleHtmlContent:true }, items:[ { xtype: 'weather' }, { xtype:'about' } ] } });
This view extends the Sencha Touch component, the Tab Panel. Take note of:
- xtype: this is a shortcut we will use to refer to this Main view. Note that we have already referenced the ‘main’ xtype in our app.js above.
- The config parameter: This is the configuration for the Panel Component – importantly not the individual panels.
A huge amount of configuration options exist. Refer the the Sencha Touch API and the Sencha Touch Examples that are downloaded with the Sencha Touch SDK. - Components often have required config parameters that must be set. The above are the minimum required for the Ext.tab.panel component.
Step 2: Create A view for the About Tab panel
See Items in the app/view/Main.js – theses will be an array of the tabs themselves. If I have 3 items there we would have 3 tab panels.
Our second tab item is referenced by an xtype ‘about’. Think of an xtype as a shortcut to the About view. We’ll start with that as it’s simpler than the Weather view 🙂
Firstly we have the views already added out our app.js. Lines 30 – 33 above. Good times.
We’ll need to create a view file – app/view/About.js
We’ll keep it simple for now and just have some text.
Ext.define('WeatherApp.view.About', { extend: 'Ext.Container', xtype: 'about', /* Configure the tab here */ config: { title: 'About', iconCls: 'settings', /* Create a title bar for the tab panel */ items: { docked: 'top', xtype: 'titlebar', title: 'About' } }, /*contents of tab */ html: 'The about page' });
Step 3: Create a View for the Weather Tab panel
Create a app/view/Weather.js view for the ‘Weather’ xtype referenced from your Main view.
Ext.define('WeatherApp.view.Weather', { extend:'Ext.List', xtype:'weather', /* Configure the tab here */ config:{ title:'Weather', //title on the tab button iconCls:'locate', //icon on the tab button disableSelection: true, /* attach this list component to the weather store */ store:'Weather', /* create a title bar for the tab panel */ /* items:{ docked:'top', xtype:'titlebar', title:'Weather' }, */ items: [ { docked: 'top', xtype:'toolbar', title:'Weather', id: 'mainToolbar', cls: '', items: [ { xtype: 'spacer' }, { xtype: 'button', cls: 'refreshWeather', iconCls: 'refresh', id: 'refreshWeather' } ] } ], /* markup for the data returned from the store */ itemTpl:Ext.create('Ext.XTemplate', '<div class="">', '<h2>{name}, {[values.sys.country]}</h2>', '<p>Time: {[this.timeFormat(new Date())]}</p>', '<p>Weather: {[values.weather[0].description]}</p>', '<img src="' + WeatherApp.app.openweatherimages + '{[values.weather[0].icon]}"/>', '<p>Temperature: {[values.main.temp]} ℃</p>', '<p>Humidity: {[values.main.humidity]} %</p>', '<p>Min Temp: {[values.main.temp_min]} ℃</p>', '<p>Max Temp: {[values.main.temp_max]} ℃</p>', '</div>', { timeFormat:function (date) { var days = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']; var newDate = date; return days[newDate.getDay() - 1] + " " + newDate.getHours() + ":" + newDate.getMinutes() + ":" + newDate.getSeconds(); } } ) }, initialize:function () { this.callParent(); } });
Suddenly it’s become a lot more complicated.
Points of interest that we spoken about already
Again this view extends a component, a new component called List. Can you imagine what that does?
- xtype is ‘Weather’. This component is included in the Main.js view via this xtype
- Config parameter for configuring this tab
- An Items parameter that has something to do with a toolbar at the top of the View
New stuff:
- A store called Weather
- The list component
- itemTpls
We’ll cover all this in the next tutorial.
Code here:
You can clone to the branch and browse to the app to see the two tabs in action.
Tutorial 1: Developing Weather Mobile Web App with Sencha Touch
Introduction:
The world needs yet another weather app. So let’s build it.
We’ll will use the Sencha Touch JavaScript framework to create the mobile web app. Over the course of several bite sized tutorials we will add need features and explore the framework.
- Tabbed views
- Weather information for the current date for a selected location
- An about page
- Possibly a weather map if we make it that far 🙂
For this tutorial we will re-create the simple getting started app.
And go from there.
Git repo
Prerequisites:
- You have a webserver installed locally
- Sencha CMD 3.1.1 installed
- Sencha Touch 2.2.0 downloaded
Getting Started App
We will use Sencha CMD tool to create the basic Getting Started App.
In your terminal go to the directory where you previously downloaded Sencha CMD
$ cd /Downloads/sencha-touch-2.2.0-commercial/touch-2.2.0/ $ sencha generate app WeatherApp /www/WeatherApp
where WeatherApp is a name to give your application and /www/WeatherApp is location where the Getting Started app will be placed.
Ok right now if you browse to your app location: along the lines of http://localhost/weatherap.
Hopefully if all went well then you’ll see the helpful Getting Started App.
Look over the generated app. It’s small but gives an overview of MVC with sencha touch.
And we’ll leave it there for the first tutorial.
In the next tutorial we’ll edit the getting started app and create the tab panels for the interface of our Weather App.
Code here:
https://github.com/jamiegood/WeatherApp/tree/GettingStartedApp
The Way of Testivus
If you write code, write tests.
Don’t get stuck on unit testing dogma.
Embrace unit testing karma.
Think of code and test as one.
The test is more important than the unit.
The best time to test is when the code is fresh.
Tests not run waste away.
An imperfect test today is better than a perfect test someday. An ugly test is better than no test.
Sometimes, the test justifies the means.
Only fools use no tools.
Good tests fail.