Créer rapidement un prototype d’application HTML5 pour téléphones portable avec Sencha Touch.

Sencha Touch est un framework Javascript. Il dispose d’une bibliothèque riche pour mettre en place rapidement une application HTML5 orienté Single Page Application.

Nous avons utilisé Sencha Touch pour développer rapidement notre jeux de quizz pour le Devoxx France 2013. Il s’agissait d’expérimenter ce framework dans le cadre d’un développement court et au budget limité. Sencha répond à cette problématique en produisant des applications HTML5 utilisables sur une grande majorité des téléphones du marché sans développement spécifique pour chaque plateforme (mis à part un design spécifique pour les tablettes).

FastContestSenchaTouch

Points positifs :

Points négatifs :

  • fort couplage (l’application créée ne pourra se défaire de Sencha)
  • documentation pas très à jour
  • forte dépendance à webkit ( => ne supporte pas Firefox, Opera, IE ainsi que de nombreux autres navigateurs)

Installer Sencha

Pour développer une application HTML5 en utilisant Sencha, il est nécessaire de télécharger l’API Sencha Touch ainsi que l’application Sencha Cmd. Le premier permet à l’application de fonctionner tandis que le second permet de créer l’archétype de l’application et de fabriquer le paquet que l’on mettra en production (ne copier que les bibliothèques Sencha effectivement utilisées, minification du Javascript, …)

API Sencha

  1. Télécharger Sencha Touch (http://www.sencha.com/products/touch/download/)
  2. Dézipper et placer dans un serveur Apache (pour éviter les problèmes de Cross Domain, sinon lancer un navigateur en désactivant la sécurité pour tester votre application en développement).

Sencha Cmd

  1. Télécharger Sencha Cmd (http://www.sencha.com/products/sencha-cmd/download)
  2. Installer (répertoire par défaut : ~/bin/Sencha)

Créer une application de type HelloWorld

Plutôt que de présenter l’application utilisée lors du Devoxx, on commencera par mettre au point une simple application.

Pour générer l’archétype de l’application, il faut créer un dossier portant le nom de l’application (ex : myapp) et lancer la commande idoine :

~\Desktop\blog\touch-2.1.1>mkdir myapp
~\Desktop\blog\touch-2.1.1>cd myapp
~\Desktop\blog\touch-2.1.1\myapp>sencha generate app myapp ../myapp

Maintenant le dossier « myapp » contient un projet Sencha. Quelques explications sur les ressources créés :

  • le fichier app.js est le point d’entrée de l’application
  • le dossier app contient les différentes classes javascript du projet,
  • le dossier ressources contient les éléments externes (icones, libs…)
  • le dossier touch contient un sous-ensemble de l’API

Développer

Nous vous proposons maintenant de créer une application Sencha. Plutôt que de vous donner le code de notre jeux de quizz, nous allons créer une application plus simple qui permet de lister des pizzas et de voir leurs ingrédients.

Sencha repose sur un framework MVC et il propose des classes que l’on peut étendre : Ext.data.Model, Ext.dataview.List, Ext.Panel, …

Nous allons débuter par décrire le modèle de donnée : ici nos pizzas et leurs ingrédients. Une relation « One to Many » relient les pizzas à leurs ingrédients, sachant qu’un ingrédient ne peut se trouver plus d ‘une fois dans une pizza.

myapp/app/model/ingredient.js

Ext.define('myapp.model.Ingredient', {
  extend: 'Ext.data.Model',
  config: {
    fields: [
     {name: 'name'}
    ]
  }
});

myapp/app/model/pizza.js

Ext.define('myapp.model.Pizza', {
  extend: 'Ext.data.Model',
  uses: ['myapp.model.Ingredient'],
  config: {
    fields: [
      {name: 'name'}
    ],
    hasMany: {
      model: 'myapp.model.Ingredient',
      name: 'ingredients'
    }
  }
});

Nous allons maintenant implémenter un store de pizzas. Un store permet de gérer les données, de lire ou de sauvegarder depuis une source locale (json, xml) ou distante (ajax, jsonp, …). Dans notre cas, on lira des données directement écrites dans le code.

myapp/app/store/menu.js

Ext.define('myapp.store.Menu', {
  extend: 'Ext.data.Store',
  requires: ['myapp.model.Pizza'],
  config: {
    model: 'myapp.model.Pizza',
    storeId: 'Menu',
    autoLoad: true,
    data: [
      {
        name: 'marguerita',
        ingredients:[
          {name: 'Tomato'},
          {name: 'Cheese'},
          {name: 'Olives'}
        ]
      }
    ]
  }
});

Les vues de l’application sont la liste des pizzas et une fenêtre qui s’ouvre lors de la sélection d’une pizza pour afficher les ingrédients

myapp/app/view/MenuList.js

Ext.define('myapp.view.MenuList', {
  extend: 'Ext.dataview.List',
  requires: ['myapp.store.Menu'],
  origin: 'menu', //custom identifier for the controller pizzaiolo
  config: {
    store: 'Menu',
    itemTpl: [
      '<div>{name}</div>'
    ]
  }
});

myapp/app/view/ingredientsListOverlay.js

Ext.define('myapp.view.IngredientsListOverlay', {
  extend: 'Ext.Panel',
  alias: 'widget.ingredientsListOverlay',
  config: {
    centered: true,
    height: 200,
    width: 200,
    modal: true,
    items: [
      {html: '<h3>Ingredients</h3>',styleHtmlContent: true}
    ]
  }
});

Nous allons maintenant implémenter un contrôleur qui gèrera l’affichage de la liste d’ingrédients quand une pizza est sélectionnée.

myapp/app/controller/pizzaiolo.js

Ext.define('myapp.controller.Pizzaiolo', {
  extend: 'Ext.app.Controller',
  requires: ['myapp.view.IngredientsListOverlay'],
  config: {
    control: {
      'list[origin=menu]': {
        itemtap: 'displayIngredients'
      }
    }
  },
  displayIngredients: function(list, index, target, record, e, eOpts){
    var menu = new myapp.store.Menu();
    overlay = Ext.widget('ingredientsListOverlay');
    Ext.Viewport.add(overlay);
    menu.getAt(index).ingredients().each(
      function(ingredient){
        overlay.insert(overlay.getItems().length,{html: ingredient.get("name")});
      }
    );
  }
});

Enfin, on modifie app.js pour qu’il charge le store et affiche la première vue (la liste de pizzas) au démarrage.

var menu = new myapp.store.Menu();
Ext.Viewport.add(Ext.create('myapp.view.MenuList'));