James Pearce
Director, Developer Relations
@jamespearce
jamesp@sencha.com
Build A
Mobile Web App
with
CSS
HTML JS
http://www.sencha.com/products/touch
Sencha Touch
A JavaScript framework for building
rich mobile apps with web standards
Pre-requisites
Sencha Touch SDK:
  http://sencha.com/products/touch/
 Yelp developer API key:
  http://www.yelp.com/developers/getting_started/
api_overview
 Install Sass and Compass:
  http://sass-lang.com/download.html
http://compass-style.org/install/
CityBars
http://sencha.com/x/bu
City bars workshop
http://sencha.com/x/bv
Development sequence
1 Structure the app
2 Layout the UI
3 Model the data
4 Load the list
5 Attach events
6 Detail page
7 Add mapping
8 Customize theme
City bars workshop
1 Structure the app
index.html
<!doctype  html>
<html>
        <head>
                <title>City  Guide</title>
        </head>
<body></body>
</html>
index.html
<script  src="lib/touch/sencha-­‐touch.js"  
                type="text/javascript"></script>
<script  type="text/javascript">
        YELP_KEY	
  =	
  'G3HueY_I5a8WZX-­‐_bFo3Mw';
        ...
</script>
<script  src="app/app.js"
                type="text/javascript"></script>
<link  href="lib/touch/resources/css/sencha-­‐touch.css"  
            rel="stylesheet"  type="text/css"  />
app.js
cb  =  new  Ext.Application({
        launch:  function()  {
                new	
  Ext.Panel({
                        layout        :  'card',
                        fullscreen:  true,
                        html:	
  "Hello	
  world!"
        
                });
        }
});
City bars workshop
cb.cards
2 Layout the UI
listCard detailCard
toolbar toolbar
dataList
index.html
cb  =  new  Ext.Application({
        launch:  function()  {
                cb.cards  =  new  Ext.Panel({
                        layout        :  'card',
                        fullscreen:  true,
                        cardSwitchAnimation:	
  'slide',
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  items:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  {id:	
  'listCard'	
  ...},	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  {id:	
  'detailCard'	
  ...}
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ]
        
                });
        }
});
listCard
{
        id:  'listCard',
	
  	
  	
  	
  layout:	
  'fit',
	
  	
  	
  	
  dockedItems:  [{
                dock  :  'top',
                xtype:	
  'toolbar',
                title:  'Please  wait'
        }],
        items:  [{
                id:  'dataList',
	
  	
  	
  	
  	
  	
  	
  	
  xtype:	
  'list',
                store:  null,
                itemTpl:  '{name}'
        }]
}
detailCard
{
        id:  'listCard',
        dockedItems:  [{
                dock  :  'top',
                xtype:  'toolbar',
                title:  ''
        }]
}
City bars workshop
3 Model the data
http://api.yelp.com/business_review_search
?ywsid=YELP_KEY
&term=BUSINESS_TYPE
&location=CITY
Apigee console
"businesses":  [
        {
          "rating_img_url"  :  "http://media4.px.yelpcdn.com/...",
          "country_code"  :  "US",
          "id"  :  "BHpAlynD9dIGIaQDRqHCTA",
          "is_closed"  :  false,
          "city"  :  "Brooklyn",
          "mobile_url"  :  "http://mobile.yelp.com/biz/...",
          "review_count"  :  50,
          "zip"  :  "11231",
          "state"  :  "NY",
          "latitude"  :  40.675758,
          "address1"  :  "253  Conover  St",
          "address2"  :  "",
          "address3"  :  "",
          "phone"  :  "7186258211",
          "state_code"  :  "NY",
          "categories":  [
            ...",
          ],
          ...
index.html
<script  type="text/javascript">
        YELP_KEY  =  'G3HueY_I5a8WZX-­‐_bFo3Mw';
        DEFAULT_CITY  =  'New  York';
        BUSINESS_TYPE  =  'Bars';
</script>
app.js
Ext.regModel("Business",  {
        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"},
        ]
});
app.js
Ext.regStore("businesses",  {
        model:  'Business',
        autoLoad:  true,
        proxy:  {
                type:  'scripttag',
                url:  'http://api.yelp.com/business_review_search'  +
                        '?ywsid='  +  YELP_KEY  +
                        '&term='  +  escape(BUSINESS_TYPE)  +
                        '&location='  +  escape(city)
                ,
                reader:  {
                        type:  'json',
                        root:  'businesses'
                }
        },
app.js
listeners:  {
        'afterrender':  function  ()  {
                cb.getCity(function  (city)  {
                        cb.getBusinesses(city,  function  (store)  {
                                console.log(store.data.items);
                        });
                });
        }
}
app.js
getCity:  function  (callback)  {
        callback(DEFAULT_CITY);
},
getBusinesses:  function  (city,  callback)  {
        Ext.regModel("Business",  {...});
        Ext.regStore("businesses",  {
                ...
                listeners:  {
                        'load':  function  (store)  {
                                callback(store);
                        }
                }
        })
}
City bars workshop
4 Load the list
app.js
var  cards  =  this;
cards.listCard  =  cards.getComponent('listCard');
cards.dataList  =  cards.listCard.getComponent('dataList');
cards.detailCard  =  cards.getComponent('detailCard');
cb.getCity(function  (city)  {
        cards.listCard.getDockedItems()[0]
	
  	
  	
  	
  	
  	
  	
  	
  	
  .setTitle(city  +  '  '  +  BUSINESS_TYPE);
        cb.getBusinesses(city,  function  (store)  {
                cards.dataList.bindStore(store);
                cards.setActiveItem(cards.listCard);
        });
});
app.js
cards.setLoading(true);
...
cards.setLoading(false);
City bars workshop
5 Attach events
A more interesting list template
‘selection’ event to switch to detail
app.js
itemTpl:
    '<img  class="photo"  src="{photo_url}"  width="40"  height="40"/>'  +
    '{name}<br/>'  +
    '<img  src="{rating_img_url_small}"/>&nbsp;'  +
    '<small>{address1}</small>'
index.html
<style>
        .photo  {
                float:left;
                margin:0  8px  16px  0;
                border:1px  solid  #ccc;
                -­‐webkit-­‐box-­‐shadow:
                        0  2px  4px  #777;
        }
</style>
app.js
listeners:  {
        selectionchange:  function  (selectionModel,  records)  {
                if  (records[0])  {
                        cb.cards.setActiveItem(cb.cards.detailCard);
                        cb.cards.detailCard.update(records[0].data);
                }
        }
}
6 Detail page
Template for the detail card
Back button with tap to switch back to list
app.js
styleHtmlContent:  true,
cls:  'detail',
tpl:  [
        '<img  class="photo"  src="{photo_url}"
            width="100"  height="100"/>',
        '<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>'
]
app.js
dockedItems:  [{
        dock  :  'top',
        xtype:  'toolbar',
        title:  '',
        items:  [{
                text:  'Back',
                ui:  'back',
                listeners:  {
                        tap:  function  ()  {
                                cb.cards.setActiveItem(
                                        cb.cards.listCard,
                                        {type:'slide',  direction:  'right'}
                                );
                        }
                }
        }]
}],
index.html
.x-­‐html  h2  {
        margin-­‐bottom:0;
}
.phone,  .link  {
        clear:both;
        font-­‐weight:bold;
        display:block;
        text-­‐align:center;
        margin-­‐top:8px;
}
7 Add mapping
Change detail page to tabbed
Add map control
Update data on both tabs
app.js
{
        id:  'detailCard',
        xtype:	
  'tabpanel',
        dockedItems:  [...]
        items:  [
                {
                        title:  'Contact',
                        tpl:  [...]
                },
                {
                        title:  'Map',
                        xtype:	
  'map',
                        ...
                        marker:
                        new  google.maps.Marker()
                }
        ]
}
index.html
<script  src="http://maps.google.com/maps/api/js?sensor=true"
                type="text/javascript">
</script>
app.js
{
        xtype:  'map',
        ...
        update:  function  (data)  {
                this.map.setCenter(
                        new  google.maps.LatLng(data.latitude,  data.longitude
                ));
                this.marker.setPosition(
                        this.map.getCenter()
                );
                this.marker.setMap(this.map);
        },
}
app.js
tabBar:  {
        dock:  'top',
        ui:  'light',
        layout:  {  pack:  'center'  }
}
City bars workshop
app.js
update:  function(data)  {
        Ext.each(this.items.items,  function(item)  {
                item.update(data);
        });
        this.getDockedItems()[0].setTitle(data.name);
}
8 Customize theme
Sass & Compass
Compile & link new theme
http://sass-lang.com/
/* SCSS */
$blue: #3bbfce;
$margin: 16px;
.content-navigation {
border-color: $blue;
color:
darken($blue, 9%);
}
.border {
padding: $margin / 2;
margin: $margin / 2;
border-color: $blue;
}
/* CSS */
.content-navigation {
border-color: #3bbfce;
color: #2b9eab;
}
.border {
padding: 8px;
margin: 8px;
border-color: #3bbfce;
}
Variables
$> sudo gem install compass
http://rubyinstaller.org/
$> compass -v
Compass 0.11.1 (Antares)
Copyright (c) 2008-2011 Chris Eppstein
Released under the MIT License.
$> sass -v
Sass 3.1.1 (Brainy Betty)
City bars workshop
citybars.scss
$base-­‐color:	
  #666;
$base-­‐gradient:	
  'glossy';
$include-­‐default-­‐icons:	
  false;
@import  'sencha-­‐touch/default/all';
@include  sencha-­‐panel;
@include  sencha-­‐buttons;
@include  sencha-­‐tabs;
@include  sencha-­‐toolbar;
@include  sencha-­‐list;
@include  sencha-­‐layout;
@include  sencha-­‐loading-­‐spinner;
$>  compass  compile  citybars.scss
overwrite  citybars.css  
index.html
<link
    href="theming/citybars.css"
    rel="stylesheet"  type="text/css"
/>
City bars workshop
James Pearce
Director, Developer Relations
@jamespearce
jamesp@sencha.com

More Related Content

PDF
Bootcamp Google Abidjan 2012: Workshop Gaou Search
TXT
Index1
PDF
Drupal Cms Prezentace
TXT
PDF
Як досвід компанії перетворився на фреймворк
PDF
Sis quiz
TXT
Index2
PDF
Palestra PythonBrasil[8]
Bootcamp Google Abidjan 2012: Workshop Gaou Search
Index1
Drupal Cms Prezentace
Як досвід компанії перетворився на фреймворк
Sis quiz
Index2
Palestra PythonBrasil[8]

What's hot (13)

PDF
Web components v1 intro
KEY
jQuery入門
PDF
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
PPTX
Entwurfsmuster für mobile JavaScript-Web-Apps - WebTechConference 2012
PPTX
JavaScript Data Binding mit jQuery Mobile - Mobile Developer Conference 2012 ...
PPTX
Entwurfsmuster für mobile JavaScript-Web-Apps – Mobile Tech Conference 2012 A...
PPTX
JavaScript Data Binding mit jQuery Mobile - MobileTech Conference Spring 2012
PPTX
10 Programación Web con .NET y C#
PDF
Javascript and jQuery for Mobile
PDF
Check out our photos of the Pixies' Metro show
PPTX
Asp .net Jquery
TXT
Load2
PDF
Get more votes!
Web components v1 intro
jQuery入門
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
Entwurfsmuster für mobile JavaScript-Web-Apps - WebTechConference 2012
JavaScript Data Binding mit jQuery Mobile - Mobile Developer Conference 2012 ...
Entwurfsmuster für mobile JavaScript-Web-Apps – Mobile Tech Conference 2012 A...
JavaScript Data Binding mit jQuery Mobile - MobileTech Conference Spring 2012
10 Programación Web con .NET y C#
Javascript and jQuery for Mobile
Check out our photos of the Pixies' Metro show
Asp .net Jquery
Load2
Get more votes!
Ad

More from James Pearce (20)

PDF
Mobile Device APIs
PDF
The City Bars App with Sencha Touch 2
PDF
An Intro to Mobile HTML5
PDF
A Snapshot of the Mobile HTML5 Revolution
PDF
A mobile web app for Android in 75 minutes
PDF
HTML5 and the dawn of rich mobile web applications pt 1
PDF
HTML5 and the dawn of rich mobile web applications pt 2
PDF
Building a Mobile App with Sencha Touch
PDF
Create a mobile web app with Sencha Touch
PDF
Cross platform mobile web apps
PDF
Bd conf sencha touch workshop
PDF
San Diego Hackathon
PDF
Building Cross Platform Mobile Web Apps
PDF
Creating and Distributing Mobile Web Applications with PhoneGap
PDF
Theming and Sass
PDF
An Introduction to Sencha Touch
PDF
Source Dev Con Keynote
PDF
Building Cloud-Based Cross-Platform Mobile Web Apps
PDF
Building cross platform mobile web apps
PDF
Building tomorrow's web with today's tools
Mobile Device APIs
The City Bars App with Sencha Touch 2
An Intro to Mobile HTML5
A Snapshot of the Mobile HTML5 Revolution
A mobile web app for Android in 75 minutes
HTML5 and the dawn of rich mobile web applications pt 1
HTML5 and the dawn of rich mobile web applications pt 2
Building a Mobile App with Sencha Touch
Create a mobile web app with Sencha Touch
Cross platform mobile web apps
Bd conf sencha touch workshop
San Diego Hackathon
Building Cross Platform Mobile Web Apps
Creating and Distributing Mobile Web Applications with PhoneGap
Theming and Sass
An Introduction to Sencha Touch
Source Dev Con Keynote
Building Cloud-Based Cross-Platform Mobile Web Apps
Building cross platform mobile web apps
Building tomorrow's web with today's tools
Ad

City bars workshop

  • 2. Build A Mobile Web App with CSS HTML JS
  • 4. Pre-requisites Sencha Touch SDK:   http://sencha.com/products/touch/  Yelp developer API key:   http://www.yelp.com/developers/getting_started/ api_overview  Install Sass and Compass:   http://sass-lang.com/download.html http://compass-style.org/install/
  • 8. Development sequence 1 Structure the app 2 Layout the UI 3 Model the data 4 Load the list 5 Attach events 6 Detail page 7 Add mapping 8 Customize theme
  • 11. index.html <!doctype  html> <html>        <head>                <title>City  Guide</title>        </head> <body></body> </html>
  • 12. index.html <script  src="lib/touch/sencha-­‐touch.js"                  type="text/javascript"></script> <script  type="text/javascript">        YELP_KEY  =  'G3HueY_I5a8WZX-­‐_bFo3Mw';        ... </script> <script  src="app/app.js"                type="text/javascript"></script> <link  href="lib/touch/resources/css/sencha-­‐touch.css"              rel="stylesheet"  type="text/css"  />
  • 13. app.js cb  =  new  Ext.Application({        launch:  function()  {                new  Ext.Panel({                        layout        :  'card',                        fullscreen:  true,                        html:  "Hello  world!"                        });        } });
  • 15. cb.cards 2 Layout the UI listCard detailCard toolbar toolbar dataList
  • 16. index.html cb  =  new  Ext.Application({        launch:  function()  {                cb.cards  =  new  Ext.Panel({                        layout        :  'card',                        fullscreen:  true,                        cardSwitchAnimation:  'slide',                        items:  [                                {id:  'listCard'  ...},                                  {id:  'detailCard'  ...}                        ]                        });        } });
  • 17. listCard {        id:  'listCard',        layout:  'fit',        dockedItems:  [{                dock  :  'top',                xtype:  'toolbar',                title:  'Please  wait'        }],        items:  [{                id:  'dataList',                xtype:  'list',                store:  null,                itemTpl:  '{name}'        }] }
  • 18. detailCard {        id:  'listCard',        dockedItems:  [{                dock  :  'top',                xtype:  'toolbar',                title:  ''        }] }
  • 20. 3 Model the data http://api.yelp.com/business_review_search ?ywsid=YELP_KEY &term=BUSINESS_TYPE &location=CITY
  • 22. "businesses":  [        {          "rating_img_url"  :  "http://media4.px.yelpcdn.com/...",          "country_code"  :  "US",          "id"  :  "BHpAlynD9dIGIaQDRqHCTA",          "is_closed"  :  false,          "city"  :  "Brooklyn",          "mobile_url"  :  "http://mobile.yelp.com/biz/...",          "review_count"  :  50,          "zip"  :  "11231",          "state"  :  "NY",          "latitude"  :  40.675758,          "address1"  :  "253  Conover  St",          "address2"  :  "",          "address3"  :  "",          "phone"  :  "7186258211",          "state_code"  :  "NY",          "categories":  [            ...",          ],          ...
  • 23. index.html <script  type="text/javascript">        YELP_KEY  =  'G3HueY_I5a8WZX-­‐_bFo3Mw';        DEFAULT_CITY  =  'New  York';        BUSINESS_TYPE  =  'Bars'; </script>
  • 24. app.js Ext.regModel("Business",  {        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"},        ] });
  • 25. app.js Ext.regStore("businesses",  {        model:  'Business',        autoLoad:  true,        proxy:  {                type:  'scripttag',                url:  'http://api.yelp.com/business_review_search'  +                        '?ywsid='  +  YELP_KEY  +                        '&term='  +  escape(BUSINESS_TYPE)  +                        '&location='  +  escape(city)                ,                reader:  {                        type:  'json',                        root:  'businesses'                }        },
  • 26. app.js listeners:  {        'afterrender':  function  ()  {                cb.getCity(function  (city)  {                        cb.getBusinesses(city,  function  (store)  {                                console.log(store.data.items);                        });                });        } }
  • 27. app.js getCity:  function  (callback)  {        callback(DEFAULT_CITY); }, getBusinesses:  function  (city,  callback)  {        Ext.regModel("Business",  {...});        Ext.regStore("businesses",  {                ...                listeners:  {                        'load':  function  (store)  {                                callback(store);                        }                }        }) }
  • 29. 4 Load the list
  • 30. app.js var  cards  =  this; cards.listCard  =  cards.getComponent('listCard'); cards.dataList  =  cards.listCard.getComponent('dataList'); cards.detailCard  =  cards.getComponent('detailCard'); cb.getCity(function  (city)  {        cards.listCard.getDockedItems()[0]                  .setTitle(city  +  '  '  +  BUSINESS_TYPE);        cb.getBusinesses(city,  function  (store)  {                cards.dataList.bindStore(store);                cards.setActiveItem(cards.listCard);        }); });
  • 33. 5 Attach events A more interesting list template ‘selection’ event to switch to detail
  • 34. app.js itemTpl:    '<img  class="photo"  src="{photo_url}"  width="40"  height="40"/>'  +    '{name}<br/>'  +    '<img  src="{rating_img_url_small}"/>&nbsp;'  +    '<small>{address1}</small>'
  • 35. index.html <style>        .photo  {                float:left;                margin:0  8px  16px  0;                border:1px  solid  #ccc;                -­‐webkit-­‐box-­‐shadow:                        0  2px  4px  #777;        } </style>
  • 36. app.js listeners:  {        selectionchange:  function  (selectionModel,  records)  {                if  (records[0])  {                        cb.cards.setActiveItem(cb.cards.detailCard);                        cb.cards.detailCard.update(records[0].data);                }        } }
  • 37. 6 Detail page Template for the detail card Back button with tap to switch back to list
  • 38. app.js styleHtmlContent:  true, cls:  'detail', tpl:  [        '<img  class="photo"  src="{photo_url}"            width="100"  height="100"/>',        '<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>' ]
  • 39. app.js dockedItems:  [{        dock  :  'top',        xtype:  'toolbar',        title:  '',        items:  [{                text:  'Back',                ui:  'back',                listeners:  {                        tap:  function  ()  {                                cb.cards.setActiveItem(                                        cb.cards.listCard,                                        {type:'slide',  direction:  'right'}                                );                        }                }        }] }],
  • 40. index.html .x-­‐html  h2  {        margin-­‐bottom:0; } .phone,  .link  {        clear:both;        font-­‐weight:bold;        display:block;        text-­‐align:center;        margin-­‐top:8px; }
  • 41. 7 Add mapping Change detail page to tabbed Add map control Update data on both tabs
  • 42. app.js {        id:  'detailCard',        xtype:  'tabpanel',        dockedItems:  [...]        items:  [                {                        title:  'Contact',                        tpl:  [...]                },                {                        title:  'Map',                        xtype:  'map',                        ...                        marker:                        new  google.maps.Marker()                }        ] }
  • 44. app.js {        xtype:  'map',        ...        update:  function  (data)  {                this.map.setCenter(                        new  google.maps.LatLng(data.latitude,  data.longitude                ));                this.marker.setPosition(                        this.map.getCenter()                );                this.marker.setMap(this.map);        }, }
  • 45. app.js tabBar:  {        dock:  'top',        ui:  'light',        layout:  {  pack:  'center'  } }
  • 47. app.js update:  function(data)  {        Ext.each(this.items.items,  function(item)  {                item.update(data);        });        this.getDockedItems()[0].setTitle(data.name); }
  • 48. 8 Customize theme Sass & Compass Compile & link new theme
  • 50. /* SCSS */ $blue: #3bbfce; $margin: 16px; .content-navigation { border-color: $blue; color: darken($blue, 9%); } .border { padding: $margin / 2; margin: $margin / 2; border-color: $blue; } /* CSS */ .content-navigation { border-color: #3bbfce; color: #2b9eab; } .border { padding: 8px; margin: 8px; border-color: #3bbfce; } Variables
  • 51. $> sudo gem install compass http://rubyinstaller.org/
  • 52. $> compass -v Compass 0.11.1 (Antares) Copyright (c) 2008-2011 Chris Eppstein Released under the MIT License. $> sass -v Sass 3.1.1 (Brainy Betty)
  • 54. citybars.scss $base-­‐color:  #666; $base-­‐gradient:  'glossy'; $include-­‐default-­‐icons:  false; @import  'sencha-­‐touch/default/all'; @include  sencha-­‐panel; @include  sencha-­‐buttons; @include  sencha-­‐tabs; @include  sencha-­‐toolbar; @include  sencha-­‐list; @include  sencha-­‐layout; @include  sencha-­‐loading-­‐spinner;
  • 55. $>  compass  compile  citybars.scss overwrite  citybars.css  
  • 56. index.html <link    href="theming/citybars.css"    rel="stylesheet"  type="text/css" />