validator

this validates input text values using a regex string in an attribute from the element it also only allowes certain characters based on regex to be inserted into the textbox

HTML

<form action="//jsfiddle.net/echo/jsonp" method="get">
    <table>
        <tr>
            <td>
                <label for="numbers">Numbers:</label>
            </td>
            <td>
                <input type="text" name='numbers' class='numbers' id='numbers' data-validator-class='numbers' data-validator-allowed='([0-9]*)[\.]?([0-9]+)' data-validator-properties='gm' />
            </td>
        </tr>
        <tr>
            <td>
                <label for="letters">Letters(including spaces):</label>
            </td>
            <td>
                <input type="text" name='letters' class='letters' id='letters' data-validator='^([a-zA-Z ]+)$'  data-validator-properties='gm' />
            </td>
        </tr>
        <tr>
            <input type="submit" value='submit' />
        </tr>
        <tr>
            <td>
                <label for="1char">1 character:</label>
            </td>
            <td>
                <input type="text" name='1char' class='1char' id='1char' data-validator='^.{1}$'  data-validator-properties='m' />
            </td>
            <td> <span class='errorreport 1char'>there aren't the correct number of characters here.</span>

            </td>
        </tr>
    </table>
</form>

CSS

.invalid {
    visibility:visible !important;
    outline:RGBA(255, 0, 0, .4) 4px groove;
}
numbers {
    line-height:1em;
}
.errorreport {
    visibility:hidden;
    outline:initial !important;
}

JavaScript

var validator = function (e) {
    
    var classed = document.getElementsByClassName(e.dataset.hasOwnProperty('validatorClass') ? e.dataset.validatorClass : e.classList[0]);
    return function () {



        if (new RegExp(e.dataset.validator, e.dataset['validatorProperties'] ? e.dataset.validatorProperties : "gm").test(e.value)) {
            [].forEach.call(classed, function (c) {
                c.classList.remove('invalid');
            });
            return false;
        } else {

            [].forEach.call(classed, function (c) {
                c.classList.add('invalid');
            });
            return true;
        }
    }.call(e);
};
var submit = function (e) {
    console.log(e);
    var firsterror = document.querySelectorAll('.invalid');
    if (firsterror.length) {
        alert('there were errors');
        firsterror[0].scrollIntoViewIfNeeded();
        firsterror[0].focus();
        e.preventDefault();
        e.stopPropagation()
        return false;
    }
    return true;
};
[].forEach.call(document.querySelectorAll('input[type=submit]'), function (e) {
    e.addEventListener('click', submit);
});

var checkValidators = function () {
    [].filter.call(document.querySelectorAll('[data-validator]'),function(e){ 
        e.addEventListener('keyup', function(){validator(e)});
        validator(e);});
    [].filter.call(document.querySelectorAll('[data-validator-allowed]'),function(e){
    e.addEventListener('input',allowed);
    });

};
var allowed =  function (e) {

    if (e.target.dataset.validatorAllowed) {
        var ss = e.target.selectionStart;
        var len = e.target.value.length;
        var m = new RegExp(e.target.dataset.validatorAllowed, e.target.dataset['validatorProperties'] ? e.target.dataset.validatorProperties : "gm");
        var mat = e.target.value.match(m);
        if (mat) e.target.value = mat.join('');
        else e.target.value = '';
        ss = ss - (len - e.target.value.length);
       ...