// ========================================================================================================================
// ========================================================================================================================
// Date             Name                Changes
/* -------------    -------------       --------------------------------------------------------------------
   11/09/2004       Tony Maynard        Created.
   11/16/2004       Tony Maynard        Added the CheckBrowserType() function.
   04/12/2005       Tony Maynard        Changed OpenLink() and OpenWindow() functions to use document.body.clientWidth/clientHeight
                                        instead of window.offsetWidth/offsetHeight.
   03/28/2006       Tony Maynard        Copied isNumber to isInteger. The only difference being isNumber allows the "." character.
   06/01/2006       Tony Maynard        Updated for Firefox.
   06/06/2006       Tony Maynard        Added SetVisibility function.
   10/13/2006       Tony Maynard        Added the String.trim function.
   03/08/2007       Tony Maynard        Added the OpenPrintWindow function. E-SESS uses this to dump report contents into a new
                                        window with no images or borders. The PrintTemplate.html page loads the opener's content div.
   03/15/2007       Tony Maynard        Added some new functions: GetClassName, SetClassName, ChangeClassName, and ToggleMenu.
   04/11/2007       Tony Maynard        Added some new functions: createRequestObject, handleEmailResponse, CallEmail.
   04/16/2007       Tony Maynard        Added BubbleSort function. Used to sort javascript arrays: aryName.sort(BubbleSort).
   07/05/2007       Tony Maynard        Added a bunch of functions to handle the standards selection navigation. They are used by
                                        ManageItems, and several standards-based reports.
   07/26/2007       Tony Maynard        Added the generic AJAX stuff that Jeremy created.
   07/27/2007       Tony Maynard        Added the StripNoPrint function. The CallEmail function uses it to remove NoPrint items
                                        before sending the e-mail. That way the e-mail SHOULD resemble the print version.
   08/30/2007       Tony Maynard        Modified answerServer to capture and discard the Firefox false error due to AJAX. The
                                        answerServer function was looking for Asynchronous in the sendObject, but it is included
                                        in the serverData, so it was never used. I also added the DelayScript(milli) function
                                        which pauses for the number of passed in milliseconds.
   09/18/2007       Tony                I added the EscapeQuotes function.
   10/15/2007       Tony                I fixed the AJAX standard selection. It was not checking Down properly for standard sets.
                                        I added stripslashes and addslashes functions.
   10/31/2007       Tony                Modified CallEmail to create RequestObject if it doesn't already exist. That way all
                                        the reports that JUST use the RequestObject to send the e-mail do not have to declare it.
   11/13/2007       Tony                Added the StripWhitespace(Content) function and modified CallEmail to try PrintContent
                                        first, then go for content.
   12/12/2007       Tony                Removed the width and height specification from OpenWindow.
   01/27/2008       Tony                Rewrote CheckBrowserType(). It now more accurately gets the browser name and version.
   06/10/2009		Tony				Added callServer2 function, which uses json2.js.

   All functions included here should be in alphabetical order.
*/
// ========================================================================================================================
// ========================================================================================================================

var MouseOverVisible = 0;
var MacToolTipVisible = 0;

// =======================================================================================================================================
function ClearContents(ClearElement)
{
    while (document.getElementById(ClearElement).childNodes[0])
        document.getElementById(ClearElement).removeChild(document.getElementById(ClearElement).childNodes[0]);

    document.getElementById(ClearElement).innerHTML = "";
}

// =======================================================================================================================================
function EscapeQuotes(OrigStr, Type)
{
    if (Type == "double" || Type == "both")
        tmpVal = OrigStr.replace(/["]/g, "\\\"");

    if (Type == "single" || Type == "both")
    tmpVal = tmpVal.replace(/[']/g, "\\\'");
    return tmpVal;
}

// =======================================================================================================================================
function stripslashes(str)
{
    str=str.replace(/\\'/g,'\'');
    str=str.replace(/\\"/g,'"');
    str=str.replace(/\\\\/g,'\\');
    str=str.replace(/\\0/g,'\0');
    return str;
}

// =======================================================================================================================================
function addslashes(str)
{
    str=str.replace(/\'/g,'\\\'');
    str=str.replace(/\"/g,'\\"');
    str=str.replace(/\\/g,'\\\\');
    str=str.replace(/\0/g,'\\0');
    return str;
}

// =======================================================================================================================================
function answerServer(RequestObject,respHandler,handleData)
{
    var status = "";
    try{
        status = RequestObject.status;
    }
    catch(e){
        status = "Firefox error trap";
    }

    if(RequestObject.readyState==4)
    {
        if(status==200)
        {
            eval(respHandler+"(RequestObject.responseText,handleData)");
        }
        else if (status != "Firefox error trap")
            alert("There was a communication error: " + status);
        RequestObject = null;
    }
}

// ========================================================================================================================
function callServer(serverAction,serverData,respHandler,handleData){
  var RequestObject = createRequestObject();          //creates an object to handle communication with the server
  var sendObject = new Object;                        //Creates an object to store data to send to the server this infomation includes:
  sendObject.serverAction = serverAction;             //The name of the function to run on the server
  sendObject.serverData=serverData;                   //Paramaters that function will need
  if(serverData.pageName)
    pageName =serverData.pageName;
  else
    pageName='AjaxCommands.php';
  var respHandler = respHandler;                      //js function name to handle the server response
  // normally, Asyncronous will not even exist, so it will call open with "true" in the else section
  if (serverData.Asyncronous == "false")
      RequestObject.open('post',pageName,false);
  else
      RequestObject.open('post',pageName,true);

  // make sure answerServer still exists when the window was actually closed before this function completes.
  RequestObject.onreadystatechange = function(){ answerServer(RequestObject,respHandler,handleData)};
  RequestObject.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  RequestObject.send(sendObject.toJSONString());
}

//========================================================================================================================
//this only varies from callServer in that it uses json2.js, which is newer    
function callServer2(serverAction,serverData,respHandler,handleData){
var RequestObject = createRequestObject();          //creates an object to handle communication with the server
var sendObject = new Object;                        //Creates an object to store data to send to the server this infomation includes:
sendObject.serverAction = serverAction;             //The name of the function to run on the server
sendObject.serverData=serverData;                   //Paramaters that function will need
if(serverData.pageName)
 pageName =serverData.pageName;
else
 pageName='AjaxCommands.php';
var respHandler = respHandler;                      //js function name to handle the server response
// normally, Asyncronous will not even exist, so it will call open with "true" in the else section
if (serverData.Asyncronous == "false")
   RequestObject.open('post',pageName,false);
else
   RequestObject.open('post',pageName,true);

// make sure answerServer still exists when the window was actually closed before this function completes.
RequestObject.onreadystatechange = function(){ answerServer(RequestObject,respHandler,handleData)};
RequestObject.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
RequestObject.send(JSON.stringify(sendObject));
} // end function callServer2(serverAction,serverData,respHandler,handleData){

// ========================================================================================================================
function CallStandardAsync(OrganizationID, StandardSetID, ParentStandardID, ChildStandardID, CurrentStandard)
{
    // If all three fields are null, then get a list of Standard Sets
    // If both Parent and Child are null, then get standards where Parent IS NULL
    // If ParentStandardID is set, get all Standards where the ParentID = $ParentStandardID
    // If ChildStandardID is set, get all Standards of Child's Parent's Parent
    SendString = "OrganizationID=" + OrganizationID + "&StandardSetID=" + StandardSetID + "&ParentStandardID=" + ParentStandardID + "&ChildStandardID=" + ChildStandardID + "&CurrentStandard=" + CurrentStandard;
//alert('sending: ' + SendString);
    RequestObject.open('post', 'GetStandards.php');
    RequestObject.onreadystatechange = handleStandardResponse;
    RequestObject.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    RequestObject.send(SendString);
}

// ========================================================================================================================
//handle the response from AJAX calls
function handleStandardResponse()
{
/*
readyState possible values:
0 = uninitialized
1 = loading
2 = loaded
3 = interactive
4 = complete

status is the server code, such as 404 for not found, or 200 for ok
statusText is the text message accompanying status

responseText is the string version of data returned from the server process

responseXML is the DOM-compatible document object of data returned
*/

    // readyState 4 means the update finished
    if ( RequestObject.readyState == 4)
    {
        // 200 status means the update completed successfully
        if (RequestObject.status == 200)
        {
//alert('async returned: ' + RequestObject.responseText);
          document.getElementById("divStandards").innerHTML = RequestObject.responseText;
          if (document.getElementById("lstStandardSets"))
          {
             // if the standard set list exists, disable the up function
             document.getElementById("btnStandardsUp").disabled = true;
          }
          else
          {
             // if the standard set list does NOT exist, enable the up function
             document.getElementById("btnStandardsUp").disabled = false;
          }
          OnStandardChange(); // disable/enable Down as needed.
        }
        else
        {
          document.getElementById("divStandards").innerHTML = 'error!! Problem occurred: ' + RequestObject.statusText;
        }
    }
}

// ========================================================================================================================
function MoveUpStandard()
{
    StandardSetID = document.getElementById("hdnStandardSetID").value;
    ChildStandardID = document.getElementById("lstStandards").value;
    CallStandardAsync(OrganizationID, StandardSetID, "", ChildStandardID, "");
}

// ========================================================================================================================
function MoveDownStandard()
{
    if (document.getElementById("lstStandardSets"))
    {
        StandardSetID = document.getElementById("lstStandardSets").value;
        CallStandardAsync(OrganizationID, StandardSetID, "", "", "");
    }
    else
    {
        StandardSetID = document.getElementById("hdnStandardSetID").value;
        ParentStandardID = document.getElementById("lstStandards").value;
        CallStandardAsync(OrganizationID, StandardSetID, ParentStandardID, "", "");
    }
}

// ========================================================================================================================
function OnStandardChange()
{
    if (document.getElementById("lstStandards"))
    {
        if (document.getElementById("lstStandards").selectedIndex == undefined)
            tmpInd = 0;
        else
            tmpInd = document.getElementById("lstStandards").selectedIndex;

        tmpRef = document.getElementById("lstStandards");
        if (tmpRef[tmpInd].getAttribute('HasChildren') == 1)
        {
            document.getElementById("btnStandardsDown").disabled = false;
        }
        else
        {
            document.getElementById("btnStandardsDown").disabled = true;
        }
    }
    else if (document.getElementById("lstStandardSets"))
    {
        if (document.getElementById("lstStandardSets").selectedIndex == undefined)
            tmpInd = 0;
        else
            tmpInd = document.getElementById("lstStandardSets").selectedIndex;

        tmpRef = document.getElementById("lstStandardSets");
        if (tmpRef[tmpInd].getAttribute('HasChildren') == 1)
        {
            document.getElementById("btnStandardsDown").disabled = false;
        }
        else
        {
            document.getElementById("btnStandardsDown").disabled = true;
        }
    }
    else
    {
        document.getElementById("btnStandardsUp").disabled = true;
    }
}


//===========================================================================================================
    function BubbleSort(a,b)
    {
        return(a-b);
    }

//===========================================================================================================
    function CallEmail(Subject, EmailAddress)
    {
        // create the request object if it doesn't already exist.
        if (typeof(RequestObject) == "undefined")
        {
           RequestObject = createRequestObject();
        }

        if (EmailAddress == "")
            EmailAddress = prompt("Please supply a return e-mail address.", "");
        // if they still did not provide an e-mail address, then just cancel out.
        if (EmailAddress == null)
            return;

        if (document.getElementById("PrintContent"))
        {
            tmpBody = document.getElementById("PrintContent").innerHTML;
            tmpBody = StripWhitespace(tmpBody);
            tmpBody = StripNoPrint(tmpBody);
        }
        else if (document.getElementById("content"))
        {
            tmpBody = document.getElementById("content").innerHTML;
            tmpBody = StripWhitespace(tmpBody);
            tmpBody = StripNoPrint(tmpBody);
        }
        // clean tmpBody up for passing special chars
        tmpBody = escape(tmpBody);
        SendString = "subject=" + Subject + "&body=" + tmpBody + "&to=" + document.getElementById("EmailAddress").value + "&from=" + EmailAddress;
        document.getElementById("EmailAddress").enabled = false;
        // SendEmail expects the following to be passed in: $subject, $body, $to, $from, $attachments
        RequestObject.open('post', '../SendEmail.php');
        RequestObject.onreadystatechange = handleEmailResponse;
        RequestObject.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        RequestObject.send(SendString);
    }

/* ==========================================================================================================
   This function removes all the excess white space from the string. In AJAX calls, this will reduce
   the amount of data passed back and forth.
========================================================================================================== */
    function StripWhitespace(Content)
    {
        Content = Content.replace(/\s*/i, "");
        return Content;
    } // end function StripWhitespace(Content)

/* ==========================================================================================================
   This function removes all the code in any HTML tags that have a class of NoPrint
========================================================================================================== */
    function StripNoPrint(Content)
    {
        var TagCount = 0;
        var Iterations = 0;
        // if NoPrint is nowhere in the string, then just return the string as is
        while(Content.indexOf("NoPrint") > -1)
        {
            NoPrintPosition = Content.indexOf("NoPrint");

            // find the first "<" BEFORE this point
            TagPosition = Content.lastIndexOf("<", NoPrintPosition) + 1;
            CutFrom = TagPosition-1;

            // get the tag type
            EndTagPosition = Content.indexOf(" ", TagPosition);
            TagType = Content.substring((TagPosition), EndTagPosition);
            TagCount++;
            // don't cut out tables.
            if (TagType == "table")
                TagCount = 0;

            // now find the matching closing tag (be sure to find the MATCH and not just the NEXT closing tag)
            while(TagCount > 0)
            {
                TagPosition = Content.indexOf("<", TagPosition)+1;
                ClosePosition = Content.indexOf(">", TagPosition)-1;
                if (Content.substr(ClosePosition, 2) == "/>")
                    TagClosedItself = 1;
                else
                    TagClosedItself = 0;

                if (TagPosition == 0)
                {
                    alert('ERROR! There are no more tags and there are ' + TagCount + ' tags still open.' + '\n' + Content);
                    TagCount = 0;
                    return Content;
                }
                if (Content.substr(TagPosition, 1) == "/")
                {
                    TagCount--; // closed a tag
//                    alert('Closed tag: ' + Content.substr((TagPosition-1), 15));
                }
                 // exclude HTML comments, br tags, img tags, and input tags
                else if (Content.substr(TagPosition, 1) != "!" && Content.substr(TagPosition, 2) != "br" && Content.substr(TagPosition, 3) != "img" && Content.substr(TagPosition, 5) != "input" && TagClosedItself == 0)
                {
                    TagCount++; // opened a tag
//                    alert('Opened tag: ' + Content.substr((TagPosition-1), 15));
                }

                if (Iterations > 10000)
                {
                    alert('hit 10000 iterations, so diving out to prevent crash');
                    TagCount = 0;
                }
                Iterations++;
            }
            CutTo = Content.indexOf(">", TagPosition+1)+1;
            Content = Content.substring(0, CutFrom) + Content.substring(CutTo);
        }
        return Content;
    } // end function StripNoPrint(Content)

//===========================================================================================================
    function ChangeGraphic(objName, graphicName)
    {
        document.getElementById(objName).src = graphicName;
    }

//===========================================================================================================
  function CheckBrowserType()
  {
      // userAgent has all the REAL browser info in it.
      UserAgentString = navigator.userAgent;

      // you MUST check for Opera first because it masquerades as IE
      if(UserAgentString.indexOf("Opera")!=-1)
      {
          BrowserName = "Opera";
          var versionindex=UserAgentString.indexOf("Opera")+6;
          var endversionindex=UserAgentString.indexOf(" ", versionindex);
          if (endversionindex == -1)
              endversionindex = UserAgentString.length;
          BrowserVersion = UserAgentString.substr(versionindex, (endversionindex-versionindex) );
      }
      else if(UserAgentString.indexOf("Firefox")!=-1)
      {
          BrowserName = "Firefox";
          var versionindex=UserAgentString.indexOf("Firefox")+8;
          var endversionindex=UserAgentString.indexOf(" ", versionindex);
          if (endversionindex == -1)
              endversionindex = UserAgentString.length;
          BrowserVersion = UserAgentString.substr(versionindex, (endversionindex-versionindex) );
      }
      else if(UserAgentString.indexOf("MSIE")!=-1)
      {
          BrowserName = "IE";
          var versionindex=UserAgentString.indexOf("MSIE")+5;
          var endversionindex=UserAgentString.indexOf(";", versionindex);
          if (endversionindex == -1)
              endversionindex = UserAgentString.length;
          BrowserVersion = UserAgentString.substr(versionindex, (endversionindex-versionindex) );
      }
      else
      {
          BrowserName = "Unknown";
          BrowserVersion = "Unknown";
      }
  }

//===========================================================================================================
    // if its not IN a text type area, do NOT allow backspace or ALT <- to go back a page in the history.
    function CheckBackspace(e)
    {
        if (!e)
          e = window.event;
        if (e.altKey && e.keyCode == 37)
        {
          e.keyCode = 0;
          e.returnValue = false;
          alert('This function has been disabled.');
        }

        target=window.event? event.srcElement : e.target;
        if( e.keyCode==8 && target.type != "text" &&
           target.type != "textarea" && target.type != "password")
        {
          if (window.event)
            e.keyCode = 0;
          e.returnValue = false;
        }
    }

//===========================================================================================================
    function CheckExistence(objName)
    {
        if (objName != null)
            return (1);
        else
            return (0);
    }

// ==========================================================================================================
// return a newly created Request Object for making AJAX requests
    function createRequestObject()
    {
        // IE 6- uses the ActiveXObject, all others use XMLHttpRequest (including IE7
        return window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
    }

// ========================================================================================================================
function DelayScript(millis)
{
    var date = new Date();
    var curDate = null;

    do { curDate = new Date(); }
    while(curDate-date < millis);
}

// ========================================================================================================================
//handle the response from AJAX calls
function handleEmailResponse()
{
/*
readyState possible values:
0 = uninitialized
1 = loading
2 = loaded
3 = interactive
4 = complete

status is the server code, such as 404 for not found, or 200 for ok
statusText is the text message accompanying status

responseText is the string version of data returned from the server process

responseXML is the DOM-compatible document object of data returned
*/
    // readyState 4 means the update finished
    if ( RequestObject.readyState == 4)
    {
        // 200 status means the update completed successfully
        if (RequestObject.status == 200)
        {
          alert('RequestObject.status ' + RequestObject.responseText);
        }
        else
        {
          alert('error!! Problem occurred: ' + RequestObject.statusText);
        }
        document.getElementById("EmailAddress").value = "";
        document.getElementById("EmailAddress").enabled = true;
    }
}
//===========================================================================================================
    function HideMouseHelp()
    {
      document.getElementById("MouseHelp").style.visibility = "hidden";
    }

//===========================================================================================================
    function isInteger(TestVal)
    {
      // This function checks to see if there are any values in TestVal that are NOT numbers.
      // It returns true if it is an integer, false if it contains any other characters.
      // ascii values of 0-9 are 48-57

      TestString = '0123456789';
      ReturnVal = true;
      if (TestVal.length == 0)
          ReturnVal = false;
      else
      {
        for (x=0; x <= (TestVal.length-1); x++)
        {
            if (TestString.indexOf(TestVal.substr(x, 1)) == -1)
               ReturnVal = false;
        }
      }
      return ReturnVal;
    }

//===========================================================================================================
    function isNumber(TestVal)
    {
      // This function checks to see if there are any values in TestVal that are NOT numbers.
      // It returns true if it is numeric, false if it contains any other characters.
      // ascii values of 0-9 are 48-57

      TestString = '0123456789.';
      ReturnVal = true;
      if (TestVal.length == 0)
          ReturnVal = false;
      else
      {
        for (x=0; x <= (TestVal.length-1); x++)
        {
            if (TestString.indexOf(TestVal.substr(x, 1)) == -1)
               ReturnVal = false;
        }
      }
      return ReturnVal;
    }

//===========================================================================================================
    function isMonetaryNumber(TestVal)
    {
      // This function checks to see if there are any values in TestVal that are NOT numbers.
      // It returns true if it is numeric, false if it contains any other characters.
      // ascii values of 0-9 are 48-57

      TestString = '0123456789.';
      ReturnVal = true;
      if (TestVal.length == 0)
          ReturnVal = false;
      else
      {
        for (x=0; x <= (TestVal.length-1); x++)
        {
            if (TestString.indexOf(TestVal.substr(x, 1)) == -1)
               ReturnVal = false;
        }
      }

      // make sure if there IS a decimal, it only occurs once, and there are 2 digits behind it.
      if (TestVal.indexOf('.') != TestVal.lastIndexOf('.') || (TestVal.length - TestVal.indexOf('.')) != 3)
        ReturnVal = false;

      return ReturnVal;
    }

//===========================================================================================================
    function isString(TestVal)
    {
      // ascii values of a-z are 97-123 and A-Z are 65-91
      TestString='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
      ReturnVal = true;
      if (TestVal.length == 0)
          ReturnVal = false;
      else
      {
        for (x=0; x<=(TestVal.length-1); x++)
        {
            if (TestString.indexOf(TestVal.substr(x, 1)) == -1)
                ReturnVal = false;
        }
      }
      return ReturnVal;
    }

//==================================================================================================================
    function isAlphanumeric(TestVal)
    {
      // This function checks to see if there are any values in TestVal that are NOT numbers, letters or spaces
      // It returns true if it is alphanumeric, false if it contains other characters.
      // ascii values of a-z are 97-123 and A-Z are 65-91

      TestString=' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
      ReturnVal = true;
      if (TestVal.length == 0)
          ReturnVal = false;
      else
      {
        for (x=0; x<=(TestVal.length-1); x++)
        {
            if (TestString.indexOf(TestVal.substr(x, 1)) == -1)
                ReturnVal = false;
        }
      }
      return ReturnVal;
    }

//==================================================================================================================
    function isName(TestVal)
    {
      // This function checks to see if there are any values in TestVal that are NOT typically in a name.
      // It returns true if it is acceptable, false if it contains other characters.
      // ascii values of a-z are 97-123 and A-Z are 65-91
      TestString="'- abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
      ReturnVal = true;
      if (TestVal.length == 0)
          ReturnVal = false;
      else
      {
        for (x=0; x<=(TestVal.length-1); x++)
        {
            if (TestString.indexOf(TestVal.substr(x, 1)) == -1)
                ReturnVal = false;
        }
      }
      return ReturnVal;
    }

//===========================================================================================================
    function isValidDate(TheDate)
    {
      // Accepts a string: mm/dd/yyyy. Returns 1 if its valid, 0 if its invalid.
      // convert the string into a new date, then break it back into the components.
      // if the orig components match the new ones, then its ok.
      // if its invalid, they won't match.

      myDate = new Date(Date.parse(TheDate));
      newYear = myDate.getFullYear();
      newMonth = myDate.getMonth()+1;
      newDay = myDate.getDate();
      if (varYear == newYear && varMonth == newMonth && varDay == newDay)
      {
          return 1;
      }
      else
      {
          return 0;
      }
    }

//===================================================================================================================
function OpenLink(PageName, WindowName)
    {
      // no menu bar
      Config='toolbar=yes,location=no,directories=no,status=yes,menubar=no,screenX=0,screenY=0,width=' + (document.body.clientWidth+15) + ',height=' + (document.body.clientHeight+20) + ',scrollbars=yes,resizable=yes'
      pop = window.open (PageName,WindowName,Config)
    }

//===========================================================================================================
    function OpenPrintWindow()
    {
        wndPrint = window.open ("PrintTemplate.html", "mywindow");
    }

//===================================================================================================================
function OpenStripped(PageName, WindowName)
    {
      // no nothing. just a window with a title bar and status bar.
      Config='toolbar=no,location=no,directories=no,status=yes,menubar=no,screenX=0,screenY=0,width=800px,height=600px,scrollbars=yes,resizable=yes'
      pop = window.open (PageName,WindowName,Config)
    }

//===================================================================================================================
function OpenWindow(PageName, WindowName)
    {
      // Same as open link, but this one allows access to the menubar.
      Config='toolbar=yes,location=no,directories=no,status=yes,menubar=yes,screenX=0,screenY=0,scrollbars=yes,resizable=yes'
      pop = window.open (PageName,WindowName,Config)
    }

//===========================================================================================================
    function PicLoader_OnError(GP)
    {
      clearTimeout();
      tmpGP = GP.substr(0, 26);
      if (tmpGP == "http://www.techfluency.org")
      {
          alert('ERROR : Missing image <' + document.getElementById("PicLoader").src + '>. Please contact your administrator to report this error.');
      }
      else
      {
          alert('ERROR (' + document.getElementById("PicLoader").src + '): The graphics could not be found in the <' + GP + '> directory. Please REFRESH the Menu and try reloading the assessment. If this error persists, contact your administrator.');
      }
    }

//===========================================================================================================
    function Quit_OnClick()
    {
        MenuWindow = window.opener;
        MenuWindow.focus();
        MenuWindow.UpdatePage();
        self.close();
    }

    function Quit_OnMouseOver(e)
    {
        if (!e) var e = window.event;
        if (e.pageX || e.pageY)
        {
         posx = e.pageX;
         posy = e.pageY;
        }
        else if (e.clientX || e.clientY)
        {
          posx = e.clientX + document.body.scrollLeft;
          posy = e.clientY + document.body.scrollTop;
        }

        document.getElementById("btnQuit").style.cursor = "pointer";
        document.getElementById("btnQuit").src = "Graphics/CloseWindow_Over.gif";
        MouseOverVisible = 1;
        document.getElementById("MouseHelp").innerHTML = "This button will close this window and return you to the menu.";
        document.getElementById("MouseHelp").style.left = (posx+5) + "px";
        document.getElementById("MouseHelp").style.top = (posy+20) + "px";
        document.getElementById("MouseHelp").style.visibility = "visible";
    }

    function Quit_OnMouseOut()
    {
        document.getElementById("btnQuit").src = "Graphics/CloseWindow_Up.gif";
        HideMouseHelp();
    }

//===========================================================================================================
    function QuitMac_OnClick()
    {
        MenuWindow = window.opener;
        MenuWindow.focus();
        MenuWindow.UpdatePage();
        self.close();
    }

//===========================================================================================================
    function Restart_OnMouseOver(e)
    {
        if (!e) var e = window.event;
        if (e.pageX || e.pageY)
        {
         posx = e.pageX;
         posy = e.pageY;
        }
        else if (e.clientX || e.clientY)
        {
          posx = e.clientX + document.body.scrollLeft;
          posy = e.clientY + document.body.scrollTop;
        }
        document.getElementById("btnRestart").style.cursor = "pointer";
        document.getElementById("btnRestart").src = "Graphics/Reset_Over.gif";

        MouseOverVisible = 1;
        document.getElementById("MouseHelp").innerHTML = "This button will restart this item.";
        document.getElementById("MouseHelp").style.left = (posx+5) + "px";
        document.getElementById("MouseHelp").style.top = (posy+20) + "px";
        document.getElementById("MouseHelp").style.visibility = "visible";
    }

    function Restart_OnMouseOut()
    {
        document.getElementById("btnRestart").src = "Graphics/Reset_Up.gif";
        HideMouseHelp();
    }

    function Restart_OnClick()
    {
        Refreshing=1;
        tmpstr = document.URL;
        if (tmpstr.slice(tmpstr.length- 9) == "Refresh=1")
            OpenLink(document.URL, '_self')
        else
            OpenLink(document.URL + '&Refresh=1', '_self')
    }

//===========================================================================================================
    function SetVisibility(Elem, State)
    {
      document.getElementById(Elem).style.visibility = State;
    }

//===========================================================================================================
    function ShowMousePos(e)
    {
        if (!e) var e = window.event;
        if (e.pageX || e.pageY)
        {
         posx = e.pageX;
         posy = e.pageY;
        }
        else if (e.clientX || e.clientY)
        {
          posx = e.clientX + document.body.scrollLeft;
          posy = e.clientY + document.body.scrollTop;
        }
        window.status = "Y:" + (posy-2) + ", X:" + (posx-2);
    }

//===========================================================================================================
    function ShowMouseHelp(HelpText)
    {
        if (!e) var e = window.event;
        if (e.pageX || e.pageY)
        {
         posx = e.pageX;
         posy = e.pageY;
        }
        else if (e.clientX || e.clientY)
        {
          posx = e.clientX + document.body.scrollLeft;
          posy = e.clientY + document.body.scrollTop;
        }
      MouseOverVisible = 1;
      document.getElementById("MouseHelp").innerHTML = HelpText;
      document.getElementById("MouseHelp").style.left = (posx-160);
      document.getElementById("MouseHelp").style.top = (posy+5);
      document.getElementById("MouseHelp").style.visibility = "visible";
    }

//===========================================================================================================
// add this function to String. It removes leading and trailing spaces. Usage: String.trim()
String.prototype.trim = function()
{
    a = this.replace(/^\s+/, '');
    return a.replace(/\s+$/, '');
};

//===========================================================================================================
function WriteHeader(GraphicPath, HeaderText)
{
//    if ( flash6Installed )
//    {
//        // ok to use flash
//alert(GraphicPath + ', ' + HeaderText);
        document.write('<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' +
              'codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0"' +
              'WIDTH="1004" HEIGHT="109" id="TopBar" ALIGN="">' +
              '<PARAM NAME=movie VALUE="' + GraphicPath + 'TopBar.swf?pageTitle=' + HeaderText + '&pageTitleShd=' + HeaderText + '">' +
              '<PARAM NAME=quality VALUE=best>' +
              '<PARAM NAME=scale VALUE=exactfit>' +
              '<PARAM NAME=wmode VALUE=opaque>' +
              '<PARAM NAME=bgcolor VALUE=#FFFFFF>' +
              '<EMBED src="' + GraphicPath + 'TopBar.swf?pageTitle=' + HeaderText + '&pageTitleShd=' + HeaderText + '" quality=best scale=exactfit wmode=opaque bgcolor=#FFFFFF  WIDTH="1004"' +
                  'HEIGHT="109" NAME="TopBar" ALIGN="" swLiveConnect=true' +
                  'TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer"></EMBED>' +
              '</OBJECT>');
        document.close();
//    }
//    else
//    {
//        // either no flash or too old. use gif.
//        document.write('<img src="' + GraphicPath + 'TopBar.gif" style="z-index:1">' +
//             '<div style="position:absolute;top:43px;left:239px;z-index:2;font-family:arial;font-weight:bold;font-size:32pt;color:white">' + HeaderText + '</div>');
//    }
}

//==========================================================================================
function WriteHeaderSizeable(GraphicPath, HeaderText, Width)
{
        document.write('<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' +
              'codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0"' +
              'WIDTH="' + Width + '" id="TopBar" ALIGN="">' +
              '<PARAM NAME=movie VALUE="' + GraphicPath + 'TopBar.swf?pageTitle=' + HeaderText + '&pageTitleShd=' + HeaderText + '">' +
              '<PARAM NAME=quality VALUE=best>' +
              '<PARAM NAME=scale VALUE=default>' +
              '<PARAM NAME=align VALUE=top>' +
              '<PARAM NAME=salign VALUE=left>' +
              '<PARAM NAME=wmode VALUE=opaque>' +
              '<PARAM NAME=bgcolor VALUE=#FFFFFF>' +
              '<EMBED src="' + GraphicPath + 'TopBar.swf?pageTitle=' + HeaderText + '&pageTitleShd=' + HeaderText + '" quality=best scale=default wmode=opaque bgcolor=#FFFFFF  WIDTH="' + Width + '"' +
                  'NAME="TopBar" ALIGN="top" SALIGN="left" swLiveConnect=true' +
                  'TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer"></EMBED>' +
              '</OBJECT>');
        document.close();
}

//==========================================================================================
function GetClassName(ObjID)
{
//        ClassName = document.getElementById(ObjID).className ? document.getElementById(ObjID).className : document.getElementById(ObjID).class;
    ClassName = document.getElementById(ObjID).className;
    return ClassName;
}

//==========================================================================================
function SetClassName(ObjID, NewClassName)
{
    /*
        SetClassName gives the ObjID a single class - NewClassName
    */
    document.getElementById(ObjID).className = NewClassName;
}

//==========================================================================================
function ChangeClassName(ObjID, OldClassName, NewClassName)
{
    /*
        ChangeClassName modifies the existing class by changing OldClassName to NewClassName.
        This is useful for objects that have multiple classes, and you just want to change
        one of those and keep the others.
    */
    FullClassString = GetClassName(ObjID);
    FullClassString = FullClassString.replace(OldClassName, NewClassName);
    document.getElementById(ObjID).className = FullClassString;
}

//==========================================================================================
function ToggleMenu(Self, ContentDiv, e)
{
    CurrentClass = GetClassName(ContentDiv);
    ImageName = "img" + Self;
    if (CurrentClass.indexOf("collapsed") > -1)
    {
        ChangeClassName(ContentDiv, "collapsed", "expanded");
        document.getElementById(Self).title = "Click to collapse";
        ChangeClassName(Self, "MenuHeader_Plus", "MenuHeader_Minus");
    }
    else
    {
        ChangeClassName(ContentDiv, "expanded", "collapsed");
        document.getElementById(Self).title = "Click to expand";
        ChangeClassName(Self, "MenuHeader_Minus", "MenuHeader_Plus");
    }
    if (!e) var e = window.event;
    e.cancelBubble = true;
    if (e.stopPropagation) e.stopPropagation();
}

//===========================================================================================================
//===========================================================================================================
//===========================================================================================================
