// $Id:$

// Shortcut manager is a static class which can be use if a page is required
// to support shortcut keys for certain features on the page
var ShortcutManager = new Function();

// Some constants for commonly used shortcut keys
ShortcutManager.KEY_BACKSPACE = 8;
ShortcutManager.KEY_TAB = 9;

ShortcutManager.KEY_ENTER = 13;
ShortcutManager.KEY_ESC = 27;

ShortcutManager.KEY_F = 70;
ShortcutManager.KEY_N = 78;
ShortcutManager.KEY_P = 80;
ShortcutManager.KEY_Q = 81;
ShortcutManager.KEY_R = 82;
ShortcutManager.KEY_S = 83;
ShortcutManager.KEY_T = 84;
ShortcutManager.KEY_U = 85;

ShortcutManager.KEY_PAGE_UP = 33;
ShortcutManager.KEY_PAGE_DOWN = 34;
ShortcutManager.KEY_END = 35;
ShortcutManager.KEY_HOME = 36;

ShortcutManager.KEY_LEFT_ARROW = 37;
ShortcutManager.KEY_UP_ARROW = 38;
ShortcutManager.KEY_RIGHT_ARROW = 39;
ShortcutManager.KEY_DOWN_ARROW = 40;

ShortcutManager.KEY_PLUS = 107;
ShortcutManager.KEY_MINUS = 109;
ShortcutManager.KEY_IE_PLUS = 187;
ShortcutManager.KEY_IE_MINUS = 189;

ShortcutManager.KEY_INSERT = 45;
ShortcutManager.KEY_DELETE = 46;

ShortcutManager.KEY_F1  = 112;
ShortcutManager.KEY_F2  = 113;
ShortcutManager.KEY_F3  = 114;
ShortcutManager.KEY_F4  = 115;
ShortcutManager.KEY_F5  = 116;
ShortcutManager.KEY_F6  = 117;
ShortcutManager.KEY_F7  = 118;
ShortcutManager.KEY_F8  = 119;
ShortcutManager.KEY_F9  = 120;
ShortcutManager.KEY_F10 = 121;
ShortcutManager.KEY_F11 = 122;
ShortcutManager.KEY_F12 = 123;

// Constants used to register which modifiers are used in combination with the key
ShortcutManager.MODIFIER_NONE = 0;
ShortcutManager.MODIFIER_ALT = 1;
ShortcutManager.MODIFIER_CTRL = 2;
ShortcutManager.MODIFIER_SHIFT = 4;
ShortcutManager.MODIFIER_ALT_CTRL = 3;
ShortcutManager.MODIFIER_ALT_SHIFT = 5;
ShortcutManager.MODIFIER_CTRL_SHIFT = 6;
ShortcutManager.MODIFIER_ALT_CTRL_SHIFT = 7;

// Constant used to register banished shortcuts
ShortcutManager.BANISHED = new Object();

// If this property is set to true then an alert box will be shown with the key code for the
// keyboard key which were pressed down
ShortcutManager.debug = false;

// Returns the numeric value for a key code char
ShortcutManager.convertToKeyCode = function(keyCodeChar)
{
   return keyCodeChar.toUpperCase().charCodeAt(0);
}

// This array is used to store the registrated shortcut keys
ShortcutManager.shortcuts = new Array();

// This array is used to store the shortcut keys which are already in use by one or more browsers
ShortcutManager.banishedShortcuts = new Array();
ShortcutManager.banishedShortcuts[ShortcutManager.MODIFIER_CTRL] = new Array();
// Register an element for which a shortcut key must be active
ShortcutManager.registerElementListener = function(element)
{
   // Register the shortcut manager's on key down method as the key down event handler for the
   // element passed as input
   $(element).bind("keydown", null,  ShortcutManager.onKeyDown);
}

// Register a shortcut, the modifiers must be a combination of the modifiers defined above for
// modifiers, the key code can be numeric or a char, the method is the method which must be
// called when the shortcut is used
ShortcutManager.registerShortcut = function(modifiers, keyCode, method)
{
   // If the key code is not numerical and not a string then an
   // invalid key code was specified
   if(typeof keyCode != "string" && typeof keyCode != "number")
      throw "Key code specified has an invalid type, the key code must be of type 'number' or 'string' (typeof keyCode = " + (typeof keyCode) + ")";

   // If the key code is not numerical then we assume it to be a char and length find out what the
   if(typeof keyCode == "string")
   {
      // If the length of the string is not 1 then throw an exception the key code must be exactly
      // one character long if it is of type string
      if(keyCode.length != 1)
         throw "The registered key code is of type string so the length must be exactly one character";

      // Get the first and only character of the string
      keyCode = ShortcutManager.convertToKeyCode(keyCode)
   }

   // If the shortcut is registered as banished then throw an exception
   if(ShortcutManager.banishedShortcuts[modifiers] != null && ShortcutManager.banishedShortcuts[modifiers][keyCode] === ShortcutManager.BANISHED)
      throw "The registered shortcut key is banished because it is used by one or more browser platforms (keyCode = " + keyCode + ")";

   // If the given modifier combination has not been registered before then we create a new array
   // for this combination
   if(ShortcutManager.shortcuts[modifiers] == null)
      ShortcutManager.shortcuts[modifiers] = new Array();

   // Register the method for the given modifier combination and key code
   ShortcutManager.shortcuts[modifiers][keyCode] = method;
}

// The on key down event handler
ShortcutManager.onKeyDown = function(e)
{
   // Handle browser platform specific issues
   if (e == null)
      e = event;

   // Register which modifiers are pressed
   var modifiers = ShortcutManager.MODIFIER_NONE;
   if (e.altKey)
      modifiers += ShortcutManager.MODIFIER_ALT;
   if (e.ctrlKey)
      modifiers += ShortcutManager.MODIFIER_CTRL;
   if (e.shiftKey)
      modifiers += ShortcutManager.MODIFIER_SHIFT;

   // Used for debugging only, and to find key code values for keys
   if (ShortcutManager.debug)
      alert(e.keyCode);

   // If the shortcut key combination is not defined then return
   if (ShortcutManager.shortcuts[modifiers] == null)
      return;

   // Load the right method based on the shortcut key combination
   var f = ShortcutManager.shortcuts[modifiers][e.keyCode];
   if (f != null)
   {
      // Call the method with the event as argument
      var result = f(e);

      // Cancel the event bubble
      if (result) //if result is true, key down event will be cancelled.
      {
         if (e.stopPropagation)
            e.stopPropagation();
         else
            e.cancelBubble = true;

         if (e.preventDefault)
            e.preventDefault();
         else
            e.returnValue = false;
      }

      return;
   }
}
