<!-- // Hide

// *** COMMON CROSS-BROWSER COMPATIBILITY CODE ***

// You'll need to edit this section if combining with any of my other scripts, make sure
// everything is included once.

var isDOM = (document.getElementById ? true : false);
var isIE = (document.all ? true: false);
var isNS4 = (navigator.appName=='Netscape' && !isDOM ? true : false);
var isIE4 = ((isIE && !isDOM) ? true : false);
var isDyn = (isDOM || isIE4 || isNS4);

function getRef(id, par)
{
 par = (!par ? document : (par.navigator ? par.document : par));
 return (isIE ? par.all[id] :
  (isDOM ? (par.getElementById?par:par.ownerDocument).getElementById(id) :
  par.layers[id]));
}

function getSty(id, par)
{
 return (isNS4 ? getRef(id, par) : getRef(id, par).style);
}

function LayerObj(id, par)
{
 this.ref = getRef(id, par);
 this.sty = getSty(id, par);

 this.x = function(nX) { if (!isNaN(nX)) this.sty.left=nX; else return parseInt(this.sty.left) }
 this.y = function(nY) { if (!isNaN(nY)) this.sty.top=nY; else return parseInt(this.sty.top) }

 this.w = function(nW) {
  if (nW) (isNS4?this.sty.clip:this.sty).width=nW;
  else return (isNS4?this.ref.document.width:this.ref.offsetWidth) }
 this.h = function(nH) {
  if (nH) (isNS4?this.sty.clip:this.sty).height=nH;
  else return (isNS4?this.ref.document.height:this.ref.offsetHeight) }
 
 this.vis = function(val) { this.sty.visibility=val }

 this.clip = function(l, t, r, b) {
  if (isNS4) with(this.sty.clip) { left=l; top=t; right=r; bottom=b }
  else this.sty.clip = 'rect('+t+'px '+r+'px '+b+'px '+l+'px)' }

 return this;
}
function getLyr(id, par) { return new LayerObj(id, par) }


/*** Menu ***/
// *** MOUSEOVER/OUT CONTROL FUNCTIONS ***

// Hide timeout.
var popTimer = 0;
// Arrays holding highlighted menu items.
var litNow = new Array();

function popOver(menuNum, itemNum)
{
 clearTimeout(popTimer);

 // Hide all other menus & dim old highlighted items, still showing this menu.
 hideAllBut(menuNum);

 // Get tree of parent menu items and light them up - global variable!
 litNow = getTree(menuNum, itemNum);
 changeCol(true);

 // Get target menu to show - if it's nonzero, position & show it.
 targetNum = menu[menuNum][itemNum].target;
 if (targetNum > 0)
 {
  // Get current menu position - menu position plus item position in menu.
  thisX = parseInt(menu[menuNum][0].ref.left) + parseInt(menu[menuNum][itemNum].ref.left);
  thisY = parseInt(menu[menuNum][0].ref.top) + parseInt(menu[menuNum][itemNum].ref.top);

  // Add those to the target's offset to set the target's position, show it.
  with (menu[targetNum][0].ref)
  {
   left = thisX + menu[targetNum][0].x;
   top = thisY + menu[targetNum][0].y;
   visibility = 'visible';
  }
 }
}

function popOut(menuNum, itemNum)
{
 // If it's a root menu item that doesn't trigger a popout, hide now, else set timeout
 // to hide all menus in 1/2 sec... remember, another mouseover clears the timeout.
 if ((menuNum == 0) && !menu[menuNum][itemNum].target) hideAllBut(0);
 else popTimer = setTimeout('hideAllBut(0)', 500);
}

function popClick(menuNum, itemNum)
{
 with (menu[menuNum][itemNum])
 {
  switch (type)
  {
   // A JavaScript function? Eval() it and break out of switch.
   case 'js:': { eval(href); break }
   // Otherwise, point to the window if nothing else and navigate.
   case '': type = 'window';
   default: if (href) eval(type + '.location.href = "' + href + '"');
  }
 }

 // Whatever happens, hide the menus when clicked.
 hideAllBut(0);
}


function getTree(menuNum, itemNum)
{
 // Array index is the menu number. The contents are null (if that menu is not a parent)
 // or the item number in that menu that is an ancestor (to light it up).
 itemArray = new Array(menu.length);

 while(1)
 {
  itemArray[menuNum] = itemNum;
  // If we've reached the top of the hierarchy, return.
  if (menuNum == 0) break;
  itemNum = menu[menuNum][0].parentItem;
  menuNum = menu[menuNum][0].parentMenu;
 }
 return itemArray;
}

// Pass an array and a boolean to specify colour change, true = over colour.
// N.B: Uses global litNow array which contains items in hierarchy.
function changeCol(isOver)
{
 // Cycle through array searching for items to change.
 for (count = 0; count < litNow.length; count++)
 {
  // If item number is present, change its colour.
  if (litNow[count])
  {
   // Nest two WITH's, the last being more specific to allow item hover colours.
   with (menu[count][0]) with (menu[count][litNow[count]])
   {
    newCol = isOver ? overCol : backCol;

    // Change the colours of the div/layer background.
    if (isNS4) ref.bgColor = newCol;
    else ref.backgroundColor = newCol;
   }
  }
 }
}

function hideAllBut(menuNum)
{
 // Get array of parent menus (item numbers irrelevant, just pass '1').
 var keepMenus = getTree(menuNum, 1);

 // ...and work through it, hiding menus that are not its ancestors/itself.
 for (count = 0; count < menu.length; count++)
  if (!keepMenus[count] && menu[count]) menu[count][0].ref.visibility = 'hidden';

 // Dim all the items in litNow array.
 changeCol(false);
}


// *** MENU ARRAY CONSTRUCTION FUNCTIONS ***

// This is incredibly, incredibly cool. Really. It takes an array of data and names and
// assigns the values to a specified object -- used to slim down the constructors here.
function addProps(obj, data, names, addNull)
{
 for (i = 0; i < names.length; i++)
  if(i < data.length || addNull) obj[names[i]] = data[i];
}

// Use above function to add our list of arguments to the menu array.
function Menu()
{
 var names = ['isVert', 'popInd', 'x','y', 'width', 'pad', 'overCol', 'backCol',
  'borderClass', 'textClass',      'parentMenu', 'parentItem', 'ref'];
 addProps(this, arguments, names, true);
}

function Item()
{
 var names = ['text', 'href', 'type', 'length', 'spacing', 'target',    'ref'];
 addProps(this, arguments, names, true);
}


// *** MAIN MENU SETUP FUNCTION ***

function createMenus()
{
 if (!isDyn) return;

 // Loop through menus, using properties of menu description object, i.e. x, y, width etc...
 for (currMenu = 0; currMenu < menu.length; currMenu++)
 if (menu[currMenu]) with (menu[currMenu][0])
 {
  // Variable for holding HTML for items and positions of next item.
  var str = '', itemX = 0, itemY = 0;

  // In NS4, since borders are assigned to the table rather than layer, increase padding.
  if (isNS4) pad++;

  // Remember, items start from 1 in the array (0 is menu object itself, above).
  // Also use properties of each item nested in the other with() for construction.
  for (currItem = 1; currItem < menu[currMenu].length; currItem++) with (menu[currMenu][currItem])
  {
   var itemID = 'menu' + currMenu + 'item' + currItem;

   // The width and height of the menu item - dependent on orientation!
   // NS6 disagrees with other browsers as to whether borders increase widths, so fix here.
   var shrink = (borderClass && isDOM && !document.all ? 2 : 0)
   var w = (isVert ? width : length) - shrink;
   var h = (isVert ? length : width) - shrink;

   // Create a div or layer text string with appropriate styles/properties.
   if (isDOM || isIE4)
   {
    str += '<div id="' + itemID + '" style="position: absolute; left: ' + itemX +
     '; top: ' + itemY + '; width: ' + w + '; height: ' + h + '; visibility: inherit; ';
    if (backCol) str += 'background: ' + backCol;
    str += '" ';
   }
   if (isNS4)
   {
    str += '<layer id="' + itemID + '" left="' + itemX + '" top="' + itemY + '" width="' + 
     w + '" height="' + h + '" visibility="inherit" ';
    if (backCol) str += 'bgcolor="' + backCol + '" ';
   }
   if (borderClass) str += 'class="' + borderClass + '" ';
   
   // Add mouseover and click handlers and finish div/layer.
   str += 'onMouseOver="popOver(' + currMenu + ',' + currItem + ')" onMouseOut="popOut(' +
     currMenu + ',' + currItem + ')" onClick="popClick(' + currMenu + ',' + currItem + ')">';



   // Add contents of item...

   if (target > 0)
   {
    // Set target's parents to this menu item.
    menu[target][0].parentMenu = currMenu;
    menu[target][0].parentItem = currItem;

    // Add a popout indicator - before text so it shows up below text in NS4.
    if (popInd)
    {
     if (isNS4) str += '<layer class="' + textClass + '" left="'+ (w - 15) + '" top="' +
      pad + '">' + popInd + '</layer>';
     else str += '<div class="' + textClass + '" style="position: absolute; left: ' + (w - 15) +
      '; top: ' + pad + '">' + popInd + '</div>';
    }
   }

   // For NS4, if a border is assigned, add a spacer to push border out to layer edges.
   // The text layer must completely overlay this table as well for proper click capturing.
   // Add a link both to generate an onClick event and to stop the ugly I-beam text cursor appearing.
   if (isNS4) str += (borderClass ? '<spacer type="block" width="' + (w - 8) + '" height="' +
    (h - 8) + '">' : '') +
    '<layer left="' + pad + '" top="' + pad + '" width="' + (w - (2 * pad)) + '" height="' +
    (h - (2 * pad)) + '"><a class="' + textClass + '" href="#" ' +
    'onClick="popClick(' + currMenu + ',' + currItem + '); return false" ' +
    'onMouseOver="status=\'\'; return true;">' + text + '</a></layer>';

   // IE4+/NS6 is an awful lot easier to work with sometimes.
   else str += '<div class="' + textClass + '" style="position: absolute; left: ' + pad +
    '; top: ' + pad + '; width: ' + (w - (2 * pad)) + '; height: ' + (h - (2 * pad)) +
    '">' + text + '</div>';

   // Finish off item.
   str += (isNS4 ? '</layer>' : '</div>');

   // Move next item position down or across by this item's length and additional spacing.
   // Subtract 1 so borders overlap slightly.
   if (isVert) itemY += length + spacing - 1;
   else itemX += length + spacing - 1;

  // End loop through items and with([menu[currMenu][currItem]).
  }



  // Now, write the menu to the document depending on browser capabilities.
  // N.B: Still using properties of menu[currMenu][0] like 'ref' etc...
   
  // Insert a div tag to the end of the BODY with menu HTML in place for IE4+.
  if (document.all)
  {
   // Give a small width and height to stop IE4 sizing to full body. Thanks to Jeff Blum
   // for pointing this out. Also, thanks to Paul Maden for helping debug this, apparently
   // the width must be a miniumum of 3 for it to work in IE4.
   document.body.insertAdjacentHTML('beforeEnd', '<div id="menu' + currMenu + 'div" ' +
    'style="position: absolute; width: 3; height: 3; visibility: hidden; z-index: 1000">' +
     str + '</div>');
   ref = getSty('menu' + currMenu + 'div');
  }
  // In NS6+ or other DOM but non-IE browsers, create a new DIV node and add text...
  else if (isDOM)
  {
   var newDiv = document.createElement('div');
   document.body.appendChild(newDiv);
   newDiv.innerHTML = str;
   ref = newDiv.style;
    
   ref.position = 'absolute';
   ref.visibility = 'hidden';
  }
  // In NS4, create a reference to a new layer and write the items to it.
  else if (isNS4)
  {
   ref = new Layer(0);
   ref.document.write(str);
   ref.document.close();
  }

  // Chuck some positions in here. Only really relevant for root menu.
  ref.left = x;
  ref.top = y;
  // Set the default cursor for the menu to be the hand (or 'pointer' if you're the W3C or
  // Mozilla Project and just trying to be difficult :)...
  if (!isNS4) ref.cursor = (document.all ? 'hand' : 'pointer');
  // IE has z-indices assigned already, IE4 doesn't like them done here for some reason.
  if (!document.all) ref.zIndex = 1000;

  // Now items have been written, loop through them again to set up references.
  for (currItem = 1; currItem < menu[currMenu].length; currItem++)
  {
   itemName = 'menu' + currMenu + 'item' + currItem;
   if (isDOM || isIE4) menu[currMenu][currItem].ref = getSty(itemName);
   if (isNS4)
   {
    menu[currMenu][currItem].ref = ref.document[itemName];
    // Also capture clicks on that item layer's document...
    with (ref.document[itemName])
    {
     document.captureEvents(Event.CLICK);
     document.onclick = new Function('popClick(' + currMenu + ', ' + currItem + ')');
    }
   }
  }

 // End loop through menus and with (menu[currMenu][0]).
 }

 // *** CENTRING FUNCTION ***  Uncomment this to centre menus.
 //positionMenu()

 // Show the root menu now that's all over. Phew!
 menu[0][0].ref.visibility = 'visible';
}










// Syntaxes:    *** START EDITING HERE, READ THIS SECTION CAREFULLY! ***
//
// menu[menuNumber][0] = new Menu(Vertical menu? (true/false), 'popout indicator', left, top,
// width, padding, 'hover colour', 'background colour', 'border stylesheet', 'text stylesheet');
//
// Left and Top are measured on-the-fly relative to the top-left corner of its trigger, or
// for the root menu, the top-left corner of the page.
//
// menu[menuNumber][itemNumber] = new Item('Text', 'URL', 'link type', length of menu item,
//  additional spacing to next menu item, number of target menu to popout);
//
// If no target menu (popout) is desired, set it to 0. Also, every menu must be targeted only
// once in the code! If you want, the 'colItem' function call in the 'Reopen' sample menu
// is an example constructor, see below in the 'Optional Code' section.
//
// Something that needs explaining - the Vertical Menu setup. You can see most menus below
// are 'true', that is they are vertical, except for the first root menu. The 'length' and
// 'width' of an item depends on its orientation -- length is how long the item runs for in
// the direction of the menu, and width is the lateral dimension of the menu. Just look at
// the examples and tweak the numbers, they'll make sense eventually :).
//
// Something else - the 'link type'. Introduced in v2.0, it was originally the name of a
// target frame. Now, you specify an empty string '' to open the URL in the current window,
// 'js:' to specify a JavaScript function, or a valid reference to a window/frame, e.g.
// 'top.leftFrame' or 'parent.popupWin'. Thanks to Martin J. Cole for suggesting the syntax!

var menu = new Array();

// Default colours passed to most menu constructors (just passed to functions, not
// a global variable - makes things easier to change later in bulk).
var defOver = '#8CB531', defBack = '#CCCCCC';

// Default 'length' of menu items - item height if menu is vertical, width if horizontal.
var defLen = 20;


// Menu 0 is the special, 'root' menu from which everything else arises and is positioned.
menu[0] = new Array();
// A non-vertical menu, different coloured menu with no popout indicator, background or border.
// *** MOVE THE MENU AROUND HERE, SEE BELOW FOR CENTRING FUNCTION ***
// It's positioned at (x = 5, y = 0) and is 17px high now, with 0px padding.
menu[0][0] = new Menu(false, '', 350, 15, 15, 0, '#666666', '#e99500', '', 'itemTextMenu');
// Notice how the targets are all set to nonzero values...
// The 'length' of each of these items is 40, and there is spacing of 10 to the next item.
// Most of the links are set to '#' hashes, make sure you change them to actual files.
menu[0][1] = new Item('&nbsp;Home', 'mainDiv.load("home.html")', 'js:', 55, 11, 0);
menu[0][2] = new Item('&nbsp;Services', '#', '', 63, 13, 2);
menu[0][3] = new Item('&nbsp;Support', '#', '', 55, 13, 3);
menu[0][4] = new Item('&nbsp;Information', '#', '', 65, 11, 4);
menu[0][5] = new Item('&nbsp;Contact Us', 'mainDiv.load("contactus.html")', 'js:', 65, 8, 0);

// Services
menu[2] = new Array();
menu[2][0] = new Menu(true, '&gt;', 0, 19, 95, 3, defOver, defBack, 'itemBorder', 'itemText');
menu[2][1] = new Item('Shared Hosting', 'mainDiv.load("shared.html")', 'js:', defLen, 0, 0);
menu[2][2] = new Item('Dedicated Hosting', 'mainDiv.load("dedicated.html")', 'js:', defLen, 0, 0);
menu[2][3] = new Item('Colocation', ' mainDiv.load("colocation.html")', 'js:', defLen, 0, 0);
menu[2][4] = new Item('Guarantee', ' mainDiv.load("guarantee.html")', 'js:', defLen, 0, 0);
menu[2][5] = new Item('Terms of Service', 'window.open("/tos.html")', 'js:', defLen, 0, 0);

// Support
menu[3] = new Array();
menu[3][0] = new Menu(true, '&lt;', 0, 19, 80, 3, defOver, defBack, 'itemBorder', 'itemText');
menu[3][1] = new Item('FAQs', 'mainDiv.load("faqs.html")', 'js:', defLen, 0, 0);
menu[3][2] = new Item('Tutorials', 'mainDiv.load("tutorials.html")', 'js:', defLen, 0, 0);
menu[3][3] = new Item('Via E-Mail', 'mailto:support@tier1host.net', '', defLen, 0, 0);


// Client Tools
menu[4] = new Array();
menu[4][0] = new Menu(true, '&gt;', 0, 19, 80, 3, defOver, defBack, 'itemBorder', 'itemText');
menu[4][1] = new Item('News', 'mainDiv.load("news.html")', 'js:', defLen, 0, 0);
menu[4][2] = new Item('About Us', 'mainDiv.load("aboutus.html")', 'js:', defLen, 0, 0);
menu[4][3] = new Item('Our Network', 'mainDiv.load("networkinfo.html")', 'js:', defLen, 0, 0);













// *** LOAD FILES INTO DIV FUNCTIONS ***


function scrLoad(fName) { with (this)
{
 if (!fName || !loaded || !isDyn) return;

 // Set this as the currently loading file, and fire the 'onbeforeload' event.
 loadingFile = fName;
 if (onbeforeload) onbeforeload();

 // Trigger a file load in IE, that calls the 'fileLoaded()' function when complete.
 if (isIE || isDOM) with (bufRef.document)
 {
  // Nest an Iframe with an onload handler.
  write('<html><body onload="parent.' + myName + '.fileLoaded()">' +
   '<iframe name="nestBuf" src="' + fName + '"></iframe></body></html>');
  close();
  // In early versions of NS6, the nested Iframe is not invoked nor is the onload event fired.
  // So we set the regular frame's location and give it 5 secs to load.
  if (!bufRef.nestBuf)
  {
   bufRef.location.href = fName;
   setTimeout(myName + '.fileLoaded()', 5000);
  }
 }
 else if (isNS4)
 {
  div.ref.onload = new Function(myName + '.fileLoaded()');
  // Netscape's load(URL, width) method...
  div.ref.load(fName, cWidth);
 }
}}


function scrFileLoaded() { with (this)
{
 // Stop dragging any scroller while we switch files.
 activeScr = null;

 // In IE or NS6, shift the contents of the IFrame buffer into the DIV.
 // Note this is still an extension of the NS6 kludge, not using the nested IFrame.
 if ((isDOM || isIE) && loadingFile)
 {
  div.ref.innerHTML = (bufRef.nestBuf ? bufRef.nestBuf.document.body.innerHTML :
   bufRef.document.body.innerHTML);
  bufRef.location.replace('about:blank');
 }

 // Set the loaded file as the one we've just loaded.
 loadedFile = loadingFile;

 // Scroll back to top... the short delay helps IE4, giving it some time to render
 // the new document to calculate its height. Also fire the 'onload' event.
 setTimeout('with(' + myName + ') { scrollTo(0); if (onload) onload() }', 1);
}}



// *** DIV SCROLLING FUNCTIONS ***


function scrScrollTo(pos) { with (this)
{
 if (!isDyn || !loaded) return;

 // Assign new top value -- parseInt() as this gets passed fractions sometimes.
 cTop = parseInt(pos);

 // Height of div, plus padding - update here as it may change often.
 divHeight = div.h() + padTop + padBot;
 // Stops 'divide by zero'
 if (divHeight == 0) divHeight = 1;

 // Are we scrolling out of range? If so, return to top/bottom.
 if (cTop + cHeight > divHeight) cTop = divHeight - cHeight;
 if (cTop < 0) cTop = 0;

 // Move div up/down... 'scrolling' div, and reclip as we do so.
 div.y(eval(divs[0][2]) - cTop + padTop);
 div.clip(0, cTop - padTop, cWidth, cTop - padTop + cHeight);


 // Define its height as the percentage of the clipping height vs div height.
 // Best to set it here as divHeight may change as images load etc.
 thmHeight = Math.ceil(barHeight * (cHeight / divHeight));

 // Minimum and maximum heights for thumb...
 if (thmHeight < minThmHeight) thmHeight = minThmHeight;
 if (thmHeight > barHeight) thmHeight = barHeight;

 // Assign the thumb its calculated height.
 thm.h(thmHeight);

 // Now is a good time to fire the 'onscroll' event if it exists.
 if (onscroll) onscroll();

 // Adjust scrollbar thumb position only if we're not already dragging it.
 if (activeScr) return;

 // What fraction is the div of its total scrolling range? 0=top, 1=bottom.
 fracDivDown = (cTop / (divHeight - cHeight));
 // Now, multiply that by the available space to move and assign its top.
 thm.y(bar.y() + fracDivDown * (barHeight - thmHeight));
}}


function scrScrollBy(amount) { with (this)
{
 // Scroll to the old location plus however much we're scrolling by.
 scrollTo(cTop + amount);

 // If we're looping, set a timeout to scroll by amount again.
 if (loop) setTimeout(myName + '.scrollBy(' + amount + ')', loop);
}}



// *** SCROLL THUMB DRAGGING EVENT HANDLERS ***


function scrThumbDown(evt) { with (this)
{
 // Set the global variable pointing to the active scroller - this scroller object.
 activeScr = this;

 // Offset of mouse cursor within the scrollbar...
 dragOffset = (isIE ? event.offsetY : evt.layerY);

 // Fire the 'onthumbdown' event if it exists.
 if (onthumbdown) onthumbdown();

 return false;
}}


function scrThumbMove(evt)
{
 // Either return true if no scroller is being dragged (so selections work), or if
 // it's NS4 just route the event...
 if (!activeScr) return (isNS4 ? document.routeEvent(evt) : true);
 else with (activeScr)
 {
  // If it's not scrollable, quit.
  if ((cTop + cHeight > divHeight) || (thmHeight == barHeight)) return;

  // Calculate the new position of the thumb within the scrollbar (0 = at the top).
  var thmTop = (isIE ? document.body.scrollTop + event.clientY : evt.pageY) - dragOffset - bar.y();
 
  // Test if the thumb is out of range, if so, bring it back, then assign its position.
  if (thmTop < 0) thmTop = 0;
  if (thmTop + thmHeight > barHeight) thmTop = barHeight - thmHeight;
  thm.y(bar.y() + thmTop);

  // Scroll to the new position.
  scrollTo((divHeight - cHeight) * (thmTop / (barHeight - thmHeight)));

  return false;
 }
}


function scrThumbUp(evt)
{
 // Fire the 'onthumbup' event if it exists.
 if (activeScr) with (activeScr) if (onthumbup) onthumbup();

 // Clear the active scroller global variable.
 activeScr = null;

 if (isNS4) return document.routeEvent(evt);
}



// *** SCROLLBAR BACKGROUND CLICK EVENT HANDLER ***


function scrBarClick(evt) { with (this)
{
 if (isIE) clickPos = document.body.scrollTop + event.clientY;
 else clickPos = evt.pageY;

 // Page up, or page down?
 if (clickPos < thm.y()) scrollBy(0 - cHeight);
 if (clickPos > (thm.y() + thmHeight)) scrollBy(cHeight);

 if (isNS4) return document.routeEvent(evt);
}}



// *** LAYOUT HANDLER FOR WINDOW RESIZE ETC ***


function scrLayout() { with (this)
{
 if (!isDyn || !loaded) return;

 var winWidth = isIE ? document.body.clientWidth : window.innerWidth;
 var winHeight = isIE ? document.body.clientHeight : window.innerHeight;

 // Minimum values for window sizes.
 if (winWidth < minWinWidth) winWidth = minWinWidth;
 if (winHeight < minWinHeight) winHeight = minWinHeight;

 // Loop through divs array, positioning/sizing controls.
 // Remember that divs[i][5] is the layer object for the div.
 for (var i = 0; i < divs.length; i++) with (divs[i][5])
 {
  x(eval(divs[i][1])); w(eval(divs[i][3]));
  // Only set Y and height if it's not the scrolling div.
  if (i) { y(eval(divs[i][2])); h(eval(divs[i][4])) }
 }

 // Bar height and clipping dimensions, accessed often so stored as object properties.
 barHeight = eval(divs[1][4]);
 cWidth = eval(divs[0][3]);
 cHeight = eval(divs[0][4]);

 // Now, display it using updated variables...
 scrollBy(0);
}}


// *** ON LOAD: CAPTURE EVENTS & MISC. SETUP ***


function scrSetup(defaultFile) { with (this)
{
 if (!isDyn) return;

 // Get layer objects for all the divs passed to the function somehow...
 for (var i = 0; i < divs.length; i++) divs[i][5] = getLyr(divs[i][0]);

 // These get accessed so often we might as well get some short references.
 div = divs[0][5];
 bar = divs[1][5];
 thm = divs[2][5];

 // Buffer frame for IE/NS6 -- same as scroller name, plus 'Buf'.
 // NS6 has troubles with the frames array and iframes, so use a workaround.
 if (!isNS4) bufRef = eval('window.' + myName + 'Buf');

 // Set up event capturing for NS4.
 if (isNS4)
 {
  bar.ref.captureEvents(Event.CLICK);
  thm.ref.captureEvents(Event.MOUSEDOWN);
  document.captureEvents(Event.MOUSEMOVE | Event.MOUSEUP);
 }

 // Pass events to specific scrollers.
 bar.ref.onclick = new Function('evt', 'return ' + myName + '.barClick(evt)');
 thm.ref.onmousedown = new Function('evt', 'return ' + myName + '.thumbDown(evt)');
 // The mouseMove and mouseUp events are global, as they can occur anywhere on the document.
 // They use the 'activeScr' global variable -- a reference to the currently dragging scroller.
 // I tried making this truly object-orientated, setting these two functions to be methods of
 // a scroller object and calling 'activeScr.thumbMove()', but it crashed Netscape 4.
 document.onmousemove = scrThumbMove;
 document.onmouseup = scrThumbUp;

 // For IE4+/NS6, create a new function that stops selections being made when dragging.
 var noSel = new Function('if (activeScr) return false');
 if (isIE) document.onselectstart = noSel;
 else if (isDOM) document.onselect = noSel;


 // It's now ready to go, call resize function to set the positions and variables...
 loaded = true;
 layout();
 // Now is a good time to fire the 'onsetup' event, it's ready to load...
 if (onsetup) onsetup();


 // Get the name of the file to be loaded from a URL query string...
 var fileName = ''
 // Get the string after the question mark.
 var URL = location.search.substring(1);
 if (URL)
 {
  // Split it into an array of scroller/filename pairs.
  URL = URL.split('&');
  // Search through that array looking for this scroller name.
  for (var i = 0; i < URL.length; i++)
   if (URL[i].split('=')[0] == myName) fileName = URL[i].split('=')[1];
 }

 // Contains string '.htm'...? (can be '.html' file of course)
 if (fileName.indexOf('.htm') != -1) load(fileName)

 // Else load default file (if we're passed one) or scroll existing content without loading.
 else if (defaultFile) load(defaultFile);
 else fileLoaded();
}}



// *** SCROLLER OBJECT CONSTRUCTOR FUNCTIONS ***


// This takes arrays of data and names and assigns the values to a specified object.
function addProps(obj, data, names, addNull)
{
 for (var i = 0; i < names.length; i++) if(i < data.length || addNull) obj[names[i]] = data[i];
}


// Main object of which instances are created.
function DHTMLScroller()
{
 // Only the first is actually passed to the function, the rest are just added as 'undefined'.
 var names = ['myName', 'bufRef', 'div', 'bar', 'thm', 'loaded', 'loop', 'divHeight', 'thmHeight',
  'barHeight', 'cHeight', 'cWidth', 'dragOffset', 'onbeforeload', 'onload', 'onscroll', 'onsetup',
  'onthumbdown', 'onthumbup'];
 addProps(this, arguments, names, true);

 // The top clipping position by default is zero -- the top of the file.
 this.cTop = 0;

 // The file(s) currently loading and displayed in the scroller,
 this.loadingFile = '';
 this.loadedFile = '';

 // Array of objects to move when the window is resized (e.g. scrollbar, arrows).
 this.divs = new Array();
 
 // Minimum height of scrollbar thumb - defaults to 20, set to something else if you want.
 this.minThmHeight = 20;
 // Minimum window sizes - script will use these if actual sizes are too low.
 this.minWinWidth = 400;
 this.minWinHeight = 300;
 // Padding at the top and bottom -- set these manually if you want.
 this.padTop = 0;
 this.padBot = 0;

 // Methods - bound to functions above.
 this.load = scrLoad;
 this.fileLoaded = scrFileLoaded;
 this.scrollTo = scrScrollTo;
 this.scrollBy = scrScrollBy;
 this.thumbDown = scrThumbDown;
 // The other thumb functions are global, associated with document.onevent.
 // They rely on the 'activeScr' global variable to tell them which scroller is being dragged.
 this.barClick = scrBarClick;
 this.setup = scrSetup;
 this.layout = scrLayout;
}


// One global variable that points to the scroller currently being dragged.
var activeScr = null;














// *** SCROLLER OBJECT SETUP -- START EDITING HERE ***.

// First, you have to create one or more scroller objects, syntax:
// var name = new DHTMLScroller('name');

var mainDiv = new DHTMLScroller('mainDiv');


// Then, working with its properties, we tell it the names of the relevant divs below we want it
// to use. This is accomplished by the 'divs' array, to which we add new items like so:
//
// divs[number] = new Array('id of div below', 'x', 'y', 'width', 'height');
//
// As you can see, the second through to fourth parameters are the positions and dimensions of the
// divs, declared here rather than as properties to the divs below. They are strings containing

// either plain numbers, or formulae using global variables like winWidth and winHeight to achieve
// special positions, e.g. centring or sizing with the window. Pass an empty string '' to tell
// the script not to set that particular parameter.
//   The divs[i][5] subarray is reserved for a layer object correpsonding to the ID. You can use
// this in custom scripts to move/size/show/hide/clip etc... the relevant div, or use any other
// functions added to the Layer API at the top of this code.
//   The first three divs are special -- divs[0] is the scroller itself, 1 = the scrollbar thumb
// (the draggable bit), and 3 = the scrollbar background. Anything after that is positioned and
// sized by the scroller engine on window resize but does not have any special properties.

with (mainDiv)
{
 // This scroller uses a div named 'mainDiv' to load files, which is positioned at (x=50, y=50)
 // and is most of the window wide and high. If you want to centre the div, try something like:
 // divs[0] = new Array('mainDiv', 'winWidth/2 - 300', 'winHeight/2 - 200', '600', '400');
 // You can't create a scroller within a table cell, but you can set it to hover over the cell --
 // be inventive with the formulae you use!
 divs[0] = new Array('mainDivContent', '43', '140', '493', '270');
 // Our scrollbar itself is positioned towards the right edge of the page and takes up most
 // of the page height.
 divs[1] = new Array('mainDivBar', '541', '163', '24', '224');
 // Don't pass Y or Height thumb settings, these are set automatically when it's dragged.
 divs[2] = new Array('mainDivThumb', '541', '', '24', '');

 // These are the up and down arrow divs, positioned on resize accordingly...
 divs[3] = new Array('mainDivUpArrows', '541', '138', '', '');
 divs[4] = new Array('mainDivDownArrows', '541', '388', '', '');

 // You can also set some other optional properties like:
 //
 // padTop = 100; padBot = 50;  // sets the padding at the top and bottom.
 // minThumbHeight = 50;  // sets the minimum height of the thumb (default 20px)
 // minWinWidth = 400; minWinHeight = 300; // sets the minimum allowable window size.
 //
 // If your web host sticks banner ads at the top of every page you load, you could always
 // declare 'padTop' to be slightly negative... don't say you heard it from me... :)


 // Next we can assign scroller events. They are 'onbeforeload', 'onload', 'onscroll', 'onsetup',
 // 'onthumbdown' and 'onthumbup'. The load events fire whenever a file is loaded into the
 // scroller, and the thumb events whenever you start or stop dragging the thumb. The scroll
 // event fires when you scroll or drag, and the setup event fires when the scroller is
 // initialised but hasn't loaded its first file. By default, the only one you need is a function
 // to show the scroller once it's finished loading a file, and hide the 'loading' message:
 
 onload = loadFunction; 
}

// Here's the example onload function -- note it is a property of the scroller and hence we use
// 'with (this)' to get at its other properties. You can just leave this alone, or you can dig
// into the source code and make other functions to show/hide loading messages, light up the
// scroller thumb as it is being dragged, use the onload to build a browsable history etc...

function loadFunction() { with (this)
{
 // Hide loading message...
 getSty('loadMessage').visibility = 'hidden';
 // And show the rest of the divs. You could modify this function to do the reverse on the
 // 'onbeforeload' event, if you so desired...
 for (var i = 0; i < divs.length; i++) divs[i][5].vis('visible');
}}



// Capture events -- make sure you combine this with any other scripts which also capture these
// events e.g. Popup Menus. You call the setup function onload with the name of a default file,
// in this case it's readme, but you'll probably want something like "home.html". Alternatively,
// you can pass a blank string "" to scroll the content already in the div, but you must manually
// specify a width on the div below via style="width: xyz" for Netscape 4.
// Note we also call a small 'bug check' function to stop Netscape 4 dying when you resize the window.

window.onload = new Function('createMenus(); mainDiv.setup("home.html");');
window.onresize = new Function('ns4BugCheck(); mainDiv.layout()');

var origWinWidth = window.innerWidth;
function ns4BugCheck()
{
 if (isNS4 && origWinWidth != window.innerWidth)
 {
  // NS4 cannot handle resizes, so reload -- but use URL query mechanism to keep the loaded file.
  var fileName = location.href;

  // Trim existing URL query string out of the current location, if any.
  if (fileName.indexOf('?') != -1) fileName = fileName.substring(0, fileName.indexOf('?'));
  // If you've got multiple scrollers, add the URLs of each and separate with '&' signs.
  location.href = fileName + '?mainDiv=' + mainDiv.loadedFile;
 }
}



// Once it's loaded, there are several handy functions you can use in the body of your page or in
// some custom script, illustrated in the example below. Syntaxes:
//
//mainDiv.load('home.html');
// mainDiv.scrollBy(20); mainDiv.scrollTo(100);

//open("http://www.tier1host.net/special.html","special","menubar=no, status=no, scrollbars=no, resizable=no, width=216, height=216, location=no, directories=no");

// End Hide -->


