
Originally Posted by
Anton
Allows the user to enter a date in ... dd/mm/yyyy or mm/dd/yyyy date formats.
What about the international date format?
Auto corrects users prefered separator to the default. So if the default separator is "-", 1/1/2007 will be converted to 1-1-2007 on validation.
Why?
Automatically finds input text fields with "date" in their id, and attaches validation to them. e.g. <input type="text" id="myDateField">. Just need to include the .js and it is set up.
Why the id attribute? For a form control to be successful and have its value submitted it must have a name attribute. That would seem to be the more logical option.
Automatically puts in todays date when "t" is keyed.
Automatically modifying user input isn't always such a good idea. It would be better to use a button that inserted the date when activated.
Uses the onblur event to validate on.
The blur event is unfriendly: the user cannot leave the control until the value is considered valid, a usability no-no. Instead, use the change event and validate before submission - only the latter is another option.
Doesn't here.
The code is vastly overcomplicated. The function below (documented in a past thread) will validate DMY, MDY, and YMD using full stops (.), dashes (-), and slashes (/) as separators.
Code:
function parseDate(string, preferMDY) {
var match, year, month, date, result;
preferMDY = Boolean(preferMDY);
if ((match = /^(\d{4})([.\/-])(\d{1,2})\2(\d{1,2})$/.exec(string))) {
year = Number(match[1]);
month = Number(match[3]);
date = Number(match[4]);
} else if ((match = /^(\d{1,2})([.\/-])(\d{1,2})\2(\d{4})$/.exec(string))) {
year = Number(match[4]);
if (preferMDY) {
month = Number(match[1]);
date = Number(match[3]);
} else {
month = Number(match[3]);
date = Number(match[1]);
}
if (month > 12) {
var temp = month;
month = date;
date = temp;
}
}
with ((result = new Date(year, --month, date)))
if ((month == getMonth()) && (date == getDate())) return result;
return null;
}
It could also accept omitted or additional separators with a small tweak to both regular expressions.
Now an examination of the code itself.
Code:
// CONSTANTS - may need your attention.
/* [List omitted] */
There is no need for these to be global, something which can also be said for the global functions (such as __checkDate). See my tutorial article in the Coding tips and tutorials board for a way to avoid polluting the global namespace.
Code:
function $(id)
{
// a'la Prototype.js, bah, its sooo BIG!
return document.getElementById(id);
}
Identifiers with a leading dollar symbol ($) are explicitly reserved for machine-generated identifiers. Like the Prototype library, which I thoroughly disdain, you flout this and provide no feature detection or provide a fall-back.
Code:
DateValidator.prototype.load = function(field)
{
/* ... */
this.fields.push(field);
}
I assume you have no desire to support earlier versions of IE which don't implement the push method?
Code:
DateValidator.prototype.onblur = function()
{
/* ... */
// Generic error message
var fName=(this.name)?this.name:this.id;
alert("Bad date in \""+fName+"\" field.");
this.select();
}
}
}
Using the blur method in combination with changing the currently focused control can lead to a fatal situation where focus is continuously changed between invalid controls, forcing the user to close their browser. This is another reason why the change event is preferred.
Expecting the name or id attributes to contain a human-readable value isn't very realistic. Instead, use an object to lookup names:
Code:
var fieldNames = {a : 'Foo', b : 'Bar'};
/* ... */
alert('Invalid date in the "' + fieldNames[this.name] '" field.');
Code:
// This trigger actually ALLOWS the page to load before looking at
// the stuff on it. Without the setTimeout, the page is
// not "really" loaded, I think the onload event triggers just
// before the page renders, so sticking in the delay of actually
// having to look at the setTimeout function distracts the browser
// so it renders before the javascript is run.
"Sticking in the delay" is nothing but a hack.
Code:
// If you use:
// document.onload = init();
// the code will not see anything.
Of course not. The init function will be called immediately - that's what an identifier followed by parentheses (containing an optional argument list) means - and its return value - presumably undefined - will be assigned to the onload property. Moreover, the load event is not dispatched from the document object, rather it is dispatched from the global object.
Verified in IE & FireFox.
Not very well, apparently.
Code:
document.onload = setTimeout("__initDateValidator()",0);
This assigns the time-out handle to the onload property.
Code:
function __initDateValidator()
{
/* ... */
// check for an error handler...
try {
handler = DateValidatorErrorHandler;
} catch(e) { }
Exception handling? This simple statement would have done quite well:
Code:
if (typeof DateValidatorErrorHandler == 'function') handler = DateValidatorErrorHandler;
Code:
// Parouse the doc for text input nodes with "date" in id.
var inFields = document.getElementsByTagName("input");
Again, no feature detection.
The function,
Code:
function __isNumber(i)
{
// Returns true if i is a number.
var x1 = i * 1;
return (x1 == i);
}
isn't up to the task. As a result, your code will validate a date string such as '1.-1.-1.55' as correct.
Bookmarks