/***************************************************************************
*                      THINK BEYOND - ADAPTIVE SOLUTIONS.
*             			webmaster@jarman.org.uk
*
*                       Client: AngloEnterprises.co.uk
*                        Copyright: Dave Jarman 2009
*
****************************************************************************
*
* Module Name: common.js
* Author     : Dave Jarman.
*
* Edit Record.
* Date          By     Comment
* ---------	    ---    ----------------------------------------------------
* 14-Sep-09	    DCJ    New Template
*
****************************************************************************
Description:


***************************************************************************/


function Common_OnLoad()
{
	$(document).ready(function(){
	  /* Configuration object - change classes, IDs and string here */
	  var config = {
	  /* CSS classes that get applied dynamically */
	    javascriptenabled:'js',
	    show:'show_on'
	  }
	
	  /* functionality starts here */
	  $('.faq').addClass(config.javascriptenabled);
	  var current = null;
	  $('.faq_q').click(function(e){
	    if(current){
	      current.removeClass(config.show);
	    }
	    current = $(this).next().addClass(config.show);
	    
	  })
	});

}



function MakeFullScreen()
{
	self.moveTo(-1,-1);
	self.resizeTo(screen.availWidth+2,screen.availHeight+2);
}

function CalcFrameHeight()
{
 var viewportwidth;
 var viewportheight;
 
 // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
 
 if (typeof window.innerWidth != 'undefined')
 {
      viewportwidth = window.innerWidth,
      viewportheight = window.innerHeight
 }
 
// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)

 else if (typeof document.documentElement != 'undefined'
     && typeof document.documentElement.clientWidth !=
     'undefined' && document.documentElement.clientWidth != 0)
 {
       viewportwidth = document.documentElement.clientWidth,
       viewportheight = document.documentElement.clientHeight
 }
 
 // older versions of IE
 
 else
 {
       viewportwidth = document.getElementsByTagName('body')[0].clientWidth,
       viewportheight = document.getElementsByTagName('body')[0].clientHeight
 }

	clientHeight = viewportheight - 38 - 103;

	Obj = document.getElementById( "content_pane" );
	if ( Obj != null )
		Obj.style.height = clientHeight + "px";
	Obj = document.getElementById( "content_pane_wide" );
	if ( Obj != null )
		Obj.style.height = clientHeight + "px";
	Obj = document.getElementById( "page_right" );
	if ( Obj != null )
		Obj.style.height = (viewportheight - 103) + "px";
	Obj = document.getElementById( "side_menu" );
	if ( Obj != null )
		Obj.style.height = clientHeight + "px";
}


var SubmitImg = null;
function CommonGetForm( Id, Url )
{
	SubmitImg = document.getElementById( "free_loading" );
	if ( SubmitImg != null )
	{
		var Pos;
	    Pos = $("#" + Id ).find(":image, :submit").offset();

		SubmitImg.style.position = 'absolute';
		SubmitImg.style.left = (Pos.left - 32) + "px";
		SubmitImg.style.top = Pos.top + "px";
		SubmitImg.style.display = 'block';
	}

  	AJAX_OnLoadEvent = HideSubmitObj;	
	AJAX_GetForm( Id, Url );
}

function HideSubmitObj( ) 
{
	if ( SubmitImg != null )
	{
		SubmitImg.style.display = 'none';
	}
}

function ShowDivision( Id )
{
    var ObjId = document.getElementById( Id );
	if ( ObjId != null )
	{
		if ( ObjId.tagName == "SPAN" )
			ObjId.style.display = 'inline';
		else
			ObjId.style.display = 'block';
	}
}

function HideDivision( Id )
{
  ObjId = document.getElementById( Id );
	if ( ObjId != null )
	{
		ObjId.style.display = 'none';
	}
}


function InvisDivision( Id )
{
  ObjId = document.getElementById( Id );
	if ( ObjId != null )
	{
		ObjId.style.visibility = 'hidden';
	}
}


function VisibleDivision( Id )
{
  ObjId = document.getElementById( Id );
	if ( ObjId != null )
	{
		ObjId.style.visibility = 'visible';
	}
}

function ToggleVisibleDivision( Id )
{
    ObjId = document.getElementById( Id );
	if ( ObjId != null )
	{
	    if ( ( ObjId.style.visibility == '' ) || 
	         ( ObjId.style.visibility == 'visible' ) ) 
  			ObjId.style.visibility = 'hidden';
  		else
  			ObjId.style.visibility = 'visible';
	}
}

function ChgQty( ObjId, Delta )
{
	var Obj = document.getElementById( ObjId );
	if ( Obj == null )
	  	return; 
	var Val = parseInt( Obj.value, 10 );
	if ( ( Val == NaN ) || ( Val <= 0 ) || ( Val > 9999 ) )
		Obj.value = '1';
	else
	{
		if ( Val + Delta < 1 )
			Obj.value = '1';
		else if ( Val + Delta > 9999 )
			Obj.value = '9999';
		else
			Obj.value = Val + Delta;
	} 
}

var CsUserName = new String( "" );
var CsUserEmail = new String( "" );
var CsUserPwd = new String( "" );
var expdate = new Date();

function GetGlobalData()
{
  // Set cookie to expire in 2 years
  //
  // 1000 milliseconds  (milliseconds per second)
  // * 60 milliseconds  (seconds per minute)
  // * 60 milliseconds  (minutes per hour)
  // * 24 milliseconds  (hours per day)
  // * 730 milliseconds  (days)
  // -----------------
  // = 730 days
  //
  expdate.setTime (expdate.getTime() + (1000*60*60*24*730));
  DelLim = "$";

  // Cookie does not exist processing
  if(getCookie("_CrazySand") == null)
  {
    // No cookie, default
    CsUserName = "";
    CsUserEmail = "";
		CsUserPwd = "";
  	SaveData = CsUserName + DelLim + CsUserEmail + DelLim + CsUserPwd + DelLim + "*";
  	setCookie("_CrazySand", SaveData, expdate);
  }

  // Cookie exists processing
  else
  {
  	SaveData = getCookie("_CrazySand");
  	EndIndex = SaveData.indexOf( DelLim );
  	CsUserName = SaveData.substring(0,EndIndex);

  	StartIndex = EndIndex + 1;
  	EndIndex = SaveData.indexOf( DelLim, StartIndex );
  	CsUserEmail = SaveData.substring(StartIndex,EndIndex);

  	StartIndex = EndIndex + 1;
  	EndIndex = SaveData.indexOf( DelLim, StartIndex );
  	CsUserPwd = SaveData.substring(StartIndex,EndIndex);

  }
}


function SetGlobalData()
{
  expdate.setTime (expdate.getTime() + (1000*60*60*24*10));
  DelLim = "$";
  SaveData = CsUserName + DelLim + CsUserEmail + DelLim + CsUserPwd + DelLim + "*";
  setCookie("_CrazySand", SaveData, expdate);
}

function DelGlobalData()
{
  delCookie("_CrazySand");
  location.reload();
}

function DelCookieButton()
{
  if ( ( CsUserName ) && ( CsUserName != "" ) )
  {
    document.write( "<center>" );
    document.write( "<button onclick='DelGlobalData();'>I am not " + CsUserName + "</button>" );
    document.write( "</center>" );
  }
}

var Cards = new makeArray(8);
Cards[0] = new CardType("MasterCard", "51,52,53,54,55", "16");
var MasterCard = Cards[0];
Cards[1] = new CardType("VisaCard", "4", "13,16");
var VisaCard = Cards[1];
Cards[2] = new CardType("AmExCard", "34,37", "15");
var AmExCard = Cards[2];
Cards[3] = new CardType("DinersClubCard", "30,36,38", "14");
var DinersClubCard = Cards[3];
Cards[4] = new CardType("DiscoverCard", "6011", "16");
var DiscoverCard = Cards[4];
Cards[5] = new CardType("enRouteCard", "2014,2149", "15");
var enRouteCard = Cards[5];
Cards[6] = new CardType("JCBCard", "3088,3096,3112,3158,3337,3528", "16");
var JCBCard = Cards[6];
var LuhnCheckSum = Cards[7] = new CardType();

/*************************************************************************\
CheckCardNumber(form)
function called when users click the "check" button.
\*************************************************************************/
function CheckCardNumber(form) {
  var tmpyear;
  if (form.CardNumber.value.length == 0) {
    alert("Please enter a Card Number.");
    form.CardNumber.focus();
    return false;
  }
  if (form.ExpYear.value.length == 0) {
    alert("Please enter the Expiration Year.");
    form.ExpYear.focus();
    return false;
  }
  if (form.ExpYear.value.length == 1) {
    form.ExpYear.value = '0' + form.ExpYear.value;
  }
  if (form.ExpYear.value > 96)
    tmpyear = "19" + form.ExpYear.value;
  else if (form.ExpYear.value < 21)
    tmpyear = "20" + form.ExpYear.value;
  else {
    alert("The Expiration Year is not valid.");
    return false;
  }
  tmpmonth = form.ExpMon.options[form.ExpMon.selectedIndex].value;
  // The following line doesn't work in IE3, you need to change it
  // to something like "(new CardType())...".
  // if (!CardType().isExpiryDate(tmpyear, tmpmonth)) {
  if (!(new CardType()).isExpiryDate(tmpyear, tmpmonth)) {
    alert("This card has already expired.");
    return  false;
  }
  card = form.CardType.options[form.CardType.selectedIndex].value;
  var retval = eval(card + ".checkCardNumber(\"" + form.CardNumber.value + "\", " + tmpyear + ", " + tmpmonth + ");");
  cardname = "";
  if (!retval)
  {
    // The cardnumber has the valid luhn checksum, but we want to know which
    // cardtype it belongs to.
    for (var n = 0; n < Cards.size; n++) {
      if (Cards[n].checkCardNumber(form.CardNumber.value, tmpyear, tmpmonth)) {
        cardname = Cards[n].getCardType();
        break;
      }
    }
    if (cardname.length > 0) {
      alert("This looks like a " + cardname + " number, not a " + card + " number.");
    }
    else {
      alert("This card number is not valid.");
    }
  }
  return retval;
}
/*************************************************************************\
Object CardType([String cardtype, String rules, String len, int year,
int month])
cardtype    : type of card, eg: MasterCard, Visa, etc.
rules       : rules of the cardnumber, eg: "4", "6011", "34,37".
len         : valid length of cardnumber, eg: "16,19", "13,16".
year        : year of expiry date.
month       : month of expiry date.
eg:
var VisaCard = new CardType("Visa", "4", "16");
var AmExCard = new CardType("AmEx", "34,37", "15");
\*************************************************************************/
function CardType() {
  var n;
  var argv = CardType.arguments;
  var argc = CardType.arguments.length;
  
  this.objname = "object CardType";
  
  var tmpcardtype = (argc > 0) ? argv[0] : "Unknown Card";
  var tmprules = (argc > 1) ? argv[1] : "0,1,2,3,4,5,6,7,8,9";
  var tmplen = (argc > 2) ? argv[2] : "13,14,15,16,19";
  
  this.setCardNumber = setCardNumber;  // set CardNumber method.
  this.setCardType = setCardType;  // setCardType method.
  this.setLen = setLen;  // setLen method.
  this.setRules = setRules;  // setRules method.
  this.setExpiryDate = setExpiryDate;  // setExpiryDate method.
  
  this.setCardType(tmpcardtype);
  this.setLen(tmplen);
  this.setRules(tmprules);
  if (argc > 4)
    this.setExpiryDate(argv[3], argv[4]);
  
  this.checkCardNumber = checkCardNumber;  // checkCardNumber method.
  this.getExpiryDate = getExpiryDate;  // getExpiryDate method.
  this.getCardType = getCardType;  // getCardType method.
  this.isCardNumber = isCardNumber;  // isCardNumber method.
  this.isExpiryDate = isExpiryDate;  // isExpiryDate method.
  this.luhnCheck = luhnCheck;// luhnCheck method.
  return this;
}

/*************************************************************************\
boolean checkCardNumber([String cardnumber, int year, int month])
return true if cardnumber pass the luhncheck and the expiry date is
valid, else return false.
\*************************************************************************/
function checkCardNumber() {
  var argv = checkCardNumber.arguments;
  var argc = checkCardNumber.arguments.length;
  var cardnumber = (argc > 0) ? argv[0] : this.cardnumber;
  var year = (argc > 1) ? argv[1] : this.year;
  var month = (argc > 2) ? argv[2] : this.month;
  
  this.setCardNumber(cardnumber);
  this.setExpiryDate(year, month);
  
  if (!this.isCardNumber())
    return false;
  if (!this.isExpiryDate())
    return false;
  
  return true;
}
/*************************************************************************\
String getCardType()
return the cardtype.
\*************************************************************************/
function getCardType() {
  return this.cardtype;
}
/*************************************************************************\
String getExpiryDate()
return the expiry date.
\*************************************************************************/
function getExpiryDate() {
  return this.month + "/" + this.year;
}
/*************************************************************************\
boolean isCardNumber([String cardnumber])
return true if cardnumber pass the luhncheck and the rules, else return
false.
\*************************************************************************/
function isCardNumber() {
  var argv = isCardNumber.arguments;
  var argc = isCardNumber.arguments.length;
  var cardnumber = (argc > 0) ? argv[0] : this.cardnumber;
  if (!this.luhnCheck())
    return false;
  
  for (var n = 0; n < this.len.size; n++)
    if (cardnumber.toString().length == this.len[n]) {
      for (var m = 0; m < this.rules.size; m++) {
        var headdigit = cardnumber.substring(0, this.rules[m].toString().length);
        if (headdigit == this.rules[m])
          return true;
      }
      return false;
    }
    return false;
}

/*************************************************************************\
boolean isExpiryDate([int year, int month])
return true if the date is a valid expiry date,
else return false.
\*************************************************************************/
function isExpiryDate() {
  var argv = isExpiryDate.arguments;
  var argc = isExpiryDate.arguments.length;
  
  year = argc > 0 ? argv[0] : this.year;
  month = argc > 1 ? argv[1] : this.month;
  
  if (!isNum(year+""))
    return false;
  if (!isNum(month+""))
    return false;
  today = new Date();
  expiry = new Date(year, month);
  if (today.getTime() > expiry.getTime())
    return false;
  else
    return true;
}

/*************************************************************************\
boolean isNum(String argvalue)
return true if argvalue contains only numeric characters,
else return false.
\*************************************************************************/
function isNum(argvalue) {
  argvalue = argvalue.toString();
  
  if (argvalue.length == 0)
    return false;
  
  for (var n = 0; n < argvalue.length; n++)
    if (argvalue.substring(n, n+1) < "0" || argvalue.substring(n, n+1) > "9")
      return false;
    
    return true;
}

/*************************************************************************\
boolean luhnCheck([String CardNumber])
return true if CardNumber pass the luhn check else return false.
Reference: http://www.ling.nwu.edu/~sburke/pub/luhn_lib.pl
\*************************************************************************/
function luhnCheck() {
  var argv = luhnCheck.arguments;
  var argc = luhnCheck.arguments.length;
  
  var CardNumber = argc > 0 ? argv[0] : this.cardnumber;
  
  if (! isNum(CardNumber)) {
    return false;
  }
  
  var no_digit = CardNumber.length;
  var oddoeven = no_digit & 1;
  var sum = 0;
  
  for (var count = 0; count < no_digit; count++) {
    var digit = parseInt(CardNumber.charAt(count));
    if (!((count & 1) ^ oddoeven)) {
      digit *= 2;
      if (digit > 9)
        digit -= 9;
    }
    sum += digit;
  }
  if (sum % 10 == 0)
    return true;
  else
    return false;
}

/*************************************************************************\
ArrayObject makeArray(int size)
return the array object in the size specified.
\*************************************************************************/
function makeArray(size) {
  this.size = size;
  return this;
}

/*************************************************************************\
CardType setCardNumber(cardnumber)
return the CardType object.
\*************************************************************************/
function setCardNumber(cardnumber) {
  this.cardnumber = cardnumber;
  return this;
}

/*************************************************************************\
CardType setCardType(cardtype)
return the CardType object.
\*************************************************************************/
function setCardType(cardtype) {
  this.cardtype = cardtype;
  return this;
}

/*************************************************************************\
CardType setExpiryDate(year, month)
return the CardType object.
\*************************************************************************/
function setExpiryDate(year, month) {
  this.year = year;
  this.month = month;
  return this;
}

/*************************************************************************\
CardType setLen(len)
return the CardType object.
\*************************************************************************/
function setLen(len) {
  // Create the len array.
  if (len.length == 0 || len == null)
    len = "13,14,15,16,19";
  
  var tmplen = len;
  n = 1;
  while (tmplen.indexOf(",") != -1) {
    tmplen = tmplen.substring(tmplen.indexOf(",") + 1, tmplen.length);
    n++;
  }
  this.len = new makeArray(n);
  n = 0;
  while (len.indexOf(",") != -1) {
    var tmpstr = len.substring(0, len.indexOf(","));
    this.len[n] = tmpstr;
    len = len.substring(len.indexOf(",") + 1, len.length);
    n++;
  }
  this.len[n] = len;
  return this;
}

/*************************************************************************\
CardType setRules()
return the CardType object.
\*************************************************************************/
function setRules(rules) {
  // Create the rules array.
  if (rules.length == 0 || rules == null)
    rules = "0,1,2,3,4,5,6,7,8,9";
  
  var tmprules = rules;
  n = 1;
  while (tmprules.indexOf(",") != -1) {
    tmprules = tmprules.substring(tmprules.indexOf(",") + 1, tmprules.length);
    n++;
  }
  this.rules = new makeArray(n);
  n = 0;
  while (rules.indexOf(",") != -1) {
    var tmpstr = rules.substring(0, rules.indexOf(","));
    this.rules[n] = tmpstr;
    rules = rules.substring(rules.indexOf(",") + 1, rules.length);
    n++;
  }
  this.rules[n] = rules;
  return this;
}





function WriteCCN()
{

  document.write( '<tr><td align=right valign=center>Credit Card Number' );
  document.write( '<td><input name="CardNumber" size="16" maxlength="19">' );
  document.write( '<tr><td align=right valign=center>Card Type:<td>' );
  document.write( '<select name="CardType">' );
  document.write( '<option value="MasterCard">MasterCard' );
  document.write( '<option value="VisaCard">Visa' );
  document.write( '<option value="AmExCard">American Express' );
  document.write( '<option value="DinersClubCard">Diners Club' );
  document.write( '<option value="DiscoverCard">Discover' );
  document.write( '<option value="enRouteCard">enRoute' );
  document.write( '<option value="JCBCard">JCB' );
  document.write( '</select>' );

  document.write( '<tr><td align=right valign=center>Expiration Date: Month<td>' );
  document.write( '  <select name="ExpMon">' );
  document.write( '<option value="1" selected>1' );
  document.write( '<option value="2">2' );
  document.write( '<option value="3">3' );
  document.write( '<option value="4">4' );
  document.write( '<option value="5">5' );
  document.write( '<option value="6">6' );
  document.write( '<option value="7">7' );
  document.write( '<option value="8">8' );
  document.write( '<option value="9">9' );
  document.write( '<option value="10">10' );
  document.write( '<option value="11">11' );
  document.write( '<option value="12">12' );
  document.write( '</select>' );
  document.write( 'Year <input name="ExpYear" size="2" maxlength="2">(Range: 1997~2020)<br>' );
  document.write( '<tr>' );
}


function ValidateAddress( ObjId1, ObjId2, ObjId3, ObjId4, ObjId5 )
{
  Ok = true;
  var AddrObj = document.getElementById( ObjId1 );
  if ( AddrObj.value.trim().length == 0 )
  {	  
	  return "Address line 1 is too short";
	}
  if ( AddrObj.value.length > 50 )
  {	  
	  return "Address line 1 is too long. Please shorten or abbreviate it.";
	}
  var AddrObj2 = document.getElementById( ObjId2 );
  if ( AddrObj2.value.length > 50 )
	  return "Address line 2 is too long. Please shorten or abbreviate it.";
	
  var AddrObj3 = document.getElementById( ObjId3 );
  if ( AddrObj3.value.length > 50 )
	  return "Address line 3 is too long. Please shorten or abbreviate it.";
	
  var AddrObj4 = document.getElementById( ObjId4 );
  if ( AddrObj4.value.trim().length == 0 )
  {	  
	  return "Town / City is too short";
	}
  if ( AddrObj4.value.length > 50 )
  {	  
	  return "Town / City is too long. Please shorten or abbreviate it.";
	}

  var AddrObj5 = document.getElementById( ObjId5 );
  if ( AddrObj5.value.trim().length == 0 )
  {	  
	  return "County is too short";
	}
  if ( AddrObj5.value.length > 50 )
  {	  
	  return "County is too long. Please shorten or abbreviate it.";
	}
	
  return null;	
}

function ValidateName( ObjId )
{
  var NameObj = document.getElementById( ObjId );
  if ( NameObj.value.length < 3 )
  {	  
	  return "Name is too short.";
	}
  if ( NameObj.value.length > 50 )
  {	  
	  return "Full Name is too long. Please shorten or abbreviate it.";
	}
	
  return null;	
}

function ValidatePostcode( ObjId )
{
  Ok = true;
  var PostcodeObj = document.getElementById( ObjId );
  if ( PostcodeObj.value.length < 6 )
  {	  
	  return "Postcode is too short.";
	}
  if ( PostcodeObj.value.length > 11 )
  {	  
	  return "Postcode is too long.";
	}
  return null;	
}


function ValidatePhone( ObjId )
{
  Ok = true;
  var Phone = document.getElementById( ObjId );
  if ( Phone == null )
  	return null;
  if ( Phone.value.length < 6 )
  {	  
	  return "Please enter a valid phone number with dialing code, in case we need to query your order.";
  }
  if ( Phone.value.length > 50 )
	  return "Phone number is too long. Please enter a real phone number.";
	  
  return null;	
}


function ValidateForm( ErrorDiv )
{
  ErrObj = document.getElementById( ErrorDiv );
	ResultStr = ValidateName("billname");
  if ( ResultStr == null )
		ResultStr = ValidateAddress("billaddr1", "billaddr2", "billaddr3", "billaddr4", "billaddr5");
	if ( ResultStr == null )
		ResultStr = ValidatePostcode("billpostcode");
	if ( ResultStr == null )
		ResultStr = ValidatePhone("billtelephone");

	if ( ResultStr == null )
	{
	  HideDivision( ErrorDiv );
	  return true;
	}
	else
	{
	  ErrObj.innerHTML = "<span class='registration_error'>" + ResultStr + "</span>";
	  ShowDivision( ErrorDiv );
	}
		
  return false;
}

function ValidateSchoolForm( ErrorDiv )
{
	ErrObj = document.getElementById( ErrorDiv );
	
	ReturnPrefix = "School ";
	ResultStr = ValidateName("schoolname");
	 if ( ResultStr == null )
		ResultStr = ValidateAddress("schooladdr1", "schooladdr2", "schooladdr3", "schooladdr4", "schooladdr5" );
	if ( ResultStr == null )
		ResultStr = ValidatePostcode("schoolpostcode");
	if ( ResultStr == null )
		ResultStr = ValidatePhone("schooltelephone");
		
	if ( ResultStr == null )
	{
		ReturnPrefix = "Personal Contact ";
		ResultStr = ValidateName("billname");
	  	if ( ResultStr == null )
			ResultStr = ValidateAddress("billaddr1", "billaddr2", "billaddr3", "billaddr4", "billaddr5");
		if ( ResultStr == null )
			ResultStr = ValidatePostcode("billpostcode");
		if ( ResultStr == null )
			ResultStr = ValidatePhone("billtelephone");
	}
		
	if ( ResultStr == null )
	{
	  HideDivision( ErrorDiv );
	  return true;
	}
	else
	{
	  ErrObj.innerHTML = "<span class='registration_error'>" + ReturnPrefix + ResultStr + "</span>";
	  ShowDivision( ErrorDiv );
	}
		
  	return false;
}


function ShowMore( MoreId, LessId )
{
  var LessObj = document.getElementById( LessId );
	if ( LessObj != null )
	  LessObj.style.display = 'none';
		
  var MoreObj = document.getElementById( MoreId );
	if ( MoreObj != null )
	  MoreObj.style.display = 'inline';
}

function toggleArea( id )
{
  var ZoneObj = document.getElementById( id );
	if ( ZoneObj != null )
	{
	  if ( ZoneObj.style.display != 'inline' )
		  ZoneObj.style.display = 'inline';
		else
		  ZoneObj.style.display = 'none';
	}
}


  var RowId = null;
  
  function getUrl()
  {
  	Pos = location.href.indexOf( '?' );
  	if ( Pos >= 0 )
  	{
  	  return location.href.substr( 0, Pos );
  	}
  	else
  	  return location.href;
  }
  
  function changeCheckbox( Id, Field )
	{
	  Url = getUrl();
	  var Obj = document.getElementById( Field + "_" + Id );
		var NewVal = 0;
		if ( Obj.checked )
		  NewVal = 1;
			
		Url = Url + "?update=" + Id + "&field=" + Field + "&newval=" + NewVal;
	  AJAX_Get( Url );
	}
	
  function changeSelect( Id, Field )
	{
	  var Obj = document.getElementById( Field + "_" + Id );
		var NewVal = "";
		if ( Obj.selectedIndex >= 0 )
		  NewVal = Obj.options[ Obj.selectedIndex ].value;

	  Url = getUrl();
		Url = Url + "?update=" + Id + "&field=" + Field + "&newval=" + NewVal;
	  AJAX_Get( Url );
	}
	
  function changeText( Id, Field )
	{
	  var Obj = document.getElementById( Field + "_" + Id );
		var NewVal = Obj.value;
		RowId = Id;
		
		NewVal = NewVal.replace(/£/g, "&pound;");
		NewVal = NewVal.replace(/"/g, "&quot;");
		
	  Url = getUrl();
		Url = Url + "?update=" + Id + "&field=" + Field + "&newval=" + escape( NewVal );
	  AJAX_Get( Url );
	}
	
	
	function updateRow( RowId, DivName )
	{
	  divSt = gResponse.indexOf( "<" + DivName + ">" );
	  divEnd = gResponse.indexOf( "</" + DivName + ">" );
	  if ( ( divSt > 0 ) && ( divEnd > 0 ) )
	  {
	    Line = gResponse.substring( divSt + DivName.length + 2, divEnd  );

//		    alert( "Done " + Line );
		  var Row = document.getElementById( "row_" + RowId );
			TdCells = Line.split( "<td align=center>" );
			for ( i = 0; i < Row.cells.length; i++ )
			{
			  Row.cells[ i ].innerHTML = TdCells[ i + 1 ];
			}
			
//			Row.innerHTML = '<tr>' + Line + '</tr>';
//		    alert( "RowLine now  " + RowLine.innerHTML );
			
			
	  }
	  else if ( ( divSt > 0 ) && ( divEnd <= 0 ) )
	  {
	    if ( !gOnSite ) 
	      alert( "Could not find end tag for division " + DivName + "\n. Possible server code crash" );
	  }
	
	}

function AjaxEnterKeyPressed( e, Url ) 
{
   var e = e ? e : event;
   var keys = ( e.keyCode ) ? e.keyCode : e.which;
   if ( keys !== 13 )
     return;
   AJAX_Get( Url );
}

/************************************************************************
*                                                                       *
*                      THINK BEYOND - ADAPTIVE SOLUTIONS.
*                      			webmaster@jarman.org.uk
*
*                       Client: Angloenterprises.co.uk
*                        Copyright: Dave Jarman 2009
*                                                                       *
*************************************************************************
*                                                                       *
* Module Name : ajax_lib.js                                             *
*                                                                       *
* Edit Record (most recent edit at top of list)                         *
* Date        	By    	CF    	Comments				                        *
* ---------   	---   	----  	--------------------------------------- *
* 09-May-09     DCJ             New module				                      *
*************************************************************************

************************************************************************/

/* Change or determine by system variable the value of this parameter to
   determine if diagnostic warnings are shown. */
var gOnSite = false;

/* constants */
var DOW_OBJ = 0;
var USER_OBJ = 1;

/* Global variables - initialised outside this script */
var gResponse;
var gDowCacheCnt = 0;
var gXmlhttp = new Array();
var AJAX_OnLoadEvent = null;

/* User xml http object. */
gXmlhttp[USER_OBJ] = null;
var gAjaxCurrentUrl = null;

/* Document object wait object. */
gXmlhttp[DOW_OBJ] = null;
var gAjaxDowUrl = null;
var gAjaxDowRunning = false;

var gGetHashExecuted = false;

var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{
			string: navigator.userAgent,
			subString: "Chrome",
			identity: "Chrome"
		},
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari",
			versionSearch: "Version"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			   string: navigator.userAgent,
			   subString: "iPhone",
			   identity: "iPhone/iPod"
	    },
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();

function AJAX_Get(url,AjaxObjNum)
{
  if ( AjaxObjNum == undefined )
    var AjaxObjNum = USER_OBJ;
    
  AJAX_Init( AjaxObjNum );

  if (gXmlhttp[AjaxObjNum])
  {
    if ( AjaxObjNum == USER_OBJ )
    {
      gGetHashExecuted = true;

      gXmlhttp[AjaxObjNum].onreadystatechange = AJAX_Response;
      gAjaxCurrentUrl = UrlAppend( url, "ajaxcall&cachecnt=" + gDowCacheCnt++ );
      gXmlhttp[AjaxObjNum].open( "GET", gAjaxCurrentUrl );
      gXmlhttp[AjaxObjNum].send(null);
      SetCursorWait( true );
    }
    else if ( AjaxObjNum == DOW_OBJ )
    {
      gXmlhttp[AjaxObjNum].onreadystatechange = AJAX_ResponseDow;
      gAjaxDowUrl = UrlAppend( url, "ajaxcall&cachecnt=" + gDowCacheCnt++ );
      gXmlhttp[AjaxObjNum].open( "GET", gAjaxDowUrl );
      gXmlhttp[AjaxObjNum].send(null);
      /* Note - we do not set cursor wait on dow objects. */
    }
  }
} /* AJAX_Get */

/* Note all forms are user driven and therefore always use the user 
  object but the 3rd parameter allows it to be specified anyway, but is 
  unlikely ever to be used. */
function AJAX_GetFormData( FormId, url )
{
  var thisForm = document.getElementById( FormId );
	
  var submitCode = thisForm.getAttribute('onsubmit');
  if ( submitCode )
  {
    /* Implementation of whether onSubmit code is executed when submit is called
       programatically is very browser dependant. W3C and DOM specifies that 
       it should do the same whether pressing the button or calling submit(),
       but it doesn't on ie or firefox. */
    var OnSubmitFunc = null;
    if ( BrowserDetect.browser == "Explorer" )
      OnSubmitFunc = submitCode;
    else if ( BrowserDetect.browser == "Firefox" )
      OnSubmitFunc = new Function( submitCode );
    if ( OnSubmitFunc != null )
    {
      // Do we expect a result from the submit code validator function
      if ( String( submitCode ).indexOf( "return" ) < 0 )   // only use on submit as validator if returns a value.
      {
        // No just call it.
        OnSubmitFunc();
      }      
      else if ( ! OnSubmitFunc() )
      {
        // Yes - negative result.
        alert( "Action cancelled" );
        return false;
      }
    }
  }

  var WorkingUrl = url;

  for ( var i = 0; i < thisForm.elements.length; i++ )
  {
    var eleObj = thisForm.elements[i];
    if ( ( eleObj.form != null ) &&
         ( eleObj.form.id == FormId ) )
    {
      if ( ( eleObj.name        != null ) &&
           ( eleObj.name.length >  0    )   )
      {
        if ( eleObj.tagName == "INPUT" )
        {
          if ( ( eleObj.type == "checkbox" ) ||
               ( eleObj.type == "radio"    )   )
          {
            if ( eleObj.checked === true ) // only include checkboxes if checked
            {
              WorkingUrl = UrlAppend( WorkingUrl, eleObj.name + "=" + escape( eleObj.value ) );
            }
          }
          else
          {
            WorkingUrl = UrlAppend( WorkingUrl, eleObj.name + "=" + escape( eleObj.value ) );
          }
        }

        if ( eleObj.tagName == "SELECT" )
        {
          if ( eleObj.selectedIndex >= 0 )
            WorkingUrl = UrlAppend( WorkingUrl, eleObj.name + "=" + eleObj.options[eleObj.selectedIndex].value );
        }
      }
    }
  }

  return WorkingUrl;	
} /* AJAX_GetFormData */

/* Note all forms are user driven and therefore always use the user 
  object but the 3rd parameter allows it to be specified anyway, but is 
  unlikely ever to be used. */
function AJAX_GetForm(FormId, url, AjaxObjNum)
{
  if ( AjaxObjNum == undefined )
    var AjaxObjNum = USER_OBJ;
  AJAX_Init( AjaxObjNum );

  WorkingUrl = AJAX_GetFormData( FormId, url );
  AJAX_Get( WorkingUrl, AjaxObjNum ); 
	
} /* AJAX_GetForm */




function AJAX_Init( AjaxObjNum )
{
  var e;
  
  if ( AjaxObjNum == undefined )
    var AjaxObjNum = USER_OBJ;
  // branch for native XMLHttpRequest object
  if(window.XMLHttpRequest) 
  {
    try
    {
      gXmlhttp[AjaxObjNum] = new XMLHttpRequest();
      /* do not hardcode the over-ridden mime as 
         1. I can throw security exception
         2. It limits support of other character encodings and response types under ajax. 
      ** if ( gXmlhttp[AjaxObjNum].overrideMimeType )
      **  gXmlhttp[AjaxObjNum].overrideMimeType('text/xml'); */
    }
    catch(e)
    {
      var String = "Exception " + e;
      gXmlhttp[AjaxObjNum] = false;
    }
    finally
    {
    }
  } 
  else if(window.ActiveXObject) 
  {
    try 
    {
      gXmlhttp[AjaxObjNum] = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch(e) 
    {
      try 
      {
        gXmlhttp[AjaxObjNum] = new ActiveXObject("Microsoft.XMLHTTP");
      } 
      catch(e) 
      {
        gXmlhttp[AjaxObjNum] = null;
      }
      finally
      {
        ;
      }
    }
    finally
    {
      ;
    }
  }
} /* AJAX_Init */


function AJAX_ReplaceDivision( DivName )
{
  divSt = gResponse.indexOf( "<" + DivName + ">" );
  divEnd = gResponse.indexOf( "</" + DivName + ">" );
  if ( ( divSt > 0 ) && ( divEnd > 0 ) )
  {
    divText = gResponse.substring( divSt + DivName.length + 2, divEnd );

    DivObj = document.getElementById( DivName );
    DivObj.innerHTML = divText;
  }
  else if ( ( divSt > 0 ) && ( divEnd <= 0 ) )
  {
    if ( !gOnSite ) 
      alert( "Could not find end tag for division " + DivName + "\n. Possible server code crash" );
  }
}


function AJAX_Response()
{
  // only if gXmlhttp[USER_OBJ] shows "loaded"
  if ( gXmlhttp[USER_OBJ] != null )
  {
    if ( (gXmlhttp[USER_OBJ].readyState == 4) ||
         (gXmlhttp[USER_OBJ].readyState == "complete") )
    {
      SetCursorWait( false );
    // only if "OK"
      var ResponseUrl = gAjaxCurrentUrl;
      if (gXmlhttp[USER_OBJ].status == 200)
      {
        var CopiedResponseText = gXmlhttp[USER_OBJ].responseText;
        gXmlhttp[ USER_OBJ ] = null;  // Clear object for heap garbage collection
        
        handleAjaxResponse( ResponseUrl, CopiedResponseText );
        if ( AJAX_OnLoadEvent )
        {
          AJAX_OnLoadEvent();
          AJAX_OnLoadEvent = null;
        }
          
      }
      else if ( !gOnSite )
      {
        window.status = "Invalid Response from " + ResponseUrl;
        gXmlhttp[ USER_OBJ ] = null;  // Clear object for heap garbage collection
      }
    }
  }
  else
  {
    // user object cancelled...
    SetCursorWait( false );
  }
}

function AJAX_ResponseDow()
{
  var CodeFound = false;
  
  // only if gXmlhttp[DOW_OBJ] shows "loaded"
  if ( ( gXmlhttp != null ) &&
       ( gXmlhttp[DOW_OBJ] != null ) )
  {
    if ( (gXmlhttp[DOW_OBJ].readyState == 4) ||
        (gXmlhttp[DOW_OBJ].readyState == "complete") )
    {
      // only if "OK"
      var ResponseUrl = gAjaxDowUrl;
      if (gXmlhttp[DOW_OBJ].status == 200)
      {
        var CopiedResponseText = gXmlhttp[DOW_OBJ].responseText;
        gXmlhttp[ DOW_OBJ ] = null;  // Clear object for heap garbage collection
        
        CodeFound = handleAjaxResponse( ResponseUrl, CopiedResponseText )
      }
      else 
        gXmlhttp[ DOW_OBJ ] = null;  // Clear object for heap garbage collection
      
      /* If we are still running, execute another ajax request. */
      if ( AJAX_IsDowRunning( CodeFound ) )
      {
        AJAX_Get( gAjaxDowUrl, DOW_OBJ );
      }
    }
  }
  else
  {
    ; /* dow cancelled. */
  }
}


function AJAX_DisableFKeys( )
{
  AJAX_FKeyUrl = "";
  document.onkeydown = null;
}

function AJAX_DowStart( Url )
{
  gAjaxDowRunning = true;
  AJAX_Get( Url, DOW_OBJ );
}

function AJAX_DowStop( Url )
{
  gAjaxDowRunning = false;
}

function AJAX_EnableFKeys( Url )
{
  AJAX_FKeyUrl = Url;
  document.onkeydown = AJAX_FKeySupport;
  document.onhelp = new Function("return false;");
  window.onhelp = new Function("return false;");
}

function AJAX_FKeySupport( evt )
{
  // Determine the event.
  var e;
  var fKeyCode = 0;
  if ( evt )
  {
    e = evt;
    fKeyCode = e.which;
  }
  else
  {
    e = window.event;
    fKeyCode = e.keyCode;
  }
  
  // Interesting key code F1 - F8?
  if( ( fKeyCode >= 112 ) && ( fKeyCode <= 119 ) )
  {
    try
    {
      /* clear all old key codes. */
      e.keyCode = 0;
    }
    catch ( e )
    {
    }
    
    // Ensure we don't handle fkey twice
    if ( e.stoppropagation )
      e.stoppropagation();
    else
      e.cancelBubble = true;
      
    // Prevent default action
    if ( e.preventDefault )
      e.preventDefault();   // DOM level 2
    else
      e.returnValue = false;  // IE

    var FKey = "&fkey=F" + ( fKeyCode - 111 );
    if ( e.shiftKey )
      FKey += "&shift";
    if ( e.altKey )
      FKey += "&alt";
    if ( e.ctrlKey )
      FKey += "&ctrl";
    if ( e.metaKey )
      FKey += "&meta";
    AJAX_Get( AJAX_FKeyUrl + FKey );
  }
}

function AJAX_IsDowRunning( CodeFound )
{
  if ( ! gAjaxDowRunning )
    return false;

  if ( CodeFound )
    return false;   /* Code was found to trigger a new dow if required. */

  /* Compare screen objects to confirm that the dow object initiate is the same screen object. */
  var DowScrPos = gAjaxDowUrl.indexOf( "&scr=" );
  if ( DowScrPos == -1 )
    DowScrPos = gAjaxDowUrl.indexOf( "?scr=" );
  var DowScrObj = "";
  if ( DowScrPos > 0 )
    DowScrObj = gAjaxDowUrl.slice( DowScrPos + 1 ).split( "&", 1 );
  else
    return false;   /* can't compare scr object from dow - therefore never will so stop running. */
    
  if ( gAjaxCurrentUrl == null )
    return true;   /* No screen under ajax so must be ok. */

  var UserScrPos = gAjaxCurrentUrl.indexOf( "&scr=" );
  if ( UserScrPos == -1 )
    UserScrPos = gAjaxCurrentUrl.indexOf( "?scr=" );
  var UserScrObj = "";
  if ( UserScrPos > 0 )
    UserScrObj = gAjaxCurrentUrl.slice( UserScrPos + 1 ).split( "&", 1 );
  else
    return true;   /* can't compare scr object from user object so keep running anyway. */

  /* Keep running if same screen objects. */
  Result = ( UserScrObj[0] == DowScrObj[0] );
  return Result;
}


function AJAX_SetDocumentUrl( EncodedUrl )
{
  // var EncodedUrl = encodeURI( Url );
  // Work around Safari bug.
  if ( ( window.top.location.hash == EncodedUrl ) ||
       ( window.top.location.hash == "#" + EncodedUrl ) )
  {
    return;
  }

  if ( ( BrowserDetect.browser == 'Chrome' ) || ( BrowserDetect.browser == 'Safari' ) )
  {
// Ignore as chrome can't cope with changing document top.
  }
  else
  {
/*    if ( confirm( BrowserDetect.browser + " " + BrowserDetect.version +
		"Set hash to " + EncodedUrl + "\non " ) ) */
      window.top.location.hash = EncodedUrl;
  }
}

function AJAX_GetDocumentFromHash()
{
  // Ensure we only do this once on a load. 
  // Some browsers (Google Chrome and brookfields IE) will re-call 
  // onLoad when ajax executed and this
  // will result in this routine being re-called incorrectly.
  if ( gGetHashExecuted )
    return;
  gGetHashExecuted = true;
  var HashUrl = decodeURI( window.top.location.hash );
  if ( HashUrl.length > 0 )
  {
    var newUrl;
    if ( HashUrl.charAt(0) == '#' )
      newUrl = HashUrl.slice( 1 );
    else
      newUrl = HashUrl;
    if ( newUrl != 'none' )
      AJAX_Get( newUrl );
  }
}


/* -------------------- Local Functions --------------------- */

function handleAjaxResponse( ResponseUrl, ResponseDiv )
{
  var       CodeFound = false;
  
  // Populate the global variable gResponse. 
  gResponse = ResponseDiv;
  var     LastCodeStart = 0;
  while ( LastCodeStart >= 0 )
  {
    codeSt = gResponse.indexOf( "<code>", LastCodeStart );
    if ( codeSt > 0 )
      codeEnd = gResponse.indexOf( "</code>", codeSt );
    else
      codeEnd = -1;
    if ( ( codeSt > 0 ) && ( codeEnd > 0 ) )
    {
      code = gResponse.substring( codeSt + 6, codeEnd );

      if ( ( code != null ) && ( code.length > 0 ) )
      {
        CodeFound = true;
        try
        {
          eval( code );   // gResponse code.
        }
        catch (e)
        {
          // If an error occurs say we didn't find any code
          CodeFound = false;
          if ( confirm( "Code error " + e.name + " (" + e.message + "). \nto url " + ResponseUrl + "\nDo you want to see the code?" ) )
          {
            var ErrorWindow = null;
            if ( code.length > 30 )
            {
              var ErrorWindow = window.open( "", "", "scrollbars=yes");
              if ( ( ErrorWindow ) && ( !ErrorWindow.opener ) )
                ErrorWindow.opener = window;
            }
            if ( ErrorWindow )
            {
              var ConvertedCode = code.replace( /</g, "&lt;" ).replace( />/, "&gt;" ).replace( /\n/g, "<br>" ).replace( / /g, "&nbsp;" );
              ErrorWindow.document.write( "<html><head><title>" + e.message + 
                                          "</title></head><body style='{font: small courier;}'>" + 
                                          "<h1 style='font: 600 small times;'>" + e.message + "</h1>" +
                                          "<h2 style='font: 600 x-small times;'>" + ResponseUrl + "</h2>" +
                                          ConvertedCode + "</body></html>" );
              ErrorWindow.document.close();
            }
            else
              alert( code );
          }
        }
      }
    }
/* No code is normal for ajax timeouts. *
    else if ( !gOnSite )
    {
      if ( LastCodeStart == 0 )
      {
        if ( confirm( "No valid code in Response - See Apply Code ?\n" + ResponseDiv ) )
        {
          DivObj = document.getElementById( "content_div" );
          if ( DivObj != null )
          {
            DivObj.innerHTML = ResponseDiv;
          }
        }
        else
        {
        }
      }
    }
*/    
    LastCodeStart = codeEnd;
  } // end while
  
  return CodeFound;
} // end handleAjaxResponse


function onAnchor()
{
  if ( this.title.length > 0 )
    window.status = this.title;
  else
    window.status = "Calling " + this.href;
  return true;
}


function offAnchor()
{
  window.status = "";
  return true;
}

function SetCursorWait( waiting )
{
  if ( waiting )
    document.body.className = "Waiting";
  else
    document.body.className = "";
}

function UrlAppend( CurrentUrl, Value )
{
  if ( CurrentUrl.indexOf( '?' ) > 0 )
    return CurrentUrl + "&" + Value;
  else
    return CurrentUrl + "?" + Value;
}

function NewPage( PageName )
{
  window.location = PageName;
}



/************************************************************************
*									*
*	End of File : ajax_lib.js					*
*									*
************************************************************************/


(function($){
	/* hoverIntent by Brian Cherne */
	$.fn.hoverIntent = function(f,g) {
		// default configuration options
		var cfg = {
			sensitivity: 7,
			interval: 100,
			timeout: 0
		};
		// override configuration options with user supplied object
		cfg = $.extend(cfg, g ? { over: f, out: g } : f );

		// instantiate variables
		// cX, cY = current X and Y position of mouse, updated by mousemove event
		// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
		var cX, cY, pX, pY;

		// A private function for getting mouse position
		var track = function(ev) {
			cX = ev.pageX;
			cY = ev.pageY;
		};

		// A private function for comparing current and previous mouse position
		var compare = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			// compare mouse positions to see if they've crossed the threshold
			if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
				$(ob).unbind("mousemove",track);
				// set hoverIntent state to true (so mouseOut can be called)
				ob.hoverIntent_s = 1;
				return cfg.over.apply(ob,[ev]);
			} else {
				// set previous coordinates for next time
				pX = cX; pY = cY;
				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
				ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
			}
		};

		// A private function for delaying the mouseOut function
		var delay = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			ob.hoverIntent_s = 0;
			return cfg.out.apply(ob,[ev]);
		};

		// A private function for handling mouse 'hovering'
		var handleHover = function(e) {
			// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
			while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
			if ( p == this ) { return false; }

			// copy objects to be passed into t (required for event object to be passed in IE)
			var ev = jQuery.extend({},e);
			var ob = this;

			// cancel hoverIntent timer if it exists
			if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

			// else e.type == "onmouseover"
			if (e.type == "mouseover") {
				// set "previous" X and Y position based on initial entry point
				pX = ev.pageX; pY = ev.pageY;
				// update "current" X and Y position based on mousemove
				$(ob).bind("mousemove",track);
				// start polling interval (self-calling timeout) to compare mouse coordinates over time
				if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}

			// else e.type == "onmouseout"
			} else {
				// unbind expensive mousemove event
				$(ob).unbind("mousemove",track);
				// if hoverIntent state is true, then call the mouseOut function after the specified delay
				if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
			}
		};

		// bind the function to the two event listeners
		return this.mouseover(handleHover).mouseout(handleHover);
	};
	
})(jQuery);

/*
 * Superfish v1.4.8 - jQuery menu widget
 * Copyright (c) 2008 Joel Birch
 *
 * Dual licensed under the MIT and GPL licenses:
 * 	http://www.opensource.org/licenses/mit-license.php
 * 	http://www.gnu.org/licenses/gpl.html
 *
 * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
 */

;(function($){
	$.fn.superfish = function(op){

		var sf = $.fn.superfish,
			c = sf.c,
			$arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
			over = function(){
				var $$ = $(this), menu = getMenu($$);
				clearTimeout(menu.sfTimer);
				$$.showSuperfishUl().siblings().hideSuperfishUl();
			},
			out = function(){
				var $$ = $(this), menu = getMenu($$), o = sf.op;
				clearTimeout(menu.sfTimer);
				menu.sfTimer=setTimeout(function(){
					o.retainPath=($.inArray($$[0],o.$path)>-1);
					$$.hideSuperfishUl();
					if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
				},o.delay);	
			},
			getMenu = function($menu){
				var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
				sf.op = sf.o[menu.serial];
				return menu;
			},
			addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); };
			
		return this.each(function() {
			var s = this.serial = sf.o.length;
			var o = $.extend({},sf.defaults,op);
			o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
				$(this).addClass([o.hoverClass,c.bcClass].join(' '))
					.filter('li:has(ul)').removeClass(o.pathClass);
			});
			sf.o[s] = sf.op = o;
			
			$('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
				if (o.autoArrows) addArrow( $('>a:first-child',this) );
			})
			.not('.'+c.bcClass)
				.hideSuperfishUl();
			
			var $a = $('a',this);
			$a.each(function(i){
				var $li = $a.eq(i).parents('li');
				$a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
			});
			o.onInit.call(this);
			
		}).each(function() {
			var menuClasses = [c.menuClass];
			if (sf.op.dropShadows  && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
			$(this).addClass(menuClasses.join(' '));
		});
	};

	var sf = $.fn.superfish;
	sf.o = [];
	sf.op = {};
	sf.IE7fix = function(){
		var o = sf.op;
		if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
			this.toggleClass(sf.c.shadowClass+'-off');
		};
	sf.c = {
		bcClass     : 'sf-breadcrumb',
		menuClass   : 'sf-js-enabled',
		anchorClass : 'sf-with-ul',
		arrowClass  : 'sf-sub-indicator',
		shadowClass : 'sf-shadow'
	};
	sf.defaults = {
		hoverClass	: 'sfHover',
		pathClass	: 'overideThisToUse',
		pathLevels	: 1,
		delay		: 800,
		animation	: {opacity:'show'},
		speed		: 'normal',
		autoArrows	: true,
		dropShadows : true,
		disableHI	: false,		// true disables hoverIntent detection
		onInit		: function(){}, // callback functions
		onBeforeShow: function(){},
		onShow		: function(){},
		onHide		: function(){}
	};
	$.fn.extend({
		hideSuperfishUl : function(){
			var o = sf.op,
				not = (o.retainPath===true) ? o.$path : '';
			o.retainPath = false;
			var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
					.find('>ul').hide().css('visibility','hidden');
			o.onHide.call($ul);
			return this;
		},
		showSuperfishUl : function(){
			var o = sf.op,
				sh = sf.c.shadowClass+'-off',
				$ul = this.addClass(o.hoverClass)
					.find('>ul:hidden').css('visibility','visible');
			sf.IE7fix.call($ul);
			o.onBeforeShow.call($ul);
			$ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
			return this;
		}
	});

})(jQuery);
