SlideShare a Scribd company logo
1 of 73
Download to read offline
Craig Walker, Chief Technology Officer   www.xero.com
Craig Walker, Chief Technology Officer   www.xero.com
What is Xero?




http://www.xero.com/signup/
BlackBerry 6
BlackBerry 6   2nd half 2011
Lots of frameworks…
•   Zepto.js
•   DynamicX
•   SproutCore
•   XUI
•   Appcelerator
•   iUI
•   iWebKit
•   jQuery Mobile
•   jQTouch
•   And lots more…
Sencha Touch
What is Sencha Touch?
   A JavaScript framework for
building rich mobile applications
Why Sencha Touch?
•   Cross-platform
•   Looks native, feels native
•   Faster, cheaper, easier to build with
•   Highly customisable
•   Flexible deployment
•   HTML5/CSS3 goodness
Yes - but WHY Sencha Touch?
Tap !== Click
Touch Event Manager
•   Built on native events
•   Abstracted for performance
•   Multi-touch & gesture support
Touch Event Manager

     Ext.fly("el").on({
       tap: function() {
          alert("You tapped me");
       },
       pinch: function() {
          alert("You pinched me");
       },
       swipe: function() {
          alert("Stop touching me...")
       }
     });
     28
Scroll Event Manager
•   Scrolling with momentum &
    bounce physics
•   Native & natural
•   Hardware accelerated
UI Toolkit
Buttons
Forms
Sliders
Pickers
Lists
Nested
Lists
Toolbars
Tabs
Panels
Carousels
Maps
Overlays
Layouts
•   Container layout specifies how its children
    components are rendered
fit
card
vbox
hbox
MVC
               Routes

              Controllers




                            Models
      Views
                            Stores
Theming
•   SASS & Compass
    – sass-lang.com
    – compass-style.org

•   CSS3 is awesome – SCSS is awesomer
SCSS                                   CSS
$blue: #3bbfce;                         /* line 5, variables.scss */
$margin: 16px;                          .example1 {
$padding: 4px;                            border-color: #3bbfce;
                                        }
.example1 {
  border-color: $blue;                  /* line 9, variables.scss */
}                                       .example2 {
                                          margin: 16px;
.example2 {                               color: #3bbfce;
  margin: $margin;                      }
  color: $blue;
}                                       /* line 14, variables.scss */
                                        .example3 {
.example3 {                               margin: 32px;
  margin: ($margin / 2px) * $padding;   }
}
SCSS                                   CSS
@mixin add-child($color) {                        /* line 18, mixins.scss */
  color: $color;                                  .example {
  background-color: lighten($color, 50);            color: red;
                                                    background-color: white;
    .child {                                      }
      padding: 5px;                               /* line 5, mixins.scss */
                                                  .example .child {
        &:first {                                   padding: 5px;
           background-color: darken($color, 10)   }
        };                                        /* line 8, mixins.scss */
                                                  .example .child:first {
        span {                                      background-color: #cc0000;
          color: mix($color, blue);               }
        }                                         /* line 12, mixins.scss */
    }                                             .example .child span {
}                                                   color: #7f007f;
                                                  }
.example {
  @include add-child(#F00);
}
SCSS                                      CSS
@import "compass";                      /* line 5, gradients.scss */
                                        .button {
$width: 100px;                            width: 100px;
                                        }
.button {                               /* line 8, gradients.scss */
  width: $width;                        .button .round {
                                          -moz-border-radius: 5px;
    .round {                              -webkit-border-radius: 5px;
      @include border-radius(5px);        -o-border-radius: 5px;
    }                                     -ms-border-radius: 5px;
                                          -khtml-border-radius: 5px;
    .linear {                             border-radius: 5px;
      @include linear-gradient(         }
         color-stops(white, #c39 30%,   /* line 12, gradients.scss */
           #b7f 70%, #aaa)              .button .linear {
      );                                  background-image: -webkit-gradient(
    }                                       linear, 0% 0%, 0% 100%,
}                                           color-stop(0%, #ffffff),
                                            color-stop(50%, #cc3399),
                                            color-stop(100%, #bb77ff));
                                          background-image: -moz-linear-gradient(top,
                                            #ffffff 0%, #cc3399 50%, #bb77ff 100%);
                                          background-image: linear-gradient(top,
                                            #ffffff 0%, #cc3399 50%, #bb77ff 100%);
                                        }
Let’s look at some code...
Demo: From Desktop to Mobile
index.html



<!doctype html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>Xero Help</title>

  <link rel="stylesheet" href="resources/css/xerohelp.css" type="text/css">
</head>
<body>
  <script type="text/javascript" src="lib/sencha-touch-debug.js"></script>
  <script type="text/javascript" src="app/xerohelp.js"></script>
</body>
</html>
app/xerohelp.js
// utils
document.write('<script type="text/javascript" src="app/utils/string.js"></script>');

// application
document.write('<script type="text/javascript" src="app/routes.js"></script>');
document.write('<script type="text/javascript" src="app/app.js"></script>');

// models
document.write('<script type="text/javascript" src="app/models/TOC.js"></script>');
document.write('<script type="text/javascript" src="app/models/HelpFile.js"></script>');

// views
document.write('<script   type="text/javascript"   src="app/views/Viewport.js"></script>');
document.write('<script   type="text/javascript"   src="app/views/TOCPanel.js"></script>');
document.write('<script   type="text/javascript"   src="app/views/HelpCarousel.js"></script>');
document.write('<script   type="text/javascript"   src="app/views/HelpPanel.js"></script>');

// controllers
document.write('<script type="text/javascript" src="app/controllers/help.js"></script>');
app/routes.js




Ext.Router.draw(function(map) {
  map.connect("/help/home", {controller: 'help', action: 'home'});
  map.connect("/help/:id", {controller: 'help', action: 'show'});
});
app/app.js

Ext.regApplication({
  name: "XERO",

  defaultUrl: '/help/home',
  defaultTarget: "viewport",

  icon: 'resources/images/icon.png',
  glossOnIcon: false,

  region: "NZ",
  apiUrl: "http://help.stage.xero.com/api",

  launch: function() {
    this.viewport = new XERO.Viewport({
      application: this
    });
  }
});
XERO.Viewport = Ext.extend(Ext.Panel, {

  id: 'viewport',                                    app/views/viewport.js
  layout: 'card',
  fullscreen: true,

  initComponent: function() {
    Ext.apply(this, {
      dockedItems: [{
         xtype: "toolbar",
         dock : "top",
         title: "Help Center",
         itemId: "help-toolbar"
      },{
         xtype: "toolbar",
         dock: "bottom",
         items: [{
            xtype: "button",
            text: "Index",
            handler: this.onTOCButtonTap,
            scope: this
         },{ xtype: "spacer" }, {
            xtype: "button",
            text: "Switch Region",
            handler: this.onSwitchRegionTap,
            scope: this
         }]
      }]
    });
    XERO.Viewport.superclass.initComponent.apply(this, arguments);
  }, ...
setTitle: function(title) {
     this.down("#help-toolbar").setTitle(title);
  },                                                  app/views/viewport.js
  onTOCButtonTap: function() {
     if(! this.tocPanel) {
       this.tocPanel = Ext.create({
         xtype: "tocpanel"
       });
     }
     this.tocPanel.show();
  },

  onSwitchRegionTap: function() {
    if(! this.regionPicker) {
      this.regionPicker = new Ext.Picker({
        slots: [{
           name : 'region',
           title: 'Switch Region',
           data : [
             {text: 'New Zealand', value: "NZ"},
             {text: 'Australia', value: "AUS"},
             {text: 'United Kingdom', value: "UK"},
             {text: 'Global', value: "INT"}
           ]
        }]
      });
    }
    this.regionPicker.show();
  }
});
app/controllers/help.js

Ext.regController("help", {

  home: function(request) {
     this.show(Ext.apply(request, {
       id: "home"
     }));
  },

  show: function(request) {
    if(! this.helpCarousel) {
      this.helpCarousel = this.render({
        xtype: 'helpcarousel'
      });
    }

      XERO.viewport.setActiveItem(this.helpCarousel);
      XERO.viewport.setTitle("Loading...");

      this.helpCarousel.loadHelpPage(request.id, request.historyUrl);
  }
});
app/models/helpfile.js

Ext.regModel("HelpFile", {
  fields: [
     { name: "id", type: "int" },
     "abstractText",
     "body",
     "heading",
     "helpPage",
     { name: "createdDateUTC", type: "date", format: "M$" },
     { name: "success", type: "boolean" }
  ]
  /*,
  validations: [
     { type: "presence", field: "helpPage" }
  ],

  hasMany: [
     { model: "Region", name: "regions" }
  ]
  */
});
app/models/toc.js
Ext.regModel("TOC", {
  fields: [
     "id",
     "helpPage",
     "href",
     "text"
  ],

  proxy: {
    type: 'scripttag',
    url: String.format("{0}/toc/", XERO.apiUrl),
    reader: {
      type: "tree",
      root: "items"
    }
  }
});

(function() {
  new Ext.data.TreeStore({
    storeId: "TOCStore",
    model: "TOC",
    autoLoad: true
  });
}());
XERO.views.HelpCarousel = Ext.extend(Ext.Carousel, {

  cls: "cards",
                                                      app/views/helpcarousel.js
  layout: "fit",

  initComponent: function() {
     XERO.views.HelpCarousel.superclass.initComponent.apply(this, arguments);
  },

  onRender: function() {
    XERO.views.HelpCarousel.superclass.onRender.apply(this, arguments);

       if(this.el) {
         this.mon(this.el, {
           tap: this.onTap,
           click: Ext.emptyFn,
           delegate: "a",
           stopEvent: true,
           scope: this
         });

           this.mon(this, {
             cardswitch: function() {
                this.onHelpSwitch(this.getActiveItem().helpPage);
             },
             scope: this
           });
       }
  },
loadHelpPage: function(id, href) {
  var bookmark;                                app/views/helpcarousel.js
  if(href.indexOf("$") != -1) {
    bookmark = href.right(href.length - href.indexOf("$") - 1);
  }

     var item = this.getComponent(id);
     if(item) {
       this.setActiveItem(item);
         if(bookmark){
         item.scrollToBookmark(bookmark);
         }
     } else {
       var panel = this.add({
         xtype: "helppanel",
         id: id,
         goToBookmark: bookmark,
         listeners: {
           helploaded: this.onHelpSwitch,
           single: true,
           scope: this
         }
       });
       this.doComponentLayout();
       this.setActiveItem(panel);
     }
},
onTap: function(e, target) {
    var id = target.getAttribute('xero:id'),        app/views/helpcarousel.js
      type = target.getAttribute('xero:type'),
      bookmark = target.getAttribute('xero:bookmark'),
      url = target.getAttribute('xero:path');

      if(type && type.toLowerCase() == "help") {
        if(bookmark) {
          this.getActiveItem().scrollToBookmark(bookmark);
        } else {
          Ext.dispatch({
            controller: "help",
            action: "show",
            id: id,
            historyUrl: target.href
          });
        }
      } else {
        if(target.href.toLowerCase().startsWith("mailto:")) {
          location.href = target.href;
        } else {
          window.open(target.href);
        }
      }
  }
});

Ext.reg('helpcarousel', XERO.views.HelpCarousel);
app/views/helppanel.js

XERO.views.HelpPanel = Ext.extend(Ext.Panel, {

  cls: "help-panel",
  layout: "fit",
  scroll: "vertical",
  styleHtmlContent: true,
  goToBookmark: null,
  html: '<div class="loading-indicator"> </div>',

  initComponent: function() {
     this.addEvents("helploaded");
     XERO.views.HelpPanel.superclass.initComponent.apply(this, arguments);
  },

  onRender: function() {
    XERO.views.HelpPanel.superclass.onRender.apply(this, arguments);
    this.loadHelpPage();
  },...
loadHelpPage: function() {
    Ext.util.JSONP.request({
      url: String.format("{0}/help/", XERO.apiUrl),       app/views/helppanel.js
      callbackKey: "callback",
      params: {
         helpPage: this.id
      },
      callback: function(doc) {
         this.helpPage = doc;
         this.title = doc.heading;
         this.update(this.helpPage.body);

           if(this.goToBookmark) {
             this.scrollToBookmark(this.goToBookmark);
           }

           this.fireEvent("helploaded", this.helpPage);
         },
         scope: this
       });
  },

  scrollToBookmark: function(bookmark) {
     var el = this.getEl().down(String.format('a[name="{0}"]', bookmark));
     if (el) {
       this.scrollIntoView(el);
     }
  },
 });

Ext.reg('helppanel', XERO.views.HelpPanel);
XERO.views.TOCPanel = Ext.extend(Ext.NestedList, {
  title: "Index",
  showAnimation: {                                     app/views/helppanel.js
     type: "slide",
     direction: "up"
  },
  floating: true,

  initComponent: function() {
    this.store = Ext.getStore("TOCStore");
    this.toolbar = {...};

      XERO.views.TOCPanel.superclass.initComponent.apply(this, arguments);

      this.mon(this, {
        selectionchange: function(list, selection) {
           var record = selection[0];
           if(record.get("leaf") === true) {
             Ext.dispatch({
               controller: "help",
               action: "show",
               id: record.get("helpPage"),
               historyUrl: String.format("/help/{0}", record.get("helpPage"))
             });
             this.hide();
           }
        },
        scope: this
      });
  }
});
Touchable help...
going native
•   Cross-platform
•   Open source
•   Extensible
•   Instantiates chromeless
    web view
•   Adds JavaScript access
    to native APIs
Web App



PhoneGap   etc…
Native APIs
•   Device identification
•   Network access
•   Sensors
•   Camera/image sources
•   Contacts
•   File access
Everything else?
•   HTML for layout
•   JavaScript for accessing device APIs
•   CSS for look & feel
•   Offline storage for standalone clients
•   Ajax, JSONP for syncing to the cloud
    –   Runs on file:// protocol which is exempt from same-origin
        policy
•   Just use Sencha Touch!
PhoneGap Build
Tips & Tricks
Tools
•   Browsers – Safari the best (unfortunately)
•   Web Inspector
•   RemoteJS (Android debugging)
•   Souders’ bookmarklets
    – stevesouders.com/mobileperf

•   Jdrop
    – jdrop.org
Object-oriented
•   Use namespaces to define your library
•   Define components – code for reusability
•   Extend first, write plugins second (not at all
    if possible)
Events rock!
•   Use events to communicate between
    components
•   Use event delegation
Override appropriately
•   Do not edit the library files
•   DO NOT EDIT THE LIBRARY FILES!
•   Use an overrides file if you need to override
    the framework
•   Do the same with CSS (but you should be
    using cls, ui properties)
Define a directory structure
•   Break your code into small files
•   Use build tools to compile for performance
•   Use sencha-touch-debug.js during dev (but
    never prod!)
•   Keep the framework up-to-date – upgrade as
    often as you can
Worry about performance
•   Understand client-side performance rules &
    use them
•   Latency bad
•   JIT compilers – compilation time relates to
    size of file the method exists in
•   Keep DOM light
•   Destroy components that aren’t visible
•   concatenate, minify, compress!
Theming/Layouts
•   Use SCSS
•   Remove unnecessary CSS by only
    including required SCSS mixins
•   Understand XTemplate
•   Understand doComponentLayout
Sencha.com

Read the forums




                        Read the docs



           Read the source!
Any questions?




                 www.xero.com
www.xero.com/careers/

More Related Content

What's hot

Worth the hype - styled components
Worth the hype - styled componentsWorth the hype - styled components
Worth the hype - styled componentskathrinholzmann
 
Drupal Omega and Responsive Build out
Drupal Omega and Responsive Build outDrupal Omega and Responsive Build out
Drupal Omega and Responsive Build outTim Whelan
 
Componentization css angular
Componentization css angularComponentization css angular
Componentization css angularDavid Amend
 
PythonでJWT生成からボット作成、投稿までやってみた
PythonでJWT生成からボット作成、投稿までやってみたPythonでJWT生成からボット作成、投稿までやってみた
PythonでJWT生成からボット作成、投稿までやってみたitoxdev
 
Bloqueador cmd-sh
Bloqueador cmd-shBloqueador cmd-sh
Bloqueador cmd-shmsbertoldi
 
Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany
Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, GermanyLet's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany
Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, GermanyBalázs Tatár
 
How to count money using PHP and not lose money
How to count money using PHP and not lose moneyHow to count money using PHP and not lose money
How to count money using PHP and not lose moneyPiotr Horzycki
 

What's hot (18)

Coding website
Coding websiteCoding website
Coding website
 
Worth the hype - styled components
Worth the hype - styled componentsWorth the hype - styled components
Worth the hype - styled components
 
Coding part
Coding partCoding part
Coding part
 
Drupal Omega and Responsive Build out
Drupal Omega and Responsive Build outDrupal Omega and Responsive Build out
Drupal Omega and Responsive Build out
 
Codigo taller-plugins
Codigo taller-pluginsCodigo taller-plugins
Codigo taller-plugins
 
PhoneGap: Local Storage
PhoneGap: Local StoragePhoneGap: Local Storage
PhoneGap: Local Storage
 
Componentization css angular
Componentization css angularComponentization css angular
Componentization css angular
 
distill
distilldistill
distill
 
Send.php
Send.phpSend.php
Send.php
 
PythonでJWT生成からボット作成、投稿までやってみた
PythonでJWT生成からボット作成、投稿までやってみたPythonでJWT生成からボット作成、投稿までやってみた
PythonでJWT生成からボット作成、投稿までやってみた
 
Xmpp prebind
Xmpp prebindXmpp prebind
Xmpp prebind
 
Bloqueador cmd-sh
Bloqueador cmd-shBloqueador cmd-sh
Bloqueador cmd-sh
 
Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany
Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, GermanyLet's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany
Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany
 
How to count money using PHP and not lose money
How to count money using PHP and not lose moneyHow to count money using PHP and not lose money
How to count money using PHP and not lose money
 
Jina Bolton
Jina BoltonJina Bolton
Jina Bolton
 
JQuery Flot
JQuery FlotJQuery Flot
JQuery Flot
 
webstudy jquery
webstudy jquerywebstudy jquery
webstudy jquery
 
$.Template
$.Template$.Template
$.Template
 

Viewers also liked

Infographic Plagtracker.com
Infographic Plagtracker.comInfographic Plagtracker.com
Infographic Plagtracker.comPlagtracker.com
 
Presentation for 350.org Volunteer Social Media Team
Presentation for 350.org Volunteer Social Media TeamPresentation for 350.org Volunteer Social Media Team
Presentation for 350.org Volunteer Social Media TeamJoe Solomon
 
The Greatist Story
The Greatist StoryThe Greatist Story
The Greatist StoryGreatist
 
Seminar on social strategies in action:Driving Business Transformation
Seminar on social strategies in action:Driving Business TransformationSeminar on social strategies in action:Driving Business Transformation
Seminar on social strategies in action:Driving Business Transformation2016
 
2012 Education Job Market Report - Monster.com
2012 Education Job Market Report - Monster.com2012 Education Job Market Report - Monster.com
2012 Education Job Market Report - Monster.comMonster
 
Uk oil output 50 percent higher by 2018
Uk oil output 50 percent higher by 2018Uk oil output 50 percent higher by 2018
Uk oil output 50 percent higher by 2018Derek Louden
 
AF spouse newsletter - Oct & Nov 2012
AF spouse newsletter - Oct & Nov 2012AF spouse newsletter - Oct & Nov 2012
AF spouse newsletter - Oct & Nov 2012Scott AFB Clinic
 
Lids up or lids down? Jennie Osborn and Natasha Taylor
Lids up or lids down? Jennie Osborn and Natasha TaylorLids up or lids down? Jennie Osborn and Natasha Taylor
Lids up or lids down? Jennie Osborn and Natasha TaylorHEA_Blogs
 
Amazon global selling manual modfied by spainbox with specific information to...
Amazon global selling manual modfied by spainbox with specific information to...Amazon global selling manual modfied by spainbox with specific information to...
Amazon global selling manual modfied by spainbox with specific information to...Manuel Gallego
 
Write That Down! Van Wilder's Guide to Social Media
Write That Down!  Van Wilder's Guide to Social MediaWrite That Down!  Van Wilder's Guide to Social Media
Write That Down! Van Wilder's Guide to Social MediaErica OGrady
 
The Social Media Roi Cookbook
The Social Media Roi CookbookThe Social Media Roi Cookbook
The Social Media Roi CookbookSocial You, S.L.
 
Razor social social media tools guide
Razor social social media tools guideRazor social social media tools guide
Razor social social media tools guideNuno Fraga Coelho
 
WebLion Hosting: Leveraging Laziness, Impatience, and Hubris
WebLion Hosting: Leveraging Laziness, Impatience, and HubrisWebLion Hosting: Leveraging Laziness, Impatience, and Hubris
WebLion Hosting: Leveraging Laziness, Impatience, and HubrisErik Rose
 
Mobile Security - Hakin9 Magazine
Mobile Security - Hakin9 MagazineMobile Security - Hakin9 Magazine
Mobile Security - Hakin9 Magazinelogfusion
 
ISC 2013 korea Pavilion Directory
ISC 2013 korea Pavilion DirectoryISC 2013 korea Pavilion Directory
ISC 2013 korea Pavilion DirectoryCindy Moon
 

Viewers also liked (20)

Infographic Plagtracker.com
Infographic Plagtracker.comInfographic Plagtracker.com
Infographic Plagtracker.com
 
Presentation for 350.org Volunteer Social Media Team
Presentation for 350.org Volunteer Social Media TeamPresentation for 350.org Volunteer Social Media Team
Presentation for 350.org Volunteer Social Media Team
 
The Greatist Story
The Greatist StoryThe Greatist Story
The Greatist Story
 
Seminar on social strategies in action:Driving Business Transformation
Seminar on social strategies in action:Driving Business TransformationSeminar on social strategies in action:Driving Business Transformation
Seminar on social strategies in action:Driving Business Transformation
 
2012 Education Job Market Report - Monster.com
2012 Education Job Market Report - Monster.com2012 Education Job Market Report - Monster.com
2012 Education Job Market Report - Monster.com
 
Uk oil output 50 percent higher by 2018
Uk oil output 50 percent higher by 2018Uk oil output 50 percent higher by 2018
Uk oil output 50 percent higher by 2018
 
AF spouse newsletter - Oct & Nov 2012
AF spouse newsletter - Oct & Nov 2012AF spouse newsletter - Oct & Nov 2012
AF spouse newsletter - Oct & Nov 2012
 
Lids up or lids down? Jennie Osborn and Natasha Taylor
Lids up or lids down? Jennie Osborn and Natasha TaylorLids up or lids down? Jennie Osborn and Natasha Taylor
Lids up or lids down? Jennie Osborn and Natasha Taylor
 
Amazon global selling manual modfied by spainbox with specific information to...
Amazon global selling manual modfied by spainbox with specific information to...Amazon global selling manual modfied by spainbox with specific information to...
Amazon global selling manual modfied by spainbox with specific information to...
 
Write That Down! Van Wilder's Guide to Social Media
Write That Down!  Van Wilder's Guide to Social MediaWrite That Down!  Van Wilder's Guide to Social Media
Write That Down! Van Wilder's Guide to Social Media
 
The Social Media Roi Cookbook
The Social Media Roi CookbookThe Social Media Roi Cookbook
The Social Media Roi Cookbook
 
Razor social social media tools guide
Razor social social media tools guideRazor social social media tools guide
Razor social social media tools guide
 
2011 04 08 this week in mcfp april 8, 2011 (1)
2011 04 08  this week in mcfp april 8,  2011 (1)2011 04 08  this week in mcfp april 8,  2011 (1)
2011 04 08 this week in mcfp april 8, 2011 (1)
 
WebLion Hosting: Leveraging Laziness, Impatience, and Hubris
WebLion Hosting: Leveraging Laziness, Impatience, and HubrisWebLion Hosting: Leveraging Laziness, Impatience, and Hubris
WebLion Hosting: Leveraging Laziness, Impatience, and Hubris
 
International Programs vol.7
International Programs vol.7International Programs vol.7
International Programs vol.7
 
Mountaineer 2013 08-16
Mountaineer 2013 08-16Mountaineer 2013 08-16
Mountaineer 2013 08-16
 
Mobile Security - Hakin9 Magazine
Mobile Security - Hakin9 MagazineMobile Security - Hakin9 Magazine
Mobile Security - Hakin9 Magazine
 
Mountaineer 2013 04-19
Mountaineer 2013 04-19Mountaineer 2013 04-19
Mountaineer 2013 04-19
 
In The Zone - January 2014
In The Zone - January 2014In The Zone - January 2014
In The Zone - January 2014
 
ISC 2013 korea Pavilion Directory
ISC 2013 korea Pavilion DirectoryISC 2013 korea Pavilion Directory
ISC 2013 korea Pavilion Directory
 

Similar to Sencha Touch

Ext js saas&compass
Ext js saas&compassExt js saas&compass
Ext js saas&compasselitonweb
 
Sass - Making CSS fun again.
Sass - Making CSS fun again.Sass - Making CSS fun again.
Sass - Making CSS fun again.Gabriel Neutzling
 
CSS: A Slippery Slope to the Backend
CSS: A Slippery Slope to the BackendCSS: A Slippery Slope to the Backend
CSS: A Slippery Slope to the BackendFITC
 
Doing more with LESS
Doing more with LESSDoing more with LESS
Doing more with LESSjsmith92
 
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)Adam Darowski
 
Software programming tools for creating/managing CSS files
Software programming tools for creating/managing CSS filesSoftware programming tools for creating/managing CSS files
Software programming tools for creating/managing CSS filesDinu Suman
 
Work and play with SASS & Compass
Work and play with SASS & CompassWork and play with SASS & Compass
Work and play with SASS & CompassAndreas Dantz
 
Sass & Compass (Barcamp Stuttgart 2012)
Sass & Compass (Barcamp Stuttgart 2012)Sass & Compass (Barcamp Stuttgart 2012)
Sass & Compass (Barcamp Stuttgart 2012)emrox
 
The Near Future of CSS
The Near Future of CSSThe Near Future of CSS
The Near Future of CSSRachel Andrew
 
CSS3 Takes on the World
CSS3 Takes on the WorldCSS3 Takes on the World
CSS3 Takes on the WorldJonathan Snook
 
A mobile web app for Android in 75 minutes
A mobile web app for Android in 75 minutesA mobile web app for Android in 75 minutes
A mobile web app for Android in 75 minutesJames Pearce
 
Wrangling the CSS Beast with Sass
Wrangling the CSS Beast  with SassWrangling the CSS Beast  with Sass
Wrangling the CSS Beast with SassRob Friesel
 
Preprocessor presentation
Preprocessor presentationPreprocessor presentation
Preprocessor presentationMario Noble
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applicationselliando dias
 
Mobile-first OOCSS, Sass & Compass at BBC Responsive News
Mobile-first OOCSS, Sass & Compass at BBC Responsive NewsMobile-first OOCSS, Sass & Compass at BBC Responsive News
Mobile-first OOCSS, Sass & Compass at BBC Responsive NewsKaelig Deloumeau-Prigent
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Chris Alfano
 
LESS : The dynamic stylesheet language
LESS : The dynamic stylesheet languageLESS : The dynamic stylesheet language
LESS : The dynamic stylesheet languageKatsunori Tanaka
 

Similar to Sencha Touch (20)

Ext js saas&compass
Ext js saas&compassExt js saas&compass
Ext js saas&compass
 
Sass - Making CSS fun again.
Sass - Making CSS fun again.Sass - Making CSS fun again.
Sass - Making CSS fun again.
 
CSS: A Slippery Slope to the Backend
CSS: A Slippery Slope to the BackendCSS: A Slippery Slope to the Backend
CSS: A Slippery Slope to the Backend
 
Doing more with LESS
Doing more with LESSDoing more with LESS
Doing more with LESS
 
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)
 
Software programming tools for creating/managing CSS files
Software programming tools for creating/managing CSS filesSoftware programming tools for creating/managing CSS files
Software programming tools for creating/managing CSS files
 
FCIP SASS Talk
FCIP SASS TalkFCIP SASS Talk
FCIP SASS Talk
 
Work and play with SASS & Compass
Work and play with SASS & CompassWork and play with SASS & Compass
Work and play with SASS & Compass
 
Sass & Compass (Barcamp Stuttgart 2012)
Sass & Compass (Barcamp Stuttgart 2012)Sass & Compass (Barcamp Stuttgart 2012)
Sass & Compass (Barcamp Stuttgart 2012)
 
The Near Future of CSS
The Near Future of CSSThe Near Future of CSS
The Near Future of CSS
 
Accelerated Stylesheets
Accelerated StylesheetsAccelerated Stylesheets
Accelerated Stylesheets
 
CSS3 Takes on the World
CSS3 Takes on the WorldCSS3 Takes on the World
CSS3 Takes on the World
 
A mobile web app for Android in 75 minutes
A mobile web app for Android in 75 minutesA mobile web app for Android in 75 minutes
A mobile web app for Android in 75 minutes
 
Wrangling the CSS Beast with Sass
Wrangling the CSS Beast  with SassWrangling the CSS Beast  with Sass
Wrangling the CSS Beast with Sass
 
Preprocessor presentation
Preprocessor presentationPreprocessor presentation
Preprocessor presentation
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
CSS Extenders
CSS ExtendersCSS Extenders
CSS Extenders
 
Mobile-first OOCSS, Sass & Compass at BBC Responsive News
Mobile-first OOCSS, Sass & Compass at BBC Responsive NewsMobile-first OOCSS, Sass & Compass at BBC Responsive News
Mobile-first OOCSS, Sass & Compass at BBC Responsive News
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
 
LESS : The dynamic stylesheet language
LESS : The dynamic stylesheet languageLESS : The dynamic stylesheet language
LESS : The dynamic stylesheet language
 

More from Craig Walker

Cloud Xero #1 - Intro to Cloud Computing
Cloud Xero #1 - Intro to Cloud ComputingCloud Xero #1 - Intro to Cloud Computing
Cloud Xero #1 - Intro to Cloud ComputingCraig Walker
 
Wellington to the World 2010 Keynote
Wellington to the World 2010 KeynoteWellington to the World 2010 Keynote
Wellington to the World 2010 KeynoteCraig Walker
 
Building Faster Websites
Building Faster WebsitesBuilding Faster Websites
Building Faster WebsitesCraig Walker
 
Ensuring Full Proof Security At Xero
Ensuring Full Proof Security At XeroEnsuring Full Proof Security At Xero
Ensuring Full Proof Security At XeroCraig Walker
 
Client Side Performance @ Xero
Client Side Performance @ XeroClient Side Performance @ Xero
Client Side Performance @ XeroCraig Walker
 

More from Craig Walker (6)

Cloud Xero #1 - Intro to Cloud Computing
Cloud Xero #1 - Intro to Cloud ComputingCloud Xero #1 - Intro to Cloud Computing
Cloud Xero #1 - Intro to Cloud Computing
 
Sencha At Xero
Sencha At XeroSencha At Xero
Sencha At Xero
 
Wellington to the World 2010 Keynote
Wellington to the World 2010 KeynoteWellington to the World 2010 Keynote
Wellington to the World 2010 Keynote
 
Building Faster Websites
Building Faster WebsitesBuilding Faster Websites
Building Faster Websites
 
Ensuring Full Proof Security At Xero
Ensuring Full Proof Security At XeroEnsuring Full Proof Security At Xero
Ensuring Full Proof Security At Xero
 
Client Side Performance @ Xero
Client Side Performance @ XeroClient Side Performance @ Xero
Client Side Performance @ Xero
 

Recently uploaded

Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsPrecisely
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 

Recently uploaded (20)

Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power Systems
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 

Sencha Touch

  • 1. Craig Walker, Chief Technology Officer www.xero.com
  • 2. Craig Walker, Chief Technology Officer www.xero.com
  • 4.
  • 5.
  • 6.
  • 8. BlackBerry 6 2nd half 2011
  • 9. Lots of frameworks… • Zepto.js • DynamicX • SproutCore • XUI • Appcelerator • iUI • iWebKit • jQuery Mobile • jQTouch • And lots more…
  • 11. What is Sencha Touch? A JavaScript framework for building rich mobile applications
  • 12. Why Sencha Touch? • Cross-platform • Looks native, feels native • Faster, cheaper, easier to build with • Highly customisable • Flexible deployment • HTML5/CSS3 goodness
  • 13. Yes - but WHY Sencha Touch?
  • 15. Touch Event Manager • Built on native events • Abstracted for performance • Multi-touch & gesture support
  • 16. Touch Event Manager Ext.fly("el").on({ tap: function() { alert("You tapped me"); }, pinch: function() { alert("You pinched me"); }, swipe: function() { alert("Stop touching me...") } }); 28
  • 17.
  • 18. Scroll Event Manager • Scrolling with momentum & bounce physics • Native & natural • Hardware accelerated
  • 23. Lists
  • 27. Maps
  • 29. Layouts • Container layout specifies how its children components are rendered
  • 30. fit
  • 31. card
  • 32. vbox
  • 33. hbox
  • 34. MVC Routes Controllers Models Views Stores
  • 35. Theming • SASS & Compass – sass-lang.com – compass-style.org • CSS3 is awesome – SCSS is awesomer
  • 36. SCSS CSS $blue: #3bbfce; /* line 5, variables.scss */ $margin: 16px; .example1 { $padding: 4px; border-color: #3bbfce; } .example1 { border-color: $blue; /* line 9, variables.scss */ } .example2 { margin: 16px; .example2 { color: #3bbfce; margin: $margin; } color: $blue; } /* line 14, variables.scss */ .example3 { .example3 { margin: 32px; margin: ($margin / 2px) * $padding; } }
  • 37. SCSS CSS @mixin add-child($color) { /* line 18, mixins.scss */ color: $color; .example { background-color: lighten($color, 50); color: red; background-color: white; .child { } padding: 5px; /* line 5, mixins.scss */ .example .child { &:first { padding: 5px; background-color: darken($color, 10) } }; /* line 8, mixins.scss */ .example .child:first { span { background-color: #cc0000; color: mix($color, blue); } } /* line 12, mixins.scss */ } .example .child span { } color: #7f007f; } .example { @include add-child(#F00); }
  • 38. SCSS CSS @import "compass"; /* line 5, gradients.scss */ .button { $width: 100px; width: 100px; } .button { /* line 8, gradients.scss */ width: $width; .button .round { -moz-border-radius: 5px; .round { -webkit-border-radius: 5px; @include border-radius(5px); -o-border-radius: 5px; } -ms-border-radius: 5px; -khtml-border-radius: 5px; .linear { border-radius: 5px; @include linear-gradient( } color-stops(white, #c39 30%, /* line 12, gradients.scss */ #b7f 70%, #aaa) .button .linear { ); background-image: -webkit-gradient( } linear, 0% 0%, 0% 100%, } color-stop(0%, #ffffff), color-stop(50%, #cc3399), color-stop(100%, #bb77ff)); background-image: -moz-linear-gradient(top, #ffffff 0%, #cc3399 50%, #bb77ff 100%); background-image: linear-gradient(top, #ffffff 0%, #cc3399 50%, #bb77ff 100%); }
  • 39. Let’s look at some code...
  • 40. Demo: From Desktop to Mobile
  • 41. index.html <!doctype html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Xero Help</title> <link rel="stylesheet" href="resources/css/xerohelp.css" type="text/css"> </head> <body> <script type="text/javascript" src="lib/sencha-touch-debug.js"></script> <script type="text/javascript" src="app/xerohelp.js"></script> </body> </html>
  • 42. app/xerohelp.js // utils document.write('<script type="text/javascript" src="app/utils/string.js"></script>'); // application document.write('<script type="text/javascript" src="app/routes.js"></script>'); document.write('<script type="text/javascript" src="app/app.js"></script>'); // models document.write('<script type="text/javascript" src="app/models/TOC.js"></script>'); document.write('<script type="text/javascript" src="app/models/HelpFile.js"></script>'); // views document.write('<script type="text/javascript" src="app/views/Viewport.js"></script>'); document.write('<script type="text/javascript" src="app/views/TOCPanel.js"></script>'); document.write('<script type="text/javascript" src="app/views/HelpCarousel.js"></script>'); document.write('<script type="text/javascript" src="app/views/HelpPanel.js"></script>'); // controllers document.write('<script type="text/javascript" src="app/controllers/help.js"></script>');
  • 43. app/routes.js Ext.Router.draw(function(map) { map.connect("/help/home", {controller: 'help', action: 'home'}); map.connect("/help/:id", {controller: 'help', action: 'show'}); });
  • 44. app/app.js Ext.regApplication({ name: "XERO", defaultUrl: '/help/home', defaultTarget: "viewport", icon: 'resources/images/icon.png', glossOnIcon: false, region: "NZ", apiUrl: "http://help.stage.xero.com/api", launch: function() { this.viewport = new XERO.Viewport({ application: this }); } });
  • 45. XERO.Viewport = Ext.extend(Ext.Panel, { id: 'viewport', app/views/viewport.js layout: 'card', fullscreen: true, initComponent: function() { Ext.apply(this, { dockedItems: [{ xtype: "toolbar", dock : "top", title: "Help Center", itemId: "help-toolbar" },{ xtype: "toolbar", dock: "bottom", items: [{ xtype: "button", text: "Index", handler: this.onTOCButtonTap, scope: this },{ xtype: "spacer" }, { xtype: "button", text: "Switch Region", handler: this.onSwitchRegionTap, scope: this }] }] }); XERO.Viewport.superclass.initComponent.apply(this, arguments); }, ...
  • 46. setTitle: function(title) { this.down("#help-toolbar").setTitle(title); }, app/views/viewport.js onTOCButtonTap: function() { if(! this.tocPanel) { this.tocPanel = Ext.create({ xtype: "tocpanel" }); } this.tocPanel.show(); }, onSwitchRegionTap: function() { if(! this.regionPicker) { this.regionPicker = new Ext.Picker({ slots: [{ name : 'region', title: 'Switch Region', data : [ {text: 'New Zealand', value: "NZ"}, {text: 'Australia', value: "AUS"}, {text: 'United Kingdom', value: "UK"}, {text: 'Global', value: "INT"} ] }] }); } this.regionPicker.show(); } });
  • 47. app/controllers/help.js Ext.regController("help", { home: function(request) { this.show(Ext.apply(request, { id: "home" })); }, show: function(request) { if(! this.helpCarousel) { this.helpCarousel = this.render({ xtype: 'helpcarousel' }); } XERO.viewport.setActiveItem(this.helpCarousel); XERO.viewport.setTitle("Loading..."); this.helpCarousel.loadHelpPage(request.id, request.historyUrl); } });
  • 48. app/models/helpfile.js Ext.regModel("HelpFile", { fields: [ { name: "id", type: "int" }, "abstractText", "body", "heading", "helpPage", { name: "createdDateUTC", type: "date", format: "M$" }, { name: "success", type: "boolean" } ] /*, validations: [ { type: "presence", field: "helpPage" } ], hasMany: [ { model: "Region", name: "regions" } ] */ });
  • 49. app/models/toc.js Ext.regModel("TOC", { fields: [ "id", "helpPage", "href", "text" ], proxy: { type: 'scripttag', url: String.format("{0}/toc/", XERO.apiUrl), reader: { type: "tree", root: "items" } } }); (function() { new Ext.data.TreeStore({ storeId: "TOCStore", model: "TOC", autoLoad: true }); }());
  • 50. XERO.views.HelpCarousel = Ext.extend(Ext.Carousel, { cls: "cards", app/views/helpcarousel.js layout: "fit", initComponent: function() { XERO.views.HelpCarousel.superclass.initComponent.apply(this, arguments); }, onRender: function() { XERO.views.HelpCarousel.superclass.onRender.apply(this, arguments); if(this.el) { this.mon(this.el, { tap: this.onTap, click: Ext.emptyFn, delegate: "a", stopEvent: true, scope: this }); this.mon(this, { cardswitch: function() { this.onHelpSwitch(this.getActiveItem().helpPage); }, scope: this }); } },
  • 51. loadHelpPage: function(id, href) { var bookmark; app/views/helpcarousel.js if(href.indexOf("$") != -1) { bookmark = href.right(href.length - href.indexOf("$") - 1); } var item = this.getComponent(id); if(item) { this.setActiveItem(item); if(bookmark){ item.scrollToBookmark(bookmark); } } else { var panel = this.add({ xtype: "helppanel", id: id, goToBookmark: bookmark, listeners: { helploaded: this.onHelpSwitch, single: true, scope: this } }); this.doComponentLayout(); this.setActiveItem(panel); } },
  • 52. onTap: function(e, target) { var id = target.getAttribute('xero:id'), app/views/helpcarousel.js type = target.getAttribute('xero:type'), bookmark = target.getAttribute('xero:bookmark'), url = target.getAttribute('xero:path'); if(type && type.toLowerCase() == "help") { if(bookmark) { this.getActiveItem().scrollToBookmark(bookmark); } else { Ext.dispatch({ controller: "help", action: "show", id: id, historyUrl: target.href }); } } else { if(target.href.toLowerCase().startsWith("mailto:")) { location.href = target.href; } else { window.open(target.href); } } } }); Ext.reg('helpcarousel', XERO.views.HelpCarousel);
  • 53. app/views/helppanel.js XERO.views.HelpPanel = Ext.extend(Ext.Panel, { cls: "help-panel", layout: "fit", scroll: "vertical", styleHtmlContent: true, goToBookmark: null, html: '<div class="loading-indicator"> </div>', initComponent: function() { this.addEvents("helploaded"); XERO.views.HelpPanel.superclass.initComponent.apply(this, arguments); }, onRender: function() { XERO.views.HelpPanel.superclass.onRender.apply(this, arguments); this.loadHelpPage(); },...
  • 54. loadHelpPage: function() { Ext.util.JSONP.request({ url: String.format("{0}/help/", XERO.apiUrl), app/views/helppanel.js callbackKey: "callback", params: { helpPage: this.id }, callback: function(doc) { this.helpPage = doc; this.title = doc.heading; this.update(this.helpPage.body); if(this.goToBookmark) { this.scrollToBookmark(this.goToBookmark); } this.fireEvent("helploaded", this.helpPage); }, scope: this }); }, scrollToBookmark: function(bookmark) { var el = this.getEl().down(String.format('a[name="{0}"]', bookmark)); if (el) { this.scrollIntoView(el); } }, }); Ext.reg('helppanel', XERO.views.HelpPanel);
  • 55. XERO.views.TOCPanel = Ext.extend(Ext.NestedList, { title: "Index", showAnimation: { app/views/helppanel.js type: "slide", direction: "up" }, floating: true, initComponent: function() { this.store = Ext.getStore("TOCStore"); this.toolbar = {...}; XERO.views.TOCPanel.superclass.initComponent.apply(this, arguments); this.mon(this, { selectionchange: function(list, selection) { var record = selection[0]; if(record.get("leaf") === true) { Ext.dispatch({ controller: "help", action: "show", id: record.get("helpPage"), historyUrl: String.format("/help/{0}", record.get("helpPage")) }); this.hide(); } }, scope: this }); } });
  • 58. Cross-platform • Open source • Extensible • Instantiates chromeless web view • Adds JavaScript access to native APIs
  • 60. Native APIs • Device identification • Network access • Sensors • Camera/image sources • Contacts • File access
  • 61. Everything else? • HTML for layout • JavaScript for accessing device APIs • CSS for look & feel • Offline storage for standalone clients • Ajax, JSONP for syncing to the cloud – Runs on file:// protocol which is exempt from same-origin policy • Just use Sencha Touch!
  • 64. Tools • Browsers – Safari the best (unfortunately) • Web Inspector • RemoteJS (Android debugging) • Souders’ bookmarklets – stevesouders.com/mobileperf • Jdrop – jdrop.org
  • 65. Object-oriented • Use namespaces to define your library • Define components – code for reusability • Extend first, write plugins second (not at all if possible)
  • 66. Events rock! • Use events to communicate between components • Use event delegation
  • 67. Override appropriately • Do not edit the library files • DO NOT EDIT THE LIBRARY FILES! • Use an overrides file if you need to override the framework • Do the same with CSS (but you should be using cls, ui properties)
  • 68. Define a directory structure • Break your code into small files • Use build tools to compile for performance • Use sencha-touch-debug.js during dev (but never prod!) • Keep the framework up-to-date – upgrade as often as you can
  • 69. Worry about performance • Understand client-side performance rules & use them • Latency bad • JIT compilers – compilation time relates to size of file the method exists in • Keep DOM light • Destroy components that aren’t visible • concatenate, minify, compress!
  • 70. Theming/Layouts • Use SCSS • Remove unnecessary CSS by only including required SCSS mixins • Understand XTemplate • Understand doComponentLayout
  • 71. Sencha.com Read the forums Read the docs Read the source!
  • 72. Any questions? www.xero.com