awj
awj

Reputation: 7949

How to obtain full value inside jQuery's keypress event?

I'm writing some jQuery which intercepts the value entered in an input field and determines whether to allow or to prevent the typed value.

I need to get the next value, i.e., what the value will be were I to permit the key-press, and I need to know this value at a point before it is displayed, so I'm using the keypress event.

My question is: inside the keypress event, how can I tell what the resultant value would be were I to permit the key-press? What is the 'potential value'?

If I write out the key-press event object to the console and inspect the properties, I can see that currentTarget.value shows this 'potential value'. However, if I use this property inside the keypress event then it returns only the value prior to the context key-press.

For example, if the user types "a" into an empty text box bound to the following jQuery

$(":input").on("keypress", function(e) {
    console.log(e);
    console.log(e.currentTarget.value);
});

Digging down through the first console output (e) shows that currentTarget.value = "a".

But the second console output (e.currentTarget.value) will show "".

If the user was then to type "b" into that same text box then: Manually inspectng e and locating currentTarget.value displays "ab"; Dumping e.currentTarget.value from inside the event displays "a".

Can anyone explain how I can get this 'potential value' while inside the keypress event?

Upvotes: 3

Views: 2096

Answers (1)

Me.Name
Me.Name

Reputation: 12544

Not the prettiest of solutions (you can see the would be result just before it's reverted), but to save the trouble of discerning between arrow/control and input keys etc, you could store the original value in keypress and revert to that in keyup if needed (also storing the selection positions for complete reversion)

$(":input").keypress(function(e) {
    $(this).data('orgValue', {value: this.value, pos: this.selectionStart, selend:this.selectionEnd});
}).keyup(function(e){
    var val = this.value;
    if(!somevalidation(val)){
        var org =$(this).data('orgValue');        
        this.value = org.value;
        this.selectionStart = org.pos;
        this.selectionEnd = org.selend;
    }
});

Example fiddle

Edit

Did some testing, but jquery makes predicting the outcome relatively easy. Not only does it fill the key property, it also fills other properties on its event on which the type of key can be checked. While testing charCode seems to be 0 for 'non input' keys. The straight forward would be:

$(":input").keypress(function(e) {
    if(!e.charCode)return; //is 0 for non input
    var cur = this.value; //current value
    var val = cur.substring(0,this.selectionStart)
        + e.key
        + cur.substring(this.selectionEnd);     
    return cur=== val //unchanged
        || somevalidation(val);        
});

But that would not include deletes/backspaces, to handle those as well:

$(":input").keypress(function(e) {
    var key,start = this.selectionStart ,end = this.selectionEnd;
    if(e.charCode)
        key = e.key;
    else{
        if(e.keyCode===8 || e.keyCode===46){
            key = '';
            if(end===start){
                if(e.keyCode===8)
                    start--;
                else
                    end++;
            }
        }
        else
            return true; //charCode is 0 for non input 46 = delete 8 = backspace
    }
    var cur = this.value; //current value
    var val = cur.substring(0, start) + key + cur.substring(end);     
    return cur=== val //unchanged
        || somevalidation(val);        
});

Fiddle

While testing this seemed to behave as expected. An other way might be have a hidden input field, send the keys there and examine its results, but the above should do the trick.

Upvotes: 3

Related Questions