  //**************************************************
  //  Image Rollover
  //**************************************************
  
  function swImg(iName,str)
  {
    document.images[iName].src = str;
  }

  //**************************************************
  // Toggle the display of <div> to hidden or visible
  // Written by H.H.Ng
  // Date: 23/Aug/04
  //**************************************************
  function exMenu(tName)
  {
     tMenu = document.all[tName].style;
     tMenu.display = (tMenu.display == 'none') ?  "block" : "none";
  }

  //*******************************************************
  // Focus the pointer to the field that contains an error
  // Written by H.H.Ng
  // Date: 23/Aug/04, rev1: 8/Jun/05
  //*******************************************************
  function focusElement(formName, elemName)
  {
     var elem = document.forms[formName].elements[elemName];
     elem.focus();

     //if this is not a select box, we highlight the entry in the box
     if((elem.type != "select-one") && (elem.type != "select-multiple"))
       elem.select();
  }

  //*******************************************************
  // Trim the string of leading and trailing spaces
  // Written by H.H.Ng
  // Date: 25/Jan/05
  //*******************************************************
  function trimString(str)
  {
    while((str.charAt(0) == ' ') || (str.charAt(0) == '\t'))
      str = str.substring(1);

    while((str.charAt(str.length - 1) == ' ') || (str.charAt(str.length - 1) == '\t'))
      str = str.substring(0, str.length - 1);

    return str;
  }

  //*************************************
  // Check if the field is empty
  // Written by H.H.Ng
  // Date: 23/Aug/04, rev1: 25/Jan/05
  //*************************************
  function isNotEmpty(fieldObj)
  {
    var str = trimString(fieldObj.value);

    if((str == null) || (str.length == 0))
    {
      //if there is only one argument, we focus on the object.
      //if there are more than one argument, it means user does not want to focus on the element
      if(arguments.length == 1)
        fieldObj.focus();

      return false;
    }

    return true;
  }

  //**********************************************************************
  // Check if the field contains a valid number with max 1 decimal places
  // Written by H.H.Ng
  // Date: 23/Aug/04, rev01:17/Feb/05
  //**********************************************************************
  function isNumber(elem)
  {
     var str = elem.value;
     var oneDecimal = false;
     var oneChar = 0;

     if(str.substring(0,1) == "-") //if this is possibly a negative number, we take the numerals for verification only
       str = str.substring(1, str.length);

     str = str.toString();

     for(var i=0; i<str.length; i++)
     {
        oneChar = str.charAt(i).charCodeAt(0);

        if(oneChar == 46)
        {
            if(!oneDecimal)
            {
                oneDecimal = true;
                continue;
            }
            else
            {
                alert("Only one decimal is allowed.");
                return false;
            }
        }

        if((oneChar < 48) || (oneChar > 57))
        {
           alert("Enter only numbers.");
           return false;
        }
     }

     return true;
  }

  //**********************************************************************
  // Check if the field contains a valid integer
  // Written by H.H.Ng
  // Date: 03/Feb/05
  //**********************************************************************
  function isInteger(elem)
  {
    var str = elem.value;
    var oneChar = 0;

    str = str.toString();

    for(var i=0; i<str.length; i++)
    {
      oneChar = str.charAt(i).charCodeAt(0);

      if (oneChar > 31 && (oneChar < 48 || oneChar > 57))
      {
        setTimeout("focusElement('" + elem.form.name + "', '" + elem.name + "')", 0);
        alert("Enter integers only in this field.");
        return false;
      }
    }

    return true;
  }

  //**********************************************************************
  // Check if the field contains a valid date
  // Written by H.H.Ng
  // Date: 12/Aug/05
  //**********************************************************************
    var dtCh    = "/";
    var minYear = 0000;
    var maxYear = 9999;

  function isDate(dtStr)
  {
    var daysInMonth = DaysArray(12);
    var pos1        = dtStr.indexOf(dtCh);
    var pos2        = dtStr.indexOf(dtCh,pos1+1);
    var strDay      = dtStr.substring(0,pos1);
    var strMonth    = dtStr.substring(pos1+1,pos2);
    var strYear     = dtStr.substring(pos2+1);

    strYr = strYear;

    if(strDay.charAt(0)=="0" && strDay.length>1)
      strDay=strDay.substring(1);

    if(strMonth.charAt(0)=="0" && strMonth.length>1)
      strMonth=strMonth.substring(1);

    for (var i = 1; i <= 3; i++)
    {
      if (strYr.charAt(0)=="0" && strYr.length>1)
        strYr=strYr.substring(1);
    }

    month = parseInt(strMonth);
    day   = parseInt(strDay);
    year  = parseInt(strYr);

    if(pos1==-1 || pos2==-1) //date format is not dd/mm/yyyy
      return false;

    if(strMonth.length<1 || month<1 || month>12) //month is invalid
      return false;

    if(strDay.length<1 || day<1 || day>31 || (month==2 && day>daysInFebruary(year)) || day > daysInMonth[month]) //day is invalid
      return false;

    if(strYear.length != 4 || year==0 || year<minYear || year>maxYear) //year is not 4 digits
      return false;

    if (dtStr.indexOf(dtCh,pos2+1)!=-1 || isDtInt(stripCharsInBag(dtStr, dtCh))==false) //alphabets were provided
      return false;

    return true;
  }

  function isDtInt(s)
  {
    var i;

      for (i = 0; i < s.length; i++)
      {
        // Check that current character is number.
        var c = s.charAt(i);

        if (((c < "0") || (c > "9")))
          return false;
      }

      // All characters are numbers.
      return true;
  }

  function stripCharsInBag(s, bag)
  {
    var i;
    var returnString = "";

    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.
    for(i=0; i<s.length; i++)
    {
      var c = s.charAt(i);

      if(bag.indexOf(c) == -1)
        returnString += c;
    }

    return returnString;
  }

  function daysInFebruary(year)
  {
    // February has 29 days in any year evenly divisible by four,
    // EXCEPT for centurial years which are not also divisible by 400.
    return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 );
  }

  function DaysArray(n)
  {
    for(var i = 1; i <= n; i++)
    {
      this[i] = 31;

      if (i==4 || i==6 || i==9 || i==11)
       this[i] = 30;

      if (i==2)
        this[i] = 29;
     }

     return this;
  }

  //***************************************************************************
  // Calculate the days difference from the FROM date and then get the TO date
  // Written by H.H.Ng
  // Date: 23/Aug/04, rev1:16/Feb/05
  //**************************************************************************
  function calGetToDt(formDt, oldInDt, oldOutDt)
  {
     var theFormDate = new Date();
     var theOldDate  = new Date();
     var theOutDate  = new Date();

     theFormDate = convertDate(formDt);
     theOldDate  = convertDate(oldInDt);
     theOutDate  = convertDate(oldOutDt);

     // The number of milliseconds in one day
     var ONE_DAY = 1000 * 60 * 60 * 24;

     // Convert both dates to milliseconds
     var date1_ms = theFormDate.getTime();
     var date2_ms = theOldDate.getTime();

     // Calculate the difference in milliseconds
     var real_diff_ms = date1_ms - date2_ms;

     var difference_ms = Math.abs(date1_ms - date2_ms);

     // Convert back to days and return
     numDaysDiff = Math.round(difference_ms/ONE_DAY);

     if(real_diff_ms>0)
       theOutDate.setDate(theOutDate.getDate() + numDaysDiff);
     else
       theOutDate.setDate(theOutDate.getDate() - numDaysDiff);

     return theOutDate.getYear() + "-" + pad(theOutDate.getMonth()+1) + "-" + pad(theOutDate.getDate());
  }

  //***************************************************************************
  // Formats the date to something that MySQL understands
  // Written by H.H.Ng
  // Date: 28/June/05
  //**************************************************************************
  function getSQLDt(dt)
  {
     var theDate = new Date();

     theDate = convertDate(dt);

     if(theDate == false)
       return false;

     return theDate.getYear() + "-" + pad(theDate.getMonth()+1) + "-" + pad(theDate.getDate());
  }

  //***********************************
  // Formats the date to dd/mmm/yy
  // Written by H.H.Ng
  // Date: 12/Aug/05
  //***********************************
  function getUKDt(dt)
  {
    var UKDate  = dt;
    var str = trimString(dt);

    if((str == null) || (str.length == 0))
       return "";

    if ((n = str.indexOf("/")) == -1)
      UKDate = str.substr(0, 2) + "/" + str.substr(2, 2) + "/" + str.substr(4, 4);

     var theDate = new Date();
     var arrMMM  = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");

     theDate = convertDate(UKDate);

     if(theDate == false)
       return false;

     return pad(theDate.getDate()) + "/" + arrMMM[theDate.getMonth()] + "/" + (theDate.getYear()+"").substring(2,4);
  }

  //**********************************************************************
  // Converts a date into the format that Javascript comprehends
  // This is a utility function for the calDaysDiff, getToDate and getSQLDt
  // Types of dates that gets converted (these are the UK standards):
  // d/m/yyyy, d/mm/yyyy, d/mmm/yyyy, dd/m/yyyy, dd/mm/yyyy, dd/mmm/yyyy
  // d/m/yy, d/mm/yy, d/mmm/yy, dd/m/yy, dd/mm/yy, dd/mmm/yy
  // d/m, d/mm, d/mmm, dd/m, dd/mm, dd/mmm
  // Written by H.H.Ng
  // Date: 12/Aug/05
  //**********************************************************************
  function convertDate(inDate)
  {
     dateComponent = inDate.split("/");

     if (dateComponent.length == 1)
     {
        dateComponent = inDate.split("-");

        if (dateComponent.length == 1)
        {
           dateComponent = inDate.split(".");

           if (dateComponent.length == 1)
           {
              alert('Your date input is not valid.');
              return false;
           }
        }
     }

     var inDay = dateComponent[0];
     var inMth = dateComponent[1];
     var inYr  = dateComponent[2];

     //set the format of day
     inDay = (inDay.length == 1) ? "0" + inDay : inDay;

     //set the year and it's format
     if(typeof inYr == "undefined") //if this is in the form d/m, d/mm, d/mmm, dd/m, dd/mm, dd/mmm, we set the year to current year
     {
        var today = new Date();
        var inYr  = today.getYear();
     }
     else
       inYr  = (inYr.length  == 2) ? "20" + inYr : inYr ; //set format to yyyy

     //set the format of month
     if(isNaN(inMth)) //month is in the format of Aug so we use the string method
       var theDate = new Date(inMth + " " + inDay + ", " + inYr)
     else //this is a number, means date is in the form d/m or dd/mm
     {
       //check if this is a valid date first
       if(isDate(inDay + "/" + inMth + "/" + inYr) == false)
       {
         alert('Your date input is not valid.');
         return false;
       }

       inMth = inMth - 1;
       inMth = (inMth.length == 1) ? "0" + inMth : inMth;

       var theDate = new Date(inYr, inMth, inDay);
     }

     return theDate;
  }

  //**********************************************************************
  // Converts a date into the format that Javascript comprehends
  // This is a utility function for the calDaysDiff and getToDate.
  // This is used for dates that follow the JP way of mm/dd or yyyy/mm/dd
  // Written by H.H.Ng
  // Date: 23/Aug/04
  //**********************************************************************
  function convertDateJP(inDate)
  {
     dateComponent = inDate.split("/");

     if (dateComponent.length == 1)
     {
        dateComponent = inDate.split("-");

        if (dateComponent.length == 1)
        {
           dateComponent = inDate.split(".");

           if (dateComponent.length == 1)
           {
              alert('Your date input is not valid.');
              return false;
           }
        }
     }

     if(dateComponent.length == 2)
     {
        today     = new Date();
        var inMth = dateComponent[0];
        var inDay = dateComponent[1];
        var inYr  = today.getYear();
     }
     else if(dateComponent.length == 3)
     {
        if(dateComponent[2].length == 4) //if it is like 05-05-2005, the last component will be the year
        {
          var inDay = dateComponent[0];
          var inMth = dateComponent[1];
          var inYr  = dateComponent[2];
        }
        else
        {
          var inYr  = dateComponent[0];
          var inMth = dateComponent[1];
          var inDay = dateComponent[2];
        }
     }

     inMth = inMth -1;

     inMth = (inMth.length == 1) ? "0" + inMth : inMth;
     inDay = (inDay.length == 1) ? "0" + inDay : inDay;
     inYr  = (inYr.length  == 2) ? "20" + inYr : inYr ;

     var theDate = new Date(inYr, inMth, inDay);

     return theDate;
  }

  //*****************************************************************************************
  // Calculate the TO date given the FROM date and the interval between the FROM and TO date
  // Written by H.H.Ng
  // Date: 23/Aug/04, rev1:16/Feb/05
  //*****************************************************************************************
  function getToDate(theInDt, numOfDays)
  {
     num = new Number(numOfDays);

     var inDate  = theInDt;
     var theDate = new Date();

     theDate = convertDate(inDate);

     if(theDate == false)
       return "";

     theDate.setDate(theDate.getDate() + num);

     return theDate.getYear() + "-" + pad(theDate.getMonth() + 1) + "-" + pad(theDate.getDate());
  }

  //*****************************************************************************************
  // To pad a number smaller than 10 with a leading zero (used for getToDate)
  // Written by H.H.Ng
  // Date: 09/May/05
  //*****************************************************************************************
  function pad(intnum)
  {
    return intnum = (intnum < 10) ? '0' + intnum : intnum;
  }

  //******************************************************************************
  // Round a floating point number to only 2 decimal places
  // NB: need to add 0.0001 because if not 2.3 will become 2.29 under it
  // Written by H.H.Ng
  // Date: 03/May/05
  //******************************************************************************
  function roundDecimal(val)
  {
    var num = new Number(val);
    var amt = new Number();

    amt = Math.round((num+0.0001)*100)/100;

    return parseFloat(amt);
  }

  function decimalCut4(val)
  {
    var num = new Number(val);
    var amt = new Number();

    amt = Math.floor((num+0.000001)*10000)/10000;

    return parseFloat(amt);
  }

  //****************************************
  // Dialog box pop up for combo boxes
  // Written by H.H.Ng
  // Date: 19/Jul/05
  //****************************************
  var glDWin     = null;                   //global variable to keep the status of dialog box window
  var glCurField = null;                   //global variable to indicate if this is the current field
  var glMainWind = window.dialogArguments; //global variable to keep the arguments that are sent to the dialog box window
  var glArrCd    = new Array();

  //to open the dialog window with the given sURL
  function openDialog(obj, sURL)
  {
    var myObject  = new Object(obj); //initialise an object to pass arguments to the dialog window
    myObject.wind = window;          //initialise the window variable so as to access the global variables from the dialog window

    //if user is not on the same text field, we reload the dialog box again
    if(obj.name != glCurField)
    {
      glCurField = obj.name; //set the current textfield to this object's name

      if(glDWin != null) //if a dialog box has been opened, we closed it first before opening it
        glDWin.close();

      glDWin = window.showModelessDialog(sURL, myObject, "dialogWidth:600px; dialogHeight:385px; dialogLeft:400px; dialogTop:200px; center:no; help:no; resizable:yes; status:no;");
    }
    else //user is still on the same textfield, so we just scroll the opened dialog box to the relevant spot
      glDWin.newXY(obj.value);

    return true;
  }

  //to be called onload and by the parent window to scroll to the position of the starting alphabets
  function newXY(str)
  {
    for(var i=0; i<glArrCd.length; i++)
    {
      //if the name of the link is more than or the same as the user's entry, set the "Yaxis coordinate" to it
      if(glArrCd[i].toUpperCase() >= str.toUpperCase())
      {
        var Yaxis = (i*21); //21 is determined by trial and error depending on the cellpadding, cellspacing, border and font size
        break; //if we have found the entry, break out of the loop and scroll to the entry
      }
    }

    scrollTo(0,Yaxis); //scroll to the desired position
    glMainWind.form.elements[glMainWind.name].focus(); //retain the focus on the textbox

    return true;
  }

  //closing of the dialog box involves resetting the global variables
  function closeWin()
  {
    glMainWind.wind.glDWin     = null;
    glMainWind.wind.glCurField = null;
    window.close();
  }

  //*****************************************************************************************
  // To highlight and de-highlight a row in a table with an onmouseover and onclick event
  // Written by H.H.Ng
  // Date: 23/Aug/04
  //*****************************************************************************************
  function setPointer(theRow, theRowNum, theAction, theDefaultColor, thePointerColor, theMarkColor)
  {
     var marked_row = new Array; // This array is used to remember mark status of rows in browse mode
     var theCells = null;

     // 1. Pointer and mark feature are disabled or the browser can't get the
     //    row -> exits
     if((thePointerColor == '' && theMarkColor == '') || typeof(theRow.style) == 'undefined')
       return false;

     // 2. Gets the current row and exits if the browser can't get it
     if(typeof(document.getElementsByTagName) != 'undefined')
       theCells = theRow.getElementsByTagName('td');
     else if(typeof(theRow.cells) != 'undefined')
       theCells = theRow.cells;
     else
       return false;

     // 3. Gets the current color...
     var rowCellsCnt  = theCells.length;
     var domDetect    = null;
     var currentColor = null;
     var newColor     = null;

     // 3.1 ... with DOM compatible browsers except Opera that does not return
     //         valid values with "getAttribute"
     if (typeof(window.opera) == 'undefined' && typeof(theCells[0].getAttribute) != 'undefined')
     {
        currentColor = theCells[0].getAttribute('bgcolor');
        domDetect    = true;
     }
     else // 3.2 ... with other browsers
     {
        currentColor = theCells[0].style.backgroundColor;
        domDetect    = false;
     } // end 3

     // 3.3 ... Opera changes colors set via HTML to rgb(r,g,b) format so fix it
     if (currentColor.indexOf("rgb") >= 0)
     {
        var rgbStr    = currentColor.slice(currentColor.indexOf('(') + 1, currentColor.indexOf(')'));
        var rgbValues = rgbStr.split(",");
        var hexChars  = "0123456789ABCDEF";
        currentColor  = "#";

        for (var i = 0; i < 3; i++)
        {
           var v = rgbValues[i].valueOf();
           currentColor += hexChars.charAt(v/16) + hexChars.charAt(v%16);
        }
     }

     // 4. Defines the new color
     // 4.1 Current color is the default one
     if (currentColor == '' || currentColor.toLowerCase() == theDefaultColor.toLowerCase())
     {
        if (theAction == 'over' && thePointerColor != '')
           newColor = thePointerColor;
        else if (theAction == 'click' && theMarkColor != '')
        {
           newColor              = theMarkColor;
           marked_row[theRowNum] = true;
        }
     }
     // 4.1.2 Current color is the pointer one
     else if (currentColor.toLowerCase() == thePointerColor.toLowerCase() &&
             (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum]))
     {
        if (theAction == 'out')
           newColor = theDefaultColor;
        else if (theAction == 'click' && theMarkColor != '')
        {
           newColor              = theMarkColor;
           marked_row[theRowNum] = true;
        }
     }
     // 4.1.3 Current color is the marker one
     else if (currentColor.toLowerCase() == theMarkColor.toLowerCase())
     {
        if (theAction == 'click')
        {
           newColor              = (thePointerColor != '') ? thePointerColor : theDefaultColor;
           marked_row[theRowNum] = (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum])
                                  ? true
                                  : null;
        }
     } // end 4

     // 5. Sets the new color...
     if (newColor)
     {
        var c = null;

        // 5.1 ... with DOM compatible browsers except Opera
        if (domDetect)
          for (c = 0; c < rowCellsCnt; c++)
            theCells[c].setAttribute('bgcolor', newColor, 0);
        else // 5.2 ... with other browsers
          for (c = 0; c < rowCellsCnt; c++)
            theCells[c].style.backgroundColor = newColor;
     } // end 5

    return true;
  } // end of the 'setPointer()' function

  //***********************************************************************
  // Function for setting and deleting and retrieving the value of cookies
  // Written by H.H.Ng
  // Date: 23/Aug/04
  //************************************************************************
  // utility function to retrieve a future expiration date in proper format;
  // pass three integer parameters for the number of days, hours,
  // and minutes from now you want the cookie to expire; all three
  // parameters required, so use zeros where appropriate
  function getExpDate(days, hours, minutes)
  {
     var expDate = new Date();
     if (typeof days == "number" && typeof hours == "number" && typeof minutes == "number")
     {
        expDate.setDate(expDate.getDate() + parseInt(days));
        expDate.setHours(expDate.getHours() + parseInt(hours));
        expDate.setMinutes(expDate.getMinutes() + parseInt(minutes));
        return expDate.toGMTString();
     }
  }

  // utility function called by getCookie()
  function getCookieVal(offset)
  {
     var endstr = document.cookie.indexOf (";", offset);

     if (endstr == -1)
        endstr = document.cookie.length;

     return unescape(document.cookie.substring(offset, endstr));
  }

  // primary function to retrieve cookie by name
  function getCookie(name)
  {
     var arg = name + "=";
     var alen = arg.length;
     var clen = document.cookie.length;
     var i = 0;

     while (i < clen)
     {
        var j = i + alen;

        if (document.cookie.substring(i, j) == arg)
            return getCookieVal(j);

        i = document.cookie.indexOf(" ", i) + 1;

        if (i == 0)
          break;
     }

     return null;
  }

  // store cookie value with optional details as needed
  function setCookie(name, value, expires, path, domain, secure)
  {
     document.cookie = name + "=" + escape (value) +
                       ((expires) ? "; expires=" + expires : "") +
                       ((path)    ? "; path=" + path       : "") +
                       ((domain)  ? "; domain=" + domain   : "") +
                       ((secure)  ? "; secure"             : "");
  }

  // remove the cookie by setting ancient expiration date
  function deleteCookie(name, path, domain)
  {
     if (document.cookie.indexOf(name) != -1)
     {
        document.cookie = name + "=" +
                          ((path)   ? "; path=" + path     : "") +
                          ((domain) ? "; domain=" + domain : "") +
                          "; expires=Thu, 04-Jan-01 00:00:01 GMT";
     }
  }

  //set the page that is to be printed to be at "print preview"; added 15/02/05
  function printPreview()
  {
     var OLECMDID = 7;
     /* OLECMDID values:
      * 6 - print
      * 7 - print preview
      * 1 - open window
      * 4 - Save As
     */

     var PROMPT = 1; // 1 PROMPT & 2 DONT PROMPT USER
     var WebBrowser = '<OBJECT ID="WebBrowser1" WIDTH=0 HEIGHT=0 CLASSID="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2"></OBJECT>';

     document.body.insertAdjacentHTML('beforeEnd', WebBrowser);
     WebBrowser1.ExecWB(OLECMDID, PROMPT);
     WebBrowser1.outerHTML = "";
  }

  //bring the cursor to the first form element. this is a user-friendly tool
  function focusFirstElem()
  {
     for (i = 0; i < document.forms[0].elements.length; i++)
     {
        if (((ns4) || (ie4)) && (document.forms[0].elements[i].type != "hidden"))
        {
           document.forms[0].elements[i].focus();
           break;
        }
     }
  }

  //this allows only integers to be entered in a form field. added 02/Feb/05
  function integersOnly(evt)
  {
    evt = (evt) ? evt : event;
    var charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode : ((evt.which) ? evt.which : 0));

    if (charCode > 31 && (charCode < 48 || charCode > 57))
    {
      alert("Enter integers only in this field.");
      return false;
    }

    return true;
  }

  /************************************************************************/
  /* To change an image upon mouse hovering an image and to change back to*/
  /* the original image upon mouse out                                    */
  /************************************************************************/
  function swImg(iName,str)
  {
    document.images[iName].src = str;
    return;
  }