/******************************************************/
/* Summary:                                           */
/* --------                                           */
/*                                                    */
/* Browser(): Detect browser                          */
/* positionFooter: put the footer navigation right at */
/* the bottom of the page, on loading and resizing.   */
/*                                                    */
/******************************************************/




/******************************
 Prototyping for legacy support 
 ******************************/
if (typeof Array.prototype.push == "undefined") {
  Array.prototype.push = function(str) {
    this[this.length] = str;
  }
}



var current_browser = new Browser();
var posX = 0;
var posY = 0;
var timerID = null;
var timerRunning = false;
var explanationElement = null;
document.onclick = getEventXandY;
if (document.captureEvents) document.captureEvents(Event.CLICK);



// FUNCTION: detects the browser for use in later functions.
//
function Browser() 
{
  var ua, s, i;

  this.isIE    = false;  // Internet Explorer
  this.isNS    = false;  // Netscape
  this.version = null;

  ua = navigator.userAgent;

  s = "MSIE";
  if ((i = ua.indexOf(s)) >= 0) 
  {
    this.isIE = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  s = "Netscape6/";
  if ((i = ua.indexOf(s)) >= 0) 
  {
    this.isNS = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  s = "Opera/";
  if ((i = ua.indexOf(s)) >= 0) 
  {
    this.isNS = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  // Treat any other "Gecko" browser as NS 6.1.

  s = "Gecko";
  if ((i = ua.indexOf(s)) >= 0) 
  {
    this.isNS = true;
    this.version = 6.1;
    return;
  }
}



/***********************************/
/* FUNCTION DEFINITIIONS FOLLOW... */
/***********************************/

function standardInit() {
  // calls all the standard preparatory functions.
  
  setLayout();
  setLinkTargets();
}


function getSections() {
  sections = new Array();

  sections[0] = document.getElementById('main-banner');
  sections[1] = document.getElementById('main-left');
  sections[2] = document.getElementById('main-right');
  sections[3] = document.getElementById('main-background');
  sections[4] = document.getElementById('main-content');
  sections[5] = document.getElementById('main-footer');

  return sections;
}

function resetSectionHeights(s) {
  for(var i in s) {
    if(typeof(s[i]) == "object" && s[i] != null) {
      s[i].style.height = "auto";
    }
  }
}

function redrawLayout() {
  resetSectionHeights(getSections());
  setLayout();
}

function setLayout() { 
  if (current_browser.version > 5) {

    sections = getSections();

    // get lowest content base to use for footer positioning.
    footerHeight = sections[5].offsetHeight;
    contentBase = getContentBasePosition(sections);
    pageBottom = getBottomOfPage() - footerHeight;

    if(1 && (footerHeight < (pageBottom - contentBase))) {
      footerPositionX = pageBottom;
    }
    else {
      footerPositionX = contentBase;
    }

    // Position the main-footer and set #page element to surround all...
    positionElement(sections[5], footerPositionX, null);
    resizePageElement(footerPositionX);
    sections[5].style.visibility = 'visible';

    if(1) {
      var contentSections = new Array(sections[1],sections[2],sections[3]);      
      setContentToMeetFooter(footerPositionX, contentSections);
      setMainContentToMeetFooter(footerPositionX);
    }
  }

}

function resizePageElement(contentLength) {
  // Function does as name suggests and sets the 
  // (div)#page to greatest length if shorter.
  pageFrame = document.getElementById("page");
  footer = document.getElementById("main-footer");
  if(pageFrame && footer) {
    pageFrame.style.height = contentLength + footer.offsetHeight + "px";
  }
}

function positionElement(element, x, y) {
  //  position and element using css values.

  var pos; 
  if(element != null) {
    element.style.position = "absolute";
    if(x != null){
      pos = x + "px";
      element.style.top = pos;
    }

    if(y != null){
      pos = y+"px";
      element.style.left = pos;
    }
    element.style.display = "block";
  }
}


function getBottomOfPage() {
  // Return the height of the div#page element 
  // Unlike previous methods, this is only a few 
  // pixels difference between IE & Firefox. 

  var holder = document.getElementById('page');
  var height = holder.offsetHeight;  

  // DEBUGGING section
  //alert("page height = " + holder.offsetHeight);

  return height;
}


function getElementTop(element) {
  // return the top position of an element.

  var top;
  if(element != null)
    top = element.offsetTop;
  else
    top = 0;

  return top;
}


function getContentBasePosition(contentSection) {
  // return the lowest base position of content.

  var contentBase, currentSectionBase;
var temp
  contentBase = 0;
  for (n=0; n < contentSection.length; n++) {
    if(contentSection[n] != null) {
      currentSectionBase = contentSection[n].offsetHeight + contentSection[n].offsetTop;
      if ((currentSectionBase > contentBase) && (contentSection[n].id != "main-footer") && (contentSection[n].id != "main-background")) {
temp = contentSection[n];
        contentBase = currentSectionBase;
      }
    }
  }

  return contentBase;
}


function setElementHeight(element, value) {
  // NOTE: padding-top on the elements needs to be zero or the length can 
  // work out to be increased by the padding amount, thus giving an 
  // unexpected result.

  var elTop, height;

  if(element != null) {
    elTop = element.offsetTop;
    height = value - elTop;
    element.style.height = height + "px";
  }
}

function setContentToMeetFooter(fPosX, changeElements) {
  // Function sets the length of changeElements to 
  // meet with the top of the fPosX section.
  // Note: Due to padding in main-content, need to 
  // handle separately (use setMainContentToMeetFooter()).

  var contentBase = fPosX;
  for(n = 0; n < changeElements.length; n++) {
    if(changeElements[n] != null) {
      setElementHeight(changeElements[n], contentBase);
    }
  }

}

function setMainContentToMeetFooter(fPosX) {
  // Function sets the length of main-content to 
  // meet with the top of the fPosX section.

  var contentBase = fPosX;
  var mainContentChildren = sections[4].childNodes;
  for(var index in mainContentChildren){
    firstContent = mainContentChildren[index];
    // Check for first visible element (ie:  content-header, not the 'skip' anchor).
    if(firstContent.nodeType == 1 && firstContent.name != 'skip')
      break;
  }
  setElementHeight(sections[4], contentBase - firstContent.offsetTop);
}

function setElementsToSameHeight(parent, className) {
  var elementArea = document.getElementById(parent);
  if(elementArea) {
    var elements = getSubElementsByClass(elementArea, className);
    var maxElementHeight = getMaximumHeight(elements);
    for(var i in elements) {
      elements[i].style.height = maxElementHeight + "px";
    }
  }
}

function setLinkTargets() {
  // Function looks through all links on a page and adds
  // correct target location, depending on whether the 
  // link is internal or external.
  var link;
  var domain = document.domain;

  for(var i in document.links) {
    link = document.links[i];

    // Internet Explorer throws up a link that doesn't have
    // .hostname, which causes an error.       
    if(link.hostname){

      // Set the target based on domain matching.
      if(link.target == "") {
        if(link.hostname != domain) {
          link.target = "_blank";
        }
        else {
         link.target = "_self";
        }
      }
    }
  }
}

function resizePageElement(contentLength) { 	 
  // Function does as name suggests and sets the 	 
  // (div)#page to greatest length if shorter. 	 
  pageFrame = document.getElementById("page"); 	 
  footer = document.getElementById("main-footer"); 	 
  if(pageFrame && footer) { 	 
    pageFrame.style.height = contentLength + footer.offsetHeight + "px"; 	 
  }
}

function childElementsToMyHeight(me, childClass) {
  var myHeight = me.offsetHeight;
  var children = getSubElementsByClass(me, childClass);
//alert("myHeight : " + myHeight + "\n" +
//      "children : " + children);
  setPixelHeights(children, myHeight);
}

function getSubElement(element) {
  var subElement = element;
  var children = element.childNodes;
  for(var i in children) {
    child = children[i];
    if(child.nodeType == 1){
      subElement = child;
      break;
    }
  }
  return subElement;
}

function getSubElements(element) {
  var subElements = new Array();
  var children = element.childNodes;
  var count = 0;
  for(var i in children) {
    child = children[i];
    if(child.nodeType == 1) {
      subElements[count] = child;
      count++;
    }
  }
  return subElements;
}

function getSubElementByClass(element, classname) {
  var elementByClass = null;
  if(element) {
    var children = element.childNodes;
    for(var i in children) {
      if(children[i].nodeType == 1) {
        if(children[i].className.indexOf(classname) >= 0) {
          elementByClass = children[i];
          break;
        }
      }
    }
  }
  return elementByClass;
}

function getSubElementsByClass(element, classname) {
  var children = element.childNodes;
  var elementsByClass = new Array();
  var index = 0;
  for(var i in children) {
    if(children[i].nodeType == 1) {
      if(children[i].className.indexOf(classname) >= 0) {
        elementsByClass[index] = children[i];
        index++;
      }
    }
  }
  return elementsByClass;
}

function setPixelHeights(elements, height) {
  for(var i in elements) {
    if(typeof(elements[i]) == "object" && elements[i] != null) {
      elements[i].style.height = height + "px";
    }
  }
}

function getMaximumHeight(elements) {
  var max = 0;
  for(var i in elements) {
    if(elements[i]) {
      if(elements[i].offsetHeight > max) {
        max = elements[i].offsetHeight;
      }
    }
  }
  return max;
}

function verticalAlign (frame, element) {  
  var frameHeight = frame.offsetHeight;
  var elementHeight = element.offsetHeight;
  var difference = frameHeight - elementHeight;
  if(difference > 1) {
    offset = difference / 2;
    element.style.marginTop = offset + "px";
  }
}

function addCrossBrowserEvent(element, event, method, bubble) {
  // Two event names can be passed to cope with IE differences.
  var eventName = event[0];

  if(bubble == null) {
    bubble = false;
  }
  if(element.addEventListener) {
    element.addEventListener(eventName, method, bubble); 
  }
  else {
    if(event.length > 1) {
      eventName = event[1];
    }
    element.attachEvent(eventName, method);
  }
}
    
 addEvent(window, "load", sortables_init);

var SORT_COLUMN_INDEX;

function sortables_init() {
    // Find all tables with class sortable and make them sortable
    if (!document.getElementsByTagName) return;
    tbls = document.getElementsByTagName("table");
    for (ti=0;ti<tbls.length;ti++) {
        thisTbl = tbls[ti];
        if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) {
            //initTable(thisTbl.id);
            ts_makeSortable(thisTbl);
        }
    }
}

function ts_makeSortable(table) {
    if (table.rows && table.rows.length > 0) {
        var firstRow = table.rows[0];
    }
    if (!firstRow) return;
    
    // We have a first row: assume it's the header, and make its contents clickable links
    for (var i=0;i<firstRow.cells.length;i++) {
        var cell = firstRow.cells[i];
        var txt = ts_getInnerText(cell);
        cell.innerHTML = '<a href="#" class="sortheader" onclick="ts_resortTable(this);return false;">'+txt+'<span class="sortarrow">&nbsp;&nbsp;&nbsp;</span></a>';
    }
        if (cell.getAttribute("initialkey")) {
          ts_resortTable(cell.getElementsByTagName("a")[0]);
        }
}

function ts_getInnerText(el) {
	if (typeof el == "string") return el;
	if (typeof el == "undefined") { return el };
	if (el.innerText) return el.innerText;	//Not needed but it is faster
	var str = "";
	
	var cs = el.childNodes;
	var l = cs.length;
	for (var i = 0; i < l; i++) {
		switch (cs[i].nodeType) {
			case 1: //ELEMENT_NODE
				str += ts_getInnerText(cs[i]);
				break;
			case 3:	//TEXT_NODE
				str += cs[i].nodeValue;
				break;
		}
	}
	return str;
}

function ts_resortTable(lnk) {
    // get the span
    var span;
    for (var ci=0;ci<lnk.childNodes.length;ci++) {
        if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
    }
    var spantext = ts_getInnerText(span);
    var td = lnk.parentNode;
    var column = td.cellIndex;
    var table = getParent(td,'TABLE');
    
    // Work out a type for the column
    if (table.rows.length <= 1) return;
    var itm = ts_getInnerText(table.rows[1].cells[column]);
    sortfn = ts_sort_caseinsensitive;
    if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) sortfn = ts_sort_date;
    if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) sortfn = ts_sort_date;
    if (itm.match(/^[£$]/)) sortfn = ts_sort_currency;
    if (itm.match(/^[\d\.]+$/)) sortfn = ts_sort_numeric;
    SORT_COLUMN_INDEX = column;
    var firstRow = new Array();
    var newRows = new Array();
    for (i=0;i<table.rows[0].length;i++) { firstRow[i] = table.rows[0][i]; }
    for (j=1;j<table.rows.length;j++) { newRows[j-1] = table.rows[j]; }

    newRows.sort(sortfn);

    if (span.getAttribute("sortdir") == 'down') {
        ARROW = '&nbsp;&nbsp;&uarr;';
        newRows.reverse();
        span.setAttribute('sortdir','up');
    } else {
        ARROW = '&nbsp;&nbsp;&darr;';
        span.setAttribute('sortdir','down');
    }
    
    // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
    // don't do sortbottom rows
    for (i=0;i<newRows.length;i++) { if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) table.tBodies[0].appendChild(newRows[i]);}
    // do sortbottom rows only
    for (i=0;i<newRows.length;i++) { if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) table.tBodies[0].appendChild(newRows[i]);}
    
    // Delete any other arrows there may be showing
    var allspans = document.getElementsByTagName("span");
    for (var ci=0;ci<allspans.length;ci++) {
        if (allspans[ci].className == 'sortarrow') {
            if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
                allspans[ci].innerHTML = '&nbsp;&nbsp;&nbsp;';
            }
        }
    }
        
    span.innerHTML = ARROW;
}

function getParent(el, pTagName) {
	if (el == null) return null;
	else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())	// Gecko bug, supposed to be uppercase
		return el;
	else
		return getParent(el.parentNode, pTagName);
}
function ts_sort_date(a,b) {
    // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa.length == 10) {
        dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
    } else {
        yr = aa.substr(6,2);
        if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
        dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
    }
    if (bb.length == 10) {
        dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
    } else {
        yr = bb.substr(6,2);
        if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
        dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
    }
    if (dt1==dt2) return 0;
    if (dt1<dt2) return -1;
    return 1;
}

function ts_sort_currency(a,b) { 
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
    return parseFloat(aa) - parseFloat(bb);
}

function ts_sort_numeric(a,b) { 
    aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
    if (isNaN(aa)) aa = 0;
    bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX])); 
    if (isNaN(bb)) bb = 0;
    return aa-bb;
}

function ts_sort_caseinsensitive(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    if (aa==bb) return 0;
    if (aa<bb) return -1;
    return 1;
}

function ts_sort_default(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa==bb) return 0;
    if (aa<bb) return -1;
    return 1;
}


function addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+,  NS6 and Mozilla
// By Scott Andrew
{
  if (elm.addEventListener){
    elm.addEventListener(evType, fn, useCapture);
    return true;
  } else if (elm.attachEvent){
    var r = elm.attachEvent("on"+evType, fn);
    return r;
  } else {
//    alert("Handler could not be removed");
  }
} 




/*******************************
 Accessibility baseFontSizing...
 *******************************/
SIZE_UP_MSG = "text size";
SIZE_DOWN_MSG = "text size";
function displayFontSwitch() {
  document.write("<span id=\"font-switch\" \n");
  document.write("       class=\"button\"\n");
  document.write("       onclick=\"switchFontSize(this)\">\n");
  if(getCookie("baseFontSize") > 0) {
    document.write(SIZE_DOWN_MSG);
  }
  else {
    document.write(SIZE_UP_MSG);
  }
  document.write("</span>");
}

function switchFontSize(element) {
  var fcv = null;
  if(Number(getCookie("baseFontSize"))) {
    fcv = 0;
    element.firstChild.nodeValue = SIZE_UP_MSG;
  }
  else {
    fcv = 1;
    element.firstChild.nodeValue = SIZE_DOWN_MSG;
  }
  setCookie("baseFontSize", fcv, null, "/");
  setBaseFontSize(fcv);
  redrawLayout();
}

function setBaseFontSize() {
  var availableSizes = new Array ();
      availableSizes.push(90);
      availableSizes.push(110);
    fcv = getCookie("baseFontSize");
  if(!fcv) {
    fcv = 0;
  }
  document.body.style.fontSize = availableSizes[fcv] + "%";
}


/*****************************
 General function for wide use
 *****************************/
function monthAsWord(m) {
  switch(m) {
    case  0: month = "January";
             break;
    case  1: month = "February";
             break;
    case  2: month = "March";
             break;
    case  3: month = "April";
             break;
    case  4: month = "May";
             break;
    case  5: month = "June";
             break;
    case  6: month = "July";
             break;
    case  7: month = "August";
             break;
    case  8: month = "September";
             break;
    case  9: month = "October";
             break;
    case 10: month = "November";
             break;
    case 11: month = "December";
             break;
    default: month = m;
  }
  return month;
}


/*
function getCookie(name) {
  value = null;
  cookies = document.cookie.split(";");

  for(var i in cookies) {
    cookie = String(cookies[i]).split("=");
    if(cookie[0].replace(" ", "") == name) {
      value = cookie[1];
      break;
    }
  }
  return value;
}
*/

// name - name of the desired cookie
// * return string containing value of specified cookie or null if cookie does not exist
function getCookie(name) {
  var dc = document.cookie;
  var prefix = name + "=";
  var begin = dc.indexOf("; " + prefix);
  
  if (begin == -1) {
    begin = dc.indexOf(prefix);
    if (begin != 0) return null;
  } else
    begin += 2;
  var end = document.cookie.indexOf(";", begin);
  if (end == -1)
    end = dc.length;
  
  return unescape(dc.substring(begin + prefix.length, end));
}


function setCookie(name, value, expires, path, domain, secure) {
  var curCookie = name + "=" + escape(value) +
      ((expires) ? "; expires=" + expires.toGMTString() : "") +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "") +
      ((secure) ? "; secure" : "");
  document.cookie = curCookie;
}

function addEventToElement(el, ev, fun) {
  if(document.addEventListener) {
    if(ev.substr(0,2).toLowerCase() == "on") { 
      ev = ev.substr(2);
    }
    el.addEventListener(ev, fun, "false");
  }
  else {
    el.attachEvent(ev, fun);
  }
}

// Used in forms submission... 
function onlySubmitOnce() {
 if (this.submitted) {
   return false;
 } else {
   this.submitted=true;
   return true;
 }
}

function highlightLink(element, componentClass, location) {
  var currentClass = element.className;
  var activeClass = " " + componentClass + "Active";
  if(element && currentClass) {
    element.className = currentClass + activeClass;
    self.status = location;
  }
}

function unhighlightLink(element, componentClass) {
  var currentClass = element.className;
  var activeClass = " " + componentClass + "Active";
  if(element && currentClass) { 
    element.className = currentClass.replace(activeClass, "");
    self.status = "";
  }
}

function getStyleValue(el, prop) {
  var styleValue = null;
  if(el.currentStyle) {
    styleValue = el.currentStyle[prop];
  }
  else {
    if(window.getComputedStyle) {
      styleValue = document.defaultView.getComputedStyle(el, null).getPropertyValue(prop);
    }
  }
  return styleValue;
}



/******************************************************************************/
/* FOLLOWING IS EXPERIMENTAL FUNCTIONALITY FOR DISPLAY/TESTING PURPOSES ONLY. */
/******************************************************************************/
// The following two function are used for displaying help boxes in management pages.
function showHelp(link,element) {
  helpElement = document.getElementById(element);
  helpElement.style.display = "block";
  if(link.offsetLeft)
    helpElement.style.left = link.offsetLeft;
  helpElement.style.position = "absolute";
  if(link.offsetTop)
    helpElement.style.top = link.offsetTop;
}
 
function hideHelp(element) {
  helpElement = document.getElementById(element);
  helpElement.style.display = "none";
}

// Function display a small pop-up with a definiation of the highlighted terminology.
function explanation(keyword, temptext) {
  if(explanationElement) {
    // Close any existing explanations.
    closeExplanation();
  }
  body = document.getElementsByTagName("body")[0]
  explanationP = document.createElement("p");
  // Look up the text based on the keyword here...
  // For now (and demo purposes), use the temptext value.
  explanationText = document.createTextNode(temptext);

  closeLink = document.createElement("a");
  closeLink.href = "javascript:closeExplanation();";
  img = document.createElement("img");
  img.alt = "close";
  img.src = "/images/icon_close.gif";
  img.style.display = "block";
  img.style.cssFloat = "right";
  
  boxWidth = 300;
 
  body.appendChild(explanationP);
  explanationP.appendChild(explanationText);
  closeLink.appendChild(img);
  explanationP.appendChild(closeLink);
  explanationElement = explanationP;

  if ((body.clientWidth - posX) < boxWidth) {
    // This will be functionality to make sure it fits on screen...
    alert("smaller");
  }
  explanationP.className = "explanation";
  explanationP.style.left = posX + "px";
  explanationP.style.position = "absolute";
  explanationP.style.top = posY + "px";
  explanationP.style.width = boxWidth + "px";
  explanationP.style.zIndex = "5000";
}

function closeExplanation() {
  document.body.removeChild(explanationElement);
  explanationElement = null;
}

function stopTimer() {
  // Currently not in use - possible final function would be
  // as part of a timeout for displaying explanations...
  if (timerRunning) {
    window.clearTimeout(timerID); 
    timerRunning = false;
  }
}



var eventPosX = 0;
var eventPosY = 0;
function getEventXandY(e)
{
  var xy = new Array(2);
	if (!e) var e = window.event;

	if (e.pageX || e.pageY)
	{
		eventPosX = e.pageX;
		eventPosY = e.pageY;
	}
	else if (e.clientX || e.clientY)
	{
		eventPosX = e.clientX + document.body.scrollLeft;
		eventPosY = e.clientY + document.body.scrollTop;
	}
//  alert("posX = " + eventPosX + "\n" +
//        "posY = " + eventPosY);
  xy[0] = eventPosX;
  xy[1] = eventPosY;
  return xy;
}
