Ok

En poursuivant votre navigation sur ce site, vous acceptez l'utilisation de cookies. Ces derniers assurent le bon fonctionnement de nos services. En savoir plus.

« Mobile avec jQuery mobile | Page d'accueil | Utiliser Word pour blogger »

20 septembre 2011

Mobile avec Sencha Touch

Dans l'article précédent, je présente le cadre d'évaluation de plusieurs frameworks pour le développement d'application mobile. Cet article présente le détail pour Sencha Touch.

Sencha Touch est le plus évolué des frameworks que nous avons évalué. La qualité de finition des composants et le support avancé des gestes propres à un écran tactile en font un framework haut de gamme qui supporte des ambitions élevées. Cependant, cette richesse vient au prix d'une courbe d'apprentissage beaucoup plus importante, typique du développement d'application "desktop", plus que du web. Alors que les autres frameworks évalués capitalisaient sur une fondation HTML, Sencha touch est basé exclusivement sur du javascript. En effet, dans la page HTML de l'application, on ne trouve absolument rien dans le BODY, tout le DOM est créé dynamiquement au chargement de la page.

Contrairement aux autres, qui se limitent à l'interface, Sencha touch offre plus de support pour la portion de gestion des données.

Bien qu'il soit relativement facile de monter une petite application à partir des exemples et de la documentation très complète, la réalisation se heurte parfois à des écueils difficiles à passer. Peut-être la version 2 qui vient d'être publiée facilitera le travail.

A plus de 350 kb, Sencha touch à un chargement initial assez long, mais il répond très bien par la suite.

 arbrSenchaListe.png

 

arbrSenchaDetail.png

Voici le code pour l'application avec Sencha Touch:

 

<!DOCTYPE html>
<!-- Sencha touch ... -->
<html>
<head>
<title>Demo Sencha touch</title>
<%--
<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
<metacharset="utf-8"/>
<metaname="viewport"
    content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
<metaname="apple-touch-fullscreen"content="yes">
<metaname="apple-mobile-web-app-capable"content="yes"><!--this is buggy??!!-->
<metaname="apple-mobile-web-app-status-bar-style"content="black">
<linkrel="apple-touch-startup-image"href="../images/splash.png"/>
<linkrel="apple-touch-icon"href="../images/logo.png">
<linkrel="icon"type="image/ico"href="../images/logo.png">
--%>
<linkrel="stylesheet"
    href="${resource(dir:'css',file:'sencha-touch.css')}"/>
<scripttype="text/javascript"
    src="${resource(dir:'js',file:'sencha-touch.js')}">
    </script>
<script  type="text/javascript">
Ext.setup({
    tabletStartupScreen:'tablet_startup.png',
    phoneStartupScreen:'phone_startup.png',
    icon:'icon.png',
    glossOnIcon:false,        
 
    onReady:function(){
        Ext.regModel('Arbre',{
            fields:['nomLatin','nomFrancais','vignette','image','type','distance','distanceNumerique']
        });
        
        
        var store =new Ext.data.Store({
            model:'Arbre',
            sorters:'nomLatin',
            getGroupString :function(record){
                return record.get('nomLatin')[0];
            },
            data:[
                   <g:each in="${arbreInstanceList}" status="i"var="arbreInstance">
                     { nomLatin:"${fieldValue(bean: arbreInstance, field: "nomLatin")}",
                       nomFrancais:" ${fieldValue(bean: arbreInstance, field:"nomFrancais")}",
                       image:" ${fieldValue(bean: arbreInstance, field: "imageURL")}",
                       type:" ${fieldValue(bean: arbreInstance, field: "type")}",
                       distance:" ${fieldValue(bean: arbreInstance, field:"distanceMinimale")}",
                       distanceNumerique:" ${fieldValue(bean: arbreInstance, field:"distanceAsInteger")}",
                       vignette:" ${fieldValue(bean: arbreInstance, field:"vignetteURL")}"},
                  </g:each>                 
              ]
        });
        
 var sliderDistance =new Ext.form.Slider({
     width:300,
     value:14.0,
    increment:1.0,
    minValue:0,
    maxValue:15.0,
    label:'Distance',
    listeners:{
         change:function(slider, thumb,newValue){
              this.label ='changed!';
     
             console.log('slider changed to : '+newValue);
             store.filterBy(function(record,id){
                 var b =(record.data.distanceNumerique <= newValue);
                 return b;
                 })
         }
        }
});
 
 
 
        var detailToolbar =new Ext.Toolbar({
            height:66,
            items:[{
                text:'Liste',
                ui:'back',
                handler:function(){
                    corePanel.setActiveItem('listwrapper',{type:'slide', direction:'right'});
                }
              },
        
            {
                xtype:'spacer'   
            },
                sliderDistance
            ,
            {
                xtype:'checkboxfield',
                label:'Feuillus',
                width:150,
                listeners:{
                    check:function(self){
                        store.filter('type',' Feuillu');
                    },
                    uncheck:function(self){
                        store.clearFilter(false);
                    }
                }
                 },
            {
                xtype    :'textfield',
                name     :'field1',
                emptyText:'enter search term',
                listeners:{
                     keyUp:function(self, e){
                         console.log('field changed to : '+this.getValue());
                         var arr =new Array();
                         arr = document.getElementsByClassName('x-list-item');
                         for(var i =0; i < arr.length; i++){
                             var obj = document.getElementsByClassName('x-list-item').item(i);
                             if(obj.textContent
                                     .indexOf(this.getValue())==-1){
                                 obj.style.display ="none";
                             }else{
                                 obj.style.display ="block";
                             }
                         }
                     }
                    }
            }
            ]
        });
        
         var detailPanel =new Ext.Panel({
            id:'detailpanel',
            tpl:'<div class=detail>'+
                '<img src="{image}"/>'+
                '<p class=distance>{distance}</p>'+
                '<p>{type}</p>'+
                '<p class="lt">{nomLatin}</p>'+
                '<p>{nomFrancais}</p>'+
                '  </div>',
            dockedItems:[detailToolbar],
 
            afterRender:function(){
                this.mon(this.el,{
                    swipe:this.handleEvent,
                    
                });
            },
                    
            handleEvent:function(e){
                if(e.direction=='right'){
                    corePanel.setActiveItem('listwrapper',{type:'slide', direction:'right'});}
            }
 
        });
        
        var nestedList =new Ext.List({
             id:'indexlist',
            fullscreen:true,
            title:'Arbres',
            itemTpl:'<div class="arbre"><img class=inList src="{vignette}" /><p class="lt"> {nomLatin} </p><p class="fr">{nomFrancais}</p><p class="dist">{distance}</p></div>',
            grouped:true,
            indexBar:true,
            dock:'top',
            store: store,
            listeners:{
                  itemtap:function(record, index,item, e){
                      detailToolbar.setTitle(record.getStore().getAt(index).data.nomLatin);      
                    detailPanel.update(record.getStore().getAt(index).data);
                    corePanel.setActiveItem('detailpanel');
                    }
       },
            onItemDisclosure:function(record, btn, index){
                detailPanel.update(record.data);
                corePanel.setActiveItem('detailpanel');
                
            }
        });
 
        var listWrapper =new Ext.Panel({
            id:'listwrapper',
            layout:'fit',
            items:[nestedList],
            dockedItems:[
               detailToolbar
            ]
        });
 
        var btnSpecTop =[
<%--            { ui:'back', text:'Back'},--%>
<%--            { xtype:'spacer'},--%>
<%--            { ui:'default', text:'Login'}--%>
        ]// end btnSpecTop
 
 
        var tapHandler =function(btn, evt){
            alert("Button '"+ btn.text +"' tapped.");
        }        
 
        var windowHauteur = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight;
 
        var corePanel  =new Ext.Panel ({
            fullscreen:true,
            layout:'card',
            cardSwitchAnimation:'slide',
            items:[listWrapper,detailPanel]
            
        });
        
        var dockedItems =[{
            xtype:'toolbar',
            dock:'top',
            title:'Arbr',
            items: btnSpecTop,
            defaults:{ handler: tapHandler }
            },
            {
                xtype:'tabpanel',
               height: windowHauteur  -48,
                defaults:{
                    scroll:'vertical'
                },
               
                tabBar:{
                    dock:'bottom',
                    ui:'dark',
                    layout:{
                        pack:'center'
                    }
                },
                items:[{
                    title:'Liste',
                    iconCls:'home',
                    cls:'card card1',
                    badgeText:'',
                    items:[corePanel]
              
                },
                {
                    title:'Zone',
                    html:'<img src="http://www.hydroquebec.com/arbres/images/img_zones_rusticite.gif" class="fitToPort"></img>',
                    iconCls:'locate',
                    cls:'card card3',
                    
                },
                {
                    title:'Préférences',
                    html:'<p>test 3</p>',
                    iconCls:'settings',
                    cls:'card card3'
                }]
             
            }                
        ]
 
        var appPanel =new Ext.Panel({
            id:'appPanel',
            fullscreen:true,
            dockedItems: dockedItems            
        });
        
        
    }   // end onReady 
    });
</script>
<style>
.card3 {
    background-color:rgb(220,221,223);
    text-align:center;
    }
.fitToPort {
width:100%;}
.detail {
margin:1em;}
</style>
</head>
<body>
 
 
</body>
</html>

14:55 Publié dans Mobile | Lien permanent | Commentaires (0)