  var emailReg = new RegExp(/^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/);
  var numReg = new RegExp(/^[0-9]/);
  var cvvReg = new RegExp(/^[0-9]{3,4}$/);
  var nameReg = new RegExp(/^[\w]+[\s]+[\w]*.?[\s]*[\w]+$/);
  
  var fl = [];
  fl.clean = true;
  fl.locked = false;
  formulate = function(formSel) {
    $(formSel)
    .find('[class*=vd]').each(function() {
      var vdtypes = getTypes($(this));
      if (vdtypes) {
        len = vdtypes.length;
        for (i=0;i<len;i++) {
          var vdtype = vdtypes[i];
          $(this).change(function() { vFormat(this,vdtype); }).keyup(function(e) { getFormat(this,vdtype,e); }).addClass('x_fc');
          switch (vdtype) {
            case "ph":
              $(this).attr('maxlength', '14').attr('size','14');
              break;
          }
        }
        addMsg(this);
      }
    })
    .end()
    .submit(function() {
      $('.vd_error').hide();
      fl.clean = true;
      fl.focus = null;
      $(this).find('.x_fc').each(function() {
        var vdtypes = getTypes($(this));
        var len = vdtypes.length;
        for (i=0;i<len;i++) {
          var vdtype = vdtypes[i];
          this.value = this.value.trim();
          switch (vdtype) {
            case 'req':
              if (this.value == "") {
                showMsg($(this).attr('name'));
                i=999;
              }
              break;
            case 'em':
              if (!emailReg.test(this.value)) {
                showMsg($(this).attr('name'),' * invalid email.');
              }
              break;
            case 'num':
              if (!numReg.test(this.value)) {
                showMsg($(this).attr('name'),' * invalid format.');
              }
              break;
            case 'cvv':
              if (!cvvReg.test(this.value)) {
                showMsg($(this).attr('name'),' * invalid format.');
              }
              break;
            case 'name':
              if (!nameReg.test(this.value)) {
                showMsg($(this).attr('name'),' * "First Last".');
              }
              break;
          }
        }
      });
      if (!fl.clean) {
        $('[name="'+fl.focus+'"]').focus().select();
        return false;
      }
    });
  };

  function getTypes(obj) {
    var vdtypes = null;
    var list = $(obj).attr('class').split(" ");
    var len = list.length;
    for (i=0;i<len;i++) {
      if (list[i].indexOf("vd-") >= 0) {
        cl = list[i].substring(3,list[i].length);
        vdtypes = cl.split("-");

        return vdtypes;
      }
    }
    return null;
  };

  function addMsg(obj,msg) {
    if (!msg) { msg = " * required."; }
    $(obj).after("<span class='vd_error' for='"+obj.name+"' id='"+obj.name+"'>"+msg+"</span>");
  };

  function showMsg(id,msg) {
    fl.clean = false;
    if (!msg) { msg = " * required."; }
    $('span[id="'+id+'"]').html(msg).show().shake();
    if (fl.focus == null) {
      fl.focus = id;
    }
  };

  function vFormat(obj,type) {
    var val;
    switch (type) {
      case "ph":
        if (obj.value!="") {
          val = obj.value.stripPunctuation();
          var a=val.substring(0,3);
          var b=val.substring(3,6);
          var c=val.substring(6,10);
          if(a.length>0) val="("+a;
          if (b!=""||a.length==3){
            val=val+") "+b;
          }
          if (c!=""||b.length==3){
            val=val+"-"+c;
          }
          obj.value = val;
        }
        break;
    }
  };

  function getFormat(obj,type,e) {
    switch (type) {
      case "ph":
        if (checkNumber(e)) {
          vFormat(obj,type);
        } else {
          obj.value = obj.value.stripLetters();
        }
    }
  };
  
  String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g,"");
  }

  String.prototype.stripPunctuation = function() {
    return this.replace( /[~`\.,;!@#\$%\^\*&\+=<>"\/:\?'\|\(\)\[\]_\-\\\s]/g, '');
  };

  String.prototype.stripLetters = function() {
    return this.replace( /[A-Za-z]/g, '');
  };

  function checkNumber(e){
    // detect last key pressed. if not a number, then dont do anything.
    var key = e.keyCode;
    return ((key>47 && key<58)||(key>95&&key<106))
  };

  $.fn.shake = function (repeat) {
    return this.each(function() {
      $(this).animate( { marginLeft:"10px" }, 50 )
      .animate( { marginLeft:"0px" } , 50 )
      .animate( { marginLeft:"5px"}, 80 )
      .animate( { marginLeft:"0px" } , 120 );
    })
  };

