/*

'  kdonline & hosted applications
'  kdx_default.js
'  keith davidson
'  August 2005

*/

// -------------------------------------------------------------------------------
// Global jscript variables
// -------------------------------------------------------------------------------

// sql characters which need to be escaped before processing
var a_sqlChars = new Array("'")

// client validation error array
var a_varErrors = new Array()

// client validation error flag
var m_blnError      = false
var m_intErrorCount = 0

var a_DaysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
var a_MonthNames = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")

// flag to enable a dataloss warning function when unloading pages
var m_blnCatchUnload = false

var intDay
var intMonth
var intYear

var dteSelectedDate
var dteToday

var blnXMLHttp = false;

var intTimeout

var strBrowserInformation = ""
var blnInternetExplorer = false
var intBrowserVersion = 0
var intBrowserMinorVersion = 0

var m_blnAdvisoryActive  = false
var m_blnAdvisoryModal = false

var m_blnFloat = false
var m_objFloat = null

var m_intCursorDeltaX
var m_intCursorDeltaY

var objAdvisory = null

var a_objDockArea = new Array()

function window.onload()
   {
   // start checking the page has completed loaded before initialising
   intTimeout = setInterval(verifyLoadComplete, 500)

   // fetch the browser information
   strBrowserInformation = navigator.appVersion
   
   // split and store the relevant information from the browser data
   intBrowserVersion       = strBrowserInformation.charAt(0)
   intBrowserMinorVersion  = strBrowserInformation.charAt(2)

   if (strBrowserInformation.indexOf("MSIE") > 0)
      {
      blnInternetExplorer = true
      
      intBrowserVersion       = strBrowserInformation.charAt(strBrowserInformation.indexOf("MSIE") + 5)
      intBrowserMinorVersion  = strBrowserInformation.charAt(strBrowserInformation.indexOf("MSIE") + 7)      
      }
   }


function padChar(strValue, strChar, intNumber)
   {
   intValueLength = (strValue.length)
   
   if(intValueLength < intNumber)
      {
      for(i=0;i<intNumber-intValueLength;i++)
         {
         strValue = strChar + strValue
         }
      }
   return strValue
   }


function catchClick()
   {
   event.cancelBubble = true
   return false   
   }


function verifyLoadComplete()
   {
   // wait until page has loaded all data
   if(document.body.readyState == "complete")
      {
      // call the page initialisation function
      initialisePage()
      
      // cancel the interval
      clearInterval(intTimeout)
      }
   }

function toggleDisplay(objTarget)
   {
   var blnModSrcElement = false
      
   // check the existence of the object first
   if(objTarget)
      {
      
      // check for the expand / collapse icon
      if(event.srcElement != null)
         {
         if(event.srcElement.tagName.toLowerCase() == "img")
            {
            blnModSrcElement = true
            }    
         }
 
      // determine the objects display status;  this is best done by checking the offsetHeight
      //if(objTarget.style.display == "none")
		if(objTarget.offsetHeight == 0)
         {
         // target is not displayed;  display object
         objTarget.style.display = "block"
			document.cookie = objTarget.id + "_expand=1"
	
         if(blnModSrcElement)
            {
            event.srcElement.src = "/images/icons/img_node_collapse.gif"
            }
         }
      else
         {
         // target is displayed;  hide object
         objTarget.style.display = "none"         
			document.cookie = objTarget.id + "_expand=0"
         
         if(blnModSrcElement)
            {
            event.srcElement.src = "/images/icons/img_node_expand.gif"
            }
         }
      }
   }
  

function orderNumerical(intValueA, intValueB)
   {
   return (parseInt(intValueA) - parseInt(intValueB))
   }
   

function extract(string,delimiter,index)
   {
   var ary = string.split(delimiter);

   if(ary.length > index)
      {
      return(ary[index]);
      }
   else
      {
      return "";
      }
   }

/*-------------------------------------------------------------------------------------------------
   PROCEDURE   :  setQueryStringParam()
   AUTHOR      :  Keith Davidson
---------------------------------------------------------------------------------------------------
   INPUTS      :  strQueryStringName
               :  strQueryStringValue
   OUTPUTS     :  None
   PURPOSE     :  Replace or add a querystring name / value pair
--------------------------------------------------------------------------------------------------*/
var m_strQuerystring = extract(location.href, "?", 1)

function setQueryStringParam(strQueryStringName, strQueryStringValue)
   {
   var strQuerystring   = ""
   var a_strQuerystring = null
   var blnParamSet = false
   
   // split the querystring into name value pairs
   a_strQuerystring = m_strQuerystring.split("&")
   
   // loop over name-value pairs;  if the parameter name is found, replace the value
   for(i=0;i<a_strQuerystring.length;i++)
      {
      if(a_strQuerystring[i].indexOf(strQueryStringName)> -1)
         {
         // matched the querystring parameter
         if(strQueryStringValue != null)
            {
            // value passed is not null;  replace old vaue with new
            strQuerystring += a_strQuerystring[i].replace(extract(a_strQuerystring[i], "=", 1), strQueryStringValue) + "&"
            }
         
         // set the 'value added' flag
         blnParamSet = true
         }
      else
         {
         if(a_strQuerystring[i].length > 0)
            {
            // no match;  add the name-value pair back into the querystring
            strQuerystring += a_strQuerystring[i] + "&"
            }
         }
      }
   // add the name-value pair if it hasn't been modified
   if((!blnParamSet || m_strQuerystring == "") && strQueryStringValue != null)
      {
      strQuerystring = strQuerystring + (strQueryStringName + "=" + strQueryStringValue)
      }
   // remove any extraneous ampersand characters
   if(strQuerystring.charAt(strQuerystring.length-1) == "&")
      {
      strQuerystring = left(strQuerystring, strQuerystring.length-1)
      }
   // reset the global variable
   m_strQuerystring = strQuerystring
   if(m_strQuerystring.length > 0 && m_strQuerystring.charAt(0) != "?")
      {
      m_strQuerystring = "?" + m_strQuerystring
      }   
   // return the global variable
   return m_strQuerystring
   }


function left(string, length)
   {
   return(string.substr(0, length))
   }

function right(string, length)
   {
   return(string.substr(string.length - length, length))
   }



// -------------------------------------------------------------------------------
// Utility functions (type conversions, format manipulations etc)
// -------------------------------------------------------------------------------

function left(string, length){
   return(string.substr(0, length))
}


function right(string, length){
   return(string.substr(string.length - length, length))
}

function awoogaa(){
   alert("awoogaa!")
}

function getXMLHttp()
   {
   if(blnInternetExplorer && intBrowserVersion < 7)
      {
      return new ActiveXObject("Microsoft.XMLHTTP");
      }
   else
      {
      // this syntax covers IE7 and alternative browsers 
      if(window.XMLHttpRequest)
         {

         // IE 7 implementation
         // -------------------   
 
         return new XMLHttpRequest;
         }
      else
         {
         return null;
         }
      }
   }

function serializeFormData(objForm)
   {
   var strFormData = ""
   
   for(i=0;i<objForm.elements.length;i++)
      {
      // don;t allow comments to be added (script will fall over)
      if(objForm.elements[i].tagName != "!")
         {
         // check the length of the string to see if it has already been populated
         if(strFormData.length > 0)
            {
            // drop in an apersand if the string already has content
            strFormData += "&"
            }

         // add the name value pair
         strFormData += objForm.elements[i].name + "=" + objForm.elements[i].value
         }
      }
   return strFormData
   }


// SQL Command validation (includes warnings for potentially unsafe commands)
// ---------------------------------------
function checkSQL()
{
var blnSubmitQuery = true
var strMessage = ""

// load the contents of the query command box into a variable
var strSQLCommand = document.all("txtSQLCommand").value

// trim the leading spaces, and remove all non-valid characters (purely for checking the command, it does not alter the actual
// contents of the command window)
while(strSQLCommand.charAt(0) == " ")
   {
   strSQLCommand = right(strSQLCommand, (strSQLCommand.length -1))
   }

// ensure that we have a string to work with
if(eval(strSQLCommand.length == 0))
   {
   alert("No command")
   return
   }

// force all characters to lowercase
// todo:  lowercase everything except values
//strSQLCommand = strSQLCommand.toLowerCase()

// check the first six characters for sql statement type
switch(left(strSQLCommand, 6).toLowerCase())
   {
   case "select":
      if(strSQLCommand.indexOf("where") ==-1)
         {
         // there is no where clause;  oops...
         blnSubmitQuery = window.confirm("CAUTION:  There is no WHERE clause in this select statement;  This query will select all rows, and may take some time.\n\nDo you want to continue?")
         }      
      break;
   
   case "insert":
      break;
   
   case "update":

      if(strSQLCommand.indexOf("where") ==-1)
         {
         // there is no where clause;  oops...
         blnSubmitQuery = window.confirm("WARNING:  There is no WHERE clause in this update statement;  ALL records will be affected.\n\nDo you want to continue?")
         }
  
      break;      
   
   case "delete":

      if(strSQLCommand.indexOf("where") ==-1)
         {
         // there is no where clause;  oops...
         blnSubmitQuery = window.confirm("WARNING:  There is no WHERE clause in this delete statement;  ALL records will be affected.\n\nDo you want to continue?")
         }

      break;      

   default:
      blnSubmitQuery = window.confirm("This is not a recognised command.\n\nWould you like to execute the command anyway?")
      break;      
   }


// check to see whether any of the validation cancelled the submit...
if(blnSubmitQuery)
   {
   document.all("frmQuery").submit()
   }
}

function loginKeypress(objField)
   {

   if(event.keyCode==13)
      {
      switch(objField.type)             
         {
         case "text":
            document.all("txt_password").focus()  
         break;

         case "password":
            login(frm_login)
         break;
         }
      }
   }


function login(elmForm)
   {
   var blnError = false

   for(i=0;i<elmForm.elements.length;i++)
      {
      if(elmForm.elements[i].value == "")
         {
         blnError = true
         }
      }   

   if(!blnError)
      {
      elmForm.submit()
      }
   else
      {
      alert("Please enter a username and password")
      blnError = false
      }
   }

function replaceString(strString, strFind, strReplace)
   {
   var a_strString            // array for holding the string constituents
   var strReturnString = ""   // return variable

   // split the string into constituents, using the find string as a delimiter
   a_strString = strString.split(strFind)

   if(a_strString.length > 0)
      {

      // iterate over the string constituents
      for(k=0;k<a_strString.length;k++)
         {

         // append the constituents back into the string
         strReturnString += a_strString[k]

         // add the replace string where the find string was removed, but only if it's not the last constituent
         if(k != a_strString.length-1)
            {
            strReturnString += strReplace
            }
         }
      }

   return strReturnString
   }


function makeCodesafe(strValue)
   {

   // loop over the sql character array
   for(j=0;j<a_sqlChars.length;j++)
      {
      // check for the current sql character
      if(strValue.indexOf(a_sqlChars[j]) > -1)
         {
         // replace the sql character with it's "double" (i.e. ' becomes '')
         strValue = replaceString(strValue, a_sqlChars[j], eval("a_sqlChars[j].toString() + a_sqlChars[j].toString()"))
         }
      }

   return strValue
   }


function getMaxDays(intMonth, intYear)
   {
   var blnLeap = false
   var intDays = a_DaysInMonth[intMonth]

   // determine leap year status; all leap years are divisible by 4
   if(intYear % 4 == 0)
      {
      blnLeap = true
      
      // check for century rule...
      if(intYear % 100 == 0 && intYear % 400 != 0)
         {
         blnLeap = false
         }
      }

   if(blnLeap && intMonth == 1)
      {
      intDays++
      }
   
   return intDays

   }

function getDates(objForm)
   {
   intDay     =  objForm.lst_date.value
   intMonth   =  objForm.lst_month.selectedIndex
   intYear    =  objForm.lst_year.value

   dteSelectedDate = new Date(intYear, intMonth, intDay)
   }

function selectMonth(objForm)
   {
   // get the current date values from the form
   getDates(objForm)

   // check that the date is valid (after today...)
   if(dteSelectedDate < dteToday)
      {
      // date is prior to today, increment year
      objForm.lst_year.selectedIndex = 1
      getDates(objForm)
      }      

   selectDay(objForm)
   }

function selectDay(objForm)
   {
   // get the current date values from the form
   getDates(objForm)

   if(intDay > getMaxDays(intMonth, intYear))
      {
      objForm.lst_date.selectedIndex = a_DaysInMonth[intMonth] - 1
      }
   }


function rowHighlight(objRef, blnHighlight)
   {
   if(blnHighlight)
      {
      objRef.style.backgroundColor = "#99CC99"
      }
   else
      {
      objRef.style.backgroundColor = "#ffffff"
      }
   }

function deleteMessage(intMsgID)
   {
   if(window.confirm("This will delete the message permanently\n\nDo you wish to continue?"))
      {
      frm_message_board.txt_message_id.value = intMsgID
      frm_message_board.submit()
      }
   }


function checkValueLength(objRef, intMaxLength)
   {
   if(objRef.value.length > intMaxLength)
      {
      }
   }

function hasValue(objInput, varCompare)
   {
   var strValue = objInput.value
        
   if(strValue.length != 0 && strValue != null)
      {
      if(varCompare != null)
         {
         if(strValue == varCompare)
            {
            return true      
            }
         else
            {
            return false            
            }
         }
      return true      
      }
   return false
   }


function addError(objInput, strErrorDesc)
   {
   var a_objErrorInstance = new Array

   a_objErrorInstance[0] = objInput
   a_objErrorInstance[1] = strErrorDesc

   a_varErrors[a_varErrors.length] = a_objErrorInstance
   
   m_blnError = true
   m_intErrorCount++
   }

function alertError()
   {
   var strMessage = "The highlighted fields have not been completed correctly.  Please hover over each field for a description of the error."

   for(i=0;i<a_varErrors.length;i++)
      {
      a_varErrors[i][0].title = a_varErrors[i][1]

      a_varErrors[i][1] = a_varErrors[i][0].style.cssText

      a_varErrors[i][0].style.border = "1px solid red"
      }

   alert(strMessage)
   clearError()
   }

function clearError()
   {
   a_varErrors.length = 0
   
   /*
   for(i=0;i<a_varErrors.length;i++)
      {
      a_varErrors[i][0].style.cssText = a_varErrors[i][1]
      a_varErrors[i][0].title = ""
      }

   a_varErrors = new Array()
   */   

   m_blnError = false
   m_intErrorCount = 0
   }

function hasError()
   {
   return m_blnError
   }

function requiredField(objInput)
   {
   if(objInput.tagName == "INPUT")
      {
      if(objInput.type.toLowerCase() == "radio")
         {
         if(!intToBool(checkRadio(objInput.name)))
            {
            //find the object with the id equal to the radio group name
            var objRadioContainer = document.getElementById(objInput.name)
            
            // add the error to the error collection
            addError(objRadioContainer, "Please select a venue")
            }
         }
      else
         {
         if(!hasValue(objInput))
            {
            // add the error to the error collection
            addError(objInput, "This field requires a value")
            }         
         }
      }
   else
      {
      if(!hasValue(objInput))
         {
         // add the error to the error collection
         addError(objInput, "This field requires a value")
         }         
      }      
   }


function checkRadio(strGroupName)
   {
   for(i=0;i<document.getElementsByName(strGroupName).length;i++)
      {
      if(document.getElementsByName(strGroupName)[i].checked)
         {
         return i+1
         }
      }
   return 0
   }


function intToBool(intValue)
   {
   if(intValue == 0)
      {
      return false
      }
   return true
   }
   
/*-------------------------------------------------------------------------------------------------
   PROCEDURE   :  getAbsTopLeft()
   AUTHOR      :  Keith Davidson
---------------------------------------------------------------------------------------------------
   INPUTS      :  objDHTML
   OUTPUTS     :  a_intCoords
   PURPOSE     :  Return the co-ordinates of an object
--------------------------------------------------------------------------------------------------*/

   function getAbsTopLeft(objDHTML)
      {
      var objOrgElm = objDHTML
      var strElementName = objDHTML.tagName
      var a_intCoords = new Array()
      
      var intX = 0
      var intY = 0         
        
      if(objDHTML.style.position.toLowerCase() != "absolute")
         {
        
         while(strElementName.toLowerCase() != "body")
            {
            if(strElementName.toLowerCase() != "form" && strElementName.toLowerCase() != "tbody" && strElementName.toLowerCase() != "tr")
               {
               intX += objDHTML.offsetLeft
               intY += objDHTML.offsetTop
               }  

            objDHTML = objDHTML.parentElement
            strElementName = objDHTML.tagName
            }
         }
      else
         {
         intX += objDHTML.offsetLeft
         intY += objDHTML.offsetTop
         }
         
      a_intCoords[0] = intX
      a_intCoords[1] = intY
      
      return a_intCoords
      }


/*-------------------------------------------------------------------------------------------------
   PROCEDURE   :  getIntersectStatus()
   AUTHOR      :  Keith Davidson
---------------------------------------------------------------------------------------------------
   INPUTS      :  obj1  -  Primary Object
               :  obj2  -  Secondary Object
   OUTPUTS     :  Boolean value
   PURPOSE     :  Determines whether the two objects overlap on the page
--------------------------------------------------------------------------------------------------*/

   function getIntersectStatus(obj1, obj2)
      {
      var a_intCoords
      var blnOverlap

      var intRequiredWidth    = 0
      var intRequiredHeight   = 0         
      var intBoundingWidth    = 0                  
      var intBoundingHeight   = 0         
      
      blnOverlap = false
      
      // check neither object is null
      if(obj1 == null || obj2 == null)
         {
         return false
         }

      // get the co-ordinates for the first object
      a_intCoords = getAbsTopLeft(obj1)
      
      var intArea1X1 = a_intCoords[0]
      var intArea1Y1 = a_intCoords[1]
      var intArea1X2 = intArea1X1 + obj1.offsetWidth
      var intArea1Y2 = intArea1Y1 + obj1.offsetHeight

      // get the co-ordinates for the second object
      a_intCoords = getAbsTopLeft(obj2)

      var intArea2X1 = a_intCoords[0]
      var intArea2Y1 = a_intCoords[1]
      var intArea2X2 = intArea2X1 + obj2.offsetWidth
      var intArea2Y2 = intArea2Y1 + obj2.offsetHeight

      // kill the array      
      a_intCoords.length = 0
      
      // calculate the bounding area
      intAreaBoundX1 = intArea1X1 < intArea2X1 ? intArea1X1: intArea2X1
      intAreaBoundY1 = intArea1Y1 < intArea2Y1 ? intArea1Y1: intArea2Y1
      intAreaBoundX2 = intArea1X2 > intArea2X2 ? intArea1X2: intArea2X2
      intAreaBoundY2 = intArea1Y2 > intArea2Y2 ? intArea1Y2: intArea2Y2         
      
      // calculate the minimum width and height to contain both objects without intersecting
      intRequiredWidth  = obj1.offsetWidth + obj2.offsetWidth
      intRequiredHeight = obj1.offsetHeight + obj2.offsetHeight         
      
      // calculate the actual width and height that does contain both objects
      intBoundingWidth  = intAreaBoundX2 - intAreaBoundX1
      intBoundingHeight = intAreaBoundY2 - intAreaBoundY1

      // compare required dimensions against actual dimensions
      if(intBoundingWidth < intRequiredWidth && intBoundingHeight < intRequiredHeight)
         {
         // objects exist in an area to small for them not to intersect
         blnOverlap = true
         }

      return blnOverlap
      }
      

   function getIndexFromID(objElement)
      {
      return right(objElement.id, (objElement.id.length - objElement.id.lastIndexOf("_") - 1))
      }
      
   function dockObject(objDock, objSprite)
      {
      var intDockAreaIndex
      var a_intDivPosition = getAbsTopLeft(objDock)
      
      objSprite.style.left = a_intDivPosition[0]
      objSprite.style.top  = a_intDivPosition[1]

      objSprite.style.width = objDock.offsetWidth
      objSprite.style.height = objDock.offsetHeight            
      }
      
	function setFeedback(strValue)
		{
		document.getElementById("span_user_feedback").innerHTML += strValue
		if(document.getElementById("span_user_feedback").className != "userFeedback")
		   {
		   document.getElementById("span_user_feedback").className = "userFeedback";
		   }
		}
		
   function valid_email(email)
      {
      var at = "@";
      var dot = ".";
      var lat = email.indexOf(at);
      var lstr = email.length;
      var ldot = email.indexOf(dot);

      if (email.indexOf(at) == -1) return false;
      if (email.indexOf(at) == -1 || email.indexOf(at) == 0 || email.indexOf(at) == lstr) return false;
      if (email.indexOf(dot) == -1 || email.indexOf(dot) == 0 || email.indexOf(dot) == lstr) return false;
      if (email.indexOf(at, (lat + 1)) != -1) return false;
      if (email.substring(lat-1, lat) == dot || email.substring(lat + 1, lat + 2) == dot) return false;
      if (email.indexOf(dot, (lat + 2)) == -1) return false;
      if (email.indexOf(" ") != -1) return false;

      return true;
}



   /*-------------------------------------------------------------------------------------------------
      PROCEDURE   : createBackground()
      AUTHOR      : Keith Davidson
   ---------------------------------------------------------------------------------------------------
      INPUTS      : None
      OUTPUTS     : None
      PURPOSE     : Create a new div element and set it's properties for use as a background
   --------------------------------------------------------------------------------------------------*/

   function createBackground(intStartOpacity, intFinishOpacity, blnAddBorder)
      {

      if(intStartOpacity==null) intStartOpacity = 100; 
      if(intFinishOpacity==null) intFinishOpacity = 100; 

      objBackground = document.createElement("DIV")
      objBackground.style.top = "0px";
      objBackground.style.position = "absolute"; 
      objBackground.style.backgroundColor = "#ddeeff";
      objBackground.style.zIndex = "-1";
      objBackground.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=intStartOpacity, finishOpacity=intFinishOpacity, style=1, startX=50, startY=0, finishX=50, finishY=100)"

      if(blnAddBorder)objBackground.style.border = "1px solid #cccccc";
      
      return objBackground
      }


   /*-------------------------------------------------------------------------------------------------
      PROCEDURE   : positionBackground()
      AUTHOR      : Keith Davidson
   ---------------------------------------------------------------------------------------------------
      INPUTS      : objArea, objBackground
      OUTPUTS     : None
      PURPOSE     : size and position one object relative to another
   --------------------------------------------------------------------------------------------------*/

   function positionBackground(objArea, objBackground)
      {
      var objParentElement = getParent(objArea, "FORM", false)

      objParentElement.style.position = "relative";
      objParentElement.style.left = "0px";
      objArea.style.marginBottom = "5px";

      objBackground.id = objArea.id + "_background"
      objBackground.style.height = objArea.offsetHeight;
      objBackground.style.width = objArea.offsetWidth;

      objArea.appendChild(objBackground)
      }
      

   /*-------------------------------------------------------------------------------------------------
      PROCEDURE   : getParent()
      AUTHOR      : Keith Davidson
   ---------------------------------------------------------------------------------------------------
      INPUTS      : objRef, strElementTagName
      OUTPUTS     : DHTML object reference
      PURPOSE     : Return the most 'recent' ancestor of a given type for a given object
   --------------------------------------------------------------------------------------------------*/

   function getParent(objRef, strElementTagName, blnTargetTag)
      {
      if(objRef!=null)
         {
         // keep looping until we find an appropriate parent or the body tag
         while((eval(objRef.tagName != strElementTagName.toUpperCase()) == blnTargetTag) || objRef.tagName == "BODY" )
            {
            objRef = objRef.parentElement
            }
         // ensure that we haven't stepped all the way up to the body tag
         if(objRef.tagName == "BODY")
            {
            objRef = null
            alert("Can't find Parent Object")
            }
         // return the object reference
         return objRef
         }
      }      