2

I have a keypress event listener on an input field to confirm a password. I want the button on the page to be disabled until the password and confirm-password fields have matching values. I am using the .keypress() jQuery function, but it seems to always be one character behind what I expect it to be?

Here is the code

$('#confirm').keypress(function() {
    console.log('#confirm').val();
    if($('#password').val() == $('#confirm').val()) {
        $('button').removeProp('disabled');
        console.log("yes");                
    } else {
        console.log("no");
    }
});

But when I inspect element and look at the console window on my page, the first time the event is fired it prints the form value as blank. Then when I enter a second character, it prints only the first, and when I type a third character it prints the first two, etc.

For example, if I put asd into the password field and begin typing the same into the confirm field the output will look like this:

<blank> no a no as no

So at this point both password and confirm fields have "asd", but I need to enter an extra character before that is recognized and the "disabled" property is removed from the button.

I have tried using .change() instead of .keypress() but that doesn't fire until the input field loses focus, which is not what I want.

James
  • 903
  • 7
  • 22
  • 1
    http://stackoverflow.com/questions/38502560/diffrence-between-keyup-keydown-keypress-and-input-events – bassxzero Feb 01 '17 at 21:20
  • 3
    You can try using the `keyup` event instead, it should trigger after the user releases the key - https://api.jquery.com/keyup/ – Tricky12 Feb 01 '17 at 21:21
  • Make sure you include some other indication that they don't match, other than a disabled button - that would _really_ frustrate me as a user – James Thorpe Feb 01 '17 at 21:24
  • 1
    use the `input` event; that's what it's for, and it works with mouse pasting, IME, etc – dandavis Feb 01 '17 at 21:25
  • @JamesThorpe There are other visual cues, I agree with the frustration haha – James Feb 01 '17 at 21:39

3 Answers3

1

I want the button on the page to be disabled until the password and confirm-password fields have matching values

If this is your goal, you can add event listeners to both inputs that call a validation function:

$('#password').on("input", function() { validatePassword(); });

$('#confirm').on("input", function() { validatePassword(); });

function validatePassword() {
    if($('#password').val() && $('#confirm').val() && $('#password').val() == $('#confirm').val()) {
        $('button').prop('disabled', false);
    } else {
        $('button').prop('disabled', true);
    }
}

It also may be worthwhile adding an ID to the button. Using 'button' would enable/disable all elements on the page.

Example: https://jsfiddle.net/doL4t9vv/1/

  • There is only one button on the page, so disabling all buttons is not a concern. – James Feb 01 '17 at 21:31
  • Gotchya. Then what I have answered should work fine then. Let me know if you have any problems with it. – John-Paul Ensign Feb 01 '17 at 21:32
  • first 2 lines could easily be combined to `$('#confirm, #password').on('input', validatePassword)` – charlietfl Feb 01 '17 at 21:49
  • I agree that they could be combined like this. However, what if you'd like to add additional logic to one input specifically, or call more than one function? For example, if you are validating a username, you can call one function to check availability (asynchronous) and another function to check for valid characters. – John-Paul Ensign Feb 01 '17 at 21:54
1

I had the same problem few months ago.
Try to use the keyup function from Jquery.

Keypress event is fired when you press the key, so the input is not fill yet.
Keyup event is fired when you release the key.

Simon Bruneaud
  • 2,263
  • 2
  • 12
  • 24
0

Can use input event and simplify this down to

var $passwords =$('#confirm, #password').on('input', function() {
    var thisValue = this.value.trim();
    // does this input have value and does it match other
    var isValid = thisValue  && thisValue  === $passwords.not(this).val().trim();
    // boolean used for disabled property    
    $('button').prop('disabled', !isValid);      
});
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • I think I prefer the extra lines of code for the added legibility ;) haha – James Feb 01 '17 at 21:43
  • Why trim the value? What if someone has a space in the first field but not in the second? E.g. password="test123" and confirm="test123 ". They are not equal and should not be treated that way. :) – John-Paul Ensign Feb 01 '17 at 21:57
  • fixed...trimmed them both – charlietfl Feb 01 '17 at 21:59
  • I was saying that you should not trim at all. – John-Paul Ensign Feb 01 '17 at 21:59
  • "password123" and "password123 " would enable the button, when it shouldn't. Especially if they want the password to have a space at the end. – John-Paul Ensign Feb 01 '17 at 22:00
  • @John-PaulEnsign why not? If user has equal number empty spaces and no other characters in both would pass – charlietfl Feb 01 '17 at 22:01
  • Test it out. https://jsfiddle.net/0khvo210/ I left it as 'text' instead of 'password' for visibility. Try the password 'test123' and for confirm simply put 'test123'. The button will be enabled. Spaces are allowed in passwords and shouldn't be trimmed. – John-Paul Ensign Feb 01 '17 at 22:08
  • have never seen any password that is viable with space on either end...that would be horrible to maintain – charlietfl Feb 01 '17 at 22:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/134628/discussion-between-john-paul-ensign-and-charlietfl). – John-Paul Ensign Feb 01 '17 at 22:11