hosted by tripod
Search the web with Hotbot Build an online Photo Album


  Matt Stanton's CyberEFL  

CONTENTS

 
 Website Development Help for EFL/ESL Teachers
Script for a Short-Answer Question that Returns
the Correct Part of the Student's Guess

I've got my teaching cap on this evening and I'm going to show you a simplish JavaScript function that can be invoked for any short-answer question that gets input from a textbox. Rather than just telling the student whether their effort was right or wrong and giving them the solution, it erases the incorrect section from the end of the string and waits for them to try again - much better than just giving it to them on a plate. For example, suppose the word was "spectacular" (we've got Moulin Rouge playing on the video at the moment and Ewan McGregor just bashed it into his typewriter) and the student guessed "SPECIAL". The script will return "spec" to the textbox because " I " is the first incorrect letter. It doesn't matter that the guess was entered in capitals because the script converts it to lowercase before doing any comparisons. When the student gets it right, an alert box pops up saying "You got it!". I'm sure I don't need to tell you, but this is a great way to get students to focus on spelling. Anyway, there's an example below. Have a play around with it until you get the feel of it. Clue: The word is a popular scripting language!

Here's the script for that below in the form of a complete HTML document:

<html>
<head>
<script language="javascript">
<!--

function checkanswer(guess,word){

var sendback;
var guessed = guess.value.toLowerCase();

if(guessed.length > word.length){
	alert(
"That's too long!\nThe answer only contains " 
+ word.length + " characters.");
	guess.focus();
	return;
}

for(var i=1; i<=word.length; i++){
	if(guessed.substring(0,i) == word.substring(0,i)){
		sendback = guessed.substring(0,i);
}else{
		break;
	}

} // end loop

if(sendback){
	
	if(sendback == word){
		alert("You got it!");
}else{
		guess.value = sendback;
		guess.focus();
	}
}else{ 
	guess.value = "";
	guess.focus();

	}

} // end function

//-->
</script>
</head>

<body onLoad="document.myform.mybox.focus();">

<form name="myform">
<input type="text" size="20" value="" name="mybox">
<input type="button" value="Check" onClick="
	checkanswer(document.myform.mybox,'javascript');"
</form>

</body>
</html>
Right, let's get on with the dissection. To make sense of it, you'll benefit from an understanding of JavaScript basics, particularly with regard to the following:-
  • Event handling
  • Variables
  • Loops
  • "if/else" constructions
  • The distinction between objects, properties and methods.
  • Functions: how to construct them, invoke them and pass parameters to them.
First, let's take a look at the BODY section:
<body onLoad="document.myform.mybox.focus();">

<form name="myform">
<input type="text" size="20" value="" name="mybox">
<input type="button" value="Check" onClick="
	checkanswer(document.myform.mybox,'javascript');"
</form>

</body>
Here I've set up a simple form consisting of a textbox and a button. The form is called "myform" and the box is called "mybox". We can refer to the textbox in the future with "document.myform.mybox". I didn't give the button a name because it doesn't need one, it's just used to invoke the function "checkAnswer". When clicked, two parameters are passed to "checkanswer" : "document.myform.mybox" and "javascript". "javascript" is just the word I chose for this example. You can pass any textbox and any word you want to the function, meaning you can make lots of questions with just the one reusable function. Before we take a look at the function, notice the "onLoad" attribute with the BODY tag. It invokes the "focus()" method to put the user's cursor into the textbox at the beginning. It's not really necessary but it saves the user some trouble.

Now let's shoot up to the HEAD and take a look at this all important function. It's the only one this script needs but it's pretty wordy. I didn't split it up because it's a nice self-contained package. First of all, let's take a look at the opening line:
function checkanswer(guess,word){
This takes the two parameters that are passed when the function is invoked and converts them into two local variables. So from now on the textbox object will be known as "guess" and the solution, in this case "javascript", will be "word". This conversion is crucial for ensuring that the function is reusable.

The function itself consists of three main parts. Here's the first:
var sendback;
var guessed = guess.value.toLowerCase();

if(guessed.length > word.length){
	alert(
"That's too long!\nThe answer only contains " 
+ word.length + " characters.");
	guess.focus();
	return;
}
First, we declare a local variable called "sendback". As you might have guessed, this is going to hold the correct part of the student's guess, which will be sent back to the textbox. The second line is worth paying attention to. "guess" only refers to the textbox itself, the entry field - it doesn't refer to what's in it. What's actually in it, the student's guess, is found in the value property of that object. This line converts that value to lower case and stores it in the variable "guessed", so "guessed" is what the student guessed, in lower case to keep this question case insensitive. You can remove ".toLowerCase()" if you want to be strict about case. I didn't want to be with this example because the trademarked name of the language is "JavaScript" and it's a bit much to expect people to remember to capitalise "Script". After the declarations, there's a little "if" clause that exits the function with an alert if the user's guess is too long.

Now let's have a look at the second part of the function, which is a "for" loop:
for(var i=1; i<=word.length; i++){
	if(guessed.substring(0,i) == word.substring(0,i)){
		sendback = guessed.substring(0,i);
}else{
		break;
	}

} // end loop
To understand it, you'll need to know how the "substring(x,x)" method works. It's the method around which this entire script revolves, so I'll take a little time out to explain it to you.

When you give JavaScript a string, the script assigns a number to every character in the string. In programming, counting always starts at zero. This means that with the word "javascript", zero corresponds to "j", one to "a" and so on. Even though "javascript" has ten characters, the last one will be 9, right? Now suppose you want to pull the first four characters out and do something with them. To do this you use the "substring" method like this: "javascript".substring(0,4). The value returned by the method will evaluate to "java", the first four characters. There are two parameters being passed to the method: 0 and 4. This means "take the the section from the first character (0) till the fifth character (4) but don't include the fifth character. It takes a while to get your head around it but it's quite easy to work with when you only want the first characters from the string because the second parameter corresponds to the number of characters you want to pull out. Here we want the first four characters so we set the parameter to 4.

I hope that's clear. If it is, the analysis of the loop should be pretty straightforward. Let's suppose that the user inputted "VBScript" (a Microsoft-only client-side scripting language). The first time into the loop the program checks to see if the first character of the guess equals the first character of the word. It doesn't, of course, so it breaks out of the loop and waits for further instructions. Now let's suppose the user entered "Jabascript". The first time through the loop "j" and "j" match so the value of "sendback" becomes "j", "i" increments by one and the loop starts again. This time "ja" and "ja" also match so "sendback" becomes "ja". The third time through, however, there's no match, so the loop ends with "sendback" holding "ja", which was the correct part of the user's effort.

OK, let's see what happens next. This is the "if" clause for when "sendback" contains a value. If the user has entered "VBScript", this part will be skipped.
if(sendback){
	
	if(sendback == word){
		alert("You got it!");
}else{
		guess.value = sendback;
		guess.focus();
	}
With the "Jabascript" example, "sendback" ended up as "ja", right. In this case "ja" does not equal "javascript", which means that the user still has work to do. As a result, "ja" gets sent to the textbox along with the cursor. When the user inputs the right answer, an alert box pops up and says "You got it!".

The last bit of the function is an "else" clause for when a value for "sendback" has not been declared. Looking back, I could have avoided the need for this and the "if(sendback)" clause simply by defining "sendback" as an empty string in the first line of the function. Sorry about that, but that's the way it goes with me. I never really have a clear plan about how the code's going to look when I start scripting. I just punch in the core code and then tweak it bit by bit until the program runs the way I want it to. What ends up as the finished script may be a little clumsy, but as Larry Wall always says about Perl, "There's more than one way to do it." and as long as it works, who cares?
}else{ 
	guess.value = "";
	guess.focus();

	}
All this does is clear the box and return focus. Lesson over.

Before I leave you to ponder this script, I ought to point out that it will also work with whole sentences instead of single words. This means it can also be used for word ordering exercises.


Last Edited: 3 May 2002
© 2002 Matt Stanton