Input/character validation on an input-element I took some time to create a function, which can validate which keys you input on an element. So far it has two uses:


You call .validate() on the object, but make sure it has a data-match attribute with the regex in it
You call .validate("REGEX") on the object, but replace REGEX with your actual regular expression


Here is an example:

document.getElementById("input").validate("[0-9A-Fa-f]");


This will only allow characters 0-9, A-F, and a-f. Nothing else.

I want to know, if I can improve this code. So far I have it the way I want it to be, but I would surely love someone else's feedback on it as well. It is really light-weight and can easily be implemented.

Thanks a lot!



Object.prototype.validate = function(myRegex) {
    var regex = this.getAttribute("data-match") || myRegex;
    var allowed = [8, 37, 38, 39, 40, 46];
    this.addEventListener("keydown", function(e) {
        var c = (e.metaKey ? '⌘-' : '') + String.fromCharCode(e.keyCode);
        if (!e.shiftKey &amp;&amp; !e.metaKey) c = c.toLowerCase();
        if ((e.ctrlKey &amp;&amp; (e.keyCode == 65 || e.keyCode == 97)) || c == '⌘-A') return true;
        if (c.match(regex) || allowed.indexOf(e.which) &gt;= 0) {
            //Do nothing
        } else {
            e.preventDefault();
        }
    });
}

document.getElementById("input").validate("[0-9A-Fa-f]");
&lt;input type="text" id="input" /&gt;
Whatever you do DON'T MODIFY Object.prototype

Modifying Object.prototype is one of the worst things you can do in JavaScript

Quoting MDN:


  Warning: Changing the [[Prototype]] of an object is, by the nature of how modern JavaScript engines optimize property accesses, a very slow operation, in every    browser and JavaScript engine. The effects on performance of altering inheritance are subtle and far-flung, and are not limited to simply the time spent in obj.__proto__ = ... statement, but may extend to any code that has access to any object whose [[Prototype]] has been altered. If you care about performance you should avoid setting the [[Prototype]] of an object. Instead, create a new object with the desired [[Prototype]] using Object.create().




What should I do?

Preferably create a function:

function Validate(element, regex) {
    // code
}


but if you want to extend an element use Element.prototype, preferable with Object.defineProperty:

Object.defineProperty(Element.prototype, 'validate', {
    value: function(regex) {
        // code
    }
});


The bonus of using this is you can instead of getters and setters which are pretty cool too.

Avoid empty ifs

Here you have:

if (c.match(regex) || allowed.indexOf(e.which) &gt;= 0) {
    //Do nothing
} else {
    e.preventDefault();
}


instead, use a NOT (!):

if (!(c.match(regex) || allowed.indexOf(e.which) &gt;= 0))
    e.preventDefault();


the best way to write this specific condition would be:

if(!c.match(regex) || allowed.indexOf(e.which) &lt; 0)


Use clear variable names

As much as I love code-golf (writing short code), this is not it. Make sure your variable names are clear.

I don't know what the c variable does so I can't suggest an alternative name, this also makes it more confusing to me on the workings of your code.

Use Regex literals not strings

Your example shows:

"[0-9A-Fa-f]"


That's a string, not a Regex, use Regex literals (to avoid escaping also):

/[0-9A-Fa-f]/