Sunday, October 9, 2011

Advanced jQuery Form validation (2): Validate a date

After checking a phone number against its international format, we will now check if a date entered as a string is valid.

We can of course use a date picker such as jQueryUI Datepicker to ease the user experience and with a nicer look and feel, but the aim of this example is to show you some advanced jQuery Form validation so we will use a very simple example. As a matter of fact, even with the aformentioned date picker, this control is still useful as your users can enter the date manually in your text input field.
In that case, we want to get a date in the format mm/dd/yyyy (e.g.: 01/31/2011), comprised between January, 1st 2000 and the current day.

As always, in the HTML form, we set the maximum length of the date field in case javascript is deactivated (so we have to do the data cleaning and checking on the server side too as we don't want to end up with wrong data).

<form id="myFormId" method="post">
    <label for="dateId">Date</label>
    <input type="text" name="date" id="dateId" maxlength="10" value="" /><br/>
    <input type="submit" value="Submit" />
</form>

The validator checks first if the date is written in the expected format (mm/dd/yyyy), then if the date is valid (leap year, maximum number of days for the given month), and if it is after January, 1st 2000. Of course, the date format can be changed easily by modifying the regular expression and changing the populating of the three variables year, month and day.
The error message uses the jQuery string formatting: it contains a variable between curly brackets ({0}) and its matching value, in that case the year entered (new Array(year)).
jQuery.format('The month of February of the year {0} counts 28 days maximum.', new Array(year));

We display the error message with the method this.showErrors(errors) where errors links the error message to the matching element name.

The form validator set of rules links them to the form id (myFormId), and to the date input field name (date). The only rule applied is the one defined in the new validator (myDateChecker). This time, we call it this way (date-id: { myDateChecker: true }), but this other way (date: "myDateChecker" }) is possible too. We can say it's a matter of writing style.
$(document).ready(function(){
    jQuery.validator.addMethod("myDateChecker", function(value, element) {
        // value: mm/dd/yyyy
        if(/^\d\d\/\d\d\/\d\d\d\d/i.test(value)) {
            // check valid date
            var year = substr(value, 6, 4);
            var month = substr(value, 0, 2);
            var day = substr(value, 3, 2);
            if (month == 2) {
                if (day == 29) {
                    if (year % 4 != 0 || year % 100 == 0 && year % 400 != 0) {
                        var errors = {};
                        errors[element.name] = jQuery.format('The month of February of the year {0} counts 28 days maximum.', new Array(year));
                        this.showErrors(errors);
                    }
                }
                else if (day > 28) {
                    var errors = {};
                    errors[element.name] = jQuery.format('The month of February of the year {0} counts 28 days maximum.', new Array(year));
                    this.showErrors(errors);
                }
            }
            else if (month == 4 || month == 6 || month  == 9 || month == 11) {
                if (day > 30) {
                    var errors = {};
                    errors[element.name] = 'The entered month counts 30 days maximum.';
                    this.showErrors(errors);
                }
            }
            else {
                if (day > 31) {
                    var errors = {};
                    errors[element.name] = 'The entered month counts 31 days maximum.';
                    this.showErrors(errors);
                }
            }

            var today = new Date();
            today.setHours(23);
            today.setMinutes(59);
            today.setSeconds(59);
            var new_epoch = new Date('2000', '0', '1');
            var entered_date = new Date(year, month - 1, day, 23, 59, 59);
            if ((entered_date > today) || (entered_date < new_epoch)) {
                var errors = {};
                errors[element.name] = 'Please enter a date between 01/01/2000 and today.';
                this.showErrors(errors);
            }
            else {
                this.hideErrors();
                return true;
            }
        }
        else {
            var errors = {};
            errors[element.name] = 'Please enter a date between 01/01/2000 and today (format: mm/dd/yyyy).';
            this.showErrors(errors);
        }
        return true;
    });

    $("#myFormId").validate({
        rules: {
            date: "myDateChecker"
        }
    });
});

Validation de formulaire jQuery avancée (2) : valider une date (in French)
Validación de formulario jQuery avanzado (2): como validar una fecha (in Spanish)
Validação de formulário jQuery avançado (2): como validar uma data (in Portuguese)

No comments:

Post a Comment