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">