/***********************************************************************

 $Id: qscore.js,v 1.3 2006/04/14 15:01:39 www Exp $

Copyright (c) Quadstone 2001, 2002

************************************************************************

Core functions for external website.

Also includes API for layer manipulation.

For layering and menu functions, we currently support:

Netscape 4.X (pref X>>0)
Mozilla (pref 0.9.4+)
Internet Explorer 4+ (pref IE5)
Opera 5 (identified as anything, though won't have features of IE)
Netscape 6 (pref 6.2 or later)

Some early versions of these browsers will be buggy though - not
a lot can be done to help.

**********************************************************************/

var is = new Object();
is.sniffed = false;
var oldBrowser = false;

function sniffBrowser() {
  // Delayed browser sniff - NS4 was causing errors doing this
  // at the start over slow connections... very strange!!!
  is.Opera = (navigator.userAgent.match(/Opera.?5\./i));
  is.NS4 = (!is.Opera && document.layers) ? true : false;
  is.IE5  = (!is.Opera && document.all) ? true : false;
  is.Moz  = (!is.Opera && !is.IE5 && document.getElementById) ? true : false;
  is.supported = (is.NS4 || is.IE5 || is.Moz || is.Opera) && !oldBrowser;

  // When using DHTML on Netscape, we need to explicitly capture all
  // mouse movements and mouse up events in the document or else it'll
  // go a bit funny sometimes :-)
  if (is.NS4) {
    window.captureEvents(Event.RESIZE);
    window.onresize = function () { location.reload(); return false; }
  }
  is.sniffed = true;
}

/***********************************************************************

First up, some bog-standard mouseover/mouseout functions and such-like.
These invoke some specific menu functions from qsextmenus.js */

var isHomePage = false;

function setImg(name,ref) {
  if (document.images) {
    document.images[name].src = ref.src;
  }
}

/* Mouseovers for main navigation strips */
function over(menu_name, img_num) {
  if (!is.sniffed) {
    sniffBrowser();
  }
  if (isHomePage) { // (Images use visibility rather than swapping)
    var l = new QSLayer(img_num + "over");
    if (l) {
      var icon = l.getIcon("QI" + img_num);
      if (icon) {
        icon.src = (img_num=="cnt" || img_num=="map" || img_num=="src") 
          ? "/images/home/nav/weeover.gif" : "/images/home/nav/bigover.gif";
      }
    }
  }
  else { // Image will have been put into array by XSLT
    setImg("leftnav"+img_num, leftnav[2*img_num+1]);
  }
  if (menu_name) {
    if (is.Moz) { // Seems to be bug resulting in very jerk anim
      window.setTimeout("QSXMenus.show('"+menu_name+"')",10);
    }
    else if (is.supported) {
      QSXMenus.show(menu_name);
    }
  }      
  return true;
}
             
function out(img_num,inout) {
  if (!is.sniffed) {
    sniffBrowser();
  }
  if (isHomePage) {
    var l = new QSLayer(img_num + "over");
    if (l) {
      var icon = l.getIcon("QI" + img_num);
      if (icon) {
        icon.src = "/images/common/blank.gif";
      }
    }
  }
  else {
    setImg("leftnav"+img_num, leftnav[2*img_num+inout]);
  }
  if (is.Moz) {
    window.setTimeout("QSXMenus.outAll(null)",10);
  }
  else if (is.supported) {
    QSXMenus.outAll(null);
  }
  return true;
}

function sidechange(img_num,inout) {
  if (!is.sniffed) {
    sniffBrowser();
  }
  if (isHomePage) {
    var l = new QSLayer(img_num + "over");
    if (l) {
      var icon = l.getIcon("QI" + img_num);
      if (icon) {
        icon.src = "/images/common/blank.gif";
      }
    }
  }
  else {
    setImg("sidenav"+img_num, sidenav[2*img_num+inout]);
  }
  if (is.Moz) {
    window.setTimeout("QSXMenus.outAll(null)",10);
  }
  else if (is.supported) {
    QSXMenus.outAll(null);
  }
  return true;
}

/* Function for preloading images specified by the XSLT stage */
function loadNavImages(base) {
  if (document.images) {
    var names = ["inf", "doc", "kb", "ser", "for", "you", "cnt", "map", "src", "hme"];
    var a = new Array(2*names.length);
    var i,j,k;
    for (i=0, k=0; i<names.length; i++) {
      for (j=0; j<2; j++, k++) {
        a[k] = new Image();
        a[k].src = base + "/" + names[i] + j + ".gif";
      }
    }
    return a;
  }
  return null;
}

function loadImageList(base,names) {
  if (document.images) {
    var a = new Array(2*names.length);
    var i,j,k;
    for (i=0, k=0; i<names.length; i++) {
      for (j=0; j<2; j++, k++) {
        a[k] = new Image();
        a[k].src = base + "/" + names[i] + j + ".gif";
      }
    }
    return a;
  }
  return null;
}

function loadTree(base, num) {
  if (document.images) {
    var i;
    var a = new Array(num+1);
    for (i=0; i<=num; i++) {
      a[i] = new Image();
      a[i].src = base + "/dots" + i + ".gif";
    }
    return a;
  }
  return null;
}

/***********************************************************************

DEBUGGING CODE & UTILITY FUNCTIONS (TEMP)

***********************************************************************/

var QSCore = new Object(); // Container for most non-DHTML internal functions
QSCore.debug = function() { return; }; // Dummy function

/* <?BEGIN DEBUGGING CODE?> - everything between here and END marker can be left off production server */

// Set debuglevel to an integer between 0 and 10.  Warnings with
// criticality *less than or equal to* the debug level are then
// displayed. Set level to 0 to avoid messages.
QSCore.debuglevel = 0;
QSCore.setDebugLevel = function(level) {
  QSCore.debuglevel = level;
}

// Where should debugging info go?
// 'status' => messages go to window status
// 'log' => messages go to new 'log' window
// 'alert' => messages goes in alert boxes (yuck!)
// Otherwise, nothing
QSCore.debug_out = null;
QSCore.setDebugger = function(str) {
  QSCore.debug_out = str;
}

QSCore.debug = function(message, criticality) {
  criticality = criticality || 0;
  if (criticality <= QSCore.debuglevel) {
    switch(QSCore.debug_out) {
    case 'status':
      window.status = message;
      break;
    case 'log':
      if (!QSCore.logwin || !QSCore.logwin.document) {
        QSCore.logwin = window.open("","Logwindow",
                                    "scrollbars=yes,directories=no,hotkeys=no,location=no,menubar=no,status=no,toolbar=no");
        QSCore.logwin.document.open("text/plain");
        QSCore.logwin.document.writeln("Log Window Open\n---------------\n");
      }
      if (is.Moz) message = "<p>"+message+"</p>";
      QSCore.logwin.document.writeln(message);
      break;
    case 'alert':
      alert(message);
      break;
    default:
      break;
    }
  }
}

// Show contents of given object in log window (if applic) or as an alert.
QSCore.dumpObj = function(obj) {
  var i,s="Contents of object " + obj +":\n\n";
  for (i in obj) {
    s += i+"="+obj[i]+"\n";
  }
  QSCore.debug(s);
}

/* <?END DEBUGGING CODE?> */

/* Opera doesn't seem to have a string splitting function,
   so here's a wee simple one which'll do for the time being :-) */

QSCore.splitString = function(str, sep) {
  var arr = new Array();
  var i,j,k;
  for (i=j=k=0; i<str.length; i++) {
    if (str.substr(i,1)==sep) {
      arr[k++] = str.substr(j,i-j);
      j=i+1;
    }
  }
  arr[k] = str.substr(j);
  return arr;
}

/**********************************************************************

Code for manipulating "layers" within documents. This is all
fairly low-level stuff.

**********************************************************************/

// QSLayer is a very simple class allowing you to refer
// to layers with given name/id "lname" correctly according
// to the underlying DOM of the browser. Called with null
// "lname" gives you an abstract reference to the top layer
// of the document - don't use this for anything much yet :-)
// Set "nowarn" if you don't want us to moan if the layer
// doesn't exist. Can be handy if the "layer" is really a 
// non-positionable <div> element and we're using NS. In this
// case the QSLayer object will be set to the document itself.
QSLayer = function(lname, nowarn) {
  this.ref = document;
  if (is.NS4 && lname && document[lname]) {
    if ((this.ref = document[lname])!=null) 
      return;
  }
  else if ((is.Opera || is.Moz) && lname) {
    if ((this.ref = document.getElementById(lname))!=null)
      return;
  }
  else if (is.IE5 && lname) {
    if ((this.ref = document.all[lname])!=null)
      return;
  }
  if (is.supported && lname && !nowarn) { // Fell through with no ref found
    QSCore.debug("new QSLayer() called with invalid layer name '"+lname+"'", 1);
  }
  return;
}

/***********************************************************************

Public Methods

***********************************************************************/

// Find icon called "name" in given layer. This is actually
// quite pointless in the case of Mozilla & IE as all images
// are in the document object, but we need this for Netscape.
// In a slight NS kludge, we'll test for the presence of the
// image in the document object as well.
QSLayer.prototype.getIcon = function(name) {
  var l = this.ref;
  if (is.NS4 && l.document && l.document[name]) {
    return l.document[name];
  }
  else {
    return document[name];
  }
}

// Extension to above - returns position of icon relative to
// top of layer. If icon doesn't exist, there's a warning.
QSLayer.prototype.getIconPos = function(name) {
  var l = this.ref;
  var im = this.getIcon(name);
  if (!im) {
    QSCore.debug("getIconPos() method couldn't find icon called " +name);
  }
  else if (is.NS4) {
    var x = l.x || 0;
    var y = l.y || 0;
    return [im.x + x, im.y + y];
  }
  else if (is.Moz || is.Opera) {
    return [im.offsetLeft + l.offsetLeft, im.offsetTop + l.offsetTop];
  }
  else if (is.IE5) { // Sodding IE5 has to do lots of nesting and stuff ;-)
    var x=0;
    var y=0;
    while (im && im.nodeName!="BODY") {
      x += im.offsetLeft;
      y += im.offsetTop;
      im = im.offsetParent;
    } 
    return [x,y];
  }
  return null;
}

QSLayer.prototype.getVisible = function() {
  var l = this.ref;
  var v = "";
  if (l && is.NS4) {
    v = l.visibility;
  }
  else if (l) {
    v = l.style.visibility;
  }
  return v.substr(0,1)=='h' ? false : true;
}

QSLayer.prototype.setVisible = function(bool) {
  var l = this.ref;
  bool = bool ? "visible" : "hidden";
  if (l && is.NS4) {
    l.visibility = bool;
  }
  else if (l) {
    l.style.visibility = bool;
  }
}

QSLayer.prototype.setPageX = function(x) {
  var l = this.ref;
  if (l && is.NS4) {
    l.x = x;
  }
  else {
    l.style.pixelLeft = x;
  }
}

QSLayer.prototype.setPageY = function(y) {
  var l = this.ref;
  if (l && is.NS4) {
    l.y = y;
  }
  else if (l) {
    l.style.pixelTop = y;
  }
}

QSLayer.prototype.moveTo = function(x, y) {
  QSCore.debug("moveTo("+x+","+y+")", 10);
  var l = this.ref;
  if (l && is.NS4) {
    l.x = x;
    l.y = y;
  }
  else if (l && is.Moz) {
    l.style.left = x + "px";
    l.style.top = y + "px";
  }
  else if (l) {
    l.style.pixelLeft = x;
    l.style.pixelTop = y;
  }
}

QSLayer.prototype.setZIndex = function(ind) {
  var l = this.ref;
  if (l && is.NS4) {
    l.zIndex = ind;
  }
  else if (l) {
    l.style.zIndex = ind;
  }
}
  
QSLayer.prototype.setClip = function(top, right, bottom, left) {
  // N.B. Clipping is not supported by Opera 5
  var l = this.ref;
  if (is.NS4 && l) {
    if (top!=null) l.clip.top = top;
    if (right!=null) l.clip.right = right;
    if (bottom!=null) l.clip.bottom = bottom;
    if (left!=null) l.clip.left = left;
    return;
  }
  else if ((is.Moz || is.IE5) && l) {
    top = (top==null) ? "auto" : (top+"px");
    right = (right==null) ? "auto" : (right+"px");
    bottom = (bottom==null) ? "auto" : (bottom+"px");
    left = (left==null) ? "auto" : (left+"px");
    if (is.Moz) l.style.clip = "auto"; // (Bug in Mozilla)
    l.style.clip = "rect("+top+" "+right+" "+bottom+" "+left+")";
    return;
  }
  return null;
}

QSLayer.prototype.getSize = function() {
  var l = this.ref;
  if (l && is.NS4) {
    return new Array(l.clip.width, l.clip.height);
  }
  else if (l && is.Opera || l && is.IE && !l.style.offsetWidth) {
    return new Array(l.style.pixelWidth, l.style.pixelHeight);
  }
  else {
    return new Array(l.offsetWidth, l.offsetHeight);
  }
}

QSLayer.prototype.setSize = function(width, height) {
  // (N.B. This method won't work in Opera 5 yet as the
  // required features are not supported)
  var l = this.ref;
  if (l && is.NS4) {
    l.clip.width = width;
    l.clip.height = height;
  }
  else if (l) {
    l.style.width = width;
    l.style.height = height;
    if (is.Moz) l.style.clip = "auto"; // BUG
    l.style.clip = "rect(0px "+(width||0)+"px "+(height||0)+"px 0px)";
  }
}

QSLayer.prototype.setScrollView = function(left, top, height, ystart) {
  this.setClip(ystart, null, ystart+height, null);
  this.moveTo(left, top-ystart);
}

QSLayer.prototype.getPageX = function() {
  var l = this.ref;
  if (l && is.NS4) {
    return l.x;
  }
  else if (l && l.offsetLeft) {
    return l.offsetLeft;
  }
  else if (l) {
    return l.pixelLeft;
  }
  else {
    return 0;
  }
}

QSLayer.prototype.getPageY = function() {
  var l = this.ref;
  if (l && is.NS4) {
    return l.y;
  }
  else if (l && l.offsetTop) {
    return l.offsetTop;
  }
  else if (l.pixelTop) {
    return l.pixelTop;
  }
  else {
    return 0;
  }
}

QSLayer.prototype.getLinks = function() {
  var l = this.ref;
  if (l && is.NS4) {
    return l.document.links;
  }
  else if (l) {
    return l.getElementsByTagName("A");
  }
  else {
    return null;
  }
}

function FlashDemo(page) {
OpenWin = this.open(page, "SnapWindow", "width=840,height=640,toolbar=no,menubar=no,location=no,scrollbars=yes,resizable=no")
   OpenWin.focus()	
}

function openWindow(page, width, height) {
OpenWin = this.open(page, "SnapWindow", "width=" + width + ",height="+ height + ",toolbar=no,menubar=no,location=no,scrollbars=yes,resizable=no")
  OpenWin.focus()
}


function hideHelp(listOfIds) {
  for (Id in listOfIds) {

    var listId = 'list' + Id;
    var titleId = 'title' + Id;
    document.getElementById(listId).style.display = "none";
    //document.getElementById(titleId).style.list-style-image = "project.png";
  }
}

function showPortalToc(Id) {
 document.getElementById('title' + Id).style.display = 'block';
 document.getElementById('list' + Id).style.display = 'block';
 document.getElementById('toctitle' + Id).style.display = 'none';
}

function hidePortalToc(Id) {
 document.getElementById('title' + Id).style.display = 'none';
 document.getElementById('list' + Id).style.display = 'none';
 document.getElementById('toctitle' + Id).style.display = 'block';
}
