Skip to content
Advertisement

Insert “/” in MM/YYYY textbox on keypress event

I want to enter a “/” when user enters MM(2 digit) so it will be like MM/YYYY.

I have done similar for credit card number input which insert a space after 4 digit on keypress.

let ccNumber = e.target.value.split(" ").join("");
      if (ccNumber.length > 0) {
         ccNumber = ccNumber.match(new RegExp('.{1,4}', 'g')).join(" ");
         }
e.target.value = ccNumber;

Advertisement

Answer

Fiddle

This works with

  • Regular keyboard input
  • Copy/Cut/Paste
  • Selected text

Adding the /

Because you’re programmatically adding the / character, you have to update the cursor position whenever that affects the new input value. This can be more than one character if the user is pasting something. Most of the code complexity revolves around this issue.

There are a lot of comments in the code explaining the various situations that come up because of the /.

Full Code

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

date.addEventListener('keypress', updateInput);
date.addEventListener('change', updateInput);
date.addEventListener('paste', updateInput);
date.addEventListener('keydown', removeText);
date.addEventListener('cut', removeText);

function updateInput(event) {
  event.preventDefault();
  var string = getString(event);
  var selectionStart = this.selectionStart;
  var selectionEnd = this.selectionEnd;
  var selectionLength = selectionEnd - selectionStart;
  var sanitizedString = string.replace(/[^0-9]+/g, '');
  // Do nothing if nothing is added after sanitization
  if (sanitizedString.length === 0) {
  	return;
  }
  // Only paste numbers that will fit
  var valLength = date.value.replace(/[^0-9]+/g, '').length;
  var availableSpace = 6 - valLength + selectionLength;
  // If `/` is selected it should not count as available space
  if (selectionStart <= 2 && selectionEnd >= 3) {
  	availableSpace -= 1;
  }
  // Remove numbers that don't fit
  if (sanitizedString.length > availableSpace) {
  	sanitizedString = sanitizedString.substring(0, availableSpace);
  }
  var newCursorPosition = selectionEnd + sanitizedString.length - selectionLength;
  // Add one to cursor position if a `/` gets inserted
  if (selectionStart <= 2 && newCursorPosition >= 2) {
    newCursorPosition += 1;
  }
  // Previous input value before current cursor position
  var valueStart = date.value.substring(0, this.selectionStart);
  // Previous input value after current cursor position
  var valueEnd = date.value.substring(this.selectionEnd, date.value.length);
  var proposedValue = valueStart + sanitizedString + valueEnd;
	// Remove anything that's not a number
  var sanitized = proposedValue.replace(/[^0-9]+/g, '');
  format(sanitized);
  this.setSelectionRange(newCursorPosition, newCursorPosition);
}

function removeText(event) {
  if (event.key === 'Backspace' || event.type === 'cut') {
    event.preventDefault();
    var selectionStart = this.selectionStart;
    var selectionEnd = this.selectionEnd;
    var selectionLength = selectionEnd - selectionStart;
    // If pressing backspace with no selected text
    if (selectionLength === 0 && event.type !== 'cut') {
    	selectionStart -= 1;
      // Remove number from before `/` if attempting to delete `/`
      if (selectionStart === 2) {
        selectionStart -= 1;
      }
    }
    var valueStart = date.value.substring(0, selectionStart);
    var valueEnd = date.value.substring(selectionEnd, date.value.length);
    // Account for added `/`
    if (selectionStart === 2) {
      selectionStart += 1;
    }
    var proposedValue = valueStart + valueEnd;
    var sanitized = proposedValue.replace(/[^0-9]+/g, '');
    format(sanitized);
    this.setSelectionRange(selectionStart, selectionStart);
  }
}

function getString(event) {
	if (event.type === 'paste') {
    var clipboardData = event.clipboardData || window.clipboardData;
    return clipboardData.getData('Text');
  } else {
  	return String.fromCharCode(event.which);
  }
}

function format(sanitized) {
	var newValue;
  var month = sanitized.substring(0, 2);
  if (sanitized.length < 2) {
  	newValue = month;
  } else {
  	var year = sanitized.substring(2, 6);
    newValue = month + '/' + year;
  }
  date.value = newValue;
}
<input id="date" type="text" maxlength="7">
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement