Search code examples
javascriptjquerywhitespacekeydownonkeyup

How do I prevent a leading space from being entered in a textbox?


I'm using jQuery 2. How do I prevent a space being entered in a textbox if it is a leading space (e.g. at the beginning of the string)? I thought this would do it

   $(document).on("keyup","#s" ,function(evt){
     var firstChar = $("#s").val()
     if(evt.keyCode == 32 && firstChar){
       $("#s").val( $("#s").val().trim() )
       console.log(" called ")
       return false;
     }
  })

And basically it does but it is a little sloppy. You can see the space being entered and then removed and I was looking for something slightly smoother -- whereby the space doesn't even make it in the textbook in the first place.


Solution

  • You have to understand the difference between keyup, keypress and keydown events :

    • keydown : It is the first event fired when the key is first down
    • keypress: this is when the input happens
    • keyup : When you "release" the key

    So, you have "keydown -> keypress -> fill the input -> release the key"

    In your scenario, you want to make things happend BEFORE the actual input gets filled, so you have to use the keydown event instead of the keyup

    From there, returning false will result in stopping the propagation of the event, so "keydown -> // Things will break here // -> keypress -> fill the input -> release the key"

    The last thing is your condition. In your code, you are not checking if firstChar is actually empty, you are just having something everytime because you get the value. Just changing a bit your condition made the code work.

    Here is a working demo :

    $(document).on("keydown","#hello" ,function(evt){
         var firstChar = $("#hello").val()
         if(evt.keyCode == 32 && firstChar == ""){
         	return false;
         }
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <input type="text" id="hello">

    For the last space, you cannot predict if a second word will be added I guess, so just do the normal trim thing, or if you are sure that only one word will be typed, simply adapt the condition.

    EDIT :

    After OP's comment saying that you can input a space by typing a space then coming back in front of the first letter, Below is a fix that does the trick.

    Basically, I base my code now not on the "first character", but on the cursor's position.

    If the cursor is at position 0, we don't let the user enter a space, otherwise, it is ok.

    The new JS code looks like this :

    $(document).on("keydown","#hello" ,function(evt){
         var caretPos = $(this)[0].selectionStart
         if(evt.keyCode == 32 && caretPos == 0){
            return false;
         }
    });
    

    EDIT 2:

    Rick Hitchcock comment :

    $() returns a jQuery collection. You can access an individual element of the collection by referring to its index ([0], [1], [2], ...). You already have the individual element (this), and there's no need to put it in a jQuery collection just so you can immediately take it back out.

    By taking this into account, $(this)[0].selectionStart can be replaced by this.selectionStart