Phone Input Mask & Validation

Mask and validate a phone input field

HTML

<!--<div>
    <label for="validateAs">Validate as:</label>
    <select id="validateAs">
        <option value="">-- Select One --</option>
        <option value="us">US/CA</option>
    </select>
</div>
<br /><br />-->
<div>
    <label for="txtPhone">Phone Number:</label>
    <input type="text" id="txtPhone" maxlength="12" placeholder="(xxx)-xxx-xxxx" size="12" /> x
    <input type="text" id="ext" placeholder="Ext'n" maxlength="5" size="5" />
    <span id="spnPhoneStatus"></span>
</div>
<div>
    <label></label> 
    <span class="format phone">ex: 555-123-4567</span>
</div>

CSS

body {
    padding: 10px;
    font-family: Arial;
    Font-size: 10pt;
}
label {
    display:inline-block;
    width:100px;
    text-align: right;
}
input {
    border:1px solid #ccc;
    border-radius: 4px;
    padding:5px 8px;
}
#spnPhoneStatus {
    font-weight:bold;
}
.format {
    color:#999;
}
.format.phone{
    display: inline-block;
    width: 130px;
}

JavaScript

$(document).ready(function () {
    $('#txtPhone').keydown(rejectNonNumeric)
    .keyup(function (ev) {
        mask(this, ev);

        if (validatePhone(this, 'us')) {
            $('#spnPhoneStatus').html('Valid');
            $('#spnPhoneStatus').css('color', 'green');
        } else {
            $('#spnPhoneStatus').html('Invalid');
            $('#spnPhoneStatus').css('color', 'red');
        }
    });
    $('#ext').keydown(rejectNonNumeric);
});

var keys = {
    UP: 38,
    DOWN: 40,
    ENTER: 13,
    ESC: 27,
    PLUS: 43,
    A: 65,
    Z: 90,
    ZERO: 48,
    NINE: 57,
    SPACE: 32,
    BSPACE: 8,
    TAB: 9,
    DEL: 46,
    CTRL: 17,
    CMD1: 91, // Chrome
    CMD2: 224 // FF
};

function validatePhone(input, type) {
    var filter, a = input.value;
    var filters = {
        us: /^((\(\d{3}\)\s)|(\d{3}-))(\d{3})-?(\d{4})$/,
        us2: /^(1?(?: |\-|\.)?(?:\(\d{3}\)|\d{3})(?: |\-|\.)?\d{3}(?: |\-|\.)?\d{4})$/
    };
    switch (type) {
        case 'us':
            filter = filters.us;
            break;
        default:
            filter = filters.us;
    }
    if (filter.test(a)) {
        return true;
    } else {
        return false;
    }
}

function rejectNonNumeric(ev){
    return (isFinite(ev.key) || // Is a number key
            ev.keyCode === keys.BSPACE ||
            ev.keyCode === keys.DEL ||
            ev.keyCode === keys.TAB ||
            ev.keyCode === keys.UP ||
            ev.keyCode === keys.DOWN ||
            ev.keyCode === keys.LEFT ||
            ev.keyCode === keys.RIGHT
        );
}

function mask(input, ev) {
    var tel = '',
        val = input.value.replace(/[^\d]*/g,'').split(''),
        len = val.length;
        val = val
    
    for (var i = 0; i < len; i++) {
    		if(i == 0){
        	val[i] = '('+val[i];
        }
        if (i == 1) {
            val[i] = val[i]+')' + '-'
        } else if (i == 5) {
            val[i] = val[i] + '-'
        }
        tel = tel + val[i]
    }
    input.value = tel;
}