1. Code
  2. Mobile Development

Build a Titanium Mobile Pizza Ordering App: Order Form Setup

Scroll to top
8 min read
This post is part of a series called Build a Titanium Mobile Pizza Ordering App.
Build a Titanium Mobile Pizza Ordering App: Topping Selection
Build a Titanium Mobile Pizza Ordering App: Order Completion

Welcome to the third installment in our series demonstrating how to build a pizza ordering application with Titanium Mobile. In this tutorial, we'll be creating the "Submit Your Order" screen.


Step 1: The Details Window

Now that the user is able to select and deselect toppings, we need to allow the user to actually submit an order. Let's start by modifying the details click event inside toppings.js:

1
2
details.addEventListener('click',function(e){
3
	var pizzaInfo = [];
4
	for (var i = 0; i < toppings.length; i++)
5
	{
6
		if (toppings[i].container != null)
7
		{
8
			pizzaInfo.push(toppings[i].title);
9
		}
10
	}
11
	Ti.App.fireEvent('details',{crust:win.crust,path:win.path,toppings:pizzaInfo});
12
});

Now when you hit the details button in the toppings window the code above will loop through our giant array of toppings and check the container property for each array item. If the item isn't null, it will add it to our temp array, called pizzaInfo. After the loop finishes, we will fire a new custom event called details. We will pass three parameters to this event:

  • The selected crust.
  • The image path to the selected crust.
  • The selected toppings (i.e. the temp array called pizzaInfo).

Step 2: Coding the openDetails Event

We need to modify our main.js file to listen for our custom event, so go ahead and open that file now. You are also going to add a new method called openDetails to the code:

1
2
var win             = Ti.UI.currentWindow;
3
4
//-- Create the sub windows

5
var crusts          = Ti.UI.createWindow();
6
var toppings        = Ti.UI.createWindow();
7
var details         = Ti.UI.createWindow();
8
9
//-- We set the background here since this wont change

10
win.backgroundImage = '../images/bg_main.png';
11
12
//-- Include our clock

13
Ti.include('../includes/clock.js');
14
15
//-- This method will close the crusts/details window and open the toppings window

16
function openToppings(e)
17
{
18
	crusts.close();
19
20
	toppings.url            = 'toppings.js';
21
	toppings.crust          = e.crust;
22
	toppings.path           = e.path;
23
	toppings.returnToppings = e.toppings;
24
	
25
	toppings.open();
26
}
27
28
//-- The method will close the toppings window and open the crusts window

29
function openCrust(e)
30
{
31
	toppings.close();
32
	//-- If the event has a crust property, that means the user hit cancel once in the toppings window

33
	if (e.crust)
34
	{
35
		crusts.crust = e.crust;
36
	}
37
	crusts.url = 'crusts.js';
38
	crusts.open();
39
}
40
41
//-- This method will close the toppings window and open the details window

42
function openDetails(e)
43
{
44
	toppings.close();
45
	
46
	details.crust       = e.crust;
47
	details.path        = e.path;
48
	details.toppings    = e.toppings;
49
	details.url         = 'details.js';
50
	
51
	details.open();
52
}
53
54
//-- Have our app listen for our custom events

55
Ti.App.addEventListener('toppings',openToppings);
56
Ti.App.addEventListener('cancelToppings',openCrust);
57
Ti.App.addEventListener('details',openDetails);
58
59
openCrust({});

Okay, your main.js file should now match the code above. In the above code, we added a new event listener at the bottom called details and when the app receives that event, we want to call the openDetails method. In the openDetails method, we first close the toppings window. We then set some properties on the details window with the values from the event we passed in toppings.js. We also set the URL property to details.js and finally call the open method.


Step 3: Creating the Details Form

We need to make a new javascript file called details.js and save it in the main_windows folder. What we want to do in this file is add three text fields:

  • Name
  • Address Line 1
  • Address Line 2

NOTE: In a real-world application, we would obviously have more fields, but for the sake of this tutorial we will have only created three fields.

We are also going to have a summary of the pizza the user has ordered with a submit order button. Let's start with the interface for this:

1
2
var win      = Ti.UI.currentWindow;
3
var orderReq = Titanium.Network.createHTTPClient();
4
5
//-- Name Text Field

6
var names = Titanium.UI.createTextField({
7
	color:'#336699',
8
	top:100,
9
	left:10,
10
	width:300,
11
	height:40,
12
	hintText:'Name',
13
	backgroundImage:'../images/textfield.png',
14
	paddingLeft:8,
15
	paddingRight:8,
16
	keyboardType:Titanium.UI.KEYBOARD_DEFAULT,
17
	returnKeyType:Titanium.UI.RETURNKEY_NEXT,
18
	suppressReturn:false
19
});
20
21
//-- Address1 Text Field

22
var address1 = Titanium.UI.createTextField({
23
	color:'#336699',
24
	top:140,
25
	left:10,
26
	width:300,
27
	height:40,
28
	hintText:'Address 1',
29
	backgroundImage:'../images/textfield.png',
30
	paddingLeft:8,
31
	paddingRight:8,
32
	keyboardType:Titanium.UI.KEYBOARD_DEFAULT,
33
	returnKeyType:Titanium.UI.RETURNKEY_NEXT,
34
	suppressReturn:false
35
});
36
37
//-- Address2 Text Field

38
var address2 = Titanium.UI.createTextField({
39
	color:'#336699',
40
	top:180,
41
	left:10,
42
	width:300,
43
	height:40,
44
	hintText:'City, State, Zip Code',
45
	backgroundImage:'../images/textfield.png',
46
	paddingLeft:8,
47
	paddingRight:8,
48
	keyboardType:Titanium.UI.KEYBOARD_DEFAULT,
49
	returnKeyType:Titanium.UI.RETURNKEY_DEFAULT
50
});
51
52
//-- Listen for the next click on the key board

53
names.addEventListener('return',function(){address1.focus();});
54
address1.addEventListener('return',function(){address2.focus();});
55
56
win.add(names);
57
win.add(address1);
58
win.add(address2);
59
60
//-- This method makes a nice formatted summary of the users order

61
function getFormattedPizza()
62
{
63
	var text = win.crust + ' pizza with:\n';
64
	if (win.toppings.length == 0)
65
	{
66
		text += '&bull; Plain (cheese pizza)\n';
67
	}
68
	else
69
	{
70
		for (var i = 0; i < win.toppings.length; i++)
71
		{
72
			text += '&bull; ' + win.toppings[i] + '\n';
73
		}
74
	}
75
	return text;
76
}
77
78
//-- Are formatted text field

79
var pizzaInfoText = Ti.UI.createLabel({
80
	text:getFormattedPizza(),
81
	font:{
82
		fontFamily:'Verdana',
83
		fontSize:14
84
	},
85
	color:'#fff',
86
	shadowColor:'#333',
87
	shadowOffset:{x:1,y:1},
88
	textAlign:'left',
89
	width:Ti.Platform.displayCaps.platformWidth,
90
	height:160,
91
	top:210,
92
	left:10
93
});
94
win.add(pizzaInfoText);
95
96
//-- Order Button

97
var order = Ti.UI.createButton({
98
	width:137,
99
	height:75,
100
	backgroundImage:'../images/order.png',
101
	top:385,
102
	left:165,
103
	opacity:0
104
});
105
106
//-- Cancel Button

107
var cancel = Ti.UI.createButton({
108
	width:137,
109
	height:75,
110
	backgroundImage:'../images/cancel.png',
111
	top:385,
112
	left:10,
113
	opacity:0
114
});
115
116
//-- If android OS, use the image property instead of backgroundImage (Ti SDK bug)

117
if (Ti.Platform.osname == 'android')
118
{
119
	order.image = '../images/order.png';
120
	cancel.image = '../images/cancel.png';
121
}
122
win.add(order);
123
win.add(cancel);
124
125
//-- Fade the order button in

126
order.animate({
127
	opacity:1,
128
	duration:500
129
});
130
131
//-- Fade the cancel button in

132
cancel.animate({
133
	opacity:1,
134
	duration:500
135
});

The above block of code may look scary, but really it is quite simple. We start by defining our win variable as well as our orderReq variable. The orderReq variable will handle our request out to our PHP file which we will cover in the next tutorial of this series.

We then define our three text fields and give them some simple properties. We add a return event listener on the text fields so when you hit next on the keyboard, it jumps to the next text field. We make a label called pizzaInfoText and set its text property to our getFormattedPizza method. This method will return a formatted list of our chosen crust and toppings. If the user selected no toppings, we will display the crust type and a simple cheese pizza. We've also made our order and cancel buttons and faded them in. Your interface should look like this now:


Step 4: Coding the Cancel Button

So you're in the submit order screen and you decide you want to remove mushrooms from your topping list. Well, no problem! The app already knows the toppings you currently have selected, so we will simply pass that temp array back to toppings.js and recheck the toppings. We first need to add an event listener to our cancel button. Scroll to the bottom of your details.js file and add this:

1
2
//-- Cancel button event. Goes back to the toppings window and remembers the users selections

3
cancel.addEventListener('click',function(){
4
	Ti.App.fireEvent('cancelDetails',{crust:win.crust,path:win.path,toppings:win.toppings});
5
});

We are firing yet another custom event, this time called cancelDetails, and again we pass three parameters:

  • The selected crust.
  • The image path to the selected crust.
  • The selected toppings (i.e. our temp array).

Step 5: Code the cancelDetails Event

Let's go back to main.js. We need to add a new event listener. Add the following to the end of our event listeners.

1
2
Ti.App.addEventListener('cancelDetails',openToppings);
3
</pre>

4
<p> Now we already have an <code>openToppings</code> method. We do however need to modify it. </p>
5
<pre name="code" class="javascript">
6
//-- This method will close the crusts/details window and open the toppings window

7
function openToppings(e)
8
{
9
	if (e.toppings)
10
	{
11
		details.close();
12
	}
13
	else
14
	{
15
		crusts.close();
16
	}
17
18
	toppings.url            = 'toppings.js';
19
	toppings.crust          = e.crust;
20
	toppings.path           = e.path;
21
	toppings.returnToppings = e.toppings;
22
	
23
	toppings.open();
24
}

So, with our modified method, we do a check for the toppings property tied to the event. If it isn't null, we want to close the details window. If it is null, we want to close the crust window. We still add our custom properties and then open our toppings window.


Step 6: Checkbox Preselection

When we go back we want to preselect the checkboxes of the topping we previously chose. We also want to add the toppings to the pizza visually. Open up the toppings.js file and scroll down to the createToppingsList method. The difference between your current one and the one below is if win.returnToppings isn't null, it will loop through our larger toppings array and compare it to our temp array. If they match up, recheck the checkbox, add the visual to the crust, and increase our toppings count.

1
2
/*

3
This method creates the topping list. Since iOS doesn't have checkmark components, I made my own using a view, a button and swapping out the background image

4
*/
5
function createToppingsList()
6
{
7
	scrollView.opacity = 0;
8
	scrollView.top = 155;
9
	scrollView.height = 120;
10
	scrollView.contentWidth = Ti.Platform.displayCaps.platformWidth;
11
    scrollView.contentHeight = 'auto';
12
    scrollView.showVerticalScrollIndicator = true;
13
    win.add(scrollView);
14
15
	for (i = 0; i < toppings.length; i++)
16
	{
17
		//-- The label

18
		var toppingLabel = Ti.UI.createLabel({
19
			text:toppings[i].title,
20
			font:{
21
				fontFamily:'Verdana',
22
				fontWeight:'bold',
23
				fontSize:14
24
			},
25
			color:'#fff',
26
			shadowColor:'#333',
27
			shadowOffset:{x:1,y:1},
28
			textAlign:'left',
29
			width:Ti.Platform.displayCaps.platformWidth - 10,
30
			left:10
31
		});
32
		
33
		//-- We add a custom property 'selected' to our checkbox view

34
		var checkbox = Ti.UI.createView({
35
			width:340,
36
			height:16,
37
			backgroundImage:'../images/checkbox_no.png',
38
			selected:false,
39
			toppingID:i
40
		});
41
		
42
		//-- if the user hits cancel in the details window, we go back and repopulate the list with previously checked toppings

43
		if (win.returnToppings)
44
		{
45
			for (j = 0; j < win.returnToppings.length; j++)
46
			{
47
				if (win.returnToppings[j] == toppings[i].title)
48
				{
49
					var aTopping = Ti.UI.createView({
50
						backgroundImage:toppings[i].path
51
					});
52
					
53
					if (Ti.Platform.osname == 'android')
54
					{
55
						aTopping.image = toppings[i].path;
56
					}
57
					else
58
					{
59
						aTopping.opacity = 0;
60
						aTopping.animate({
61
							opacity:1,
62
							duration:500
63
						});
64
					}
65
					toppingsHolder.add(aTopping);
66
					toppings[i].container = aTopping;
67
					checkbox.backgroundImage = '../images/checkbox_yes.png';
68
					checkbox.selected = true;
69
					numToppings += 1;
70
				}
71
			}
72
		}
73
		
74
		var toggler = Ti.UI.createView({
75
			width:Ti.Platform.displayCaps.platformWidth,
76
			height:20,
77
			top: i * 20
78
		});
79
		
80
		//-- We use the singletap event rather than the click since its in a scroll view

81
		checkbox.addEventListener('singletap',toppingListClick);
82
		toggler.add(toppingLabel);
83
		toggler.add(checkbox);
84
		
85
		scrollView.add(toggler);
86
	}
87
	scrollView.animate({
88
		opacity:1,
89
		duration:500
90
	});
91
}

Conclusion

In this tutorial we created the "Submit Oder" screen that is the last screen we will need in this tutorial series. We also added two more custom events to our app that allowed us to jump between the "Choose Crust" and "Submit Order" screens.

The next part of this series will go over doing the form authentication necessary to handle submissions and then e-mailing the order chosen along with the customer information submitted (a web server with a mail client and PHP installed will be required in order to send the e-mail order notification).