Jquery: filter input on keypress
Asked Answered
M

5

6

I have a text field, which will accept only the following characters:

Allowed characters: [a-z 0-9 + # - .]

This is the same filter SO does in the 'Tags' field, when you're asking a question. If the user types an invalid character, i want the current text field value to remain unchanged. I tried:

$('#post_tags').keypress(function(event){
    var char = String.fromCharCode(event.which)
    var txt = $(this).val()

    if (! txt.match(/[^A-Za-z0-9+#-\.]/)){
        $(this).val(txt.replace(char, ''));
    }
})

Why it doesn't work? Thanks!

Modal answered 20/6, 2013 at 18:5 Comment(2)
How does it not work? What does it do instead of the behaviour you want?Ailey
What about DEL BACKSPACE and the arrow keys?!Metic
S
5
/[^A-Za-z0-9+#-\.]/

This negates the match of any one of those characters. To make it match more than one character, you have to use a + in there:

/[^A-Za-z0-9+#-\.]+/
                  ^

And now to match the whole string, you need to add anchors:

/^[^A-Za-z0-9+#-\.]+$/
 ^                  ^

EDIT: Okay, it seems that the - here is also creating a range from character # to .. In this case, you can either escape it, or put it at the end:

/^[^A-Za-z0-9+#\-\.]+$/

/^[^A-Za-z0-9+#\.-]+$/
Spore answered 20/6, 2013 at 18:7 Comment(4)
if you return false in the handler it will prevent the value to be updatedItu
@Modal Use anchors if that's the case, ^ meaning the beginning of a string and $ meaning the end of a string. This ensures that the whole strings matches (or not) the pattern.Spore
@Modal I didn't notice the - character being naughty here ;) See the edit to my answer.Spore
@Modal Also, why don't you use if (txt.match(/^[A-Za-z0-9+#\.-]+$/)) instead of using double negations?Spore
P
14

This worked for me:

$(function(){
    $('#t').keypress(function(e){
        var txt = String.fromCharCode(e.which);
        console.log(txt + ' : ' + e.which);
        if(!txt.match(/[A-Za-z0-9+#.]/)) 
        {
            return false;
        }
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input id="t" />
Pseudoscope answered 20/6, 2013 at 18:28 Comment(1)
It is possible to insert text into input from clipboard. Also DEL and BACKSPACE do not work.V
S
5
/[^A-Za-z0-9+#-\.]/

This negates the match of any one of those characters. To make it match more than one character, you have to use a + in there:

/[^A-Za-z0-9+#-\.]+/
                  ^

And now to match the whole string, you need to add anchors:

/^[^A-Za-z0-9+#-\.]+$/
 ^                  ^

EDIT: Okay, it seems that the - here is also creating a range from character # to .. In this case, you can either escape it, or put it at the end:

/^[^A-Za-z0-9+#\-\.]+$/

/^[^A-Za-z0-9+#\.-]+$/
Spore answered 20/6, 2013 at 18:7 Comment(4)
if you return false in the handler it will prevent the value to be updatedItu
@Modal Use anchors if that's the case, ^ meaning the beginning of a string and $ meaning the end of a string. This ensures that the whole strings matches (or not) the pattern.Spore
@Modal I didn't notice the - character being naughty here ;) See the edit to my answer.Spore
@Modal Also, why don't you use if (txt.match(/^[A-Za-z0-9+#\.-]+$/)) instead of using double negations?Spore
L
2

You don't need to replace the char, only prevent it.

var char = String.fromCharCode(event.which)
if (!char.match(/^[^A-Za-z0-9+#\.\-]+$/)) event.preventDefault();
Leatriceleave answered 20/3, 2015 at 17:44 Comment(1)
This works instead: if (!char.match(/[A-Za-z0-9+#\.\-]/)) event.preventDefault();Zusman
G
1

Alternate Solution

One thing that might help would be to use the .which field instead. Then simply return false when it doesn't fit. I actually have a huge object full of .which info for all major browsers. It includes arrays you could borrow from it to create something like:

var alphaNumericNcontrols = [ 8,9,13,16,17,18,19,20,32,33,34,35,36,37,38,39,40,44,45,46,145,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,96,97,98,99,100,101,102,103,104,105 ],
    illegal = {
        reg: [ 106,111,191,220 ],
        shift: [ 56,59,188,190,191,220,222 ]
    }

$(document).on("keydown", "input[type=text]", function(e) {
    var eKey = e.which || e.keyCode;
    if (alphaNumericNcontrols.indexOf(eKey) === -1) return false;
    if (illegal.reg.indexOf(eKey) > -1) return false;
    if (e.shiftKey && illegal.shift.indexOf(eKey) > -1) return false;
});

See Working Example Here

Keep in mind my Object is not perfect and there are some updates I probably need to make to it, but i did my best to establish everything from every possible major browser!

Grafting answered 20/6, 2013 at 18:27 Comment(1)
I really like this solution and it's perfect for what I need. Do you know how I can prevent someone from adding emoji? Right now it still lets me do that.Rothwell
M
0

Thanks everyone.

Actually my problem was a little more difficult: filter invalid keys and start a ajax call for valid ones, in 2 different ways: if the user press SPACE/COMMA or while he/her still typing. Here's the code:

$(document).ready(function(){

$('#post_tags').keypress(function(e){
    var txt = String.fromCharCode(e.which);
    console.log(txt + ' : ' + e.which);

    if(txt.match(/^[^A-Za-z0-9+#\-\.]+$/))
    {
          return false;
    }
})

$('#post_tags').keyup(function(event){
      code = event.which
      var token = String.fromCharCode(code)
      var txt = $(this).val()

              //create a new tag, take it out of textfield
      if (code == 32 || code == 188)
      {
        console.log("AJAX new word keyup")

          $.ajax({
            type: 'get',
            url: '/posts/tags_change',
            dataType: "json",
            data: "query=" + $(this).val(),

            success: function(data) {
            console.log(data)
            $('#post_tags').val('')
            },

            error: function(data) {
                alert("Ajax error")
            }
          });
    }
    else
    {
                    //do autocomplete ajax
        console.log("typing:" + txt)
    }

});

})

Dont' know if this is 100% right!

Modal answered 20/6, 2013 at 19:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.