/*
  Taken from: http://www.faqts.com/knowledge_base/entry/edit/index.phtml?aid=1661&fid=145&return_url=%2Fknowledge_base%2Fview.phtml%2Faid%2F1661
  Also useful: http://www.quirksmode.org/js/keys.html

  the third argument to changeKey should be a function

    function exampleKeyChecker (keyCode, key)

  which returns an object

    { cancelKey: boolean, replaceKey: boolean, newKeyCode: number, newKey: string }

  Not all properties need to be present, if cancelKey is set to true the
  other properties are not needed.

  If replaceKey is set to true then at least newKeyCode needs to be set.
*/

function changeKey (textControl, evt, keyChecker) {
  var keyCode = evt.keyCode ? evt.keyCode :
    evt.charCode ? evt.charCode :
    evt.which ? evt.which : void 0;
  var key;
  if (keyCode) {
    key = String.fromCharCode(keyCode);
  }
  var keyCheck = keyChecker(keyCode, key);
  if (keyCode && window.event && !window.opera) {
    if (keyCheck.cancelKey) {
      return false;
    }
    else if (keyCheck.replaceKey) {
      window.event.keyCode = keyCheck.newKeyCode;
      if (window.event.preventDefault) {
        window.event.preventDefault();
      }
      return true;
    }
    else {
      return true;
    }
  }
  else if (typeof textControl.setSelectionRange != 'undefined') {
    if (keyCheck.cancelKey) {
      if (evt.preventDefault) {

        evt.preventDefault();
      }
      return false;
    }
    else if (keyCheck.replaceKey) {
      // cancel the key event and insert the newKey for the current
      // selection
      if (evt.preventDefault) {
        evt.preventDefault();
      }
      var oldSelectionStart = textControl.selectionStart;
      var oldSelectionEnd = textControl.selectionEnd;
      var selectedText = textControl.value.substring(oldSelectionStart,
                                                     oldSelectionEnd);
      var newText = typeof keyCheck.newKey != 'undefined'
        ? keyCheck.newKey
        : String.fromCharCode(keyCheck.newKeyCode);
      textControl.value =
        textControl.value.substring(0, oldSelectionStart) +
        newText +
        textControl.value.substring(oldSelectionEnd);
      textControl.setSelectionRange(oldSelectionStart + newText.length,
                                    oldSelectionStart + newText.length);
      return false;
    }
    else {
      return true;
    }
  }
  else if (keyCheck.cancelKey) {
    if (evt.preventDefault) {
      evt.preventDefault();
    }
    return false;
  }
  else {
    return true;
  }
}

function lettersToUpperCase (keyCode, key) {
  var newKey = key.toUpperCase();
  if (newKey != key) {
    return { replaceKey: true,
             newKeyCode: newKey.charCodeAt(),
             newKey: newKey };
  }
  else {
    return { cancelKey: false };
  }
}

function digitsToX (keyCode, key) {
  if ("0123456789".indexOf(key) != -1) {
    return { replaceKey: true,
             newKeyCode: "X".charCodeAt(),
             newKey: "X" };
  }
  else {
    return { cancelKey: false };
  }
}

function umlautsToASCII (keyCode, key) {
  var asciiUmlauts = {
    "ÃƒÂ¤": "ae",
    "ÃƒÂ¶": "oe",
    "ÃƒÂ¼": "ue",
    "Ãƒï¿½": "Ae",
    "Ãƒï¿½": "Oe",
    "Ãƒï¿½": "Ue"
  };
  if ("ÃƒÂ¤ÃƒÂ¶ÃƒÂ¼Ãƒï¿½Ãƒï¿½Ãƒï¿½".indexOf(key) != -1) {
    return { replaceKey: true,
             newKeyCode: keyCode,
             newKey: asciiUmlauts[key] };
  }
  else {
    return { cancelKey: false };
  }
}

function cancelDigits (keyCode, key) {
  if (isNavKey(keyCode, key)) return { cancelKey: false }
  return { cancelKey: "0123456789".indexOf(key) != -1 };
}

function permitDigits (keyCode, key) {
  if (isNavKey(keyCode, key)) return { cancelKey: false }
  return { cancelKey: "0123456789".indexOf(key) == -1 };
}

function cancelEnter (keyCode, key) {
  if (isNavKey(keyCode, key)) return { cancelKey: false }
  return { cancelKey: keyCode == 13 };
}


//   8: BS
//  13: CR
//  46: .
//  37: % and LEFT
//  39: ' and RIGHT
function isNavKey(keyCode, key) {
  var ignoreKeyCodes = [8, 9, 46, 37, 39];
  for (i=0; i<ignoreKeyCodes.length; i++) {
    if (ignoreKeyCodes[i] == keyCode) { return true; }
  }
}
