HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Input/character validation on an input-element

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
inputelementcharactervalidation

Problem

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 && !e.metaKey) c = c.toLowerCase();
if ((e.ctrlKey && (e.keyCode == 65 || e.keyCode == 97)) || c == '⌘-A') return true;
if (c.match(regex) || allowed.indexOf(e.which) >= 0) {
//Do nothing
} else {
e.preventDefault();
}
});
}

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

``

Solution

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) >= 0) {
    //Do nothing
} else {
    e.preventDefault();
}


instead, use a NOT (!):

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


the best way to write this specific condition would be:

if(!c.match(regex) || allowed.indexOf(e.which) < 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]/

Code Snippets

function Validate(element, regex) {
    // code
}
Object.defineProperty(Element.prototype, 'validate', {
    value: function(regex) {
        // code
    }
});
if (c.match(regex) || allowed.indexOf(e.which) >= 0) {
    //Do nothing
} else {
    e.preventDefault();
}
if (!(c.match(regex) || allowed.indexOf(e.which) >= 0))
    e.preventDefault();
if(!c.match(regex) || allowed.indexOf(e.which) < 0)

Context

StackExchange Code Review Q#122696, answer score: 5

Revisions (0)

No revisions yet.