You are on page 1of 22

Step 1: Prepare XML for our quiz application

1) Create a folder QuizData.

2) Now create following XML file in your favourite text editor.

<?xml version=1.0 encoding=UTF-8?>

<Quiz>

</Quiz>

Yes you are right, this is a root node

Save this file as Quiz.xml in the same folder QuizData.

Add a node to the above XML file,

<Quiz>

<Question>

<QText>This is Question no.1. </QText>

</Question>

</Quiz>

Here we have added one question to our XML file. You can add more questions but for now it
will work. Later we shall add good set of questions.

3) A quiz is incomplete without options with one right answer to choose from.

Lets add options as follows,(Bold lines)

<Quiz>

<Question>

<QText>Q1.This is Question no.1. </QText>

<Option> Place here option no1 </Option>

<Option> Place here option no2 </Option>


<Option> Place here option no3 </Option>

</Question>

</Quiz>

Here we set a question with three options. For now we shall use this XML.

Step 2: Now its time for some Flashing


1) Create a new Flash Document for Action Script 3 and save it in the same folder QuizData
where you saved your xml file Quiz.xml.

2) Adjust stage size as 800 x 600.

3) Add dynamic text field (Arial, 20, bold) to the stage and place it at the top. Expand it enough
as it is going to display your question. Give Instance name as Question_TF.

(Note: For CS5, embed font for action script.)

Step 3: Loading XML file


In this step we shall load XML file created in step1 to create XML document and access children
form it.

Add following script to a first and only keyframe in a time line.

var url:URLRequest = new URLRequest(Quiz.xml); // url of xml file


var xmlLoader:URLLoader = new URLLoader(url); // xml file loader

//When xml file is completely loaded call onXMLLoad function

xmlLoader.addEventListener(Event.COMPLETE, onXMLLoad);

//Create XML document and have access to its children

var xml:XML;

var xmlList:XMLList;

var xmlChildren;

function onXMLLoad(e:Event):void

xml = new XML(xmlLoader.data); //create XML document

xmlList = new XMLList(xml); //create XML List of XML nodes

xmlChildren = xmlList.children (); //Get number of child nodes

Step 4: Extracting question from XML


1) Continue with the above code. Our first task is to display the question in the TextField we
have on the stage. How will we do that?

2) We shall add a new function generateQuestion () to our script as follows,

function generateQuestion (): void {

//Extract a question from xml file

Call this function inside onXMLLoad function as shown below. (Bold line)

function onXMLLoad(e:Event):void {

xml = new XML(xmlLoader.data); //create XML document

xmlList = new XMLList(xml); //create XML List of XML nodes


xmlChildren = xmlList.children(); //Get number of child nodes

generateQuestion (); // This function extracts question from XML.

3) Make generateQuestion () function working as follows,

function generateQuestion (): void {

//Extract a question from xml file

Question_TF.text = xmlChildren.QText;

4) Modify it and get total number of questions. (used in coming steps)

var totalQuestions:Number;

function generateQuestion (): void {

Question_TF.text = xmlChildren.QText;

//get total number of questions

totalQuestions = xmlChildren.length();

(Note: For CS5 embed font for action script using properties panel for text field)

Press CTRL+ENTER (Win)/CMD+ENTER (Mac) to test it.

There it is! Our first question is nicely placed in the text field.

Step 5: Preparing radio buttons for options


Our second task is to display options below question. We shall use radio buttons for this purpose,
as we are going to make objective test with single choice option.

To achieve this we need total number of options specified in XML file. So that we can decide
how many radio buttons needs to be added to the stage below a Question.

1) Get total number of options for the current question as follows, (Bold lines)
var totalOptions: Number;

function generateOptions (): void {

//Get total number of options for the current question

totalOptions = xmlChildren.Option.length();

Call this function inside generateQuestion() as shown, (Bold line)

function generateQuestion():void{

Question_TF.text = xmlChildren.QText;

totalQuestions = xmlChildren.length();

//create and place options below question

generateOptions();

2) Before creating and placing radio buttons we must have to do couple of things.

First add following lines to the start of the script,

import fl.controls.RadioButton;

import fl.controls.RadioButtonGroup;

Secondly, add radio button component to the library

(Drag radio button component directly to the library)

Or

(Drag it to the stage. So that it is available in the library. But here delete it from the stage after
dragging because we are going to add them dynamically.)

3) To create and place radio buttons modify generateOptions() function and add new vars to the
script as follows, (Bold lines)

var totalOptions:Number;
var radioButton:RadioButton;//a radio button

var vPadding:uint = 0;//control the distance between radio buttons

var vSpacing:uint = 50;//provide equal space between radio buttons

function generateOptions():void{

//Get total number of options for the current question

totalOptions = xmlChildren.Option.length();

//Create radio buttons equal to the number of options of current question

for (var i:int = 0; i < totalOptions; i++) {

radioButton = new RadioButton(); // create radio button

addChild(radioButton); //add it to the stage

radioButton.x = Question_TF.x + 30; // adjust x position

//Adjust y position of radio buttons

radioButton.y = (vPadding + vSpacing) + (Question_TF.y +


Question_TF.height);

vPadding += vSpacing;

Press CTRL+ENTER (Win) / CMD+ENTER (Mac) to test it.

Wow!!! See those radio buttons living on their floors.

But they are required to be filled with options specified in xml file. Perform next step.

Step 6: Adding options for a given question


Continue with above for loop. Modify it as shown below (bold lines),

for (var i:int = 0; i < totalOptions; i++){

radioButton = new RadioButton();


addChild(radioButton);

radioButton.x = Question_TF.x + 30;

radioButton.y = (vPadding + vSpacing) + (Question_TF.y +


Question_TF.height);

vPadding += vSpacing;

//Extract and add option form xml to radio button label

radioButton.label = xmlChildren.Option[i];

radioButton.width = 300; // for proper display of options

COOL!!! All radio buttons are displaying options extracted from xml file.

Step 7: Setting up a correct answer


How to check whether the current selection is correct or incorrect answer?

Any Guess?

Hint: Use XML attributes.

This is the perfect situation where we can take the help of XML attribute.

1) Modify our Quiz.xml file as shown (bold words)

<Quiz>

<Question>

<QText>Q1.This is Question no.1. </QText>

<Option> Place here option no1 </Option>

<Option correct =1> Place here option no2 </Option>

<Option> Place here option no3 </Option>

</Question>

</Quiz>
We have added XML attribute correct = 1. We shall use this attribute to set current option as a
correct answer.

The logic behind this approach is simple. Consider following points,

a) Get an index number of the option (XML file) having attribute correct = 1.

i.e. <Option correct = 1>

b) Get an index number of the selected radio button.

c) Compare these index numbers with each other. If they are equal, the answer
is correct else it is incorrect.

2) So we have a new task now. Get the index number of the option having attribute correct = 1
in xml file. So modify the script as follows. (Bold lines)

var totalOptions:Number;

var radioButton:RadioButton;

var vPadding:uint = 0;

var vSpacing:uint = 50;

var isCorrect:Number;

var correctAnswerIndex:Number;

function generateOptions():void{

totalOptions = xmlChildren.Option.length();

for (var i:int = 0; i < totalOptions; i++){

radioButton = new RadioButton();

addChild(radioButton);

radioButton.x = Question_TF.x + 30;

radioButton.y = (vPadding + vSpacing) + (Question_TF.y +


Question_TF.height);

vPadding += vSpacing;
radioButton.label = xmlChildren.Option[i];

radioButton.width = 300;

//Get the index of correct option(correct attribute) from xml file

isCorrect = xmlChildren.Option[i].@correct;

if(isCorrect == 1){

correctAnswerIndex = i; //this is the index no. of correct option

Our next target is to get an index number of selected radio button. But wait. It is not as straight
forward as you think.

First we have to create a group of radio buttons to act as a single component.

Step 8: Grouping radio buttons


We shall group radio buttons. They will act as a single component. So we can use
getRadioButtonIndex() method available with radio button group to get an index number of a
selected radio button which is our next task.

Before that let us create a group of radio buttons as follows (Bold lines);

var totalOptions:Number;

var radioButton:RadioButton;

var radioButtonGroup:RadioButtonGroup;

var vPadding:uint = 0;

var vSpacing:uint = 50;

var isCorrect:Number;

var correctAnswerIndex:Number;

function generateOptions():void {
totalOptions = xmlChildren.Option.length();

radioButtonGroup = new RadioButtonGroup(options);

for (var i:int = 0; i < totalOptions; i++){

radioButton = new RadioButton();

addChild(radioButton);

radioButton.x = Question_TF.x + 30;

radioButton.y = (vPadding + vSpacing) + (Question_TF.y +


Question_TF.height);

vPadding += vSpacing;

radioButton.label = xmlChildren.Option[i];

radioButton.width = 300;

radioButton.group = radioButtonGroup; //grouping radio buttons

isCorrect = xmlChildren.Option[i].@correct;

if(isCorrect == 1){

correctAnswerIndex = i;

Step 9: Get an index no. of selected radio button


This step is really important in terms of the approach we have attempted here to develop this
XML driven quiz application.

This step will not only satisfy our second need of getting an index number of selected radio
button but we are also adding a new function checkAnswer() to the script as follows,

var currentRadioButton;

var currentSelection;
function checkAnswer(e:MouseEvent):void {

currentRadioButton = e.currentTarget; // store selected radio button

//Get an index number of selected radio button

currentSelection = radioButtonGroup.getRadioButtonIndex(currentRadioButton));

Now that we have both index numbers as,

correctAnswerIndex (for XML option with attribute as <Option correct = 1>)

correctSelection (for selected radio button)

It is time to compare them with each other. Follow the next step

Step 10: Checking correct answer


We cannot complete a quiz without checking the answer and displaying the result.

Our immediate goal is to achieve the same. How to do that?

We shall modify the checkAnswer (e: MouseEvent) function as shown, (Bold lines)

var currentRadioButton;

var currentSelection:Number;

var resultStr:String;

var result_TF:TextField = new TextField (); //to display result for current question

result_TF.width = 250; //for proper text display

addChild (result_TF); //add it to the stage

function checkAnswer(e:MouseEvent):void {

currentRadioButton = e.currentTarget; // store selected radio button

//Get an index number of selected radio button

currentSelection = (radioButtonGroup.getRadioButtonIndex(currentRadioButton));
//Check and store answer

resultStr = (currentSelection == correctAnswerIndex) ? Correct : Incorrect;

//Display a result

result_TF.text = resultStr;

//Positioning the result textfield

result_TF.x = radioButton.x + 30; //x position

result_TF.y = (vPadding + vSpacing)+50; //y position

If you test the movie and click radio buttons nothing will happen. Why? Follow next step.

Step 11: Responding to mouse click


To make radio buttons respond to mouse click, add following line (bold line) to for loop of
generateOptions() function as shown,

for (var i:int = 0; i < totalOptions; i++){

radioButton = new RadioButton(); // create radio button

addChild(radioButton); //add it to the stage

radioButton.x = Question_TF.x + 30; // adjust x position

//Adjust y position of radio buttons

radioButton.y = (vPadding + vSpacing) + (Question_TF.y +


Question_TF.height);

vPadding += vSpacing;

//Extract option from XML file and add it to radio button label

radioButton.label = xmlChildren.Option[i];

radioButton.width = 300; // for proper display of options

//Get the index of correct option already set in xml file


isCorrect = xmlChildren.Option[i].@correct;

if(isCorrect == 1){

correctAnswerIndex = i; //this is the index no. of correct option

radioButton.addEventListener(MouseEvent.CLICK, checkAnswer);

Test your movie.

Congrats!!! They are responding showing result. Now we are very close to the final version.

Step 12: Adding more questions


We were dealing with only one question up to this step. Its time to add more fun to our Quiz
App by adding more questions thus satisfying the need XML Driven.

First modify our XML file Quiz.xml as follows (Bold lines)

<?xml version=1.0 encoding=UTF-8?>

<Quiz>

<Question>

<QText> Q1. This is my first question. </QText>

<Option> Place here option no1 </Option>

<Option correct = 1> Place here option no2 </Option>

<Option> Place here option no3 </Option>

</Question>

<Question>

<QText> Q2. This is my second question. </QText>

<Option correct = 1> Place here option no1 </Option>

<Option> Place here option no2 </Option>


<Option> Place here option no3 </Option>

<Option> Place here option no4 </Option>

</Question>

<Question>

<QText> Q3. This is my third question. </QText>

<Option> Place here option no1 </Option>

<Option correct = 1> Place here option no2 </Option>

</Question>

</Quiz>

I had intentionally placed different number of options for different questions. You can have your
choice. (of number of questions and their number of options). Only take care of placing attribute
correct = 1.

This was about XML. What about action script in Flash? We must modify it.

Step 13: Go to next question


This is the climax scene of our movie. So watch it carefully otherwise you will not be able to tell
the story to others. Onwards you are going to see some important additions in the script those are
essentially very important to make this quiz application XML Driven. So first read following
points.

1) Introducing a new var currentQuestion:Number.

We shall utilize this var to point out (XML) index number of a question and so the related
options going to be displayed on the stage.

Mostly we shall modify generateQuestion() and generateOptions() by replacing xmlChildren


with xmlChildren[currentQuestion]. See it soon.

2) And one more var radioButtonContainer:Movieclip.

This will hold all radio buttons of current question. And will help to remove those radio buttons
from the stage and add new ones.

3) And last one for now i swear, var radioButtonArray:Array.


This will store radio buttons and will provide a reference of each radioButton to built in function
removeChild().

4) I know you are waiting for finishing touch. Please have patience. Face it.

There is also a new function nextQuestion(e:MouseEvent) joining our family.

This is an important member of our family. It will open the door to meet the next question and its
option.

Some part of the script is self explanatory. More focus on a logical part of it.

Dont test the movie now. Do it after going through next step as we are also going to modify our
generateOptions() function by adding radioButtonArray.

First go through new function nextQuestion(e:MouseEvent)

// Go to next question

var currentQuestion:Number = 0; // reference to index number of question (XML file)

function nextQuestion(e:MouseEvent):void{

Question_TF.text = ;

result_TF.text = ;

//remove previous options

for (var i:int = 0; i < totalOptions; i++){

radioButtonContainer.removeChild(radioButtonArray[i]);

//check if current question is last question

if(currentQuestion < totalQuestions-1){

//next question index

currentQuestion++;

vPadding = 0;

totalOptions = 0;
radioButtonArray = [];

generateQuestion();

The var radioButtonArray:Array is still undefined. Go to next step.

Step 14: Push radio buttons into an array


Here we shall modify generateOptions() function with the addition of var
radioButtonArray:Array

We shall also add a var radioButtonContainer:Movieclip and replace addChild(radioButton)


with radioButtonContainer.addChild(radioButton); in generateOptions().

We shall also use currentQuestion as xmlChildren[currentQuestion]. In our two functions i.e.


generateQuestion() and generateOptions().

First modify generateOptions()

See it carefully, as shown below (Bold lines),

// Create and place radio buttons below question

var totalOptions:Number;

var radioButton:RadioButton;

var radioButtonGroup:RadioButtonGroup;

var vPadding:uint = 0;

var vSpacing:uint = 50;

var isCorrect:Number;

var correctAnswerIndex:Number;

var radioButtonArray:Array;

var radioButtonContainer:MovieClip = new MovieClip();

addChild(radioButtonContainer);
function generateOptions():void{

radioButtonArray= new Array(); //Store radio buttons for reference

//Get total number of options for the current question

totalOptions = xmlChildren[currentQuestion].Option.length();

radioButtonGroup = new RadioButtonGroup(options);

for (var i:int = 0; i < totalOptions; i++){

radioButton = new RadioButton();

radioButton.selected = false;

//Previous addChild(radioButton) statement is replaced by following

radioButtonContainer.addChild(radioButton);

radioButton.x = Question_TF.x + 30;

radioButton.y = (vPadding + vSpacing) + (Question_TF.y +


Question_TF.height);

vPadding += vSpacing;

radioButton.label = xmlChildren[currentQuestion].Option[i];

radioButton.width = stage.stageWidth;

radioButton.group = radioButtonGroup;

isCorrect = xmlChildren[currentQuestion].Option[i].@correct;

if(isCorrect == 1){

correctAnswerIndex = i;

radioButton.addEventListener(MouseEvent.CLICK, checkAnswer);

//push radio buttons into array for reference to removeChild()

radioButtonArray.push(radioButton);
}

Now modify generateQuestion(),

function generateQuestion():void{

//extract question from XML file

Question_TF.text = xmlChildren[currentQuestion].QText;

totalQuestions = xmlChildren.length();

generateOptions();

Finish next step and you are done with what you are expecting.

Step 15: Adding Next button to the stage


Create a button (of your choice, I have added arrow ) on the stage.

Give instance name as nextButton to your button. Dont worry about its position. We are going
to handle it in a script.

After creating a button our next task is to make it functioning. Modify function
checkAnswer(e:MouseEvent) as shown (Bold lines).

nextButton.visible = false;

var currentRadioButton;

var currentSelection:Number;

var resultStr:String;

var result_TF:TextField = new TextField ();

result_TF.width = 250;

addChild (result_TF);

function checkAnswer(e:MouseEvent):void {
currentRadioButton = e.currentTarget;

currentSelection = (radioButtonGroup.getRadioButtonIndex(currentRadioButton));

resultStr = (currentSelection == correctAnswerIndex) ? Correct : Incorrect;

result_TF.text = resultStr;

result_TF.x = radioButton.x + 30;

result_TF.y = (vPadding + vSpacing)+50;

//For correct answer ready to display next question

if(resultStr == Correct){

//check if current question is last question

if(currentQuestion < totalQuestions-1){

nextButton.visible = true;

nextButton.addEventListener(MouseEvent.CLICK,
nextQuestion);

//next button position

nextButton.x = result_TF.x + result_TF.width + 40;

nextButton.y = result_TF.y;

}else{

result_TF.text = resultStr + > Quiz Complete;

}else

nextButton.visible = false;

nextButton.removeEventListener(MouseEvent.CLICK,
nextQuestion);
}

This functions checks for correct answer. If answer is correct and the current question is not the
last question then it displays Next button on the stage. If answer is incorrect then it shows Quiz
Complete after result.

Good News!!!. Finally you can call it as XML driven quiz application.

Modify Quiz.xml as per your need and experience the power of XML Driven.

If you wish you can stop here or you perform next step. I suggest the later one.

Step 16: Finally do some text formatting


Typography is an important part of any project (Digital or Non Digital). It really matters how
text is handled.

We shall do some text formatting now. (Not great but will satisfy our need).

Our radio buttons labels are very poor. Make them more readable.

1) Add following lines at the start (below import statements) of the script

//Text formatting

var globalTextFormat:TextFormat = new TextFormat();

globalTextFormat.font = Arial;

globalTextFormat.size = 18;

globalTextFormat.bold = true;

//

2) To apply the above textformat to radio button labels, add following line into for loop of
generateOptions() as shown (Bold line)

//Make radio button label more readable

radioButton.setStyle(textFormat,globalTextFormat);

3) We shall also apply this text format to result text field.


Important to say, that we are also making the text colour of result to change as per the answer. If
answer is correct then result text will have Green colour. And if answer is incorrect it will have
Red colour.

Modify function checkAnswer(e:MouseEvent) as shown (Bold lines).

var currentRadioButton;

var currentSelection:Number;

var resultStr:String;

var resultStrColor;

var result_TF:TextField = new TextField ();

result_TF.defaultTextFormat = globalTextFormat;

result_TF.width = 250;

addChild (result_TF);

function checkAnswer(e:MouseEvent):void {

currentRadioButton = e.currentTarget;

currentSelection = (radioButtonGroup.getRadioButtonIndex(currentRadioButton));

resultStr = (currentSelection == correctAnswerIndex) ? Correct : Incorrect;

result_TF.text = resultStr;

//Change text color of result as per answer (Green for correct and Red for incorrect)

resultStrColor = (resultStr == Correct) ? 0009900 : 0xFF0000;

result_TF.textColor = resultStrColor;

result_TF.x = radioButton.x + 30;

result_TF.y = (vPadding + vSpacing)+50;

//rest of the code remains same .

}.
Nice Music Please!!! I am very much excited to say that we have finished our long journey to
reach to see how to build XML Driven Quiz Application.

Conclusion
After completing this Flash tutorial you are able to develop any XML driven application. We also
got opportunity to handle radio buttons. In the final section we did text formatting which will
certainly help in your future work.

Since our goal was to learn to build XML driven application we ignored beauty and styling of
GUI. We were more focused on logical part. We also ignored scoring for the same reason. Now
you know it is not that tough. I believe you can add it yourself. And you can improve it
yourself. Thanks for your patience. Have a nice time and best of luck. Come back to see my
more upcoming tutorials.

You might also like