Search code examples
javascriptevent-handlingtextinputsanitizationpreventdefault

Why doesn't preventDefault() of an input event stop changes to the value of a form element


This question has been asked and answered before; none of the previous answers given here seem to fix my situation. Therefore I need to ask, once again, why isn't the event prevented correctly?

document.addEventListener("input", event => {
   if(event.data == '#' || event.data == '+' || event.data == '.' || event.data == ';'){
       event.preventDefault();
       alert("Non-allowed character detected: " + event.data);
       return false;
    }
});

I have tried different versions, for example I added the event.stopPropagation() and event.stopImmediatePropagation() but nothing changed. What am I doing wrong and how do I fix it?

It might help to know that I'm simply trying to stop the input of certain characters.


Solution

  • Your code does not prevent input because you are using an "input" event. The event listener "input" is fired after the input occurs, so its default cannot be prevented.

    Instead, use "keydown" which fires before the action, hence the default action can be prevented.

    Here is your updated code:

    document.addEventListener("keydown", event => {
        if (event.key === '#' || event.key === '+' || event.key === '.' || event.key === ';') {
            event.preventDefault();
            alert("Non-allowed character detected: " + event.key);
            return false;
        }
    });
    

    Also, if you want to stop someone from pasting in such characters using the context menu or drag&drop, you can use all these functions together:

    // Existing code for detecting keystrokes
     document.addEventListener("keydown", event => {
         if (event.key === '#' || event.key === '+' || event.key === '.' || event.key === ';') {
             event.preventDefault();
             alert("Non-allowed character detected: " + event.key);
             return false;
         }
     });
    
    // Code to prevent pasting non-allowed characters
    document.addEventListener("paste", event => {
        var clipboardData = event.clipboardData || window.clipboardData || event.originalEvent.clipboardData;
        var pastedData = clipboardData.getData('text');
        if (pastedData.includes('#') || pastedData.includes('+') || pastedData.includes('.') || pastedData.includes(';')) {
            event.preventDefault();
            alert("Non-allowed character detected in your paste: " + pastedData);
            return false;
        }
    });
    
    // Code to prevent drop non-allowed characters
    document.addEventListener("drop", event => {
        var droppedData = event.dataTransfer.getData('text');
        if (droppedData.includes('#') || droppedData.includes('+') || droppedData.includes('.') || droppedData.includes(';')) {
            event.preventDefault();
            alert("Non-allowed character detected in your drop: " + droppedData);
            return false;
        }
    });
    

    Or if you really want to use input, you can, but first the content will be written, then deleted from the input:

    // Listen to input event
    inputField.addEventListener('input', function(event) {
        var value = event.target.value;
        // Check for disallowed characters
        if (value.includes('#') || value.includes('+') || value.includes('.') 
        || value.includes(';')) {
            alert("Non-allowed character detected.");
            // Remove disallowed characters
            event.target.value = value.replace(/[\#\+\.;]/g, '');
        }
    });
    

    All relevant parts of the above code as executable stack snippet ...

    // Existing code for detecting keystrokes
    document.addEventListener("keydown", event => {
      if (event.key === '#' || event.key === '+' || event.key === '.' || event.key === ';') {
        event.preventDefault();
    
        alert("Non-allowed character detected: " + event.key);
        return false;
      }
    });
    
    // Code to prevent pasting non-allowed characters
    document.addEventListener("paste", event => {
      var clipboardData = event.clipboardData || window.clipboardData || event.originalEvent.clipboardData;
      var pastedData = clipboardData.getData('text');
    
      if (pastedData.includes('#') || pastedData.includes('+') || pastedData.includes('.') || pastedData.includes(';')) {
        event.preventDefault();
    
        alert("Non-allowed character detected in your paste: " + pastedData);
        return false;
      }
    });
    
    // Code to prevent drop non-allowed characters
    document.addEventListener("drop", event => {
      var droppedData = event.dataTransfer.getData('text');
    
      if (droppedData.includes('#') || droppedData.includes('+') || droppedData.includes('.') || droppedData.includes(';')) {
        event.preventDefault();
    
        alert("Non-allowed character detected in your drop: " + droppedData);
        return false;
      }
    });
    
    // Listen to input event
    document.querySelector('input[type="text"]').addEventListener('input', function(event) {
      var value = event.target.value;
    
      // Check for disallowed characters
      if (value.includes('#') || value.includes('+') || value.includes('.') || value.includes(';')) {
        alert("Non-allowed character detected.");
    
        // Remove disallowed characters
        event.target.value = value.replace(/[\#\+\.;]/g, '');
      }
    });
    form { width: 80%; }
    label > span { display: block; margin: 4px 0 8px 0; }
    input { width: 99%; }
    <form>
      <fieldset>
        <legend>+++ Some ... Text ... To ... Copy ... From +++</legend>
    
        <label>
          <span># more text to copy from; #</span>
          <input
            type="text"
            required
            pattern="[^#+.;]+"
            placeholder="following chars are not allowed ... #+.;"
          />
        </label>
      </fieldset>
    </form>