Banu Priya
Banu Priya

Reputation: 61

Auto slash(/) for date input using Javascript

Auto slash(/) with leading and trailing space in a date value is working fine.

var date = document.getElementById('date');

    function checkValue(str, max) {
      if (str.charAt(0) !== '0' || str == '00') {
        var num = parseInt(str);
        if (isNaN(num) || num <= 0 || num > max) num = 1;
        str = num > parseInt(max.toString().charAt(0)) 
               && num.toString().length == 1 ? '0' + num : num.toString();
      };
      return str;
    };

    date.addEventListener('input', function(e) {
      this.type = 'text';
      var input = this.value;
      if (/\D\/$/.test(input)) input = input.substr(0, input.length - 3);
      var values = input.split('/').map(function(v) {
        return v.replace(/\D/g, '')
      });
      if (values[0]) values[0] = checkValue(values[0], 12);
      if (values[1]) values[1] = checkValue(values[1], 31);
      var output = values.map(function(v, i) {
        return v.length == 2 && i < 2 ? v + ' / ' : v;
      });
      this.value = output.join('').substr(0, 14);
    });
<input type="text" id="date" /> 

But when I tried to remove the space before and after slash(/). But when I deleting each character using backspace key, slash is not deleting.

Below is what I tried.

var date = document.getElementById('date');

    function checkValue(str, max) {
      if (str.charAt(0) !== '0' || str == '00') {
        var num = parseInt(str);
        if (isNaN(num) || num <= 0 || num > max) num = 1;
        str = num > parseInt(max.toString().charAt(0)) 
               && num.toString().length == 1 ? '0' + num : num.toString();
      };
      return str;
    };

    date.addEventListener('input', function(e) {
      this.type = 'text';
      var input = this.value;
      if (/\D\/$/.test(input)) input = input.substr(0, input.length - 1);
      var values = input.split('/').map(function(v) {
        return v.replace(/\D/g, '')
      });
      if (values[0]) values[0] = checkValue(values[0], 12);
      if (values[1]) values[1] = checkValue(values[1], 31);
      var output = values.map(function(v, i) {
        return v.length == 2 && i < 2 ? v + '/' : v;
      });
      this.value = output.join('').substr(0, 10);
    });
<input type="text" id="date" /> 


    

Please suggest me to rectify this.

Upvotes: 2

Views: 16875

Answers (4)

Lei Qin
Lei Qin

Reputation: 11

This is my regex solution for React:

// add auto "/" for date, i.e. MM/YY
  handleExpInput(e) {

    // ignore invalid input
    if (!/^\d{0,2}\/?\d{0,2}$/.test(e.target.value)) {
      return;
    }

    let input = e.target.value;

    if (/^\d{3,}$/.test(input)) {
      input = input.match(new RegExp('.{1,2}', 'g')).join('/');
    }

    this.setState({
      expDateShow: input,
    });
  }

Upvotes: 0

John Dover
John Dover

Reputation: 769

I also had this come up as a requirement for an application that I am building and I implemented my solution like this.

$(document).ready(function () {
    Date.prototype.toShortDateString = function() {
        return (this.getMonth() + 1) + "/" + this.getDate() + "/" + this.getFullYear();
    }
    //#region CUSTOM FUNCTIONS FOR DATEPICKERS
    function isTextSelected(input) {
        if (typeof input.selectionStart == "number" && input.selectionStart != input.value.length && input.selectionStart != input.selectionEnd) {
            return true;
        } else if (typeof document.selection != "undefined") {
            input.focus();
            return document.selection.createRange().text == input.value;
        }
        return false;
    }
    function isNumber(e) {
        var allowedKeys = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105];
        if ($.inArray(e.keyCode, allowedKeys) != -1 && !e.originalEvent.shiftKey) {
            return true;
        }
        return false;
    }
    function isBackspace(keyCode) {
        var allowedKeys = [8];
        if ($.inArray(keyCode, allowedKeys) != -1) {
            return true;
        }
        return false;
    }
    function isAllowedKey(keyCode) {
        var allowedKeys = [9, 13, 16, 37, 38, 39, 40];//191,111];
        if ($.inArray(keyCode, allowedKeys) != -1) {
            return true;
        }
        return false;
    }
    //#endregion
    $.fn.extend({
        allowMMDDYYYY: function (validate) {
            $(this).keydown(function (e) {
                var that = this;
                if (!isNumber(e) && !isBackspace(e.keyCode) && !isAllowedKey(e.keyCode)) {
                    e.preventDefault();
                } else if ($(that).val().length == 10 && !isBackspace(e.keyCode) && !isAllowedKey(e.keyCode)) {// && !isTextSelected(e.target) && isNumber(e.keyCode)) {
                    if(!isTextSelected(e.target) && isNumber(e))
                    e.preventDefault();
                }
            });
            $(this).keyup(function (e) {
                var that = this;
                var value = $(that).val();
                if (e.keyCode != 8 && !isAllowedKey(e.keyCode)) {
                    switch (value.length) {
                        case 2:
                            $(that).val(value + "/");
                            break;
                        case 3:
                            if (value.indexOf("/") == -1) {
                                $(that).val(value.substr(0, 2) + "/" + value.substr(2, 1));
                            }
                            break;
                        case 4:
                            if (value.substr(0,3).indexOf("/") == -1) {
                                $(that).val(value.substr(0, 2) + "/" + value.substr(2, 2));
                            }
                            break;
                        case 5:
                            if (e.target.selectionStart == value.length) {
                                if (e.target.selectionStart != 1) {
                                    $(that).val(value + "/");
                                }
                            }
                            break;
                        case 6:
                            if (e.target.selectionStart == value.length) {
                                if (value.substr(5).indexOf("/") == -1) {
                                    $(that).val(value.substr(0, 5) + "/" + value.substr(5, 1));
                                }
                            } else if (e.target.selectionStart == 2) {
                                $(that).val(value.substr(0, 2) + "/" + value.substr(2))
                                e.target.selectionStart = 3;
                                e.target.selectionEnd = 3;
                            }
                            break;
                        case 7:
                            if (e.target.selectionStart == value.length) {
                                if (value.substr(5).indexOf("/") == -1) {
                                    $(that).val(value.substr(0, 6) + "/" + value.substr(5, 2));
                                }
                            } else if (e.target.selectionStart == 2) {
                                $(that).val(value.substr(0, 2) + "/" + value.substr(2));
                                e.target.selectionStart = 3;
                                e.target.selectionEnd = 3;
                            }
                            break;
                        case 9:
                            if (value.substr(3, 5).indexOf("/") == -1) {
                                $(that).val(value.substr(0,5) + "/" + value.substr(5))
                            } else if (value.substr(0, 3).indexOf("/") == -1) {
                                $(that).val(value.substr(0, 2) + "/" + value.substr(2))
                            }
                            break;
                            //IF THE LENGTH IS 10 (ONKEYUP) THEN CALL VALIDATION ON OTHER DATEPICKER ELEMENTS.
                        case 10:
                            if (!isTextSelected(e.target)) {
                                validate();
                            }
                            break;
                    }
                }
            });
        }
    });
    //#endregion
    $("input[data-role='datepicker']").each(function (i, o) {
        var jqueryElement = $(o);
        jqueryElement.allowMMDDYYYY(function () {
            //THIS IS MY CALLBACK FUNCTION TO ALLOW VALIDATION ON OTHER ELEMENTS 
            console.log("validating");
        });
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" data-role="datepicker"/>

My requirements we to be able to enter MMddyyyy format without slashes and it would auto populate the slashes as they typed. Solution does not allow any characters but numbers,backspace, arrow keys, ctrl, and shift key. This extension also has a callback function so that you can validate other elements after a date has been entered (since i was using jquery validator).

Upvotes: 1

Anthony
Anthony

Reputation: 1581

Here's a alternate answer even though Albzi's answer works perfectly fine. You can use the keydown event and check if backspace or delete is being pressed and return false in your event. I also added a maxlength of 10 to your input element so it does not exceed 10 characters.

var date = document.getElementById('date');

function checkValue(str, max) {
  if (str.charAt(0) !== '0' || str == '00') {
    var num = parseInt(str);
    if (isNaN(num) || num <= 0 || num > max) num = 1;
    str = num > parseInt(max.toString().charAt(0)) && num.toString().length == 1 ? '0' + num : num.toString();
  };
  return str;
};

date.addEventListener('keydown', function(e) {
  this.type = 'text';
  var input = this.value;
  var key = e.keyCode || e.charCode;

  if (key == 8 || key == 46)    // here's where it checks if backspace or delete is being pressed
    return false;
    
  if (/\D\/$/.test(input)) input = input.substr(0, input.length - 1);
  var values = input.split('/').map(function(v) {
    return v.replace(/\D/g, '')
  });
  if (values[0]) values[0] = checkValue(values[0], 12);
  if (values[1]) values[1] = checkValue(values[1], 31);
  var output = values.map(function(v, i) {
    return v.length == 2 && i < 2 ? v + '/' : v;
  });
  this.value = output.join('').substr(0, 10);
});
<input type="text" id="date" maxlength="10" />

Upvotes: 2

Albzi
Albzi

Reputation: 15609

var date = document.getElementById('date');

    function checkValue(str, max) {
      if (str.charAt(0) !== '0' || str == '00') {
        var num = parseInt(str);
        if (isNaN(num) || num <= 0 || num > max) num = 1;
        str = num > parseInt(max.toString().charAt(0)) 
               && num.toString().length == 1 ? '0' + num : num.toString();
      };
      return str;
    };

    date.addEventListener('input', function(e) {
      this.type = 'text';
      var input = this.value;
      if (/\D\/$/.test(input)) input = input.substr(0, input.length - 3);
      var values = input.split('/').map(function(v) {
        return v.replace(/\D/g, '')
      });
      if (values[0]) values[0] = checkValue(values[0], 12);
      if (values[1]) values[1] = checkValue(values[1], 31);
      var output = values.map(function(v, i) {
        return v.length == 2 && i < 2 ? v + ' / ' : v;
      });
      this.value = output.join('').substr(0, 14);
    });
input {
    word-spacing:-3px;
}
<input type="text" id="date" />

You can 'cheat' and use some CSS:

word-spacing:-3px;

This moves the / closer to the text.

The reason it doesn't work when you remove the spaces from the JavaScript is because your code is looking for a string length of 2, but the string length goes to 3 when you add the / with no spaces.

Upvotes: 14

Related Questions