Question

I haven't got much experience with JavaScript, though I have programmed in other languages and understand generally what all the functions and Event Listeners do and whatnot.

However I have been playing around with an assignment for a few hours, and unsure of something,I have tried to use Google to find the answers but have had no luck.

So I am trying to make it so the functions are called when the event happens (such as "blur" and "click"), however it seems since all the Listeners are loaded in the "addListeners()" function. All the event listeners only trigger when the page is loaded/reloaded and they send the alerts then.

The code looks like this:

  <!DOCTYPE HTML>

<html>
<head>
<link rel="stylesheet" type="text/css" href="order-form.css">
<meta http-equiv="content-type" content="text/html; charset=windows-1250">
<title>Food order form</title>
<script type="text/Javascript">

function validateForm (form) {
    if (isNotEmpty(form.room)){  
      if (checkName(form.name)){ 

        if (validRoom(form.room)) {

          return true;
        }
      }
    }
  return false;
}

function isNotEmpty(elem){
  var str = elem.value;
  if (str == null || str.length == 0){
    alert("Please fill in the required fields.");
    return false;
  }
  else {
    return true;
  }
}

function checkName(theName) {
  if (theName.value == "") {
    alert ("Name must be entered");
    return false;
  };
  if (!validName(theName.value)){
    alert("Name should be alphabetic"); 
    return false;
  };
  return true;
}

function validName(theName) {
var valid = true;
for (var i = 0; i < theName.length; i++) {
   thisChar = theName.charAt(i);
   if ( ((thisChar < "A") || (thisChar > "Z")) &&
       ((thisChar < "a") || (thisChar > "z"))){ 
           return !valid;
       }; 
   };
theName.charAt(0).toUpperCase();
return valid;
}

function validRoom(theRoom) {
  var valid = true;
  if (theRoom.value == "") {
        alert ("Room number must be entered");
        return !valid;
  };
  roomNumber = parseInt(theRoom.value); 
  if (isNaN(roomNumber)){  
    alert("A number is required"); 
        return !valid;
  };
  if ((roomNumber < 100) || (roomNumber > 399)){
    alert("Room number must be between 100 and 399"); 
        return !valid;
  };
  return valid;
}

  function formClock() {
   var time = new Date()
   var hour = time.getHours()
   var minute = time.getMinutes()
   var second = time.getSeconds()
   var temp = "" + ((hour > 12) ? hour - 12 : hour)
   temp += ((minute < 10) ? ":0" : ":") + minute
   temp += ((second < 10) ? ":0" : ":") + second
   temp += (hour >= 12) ? " P.M." : " A.M."
   document.FoodOrder.Time.value = temp ;
   setTimeout("formClock()",1000) ;
}

  function checkRoom(theRoom) {
    if (theRoom.value ==""){
        alert("Room number must be entered");}

    roomNumber = parseInt(theRoom.value);
    if (isNaN(roomNumber)){
            alert("A number is required");}

    if ((roomNumber < 100) || (roomNumber > 399)){
            alert("Room number must be between 100 and 399"); 
      } 
}

  function addListeners(){
  clock = document.getElementById("clock");
  clock.addEventListener("mouseover", formClock, false);

  submit = document.getElementById("submit");
  submit.addEventListener("click", validateForm(FoodOrder), false);

  room = document.getElementById("room");
  room.addEventListener("blur", checkRoom(FoodOrder.room), false);
    }



  window.addEventListener("load", addListeners, false);
</script>
</head>

<body>
<h2>Froggle's Food Delivery Service<br>Order Form</h2>

<div class="form"><form NAME="FoodOrder"
      ACTION="#"
      METHOD="POST">

<p><input TYPE = "text" NAME = "Time" id="clock" SIZE = 20>
<p>Name <input TYPE = "text" NAME = "name" SIZE = 20>

<br>IST Room <input TYPE = "text" NAME = "room" id="room" SIZE =3>

<br>Food Menu: 
   <br> <input TYPE="radio" NAME="food" value="Chilli-4.50">Chilli $4.50
  <br><input TYPE="radio" NAME="food" value="Pizza-2.50"> Pizza  $2.50
  <br><input TYPE="radio" NAME="food" value="Wedges-4.50"> Wedges $4.50
  <br><input TYPE="radio" NAME="food" value="Bagel-3.00"> Bagel $3.00
<br><br>Drink Menu: 
    <br><input TYPE="radio" NAME="drink" value="Flavoured Milk-1.00"> Flavoured $1.00
    <br><input TYPE="radio" NAME="drink" value="Mineral Water-1.50"> Mineral Water  $1.50
    <br><input TYPE="radio" NAME="drink" value="Ale-4.50"> Ale $4.50

<br>
<br>  <input TYPE=SUBMIT VALUE="Order" id="submit" >
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <input TYPE=RESET VALUE="Cancel"><br>
</form></div>

  </body>
  </html>

Any and all help is appreciated thanks in advance.

Was it helpful?

Solution

The problem is with these lines of code:

  submit = document.getElementById("submit");
  submit.addEventListener("click", validateForm(FoodOrder), false);

  room = document.getElementById("room");
  room.addEventListener("blur", checkRoom(FoodOrder.room), false);

validateForm(FoodOrder) and checkRoom(FoodOrder.room) execute those functions immediately. Whenever you have a function name followed by (), you are sending a command to Javascript to execute the function immediately. You then assign the result of that function as the event listener. Obviously this calculates the result of validateForm and checkForm when the page loads, and subsequently doesn't do anything useful.

What you want to do, of course, is execute those snippets of code only when the event is fired. To do this you need to pass an actual function to addEventListener, as you do in the following line of code:

clock.addEventListener("mouseover", formClock, false);

But you need to pass parameters to the functions, which you can't do just by passing the name. So what to do? Well, you actually need to create another function which is run when the event is fired and which in turn calls the function you want with the appropriate parameters:

  submit = document.getElementById("submit");
  submit.addEventListener("click", function() {
      validateForm(FoodOrder);
  }, false);

  room = document.getElementById("room");
  room.addEventListener("blur", function() {
      checkRoom(FoodOrder.room);
  }, false);

You can see your code in action on jsFiddle, a good tool for testing and prototyping Javascript and HTML!

Note also one bit of your code which is bad practice:

setTimeout("formClock()",1000) ;

It is never a good idea to pass a string to setTimeout. You can pass a function object:

setTimeout(formClock, 1000);

OTHER TIPS

this is because you're calling your functions

validateForm(FoodOrder)

instantly and assign their result to the event

it would be fine if the function above returns another function but this is not the case

so just wrap it around in another function like this:

submit.addEventListener("click", function() { validateForm(FoodOrder) }, false);

you should also replace load event with DOMContentLoaded to attach your events earlier

But it would be the best to use jQuery:

$(function() {
    $('#clock').mouseover(formClock);
    $('#submit').click(function() { validateForm(FoodOrder) });
    $('#room').blur(function() { checkRoom(FoodOrder.room) });
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top