Date validation using onkeydown in Javascript and ASP

R

Rob

I have a date text box (input type = text) in an ASP.NET/Javascript
environment. I wanted to force the users to enter dates in a
"__/__/____", "dd/mm/yyyy" or similar format. The textbox needs to
support normal copy/paste/delete format. There wasn't much on Google
to help so (after a bit of toil) though I'd post my suggested solution
here. No guarantees I'm afraid; just hope it helps somebody out there.

Rob

Here's the ASP source code:

<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="WebForm2.aspx.vb" Inherits="WebApplication1.WebForm2"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<script language="Javascript" src="DateMask.js"></script>
</head>
<body>
<form id="frmMain">
<b>Date TextBox</b><p></p>
Enter Date:
<input type="text" name="txtDate" id="txtDate" size="10"
maxlength="10" onkeydown="dateOnKeyDown()"
onpaste="dateOnPaste(this)" value="__/__/____">
<p></p>
</form>
</body>
</html>

And the contents of DateMask.js:

function dateOnKeyDown() {
/* Purpose : Formats date text field so it adheres to
* the dd/mm/yyyy format
*
* Effects : Sets the value of the text field
*
* Inputs : None
*
* Returns : None
*/

var DATE_DIVIDER = "/";
var SPACE_CHARACTER = "_";

var objTextBox = window.event.srcElement;
var iKeyCode = window.event.keyCode;
var bSelectedText = false;

// Exit if field is read-only
if (window.event.srcElement.readOnly) return;

// Allow key presses of <cursor arrow> or <Home> or <End>
if ((iKeyCode > 36 && iKeyCode < 41) || (iKeyCode > 34 && iKeyCode <
37)) {
return 1;
}

// Allow <Ctrl+C>, <Ctrl+V>, <Ctrl+X> and <Ctrl+Z>
if (window.event.ctrlKey && (iKeyCode == 67 || iKeyCode == 86 ||
iKeyCode == 88 || iKeyCode == 90)) {
return 1;
}

// Get the position of the cursor
var iCaretPosition = getCaretPosition(objTextBox);

// Get the selected text
var objSelectedText = document.selection.createRange();

// Determine if some text has been selected
if (objSelectedText.parentElement() == objTextBox &&
objSelectedText.text.length > 0)
{
bSelectedText = true;
}

// Get the element next to the cursor (to be used later)
var sFirstElement = objTextBox.value.substring(iCaretPosition,
iCaretPosition-1);

// Do not enter number if there's no space for it
if ((sFirstElement != SPACE_CHARACTER) && !(iKeyCode == 8 || iKeyCode
== 46) && objSelectedText.text == 0) {
return 0;
}

// If key pressed is <0-9>
if ((iKeyCode > 47 && iKeyCode < 58) ||
(iKeyCode > 95 && iKeyCode < 106)) {
if (iKeyCode > 95) iKeyCode -= (95-47);

// Do not update text/move cursor if it is at the end of the textbox
if (iCaretPosition != 11) {

// Only write the character if it's filling an empty gap
// ie don't overwrite existing number or '/' characters
var sNextElement = objTextBox.value.substring(iCaretPosition-1,
iCaretPosition);

if (!bSelectedText && sNextElement == SPACE_CHARACTER) {
// Get the text before the cursor
var sElement1 = objTextBox.value.substring(0, iCaretPosition-1);
// Get the text after the cursor
var sElement2 = objTextBox.value.substring(iCaretPosition +
objSelectedText.text.length, objTextBox.value.length);
// Append the new character
sElement1 += String.fromCharCode(iKeyCode);
// Append the text from after the cursor
sElement1 += sElement2;
objTextBox.value = sElement1;

// Move the cursor position on one for "/" charcters
switch (iCaretPosition) {
case 2:
case 5:
iCaretPosition = iCaretPosition+1;
default:
}
}

// Handle selected text
if (bSelectedText) {

// Get the text before the selected text
var sElement1 = objTextBox.value.substring(0, iCaretPosition-1);

// We need to keep "/" characters
if (sFirstElement == DATE_DIVIDER) {
sElement1 += DATE_DIVIDER;
}

// Append the new character
sElement1 += String.fromCharCode(iKeyCode);

// Replace the remaining selected text with blank spaces
for (var i=1; i<objSelectedText.text.length; i++) {
var sDeletedChar = objSelectedText.text.substring(i, i+1);
if (sDeletedChar == DATE_DIVIDER) {
// Keep the slash characters
sElement1 += DATE_DIVIDER;
} else {
// Do not insert extra space if the first selected character is
a "/"
if (!(i==1 && sFirstElement == DATE_DIVIDER)) {
// Replace numbers with a space
sElement1 += SPACE_CHARACTER;
}
}
}

// Get the text after the selected text and append
var sElement2 = objTextBox.value.substring(iCaretPosition +
objSelectedText.text.length-1, objTextBox.value.length);
sElement1 += sElement2;
objTextBox.value = sElement1;
}

// Put the cursor in the correct position
objSelectedRange = objTextBox.createTextRange();

// Move cursor on 1 if the first selected character is a "/"
if (bSelectedText && sFirstElement == DATE_DIVIDER) iCaretPosition
= iCaretPosition+1;
objSelectedRange.move("character", iCaretPosition)
objSelectedRange.select();

}
} // End if key pressed is <0-9>

// If key pressed is <Del>
if (iKeyCode == 8 || iKeyCode == 46) {

// Handle selected text
if (bSelectedText) {

// Get the text before the selected text
var sElement1 = objTextBox.value.substring(0, iCaretPosition-1);

// We need to keep "/" characters
if (sFirstElement == DATE_DIVIDER) {
sElement1 += DATE_DIVIDER;
}

// Append the new character
sElement1 += SPACE_CHARACTER;

// Replace the remaining selected text with blank spaces
for (var i=1; i<objSelectedText.text.length; i++) {
var sDeletedChar = objSelectedText.text.substring(i, i+1);
if (sDeletedChar == DATE_DIVIDER) {
// Keep the slash characters
sElement1 += DATE_DIVIDER;
} else {
// Do not insert extra space if the first selected character is a
"/"
if (!(i==1 && sFirstElement == DATE_DIVIDER)) {
// Replace numbers with a space
sElement1 += SPACE_CHARACTER;
}
}
}

// Get the text after the selected text and append
var sElement2 = objTextBox.value.substring(iCaretPosition +
objSelectedText.text.length-1, objTextBox.value.length);
sElement1 += sElement2;
objTextBox.value = sElement1;

iCaretPosition = iCaretPosition+1;

} else {
// We need to delete character by character
if (iCaretPosition != 11 || iKeyCode != 46) {

if (iKeyCode == 46) iCaretPosition = iCaretPosition+1;

if (iCaretPosition != 1 && iCaretPosition != 4 && iCaretPosition
!= 7){
var sElement1 = objTextBox.value.substring(0, iCaretPosition-2);
var sElement2 = objTextBox.value.substring(iCaretPosition-1,
objTextBox.value.length);
sElement1 += SPACE_CHARACTER;
sElement1 += sElement2;
objTextBox.value = sElement1;
}
}
}

// Put the cursor in the correct position
objRange = objTextBox.createTextRange();
// Move cursor on 1 if the first selected character is a "/"
if (bSelectedText && sFirstElement == DATE_DIVIDER) iCaretPosition =
iCaretPosition+1;
objRange.move("character", iCaretPosition - 2)
objRange.select();

} // End if key pressed is <Del>

// If key pressed is <Tab>
if (iKeyCode != 9) {
event.returnValue = false;
}
}


function getCaretPosition(objTextBox){
/* Purpose : Returns the caret position of the cursor
* in the text box
*
* Effects : None
*
* Inputs : objTextBox - a text box
*
* Returns : Integer indicating the caret position
* in the text box
*/

var i = objTextBox.value.length+1;

if (objTextBox.createTextRange){
objCaret = document.selection.createRange().duplicate();
while (objCaret.parentElement()==objTextBox &&
objCaret.move("character",1)==1) --i;
}

return i;
}

function dateOnPaste(objTextBox) {
/* Purpose : Handles paste event
*
* Effects : Copies the clipboard value to the text field
*
* Inputs : None
*
* Returns : None
*/

var sClipboard = window.clipboardData.getData('Text');

// Validate that the pasted text is in nn/nn/nnnn format
if (sClipboard.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)) {
objTextBox.value = sClipboard;
} else {
// Do not allow paste
window.event.returnValue = 0;
}
}
 
D

Dr John Stockton

JRS: In article <[email protected]>,
dated Mon, 15 Nov 2004 06:25:53, seen in Rob
Lines: 290
I have a date text box (input type = text) in an ASP.NET/Javascript
environment. I wanted to force the users to enter dates in a
"__/__/____", "dd/mm/yyyy" or similar format. The textbox needs to
support normal copy/paste/delete format. There wasn't much on Google
to help so (after a bit of toil) though I'd post my suggested solution
here. No guarantees I'm afraid; just hope it helps somebody out there.

Those paid by the yard, perhaps.

ISTM better to allow anything to be put in the box and to check it for
being the right format, /^\d\d\/\d\d\/\d\d\d\d$/, when appropriate. Why
not do a proper check of the date value, including rejection of day too
big for month and test within plausible year range? It takes rather
little code - see newsgroup FAQ & sig below, then js-date4.htm.

You have apparently allowed your posting agent to wrap code lines. That
is bad; code for News should be written not to exceed about 72
chars/line, with line-breaks and indentation added judiciously.
Here's the ASP source code:

<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="WebForm2.aspx.vb" Inherits="WebApplication1.WebForm2"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

if (sClipboard.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)) {

For [0-9] write \d.
For dd/mm/yyyy, /^[0-3]\d\/[01]\d\/\d{4}$/ would, for example, reject
12/25/2004; but if a proper check is done there is no need to RegExp
specific digits.


BTW, your
// Allow key presses of <cursor arrow> or <Home> or <End>
if ((iKeyCode > 36 && iKeyCode < 41) || (iKeyCode > 34 && iKeyCode <
37))

seems odd; does it mean 36 36 37 38 39 40 ?


Also, it's trivial to be more liberal with the separator; some prefer
space, dot, or minus. /^\d\d(\D)\d\d\1\d\d\d\d$/ should allow any
repeated separator.
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

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

Latest Threads

Top