(function() {
 function isCommandKey(code) {
  if (code > 63232) {
   // safari keypress
   switch (code) {
    case 63232: //
    case 63233: //
    case 63234: //
    case 63235: //
     // FIXME:
    code -= 63232 + 38; break;
    case 63236: // F1
    case 63237: // F2
    case 63238: // F3
    case 63239: // F4
    case 63240: // F5
    case 63241: // F6
    case 63242: // F7
    case 63243: // F8
    case 63244: // F9
    case 63245: // F10
    case 63246: // F11
    case 63247: // F12
     code = code - 63236 + 112; break;
    case 63272: // delete
     code = 46; break;
    case 63273: // home 
     code = 36;
    case 63275: // end
     code = 35; break;
    case 63276: // page up
     code = 33; break;
    case 63277: // page down
     code = 34; break;
    case 63289: // numlock
     code = 144; break;
   }
  }
  // FIXME: help key on mac
  switch (code) {
   case 8:   // backspace
   case 9:   // tab
   case 13:  // enter
   case 16:  // shift
   case 17:  // ctrl/cmd
   case 18:  // alt
   case 19:  // break
   case 20:  // caps lock
   case 27:  // escape
   case 33:  // page up
   case 34:  // page down
   case 35:  // end
   case 36:  // home
   case 37:  // left
   case 38:  // up
   case 39:  // right
   case 40:  // down
   case 44:  // print screen
   case 45:  // insert
   case 46:  // delete
   case 91:  // windows start key
   case 106: // numpad *
   case 107: // numpad +
   case 109: // numpad -
   case 111: // numpad /
   case 112: // F1
   case 113: // F2
   case 114: // F3
   case 115: // F4
   case 116: // F5
   case 117: // F6
   case 118: // F7
   case 119: // F8
   case 120: // F9
   case 121: // F10
   case 122: // F11
   case 123: // F12
   case 144: // numlock
   case 145: // scrolllock
    return true;
  }
  return false;
 }
 jQuery.fn.formTextLimiter = function(callback) {
  this.each(function() {
   var maxLengthValue = this.getAttribute("maxlength");
   if (!maxLengthValue) return;
   var maxLength = parseInt(maxLengthValue);
   var eThis = this;
   var jThis = jQuery(this);
   //if (jThis.next("span.textcounter").length != 0) return;
   if (callback) callback(maxLength, maxLength - this.value.length, eThis);
   jThis.keypress(function(e) {
    if (isCommandKey(e.keyCode)) return true;
    var curLength = maxLength - eThis.value.length;
    if (curLength <= 0) {
     return false;
    } else {
     if (callback) callback(maxLength, curLength, eThis);
     return true;
    }
   }).keyup(function(e) {
    var curLength = maxLength - eThis.value.length;
    if (callback) callback(maxLength, curLength, eThis);
    return true;
   }).keydown(function(e) {
    var keyCode = e.keyCode
    if (isCommandKey(e.keyCode)) return true;
    return maxLength > eThis.value.length;
   });
  });
 };
})();

