Georgi Michev
Georgi Michev

Reputation: 894

Date validator in javascript

I have few months java experience, but now I am trying to write my first javascript to validate a date input. I am not sure what is wrong in the code.

            <label for="Start-date" class="label">Available start date</label>
            <input type="text" onsubmit="isValidDate()" class="w-input" maxlength="256" name="Start-date" data-name="Start date" placeholder="dd/mm/yyyy" id="Start-date" th:value="${possibleStartDate}" />
            <script>
            var validDate = true;
            function isValidDate(){

                var dateString = document.getElementById("Start-date");
                // First check for the pattern
                if(!/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(dateString)){
                    validDate = false;
                    return;
                }  

                // Parse the date parts to integers
                var parts = dateString.split("/");
                var day = parseInt(parts[1], 10);
                var month = parseInt(parts[0], 10);
                var year = parseInt(parts[2], 10);

                // Check the ranges of month and year
                if(year < 1000 || year > 3000 || month == 0 || month > 12){
                    validDate = false;
                    return;
                }    

                var monthLength = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

                // Adjust for leap years
                if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)){
                    monthLength[1] = 29;
                }    

                // Check the range of the day
               if (!(day > 0 && day <= monthLength[month - 1])){
                   validDate = false;
                   return;
               }else{
                   return;
               }
            };
            if(!validDate){
                alert("Invalid date!");
            }
            </script>

Also what is the better alternative to alert ? Something like a red small message under the textfield that the input is incorrect when submit button is pressed. I know it is better to have separate file for the javascript, but I am not sure where in the html to put the tags to link the file.

Upvotes: 0

Views: 176

Answers (2)

Chirag Ravindra
Chirag Ravindra

Reputation: 4830

There were quite a few things which needed a little tweak:

  1. var dateString = document.getElementById("Start-date") should be var dateString = document.getElementById("Start-date").value;

  2. var day = parseInt(parts[1], 10); should be var day = parseInt(parts[0], 10); and var month = parseInt(parts[0], 10); should be var month = parseInt(parts[1], 10); to support dd/mm/yyyy

  3. Inputs don't fire onsubmit unless they are a part of a form you can try onblur instead

  4. I have wrapped the input with div with children indicating success/error to show the message better. (The messages are hidden shown using classes on the root div and supporting styles)

  5. I have spearated out the validation of a date string from DOM manipulation so you can reuse the validation across multiple places

NOTES:

  1. You may be better off setting the input type as date (the browser will open up a date picker if it supports it)
  2. You can also optionally use libraries like momentjs to make common date operations a little easier.

/**
 * Function which takes a string as an input and validates if it
 * is a date in the dd/mm/yyyy format
 * @param {string} dateString - The string representation of the date to validate
 8 @returns {boolean} value indicating if the date is valid (true) or not (false)
 */
function isValidDate(dateString) {
  var validDate = true;
  
  // First check for the pattern
  if (!/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(dateString)) {
    return false;
  }

  // Parse the date parts to integers
  var parts = dateString.split("/");
  var day = parseInt(parts[0], 10);
  var month = parseInt(parts[1], 10);
  var year = parseInt(parts[2], 10);

  if(isNaN(day)  || isNaN(month) || isNaN(year)){
    return false;
  }
  
  // Check the ranges of month and year
  if (year < 1000 || year > 3000 || month < 1 || month > 12) {
    return false;
  }

  var monthLength = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

  // Adjust for leap years
  if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
    monthLength[1] = 29;
  }

  // Check the range of the day
  if (!(day > 0 && day <= monthLength[month - 1])) {
    return false;
  }
  
  return true;

};


/**
 * Function which executes each time the input loses focus (onblur)
 */
function validateDate() {
  // Get a reference to the container
  var container = document.querySelector('.date');

  // Clear stale error/success messages
  container.className = container.className.replace('success', '');
  container.className = container.className.replace('error', '');

  // Get current value of input
  var dateString = document.getElementById("Start-date").value;
  
  // Test if the string is a valid date
  var isValid = isValidDate(dateString);
  
  // Update classess of container to show success/error
  if (!isValid) {
    container.className += ' error';
  } else {
    container.className += ' success';
  }
}
div.date .error {
  display: none;
  background: red;
  color: white;
}

div.date .success {
  display: none;
  background: darkgreen;
  color: white;
}

div.date.success .success {
  display: block;
}

div.date.error .error {
  display: block;
}
<div class="date">
  <label for="Start-date" class="label">Available start date</label>
  <input type="text" onblur="validateDate()" class="w-input" maxlength="256" name="Start-date" data-name="Start date" placeholder="dd/mm/yyyy" id="Start-date" th:value="${possibleStartDate}" />
  <div class="error">Please enter a valid date</div>
  <div class="success">Date is valid</div>
</div>

Upvotes: 1

D. Pardal
D. Pardal

Reputation: 6597

If you're using the EcmaScript Date Time String Format, you can use the Date constructor. (Info

var dateString = document.getElementById("Start-date").value;
var validDate = !(isNaN( new Date(dateString) )

HTML5 also supports a type="date" in the <input> tag. This will prevent the browser from submitting the form if the date is invalid.

Also, I think you meant

var dateString = document.getElementById("Start-date").value;

Instead of

var dateString = document.getElementById("Start-date");

Because document.getElementById("Start-date") is an object.

Upvotes: 0

Related Questions