Added:
- Form validation using pattern attribute, thanks morbusg
 - Allowed for pasting ISO yyyy-mm-dd formats, along with mm/dd/yyyy and m/d/yyyy, thanks J-H
 
const dateInputdateInputs = document.getElementByIdquerySelectorAll('dateInput''.date-input');
dateInputs.forEach(dateInput => {
    let lastValue = ""; // To keep track of the previous value for backspace detection
    
    dateInput.addEventListener('input', function() {
        let val = dateInputthis.value;
        // If backspacing, skip the rest of the formatting
        if (lastValue && lastValue.length > val.length) {
            lastValue = val;
            return;
        }
        if (val.endsWith('/')) {
            val = val.slice(0, -1); // Remove the manually entered slash
            if (val.length === 1) {
                val = '0' + val + '/';
            } else if (val.length === 4) {
                val = val.slice(0, 3) + '0' + val.slice(3) + '/';
            }
        }
        val = val.replace(/\D/g, ''); // Remove any non-digit characters
        // Apply the MM/DD/YYYY format with constraints
        if (val.length === 1 && parseInt(val, 10) > 1) {
            val = '0' + val + '/';
        } else if (val.length >= 2) {
            let month = parseInt(val.substring(0, 2), 10);
            if (month === 0) month = 1;
            if (month > 12) month = 12;
            val = (month < 10 ? '0' + month : month) + '/' + val.substring(2);
        }
        if (val.length === 4 && parseInt(val.substring(3, 4), 10) > 3) {
            val = val.substring(0, 3) + '0' + val.substring(3) + '/';
        } else if (val.length >= 5) {
            let day = parseInt(val.substring(3, 5), 10);
            if (day === 0) day = 1;
            if (day > 31) day = 31;
            val = val.substring(0, 3) + (day < 10 ? '0' + day : day) + '/' + val.substring(5);
        }
        if (val.length === 7) {
            const yearStart = parseInt(val.substring(6, 7), 10);
            if (yearStart >= 4 && yearStart <= 9) { // If between 4 - 9 assume 1900's
                val = val.substring(0, 6) + '19' + val.substring(6);
            } else if (yearStart === 0 || yearStart === 3) { // If between 0 or 3 assume 2000's
                val = val.substring(0, 6) + '20' + val.substring(6);
            }
        } else if (val.length >= 10) {
            let year = parseInt(val.substring(6, 10), 10);
            if (year < 1900) {
                year = 1900;
            } else if (year > 2100) {
                year = 2100;
            }
            val = val.substring(0, 6) + year;
        }
        dateInputthis.value = val;
        lastValue = val;
        dateInput.addEventListener('paste', function(e) {
            e.preventDefault();
            const clipboardData = e.clipboardData || window.clipboardData;
            let pastedData = clipboardData.getData('Text');
            if (isISOFormat(pastedData)) {
                this.value = convertFromISOFormat(pastedData);
            } 
            else if (isShortDateFormat(pastedData)) {
                this.value = convertFromShortFormat(pastedData);
            } 
            else if (isStandardDateFormat(pastedData)) {
                this.value = pastedData;
            } 
            else {
                // If it doesn't match any of the allowed formats, don't set the value.
                this.value = "";
                alert("Please paste a date in the correct format!");
                return;
            }
            let event = new Event('input', {
                'bubbles': true,
                'cancelable': true
            });
            dateInput.dispatchEvent(event); // manually dispatch input event to trigger your input handler after paste
        });
    });
    // Prevent users from entering non-digit characters, except slash
    dateInput.addEventListener('keydown', function(e) {
        if (!isNumericEventisAllowedDateKeyEvent(e)) {
            e.preventDefault();
        }
    });
});
// Check if it's in yyyy-mm-dd format
function isNumericEventisISOFormat(edate) {
    const isoPattern = /^\d{4}-\d{2}-\d{2}$/;
 let charCode = ereturn isoPattern.keyCode;test(date);
}
// Convert yyyy-mm-dd to MM/DD/YYYY
function convertFromISOFormat(isoDate) {
    ifconst parts = isoDate.split(charCode'-');
 > 31 && return `${parts[1]}/${parts[2]}/${parts[0]}`;
}
// Check if it's in m/d/yyyy format
function isShortDateFormat(charCodedate) <{
 48 || charCode >const 57shortDatePattern = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
    return shortDatePattern.test(date);
}
// &&Convert charCodem/d/yyyy !==to 37MM/DD/YYYY
function &&convertFromShortFormat(shortDate) charCode{
 !== 39 && charCodeconst !==parts 8= &&shortDate.split('/');
 charCode !== 46 &&const charCodemonth !=== 191parts[0].padStart(2, '0');
    const day = parts[1].padStart(2, '0');
    const year = parts[2];
    return `${month}/${day}/${year}`;
}
// Check if it's in mm/dd/yyyy format
function isStandardDateFormat(date) {
    const standardDatePattern = /^\d{2}\/\d{2}\/\d{4}$/;
    return false;standardDatePattern.test(date);
}
function isAllowedDateKeyEvent(e) {
    let charCode }= e.keyCode;
    // Allow CTRL key or CMD key on Mac (e.metaKey)
    if (e.ctrlKey || e.metaKey) {
        return true;
    }
    if (charCode > 31 && (charCode < 48 || charCode > 57) && charCode !== 37 && charCode !== 39 && charCode !== 8 && charCode !== 46 && charCode !== 191) {
        return false;
    }
    return true;
}
<input type="text" id="dateInput"class="date-input" placeholder="mm/dd/yyyy" pattern="\d*">pattern="\d{2}/\d{2}/\d{4}" inputmode="numeric">