// ----- DETECTION

// platform detection
isWinOS = (navigator.appVersion.indexOf("Windows") != -1) ? true : false;
isMacOS = (navigator.appVersion.indexOf("Macintosh") != -1) ? true : false;

// browser detection
verInt = parseInt(navigator.appVersion.substring(0,1));
PWndUsingMSIE = (navigator.appVersion.indexOf("MSIE") == -1) ? false : true;
PWndUsingMSIE3 = (PWndUsingMSIE && (verInt == 2 || verInt == 3)) ? true : false;
PWndUsingMSIE4 = (PWndUsingMSIE && verInt == 4 && navigator.appVersion.indexOf("MSIE 5.") == -1) ? true : false;
PWndUsingMSIE5 = (PWndUsingMSIE && verInt == 4 && navigator.appVersion.indexOf("MSIE 5.") != -1) ? true : false;
PWndUsingNN = (navigator.appName.indexOf("Netscape") == -1) ? false : true;
PWndUsingNN2 = (PWndUsingNN && verInt == 2) ? true : false;
PWndUsingNN3 = (PWndUsingNN && verInt == 3) ? true : false;
PWndUsingNN4 = (PWndUsingNN && verInt == 4) ? true : false;
PWndUsingNN5 = (PWndUsingNN && verInt == 5) ? true : false;

// technology detection
implementsVB = ((PWndUsingMSIE && isWinOS) || (isMacOS && PWndUsingMSIE3)) ? true : false;  // VBScript
implementsImgObj = document.images ? true : false;  // Image Object
implementsMSDOM = document.all ? true : false;  // Microsoft Document Object Model
implementsNSDOM = document.layers ? true : false;  // Netscape Document Object Model


// ----- "POPUP" WINDOWS

// Parameters:
//   wReg - [REQUIRED] name of the *global* variable assigned this instance (for non-OO eval, window-focus operations).
//   wUrl - Default Target URL for new windows; =~ "about:blank".
//   wAttribs - Default window attributes for new windows; =~ no attributes.
//   wWait - Default re-open millisecond timeout for un-focusable (i.e. NN 2, MSIE 3) or buggy-focusable(i.e. MSIE 4) windows; =~ 250 ms.
// SEE PUBLIC Data and Methods for more info.
function PopupWindowObject(wReg, wUrl, wAttribs, wWait) {

  // --- PRIVATE
  // Data
  this.hashPopups = new PWndEmptyHash();
  this.errNoReg = "PopupWindowObject Instance Container Not Registered!";
  // Methods
  this.isValidReg = PWndIsValidRegistrant;

  // --- PUBLIC
  // Data
  this.registrant   = wReg;  // name of the *global* variable containing this instance
  if (! this.isValidReg())
    window.alert(this.errNoReg);
  this.url          = (wUrl == null ? "about:blank" : wUrl);  // default url for windows
  this.attributes   = wAttribs;  // default attributes for windows
  this.wait         = (wWait == null ? 250 : wWait);  // default ms timeout for re-open-type focus
  this.reliableMode   = true;  // if this script should perform reliable focusing in buggy browsers
  this.retainUrl    = true;  // true if a re-open retains the same url; otherwise false to use default url (some security restrictions apply)
  // Methods
  this.getHandle      = PWndHandle;
  this.newWindow      = PWndNew;       // open a new window
  this.showWindow     = PWndShow;  // shows a window using focus (if exists) or new (if does not exist)
  this.isOpened = PWndIsOpened;  // tells if the window is opened
  this.isClosed = PWndIsClosed;  // tells if the window is closed
  this.focusWindow    = PWndFocus;     // focus a window
  this.closeWindow    = PWndClose;     // close a window
}

function PWndIsValidRegistrant() {
  return (this.registrant == null || this.registrant == "") ? false : true;
}

// Show the window regardless of what operations need to be performed.
function PWndShow(wId, wUrl, wAttribs) {
  if (! this.isValidReg())
    return false;

  if (this.isOpened(wId)) { // window needs focus
    return this.focusWindow(wId, wUrl, wAttribs);
  }
  else { // window needs to be opened
    return this.newWindow(wId, wUrl, wAttribs);
  }
}


// For the specific purpose of having a completely empty object.
// NOTE: Arrays are not instantiated empty (see length property).
function PWndEmptyHash() {
  // populate me
}


// Opens a window under the specified id, if the id has not yet been assigned a window.
// Returns successfullness of this operation.
// IMPORTANT NN2: Because it is not implicitly possible to tell if a window is closed,
// place the following explicit javascript code inside all popup windows (to help this main script):
//
//    function wndDESTROY() {
//      var usingNetscape = (navigator.appName.indexOf("Netscape") == -1) ? false : true;
//      var usingNetscape2 = (usingNetscape && parseInt(navigator.appVersion.substring(0,1))== 2) ? true : false;
//      if (usingNetscape2 == true) {self.myOpener = true;}
//    }
//
//    <body onunload="wndDESTROY();">  // if a body exists
//    <frameset onunload="wndDESTROY();">  // if a frameset exists
//
function PWndNew(wId, wUrl, wAttribs) {
  if (! this.isValidReg())
    return false;

  if (this.isOpened(wId)) //exists already
    return false;

  if (wUrl == null) {wUrl = this.url;}
  if (wAttribs == null) {wAttribs = this.attributes;}

  wndNew = window.open(wUrl, wId, wAttribs);

  if (wndNew != null) {
    if (PWndUsingNN2 == true) {
      wndNew.myOpener = true;
    }
    this.hashPopups[wId] = wndNew;  // assign window handle value to ID key
    return true;
  }
  else {
    window.status = ("new wnd handle is null");
    return false;
  }
}

function PWndHandle(wId) {
  if (! this.isValidReg())
    return null;

  return this.hashPopups[wId];
}

// Closes the specified window, if it is open.
//
function PWndClose(wId) {  //closes specified window
  if (! this.isValidReg())
    return false;

  var wndHandle = this.hashPopups[wId];

  if (this.isOpened(wId)) {
    if (PWndUsingNN2 == true)
      wndHandle.myOpener = false;
    wndHandle.close();
  }

  this.hashPopups[wId] = null;

  return true;
}


// Tells is the specified window is opened, using various browser techniques.
//
function PWndIsOpened(wId) {
  if (! this.isValidReg())
    return null;

  var wndHandle = this.hashPopups[wId];
  if (wndHandle == null) return false;

  if (PWndUsingNN) {
    if (PWndUsingNN2) {
      if (wndHandle == null) {return false;}
      if (wndHandle.myOpener == true) {return true;}
      if (wndHandle.myOpener == false) {return false;}
      return true;  // assume opened if custom property .myOpener does not exist
    }
    else  // Netscape v3+
      return (! wndHandle.closed);
  }

  else if (PWndUsingMSIE) {  // any MS version
    return (! wndHandle.closed);
  }

  return true;  // because wndHandle was not null.
}


// Tells if the specified window is closed.
function PWndIsClosed(wId) {
  if (! this.isValidReg())
    return null;

  return (! this.isOpened(wId));
}


// Focuses the specified window.
function PWndFocus(wId, wUrl, wAttribs, wWait) {
  if (! this.isValidReg())
    return false;

  if (this.isClosed(wId))
    return false;

  var wndHandle = this.hashPopups[wId];

  if (wUrl == null) {wUrl = (this.retainUrl ? wndHandle.location.href : this.url);}
  if (wWait == null) {wWait = this.wait;}
  if (wAttribs == null) {wAttribs = this.attributes}

  // re-open window using timer
  if (PWndUsingMSIE3 || (PWndUsingMSIE4 && this.reliableMode)) {
    this.closeWindow(wId);
    var delayedCall = this.registrant + ".newWindow('" + wId + "','" + wUrl + "','" + wAttribs +"')";
    window.setTimeout(delayedCall, wWait);
  }
  // vanilla re-open window
  else if (PWndUsingNN2) {
    this.closeWindow(wId);
    this.newWindow(wId, wUrl, wAttribs);
  }
  // use .focus() method
  else {
    wndHandle.location.href = wUrl;
    wndHandle.focus();
  }

  return true;
}
