//
//                Copyright (c) 2004 Smartlink Corp.
//                       All rights reserved.
//

var VIRK_LAYOUT = /*VIRK_LAYOUT*/'us'/*VIRK_LAYOUT*/;
var VIRK_NOKBD = /*VIRK_NOKBD*/false/*VIRK_NOKBD*/;
navigator.ns70 = navigator.userAgent.indexOf ("Netscape6") > 0
              || navigator.userAgent.indexOf ("Netscape/7.0") > 0;
navigator.gecko  = navigator.userAgent.indexOf ("Gecko") >= 0;
navigator.safari = navigator.userAgent.indexOf ("Safari") >= 0;
var noKbd = VIRK_NOKBD || navigator.ns70;
var virkCtrl = null;

//////////////////////////////////////////////////////////////////////////////
//
// VirkCtrl
//

ctrlAttachEvent (window, "load",   createVirkCtrl);
ctrlAttachEvent (window, "unload", function () { virkCtrl.detach () });

function createVirkCtrl () {
   virkCtrl = new VirkCtrl ();
   if (window.opener || window.dialogArguments)
      virkCtrl.attach ();
}

function VirkCtrl () {
   this.mainWnd    = getOpener ();
   this.onKeyPress = virkOnKeyPress;
   this.attach     = virkAttach;
   this.detach     = virkDetach;
   this.setLayout  = function (layout) { this.kbd.setLayout (layout) };
   this.getLayout  = function () { return this.kbd.getLayout (); };
   
   this.hookCtrl   = virkHookCtrl;
   this.unhookCtrl = virkUnhookCtrl;
   this.updateSel  = virkUpdateSel;
   
   this.textRange  = null;
   this.activeCtrl = null;
   if (this.mainWnd.theVirk && this.mainWnd.theVirk.activeCtrl)
      this.updateSel (this.mainWnd.theVirk.activeCtrl);
   
   var layout = VIRK_LAYOUT;
   if (!layout)
      layout = getQueryParam (document.location.href, "layout");
   this.kbd = new Keyboard (this, layout, VIRK_NOKBD);
}

function getOpener () {
   if (window.dialogArguments && window.dialogArguments.opener) // dialog?
      return window.dialogArguments.opener;
   if (window.opener) // window?
      return window.opener;
   if (window.parent != window.self) // frame?
      return window.parent;
   if (window.frameElement)
      return window.frameElement.parentElement.document.parentWindow;
   return window;
}

function virkEnumObjects (wnd, listener) {
   try {
      var frames = wnd.document.getElementsByTagName ("IFRAME");
      for (var i = 0; i < frames.length; ++i)
         listener.onFrame (frames [i]);

      var doc = wnd.document, forms = doc.forms;
      for (var i = 0; i != forms.length; ++i) {
         var form = forms [i];
         for (var j = 0; j != form.elements.length; ++j) {
            var ctrl = form.elements [j];
            isEditable (ctrl) && listener.onCtrl (ctrl, doc);
         }
      }
      
      if (window.showModalDialog) { // IE?
         var ctrls = wnd.document.getElementsByTagName ("DIV");
         for (var j = 0; j != ctrls.length; ++j) {
            var ctrl = ctrls [j];
            isEditable (ctrl) && listener.onCtrl (ctrl, doc);
         }
      }
      
      for (var i = 0; i != wnd.frames.length; ++i)
         virkEnumObjects (wnd.frames [i], listener);
   }
   catch (e) { // exception if wnd is from another domain
   }
}

function VirkAttacher () {
}

VirkAttacher.prototype.onCtrl = function (ctrl, doc) {
   virkCtrl.hookCtrl (ctrl, doc);
   if (virkCtrl.activeCtrl == null)
      virkCtrl.updateSel (ctrl)
}

VirkAttacher.prototype.onFrame = function (frame) {
   if (frame.style.visibility == "hidden" || frame.style.display == "none")
      return;
   ctrlAttachEvent (frame, "load", virkReAttach);
}

function VirkDetacher () {
}

VirkDetacher.prototype.onCtrl = function (ctrl, doc) {
   virkCtrl.unhookCtrl (ctrl);
}

VirkDetacher.prototype.onFrame = function (frame) {
   ctrlDetachEvent (frame, "load", virkReAttach);
}

function virkAttach () {
   virkEnumObjects (this.mainWnd, new VirkAttacher ());
}

function virkDetach () {
   if (!this.mainWnd || this.mainWnd.closed)
      return;
   virkEnumObjects (this.mainWnd, new VirkDetacher ());
}

function virkReAttach (e) {
   virkEnumObjects (virkCtrl.mainWnd, new VirkAttacher ());
}

function ctrlAttachEvent (ctrl, type, listener) {
   if (ctrl.addEventListener) {
      ctrl.addEventListener (type, listener, false);
   }
   else if (ctrl.attachEvent) {
      ctrl.detachEvent ("on" + type, listener);
      ctrl.attachEvent ("on" + type, listener);
   }
}

function ctrlDetachEvent (ctrl, type, listener) {
   if (ctrl.removeEventListener)
      ctrl.removeEventListener (type, listener, false);
   else if (ctrl.detachEvent)
      ctrl.detachEvent ("on" + type, listener);
}

var HOOK_EVENTS = [
   { type: "focus",    listener: vkOnFocus     },
   { type: "click",    listener: vkOnFocus     },
   { type: "mouseup",  listener: vkOnFocus     },
   { type: "keydown",  listener: vkOnKeyDown,  skip: noKbd },
   { type: "keyup",    listener: vkOnKeyUp,    skip: noKbd },
   { type: "keypress", listener: vkOnKeyPress, skip: noKbd }
];

function virkHookCtrl (ctrl, doc) {
   for (var i = 0; i < HOOK_EVENTS.length; ++i) {
      var e = HOOK_EVENTS [i];
      if (!e.skip)
         ctrlAttachEvent (ctrl, e.type, e.listener);
   }
   if (!ctrl.ownerDocument)
      ctrl.ownerDocument = doc;
   
   return ctrl;
}

function virkUnhookCtrl (ctrl) {
   for (var i = 0; i < HOOK_EVENTS.length; ++i) {
      var e = HOOK_EVENTS [i];
      ctrlDetachEvent (ctrl, e.type, e.listener);
   }
}

function getEventTarget (e) {
   if (!e)
      e = window.event;
   return e.srcElement || e.target;
}

function virkOnKeyPress (str) {
   this.updateSel (this.activeCtrl);
   if (!this.textRange) // null if activeCtrl is disabled
      return;
   if (str == "<enter>")
      str = "\n";
   switch (str) {
      case "<bs>":  this.textRange.deleteText (-1); break;
      case "<del>": this.textRange.deleteText (0); break;
      default:      this.textRange.insertText (str); break;
   }
   if (str.charCodeAt (0) > 0x5b0 && str.charCodeAt (0) < 0x6ff)
      this.textRange.ctrl.dir = "rtl";
}

function virkUpdateSel (ctrl) {
   try {
      var prevRange = this.textRange;
      this.activeCtrl = this.textRange = null;
      if (!ctrl)
         return;
      var range = new TextRange (ctrl);
      if (!range.ctrl)
         return;
      ctrl.focus ();
      this.activeCtrl = ctrl;
      this.textRange  = (range.ctrl == ctrl ? range : prevRange);
   }
   catch (e) {
      // fails if control is disabled or hidden
      // fails if selection belongs to another domain
   }
}

function isEditable (ctrl) {
   return !ctrl.disabled &&
          (ctrl.isContentEditable ||
           ctrl.tagName == "INPUT" && ctrl.type == "text" ||
           ctrl.tagName == "TEXTAREA");
}

function vkOnFocus (e) {
   virkCtrl.updateSel (getEventTarget (e));
}

function vkOnKeyDown (e) {
   var ctrl = getEventTarget (e);
   if (e.keyCode == 8 /*<del>*/ || e.keyCode == 46 /*<bs>*/)
      eventPreventDefault (e);
   virkCtrl.updateSel (ctrl);
   virkCtrl.kbd.onKeyDown (e);
}

function vkOnKeyUp (e) {
   virkCtrl.kbd.onKeyUp (e);
}

function vkOnKeyPress (e) {
   if (!(e.keyCode >= 33 && e.keyCode <= 40)) // not arrows?
      eventPreventDefault (e);
}

function eventPreventDefault (e) {
   if (e) {
      e.returnValue = false;
      if (e.preventDefault)
         e.preventDefault ();
   }
}

function getQueryParam (query, param) {
   var value = new RegExp (param + "=([^&]*)").exec (query);
   if (!value || value.length < 2)
      return "";
   return value [1];
}

//////////////////////////////////////////////////////////////////////////////
//
// TextRange
//

function TextRange (ctrl) {
   if (!ctrl.ownerDocument)
      return;
   this.ctrl = ctrl;
   if (document.selection) {
      this.range = ctrl.ownerDocument.selection.createRange ();
      this.ctrl = this.range.parentElement ();
      this.insertText = rangeInsertText;
      this.deleteText = rangeDeleteText;
   }
   else {
      this.insertText = plainInsertText;
      this.deleteText = plainDeleteText;
   }
}

function rangeInsertText (text) {
   this.range.text = text;
   this.range.collapse (false);
   this.range.select ();
}

function rangeDeleteText (dir) {
   if (!this.range.text) {
      var savedRange = this.range.duplicate ();
      if (dir < 0)
         this.range.moveStart ("character", -1);
      else
         this.range.moveEnd ("character", 1);
      if (/<.*>/.test (this.range.htmlText)) {
         this.range = savedRange;
         return;
      }
   }
   this.range.text = "";
   this.range.collapse (false);
   this.range.select ();
}

function plainInsertText (text) {
   this.ctrl.value = this.ctrl.value + text;
}

function plainDeleteText (dir) {
   if (dir < 0 && this.ctrl.value.length)
      this.ctrl.value = this.ctrl.value.substr (0, this.ctrl.value.length - 1);
}
