the city bars app with sencha touch 2

85
The City Bars App with Sencha Touch 2

Upload: james-pearce

Post on 25-Apr-2015

14.104 views

Category:

Technology


1 download

DESCRIPTION

 

TRANSCRIPT

Page 1: The City Bars App with Sencha Touch 2

The City Bars Appwith

Sencha Touch 2

Page 2: The City Bars App with Sencha Touch 2

A JavaScript framework for building rich mobile apps with web standards

Sencha Touch

Page 3: The City Bars App with Sencha Touch 2

http://sencha.com/x/d5http://sencha.com/x/ed

Page 4: The City Bars App with Sencha Touch 2

Basically...

Get a WebKit-based desktop browser

Get some emulators & real devices

Download the Sencha Touch 2 PR2 SDK

Develop against a local web server

Optional, but highly recommended!

Page 5: The City Bars App with Sencha Touch 2
Page 6: The City Bars App with Sencha Touch 2
Page 7: The City Bars App with Sencha Touch 2

http://sencha.com/touch

Page 8: The City Bars App with Sencha Touch 2

stylesheet

script framework

Page 9: The City Bars App with Sencha Touch 2

Introducing theCity Bars App

Page 10: The City Bars App with Sencha Touch 2
Page 11: The City Bars App with Sencha Touch 2
Page 12: The City Bars App with Sencha Touch 2

http://senchalearn.github.com/citybars2

http://sencha.com/x/ee

Page 13: The City Bars App with Sencha Touch 2

Pre-requisites

 Yelp developer API key:  http://www.yelp.com/developers/

 Install Sass and Compass:  http://sass-lang.com/download.html

http://compass-style.org/install/

Page 14: The City Bars App with Sencha Touch 2

http://github.com/senchalearn/citybars2

Page 15: The City Bars App with Sencha Touch 2

Development sequence

1 App Architecture

2 UI Structure

3 Data Modeling

4 List Binding

5 List Event Handler

6 Detail Page

7 Customize Theme

Page 16: The City Bars App with Sencha Touch 2
Page 17: The City Bars App with Sencha Touch 2

Application Architecture

1_app_architecture

Page 18: The City Bars App with Sencha Touch 2

application

JS + CSS in SDK

entry point

Page 19: The City Bars App with Sencha Touch 2

<!doctype  html><html>        <head>

               <title>City  Guide</title>

               <script  src="lib/touch2/sencha-­‐touch-­‐all-­‐debug.js"></script>                <link  href="lib/touch2/resources/css/sencha-­‐touch.css"                              rel="stylesheet"  />

               <script  src="app/app.js"></script>

       </head>        <body></body></html>

index.html

our app

don’t panic

JS + CSS*

*or from CDN

yay! HTML5

Page 20: The City Bars App with Sencha Touch 2

var  CB;Ext.application({

       launch:  function()  {                CB  =  this;                CB.cards  =  Ext.create('Ext.Panel',  {                        fullscreen:  true,                        html:  'Hello  world'                });        }

});config object

global namespace

instantiates application

create main UI panel

launch event

app.js

Page 21: The City Bars App with Sencha Touch 2
Page 22: The City Bars App with Sencha Touch 2
Page 23: The City Bars App with Sencha Touch 2

UI Structure

2_ui_structure

Page 24: The City Bars App with Sencha Touch 2

CB.cards

listCard detailCard

toolbar toolbar

dataList

click

back

Page 25: The City Bars App with Sencha Touch 2

var  CB;Ext.application({

       launch:  function()  {                CB  =  this;                CB.cards  =  Ext.create('Ext.Panel',  {                        fullscreen:  true,                        layout:  'card',                        items:  [{                                id:  'listCard',                                html:  'List'                        },  {                                id:  'detailCard',                                html:  'Detail'                        }]                });        }

});

id-based ref

UI children

variable ref

how children lay out

Page 26: The City Bars App with Sencha Touch 2
Page 27: The City Bars App with Sencha Touch 2

<aside>about layouts

and components

Page 28: The City Bars App with Sencha Touch 2

Layoutscard

fit hbox

vbox

Page 29: The City Bars App with Sencha Touch 2

Child component patterns I

var  list  =  new  Ext.List({        store:  store,        ...});

var  panel  =  new  Ext.Panel({        items:  [list,  ...],        ...});

reference component by var

instantiate component

Page 30: The City Bars App with Sencha Touch 2

Child component patterns II

var  list  =  Ext.create('Ext.List',  {        store:  store,        ...});

var  panel  =  Ext.create('Ext.Panel',  {        items:  [list,  ...]        ...});

preferable in ST2

Page 31: The City Bars App with Sencha Touch 2

Child component patterns III

var  panel  =  Ext.create('Ext.Panel',  {        items:  [                {                        xtype:  'list',                        store:  store,                        ...                },  ...        ],        ...});

deferred creation*

* a lightweight object until then

Page 32: The City Bars App with Sencha Touch 2

</aside>

Page 33: The City Bars App with Sencha Touch 2

{        //  the  list  card        id:  'listCard',        layout:  'fit',        items:  [{                //  main  top  toolbar                xtype:  'toolbar',                docked:  'top',                title:  'Please  wait'                //  will  get  added  once  city  known        },  {                //  the  list  itself                //  gets  bound  to  the  store  once  city  known                id:  'dataList',                xtype:  'list'        }]}

* list will be bound to a store later

list*

The list card

list should fill whole card

docked top toolbar

Page 34: The City Bars App with Sencha Touch 2

{        //  the  details  card        id:  'detailCard',        items:  [{                //  detail  page  also  has  a  toolbar                docked  :  'top',                xtype:  'toolbar',                title:  ''        },  {                //  textual  detail        }]}

detail page to come later...

The detail card

another docked toolbar*

* title will be dynamically set

Page 35: The City Bars App with Sencha Touch 2

note:list already

scrollable

Page 36: The City Bars App with Sencha Touch 2

Data modeling

3_data_modeling

Page 37: The City Bars App with Sencha Touch 2

http://api.yelp.com/business_review_search

?ywsid=YELP_KEY

&term=BUSINESS_TYPE

&location=CITY

The YELP API...

free, rate limited

business type, and city name

Page 38: The City Bars App with Sencha Touch 2

...returns a nested JSON array

mmm, json

Page 39: The City Bars App with Sencha Touch 2

‘businesses’ array

Apigee API console

Page 40: The City Bars App with Sencha Touch 2

"businesses":  [    {        "rating_img_url"  :  "http://media4.px.yelpcdn.com/...",        "country_code"  :  "US",        "id"  :  "BHpAlynD9dIGIaQDRqHCTA",        "is_closed"  :  false,        "city"  :  "Nashville",        "mobile_url"  :  "http://mobile.yelp.com/biz/...",        "review_count"  :  50,        "zip"  :  "11231",        "state"  :  "TN",        "latitude"  :  40.675758,        "address1"  :  "253  Conover  St",        "address2"  :  "",        "address3"  :  "",        "phone"  :  "7186258211",        "state_code"  :  "TN",        "categories":  [...],        ...    },  ...]

some fields areuseful for our app

Page 41: The City Bars App with Sencha Touch 2

Ext.define("Business",  {        extend:  "Ext.data.Model",        fields:  [                {name:  "id",  type:  "int"},                {name:  "name",  type:  "string"},                {name:  "latitude",  type:  "string"},                {name:  "longitude",  type:  "string"},                {name:  "address1",  type:  "string"},                {name:  "address2",  type:  "string"},                {name:  "address3",  type:  "string"},                {name:  "phone",  type:  "string"},                {name:  "state_code",  type:  "string"},                {name:  "mobile_url",  type:  "string"},                {name:  "rating_img_url_small",  type:  "string"},                {name:  "photo_url",  type:  "string"},        ]});

give the ‘class’ a name

Create a data model

extending base model

and with these named, typed fields

Page 42: The City Bars App with Sencha Touch 2

<aside>

</aside>

Models can be associated

with other models

Fields can also have default values,

conversion functions, and validation

Page 43: The City Bars App with Sencha Touch 2

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

Create a model store

Think of a store as a ‘table’ of model instance ‘rows’

create the store

containing thistype of model

Page 44: The City Bars App with Sencha Touch 2

var  store  =  Ext.create('Ext.data.Store',  {        model:  'Business',        autoLoad:  true,        proxy:  {                //  call  Yelp  to  get  business  data                type:  'scripttag',                url:  'http://api.yelp.com/business_review_search'  +                          '?ywsid='  +  YELP_KEY  +                          '&term='  +  escape(BUSINESS_TYPE)  +                          '&location='  +  escape(DEFAULT_CITY)                ,                reader:  {                        type:  'json',                        root:  'businesses'                }        }});

Configure data sourceloads as soon as possible

construct API URL

source

read array from inside JSON

JSONP

Page 45: The City Bars App with Sencha Touch 2

<script>        YELP_KEY  =  'G3HueY_I5a8WZX-­‐_bAAAA';        DEFAULT_CITY  =  'San  Francisco';        BUSINESS_TYPE  =  'Bars';</script>

Create constants

please change this!

Page 46: The City Bars App with Sencha Touch 2

We can make the proxy URL dynamic,

which would allow geolocation.

But this requires an async

callback sequence.

Page 47: The City Bars App with Sencha Touch 2

getCity:  function  (callback)  {        callback(DEFAULT_CITY);        //  this  could  now  be  a  geo  lookup  to        //  get  the  nearest  city},

getBusinesses:  function  (city,  callback)  {

       Ext.define("Business",  {                ...        });                var  store  =  Ext.create('Ext.data.Store',  {                ...        });

}

Two-phase async sequence

and this will need to fire the callback with store when it autoloads

the data codewe just wrote

use this in the URL

call whenUI ready

Page 48: The City Bars App with Sencha Touch 2

var  store  =  Ext.create('Ext.data.Store',  {        ...        listeners:  {                //  when  the  records  load,  fire  the  callback                load:  function  (store)  {                        callback(store);                }        }}); fire the callback with store

when loaded

eventlisteners

Page 49: The City Bars App with Sencha Touch 2

store

records

cheeky callback

Page 50: The City Bars App with Sencha Touch 2

List Binding

4_list_binding

Page 51: The City Bars App with Sencha Touch 2

//  get  the  cityCB.getCity(function  (city)  {

       //  then  use  Yelp  to  get  the  businesses        CB.getBusinesses(city,  function  (store)  {

               //  then  bind  data  to  list  and  show  it                CB.cards.query('#dataList')[0].setStore(store);

       });});

bind the store to itget dataList by its id

our 2 async functions

Page 52: The City Bars App with Sencha Touch 2

but we haz records!

:-(

Page 53: The City Bars App with Sencha Touch 2

CB.getCity(function  (city)  {

       cards.query('#listCard  toolbar')[0]                .setTitle(city  +  '  '  +  BUSINESS_TYPE);

       ...

now title will always match city

another component query

Page 54: The City Bars App with Sencha Touch 2

{        id:  'dataList',        xtype:  'list',        store:  null,        itemTpl:  '{name}'}

model fields in curly braces

List items are templated

Page 55: The City Bars App with Sencha Touch 2

Ext.create('Ext.LoadMask',  Ext.getBody(),  {        store:  store,        msg:  ''});

instantiate mask

Spinner bound to store

over body

will show when store is loading

Page 56: The City Bars App with Sencha Touch 2
Page 57: The City Bars App with Sencha Touch 2

A more interesting template

itemTpl:        '<img  class="photo"  src="{photo_url}"  width="40"  height="40"/>'  +        '{name}<br/>'  +        '<img  src="{rating_img_url_small}"/>&nbsp;'  +        '<small>{address1}</small>'

HTML allowed

Page 58: The City Bars App with Sencha Touch 2

<style>        .photo  {                float:left;                margin:0  8px  16px  0;                border:1px  solid  #ccc;                -­‐webkit-­‐box-­‐shadow:  0  2px  4px  #777;        }</style>

Hack the style

Page 59: The City Bars App with Sencha Touch 2

...width="40"  height="40"  />

seems likea waste

Page 60: The City Bars App with Sencha Touch 2

src.sencha.io<img  src="http://src.sencha.io/40/{photo_url}"          width="40"  height="40"/>

4 times smaller

Page 61: The City Bars App with Sencha Touch 2

List Event Handler

5_list_event_handler

Page 62: The City Bars App with Sencha Touch 2

{        id:  'dataList',        ...        listeners:  {                selectionchange:  function  (selectionModel,  records)  {                        //  if  selection  made,  slide  to  detail  card                        if  (records[0])  {

                               CB.cards.setActiveItem(1);

                               CB.cards.getActiveItem().setData(                                        records[0].data                                );

                       }                }        }}

when list itemsare selected

selection

also fires on deselection

detail card

apply record data...

...to detail page template

Page 63: The City Bars App with Sencha Touch 2

A back button

items:  [{        //  detail  page  also  has  a  toolbar        docked  :  'top',        xtype:  'toolbar',        title:  '',        items:  [{                //  containing  a  back  button                //  that  slides  back  to  list  card                text:  'Back',                ui:  'back',                listeners:  {                        tap:  function  ()  {                                CB.cards.setActiveItem(0);                        }                }        }],  ...

back to list

when tapped

arrow style

children of toolbarsare implicitlyxtype: ‘button’

Page 64: The City Bars App with Sencha Touch 2
Page 65: The City Bars App with Sencha Touch 2

Detail Page

6_detail_page

Page 66: The City Bars App with Sencha Touch 2

{        //  textual  detail        styleHtmlContent:  true,        cls:  'detail',        tpl:  [                '<img  class="photo"  src="{photo_url}"  />',                '<h2>{name}</h2>',                '<div  class="info">',                        '{address1}<br/>',                        '<img  src="{rating_img_url_small}"/>',                '</div>',                '<div  class="phone  x-­‐button">',                        '<a  href="tel:{phone}">{phone}</a>',                '</div>',                '<div  class="link  x-­‐button">',                        '<a  href="{mobile_url}">Read  more</a>',                '</div>'        ]}]

style this card as regular HTML

CSS class for styling

template fora whole panel

Page 67: The City Bars App with Sencha Touch 2

:-(

Page 68: The City Bars App with Sencha Touch 2

CB.cards.getActiveItem().setData(        records[0].data);

setData does not cascade into child items!

Remember this?

Page 69: The City Bars App with Sencha Touch 2

setData:  function  (data)  {        this.query('toolbar')[0].setTitle(data.name);        this.query('[cls="detail"]')[0].setData(data);},

set title on toolbar

Override setData

apply data to template on inner panel

Page 70: The City Bars App with Sencha Touch 2

good

not so much

Page 71: The City Bars App with Sencha Touch 2

A little styling

.x-­‐html  h2  {        margin-­‐bottom:0;}.phone,  .link  {        clear:both;        font-­‐weight:bold;        display:block;        text-­‐align:center;        margin-­‐top:8px;}

.detail  {        -­‐webkit-­‐box-­‐orient:  vertical;}.detail  .photo  {        float:none;}

formattingthe buttons

temporaryfixes

Page 72: The City Bars App with Sencha Touch 2
Page 73: The City Bars App with Sencha Touch 2

One final tweak

{        //  textual  detail        cls:  'detail',        styleHtmlContent:  true,        ...

...to outer card

move frominner panel...

{        //  the  details  card        id:  'detailCard',        styleHtmlContent:  true,

Page 74: The City Bars App with Sencha Touch 2

complete with<h2> </h2>

Page 75: The City Bars App with Sencha Touch 2
Page 76: The City Bars App with Sencha Touch 2
Page 77: The City Bars App with Sencha Touch 2

Development sequence

1 App Architecture

2 UI Structure

3 Data Modeling

4 List Binding

5 List Event Handler

6 Detail Page

7 Customize Theme

Page 78: The City Bars App with Sencha Touch 2

Other ideas...

Page 79: The City Bars App with Sencha Touch 2

‘Responsive’ Apps

http://sencha.com/x/cv

Page 80: The City Bars App with Sencha Touch 2

Packaging

Add to home screen - Icon - Splash screen

Hybrid app; PhoneGap / NimbleKit - Contacts API - Geolocation

http://sencha.com/x/cyhttp://sencha.com/x/de

Page 81: The City Bars App with Sencha Touch 2

Geolocation

Page 82: The City Bars App with Sencha Touch 2

O!ine app

http://github.com/jamesgpearce/confess

Page 83: The City Bars App with Sencha Touch 2

O!ine data

Taking Yelp data o"ine

Taking images o"ine - src.sencha.io to generate cross-origin B64

Detecting network connection changes

http://sencha.com/x/df

Page 84: The City Bars App with Sencha Touch 2

Debugging

http://phonegap.github.com/weinre

Page 85: The City Bars App with Sencha Touch 2

James Pearce @ jamespearce