Check numbers entered

S

Steve Wylie

I am constructing an HTML questionnaire and one of the questions
requires people to rate some choices from 1 to 5, where 1 is their
favourite and 5 is their least favourite:

Car
Bus
Taxi cab
Train
Airplane

Each choice has an INPUT TYPE=TEXT tag to contain the response. I
also have a function that is called ONCHANGE in order to check that a
number is entered between 1 and 5:

function CheckNos(obj) {
if(obj.value.match(/[^\d]/) || obj.value<1 || obj.value>5)
{alert("Please enter a number between 1 and 5");obj.value="";return
false}
}

This works fine, but ideally I would like a function that could check
ONCHANGE that someone has not filled in the same number twice, for
example answered "1" for all of them. They are only allowed to use
each rating number once, so rating their choice 1 to 5.

Can anyone suggest a short function that could accomplish this easily?
Could I use some kind of array with 5 elements and allocate a flag
value once that number had been chosen, then check that the value had
been set?

I don't have a large amount of experience in Javascript so perhaps
someone could help me.

Thanks

Steve Wylie
United Kingdom
 
L

Lee

Steve Wylie said:
I am constructing an HTML questionnaire and one of the questions
requires people to rate some choices from 1 to 5, where 1 is their
favourite and 5 is their least favourite:

Car
Bus
Taxi cab
Train
Airplane

Each choice has an INPUT TYPE=TEXT tag to contain the response. I
also have a function that is called ONCHANGE in order to check that a
number is entered between 1 and 5:

function CheckNos(obj) {
if(obj.value.match(/[^\d]/) || obj.value<1 || obj.value>5)
{alert("Please enter a number between 1 and 5");obj.value="";return
false}
}

This works fine, but ideally I would like a function that could check
ONCHANGE that someone has not filled in the same number twice, for
example answered "1" for all of them. They are only allowed to use
each rating number once, so rating their choice 1 to 5.

Can anyone suggest a short function that could accomplish this easily?
Could I use some kind of array with 5 elements and allocate a flag
value once that number had been chosen, then check that the value had
been set?

I'll assume that this is not a class assignment.

Since the elements of the form are accessible as an array, you don't
need to create a new one. If each entry is checked as it is changed,
the only possible source of duplication is for this new value to be
a duplicate of one existing value. All you need to do is to check
each other member of this ranking group against this new value.

Here's a simple (not completely idiot-proof or the most efficient)
solution that's flexible enough to use more than once in the same
form with a different number of members in each ranking group:

<html>
<head>
<script type="text/javascript">
function checkRank(box,firstName,count){

// *box* is the text field whose onChange handler called us.
// *firstName* is the name of the first field in this rank group.
// *count* is the number of items being ranked.
// Note that *count* must be less than 10.
//
// Check that text field *box* has a value from 1 to *count*,
// then check *count* text fields beginning at *firstName*,
// ensuring that no other field has the same value as *box*.


var errMsg="Please enter a digit 1-"+count+"\n"
+"that has not been used previously."

box.value=box.value.replace(/\s*/g,""); // remove spaces

if(!box.value.search(/^$/)) return; // this change is a deletion

if(box.value.search(new RegExp("^[1-"+count+"]$"))){
alert(errMsg);
box.value="";
return;
}

var group=box.form.elements;

for(var i=0;i<group.length;i++){
if(group.name==firstName){
firstIndex=i;
break;
}
}
var firstIndex=i; // will be group.length if no match

if(firstIndex+count-1>group.length){
alert("Bad arguments! Fire the web designer!");
return;
}

for(var i=0;i<count;i++){
if(group[firstIndex+i]!=box &&
group[firstIndex+i].value==box.value){
alert(errMsg);
box.value="";
return;
}
}

}
</script>
</head>
<body>
<form>

<table>
<tr>
<td align="right">Car</td>
<td><input name="car" size="3" onchange="checkRank(this,'car',5)"></td>
</tr>
<tr>
<td align="right">Bus</td>
<td><input name="bus" size="3" onchange="checkRank(this,'car',5)"></td>
</tr>
<tr>
<td align="right">Taxi cab</td>
<td><input name="taxi" size="3" onchange="checkRank(this,'car',5)"></td>
</tr>
<tr>
<td align="right">Train</td>
<td><input name="train" size="3" onchange="checkRank(this,'car',5)"></td>
</tr>
<tr>
<td align="right">Airplane</td>
<td><input name="plane" size="3" onchange="checkRank(this,'car',5)"></td>
</tr>
</table>
<input type="reset" value="clear">
</form>
</body>
</html>



<html>
<head>
<script type="text/javascript">
function checkRank(box,firstName,count){

// *box* is the text field whose onChange handler called us.
// *firstName* is the name of the first field in this rank group.
// *count* is the number of items being ranked.
// Note that *count* must be less than 10.
//
// Check that text field *box* has a value from 1 to *count*,
// then check *count* text fields beginning at *firstName*,
// ensuring that none has the same value as *box*.

var errMsg="Please enter a digit 1-"+count+"\n"
+"that has not been used previously."

box.value=box.value.replace(/\s*/g,""); // remove spaces

if(!box.value.search(/^$/)) return; // change is a deletion

if(box.value.search(new RegExp("^[1-"+count+"]$"))){
alert(errMsg);
box.value="";
return;
}

group=box.form.elements;

for(var i=0;i<group.length;i++){
if(group.name==firstName){
firstIndex=i;
break;
}
}
var firstIndex=i; // will be group.length if no match

if(firstIndex+count-1>group.length){
alert("Bad arguments! Fire the web designer!");
return;
}

for(var i=0;i<count;i++){
if(group[firstIndex+i]!=box &&
group[firstIndex+i].value==box.value){
alert(errMsg);
box.value="";
return;
}
}

}
</script>
</head>
<body>
<form>

<table>
<tr>
<td align="right">Car</td>
<td><input name="car" size="3" onchange="checkRank(this,'car',5)"></td>
</tr>
<tr>
<td align="right">Bus</td>
<td><input name="bus" size="3" onchange="checkRank(this,'car',5)"></td>
</tr>
<tr>
<td align="right">Taxi cab</td>
<td><input name="taxi" size="3" onchange="checkRank(this,'car',5)"></td>
</tr>
<tr>
<td align="right">Train</td>
<td><input name="train" size="3" onchange="checkRank(this,'car',5)"></td>
</tr>
<tr>
<td align="right">Airplane</td>
<td><input name="plane" size="3" onchange="checkRank(this,'car',5)"></td>
</tr>
</table>
<input type="reset" value="clear">
</form>
</body>
</html>
 
S

Steve Wylie

Hi Lee

Thanks for replying with your suggested script. It actually kills 3 birds
with one stone as I notice it also checks that the entry is a valid number
and also that it is within the specified range, so that eliminates the need
for me to use my existing function just to do that on its own.

I'll have to wait till I get back to work on Thursday to try it out on my
actual questionnaire.

No, it's not a school assignment(!) I work for a local government authority
in south-east England and your script will be used in the client-side
validation of one of our consultation questionnaires we put out, asking
residents in our district their views on crime, licensing laws and fire
safety. So all pretty worthwhile stuff I think you'll agree. Think I'll
put a comment line at the top of your function, "This script by Lee", not
that anyone will see it unless they look at the source!

Thanks again for your assistance.

Steve Wylie
 
D

Dr John Stockton

JRS: In article <[email protected]>, seen
in news:comp.lang.javascript said:
I am constructing an HTML questionnaire and one of the questions
requires people to rate some choices from 1 to 5, where 1 is their
favourite and 5 is their least favourite:
Each choice has an INPUT TYPE=TEXT tag to contain the response. I
also have a function that is called ONCHANGE in order to check that a
number is entered between 1 and 5:


function CheckNos(obj) {
if(obj.value.match(/[^\d]/) || obj.value<1 || obj.value>5)
{alert("Please enter a number between 1 and 5");obj.value="";return
false}
}

Between 1 & 5, the only integers are the digits 2 3 4.

function CheckNos(obj) {
if (!obj.value.match(/^[1-5]$/)) {
alert("Please enter a digit in 1 to 5") ;
obj.value="" ;
return false }
return true }

function CheckNos(obj) {
var OK = (obj.value.match(/^[1-5]$/))
if (!OK) {alert("Please enter a digit in 1 to 5") ; obj.value="" }
return OK }
This works fine, but ideally I would like a function that could check
ONCHANGE that someone has not filled in the same number twice, for
example answered "1" for all of them. They are only allowed to use
each rating number once, so rating their choice 1 to 5.

Can anyone suggest a short function that could accomplish this easily?
Could I use some kind of array with 5 elements and allocate a flag
value once that number had been chosen, then check that the value had
been set?

Better to check on finished, since it is legitimate to put 1 2 3 1 5
then change the first one to a 4.

If you check the product for being 120, I think only 2 2 2 3 5 permuted
will falsely pass. If you check also that the sum is 15 ... .

Number them 1 2 3 5 7, check with /^[12357]$/, and you need a product of
210, which no other combination of 1 2 3 5 7 can give.

The following should work, more generally :
var A = [] // an empty array
for each entry, get value V, then A[V] = 1
check that A[1]..A[5] all exist.
or
var A = []
for each entry, get value V, then A[V] = '#'
OK = A.join('').length==5
 
S

Steve Wylie

Thank you for your response, Dr John, but I think I'll stick with
Lee's suggestion because I can't understand your number play!
(Grade 4 CSE Maths, mate - this isn't my forté!)

Thanks anyway.

Steve
 
D

Dr John Stockton

JRS: In article <[email protected]>, seen
in news:comp.lang.javascript said:
Thank you for your response, Dr John, but I think I'll stick with
Lee's suggestion because I can't understand your number play!
(Grade 4 CSE Maths, mate - this isn't my forté!)

The paragraphs containing the numbers 120 & 210 only require what in my
time was taught to eight-year-olds; I don't know what CSE requirements
are.

For a set of numbers in 1..5 to multiply to 120 they must contain one 5,
and the others must make 24. To make 24, there must be a 3, and the
others must make 8. 8 can only be made as 4*2*1 and 2*2*2.

To get 210 by multiplying five numbers selected from 1 2 3 5 & 7, there
must be a 7, a 5, a 3, a 2 and a 1 (7 5 3 2 have no common factors).

The following paragraphs of that article show what should be the
shortest and most efficient check for the general case; but of course
they are a component rather than a fully-built answer.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top