Read "Writing and Debugging JavaScripts", before trying out these examples. At a minimum, you should have the "Firebug" (or Web Developer Tools). 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 behavior programming codes in three different files, ".html
", ".css
" and ".js
", for ease of maintenance and good software engineering practice. The now-preferred approach is not to embed styles and JavaScript codes inside HTML document, but keep them in separate files.
[TODO] More examples on jQuery + HTML5/CSS3
HTML Form Input Validation
NOTE: HTML5 supports form input validation. You should use HTML5 for input validation, which is much simpler and stable (Read "HTML Form By Examples"). On the other hand, there are also tons of advanced Form Input Validator libraries, such as Parsley JS.
Using HTML5
HTML "H5FormValidation.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 |
<!DOCTYPE html>
<!-- H5FormValidation.html -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>HTML Form Input Validation Using HTML5</title>
</head>
<body>
<h2>HTML Form Input Validation Using HTML5</h2>
<form id="formTest" method="get" action="processData">
<table>
<tr>
<td><label for="txtName">Name<span class="required">*</span></label></td>
<td><input type="text" id="txtName" name="name" required autofocus></td>
</tr>
<tr>
<td><label for="txtAddress">Address</label></td>
<td><input type="text" id="txtAddress" name="address"></td>
</tr>
<tr>
<td><label for="txtZipcode">Zip Code<span class="required">*</span></label></td>
<td><input type="text" id="txtZipcode" name="zipcode"
placeholder="enter a 5-digit code"
required pattern="^\d{5}$"
oninvalid="this.setCustomValidity('Enter a 5-digit zipcode')"
oninput="setCustomValidity('')"></td>
</tr>
<tr>
<td>Country<span class="required">*</span></td>
<td><select id="selCountry" name="country" required>
<option value="" selected>Please select...</option>
<option value="AA">AA</option>
<option value="BB">BB</option>
<option value="CC">CC</option>
</select></td>
</tr>
<tr>
<td>Gender<span class="required">*</span></td>
<td><label><input type="radio" name="gender" value="m" required>Male</label>
<label><input type="radio" name="gender" value="f">Female</label></td>
</tr>
<tr>
<td>Preferences<span class="required">*</span></td>
<td><label><input type="checkbox" name="color" value="r">Red</label>
<label><input type="checkbox" name="color" value="g" checked>Green</label>
<label><input type="checkbox" name="color" value="b">Blue</label></td>
</tr>
<tr>
<td><label for="txtPhone">Phone<span class="required">*</span></label></td>
<td><input type="tel" id="txtPhone" name="phone" required></td>
</tr>
<tr>
<td><label for="txtEmail">Email<span class="required">*</span></label></td>
<td><input type="email" id="txtEmail" name="email" required></td>
</tr>
<tr>
<td><label for="txtPassword">Password<span class="required">*</span></label></td>
<td><input type="password" id="txtPassword" name="password"
required pattern="^\w{6,8}$"
placeholder="6-8 characters"></td>
</tr>
<tr>
<td><label for="txtPWVerified">Verify Password<span class="required">*</span></label></td>
<td><input type="password" id="txtPWVerified" name="pwVerified" required></td>
</tr>
<tr>
<td><label for="dateBirthday">Birthday<span class="required">*</span></label></td>
<td><input type="date" id="dateBirthday" name="birthday" required></td>
</tr>
<tr>
<td><label for="timeAppt">Appointment<span class="required">*</span></label></td>
<td><input type="time" id="timeAppt" name="appointment" required></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="SEND" id="btnSubmit">
<input type="reset" value="CLEAR" id="btnReset"></td>
</tr>
</table>
</form>
</body>
</html>
|
How it Works?
- <input type="text" id="txtName" name="name" required autofocus>
The attributerequired
specifies that input cannot be empty. The attributeautofocus
sets the focus to this element. - <input type="text" id="txtZipcode" name="zipcode"
placeholder="enter a 5-digit code"
required pattern="^\d{5}$"
oninvalid="this.setCustomValidity('Enter a 5-digit zipcode')"
oninput="setCustomValidity('')">
The attributeplaceholder="text"
is used to show hints on the text field as watermark. The attributepattern="regex"
specifies an regular expression (regex) pattern to be validated for this field. Theoninvalid
andoninput
event handlers are used to customize the error message. - <select id="selCountry" name="country" required>
Similarly, we can userequired
on<select>
to specify input value cannot be an empty string. - <label><input type="radio" name="gender" value="m" required>Male</label>
<label><input type="radio" name="gender" value="f">Female</label>
For radio buttons, it is sufficient to place anrequired
on one of the buttons. [How to specifyrequired
for checkboxes?] - <input type="tel" id="txtPhone" name="phone" required pattern="^\d+$" placeholder="digits only">
HTML5 addstype="tel"
to<input>
, but it is not widely supported. - <input type="email" id="txtEmail" name="email" required>
HTML5 addstype="email"
to<input>
for email input, which can be validated (viarequired
). - <input type="date" id="dateBirthday" name="birthday" required>
<input type="time" id="timeAppt" name="appointment" required>
HTML5 addstype="date"
andtype="time"
to<input>
. Some browsers (e.g., Chrome) could show a data-picker and time-picker.
Using JavaScript
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:
- An input field is required and cannot be left empty.
- An input field has he required number of character (e.g., password).
- A valid email address (user@hostname.com)
- A valid numeric string (e.g., phone number, zip code, credit card number), or all-letter string.
- A valid date.
Screenshot
Click the image to run the demo.
HTML: "JSFormValidation.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 |
<!DOCTYPE html>
<!-- JSFormValidation.html -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>HTML Form Input Validation Using JavaScript</title>
<link rel="stylesheet" href="JSFormValidation.css">
<script src="JSFormValidation.js"></script>
</head>
<body>
<h2>HTML Form Input Validation Using JavaScript</h2>
<form id="formTest" method="get" action="processData">
<table>
<tr>
<td><label for="txtName">Name<span class="required">*</span></label></td>
<td><input type="text" id="txtName" name="name"></td>
<td id="elmNameError" class="errorMsg"> </td></tr>
<tr>
<td><label for="txtAddress">Address</label></td>
<td><input type="text" id="txtAddress" name="address"></td>
<td id="elmAddressError" class="errorMsg"> </td></tr>
<tr>
<td><label for="txtZipcode">Zip Code<span class="required">*</span></label></td>
<td><input type="text" id="txtZipcode" name="zipcode"></td>
<td id="elmZipcodeError" class="errorMsg"> </td></tr>
<tr>
<td>Country<span class="required">*</span></td>
<td><select id="selCountry" name="country">
<option value="" selected>Please select...</option>
<option value="AA">AA</option>
<option value="BB">BB</option>
<option value="CC">CC</option>
</select></td>
<td id="elmCountryError" class="errorMsg"> </td></tr>
<tr>
<td>Gender<span class="required">*</span></td>
<td><label><input type="radio" name="gender" value="m">Male</label>
<label><input type="radio" name="gender" value="f">Female</label></td>
<td id="elmGenderError" class="errorMsg"> </td></tr>
<tr>
<td>Preferences<span class="required">*</span></td>
<td><label><input type="checkbox" name="color" value="r">Red</label>
<label><input type="checkbox" name="color" value="g">Green</label>
<label><input type="checkbox" name="color" value="b">Blue</label></td>
<td id="elmColorError" class="errorMsg"> </td></tr>
<tr>
<td><label for="txtPhone">Phone<span class="required">*</span></label></td>
<td><input type="text" id="txtPhone" name="phone"></td>
<td id="elmPhoneError" class="errorMsg"> </td></tr>
<tr>
<td><label for="txtEmail">Email<span class="required">*</span></label></td>
<td><input type="text" id="txtEmail" name="email"></td>
<td id="elmEmailError" class="errorMsg"> </td></tr>
<tr>
<td><label for="txtPassword">Password (6-8 characters)<span class="required">*</span></label></td>
<td><input type="password" id="txtPassword" name="password"></td>
<td id="elmPasswordError" class="errorMsg"> </td></tr>
<tr>
<td><label for="txtPWVerified">Verify Password<span class="required">*</span></label></td>
<td><input type="password" id="txtPWVerified" name="pwVerified"></td>
<td id="elmPWVerifiedError" class="errorMsg"> </td></tr>
<tr>
<td> </td>
<td><input type="submit" value="SEND" id="btnSubmit">
<input type="reset" value="CLEAR" id="btnReset"></td>
<td> </td></tr>
</table>
</form>
</body>
</html>
|
CSS: "JSFormValidation.css"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* JSFormValidation.css */ .required { /* Marker for required fields */ color: red; } .errorMsg { /* for error messages */ color: red; } .errorBox { /* for the error input text fields */ border: 2px solid red; } table { border: 0; } td { margin: 0; padding: 3px 10px; } |
JavaScript: "JSFormValidation.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 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
// JSFormValidation.js /* * Run init() after the page is loaded */ window.onload = init; /* * Initialization */ function init() { // Bind "onsubmit" event handler to the "submit" button document.getElementById("formTest").onsubmit = validateForm; // Bind "onclick" event handler to "reset" button document.getElementById("btnReset").onclick = clearForm; // Set initial focus document.getElementById("txtName").focus(); } /* * The "onsubmit" event handler to validate the input fields. * * Most of the input validation functions take 3 arguments: * inputElm: Input element to be validated. * errMsg: the error message to be displayed if validation fails. * errElm: to place the error message * * @param theForm: the form to be validated */ function validateForm(theForm) { with(theForm) { // return false would prevent default submission return (isNotEmpty(txtName, "Please enter your name!", elmNameError) && isNumeric(txtZipcode, "Please enter a 5-digit zip code!", elmZipcodeError) && isLengthMinMax(txtZipcode, 5, 5, "Please enter a 5-digit zip code!", elmZipcodeError) && isSelected(selCountry, "Please make a selection!", elmCountryError) && isChecked("gender", "Please check a gender!", elmGenderError) && isChecked("color", "Please check a color!", elmColorError) && isNumeric(txtPhone, "Please enter a valid phone number!", elmPhoneError) && isValidEmail(txtEmail, "Enter a valid email!", elmEmailError) && isValidPassword(txtPassword, "Password shall be 6-8 characters!", elmPasswordError) && verifyPassword(txtPassword, txtPWVerified, "Different from new password!", elmPWVerifiedError) ); } } /* * Helper function, to be called after validation, to show or clear * existing error message, and to set focus to the input element * for correcting error. * If isValid is false, show the errMsg on errElm, and place the * focus on the inputElm for correcting the error. * Else, clear previous errMsg on errElm, if any. * * @param isValid (boolean): flag indicating the result of validation * @param errMsg (string)(optional): error message * @param errElm (object)(optional): if isValid is false, show errMsg; else, clear. * @param inputElm (object)(optional): set focus to this element, * if isValid is false */ function postValidate(isValid, errMsg, errElm, inputElm) { 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 (inputElm !== undefined && inputElm !== null) { inputElm.classList.add("errorBox"); // Add class for styling inputElm.focus(); } } else { // Clear previous error message on errElm, if provided. if (errElm !== undefined && errElm !== null) { errElm.innerHTML = ""; } if (inputElm !== undefined && inputElm !== null) { inputElm.classList.remove("errorBox"); } } } /* * Validate that input value is not empty. * * @param inputElm (object): input element * @param errMsg (string): error message * @param errElm (object): element to place error message */ function isNotEmpty(inputElm, errMsg, errElm) { var isValid = (inputElm.value.trim() !== ""); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } /* Validate that input value contains one or more digits */ function isNumeric(inputElm, errMsg, errElm) { var isValid = (inputElm.value.trim().match(/^\d+$/) !== null); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } /* Validate that input value contains only one or more letters */ function isAlphabetic(inputElm, errMsg, errElm) { var isValid = (inputElm.value.trim().match(/^[a-zA-Z]+$/) !== null) ; postValidate(isValid, errMsg, errElm, inputElm); return isValid; } /* Validate that input value contains one or more digits or letters */ function isAlphanumeric(inputElm, errMsg, errElm) { var isValid = (inputElm.value.trim().match(/^[0-9a-zA-Z]+$/) !== null); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } /* Validate that input value length is between minLength and maxLength */ function isLengthMinMax(inputElm, minLength, maxLength, errMsg, errElm) { var inputValue = inputElm.value.trim(); var isValid = (inputValue.length >= minLength) && (inputValue.length <= maxLength); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } // Validate that input value is a valid email address function isValidEmail(inputElm, errMsg, errElm) { var isValid = (inputElm.value.trim().match( /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/) !== null); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } /* * Validate that a selection is made (not default of "") in <select> input * * @param selectElm (object): the <select> element */ function isSelected(selectElm, errMsg, errElm) { // You need to set the default value of <select>'s <option> to "". var isValid = (selectElm.value !== ""); // value in selected <option> postValidate(isValid, errMsg, errElm, selectElm); return isValid; } /* * Validate that one of the checkboxes or radio buttons is checked. * Checkbox and radio are based on name attribute, not id. * * @param inputName (string): name attribute of the checkbox or radio */ function isChecked(inputName, errMsg, errElm) { var elms = document.getElementsByName(inputName); var isChecked = false; for (var i = 0; i < elms.length; ++i) { if (elms[i].checked) { isChecked = true; break; } } postValidate(isChecked, errMsg, errElm, null); // no focus element return isChecked; } // Validate password, 6-8 characters of [a-zA-Z0-9_] function isValidPassword(inputElm, errMsg, errElm) { var isValid = (inputElm.value.trim().match(/^\w{6,8}$/) !== null); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } // Verify password. function verifyPassword(pwElm, pwVerifiedElm, errMsg, errElm) { var isTheSame = (pwElm.value === pwVerifiedElm.value); postValidate(isTheSame, errMsg, errElm, pwVerifiedElm); return isTheSame; } /* * The "onclick" handler for the "reset" button to clear the display, * including the previous error messages and error box. */ function clearForm() { // Remove class "errorBox" from input elements var elms = document.querySelectorAll('.errorBox'); // class for (var i = 0; i < elms.length; i++) { elms[i].classList.remove("errorBox"); } // Remove previous error messages elms = document.querySelectorAll('[id$="Error"]'); // id ends with Error for (var i = 0; i < elms.length; i++) { elms[i].innerHTML = ""; } // Set initial focus document.getElementById("txtName").focus(); } |
How it Works?
- We separate the HTML contents, CSS presentation styles, and JavaScript programming codes in three files.
- Let's begin with the HTML:
- <form id="formTest" method="get" action="processData">
We define an HTML form with uniqueid="theForm"
. - <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. - <td><input type="text" id="txtName" name="name"/></td>
<td id="elmNameError" class="errorMsg"> </td>
Each<input>
element is assigned an uniqueid
, so that it can be selected in JavaScript via thedocument.getElementById()
function. It also contain aname
attribute, identifying thename=value
request parameter. The
<td>
element in the 3rd column for displaying the error message has anid
ending with "Error". - <select ...><option value="" selected>Please select...</option>
For the<select>
element, we define a default no-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. - For checkboxes and radio buttons, we cannot use
id
, as there are more than one elements andid
must be unique. Instead, we set a commonname
. The JavaScript would usedocument.getElementsByName()
to select all the elements with the samename
.
- <form id="formTest" method="get" action="processData">
- The CSS is simple:
- .errorMsg { color: red; }
A class-selector for displaying the error messages in red. - errorBox { border: 2px solid red; }
A class-selector for displaying the erroneous input element with a red border. It can be used for<input type="text|password">
and<select>
, but not for<input type="checkbox|radio">
.
- .errorMsg { color: red; }
- We move on to the JavaScript:
- window.onload = init;
We attach theinit()
function as the onload event handler. That isinit()
runs after the page is fully loaded. - function init() {
document.getElementById("formTest").onsubmit = validateForm;
document.getElementById("btnReset").onclick = clearForm;
document.getElementById("txtName").focus();
}
In theinit()
function, we attachvalidateForm
function as theonsubmit
handler;clearForm
function as theonclick
handler; and set the initial focus to the first input element having theid
oftxtName
. - function validateForm() {
return (isNotEmpty(...) && isNumeric(...) && ...); }
ThevalidateForm()
function calls the various input validation functions to validate the input fields. It returnstrue
if all the input validation functions returntrue
, resulted in the form data to be submitted to theaction
's url. Otherwise, it returnsfalse
, the form data will not be submitted and the current page remains. - function isNotEmpty(inputElm, errMsg, errElm) {
var isValid = (inputElm.value.trim() !== "");
postValidate(isValid, errMsg, errElm, inputElm);
return isValid;
}
Let's look into an input validation functionisNotEmpty()
in details. It takes 3 arguments, an input element, an error message, and an error message element. It gets thevalue
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 variableisValid
. It invokes thepostValidate()
and return the boolean flag. - function postValidate(isValid, errMsg, errElm, inputElm) { ... }
ThepostValidate()
accepts 4 arguments. If the input is invalid (isValid
isfalse
), it set theinnerHMTL
oferrElm
to theerrMsg
, and add aclass
"errorBox
" toinputElm
. The CSS class-selector.errorBox
will display the input element with a red boundary. Otherwise, it clears theinnerHTML
of theerrElm
and removeclass
"errorBox
" frominputElm
. - function isNumeric(inputElm, errMsg, errElm) {
var isValid = (inputElm.value.trim().match(/^\d+$/) !== null);
For input validation functions such asisNumeric()
, we use regular expression (regex) to perform pattern matching, e.g., regex/^\d+$/
matches 1 or more digits; regex/^[a-zA-Z]+$/
matches one or more letters;/^[0-9]{5,8}$/
matches string of 5 to 8 digits. Thestring.match(regex)
returnnull
if no match is found. Regular expression is extremely powerful for text processing. Read "Regular Expression" for more details. - In
isValidEmail()
function, we check for the email pattern of "a@b.cc
" via regex/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/
. - In
isSelected()
used by<select>
, theselectedElm.value
returns the value of the selected<option>
. - In
isChecked()
used by input<type="checkbox|radio">
, we used thedocument.getElementsByName()
to select all elements with the commonname
attribute. We loop through all elements to look for.checked
property. - In
isValidPassword()
, we use regex/^\w{6,8}$/
, which accepts 6 to 8 word characters. - In
clearForm()
, we usedocument.querySelectorAll('.errorBox')
to select all elements with class "errorBox
", and remove thisclass
value from theclassList
. We then usedocument.querySelectorAll('[id$="Error"]')
to select all elements withid
ending with "Error
" and remove its contents (possibly previous error message).
- window.onload = init;
- Some notes in form input validation:
- 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.
- A password may contain letter, digit and special characters such as
@
. it probably does not contain space.
Using jQuery
jQuery (a JavaScript Framework) provides elegant selectors and event handling syntax, which greatly simplifies the coding. jQuery is preferred nowadays, over raw JavaScript.
HTML "JQFormValidation.html"
Same as "JSFormValidation.html
", except the references to CSS and JavaScipt, and the inclusion of jQuery library, and may be the title.
<head> ...... <link rel="stylesheet" href="JQFormValidation.css"> <script src="js/jquery-1.11.2.min.js"></script> <script src="JQFormValidation.js"></script> </head>
CSS "JQFormValidation.css"
Exactly the same as "JSFormValidation.css
".
JavaScript "JQFormValidation.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 |
// JQFormValidation.js /* * Shorthand for $(document).ready( function() {...} ) * Run once the DOM tree is contructed. */ $( function() { // Set initial focus $('#txtName').focus(); // Bind "submit" event handler to form $('#formTest').on('submit', function() { var $form = $(this); // return false would prevent default submission return isNotEmpty($form.find('#txtName'), "Please enter your name!", $form.find('#elmNameError')) && isNumeric($form.find('#txtZipcode'), "Please enter a 5-digit zip code!", $form.find('#elmZipcodeError')) && isLengthMinMax($form.find('#txtZipcode'), 5, 5, "Please enter a 5-digit zip code!", $form.find('#elmZipcodeError')) && isSelected($form.find('#selCountry'), "Please make a selection!", $form.find('#elmCountryError')) && isChecked($form.find('[name="gender"]:checked'), "Please check a gender!", $form.find('#elmGenderError')) && isChecked($form.find('[name="color"]:checked'), "Please check a color!", $form.find('#elmColorError')) && isNumeric($form.find('#txtPhone'), "Please enter a valid phone number!", $form.find('#elmPhoneError')) && isValidEmail($form.find('#txtEmail'), "Enter a valid email!", $form.find('#elmEmailError')) && isValidPassword($form.find('#txtPassword'), "Password shall be 6-8 characters!", $form.find('#elmPasswordError')) && verifyPassword($form.find('#txtPassword'), $form.find('#txtPWVerified'), "Different from new password!", $form.find('#elmPWVerifiedError')) ; }); // Bind "click" event handler to "reset" button $('#btnReset').on('click', function() { $('.errorBox').removeClass('errorBox'); // remove the error styling $('td[id$="Error"]').html(''); // id ends with "Error", remove contents $('txtName').focus(); // Set focus element }); }); /* * Helper function, to be called after validation, to show or clear * existing error message, and to set focus to the input element * for correcting error. * If isValid is false, show the errMsg on errElm, and place the * focus on the inputElm for correcting the error. * Else, clear previous errMsg on errElm, if any. * * @param isValid (boolean): flag indicating the result of validation * @param errMsg (string)(optional): error message * @param errElm (jQuery object)(optional): if isValid is false, show errMsg; else, clear. * @param inputElm (jQuery object)(optional): set focus to this element, * if isValid is false */ function postValidate(isValid, errMsg, errElm, inputElm) { if (!isValid) { // Show errMsg on errElm, if provided. if (errElm !== undefined && errElm !== null && errMsg !== undefined && errMsg !== null) { errElm.html(errMsg); } // Set focus on Input Element for correcting error, if provided. if (inputElm !== undefined && inputElm !== null) { inputElm.addClass("errorBox"); // Add class for styling inputElm.focus(); } } else { // Clear previous error message on errElm, if provided. if (errElm !== undefined && errElm !== null) { errElm.html(''); } if (inputElm !== undefined && inputElm !== null) { inputElm.removeClass("errorBox"); } } } /* * Validate that input value is not empty. * * @param inputElm (jQuery object): input element * @param errMsg (string): error message * @param errElm (jQuery object): element to place error message */ function isNotEmpty(inputElm, errMsg, errElm) { var isValid = (inputElm.val().trim() !== ""); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } /* Validate that input value contains one or more digits */ function isNumeric(inputElm, errMsg, errElm) { var isValid = (inputElm.val().trim().match(/^\d+$/) !== null); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } /* Validate that input value contains only one or more letters */ function isAlphabetic(inputElm, errMsg, errElm) { var isValid = (inputElm.val().trim().match(/^[a-zA-Z]+$/) !== null) ; postValidate(isValid, errMsg, errElm, inputElm); return isValid; } /* Validate that input value contains one or more digits or letters */ function isAlphanumeric(inputElm, errMsg, errElm) { var isValid = (inputElm.val().trim().match(/^[0-9a-zA-Z]+$/) !== null); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } /* Validate that input value length is between minLength and maxLength */ function isLengthMinMax(inputElm, minLength, maxLength, errMsg, errElm) { var inputValue = inputElm.val().trim(); var isValid = (inputValue.length >= minLength) && (inputValue.length <= maxLength); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } // Validate that input value is a valid email address function isValidEmail(inputElm, errMsg, errElm) { var isValid = (inputElm.val().trim().match( /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/) !== null); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } /* * Validate that a selection is made (not default of "") in <select> input * * @param selectElm (jQuery object): the <select> element */ function isSelected(selectElm, errMsg, errElm) { // You need to set the default value of <select>'s <option> to "". var isValid = (selectElm.val() !== ""); // value in selected <option> postValidate(isValid, errMsg, errElm, selectElm); return isValid; } /* * Validate that one of the checkboxes or radio buttons is checked. * Checkbox and radio are based on name attribute, not id. * * @param inputElms (jQuery object): "checked" checkboxes or radio */ function isChecked(inputElms, errMsg, errElm) { var isChecked = inputElms.length > 0; postValidate(isChecked, errMsg, errElm, null); // no focus element return isChecked; } // Validate password, 6-8 characters of [a-zA-Z0-9_] function isValidPassword(inputElm, errMsg, errElm) { var isValid = (inputElm.val().trim().match(/^\w{6,8}$/) !== null); postValidate(isValid, errMsg, errElm, inputElm); return isValid; } // Verify password. function verifyPassword(pwElm, pwVerifiedElm, errMsg, errElm) { var isTheSame = (pwElm.val() === pwVerifiedElm.val()); postValidate(isTheSame, errMsg, errElm, pwVerifiedElm); return isTheSame; } |
How it Works
- $( function() { ... }
We place all the initialization operations under$( function() {...} )
, which is a shorthand for$(document).ready(function() {...} )
. These operations run once the ROM tree is construction, but before the external resources (such as images) are fully loaded. "ready
" is a jQuery extension, which is better thanonload
in JavaScript. - $('#txtName').focus();
The jQuery ID-selector$('#txtName')
selects element with specificid
, and set it as initial focus element. - $('#formTest').on('submit', function() { ... }
This selects the<form>
element and bind an handler to eventsubmit
. You can also use.submit(handler)
as the shorthand for.on(event, handler)
. - var $form = $(this);
$(this)
holds the jQuery object under operation, i.e., the<form>
. We assign it a variable$form
. By convention, we prefix variable of jQuery object with'$'
for ease of identification. - $form.find('#txtName')
Find the element nested under$form
, i.e., descendants of$form
. - $('#btnReset').on('click', function() { ... }
Similarly, we bind an hander to the click event for the reset button. We can use.addClass(classValue)
and.removeClass(classValue)
to add or remove a value fromclass
attribute of the selected elements. We can use.html(value)
to set the innerHTML of the selected elements; and.val()
to retrieve the value. - To check if the selector returns no matches, you can compare the
.length
property with zero.
Tic-Tac-Toe
Screenshot
Click the image to run the demo.
HTML "JSTicTacToe.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 |
<!DOCTYPE html>
<!-- JSTicTacToe.html -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tic-Tac-Toe</title>
<link rel="stylesheet" href="JSTicTacToe.css">
<script src="JSTicTacToe.js"></script>
</head>
<body>
<h1>Tic-Tac-Toe</h1>
<table>
<tr>
<td id="cell0"> </td>
<td id="cell1"> </td>
<td id="cell2"> </td>
</tr>
<tr>
<td id="cell3"> </td>
<td id="cell4"> </td>
<td id="cell5"> </td>
</tr>
<tr>
<td id="cell6"> </td>
<td id="cell7"> </td>
<td id="cell8"> </td>
</tr>
</table><br>
<input type="button" id="btnNewGame" value="New Game">
</body>
</html>
|
CSS "JSTicTacToe.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 39 |
/* JSTicTacToe.css */ 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; } |
JavaScript "JSTicTacToe.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 |
// JSTicTacToe.js /* * 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 = " "; // 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 === " ") { 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; } } |
How it Works?
- 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.
- 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. - 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. - The
init()
function, which is theonload
handler, resets the game variables and cell contents viaresetGame()
, and attaches the functionresetGame()
as the button'sonclick
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. - We use
window.onload=init
to ensure thatinit()
is run after the page is fully loaded, so as to access the elements defined in the page. - 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 number000000111
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 leading0b
, like C/C++/Java.) Similarly, we define two global variables,crossPattern
andnoughtPattern
to keep track of the crosses and noughts placed on the game board so far. - A boolean flag
crossPlaying
is used to keep track of the current player. - The
resetGame()
function resets the game variables (empty thecrossPattern
andnoughtPattern
and set the current player to "cross"). It also clears the contents of the cells, and attachesplay()
function as theonmousedown
event handler, so that the user can click on the cell to play the game. - Whenever the user clicks on a cell, the
play()
event handler triggers with themousedown
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 thecheckWin()
to check if the current player wins the game. If not, it disables this cell by removing theonmousedown
handler, and toggles the current player. - 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 Picker
Screenshot
Click the image to run the demo.
JavaScript Utilities "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 29 |
// DateUtil.js // 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()]; } |
How it Works?
- The function
isLeapYear(year)
returns true ifyear
is a leap year. - The function
getDaysInMonth(year, month)
returns the number of days in the givenmonth
(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. - The function
getDayInWeek(year, month, day)
returns the day of the week (Sunday to Saturday). It constructs a built-in objectDate
with the givenyear
,month
andday
, and use thegetDay()
function of theDate
object to obtain the day of the week in the range of 0-6.
HTML "JSDatePicker.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 |
<!DOCTYPE html>
<!-- JSDatePicker.html -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>A Date Chooser</title>
<script src="JSDateUtil.js"></script>
<script src="JSDatePicker.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>
<input type="text" name="dayInWeek" id="dayInWeek" readonly>
<input type="button&quoquot; id="btnNow" value="Now">
</form>
</body>
</html>
|
JavaScript "JSDatePicker.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 |
// JSDatePicker.js 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); } |
How it Works?
- 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.
- [TODO]
Calendars
Click the image to run the demo.
HTML "JSCalendarSimple.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 |
<!DOCtype html>
<!-- JSCalendarSimple.html -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>JavaScript Calendar</title>
<link rel="stylesheet" href="JSCalendarSimple.css">
<script src="JSDateUtil.js"></script>
<script src="JSCalendarSimple.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>
|
CSS "JSCalendarSimple.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 |
/* JSCalendarSimple.css */
.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
}
|
JavaScript "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 161 |
// JSCalendarSimple.js 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); } } |
How it Works?
- TODO
JavaScript Animation - A Digital Clock
Screenshot
Click the image to run the demo.
JavaScript "JSClockDigital.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 |
<!DOCTYPE html> <!-- JSClockDigital.html --> <html lang="en"> <head> <meta charset="utf-8"> <title>A JavaScript Clock</title> <script type="text/javascript"> window.onload = initClock; 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> <h1 id="clockDisplay"></h1> </body> </html> |
How it works?
- We use the
new Date()
to create aDate
object with the current time and assign to the variablenow
. - We then use the
getHours()
,getMinutes()
,getSeconds()
function ofnow
object to retrieve the hours, minutes and seconds. - We display the clock by setting the
innerHTML
property of the<h1>
tag. We use thegetElementById()
function to retrieve the<h1>
tag. - The function
initClock()
is invoked when the browser loads this page, by attaching it to theonload
event handler. - In
initClock()
, thesetTimeout('initClock()', 500)
function is used to recursively invoke theinitClock()
function every 500 msec, to refresh the display.
JavaScript Animation - Bouncing Balls
Screenshot
Click the image to run the demo.
HTML "JSBouncingBallSimple.html"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!DOCTYPE html> <!-- JSBouncingBallSimple.html --> <html lang="en"> <head> <meta charset="utf-8"> <title>JavaScript Bouncing balls</title> <link rel="stylesheet" href="JSBouncingBallSimple.css"> <script src="JSBouncingBallSimple.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" id="ball" src="images/ball_red.gif" alt="ball"> </body> </html> |
CSS "JSBouncingBallSimple.css"
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* JSBouncingBallSimple.css */ #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; } |
JavaScript "JSBouncingBallSimple.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 |
// JSBouncingBallSimple.js 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.getElementsByClassName("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.getElementsByClassName("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
How it Works?
- 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:
- An id-selector
box
to absolutely position the container box. We use a<div id="box">
tag for the container box by enabling itsborder
property. In theinit()
function, we retrieve the<div id="box">
element viabox=document.getElementById("box")
. We then absolutely position the<div>
element viabox.style.left|top|width|height
. - 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 becauseid
needs to be unique, but many elements can use the sameclass
. The ball is represented by an<img class="ball" src="images/ball_red.gif" />
tag. We useballs=document.getElementsByClassName("ball")
to retrieve an array of the<img>
elements. We then useballs[0].style.left|top|width|height
to position the ball.
- An id-selector
- The
onload
event handler invokes theinit()
, which positions the container box, and the initial position of the ball. - The
moveOneStep()
function invokessetTimeout("moveOneStep()", 60)
, which recursively runs the move() at the specified time (msec) interval. - 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.
JavaScript "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:
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 src="JSSnow.js"></script>
How it Works
- The width and height of the displayed image is controlled by the CSS style.
- 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.
- 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.
HTML "JSXYPlot.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 |
<!DOCTYPE html> <!-- JSXYPlot.html --> <html lang="en"> <head> <meta charset="utf-8"> <title>JavaScript XY-Plotting</title> <link rel="stylesheet" href="JSXYPlot.css"> <script src="JSXYPlot.js"></script> </head> <body> <h2>JavaScript Plotting</h2> <table> <tr> <td> <fieldset> <legend>New</legend> <label>X: <input type="text" size="3" id="newX"></label> <label>Y: <input type="text" size="3" id="newY"></label> <input id="btnCreate" type="button" value="CREATE"> </fieldset> </td> <td> <fieldset> <legend>Update</legend> No: <select name="updateNo" id="updateNo" ></select> <label>X: <input type="text" size="3" id="updateX"></label> <label>Y: <input type="text" size="3" id="updateY"></label> <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> |
CSS "JSXYPlot.css"
1 2 3 4 5 6 7 8 9 10 11 |
/* JSXYPlot.css */ /* id-selector for the container */ #box { position: absolute; border: thick solid red; } /* class-selector for the items and item descriptions */ .item, .itemDesc { position: absolute; } |
JavaScript "JSXYPlot.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 |
// JSXYPlot.js 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
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.
HTML "H5BouncingBall.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 |
<!DOCTYPE html> <!-- H5BouncingBall.html --> <html lang="en"> <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
- HTML 5 provides a new "Canvas API" to support 2D drawing. To use the canvas:
- Create a canvas element via the new
<canvas></canvas>
tag. - In the script, select the canvas element (via
document.getElementById()
) and get the canvas' context (viacanvas.getContext('2d')
). Currently, only'2d'
context is supported. - You can then use the context for drawing. For example,
clearRect()
to clear the container box;beginPath()
andclosePath()
to enclose a path;arc()
,moveTo()
,lineTo()
to define a path.
- Create a canvas element via the new
- We use
window.addEventListener("load", init, true)
to register an event handler (init
function) to theload
event. - We use
setInterval(draw, 30)
to schedule functiondraw()
every 30 msec. - The ball bouncing algorithm is the same as the previous example.
JavaScript Calculators
Screenshot
Click the image to run the demo.
HTML "JSCalculatorSimple.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 |
<!DOCTYPE html>
<!-- JSCalculatorSimple.html -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple JavaScript Calculator</title>
<style>
input {
font-family: consola, monospace;
color: blue;
}
td {
margin-left: auto;
margin-right: auto;
text-align: center;
}
table {
border: thick solid;
}
</style>
</head>
<body>
<h2>Simple JavaScript Calculator</h2>
<form name="calcForm">
<table>
<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>
|
How it Works?
- 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. - A form (called "
calcForm
") is defined with a text field (called "display
"), and 16 buttons. - The inputs are appended to
display.value
. The result is evaluated via theeval()
function in theonclick
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 40 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JavaScript Example: Sending HTTP POST Request</title>
<script>
/*
* 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 44 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JavaScript Example: Sending HTTP POST Request</title> <script> /* * 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 45 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JavaScript Example: Sending HTTP POST Request</title> <script> /* * 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".
Link To JavaScript/jQuery References & Resources