Code:
var pageFilterGame = {
xtype: 'panel',
title: 'Filter Games',
scrollable: true,
items: [
{
xtype: 'fieldset',
title: 'Filter games to find the perfect one',
instructions: 'Please fill in atleast one field to start.',
id: 'formFilterGames',
items: [
{
xtype: 'selectfield',
label: 'What enviroment will this game be played in',
options: [
{ text: 'Outside on Grass', value: 'grass' },
{ text: 'Outside on Concrete', value: 'concrete' },
{ text: 'Inside', value: 'inside' }
]
},
{
xtype: 'selectfield',
name: 'equipment',
label: 'What equipment do you have',
options: [{text: 'DB form'}]
},
{
xtype: 'numberfield',
name : 'Player Numbers',
label: 'How many players do you have',
minValue: 2,
maxValue: 50
},
{
xtype: 'numberfield',
name: 'avgname',
label: 'Average age of players',
minValue: 2,
maxValue: 99
},
{
xtype: 'selectfield',
label: 'Sort result by:',
options: [
{ text: 'Highest Rated', value: 'rated' },
{ text: 'Equipment', value: 'equipment' },
{ text: 'Alphabetically', value: 'alpha' }
]
},
],
},
{
xtype: 'toolbar',
docked: 'bottom',
items: [
{
text: 'Filter Games',
ui: 'confirm',
action: 'ucFilterGames'
},
{
text: 'View All Games',
ui: 'action',
action: 'ucGetAllGames'
},
]
}
]
};
var pageSearch = {
xtype: 'panel',
title: 'Search',
scrollable: true,
items: [
{
xtype: 'fieldset',
title: 'Search',
id: 'formSearch',
items: [
{
xtype: 'searchfield',
label: 'Search',
name: 'search'
}
]
},
{
xtype: 'toolbar',
docked: 'bottom',
items: [
{
text: 'Search',
ui: 'confirm',
action: 'ucSearchGames',
},
]
}
]
};
var pageProfileLogin = {
xtype: 'panel',
title: 'My Profile',
scrollable: true,
items: [
{
xtype: 'fieldset',
title: 'Please login to access your profile',
items: [
{
xtype: 'textfield',
name : 'username',
label: 'Username'
},
{
xtype: 'passwordfield',
name: 'password',
label: 'Password',
clearIcon: false
}
]
},
{
xtype: 'toolbar',
docked: 'bottom',
items: [
{
text: 'Login',
ui: 'confirm',
handler: function() {Ext.getCmp('navView').push(pageProfile);}
},
{
ui: 'action',
text: 'Create New',
handler: function() {Ext.getCmp('navView').push(pageNewProfile);}
}
]
}
]
};
var pageNewProfile = {
xtype: 'panel',
title: 'New Profile',
scrollable: true,
items: [
{
xtype: 'fieldset',
title: 'Please fill in the form to create your profile',
items: [
{
xtype: 'textfield',
name : 'username',
label: 'Username',
placeHolder: 'Sthir'
},
{
xtype: 'passwordfield',
name: 'password',
label: 'Password',
placeHolder: '123456',
clearIcon: false
},
{
xtype: 'textfield',
name : 'name',
label: 'Name',
placeHolder: 'Steven@sencha.com',
listeners: {
blur: function(thisTxt, eventObj) {
var val = thisTxt.getValue();
//validate using the pattern
if (val.search("/[0-9]/)") == -1)
Ext.Msg.alert("Error", "Invalid name!");
else
Ext.Msg.alert("Info", "Valid name!");
},
}
},
{
xtype: 'emailfield',
name : 'email',
label: 'Email',
placeHolder: 'you@sencha.com',
ClearIcon: true,
listeners: {
blur: function(thisTxt, eventObj) {
var val = thisTxt.getValue();
//validate using the pattern
if (val.search("[a-z]+@[a-z]+[.][a-z]+") == -1)
Ext.Msg.alert("Error", "Invalid e-mail address!");
else
Ext.Msg.alert("Info", "Valid e-mail address!");
},
},
},
],
},
{
xtype: 'toolbar',
docked: 'bottom',
items: [
{
text: 'Create Profile',
ui: 'confirm',
},
]
}
]
};
var pageProfile = {
xtype: 'tabpanel',
title: 'My Profile',
scrollable: true,
items: [
{
title: 'Edit Profile',
xtype: 'fieldset',
title: 'Welcome, you may edit your profile here.',
items: [
{
xtype: 'textfield',
name : 'username',
label: 'Username'
},
{
xtype: 'passwordfield',
name: 'password',
label: 'Password',
clearIcon: false
},
{
xtype: 'textfield',
name : 'name',
label: 'Name',
listeners: {
blur: function(thisTxt, eventObj) {
var val = thisTxt.getValue();
//validate using the pattern
if (val.search("/[0-9]/)") == -1)
Ext.Msg.alert("Error", "Invalid name!");
else
Ext.Msg.alert("Info", "Valid name!");
},
}
},
{
xtype: 'emailfield',
name : 'email',
label: 'Email',
placeHolder: 'you@getcreative.com',
ClearIcon: true,
listeners: {
blur: function(thisTxt, eventObj) {
var val = thisTxt.getValue();
//validate using the pattern
if (val.search("[a-z]+@[a-z]+[.][a-z]+") == -1)
Ext.Msg.alert("Error", "Invalid e-mail address!");
else
Ext.Msg.alert("Info", "Valid e-mail address!");
},
},
},
{
xtype: 'toolbar',
docked: 'bottom',
items: [
{
text: 'Save Profile',
ui: 'confirm',
},
{
text: 'Cancel Changes',
ui: 'action',
},
]
},
]
},
{
title: 'Favourites',
html: 'Below is a list of you favourite games!',
items: [
{
xtype: 'toolbar',
docked: 'bottom',
items: [
{
text: 'View Game',
ui: 'action',
},
{
text: 'Remove from Favourites',
ui: 'action',
},
]
}
]
},
{
title: 'Create a Game',
scrollable: true,
items: [
{
xtype: 'fieldset',
title: 'General Game Details',
instructions: 'Please fill in all fields.',
id: 'formCreateGames',
items: [
{
xtype: 'textfield',
label: 'What is your game called',
name: 'title',
placeHolder: 'Football',
},
{
xtype: 'textareafield',
label: 'Description',
name: 'description',
placeHolder: 'A short decription on how the game is played',
maxRows: 4
},
{
xtype: 'fieldset',
title: 'What enviroment will this game be played in',
items: [
{
xtype: 'checkboxfield',
name : 'grass',
label: 'Outside on Grass',
value: 'grass'
},
{
xtype: 'checkboxfield',
name : 'concrete',
label: 'Outside on Concrete',
value: 'concrete'
},
{
xtype: 'checkboxfield',
name : 'inside',
label: 'Inside',
value: 'inside'
}
]
},
{
xtype: 'selectfield',
name: 'equipment',
label: 'What equipment would you need',
options: [{text: 'DB form'}]
},
{
xtype: 'numberfield',
name : 'Player Numbers',
label: 'How many players could play (min)',
placeHolder: '2',
minValue: 2,
maxValue: 50
},
{
xtype: 'numberfield',
name : 'Player Numbers',
label: 'How many players could play (max)',
placeHolder: '10',
minValue: 2,
maxValue: 50
},
{
xtype: 'numberfield',
name: 'avgname',
label: 'Average age of players',
placeHolder: '14',
minValue: 2,
maxValue: 99
},
{
xtype: 'textfield',
label: 'link to image',
name: 'image',
placeHolder: 'www.sports.com/football.jpg',
},
],
},
{
xtype: 'toolbar',
docked: 'bottom',
items: [
{
text: 'Save',
ui: 'confirm',
},
]
}
]
}
]
};
var viewTabConfig = {
xtype: 'tabpanel',
styleHtmlContent: true,
title: 'Get Creative!',
items: [pageFilterGame, pageSearch, pageProfileLogin]
};
var viewDef = {
extend: 'Ext.NavigationView',
id: 'navView',
requires: [
'Ext.TitleBar',
'Ext.Video',
'Ext.field.Password',
'Ext.field.Select',
'Ext.field.Number',
'Ext.field.Search',
'Ext.field.Email',
'Ext.field.Checkbox',
'Ext.form.FieldSet',
'Ext.tab.Panel',
'Ext.data.Store',
'Ext.data.reader.Xml',
'Ext.navigation.Bar'
],
config: {
fullscreen: true,
items: [viewTabConfig],
model: 'Games'
}
};
Ext.define("a2.view.Main", viewDef);
Games.js
Code:
//
// The code in this function should now be familar to you. We have worked on this in Workshop 7. At this point, did you notice
// that Ext.jax.request() is an async call? When one makes an async call, your App can continue to respond to user inputs while waiting
// for the server response. This means that you need to be careful with how you code.
//
// One way to modify this into an sync call is to put a mask, and then wait for the success or failure event to fire.
//
function Search() {
//get the store and the value of the field
var value = field.getValue(),
store = Ext.getCmp('gamelist').getStore(); // getting the store that drives the contact list
//first clear any current filters on thes tore
store.clearFilter();
//check if a value is set first, as if it isnt we dont have to do anything
if (value) {
//the user could have entered spaces, so we must split them so we can loop through them all
var searches = value.split(' '),
regexps = [],
i;
//loop them all
for (i = 0; i < searches.length; i++) {
//if it is nothing, continue
if (!searches[i]) continue;
//if found, create a new regular expression which is case insenstive
regexps.push(new RegExp(searches[i], 'i'));
}
//now filter the store by passing a method
//the passed method will be called for each record in the store
store.filter(function(record) {
var matched = [];
//loop through each of the regular expressions
for (i = 0; i < regexps.length; i++) {
var search = regexps[i],
didMatch = record.get('title').match(search);
//if it matched the title, push it into the matches array
matched.push(didMatch);
} //if nothing was found, return false (dont so in the store)
if (regexps.length > 1 && matched.indexOf(false) != -1) {
return false;
} else {
//else true true (show in the store)
return matched[0];
}
});
}
};
/**
* Called when the user taps on the clear icon in the search field.
* It simply removes the filter form the store
*/
function SearchClear () {
//call the clearFilter method on the store instance
Ext.getCmp('gameList').getStore().clearFilter();
}
function searchGames() {
var form = Ext.getCmp('a2.views.main.formSearch');
var data = form.getValues();
Ext.Ajax.request({
url: 'getGames.php',
method: 'GET',
params: {
id: data.id
},
success: function(response) {
var obj = Ext.JSON.decode(response.responseText);
if(obj.success) {
var gamesList = Ext.create('Ext.List', {
fullscreen: true,
itemTpl: '{title}<br />{description}<br />Enviroment: {enviroment}<br />Equipment Needed: {equipment}<br />Min Players: {minPlayers} Max Players: {maxPlayers}<br /> Age: {age}<br />Link to image: {image}',
data: obj.games
});
Ext.getCmp('navView').push(gamesList);
}
else {
Ext.Msg.alert("Error!", "Cannot find a game in the database!");
}
}
});
}
function filterGrades() {
var form = Ext.getCmp('frmFilterGames');
var data = form.getValues();
Ext.Ajax.request({
url: 'getGames.php',
method: 'GET',
params: {
id: data.id
},
success: function(response) {
var obj = Ext.JSON.decode(response.responseText);
if(obj.success) {
var gamesList = Ext.create('Ext.List', {
fullscreen: true,
itemTpl: '{title}<br />{description}<br />Enviroment: {enviroment}<br />Equipment Needed: {equipment}<br />Min Players: {minPlayers} Max Players: {maxPlayers}<br /> Age: {age}<br />Link to image: {image}',
data: obj.games
});
Ext.getCmp('navView').push(gamesList);
}
else {
Ext.Msg.alert("Error!", "Cannot find a game in the database!");
}
}
});
}
function getGames() {
Ext.destroy(Ext.getCmp('frmGrades'));
//
// Strictly speaking, this part of the code is a view definition and should, by proper MVC coding, be placed in a
// separate file and done properly with Ext.define() so that when the controller needs it, it can just call Ext.define()
// here rather then what I am doing below.
//
var p = {
title: 'Grades',
xtype: 'formpanel',
id: 'frmGrades',
items: [
{
xtype: 'fieldset',
instructions: 'Enter your student ID and then tap button below.',
title: 'Get Grades',
items: [
{
xtype: 'textfield',
name: 'id',
label: 'Student ID',
}]
},
{
xtype: 'fieldset',
items: [
{
xtype: 'button',
ui: 'confirm',
action: 'ucRetrieveGrades',
text: 'Get Grades!',
}]
}]
};
Ext.getCmp('navView').push(p);
}
function getAllGames() {
var gameStoreRef = Ext.create('Ext.data.Store', {
model: 'a2.model.Games',
sorters: 'title',
grouper: {
groupFn: function(record) {
return record.get('title') [0];
}
},
});
gameStoreRef.load();
var gameList = Ext.create('Ext.List', {
fullscreen: true,
itemTpl: '<b>{title}</b><br /><i>{description}</i><br /><u>Enviroment:</u> {enviroment}<br /><u>Equipment Needed:</u> {equipment}<br /><u>Min Players:</u> {minPlayers} <u>Max Players:</u> {maxPlayers}<br /> <u>Age:</u> {age}<br /><img src="{image}" height="180" />',
store: gameStoreRef,
grouped: true,
title: 'All Games',
loadingText: 'Loading...'
});
Ext.getCmp('navView').push(gameList);
}
//
// Once a store is in existence, we can perform addition operations on it. For example, we can sort the data by defining
// a function on which attribute is used in the sort via the "grouper" property.
//
var staffStoreRef = Ext.create('Ext.data.Store', {
model: 'a2.model.Staff',
grouper: function(r) {
return r.get('lastName')[0];
},
sorters: 'lastName'
});
var staffListCfg = {
xtype: 'list',
store: staffStoreRef,
title: 'Staff Information',
loadingText: 'Loading...',
fullscreen: true,
itemTpl: '{firstName} {lastName}',
grouped: true,
indexBar: true,
onItemDisclosure: true,
//
// There are two ways to handle events. The first is to listen to it via the controller, which we have introduced
// in Workshop 7 and used below. Another way is to set them up using the listeners. With listeners, you can tie a function
// to an event so that when an event fires, the function is executed. Here, I am showing you two events that I am
// listening for. The first is when the user taps the list to select an item, which will fire the 'select' event. When
// the user taps the -> on the list, it fires the 'disclose' event. When the 'select' event fires, the staffListCfg_select()
// function defined below is fired to allow you to do something in response to it.
//
listeners: {
select: staffListCfg_select,
disclose: staffListCfg_disclose,
},
};
function getStaff() {
staffStoreRef.load();
var staffList = Ext.create('Ext.List', staffListCfg);
Ext.getCmp('navView').push(staffList);
}
//
// I became aware of the parameters by referring to the events documented. Remember that each Sencha component contains
// documentation that shows information like config options and methods. Another important list is the events that relate to
// a Sencha component. This is similar to event driven programming like Java and .NET so it should be easy to
// understand them.
//
function staffListCfg_select(view, record) {
var staffListDetails = Ext.create('Ext.Panel');
staffListDetails.setHtml(record.get('description'));
Ext.getCmp('navView').push(staffListDetails);
view.deselectAll();
}
function staffListCfg_disclose(view, record) {
var staffListDetails = Ext.create('Ext.Panel');
staffListDetails.setHtml(record.get('description'));
Ext.getCmp('navView').push(staffListDetails);
view.deselectAll();
}
//
// The body of your controller code.
//
var controllerDef = {
extend: 'Ext.app.Controller',
config: {
control: {
'button[action=ucGetStaff]': {
tap: function() {
getStaff();
}
},
'button[action=ucGetGrades]': {
tap: function() {
getGrades();
}
},
'button[action=ucGetAllGames]': {
tap: function() {
getAllGames();
}
},
'button[action=ucFilterGames]': {
tap: function() {
filterGames();
}
},
'button[action=ucSearchGames]': {
tap: function() {
searchGames();
}
}
}
}};
Ext.define('a2.controller.Handler', controllerDef);
games.json
Code:
{
"success": true,
"games": [
{
"title": "Basketball",
"enviroment": "concrete, inside",
"equipment": "Basketball, basketball hoop",
"minPlayers": "4",
"maxPlayers": "20",
"age": "12",
"description": "A very common sport. It is played with one ball and two hoops. Players must 'dribble' the ball if they wish to move.",
"image": "http://www.youth-basketball-tips.com/images/ybttitle.jpg"
},
{
"title": "Football",
"enviroment": "concrete, inside",
"equipment": "Football, Markers",
"minPlayers": "4",
"maxPlayers": "20",
"age": "12",
"description": "A popular sport that can be played as a contact or just a 'touch' sport with the aim to score trys by kicking or plaving the football between the goals or try line.",
"image": "http://www.armandosports.com.au/images/Sherrin KB Red Football New.jpg"
},
{
"title": "Hockey",
"enviroment": "concrete, inside",
"equipment": "Puck, Markers, Hockey Sticks",
"minPlayers": "4",
"maxPlayers": "20",
"age": "12",
"description": "A team game where players use hockey sticks to hit the puch into the other teams goal.",
"image": "http://www.fih.ch/files/pictures/sticklogo.jpg"
},
{
"title": "Tig",
"enviroment": "concrete, inside",
"equipment": "Markers",
"minPlayers": "3",
"maxPlayers": "20",
"age": "12",
"description": "A game which one has to catch and 'tig' the other person in order to not 'be it'.",
"image": ""
},
{
"title": "Golf",
"enviroment": "grass, inside",
"equipment": "Golf Ball, Golf Sticks",
"minPlayers": "1",
"maxPlayers": "10",
"age": "14",
"description": "The aim of this game is to put the golf ball in to the hole or to a predertimed place.",
"image": "http://upload.wikimedia.org/wikipedia/commons/thumb/8/84/258364_10150286385941427_576911426_9539410_221526_o.jpg/300px-258364_10150286385941427_576911426_9539410_221526_o.jpg"
}
]
}