TABLE OF CONTENTS (HIDE)

JavaScript Examples

Read "Writing and Debugging JavaScripts", before trying out these examples. At a minimum, you should have the "Firebug". It is very difficult to debug JavaScript codes due to its loose syntax. One misspell character, in variable or function name, may waste a lot of your time, as JavaScript treat it as a new item or abort the function.

It is a good practice to separate the HTML contents, CSS presentation styles and JavaScript programming codes in three different files, ".html", ".css" and ".js", for ease of maintenance and good software engineering design. The now-preferred approach is not to embed styles and JavaScript codes inside HTML document, but keep them in separate files.

These examples are testing only on Firefox 7. They may not run on your browsers!

Validating HTML Form Inputs 

You can use JavaScript to valid an HTML form's input field before submitting the form data to the server. The JavaScript can verify that:

  1. A input field is required and cannot be left empty.
  2. A input field has he required number of character (e.g., password).
  3. A valid email address (user@hostname.com)
  4. A valid numeric string (e.g., phone number, zip code, credit card number), or all-letter string
  5. A valid date.
Screenshot

Click the image to run the demo.

image
"FormValidation.html"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<html>
<head>
  <title>Test JavaScript Form Validation</title>
  <link rel="stylesheet" href="FormValidation.css">
  <script type="text/javascript" src="FormValidation.js" ></script>
</head>
 
<body>
  <h2>Test JavaScript Form Validation</h2>
 
  <form id="theForm" method="get" action="submitData">
    <table>
    <tr>
      <td>Name<span class="red">*</span></td>
      <td><input type="text" id="name" name="name"/></td>
      <td id="nameError" class="red">&nbsp;</td></tr>
    <tr>
      <td>Address</td>
      <td><input type="text" id="address" name="address" /></td>
      <td id="addressError" class="red">&nbsp;</td></tr>
    <tr>
      <td>Zip Code<span class="red">*</span></td>
      <td><input type="text" id="zipcode" name="zipcode" /></td>
      <td id="zipcodeError" class="red">&nbsp;</td></tr>
    <tr>
      <td>Country<span class="red">*</span></td>
      <td><select id="country" name="country">
            <option value="" selected>Please select...</option>
            <option value="AA">AA</option>
            <option value="BB">BB</option>
            <option value="CC">CC</option>
          </select><br /></td>
      <td id="countryError" class="red">&nbsp;</td></tr>
    <tr>
      <td>Gender<span class="red">*</span></td>
      <td><input type="radio" name="gender" value="m" />Male
          <input type="radio" name="gender" value="f" />Female</td>
      <td id="genderError" class="red">&nbsp;</td></tr>
    <tr>
      <td>Preferences<span class="red">*</span></td>
      <td><input type="checkbox" name="color" value="r" />Red
          <input type="checkbox" name="color" value="g" />Green
          <input type="checkbox" name="color" value="b" />Blue</td>
      <td id="colorError" class="red">&nbsp;</td></tr>
    <tr>
      <td>Phone<span class="red">*</span></td>
      <td><input type="text" id="phone" name="phone" /></td>
      <td id="phoneError" class="red">&nbsp;</td></tr>
    <tr>
      <td>Email<span class="red">*</span></td>
      <td><input type="text" id="email" name="email" /></td>
      <td id="emailError" class="red">&nbsp;</td></tr>
    <tr>
      <td>password (6-8 characters)<span class="red">*</span></td>
      <td><input type="password" id="password" name="password" /></td>
      <td id="passwordError" class="red">&nbsp;</td></tr>
    <tr>
      <td>Verify password<span class="red">*</span></td>
      <td><input type="password" id="pwVerified" name="pwVerified" /></td>
      <td id="pwVerifiedError" class="red">&nbsp;</td></tr>
    <tr>
      <td>&nbsp;</td>
      <td><input type="submit" value="SEND" id="submit"/>&nbsp;
          <input type="reset" value="CLEAR" id="reset"/></td>
      <td>&nbsp;</td></tr>
    </table>
  </form>
</body>
</html>
"FormValidation.css"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.red {  /* for error messages */
   color: red;
}
 
input.error {  /* for the error input text fields */
   border: 1px red inset;
   padding: 2px;
}
 
table {
   border: 0;
}
 
td {
   margin: 0;
   padding: 3px 10px 3px 3px;
}
"FormValidation.js"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
window.onload = init;
 
// The "onload" handler. Run after the page is fully loaded.
function init() {
   // Attach "onsubmit" handler
   document.getElementById("theForm").onsubmit = validateForm;
   // Attach "onclick" handler to "reset" button
   document.getElementById("reset").onclick = clearDisplay;
   // Set initial focus
   document.getElementById("name").focus();
}
 
/* The "onsubmit" handler to validate the input fields.
 * Most of the input validation functions take 2 arguments:
 * inputId or inputName: the "id" of the <input> element to be validated
 *   or "name" for checkboxes and radio buttons.
 * errorMsg: the error message to be displayed if validation fails.
 *   The message shall be displayed on an element with id of
 *   inputID+"Error" if it exists; otherwise via an alert().
 */
function validateForm() {
   return (isNotEmpty("name", "Please enter your name!")
        && isNumeric("zipcode", "Please enter a 5-digit zip code!")
        && isLengthMinMax("zipcode", "Please enter a 5-digit zip code!", 5, 5)
        && isSelected("country", "Please make a selection!")
        && isChecked("gender", "Please check a gender!")
        && isChecked("color", "Please check a color!")
        && isNumeric("phone", "Please enter a valid phone number!")
        && isValidEmail("email", "Enter a valid email!")
        && isLengthMinMax("password", "Enter a valid password!", 6, 8)
        && verifyPassword("password", "pwVerified", "Different from the password!"));
}
 
// Return true if the input value is not empty
function isNotEmpty(inputId, errorMsg) {
   var inputElement = document.getElementById(inputId);
   var errorElement = document.getElementById(inputId + "Error");
   var inputValue = inputElement.value.trim();
   var isValid = (inputValue.length !== 0);  // boolean
   showMessage(isValid, inputElement, errorMsg, errorElement);
   return isValid;
}
 
/* If "isValid" is false, print the errorMsg; else, reset to normal display.
 * The errorMsg shall be displayed on errorElement if it exists;
 *   otherwise via an alert().
 */
function showMessage(isValid, inputElement, errorMsg, errorElement) {
   if (!isValid) {
      // Put up error message on errorElement or via alert()
      if (errorElement !== null) {
         errorElement.innerHTML = errorMsg;
      } else {
         alert(errorMsg);
      }
      // Change "class" of inputElement, so that CSS displays differently
      if (inputElement !== null) {
         inputElement.className = "error";
         inputElement.focus();
      }
   } else {
      // Reset to normal display
      if (errorElement !== null) {
         errorElement.innerHTML = "";
      }
      if (inputElement !== null) {
         inputElement.className = "";
      }
   }
}
 
// Return true if the input value contains only digits (at least one)
function isNumeric(inputId, errorMsg) {
   var inputElement = document.getElementById(inputId);
   var errorElement = document.getElementById(inputId + "Error");
   var inputValue = inputElement.value.trim();
   var isValid = (inputValue.search(/^[0-9]+$/) !== -1);
   showMessage(isValid, inputElement, errorMsg, errorElement);
   return isValid;
}
 
// Return true if the input value contains only letters (at least one)
function isAlphabetic(inputId, errorMsg) {
   var inputElement = document.getElementById(inputId);
   var errorElement = document.getElementById(inputId + "Error");
   var inputValue = inputElement.value.trim();
   var isValid = inputValue.match(/^[a-zA-Z]+$/);
   showMessage(isValid, inputElement, errorMsg, errorElement);
   return isValid;
}
 
// Return true if the input value contains only digits and letters (at least one)
function isAlphanumeric(inputId, errorMsg) {
   var inputElement = document.getElementById(inputId);
   var errorElement = document.getElementById(inputId + "Error");
   var inputValue = inputElement.value.trim();
   var isValid = inputValue.match(/^[0-9a-zA-Z]+$/);
   showMessage(isValid, inputElement, errorMsg, errorElement);
   return isValid;
}
 
// Return true if the input length is between minLength and maxLength
function isLengthMinMax(inputId, errorMsg, minLength, maxLength) {
   var inputElement = document.getElementById(inputId);
   var errorElement = document.getElementById(inputId + "Error");
   var inputValue = inputElement.value.trim();
   var isValid = (inputValue.length >= minLength) && (inputValue.length <= maxLength);
   showMessage(isValid, inputElement, errorMsg, errorElement);
   return isValid;
}
 
// Return true if the input value is a valid email address
// (For illustration only. Should use regexe in production.)
function isValidEmail(inputId, errorMsg) {
   var inputElement = document.getElementById(inputId);
   var errorElement = document.getElementById(inputId + "Error");
   var inputValue = inputElement.value;
   var atPos = inputValue.indexOf("@");
   var dotPos = inputValue.lastIndexOf(".");
   var isValid = (atPos > 0) && (dotPos > atPos + 1) && (inputValue.length > dotPos + 2);
   showMessage(isValid, inputElement, errorMsg, errorElement);
   return isValid;
}
 
// Return true if selection is made (not default of "") in <select> input
function isSelected(inputId, errorMsg) {
   var inputElement = document.getElementById(inputId);
   var errorElement = document.getElementById(inputId + "Error");
   var inputValue = inputElement.value;
   // You need to set the default value of <select>'s <option> to "".
   var isValid = inputValue !== "";
   showMessage(isValid, inputElement, errorMsg, errorElement);
   return isValid;
}
 
// Return true if the one of the checkboxes or radio buttons is checked
function isChecked(inputName, errorMsg) {
   var inputElements = document.getElementsByName(inputName);
   var errorElement = document.getElementById(inputName + "Error");
   var isChecked = false;
   for (var i = 0; i < inputElements.length; i++) {
      if (inputElements[i].checked) {
         isChecked = true;  // found one element checked
         break;
      }
   }
   showMessage(isChecked, null, errorMsg, errorElement);
   return isChecked;
}
 
// Verify password. The password is kept in element with id "pwId".
// The verified password in id "verifiedPwId".
function verifyPassword(pwId, verifiedPwId, errorMsg) {
   var pwElement = document.getElementById(pwId);
   var verifiedPwElement = document.getElementById(verifiedPwId);
   var errorElement = document.getElementById(verifiedPwId + "Error");
   var isTheSame = (pwElement.value === verifiedPwElement.value);
   showMessage(isTheSame, verifiedPwElement, errorMsg, errorElement);
   return isTheSame;
}
 
// The "onclick" handler for the "reset" button to clear the display
function clearDisplay() {
   var elms = document.getElementsByTagName("*");  // all tags
   for (var i = 0; i < elms.length; i++) {
      if ((elms[i].id).match(/Error$/)) {  // no endsWith() in JS?
         elms[i].innerHTML = "";
      }
      if (elms[i].className === "error") {  // assume only one class
         elms[i].className = "";
      }
   }
   // Set initial focus
   document.getElementById("name").focus();
}
Dissecting the Program
  1. We seperate the HTML contents, CSS presentation styles, and JavaScript programming codes in three files.
  2. Let's begin with the HTML:
    1. <form id="theForm" method="get" action="submitData">
      We define an HTML form with unique id="theForm".
    2. <table>...</table>
      We set up a table with three columns, which displays the labels, input elements and error messages (if any), respectively. See the screenshot.
    3. <td><input type="text" id="name" name="name"/></td>
      <td id="nameError" class="red">&nbsp;</td>

      Each <input> element is assigned an unique id, so that it can be selected in JavaScript via the document.getElementById() function. It also contain a name attribute, with is set to the same value as id. The <td> element in the 3rd column for displaying the error message has an id made up of input element's id plus "Error".
    4. <select ...><option value="" selected>Please select...</option>
      For the <select> element, we define a default non-selection <option>, with value of "" (empty string) and label of "Please select...". This is necessary so that we can detect whether the user has made a selection.
    5. For checkboxes and radio buttons, we cannot use id, as there are more than one elements and id must be unique. Instead, we set a common name. The JavaScript would use document.getElementsByName() to select all the elements with the same name. The <td> element for displaying the error message has an id of name plus "Error".
  3. The CSS is simple:
    1. .red { color: red; }
      A class-selector for displaying the error messages in red.
    2. input.error { border: 1px red inset; ... }
      A class-selector for displaying the erroneous <input> element with a red border. This is only applicable to text and password fields.
  4. We move on to the JavaScript:
    1. window.onload = init;
      We attach the init() function as the onload event handler. That is init() runs after the page is fully loaded.
    2. function init() {
         document.getElementById("theForm").onsubmit = validateForm;
         document.getElementById("reset").onclick = clearDisplay;
         document.getElementById("name").focus();
      }

      In the init() function, we attach validateForm function as the onsubmit handler; clearDisplay function as the onclick handler; and set the initial focus to the first input element having the id of name.
    3. function validateForm() { return (isNotEmpty(...) && isNumeric(...) && ...); }
      The validateForm() function triggered when the user clicks the submit button. It calls the various input validation functions to validate the input fields. It returns true if all the input validation functions return true, resulted in the form data to be submitted to the action's url. Otherwise, it returns false, the form data will not be submitted and the current page remains.
    4. function isNotEmpty(inputId, errorMsg) {
         var inputElement = document.getElementById(inputId);
         var errorElement = document.getElementById(inputId + "Error");

      Let's look into an input validation function isNotEmpty() in details. It takes 2 arguments, an input element's id, and an error message. It first gets the input element via the inputId. It then gets the element for displaying error message via our agree-upon convention that its id is inputId plus "Error".
    5. var inputValue = inputElement.value.trim();
      var isValid = (inputValue.length !== 0);
      showMessage(isValid, inputElement, errorMsg, errorElement);
      return isValid;

      It gets the value from the input element, trim() to remove the leading and trailing whitespaces. It then checks for empty string, and assigned the result to a boolean variable isValid. It invokes the showMessage() and return the boolean flag.
    6. function showMessage(isValid, inputElement, errorMsg, errorElement) { ... }
      The showMesaage() accepts 4 arguments. If the input is invalid (isValid is false), it set the innerHMTL of errorElement to the errorMsg, and the class of inputElement to "error". CSS class-selector input.error will display the input element with a red boundary. If the errorElement is null, the errorMsg will be displayed via an alert(). Otherwise, it clears the innerHTML of the errorElement and the class attribute of the inputElement.
    7. function isNumeric(inputId, errorMsg) {
         ......
         var isValid = (inputValue.search(/^[0-9]+$/) !== -1);

      For input validation function such as isNumeric(), we use regular expression to perform pattern matching, e.g., regexe /^[0-9]+$/ matches 1 or more digits; regexe /^[a-zA-Z]+$/ matches one or more letters (but no internationalization?!); /^[0-9]{5,8}$/ matches string of 5 to 8 digits. The string.search(regexe) return the position of the match or -1 if there is no match. Regular expression is extremely powerful for text processing. Read "Regular Expression" for more details.
    8. In isValidEmail() function, we check for the pattern "a@b.cc" by checking for the position of @ and '.'. This is done merely for illustration. In production, it is much easier to use a regexe such as /^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/, or /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ (there are scary, but much more powerful in 1 line of code).
    9. verifyPassword(): [TODO]
    10. clearDisplay(): [TODO]
  5. Some notes in form input validation:
    1. What is a valid name, address and zipcode? The name and address vary from country to country and they may contain non-ASCII characters. Zipcode may not be numeric and may contain space.
    2. A password may contain letter, digit and special characters such as @. it probably does not contain space.
    [TODO more]

Another Version

HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<!DOCTYPE html>
<html>
<head>
  <title>Test JavaScript Form Validation</title>
  <link rel="stylesheet" href="FormValidation.css">
  <script type="text/javascript" src="FormValidation.js" ></script>
</head>
 
<body>
  <h2>Test JavaScript Form Validataion</h2>
 
  <form method="get" action="submitData" onsubmit="return validateForm(this)">
    <table>
    <tr>
      <td>Name<span class="red">*</span></td>
      <td>
        <input type="text" id="name" name="name"/>&nbsp;&nbsp;
        <span id="nameError" class="red"></span>
      </td></tr>
    <tr>
      <td>Address</td>
      <td>
        <input type="text" id="address" name="address" />&nbsp;&nbsp;
        <span id="addressError" class="red"></span>
      </td></tr>
    <tr>
      <td>Zip Code<span class="red">*</span></td>
      <td>
        <input type="text" id="zipcode" name="zipcode" />&nbsp;&nbsp;
        <span id="zipcodeError" class="red"></span>
      </td></tr>
    <tr>
      <td>Country<span class="red">*</span></td>
      <td>
        <select id="country" name="country">
          <option value="" selected>Please select...</option>
          <option value="AA">AA</option>
          <option value="BB">BB</option>
          <option value="CC">CC</option>
        </select>&nbsp;&nbsp;
        <span id="countryError" class="red"></span>
      </td></tr>
    <tr>
      <td>Gender<span class="red">*</span></td>
      <td>
        <input type="radio" name="gender" value="m" />Male
        <input type="radio" name="gender" value="f" />Female &nbsp;&nbsp;
        <span id="genderError" class="red"></span>
      </td></tr>
    <tr>
      <td>Preferences<span class="red">*</span></td>
      <td>
        <input type="checkbox" name="color" value="r" />Red
        <input type="checkbox" name="color" value="g" />Green
        <input type="checkbox" name="color" value="b" />Blue &nbsp;&nbsp;
        <span id="colorError" class="red"></span>
      </td></tr>
    <tr>
      <td>Phone<span class="red">*</span></td>
      <td>
        <input type="text" id="phone" name="phone" />&nbsp;&nbsp;
        <span id="phoneError" class="red"></span>
      </td></tr>
    <tr>
      <td>Email<span class="red">*</span></td>
      <td>
        <input type="text" id="email" name="email" />
        <span id="emailError" class="red"></span>
      </td></tr>
    <tr>
      <td>password (6-8 characters)<span class="red">*</span></td>
      <td>
        <input type="password" id="password" name="password" />&nbsp;&nbsp;
        <span id="passwordError" class="red"></span>
      </td></tr>
    <tr>
      <td>Verify password<span class="red">*</span></td>
      <td>
        <input type="password" id="pwVerified" name="pwVerified" />&nbsp;&nbsp;
        <span id="pwVerifiedError" class="red"></span>
      </td></tr>
    <tr>
      <td>&nbsp;</td>
      <td>
        <input type="submit" value="SEND" id="submit"/>&nbsp;
        <input type="reset" value="CLEAR" id="reset"/>&nbsp;&nbsp;
      </td></tr>
    </table>
  </form>
</body>
</html>
CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* for error messages */
.red {
   color: red;
}
 
/* for the error input text fields */
input.error {
   border: 1px red inset;
   padding: 2px;
}
 
table {
   border: 0;
}
 
td {
   margin: 0;
   padding: 3px 10px 3px 3px;
}
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
window.onload = init;    // run init() after the page is loaded
 
/*
 * Initialization
 */
function init() {
   // Attach "onclick" handler to "reset" button
   document.getElementById("reset").onclick = clearDisplay;
   // Set initial focus
   document.getElementById("name").focus();
}
 
/*
 * The "onsubmit" handler to validate the input fields.
 * Most of the input validation functions take 3 arguments:
 *   inputElement: to be validated
 *   errMsg: the error message to be displayed if validation fails.
 *   errElm: to place the error message (or via alert if this is null)
 */
function validateForm(thisForm) {
   with(thisForm) {
      return (isNotEmpty(name.value, name, "Please enter your name!", nameError)
           && isNumeric(zipcode.value, zipcode, "Please enter a 5-digit zip code!", zipcodeError)
           && isLengthMinMax(zipcode.value, 5, 5, zipcode, "Please enter a 5-digit zip code!", zipcodeError)
           && isSelected(country.value, country, "Please make a selection!", countryError)
           && isChecked("gender", null, "Please check a gender!", genderError)
           && isChecked("color", null, "Please check a color!", colorError)
           && isNumeric(phone.value, phone, "Please enter a valid phone number!", phoneError)
           && isValidEmail(email.value, email, "Enter a valid email!", emailError)
           && isValidPassword(password.value, password, "Password shall be 6-8 characters!", passwordError)
           && verifyPassword(password.value, pwVerified.value, pwVerified, "Different from new password!", pwVerifiedError));
   }
}
 
/*
 * Helper function to show or clear error message, and set focus
 *   to the input element for correcting error.
 * If isValid is false, show the errMsg on errElm, and place the
 *   focus on the focusInputElm for correcting the error.
 * Else, clear previous errMsg on errElm, if any.
 *
 * Parameters focusInputElm, errMsg and errElm are optional.
 */
function showMessageAndFocus(isValid, focusInputElm, errMsg, errElm) {
   if (!isValid) {
      // Show errMsg on errElm, if provided.
      if (errElm !== undefined && errElm !== null
            && errMsg !== undefined && errMsg !== null) {
         errElm.innerHTML = errMsg;
      }
      // Set focus on Input Element for correcting error, if provided.
      if (focusInputElm !== undefined && focusInputElm !== null) {
         focusInputElm.className = "error";
         focusInputElm.focus();
      }
   } else {
      // Clear previous error message on errElm, if provided.
      if (errElm !== undefined && errElm !== null) {
         errElm.innerHTML = "";
      }
      if (focusInputElm !== undefined && focusInputElm !== null) {
         focusInputElm.className = "";
      }
   }
}
 
/* Validate the inputValue is not empty (and not null). */
function isNotEmpty(inputValue, focusInputElm, errMsg, errElm) {
   var isValid = (inputValue !== null)
              && (inputValue.trim() !== "");
   showMessageAndFocus(isValid, focusInputElm, errMsg, errElm);
   return isValid;
}
 
/* Return true if the input value contains only digits (at least one) */
function isNumeric(inputValue, focusInputElm, errMsg, errElm) {
   var isValid = (inputValue !== null
               && inputValue.trim().match(/^\d+$/) !== null);
   showMessageAndFocus(isValid, focusInputElm, errMsg, errElm);
   return isValid;
}
 
/* Return true if the input value contains only letters (at least one) */
function isAlphabetic(inputValue, focusInputElm, errMsg, errElm) {
   var isValid = (inputValue !== null
               && inputValue.trim().match(/^[a-zA-Z]+$/) !== null) ;
   showMessageAndFocus(isValid, focusInputElm, errMsg, errElm);
   return isValid;
}
 
/* Return true if the input value contains only digits and letters (at least one) */
function isAlphanumeric(inputValue, focusInputElm, errMsg, errElm) {
   var isValid = (inputValue !== null
               && inputValue.trim().match(/^[0-9a-zA-Z]+$/) !== null);
   showMessageAndFocus(isValid, focusInputElm, errMsg, errElm);
   return isValid;
}
 
/* Return true if the input length is between minLength and maxLength */
function isLengthMinMax(inputValue, minLength, maxLength, focusInputElm, errMsg, errElm) {
   var inputValue = inputValue.trim();
   var isValid = (inputValue.length >= minLength) && (inputValue.length <= maxLength);
   showMessageAndFocus(isValid, focusInputElm, errMsg, errElm);
   return isValid;
}
 
// Return true if the input value is a valid email address
function isValidEmail(inputValue, focusInputElm, errMsg, errElm) {
   var isValid = (inputValue !== null)
               && (inputValue.trim().match(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/) !== null);
   showMessageAndFocus(isValid, focusInputElm, errMsg, errElm);
   return isValid;
}
 
/* Return true if selection is made (not default of "") in <select> input */
function isSelected(inputValue, focusInputElm, errMsg, errElm) {
   // You need to set the default value of <select>'s <option> to "".
   var isValid = (inputValue !== "");
   showMessageAndFocus(isValid, focusInputElm, errMsg, errElm);
   return isValid;
}
 
/* Return true if the one of the checkboxes or radio buttons is checked
 * Need to check all elements of the "names" */
function isChecked(inputName, focusInputElm, errMsg, errElm) {
   var inputElements = document.getElementsByName(inputName);
   var isChecked = false;
   for (var i = 0; i < inputElements.length; i++) {
      if (inputElements[i].checked) {
         isChecked = true;  // found one element checked
         break;
      }
   }
   showMessageAndFocus(isChecked, focusInputElm, errMsg, errElm);
   return isChecked;
}
 
 
// Validate password, 6-8 characters of [a-zA-Z0-9_]
function isValidPassword(inputValue, focusInputElm, errMsg, errElm) {
   var isValid = (inputValue !== null)
               && (inputValue.trim().match(/^\w{6,8}$/) !== null);
   showMessageAndFocus(isValid, focusInputElm, errMsg, errElm);
   return isValid;
}
 
 
// Verify password.
function verifyPassword(pw, verifiedpw, focusInputElm, errMsg, errElm) {
   var isTheSame = (pw === verifiedpw);
   showMessageAndFocus(isTheSame, focusInputElm, errMsg, errElm);
   return isTheSame;
}
 
// The "onclick" handler for the "reset" button to clear the display
function clearDisplay() {
   var elms = document.getElementsByTagName("*");  // all tags
   for (var i = 0; i < elms.length; i++) {
      if ((elms[i].id).match(/Error$/)) {
         elms[i].innerHTML = "";
      }
      if (elms[i].className === "error") {  // assume only one class
         elms[i].className = "";
      }
   }
   // Set initial focus
   document.getElementById("name").focus();
}
Notes:
  1. For the JavaScript validation functions, it is more flexible to separate the input value and input element, so that the function can also be used in other contexts without the input element. Also, I made focusInputElm, errMsg, and errElm optional, so that these functions can be used for pure input value validation.

Tic-Tac-Toe

Screenshot

Click the image to run the demo.

image
"TitTacToe.html"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html>
<head>
  <title>Tic-Tac-Toe</title>
  <link rel="stylesheet" href="TicTacToe.css">
  <script src="TicTacToe.js"></script>
</head>
 
<body>
  <h1>Tic-Tac-Toe</h1>
  <table>
    <tr>
      <td id="cell0">&nbsp;</td>
      <td id="cell1">&nbsp;</td>
      <td id="cell2">&nbsp;</td>
    </tr>
    <tr>
      <td id="cell3">&nbsp;</td>
      <td id="cell4">&nbsp;</td>
      <td id="cell5">&nbsp;</td>
   </tr>
   <tr>
      <td id="cell6">&nbsp;</td>
      <td id="cell7">&nbsp;</td>
      <td id="cell8">&nbsp;</td>
    </tr>
  </table>
  <p><input type="button" id="btnNewGame" value="New Game" /></p>
</body>
</html>
"TitTacToe.css"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
body {
  background-color: white;
  color: black;
  font-family: Arial, Helvetica, sans-serif;
}
 
h1 {
  font-size: 28px;
}
 
table {
  border-collapse: collapse;
}
 
td {
  padding: 10px;
  border: 3px #888 solid;
  text-align: center;
  font-size: 28px;
  width: 20%;
  font-family: Consolas, monospace
}
 
/* Set the border (top, right, bottom, left) of the cells */
#cell0 { border-style: none  solid solid none;  }
#cell1 { border-style: none  solid solid solid; }
#cell2 { border-style: none  none  solid solid; }
#cell3 { border-style: solid solid solid none;  }
#cell4 { border-style: solid solid solid solid; }
#cell5 { border-style: solid none  solid solid; }
#cell6 { border-style: solid solid none  none;  }
#cell7 { border-style: solid solid none  solid; }
#cell8 { border-style: solid none  none  solid; }
 
/* winning cells style */
.winningCell {
  background-color: #f88;
}
"TitTacToe.js"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
 * The cells are numbered from 0 to 8 from top-left to bottom-right.
 */
 
window.onload = init;  // run init() after the page is loaded
 
const NUM_CELLS = 9;
 
// A pattern is a 9-bit number where bit x represents cell x.
const WINNING_PATTERNS
    = new Array(0007, 0070, 0700, 0444, 0222, 0111, 0421, 0124); // Octal
var crossPattern, noughtPattern;  // keep the plays so far
 
// "cross" is currently playing (boolean of true or false)
var crossPlaying;
 
// Initialize the game
function init() {
   resetGame();
   document.getElementById("btnNewGame").onclick = resetGame;
}
 
// Reset game by clearing all the cells and player's pattern
function resetGame() {
   crossPattern = 0;
   noughtPattern = 0;
   crossPlaying = true;
   for (var cellNum = 0; cellNum < NUM_CELLS; cellNum++) {
      var elm = document.getElementById("cell" + cellNum);
      elm.innerHTML = "&nbsp;";  // Clear content
      elm.className = "";        // Reset the class, used by CSS
      elm.onmousedown = play;    // Attach mouse click handler
   }
}
 
// Mouse-click handler
function play(evt) {
   var thisCell;
   if (evt) {  // non-IE
     thisCell = evt.target;
   } else {    // IE
     thisCell = window.event.srcElement;
   }
 
   // Place the seed on the cell clicked and update the player's pattern
   if (thisCell.innerHTML === "&nbsp;") {
      if (crossPlaying) {
         thisCell.innerHTML = "x";
         crossPattern |=  Math.pow(2, thisCell.id.charAt(4));
      } else {
         thisCell.innerHTML = "o";
         noughtPattern |=  Math.pow(2, thisCell.id.charAt(4));
      }
   }
   if (!checkWin()) {
      // Continue playing
      // Disable mouse click for this cell. This cell is no longer active
      thisCell.onmousedown = null;
      // toggling the current player
      crossPlaying = !crossPlaying;
   }
}
 
// Check if the current player wins the game
function checkWin() {
   var theWinningPattern = -1;
   var playerPattern;
   if (crossPlaying) {
      playerPattern = crossPattern;
   } else {
      playerPattern = noughtPattern;
   }
 
   // Check if playerPattern is one of the winning patterns
   for (var i = 0; i < WINNING_PATTERNS.length; i++) {
      if ((WINNING_PATTERNS[i] & playerPattern) === WINNING_PATTERNS[i]) {
         theWinningPattern = WINNING_PATTERNS[i];
         break;
      }
   }
 
   // Change the class name of the cells of the winning pattern
   // CSS class-selector displays them differently
   if (theWinningPattern > -1) {
      for (var cellNum = 0; cellNum < NUM_CELLS; cellNum++) {
         var elm = document.getElementById("cell" + cellNum);
         if (theWinningPattern & Math.pow(2, cellNum)) {
            elm.className = "winningCell";
         }
         elm.onmousedown = null;  // disable mouse click for all cells
      }
      return true;
   } else {
      return false;
   }
}
Dissecting the Program
  1. There are three files: an HTML, a CSS and a JavaScript, which cleanly separate their respective functions. Take note that the HTML file deals only with the content and there is no script nor style embedded.
  2. The HTML page puts up a 3x3 table of 9 cells, each with a unique id. It also include a button for creating a new game.
  3. The CSS define the presentation style for the HTML elements. A special class-selector called ".winningCell" is defined to change the background color of the 3 winning cells.
  4. The init() function, which is the onload handler, resets the game variables and cell contents via resetGame(), and attaches the function resetGame() as the button's onclick handler. Take note that clicking the "New Game" button does not involve refreshing of the page (which requires a costly access to the server), but simply reseting all the game variables and cell contents.
  5. We use window.onload=init to ensure that init() is run after the page is fully loaded, so as to access the elements defined in the page.
  6. We define a global array WINNING_PATTERNS, to keep the eight 3-in-a-row winning patterns. Each pattern is a 9-bit number, with bit-x represents cell-x. For example, the binary number 000000111 indicates that cells 0, 1, and 2 are occupied. The numbers are expressed in octal with a leading zero. (JavaScript does not seen to support binary number with a leading 0b, like C/C++/Java.) Similarly, we define two global variables, crossPattern and noughtPattern to keep track of the crosses and noughts placed on the game board so far.
  7. A boolean flag crossPlaying is used to keep track of the current player.
  8. The resetGame() function resets the game variables (empty the crossPattern and noughtPattern and set the current player to "cross"). It also clears the contents of the cells, and attaches play() function as the onmousedown event handler, so that the user can click on the cell to play the game.
  9. Whenever the user clicks on a cell, the play() event handler triggers with the mousedown event object as the argument. It first identifies the cell-clicked (with different methods for IE and non-IE browsers). It places the current player's symbol on the game board, and updates the player's pattern. It then calls the checkWin() to check if the current player wins the game. If not, it disables this cell by removing the onmousedown handler, and toggles the current player.
  10. The chcekWin() function checks the current player's pattern against the eight winning patterns. If the current player wins, it highlights the three winning cells by changing the cells' class attribute. The CSS class-selector will automatically display the cell with a different background color. It also disables all the cells. User has to click the "New Game" button to start a new game.

A Date Chooser

Screenshot

Click the image to run the demo.

image
"dateUtil.js"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Return true if the given year is a leap year
function isLeapYear(year) {
   return ((year % 4) === 0 && ((year % 100) !== 0 || (year % 400) === 0));
}
 
// Return the number of days in the given month (1-12) of the year (xxxx)
function getDaysInMonth(year, month) {
   if (month === 2) {
      if (isLeapYear(year)) {
         return 29;
      } else {
         return 28;
      }
   } else if ((month === 1) || (month === 3) || (month === 5) || (month === 7)
       || (month === 8) || (month === 10) || (month === 12)) {
      return 31;
   } else {
      return 30;
   }
}
 
// Get the day of the week given year, month (1-12) and day (1-31)
function getDayInWeek(year, month, day) {
  var weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday",
                  "Thursday", "Friday", "Saturday"];
  var theDate = new Date(year, month-1, day);
  return weekdays[theDate.getDay()];
}
Dissecting the Program
  1. The function isLeapYear(year) returns true if year is a leap year.
  2. The function getDaysInMonth(year, month) returns the number of days in the given month (1-12) of the year (4-digit). Take note that JavaScript represents a month in the range of 0-11 (for Jan to Dec), instead of 1-12.
  3. The function getDayInWeek(year, month, day) returns the day of the week (Sunday to Saturday). It constructs a built-in object Date with the given year, month and day, and use the getDay() function of the Date object to obtain the day of the week in the range of 0-6.
"JSDateChooser.html"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<html>
<head>
  <title>A Date Chooser</title>
  <script type="text/javascript" src="DateUtil.js"></script>
  <script type="text/javascript" src="DateChooser.js"></script>
</head>
<body>
  <h2>A Date Chooser</h2>
  <form id="theForm">
    Year: <input type="text" name="year" id="year" size="4" maxLength="4" />
    Month: <select name="month" id="month">
      <option id="month1" value="1">Jan</option>
      <option id="month2" value="2">Feb</option>
      <option id="month3" value="3">Mar</option>
      <option id="month4" value="4">Apr</option>
      <option id="month5" value="5">May</option>
      <option id="month6" value="6">Jun</option>
      <option id="month7" value="7">Jul</option>
      <option id="month8" value="8">Aug</option>
      <option id="month9" value="9">Sep</option>
      <option id="month10" value="10">Oct</option>
      <option id="month11" value="11">Nov</option>
      <option id="month12" value="12">Dec</option>
    </select>
    Day: <select name="day" id="day"></select>&nbsp;
    <input type="text" name="dayInWeek" id="dayInWeek" readonly />&nbsp;
    <input type="button" id="btnNow" value="Now" />
  </form>
</body>
</html>
"DateChooser.js"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
window.onload = init;
 
// Global variables for the currently selected year, month and day
var selectedYear;   // 4-digit year
var selectedMonth;  // 1 to 12 for Jan to Dec
var selectedDay;    // 1 to 31
 
// The "onload" handler, runs after the page is fully loaded.
function init() {
   setToday();      // Set global variables
   updateDisplay();
 
   document.getElementById("year").onchange = function() {
      selectedYear=this.value;
      // In case the current day is no longer valid for non-leap year,
      // e.g., 29 Feb 2001. Set to the last year of the month
      updateDayDisplay();
      updateDayInWeekDisplay();
   }
 
   document.getElementById("month").onchange = function() {
      selectedMonth=this.value;
      // In case the current day is no longer valid, e.g., 31 in Feb.
      // Set to the last year of the month
      updateDayDisplay();
      updateDayInWeekDisplay()
   }
 
   document.getElementById("day").onchange = function() {
      selectedDay=this.value;
      updateDayInWeekDisplay();
   }
 
   document.getElementById("btnNow").onclick = function() {
      setToday();
      updateDisplay();
   }
}
 
// Set global variable selectedYear, selectedMonth and selectedDay
// to today.
function setToday() {
   var now = new Date();
   selectedYear = now.getFullYear();   // 4-digit year
   selectedMonth = now.getMonth() + 1; // 1 to 12 for Jan to Dec
   selectedDay = now.getDate();        // 1 to 31
}
 
// Update the year, month, day and day-in-week display according
// to the selected values.
function updateDisplay() {
   // Set the value of text fields and select the correct options
   document.getElementById("year").value = selectedYear;
   updateMonthDisplay();
   updateDayDisplay();
   updateDayInWeekDisplay();
}
 
function updateMonthDisplay() {
   document.getElementById("month" + selectedMonth).selected = true;
}
 
function updateDayDisplay() {
   var elm = document.getElementById("day");
   elm.innerHTML = "";
   var daysInMonth = getDaysInMonth(selectedYear, selectedMonth);
   // The selectedDay is no longer valid. Set to the last day of month
   if (selectedDay > daysInMonth) {
      selectedDay = daysInMonth;
   }
   var options = "";
   for (var day = 1; day <= daysInMonth; day++) {
      options += "<option value='" + day + "'";
      if (day === selectedDay) {
         options += " selected";
      }
      options += ">" + day + "</option>";
   }
   elm.innerHTML = options;
}
 
function updateDayInWeekDisplay() {
   document.getElementById("dayInWeek").value
      = getDayInWeek(selectedYear, selectedMonth, selectedDay);
}
Dissecting the Program
  1. The form consists of 5 input elements: a text field for the year, pull-down menus for month and day, a read-only text field for the day of the week. and a button to set the display to today. When the page is first loaded, the current date is display. If you change the year, month or day, the day of the week changes. If you change the year or month, the options in day adjust automatically, e.g., there are 28/29 days in Feb for non-leap and leap years.
  2. [TODO]

Calendars

A Simple Monthly Calendar

Click the image to run the demo.

image
"CalendarSimple.html"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCtype html>
<html>
<head>
  <title>Calendar</title>
  <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
  <link rel="stylesheet" href="CalendarSimple.css">
  <script type="text/javascript" src="DateUtil.js"></script>
  <script type="text/javascript" src="CalendarSimple.js"></script>
</head>
 
<body>
  <h2>Calendar</h2>
 
  <form id="frmCalendar">
    <select id="selMonth">
      <option>January</option>
      <option>February</option>
      <option>March</option>
      <option>April</option>
      <option>May</option>
      <option>June</option>
      <option>July</option>
      <option>August</option>
      <option>September</option>
      <option>October</option>
      <option>November</option>
      <option>December</option>
    </select>
    <input type="text" id="tfYear" size="4" maxlength="4" />
    <br /><br />
 
    <input type="button" id="btnPrevYear"  value=" <<  " />
    <input type="button" id="btnPrevMonth" value="  <  " />
    <input type="button" id="btnToday"     value="Today" />
    <input type="button" id="btnNextMonth" value="  >  " />
    <input type="button" id="btnNextYear"  value="  >> " />
    <br /><br />
 
    <table id="tableCalendar"></table>
  </form>
</body>
</html>
"CalendarSimple.css"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.today {
  background: gray;
  color: white;
  font-weight: bold
}
 
.sunday {
  color: red
}
 
input, select {
  font-family: Consolas, monospace;
  font-weight: bold;
  color: blue
}
 
table {
  font-family: Consolas, monospace;
  text-align: right;
  border-collapse:collapse;
  border: 1px solid black
}
 
td, th {
  padding: 3px 5px;
  border: 1px solid black
}
"CalendarSimple.js"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
window.onload = init;
 
// Global variables
// Today's year, month(0-11) and day(1-31)
var thisYear, thisMonth, thisDay;
 
// The "onload" handler, run after the page is fully loaded.
function init() {
   setToday();
 
   document.getElementById("selMonth").onchange = setMonth;
   document.getElementById("tfYear").onchange   = setYear;
 
   document.getElementById("btnPrevYear").onclick  = setPreviousYear;
   document.getElementById("btnPrevMonth").onclick = setPreviousMonth;
   document.getElementById("btnNextMonth").onclick = setNextMonth;
   document.getElementById("btnNextYear").onclick  = setNextYear;
   document.getElementById("btnToday").onclick     = setToday;
 
   document.getElementById("frmCalendar").onsubmit = function() {
      return false; // Stay in current page, do not refresh.
   }
}
 
// Set thisYear, thisMonth, thisDay to Today
// So that we can highlight today on the calendar
function setToday() {
   var now   = new Date();         // today
   thisDay   = now.getDate();      // 1-31
   thisMonth = now.getMonth();     // 0-11
   thisYear  = now.getFullYear();  // 4-digit year
 
   document.getElementById("selMonth").selectedIndex = thisMonth;
   document.getElementById("tfYear").value = thisYear;
   printCalendar(thisYear, thisMonth);
}
 
// Print the month-calendar for the given 4-digit year and month (0-11)
function printCalendar(year, month) {
   var daysInMonth = getDaysInMonth(year, month + 1);  // number of days
   var firstDayOfMonth = (new Date(year, month, 1)).getDay();  // 0-6 for Sun to Sat
 
   var tableInnerHTML = "<tr><th class='sunday'>Sun</th><th>Mon</th><th>Tue</th>"
        + "<th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th></tr>";
 
   var tdCellCount = 0;  // count of table's <td> cells
   if (firstDayOfMonth !== 0) {  // Leave these cells blank
      tableInnerHTML += "<tr><td colspan='" + firstDayOfMonth + "'></td>";
      tdCellCount = firstDayOfMonth;
   }
   for (var day = 1; day <= daysInMonth; day++) {
      if (tdCellCount % 7 === 0) {  // new table row
         tableInnerHTML += "<tr>";
      }
 
      // Use different style classes for today, sunday and other days
      if ((day === thisDay) && (month === thisMonth) && (year === thisYear)) {
         tableInnerHTML += "<td class='today'>" + day + "</td>";
      } else if (tdCellCount % 7 === 0) {
         tableInnerHTML += "<td class='sunday'>" + day + "</td>";
      } else {
         tableInnerHTML += "<td>" + day + "</td>";
      }
 
      tdCellCount++;
      if (tdCellCount % 7 === 0) {
         tableInnerHTML += "</tr>";
      }
   }
   // print the remaining cells and close the row
   var remainingCells = 7 - tdCellCount % 7;
   if (remainingCells < 7) {
      tableInnerHTML += "<td colspan='" + remainingCells + "'></td></tr>";
   }
 
   document.getElementById("tableCalendar").innerHTML = tableInnerHTML;
}
 
// The onchange handler for the month selection
function setMonth() {
   var year  = document.getElementById("tfYear").value;
   var month = document.getElementById("selMonth").selectedIndex;
   printCalendar(year, month);
}
 
// The onchange handler for the year textfield
function setYear() {
   var year  = document.getElementById("tfYear").value;
   var month = document.getElementById("selMonth").selectedIndex;
   if (isValidYear(year)) {
      printCalendar(year, month);
   }
}
 
// Validate the year
function isValidYear(year) {
   if (year < 1 || year > 9999) {
      alert ("Sorry, the year must be between 1 and 9999.");
      document.getElementById("tfYear").focus();
      return false;
   } else {
      return true;
   }
}
 
// The onclick handler for the previous-year button
function setPreviousYear() {
   var year  = document.getElementById("tfYear").value;
   var month = document.getElementById("selMonth").selectedIndex;
   year--;
   if (isValidYear(year)) {
      document.getElementById("tfYear").value = year;
      printCalendar(year, month);
   }
}
 
// The onclick handler for the next-year button
function setNextYear() {
   var year  = document.getElementById("tfYear").value;
   var month = document.getElementById("selMonth").selectedIndex;
   year++;
   if (isValidYear(year)) {
      document.getElementById("tfYear").value = year;
      printCalendar(year, month);
   }
}
 
// The onclick handler for the previous-month button
function setPreviousMonth() {
   var year  = document.getElementById("tfYear").value;
   var month = document.getElementById("selMonth").selectedIndex;
   if (month === 0) {
      month = 11;
      year--;
   } else {
      month--;
   }
   if (isValidYear(year)) {
      document.getElementById("tfYear").value = year;
      document.getElementById("selMonth").selectedIndex = month;
      printCalendar(year, month);
   }
}
 
// The onclick handler for the next-year button
function setNextMonth() {
   var year  = document.getElementById("tfYear").value;
   var month = document.getElementById("selMonth").selectedIndex;
   if (month === 11) {
      month = 0;
      year++;
   } else {
      month++;
   }
   if (isValidYear(year)) {
      document.getElementById("tfYear").value = year;
      document.getElementById("selMonth").selectedIndex = month;
      printCalendar(year, month);
   }
}
Dissecting the Program
  1. TODO

JavaScript Animation - A Digital Clock

Screenshot

Click the image to run the demo.

image
"ClockDigital.html"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<html>
<head>
<title>A JavaScript Clock</title>
<script type="text/javascript">
function initClock() {
  var now = new Date();
  var hr  = now.getHours();
  var min = now.getMinutes();
  var sec = now.getSeconds();
  if (min < 10) min = "0" + min;  // insert a leading zero
  if (sec < 10) sec = "0" + sec;
  document.getElementById('clockDisplay').innerHTML
     = "Time is " + hr + ":" + min + ":" + sec;
  setTimeout('initClock()', 500);
}
</script>
</head>
<body onload="initClock()">
<h1 id="clockDisplay"></h1>
</body>
</html>
Dissecting the Program
  1. We use the new Date() to create a Date object with the current time and assign to the variable now.
  2. We then use the getHours(), getMinutes(), getSeconds() function of now object to retrieve the hours, minutes and seconds.
  3. We display the clock by setting the innerHTML property of the <h1> tag. We use the getElementById() function to retrieve the <h1> tag.
  4. The function initClock() is invoked when the browser loads this page, by attaching it to the onload event handler.
  5. In initClock(), the setTimeout('initClock()', 500) function is used to recursively invoke the initClock() function every 500 msec, to refresh the display.

JavaScript Animation - Bouncing Balls

Screenshot

Click the image to run the demo.

image
"BouncingBallSimple.html"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head>
  <title>Bouncing balls</title>
  <link rel="stylesheet" href="BouncingBallSimple.css">
  <script type="text/javascript" src="BouncingBallSimple.js"></script>
</head>
 
<body>
  <h2>JavaScript Bouncing Ball</h2>
  <!-- holder for container box -->
  <div id="box"></div>
  <!-- Use name and class to handle more than one balls -->
  <img class="ball" name="ball" src="images/ball_red.gif" />
</body>
</html>
"BouncingBallSimple.css"
1
2
3
4
5
6
7
8
9
10
11
12
#box {  /* The container box */
  position: absolute;
  border: thick solid;
  border-color: red;
}
 
/* The ball image.
 * Use class selector to handle more than one balls
*/
img.ball {
  position: absolute;
}
"BouncingBallSimple.js"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
window.onload = init;
 
// Constants to define the box dimensions
const MIN_X = 20;
const MIN_Y = 80;
const WIDTH = 400;
const HEIGHT = 400;
const MAX_X = MIN_X + WIDTH - 1;
const MAX_Y = MIN_Y + HEIGHT - 1;
 
// The ball
var ballRadius = 30;
var ballSize = ballRadius*2 + 1;
// Randomly place the initial ball within the box, slightly off from border
var ballCenterX = (WIDTH - 2*ballSize)*Math.random() + (MIN_X + ballSize);
var ballCenterY = (HEIGHT - 2*ballSize)*Math.random() + (MIN_Y + ballSize);
// Initial speed
var ballSpeedX = 8;
var ballSpeedY = 6;
 
function init() {
   var box = document.getElementById("box");
   // Position the box absolutely via CSS style
   box.style.left = (MIN_X - 5) + "px";  // unit in px (pixels)
   box.style.top = (MIN_Y - 5) + "px";
   box.style.width = WIDTH + "px";
   box.style.height = HEIGHT + "px";
 
   var balls = document.getElementsByName("ball");
   // Position the ball image absolutely via CSS style
   balls[0].style.left = (ballCenterX - ballRadius) + "px";
   balls[0].style.top  = (ballCenterY - ballRadius) + "px";
   balls[0].style.width = ballSize + "px";
   balls[0].style.height = ballSize + "px";
 
   moveOneStep();
}
 
function moveOneStep() {
   // Calculate the ball's new position
   ballCenterX += ballSpeedX;
   ballCenterY += ballSpeedY;
   // Check if the ball moves over the bounds
   // If so, adjust the position and speed.
   if (ballCenterX - ballRadius < MIN_X) {
      ballSpeedX = -ballSpeedX; // Reflect along normal
      ballCenterX = MIN_X + ballRadius; // Re-position the ball at the edge
   } else if (ballCenterX + ballRadius > MAX_X) {
      ballSpeedX = -ballSpeedX;
      ballCenterX = MAX_X - ballRadius;
   }
   // May cross both x and y bounds
   if (ballCenterY - ballRadius < MIN_Y) {
      ballSpeedY = -ballSpeedY;
      ballCenterY = MIN_Y + ballRadius;
   } else if (ballCenterY + ballRadius > MAX_Y) {
      ballSpeedY = -ballSpeedY;
      ballCenterY = MAX_Y - ballRadius;
   }
 
   var balls = document.getElementsByName("ball");
   balls[0].style.left = (ballCenterX - ballRadius) + "px";
   balls[0].style.top  = (ballCenterY - ballRadius) + "px";
 
   // Recursively call move after the specified msec
   setTimeout("moveOneStep()", 60);
}
Ball Images
image image image image
Dissecting the Program
  1. To perform animation in JavaScript, we use CSS's absolute positioning to position the image and then move the image. We define two CSS styles:
    1. An id-selector box to absolutely position the container box. We use a <div id="box"> tag for the container box by enabling its border property. In the init() function, we retrieve the <div id="box"> element via box=document.getElementById("box"). We then absolutely position the <div> element via box.style.left|top|width|height.
    2. An class-selector img.ball to absolutely position the ball. We use the class-selector for the ball in order to handle more than one balls. This is because id needs to be unique, but many elements can use the same class. The ball is represented by an <img class="ball" name="ball" src="images/ball_red.gif" /> tag. We use balls=document.getElementsByName("ball") to retrieve an array of the <img> elements. We then use balls[0].style.left|top|width|height to position the ball.
  2. The onload event handler invokes the init(), which positions the container box, and the initial position of the ball.
  3. The moveOneStep() function invokes setTimeout("moveOneStep()", 60). which recursively runs the move() at the specified time (msec) interval.
  4. Read "The world of Bouncing Ball" on the bouncing ball algorithm. There are many limitations on doing complex animation on JavaScript. Applet is a much better platform.
Creating a one-pixel image

JavaScript's animation is often carry out by absolutely position (and re-position) an image via CSS position:absolute and imgElm.style.left|top|width|height attributes. The image's width and height is controlled via the style.width and style.height properties. An one-pixel image (which is smallest in size) can be stretched to fill the specified style.width and style.height.

To create a one-pixel image:

  • Launch "Paint" ⇒ Select the desired color ⇒ Fill ⇒ Select "Resize", and set the width and height to 1x1 pixel ⇒ Save as "png" or "gif".

The one-pixel image can be stretched to a rectangle of any size, which can be used in application such as drawing 2D bar chart. It cannot be used as a round ball though.

You can also create a one-pixel animated image, which alternates a few colors.

JavaScript Animation - Falling Snow, Falling Leave

Click here to run the demo.

"JSSnow.js"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Place <script type="text/javascript" src="JSSnow.js"></script> in <head>
window.onload = init;
 
const NUMBER = 12;  // Number of items
const IMAGE_PATH = "images/"
//var SOURCE_IMAGES = [
//   "snow1.gif", "snow2.gif", "snow3.gif", "snow4.gif"];
const SOURCE_IMAGES = [
   "leaf_green.gif", "leaf_orange_green.gif", "leaf_red.gif",
   "leaf_yellow_green.gif", "leaf_rotten.gif"];
 
// Each image has it own property, kept in an array
var xPos       = new Array();  // x position for the images
var yPos       = new Array();  // y position for the images
var size       = new Array();  // size (square) of the images
var xStep      = new Array();  // x displacement per time step
var yStep      = new Array();  // y displacement per time step
var xSineMag   = new Array();  // Magnitude of x sine variations
var xStepAccum = new Array();  // Accumulated sum of x displacement
 
// Screen width and height (browser dependent!)
var xMin = document.documentElement.scrollLeft + 20;
var xMax = document.documentElement.scrollLeft
       + document.documentElement.clientWidth - 20;
var yMin = document.documentElement.scrollTop + 30
var yMax = document.documentElement.scrollTop
       + document.documentElement.clientHeight - 30;
 
// Initialize the images and arrays
function init() {
   for (var i = 0; i < NUMBER; i++) {
      initItem(i);
 
      // Absolutely position the images using CSS style
      // <div> tags shall be under the <body>
      var imgElm = document.createElement("img");
      document.body.appendChild(imgElm);
      imgElm.clasName = "images";
      imgElm.name = "images";
      imgElm.src = IMAGE_PATH + SOURCE_IMAGES[i % SOURCE_IMAGES.length];
      imgElm.style.position = "absolute";
      imgElm.style.width = size[i] + "px";
      imgElm.style.height = size[i] + "px";
   }
   moveOneStep();
}
 
// Initialize the falling item given the itemIndex of the array
function initItem(itemIndex) {
   xStepAccum[itemIndex] = 0;
   xSineMag[itemIndex] = 20 + Math.random() * 40;  // 20 to 60
   // Slight variations in size and speed
   size[itemIndex]  = 25 + Math.random() * 5;    // 5 to 30
   xStep[itemIndex] = (Math.random() - 0.5) / 5; // -0.1 to 0.1
   yStep[itemIndex] = 1 + Math.random();         // 1 to 2
   // Initially place the images randomly within the screen
   xPos[itemIndex] = Math.random() * (xMax - xMin - size[itemIndex]*4)
                     + size[itemIndex] + xMin;
   yPos[itemIndex] = Math.random() * (yMax - yMin - size[itemIndex]*4)
                     + size[itemIndex] + yMin;
}
 
function moveOneStep() {
   xMin = document.documentElement.scrollLeft + 20;
   xMax = document.documentElement.scrollLeft
       + document.documentElement.clientWidth - 20;
   yMin = document.documentElement.scrollTop + 30
   yMax = document.documentElement.scrollTop
       + document.documentElement.clientHeight - 30;
   var images = document.getElementsByName("images");
   for (var i = 0; i < NUMBER; ++ i) {  // Go thru each image
      // update y position
      yPos[i] += yStep[i];
      // Check if the image falls outside the screen
      if (yPos[i] > yMax) {
         // Reposition the image and change its speed
         initItem(i);
         yPos[i] = 0;
      }
 
      // update x position - in sine curve, with some randomness.
      xStepAccum[i] += xStep[i];
      var xNew = xPos[i] + Math.random()*0.3 + xSineMag[i]*Math.sin(xStepAccum[i]);
      if (xNew > xMax) {
         xNew = xMax;
      }
 
      // Set the absolute position of the image
      images[i].style.top  = yPos[i] + "px";
      images[i].style.left = xNew + "px";
   }
   setTimeout("moveOneStep()", 100);
}
Images

I collected these images from the web and converted into transparent GIF:

image image image image image image image image image image
HTML

To use this script, place the following line in your HTML file, and also check the image file name and path in the script.

<script type="text/javascript" src="JSSnow.js"></script>
Dissecting the Program
  1. The width and height of the displayed image is controlled by the CSS style.
  2. To convert a GIF image to transparent using Photoshop: From "Image" menu ⇒ Mode ⇒ Color Table ⇒ Select the "Dropper" ⇒ Click on the background. This turns the background to check-box pattern (i.e., no color) ⇒ Save.
  3. To convert a JPEG image to transparent GIF using Photoshop: From "Image" menu ⇒ Mode ⇒ Index mode ⇒ Color: 256 ⇒ Check "Transparency". Then, do previous step and save as GIF format.

[TODO] Convert to object-oriented.

JavaScript Animation - X-Y Plotting

Screenshot

Click the image to run the demo.

image
"XYPlot.html"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html>
<head>
  <title>XY-Ploting</title>
  <link rel="stylesheet" href="XYPlot.css" />
  <script type="text/javascript" src="XYPlot.js"></script>
</head>
 
<body>
  <h2>JavaScript Plotting</h2>
  <table>
    <tr>
      <td>
        <fieldset>
          <legend>New</legend>
          X: <input type="text" size="3" id="newX" />
          Y: <input type="text" size="3" id="newY" />
          <input id="btnCreate" type="button" value="CREATE" />
        </fieldset>
      </td>
      <td>
        <fieldset>
          <legend>Update</legend>
          No: <select name="updateNo" id="updateNo" ></select>
          X: <input type="text" size="3" id="updateX" />
          Y: <input type="text" size="3" id="updateY" />
          <input id="btnUpdate" type="button" value="UPDATE" />
        </fieldset>
      </td>
    </tr>
  </table>
 
  <!-- the container -->
  <div id="box" ></div>
  <!-- contains all the items and item description -->
  <div id="allItems"></div>
</body>
</html>
"XYPlot.css"
1
2
3
4
5
6
7
8
9
10
/* id-selector for the container */
#box {
   position: absolute;
   border: thick solid red;
}
 
/* class-selector for the items and item descriptions */
.item, .itemDesc {
   position: absolute;
}
"XYPlot.js"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
window.onload = init;
 
const SOURCE_IMAGE = "images/car_green.gif";
const SIZE = 50;  // width and height for the image
const MARGIN_LEFT = 15;  // left-margin for the container
const MARGIN_TOP  = 180; // top-margin for the container
// x, y coordinates of the items
const X_MIN = 0;
const Y_MIN = 0;
const X_MAX = 600;
const Y_MAX = 300;
const WIDTH = X_MAX - X_MIN + 1;
const HEIGHT = Y_MAX - Y_MIN + 1;
 
var numItems = 0;  // number of items created so far
 
// The onload handler. Initialize the bounds
function init() {
   var box = document.getElementById("box");
   box.style.top = MARGIN_TOP + "px";
   box.style.left = MARGIN_LEFT + "px";
   box.style.width = WIDTH + "px";
   box.style.height = HEIGHT + "px";
 
   document.getElementById("btnCreate").onclick = newItem;
   document.getElementById("btnUpdate").onclick = updateItem;
}
 
// Create a new item at x, y
function newItem() {
   // Need to parseInt as it will be added.
   var x = parseInt(document.getElementById("newX").value);
   var y = parseInt(document.getElementById("newY").value);
   var displayX = x + MARGIN_LEFT;
   var displayY = y + MARGIN_TOP;
   if ((x >= X_MIN) && (x <= X_MAX) && (y >= Y_MIN) && (y <= Y_MAX)) {
      numItems++;
      // Put up an <img> to represent the item
      var itemImg = "<img class='item' name='item' src='"
            + SOURCE_IMAGE + "' style='width:" + SIZE
            + "px; height:" + SIZE + "px; top:" + displayY
            + "px; left:" + displayX + "px' />";
 
      // Put up a <p> for the item description
      var itemDesc = "<p class='itemDesc' name='itemDesc' style='top:"
            + displayY + "px; left:" + displayX
            + "px'>" + numItems + "</p>";
 
      document.getElementById('allItems').innerHTML += itemImg + itemDesc;
      // add a form's select option
      document.getElementById('updateNo').innerHTML
            += "<option>" + numItems + "</option>";
   }
}
 
// Update the position of itemNo to x, y
function updateItem() {
   var x = parseInt(document.getElementById("updateX").value);
   var y = parseInt(document.getElementById("updateY").value);
   var itemNo = document.getElementById("updateNo").value - 1;
 
   var items = document.getElementsByName("item");
   var itemDescs = document.getElementsByName("itemDesc");
   if (itemNo < items.length
       && (x >= X_MIN) && (x <= X_MAX) && (y >= Y_MIN) && (y <= Y_MAX)) {
      items[itemNo].style.left = x + MARGIN_LEFT + "px";
      items[itemNo].style.top  = y + MARGIN_TOP + "px";
      itemDescs[itemNo].style.left = x + MARGIN_LEFT + "px";
      itemDescs[itemNo].style.top  = y + MARGIN_TOP + "px";
   }
}
Images
image
Dissecting the Program

[TODO]

JavaScript - Bar Chart

[TODO]

JavaScript Animation - Bouncing Ball on HTML 5

This example runs on browser that support HTML 5, such as Firefox and Chrome, exclude IE.

HTML 5 provides a 2D canvas, which you can draw primitive shapes such as a circle. No ball image is needed in this example.

Click here to run the demo.

"BouncingBallHtml5.html"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Bouncing Ball (HTML 5)</title>
 
<script>
var MIN_X = 0;
var MIN_Y = 0;
var WIDTH = 520;
var HEIGHT = 410;
var MAX_X = MIN_X + WIDTH - 1;
var MAX_Y = MIN_Y + HEIGHT - 1;
 
var ballRadius = 30;
var ballSize = ballRadius*2 + 1;
// Randomly place the initial ball within the box, slightly off from border
var ballCenterX = (WIDTH - 2*ballSize)*Math.random() + (MIN_X + ballSize);
var ballCenterY = (HEIGHT - 2*ballSize)*Math.random() + (MIN_Y + ballSize);
// Initial speed
var ballSpeedX = 5;
var ballSpeedY = 3;
 
var context;
 
function init() {
  var canvas = document.getElementById('box');
  canvas.width = WIDTH;
  canvas.height = HEIGHT;
  canvas.style.border = "1px solid";
 
  context = canvas.getContext('2d');
  setInterval(draw, 30);
}
 
// Draw the ball
function draw() {
   // Calculate the ball's new position
   ballCenterX += ballSpeedX;
   ballCenterY += ballSpeedY;
   // Check if the ball moves over the bounds
   // If so, adjust the position and speed.
   if (ballCenterX - ballRadius < MIN_X) {
      ballSpeedX = -ballSpeedX; // Reflect along normal
      ballCenterX = MIN_X + ballRadius; // Re-position the ball at the edge
   } else if (ballCenterX + ballRadius > MAX_X) {
      ballSpeedX = -ballSpeedX;
      ballCenterX = MAX_X - ballRadius;
   }
   // May cross both x and y bounds
   if (ballCenterY - ballRadius < MIN_Y) {
      ballSpeedY = -ballSpeedY;
      ballCenterY = MIN_Y + ballRadius;
   } else if (ballCenterY + ballRadius > MAX_Y) {
      ballSpeedY = -ballSpeedY;
      ballCenterY = MAX_Y - ballRadius;
   }
 
   context.clearRect(MIN_X, MIN_Y, MAX_X, MAX_Y);
   context.fillStyle="#FF0000";
   context.beginPath();
   context.arc(ballCenterX, ballCenterY, ballRadius, 0, Math.PI*2, true);
   context.closePath();
   context.fill();
}
 
window.addEventListener("load", init, true);
</script>
 
</head>
<body>
  <section>
    <h2>Bouncing Ball (on HTML 5 Canvas)</h2>
    <canvas id="box">Canvas not supported</canvas>
  </section>
</body>
</html>
Dissecting the Program
  1. HTML 5 provides a new "Canvas API" to support 2D drawing. To use the canvas:
    1. Create a canvas element via the new <canvas></canvas> tag.
    2. In the script, select the canvas element (via document.getElementById()) and get the canvas' context (via canvas.getContext('2d')). Currently, only '2d' context is supported.
    3. You can then use the context for drawing. For example, clearRect() to clear the container box; beginPath() and closePath() to enclose a path; arc(), moveTo(), lineTo() to define a path.
  2. We use window.addEventListener("load", init, true) to register an event handler (init function) to the load event.
  3. We use setInterval(draw, 30) to schedule function draw() every 30 msec.
  4. The ball bouncing algorithm is the same as the previous example.

JavaScript Calculators

A Simple Calculator

Screenshot

Click the image to run the demo.

image
"CalculatorSimple.html"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<html>
<head>
  <title>Simple Calculator</title>
  <style type="text/css">
     input {
       font-family:consola,monospace;
       color:blue
     }
     td {
       margin-left: auto;
       margin-right: auto;
       text-align: center
     }
  </style>
</head>
 
<body>
<h2>Simple Calculator</h2>
 
<form name="calcForm">
<table border="5">
<tr>
  <td colspan="4"><input type="text" name="display"
                         style="text-align:right"></td>
</tr>
<tr>
  <td><input type="button" name="btn1" value="1"
             onclick="calcForm.display.value += '1'"></td>
  <td><input type="button" name="btn2" value="2"
             onclick="calcForm.display.value += '2'"></td>
  <td><input type="button" name="btn3" value="3"
             onclick="calcForm.display.value += '3'"></td>
  <td><input type="button" name="btnAdd" value="+"
             onclick="calcForm.display.value += ' + '"></td>
</tr>
<tr>
  <td><input type="button" name="btn4" value="4"
             onclick="calcForm.display.value += '4'"></td>
  <td><input type="button" name="btn5" value="5"
             onclick="calcForm.display.value += '5'"></td>
  <td><input type="button" name="btn6" value="6"
             onclick="calcForm.display.value += '6'"></td>
  <td><input type="button" name="btnSub" value="-"
             onclick="calcForm.display.value += ' - '"></td>
</tr>
<tr>
  <td><input type="button" name="btn7" value="7"
             onclick="calcForm.display.value += '7'"></td>
  <td><input type="button" name="btn8" value="8"
             onclick="calcForm.display.value += '8'"></td>
  <td><input type="button" name="btn9" value="9"
             onclick="calcForm.display.value += '9'"></td>
  <td><input type="button" name="btnMul" value="x"
             onclick="calcForm.display.value += ' * '"></td>
</tr>
<tr>
  <td><input type="button" name="btnClear"
             value="C" onclick="calcForm.display.value = ''"></td>
  <td><input type="button" name="btn0" value="0"
             onclick="calcForm.display.value += '0'"></td>
  <td><input type="button" name="btnEqual" value="="
             onclick="calcForm.display.value = eval(calcForm.display.value)"></td>
  <td><input type="button" name="btnDiv" value="/"
             onclick="calcForm.display.value += ' / '"></td>
</tr>
</table>
</form>
 
</body>
</html>
Dissecting the Program
  1. A CSS style is defined for the <input> tag to set the font face; another for the <td> tag to centralize the buttons within the cell.
  2. A form (called "calcForm") is defined with a text field (called "display"), and 16 buttons.
  3. The inputs are appended to display.value. The result is evaluated via the eval() function in the onclick handler for the '=' button.

Sending an HTTP GET|POST Request via JavaScript

Sending an HTTP GET request is easier, as the parameters can be included in the hyperlink. Sending a POST request is much harder, which is typically accomplished via a HTML form with method='POST'.

Other than using a HTML form, you can also trigger a HTTP POST via JavaScript, by creating and submitting an virtual form.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<html>
<head>
<title>JavaScript Example: Sending HTTP POST Request</title>
 
<script type="text/javascript">
/*
 * Send a POST request to /test
 * with parameter todo=update&username=peter
 */
function sendHttpPostRequest() {
   var form = document.createElement("form");
   form.setAttribute("method", "post");
   form.setAttribute("action", "/test.php");
 
   var hiddenField = document.createElement("input");
   hiddenField.setAttribute("type", "hidden");
   hiddenField.setAttribute("name", "todo");
   hiddenField.setAttribute("value", "update");
   form.appendChild(hiddenField);
 
   hiddenField = document.createElement("input");
   hiddenField.setAttribute("type", "hidden");
   hiddenField.setAttribute("name", "username");
   hiddenField.setAttribute("value", "peter");
   form.appendChild(hiddenField);
 
   document.body.appendChild(form);
   form.submit();
}
</script>
</head>
 
<body>
<p>
  <a href="http://www.nowhere.com" onclick="sendHttpPostRequest(); return false;">
  Click to send an HTTP POST Request</a>
</p>
</body>
</html>
Function for Sending an HTTP GET|POST Request

You can use the following JavaScript function for send an HTTP GET|POST request:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<html>
<head>
<title>JavaScript Example: Sending HTTP POST Request</title>
 
<script type="text/javascript">
/*
 * Send an HTTP GET|POST request to path with params.
 * To call: sendHttpRequest('path', {'k1':'v1', 'k2':'v2'})
 */
function sendHttpRequest(path, params, method) {
   // Set request method to POST if it is not specified.
   // JavaScript's way of default function argument for trailing arguments
   method = method || "post";
 
   var form = document.createElement("form");
   form.setAttribute("method", method);
   form.setAttribute("action", path);
 
   for (var key in params) {
       if (params.hasOwnProperty(key)) {
           var hiddenField = document.createElement("input");
           hiddenField.setAttribute("type", "hidden");
           hiddenField.setAttribute("name", key);
           hiddenField.setAttribute("value", params[key]);
 
           form.appendChild(hiddenField);
        }
   }
 
   document.body.appendChild(form);
   form.submit();
}
</script>
</head>
 
<body>
<p>
  <a href="http://www.nowhere.com"
     onclick="sendHttpRequest('test.php', {'todo':'update', 'user':'peter'}); return false;">
  Click to send an HTTP POST Request</a>
</p>
</body>
</html>
Duplicate Names

The previous function cannot handle duplicate names, e.g., user[]=aaa&user[]=bbb, as an object cannot have duplicate property. To support duplicate names, use two separate arrays for names and values instead, as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<html>
<head>
<title>JavaScript Example: Sending HTTP POST Request</title>
 
<script type="text/javascript">
/*
 * Send an HTTP GET|POST request to path with name-value pairs
 *  in nameArray and valueArray. Allow duplicate names.
 * To call: sendHttpRequestDuplicateNames('path', ['k1', 'k2'], ['v1', 'v2'])
 */
function sendHttpRequestDuplicateNames(path, nameArray, valueArray, method) {
   if (nameArray.length === 0 || nameArray.length !== valueArray.length) return false;
 
   // Set request method to POST if it is not specified.
   // JavaScript's way of default function argument for trailing arguments
   method = method || "post";
 
   var form = document.createElement("form");
   form.setAttribute("method", method);
   form.setAttribute("action", path);
 
   for (var i = 0; i < nameArray.length; i++) {
      var hiddenField = document.createElement("input");
      hiddenField.setAttribute("type", "hidden");
      hiddenField.setAttribute("name", nameArray[i]);
      hiddenField.setAttribute("value", valueArray[i]);
 
      form.appendChild(hiddenField);
   }
 
   document.body.appendChild(form);
   form.submit();
}
</script>
</head>
 
<body>
<p>
  <a href="http://www.nowhere.com"
     onclick="sendHttpRequestDuplicateNames('test.php', ['user[]', 'user[]'], ['peter', 'paul'], 'get'); return false;">
  Click to send an HTTP POST Request</a>
</p>
</body>
</html>
AJAX POST Request

You can also use JavaScript to send an AJAX POST request. Read "AJAX Basics".

CURD (Create-Update-Read-Delete) Database Table

[TODO]

REFERENCES & RESOURCES

  1. HTML/CSS/JavaScript Tutorial @ http://www.w3school.com.