Monday, April 04, 2011

Stop form input from capturing/ignoring certain keypresses

Too many web forms have some stupid javascript that tries to limit what keys you can press while you are focused in a certain input element. For example, in my bank billpay system, they have javascript that makes it so you can only type numbers while you are in the "Zip Code" field. When they do that, it disables me from using the CMD+v to paste a zip code in the field, because "CMD+v" is not a number.

Here is a sample of the javascript they use:

function numbersonly(myfield, e)
{
    var key, keychar;
    if (e) key = e.which;
    else return true;
   
    // allow control keys
    if ((key==null) || (key==0) || (key==8) ||
         (key==9) || (key==13) || (key==27) )
        return true;

    // numbers
    else if ((("0123456789").indexOf(keychar) > -1))  return true;
    else return false;
}

Then they have HTML like this:

<input onKeyPress="return numbersonly(this, event)" type="text" />

So, if you are a Windows user, you probably are allowed to CONTROL+v to paste a zip code. But Mac users just see the "Edit" menu flicker for a moment and their paste command (keycode 118) is dropped on the floor. Neither can you "CMD+," (keycode 44) to get Application Preferences, or use the metakey to do any other Firefox action while in that form field. It should validate only when the user is ready to submit, not while typing.

Install Greasemonkey and rip that crap out with this script:

// ==UserScript==
// @name           Get Off My Keypress
// @namespace      http://gomk.amulder.modwest.com/gomk.user.js
// @description    stop websites from setting event handlers to capture your keypresses
// @include        https://sitethatbothersyou.com/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js
// ==/UserScript==

$(document).ready(function() {
    // unsafeWindow.console.log("testing firebug after jq");     
    $("input").each(function(i, elem) {
        // unsafeWindow.console.log(i + $(elem).attr("name"));
        var h = elem.getAttribute("onKeyPress");
        // might return "return numbersonly(this, event)"
        if(h) elem.setAttribute("onKeyPress", "return true");
    });     
}); 

Having to use Greasemonkey is really more complicated than it should be. We should be able to use the new CAPS (capabilities) security policy settings built into Firefox 4 to grant noAccess to specific websites to set onkeypress events or read what keys you are pushing on. I tried several iterations using the "Control de Scripts" extension to block these:

HTMLInputElement.onKeyPress
Window.numbersonly
Window.onKeyPress
Window.onkeypress
event.preventDefault 

but none worked. I think this is because I don't really grasp what an event handler is or where it is in the DOM. Maybe someone else can comment to get a solution that is native to the browser, without needing a whole extension just to do this one simple thing.