danvega
19 Jul 2010, 12:53 PM
I am writing what I would think to be a typical web based mobile application and I am still running into some issues. I would like to post an example here and then ask a few questions about the structure and point out some of the bugs. Any advice you can give would be really helpful as I need to finish this app this week. By the way this is an application for a conference.
The first part of the application is my main "application.js" and it the entry point for my app. Here i set up a toolbar and a pretty basic tab layout with a bottom toolbar. This is pretty much just like the tabs2 example and gives us a good starting point for our app.
Ext.ns("cfu","cfu.ui");
Ext.setup({
tabletStartupScreen: 'assets/images/tablet_startup.png',
phoneStartupScreen: 'assets/images/phone_startup.png',
icon: 'assets/images/icon.png',
glossOnIcon: false,
onReady: function() {
var titlebar = new Ext.Toolbar({
id:'app-titlebar',
dock:'top'
});
var tp = new Ext.TabPanel({
fullscreen:true,
ui:'light',
dockedItems:[titlebar],
layout: 'card',
activeItem: 0,
animation:{
type:'slide',
cover:true
},
tabBar: {
centered:true,
dock:'bottom',
layout: {pack:'center'}
},
defaults:{
scroll:'vertical'
},
listeners: {
afterlayout : function() {
titlebar.setTitle(this.layout.activeItem.title);
},
cardswitch: function(card) {
titlebar.setTitle(card.title);
}
},
items:[
{
xtype:'schedule',
iconCls:'time'
},
{
xtype:'topics',
iconCls:'bookmarks'
},
{
xtype:'speakers',
iconCls:'team'
},
{
xtype:'twitter',
iconCls:'info'
},
{
title:'About',
iconCls:'info'
}
]
});
}
});
You will see the 1st item in the items array is schedule. Below is the code for our schedule component. It has 4 buttons at the top for the different days of the conference. When you click the day the main panel is updated with the data. I also have an active listener so that when this component is active we can auto load our first days data. When you click on a list item the detail card is shown.
cfu.ui.Schedule = Ext.extend(Ext.Container,{
title:'Schedule',
layout:'card',
// called during component initialization
initComponent : function(){
var titlebar = Ext.getCmp('app-titlebar');
Ext.regModel('Schedule', {
fields: ['start','topic']
}),
this.sb = new Ext.SplitButton({
defaults:{
handler:this.loadData
},
centered:true,
items:[
{xtype:'button',id:'wednesday',text:'Wed'},
{xtype:'button',id:'thursday',text:'Thur'},
{xtype:'button',id:'friday',text:'Fri'},
{xtype:'button',id:'saturday',text:'Sat'}
]
});
// list of sessions
this.sessions = new Ext.List({
id:'sessionList',
tpl: '<tpl for="."><div class="schedule"><strong>{start}</strong> {topic}</div></tpl>',
itemSelector: 'div.schedule',
singleSelect: true,
scroll:'vertical',
store: new Ext.data.Store({
model: 'Schedule',
groupField: 'start',
getGroupString: function(record){
return record.get('start')[0];
}
}),
listeners: {
itemtap: function(view, index, item, e){
var rec = view.store.getAt(index);
main.setCard(1)
detail.update({
start: rec.get('start'),
topic: rec.get('topic')
});
}
}
});
// detail card
var detail = new Ext.Panel({
tpl: '<tpl for=".">Topic: {topic}</tpl>',
listeners: {
activate:function(){
titlebar.add({
id:'btnBack',
xtype:'button',
text: 'Back',
handler: function(){
main.setCard(0);
}
});
titlebar.doLayout();
},
deactivate : function(){
titlebar.remove('btnBack');
titlebar.doLayout();
}
}
});
var main = new Ext.Container({
fullscreen:true,
layout: 'card',
items: [
{
xtype:'container',
items:[this.sb,this.sessions]
},
detail
]
});
this.items = [main];
// the components superclass
cfu.ui.Schedule.superclass.initComponent.apply(this,arguments);
// events
main.on('activate', this.onActivate, this);
},
onActivate: function(){
this.sb.setActive('wednesday');
this.loadData({id:'wednesday'});
},
/*
* Change handler for our split button
* When the day changes this method will load the correct schedule into our list
*/
loadData: function(b,e){
Ext.getBody().mask(false, '<div class="loading">Loading…</div>');
var dURL = 'data/' + b.id + '.txt';
Ext.Ajax.request({
url: dURL,//replace with AJAX call
success: function(response, opts) {
Ext.getBody().unmask();
result = JSON.parse(response.responseText);
var item = result.items;
if (item) {
Ext.getCmp('sessionList').getStore().loadData(item);
}
else {
alert('There was an error retrieving the list.');
}
},
failure: function(response, opts){
Ext.getBody().unmask();
}
});
}
});
Ext.reg('schedule',cfu.ui.Schedule);
There are so many issues with just this piece but here are some thoughts
- The list does not scroll properly. It starts to scroll but it basically snaps back the list. I am not sure what causes this
- Why is my onActivate() method being called 2x ?
- Is this the way you typically layout a project?
- when i click the list item the text shows up for the new card but I still see the split button bar
- because there is a single title bar for the application I feel that its kind of hackish what I am doing here. I am getting the toolbar then adding a back button when the detail card is activated and then removing it manually.
I know this is a lot but I have basically hacked this together by going through the examples. Any help you can give me is much appreciated.
The first part of the application is my main "application.js" and it the entry point for my app. Here i set up a toolbar and a pretty basic tab layout with a bottom toolbar. This is pretty much just like the tabs2 example and gives us a good starting point for our app.
Ext.ns("cfu","cfu.ui");
Ext.setup({
tabletStartupScreen: 'assets/images/tablet_startup.png',
phoneStartupScreen: 'assets/images/phone_startup.png',
icon: 'assets/images/icon.png',
glossOnIcon: false,
onReady: function() {
var titlebar = new Ext.Toolbar({
id:'app-titlebar',
dock:'top'
});
var tp = new Ext.TabPanel({
fullscreen:true,
ui:'light',
dockedItems:[titlebar],
layout: 'card',
activeItem: 0,
animation:{
type:'slide',
cover:true
},
tabBar: {
centered:true,
dock:'bottom',
layout: {pack:'center'}
},
defaults:{
scroll:'vertical'
},
listeners: {
afterlayout : function() {
titlebar.setTitle(this.layout.activeItem.title);
},
cardswitch: function(card) {
titlebar.setTitle(card.title);
}
},
items:[
{
xtype:'schedule',
iconCls:'time'
},
{
xtype:'topics',
iconCls:'bookmarks'
},
{
xtype:'speakers',
iconCls:'team'
},
{
xtype:'twitter',
iconCls:'info'
},
{
title:'About',
iconCls:'info'
}
]
});
}
});
You will see the 1st item in the items array is schedule. Below is the code for our schedule component. It has 4 buttons at the top for the different days of the conference. When you click the day the main panel is updated with the data. I also have an active listener so that when this component is active we can auto load our first days data. When you click on a list item the detail card is shown.
cfu.ui.Schedule = Ext.extend(Ext.Container,{
title:'Schedule',
layout:'card',
// called during component initialization
initComponent : function(){
var titlebar = Ext.getCmp('app-titlebar');
Ext.regModel('Schedule', {
fields: ['start','topic']
}),
this.sb = new Ext.SplitButton({
defaults:{
handler:this.loadData
},
centered:true,
items:[
{xtype:'button',id:'wednesday',text:'Wed'},
{xtype:'button',id:'thursday',text:'Thur'},
{xtype:'button',id:'friday',text:'Fri'},
{xtype:'button',id:'saturday',text:'Sat'}
]
});
// list of sessions
this.sessions = new Ext.List({
id:'sessionList',
tpl: '<tpl for="."><div class="schedule"><strong>{start}</strong> {topic}</div></tpl>',
itemSelector: 'div.schedule',
singleSelect: true,
scroll:'vertical',
store: new Ext.data.Store({
model: 'Schedule',
groupField: 'start',
getGroupString: function(record){
return record.get('start')[0];
}
}),
listeners: {
itemtap: function(view, index, item, e){
var rec = view.store.getAt(index);
main.setCard(1)
detail.update({
start: rec.get('start'),
topic: rec.get('topic')
});
}
}
});
// detail card
var detail = new Ext.Panel({
tpl: '<tpl for=".">Topic: {topic}</tpl>',
listeners: {
activate:function(){
titlebar.add({
id:'btnBack',
xtype:'button',
text: 'Back',
handler: function(){
main.setCard(0);
}
});
titlebar.doLayout();
},
deactivate : function(){
titlebar.remove('btnBack');
titlebar.doLayout();
}
}
});
var main = new Ext.Container({
fullscreen:true,
layout: 'card',
items: [
{
xtype:'container',
items:[this.sb,this.sessions]
},
detail
]
});
this.items = [main];
// the components superclass
cfu.ui.Schedule.superclass.initComponent.apply(this,arguments);
// events
main.on('activate', this.onActivate, this);
},
onActivate: function(){
this.sb.setActive('wednesday');
this.loadData({id:'wednesday'});
},
/*
* Change handler for our split button
* When the day changes this method will load the correct schedule into our list
*/
loadData: function(b,e){
Ext.getBody().mask(false, '<div class="loading">Loading…</div>');
var dURL = 'data/' + b.id + '.txt';
Ext.Ajax.request({
url: dURL,//replace with AJAX call
success: function(response, opts) {
Ext.getBody().unmask();
result = JSON.parse(response.responseText);
var item = result.items;
if (item) {
Ext.getCmp('sessionList').getStore().loadData(item);
}
else {
alert('There was an error retrieving the list.');
}
},
failure: function(response, opts){
Ext.getBody().unmask();
}
});
}
});
Ext.reg('schedule',cfu.ui.Schedule);
There are so many issues with just this piece but here are some thoughts
- The list does not scroll properly. It starts to scroll but it basically snaps back the list. I am not sure what causes this
- Why is my onActivate() method being called 2x ?
- Is this the way you typically layout a project?
- when i click the list item the text shows up for the new card but I still see the split button bar
- because there is a single title bar for the application I feel that its kind of hackish what I am doing here. I am getting the toolbar then adding a back button when the detail card is activated and then removing it manually.
I know this is a lot but I have basically hacked this together by going through the examples. Any help you can give me is much appreciated.