// rpFunctions.js  Version 20111212
// Copyright © 2008-2012 Eric Friedman.  All rights reserved.
//
// This file provides client-side javascript functions to support HTML pages
// with input forms, popup menus, etc.  This file must be included in the
// <BODY> section of HTML pages as follows:

//    <script type='text/javascript' src='rpFunctions.js'></script>

// 20120206  emf  added function comments
// 20111212  dms  added Fusion Chart print utility (but commented out)
// 20110811  dms  added dhtmlLoad as generic means to dynamically load js and css code
// 20110729  dms  modify cursorloc to track SPAN elements within an A element
// 20110720  dms  add onLoadSetup, ported from report.asp jQuery(document).ready function
// 20110625  dms  re-adjust vpGetSize graph adjustment frmo 85 to 10
// 20110624  dms  remove techDetail section from calculation in getVPSize
// 20110516  dms  added some wiggle room in vpGetSize for graph display tech details
// 20101127  dms  added formChanged.override = false; to initForms to reset value

// 20110614  emf  added more room in vpGetSize for graph display tech details
// 20101127  dms  added formChanged.override = false to reset value in initForms
// 20110516  dms  added some room in vpGetSize for graph display tech details
// 20110513  dms  moved getVPSize from fxHeader for use in both grid and graph
//                resize; added adjustForSliderActivation for use in grid graph
//                resize event handling when making dimension selection area show/hide
// ---------------------------------------------------------------------------------

//----------------
//Global variables
//----------------

var cursor = new Object();                   // Holds location of last anchor or image click
var expanded = new Image();                  // Global object to hold images
expanded.src = "Images/expanded.gif";        // Path to expanded image
var collapsed = new Image();
collapsed.src = "Images/collapsed.gif";      // Path to collapsed image
var loading = new Image();
loading.src = "Images/loading.gif";          // Path to animated loading image

// Replace browser's contextmenu event handler with our own
document.oncontextmenu = translateRightClick;

// Automatically call the initForms() function upon page load
addLoadEvents(initForms);
//--------------------------------------------------------------------------------------------------

function initForms() {

// Purpose:   This function should be called by the page onload event. It
//            initializes field attributes across all forms on the page:
//              1. Creates a new orig_Value property for each field on the page,
//                 and initializes it to the appropriate incoming field value.
//              2. Applies CSS highlight classes to input fields of type=text
//                 and type=password, and to textarea fields, if they are not
//                 readOnly.

// Arguments: none

// Returns:   true if able to initialize form elements, false otherwise.
// ---------------------------------------------------------------------------

   if (!document.getElementsByTagName) return false;        // Make sure browser supports js

   var field,fieldtype,allfields,i;

   //----------------------------------------
   // Loop through all input elements on page
   //----------------------------------------

   allfields = document.getElementsByTagName("input");
   for (i=0; i < allfields.length; i++) {
      field = allfields[i];
      fieldtype = field.getAttribute("type");

      // Create an appropriately initialized orig_Value node for each input field
      if ((fieldtype == "checkbox") || (fieldtype == "radio"))
         field.orig_Value = field.checked;                  // Checkbox & radio buttons alter checked
      else
         field.orig_Value = field.value;                    // All other fields alter their value

      // Add special CSS classes to text and password field onfocus and onblur events
      if (!field.readOnly && ((fieldtype == "text") || (fieldtype == "password"))) {
         addEvent(field,'focus',function() {this.className = 'highlightActiveField';} );
         addEvent(field,'blur',function() {this.className = 'highlightInactiveField';} );
      }
   }

   //-------------------------------------------
   // Loop through all textarea elements on page
   //-------------------------------------------

   allfields = document.getElementsByTagName("textarea");
   for (i=0; i < allfields.length; i++) {

      // Create an appropriately initialized orig_Value for each textarea field
      field = allfields[i];
      field.orig_Value = field.value;                       // Textarea fields alter their value

      // Add special CSS classes to textarea field onfocus and onblur events
      if (!field.readOnly) {
         addEvent(field,'focus',function() {this.className = 'highlightActiveField';} );
         addEvent(field,'blur',function() {this.className = 'highlightInactiveTextarea';} );
      }
   }

   //-----------------------------------------
   // Loop through all select elements on page
   //-----------------------------------------

   allfields = document.getElementsByTagName("select");
   for (i=0; i < allfields.length; i++) {

      // Create an appropriately initialized orig_Value for each select field
      field = allfields[i];
      field.orig_Value = field.value;                       // Select fields alter their value
   }

   formChanged.override = false;

   return true;
}
//--------------------------------------------------------------------------------------------------

function disableInput(bDisable) {

// Purpose:   This function should be called by the page onBeforeUnload
//            event and onUnload events. It disables (bDisable = true) or enables
//            (bDisable = false) all input, textarea, select and anchor elements
//            across all forms on the page so that users cannot (or can again)
//            interact with them.  Disable is used while waiting for the next page
//            to load, with reenable after a few seconds to cure IE issues.

// Arguments: bDisable - should contain true or false.  If true, elements are
//            disabled.  If false, elements are enabled.  If argument is
//            omitted, the default value is true.

// Returns:   None (to avoid triggering the onBeforeUnload dialog box).
// ------------------------------------------------------------------------

   if (!document.getElementsByTagName) return;              // Make sure browser supports js
   if (typeof bDisable == 'undefined' ) bDisable = true;    // Set default value for arg bDisable

   var allfields,i;

   //----------------------------------------
   // Loop through all input elements on page
   //----------------------------------------

   allfields = document.getElementsByTagName("input");
   for (i=0; i < allfields.length; i++) {
      allfields[i].disabled = bDisable;
   }

   //-------------------------------------------
   // Loop through all textarea elements on page
   //-------------------------------------------

   allfields = document.getElementsByTagName("textarea");
   for (i=0; i < allfields.length; i++) {
      allfields[i].disabled = bDisable;
   }

   //-----------------------------------------
   // Loop through all select elements on page
   //-----------------------------------------

   allfields = document.getElementsByTagName("select");
   for (i=0; i < allfields.length; i++) {
      allfields[i].disabled = bDisable;
   }

   //-----------------------------------------
   // Loop through all anchor elements on page
   //-----------------------------------------

   allfields = document.getElementsByTagName("a");
   for (i=0; i < allfields.length; i++) {
      disableAnchor(allfields[i],bDisable);
   }
}
//--------------------------------------------------------------------------------------------------

function disableAnchor(obj, bDisable) {

// Purpose: This function disables a specific anchor <a> element on a page.  It's
// required because current browsers do not implement the anchor.disable attribute.
// IE only changes the link's color but does not actually disable the anchor if it
// has an href value.  Firefox does not provide any support for it.

// Arguments: obj - anchor element to disable or enable
//            bDisable - should contain true or false.  If true, elements are
//            disabled.  If false, elements are enabled.  If argument is
//            omitted, the default value is true.

// Returns:   None
// --------------------------------------------------------------------------------

   if (obj != null) {                                          // Make sure object exists
      if (typeof bDisable == 'undefined' ) bDisable = true;    // Set default value for arg bDisable

      if (bDisable) {                                          // Disable anchor
         var href = obj.getAttribute("href");                  // Get original href
         var onclick = obj.getAttribute("onclick");            // Get onclick attribute

         // Move previous href to new attribute href_bak
         if (href && href != "" && href != null) {
            obj.setAttribute('href_bak', href);
            obj.removeAttribute('href'); 
         }

         // Move previous onclick attrbiute to new attribute onclick_bak
         if (onclick != null) {
            obj.setAttribute('onclick_bak', onclick); 
            obj.setAttribute('onclick', "void(0);"); 
         }

         // Change link color - disabled
         // obj.style.color="gray";

      } else {                                                 // Re-enable anchor
         var hrefBack = obj.getAttribute("href_bak");          // Retrieve stored href attribute
         var onclickBack = obj.getAttribute("onclick_bak");    // Retrieve stored onclick attribute

         if (onclickBack !=null) {                             // Restore original onclick
            obj.setAttribute('onclick',onclickBack);
            obj.removeAttribute('onclick_bak'); 
         }

         if (hrefBack !=null ) {                               // Restore original href
            obj.setAttribute('href',hrefBack); 
            obj.removeAttribute('href_bak'); 
         }

         // Restore link color - disabled
         // obj.style.color="blue"; 
      }
   }
}
//--------------------------------------------------------------------------------------------------

function submitPushed(objForm) {

// Purpose:   Call submitPushed when a form's submit button is pushed.  It calls
//            function formChanged(objForm) to see if any fields in the argument
//            form have been changed from their original values.  If not, it
//            displays an alert message to the user and returns false.

// Usage from HTML:
//            <form name='formname' onsubmit='return submitPushed
//                 (document.getElementById(""formname""))' autocomplete='off' ...>

// Arguments: objForm - Form object whose fields to check for changes.

// Returns:   True if any form fields have changed.  Otherwise, display alert
//            msg and return false.
// --------------------------------------------------------------------------------

   var submit = formChanged(objForm);                       // Have any fields changed?
   if (submit)
      formChanged.override = true;                          // Yes; Override future formChanged calls
   else
      alert("No changes have been entered.");               // No changes, display alert
   return submit;
}
//--------------------------------------------------------------------------------------------------

function formChanged(objForm) {

// Purpose:  Determine if any form elements contained in the argument form
//           object reference have been changed.  It compares each current
//           field.value in the form to its field.orig_Value created and
//           populated by initForms().

//           Once formChanged has returned true and the user has acknowledged
//           that changes will be lost by navigating away from current page,
//           caller should set formChange.override = true to prevent subsequent
//           calls to formChanged by the page onbeforeunload event from again
//           returning true.  Otherwise user will be asked a second time.

// Argument: objForm - form to be checked for changes.

// Returns:  True if any element's value has changed, false if objForm is
//           not an object, browser doesn't support getElementsByTagName,
//           no fields have changed, or formChanged.override is true.
// ----------------------------------------------------------------------------

   if (!!formChanged.override) return false;                // Exit if function has been overridden
   if (!objForm) return false;                              // Exit if objForm is not an object
   if (!objForm.getElementsByTagName) return false;         // Exit if browser doesn't support getElementsByTagName

   var field,fieldtype,i;
   var allfields = objForm.elements;                        // Get all form's fields

   // Loop through all form elements checking for changes
   for (i=0; i < allfields.length; i++) {
      field = allfields[i];

      // Has field's value changed from its original value?
      if (field.orig_Value != undefined) {
         fieldtype = field.getAttribute("type");

         if ((fieldtype == "checkbox") || (fieldtype == "radio")) {
            if (field.checked != field.orig_Value) return true;  // Has checkbox or radio button changed?
         }
         else if (field.value != field.orig_Value) return true;  // Has other field changed?
      }
   }
   return false;                                            // No fields have changed
}
//--------------------------------------------------------------------------------------------------

function deleteItem(sItemName,sSessionId) {

// Purpose:   Have user confirm the Delete button push.  If confirmed,
//            return an href to calling script with a ?DELETE=sessionid
//            search string that tells it to delete the current item.

// Arguments: sItemname - description of current item
//            iSessionId - unique number assigned to this form window

// Returns:   true if delete confirmed, false otherwise.
// --------------------------------------------------------------------

   var del = confirm("Are you sure you want to Delete " + sItemName + "?");
   if (del)
      location.replace(locationPageName() + "?DELETE=" + sSessionId);
   return del;
}
//--------------------------------------------------------------------------------------------------

function deleteItem(event,sProgName,sItemName,sSessionId) {

// Purpose:   Have user confirm the Delete button push.  If confirmed,
//            submit page to have handled and refreshed based one ?DELETE=sessionid
//            search string that tells it to delete the current item.

// Arguments: event - event that triggered delete
//            sItemname - description of current item
//            iSessionId - unique number assigned to this form window

// Returns:   true if delete confirmed, false otherwise.
// --------------------------------------------------------------------

   var del = confirm("Are you sure you want to Delete " + sItemName + "?");
   if (del)
      handleFormSubmit (event, sProgName + "?DELETE=" + sSessionId, false, true)
   return del;
}
//--------------------------------------------------------------------------------------------------

function locationPageName() {

// Purpose: This function returns the absolute page name of the current href
//          excluding any '?' search string.
// -------------------------------------------------------------------------

   var qPos = location.href.indexOf("?");                   // Find '?' that ends our base URL
   if (qPos == -1) 
      return location.href;                                 // If no '?' found, return the URL
   else
      return location.href.substr(0,qPos);                  // Return URL excluding search string
}
//--------------------------------------------------------------------------------------------------

function exitPage(objForm,URL) {

// Purpose:   Call this function when user clicks a button with an onclick method
//            that transfers to a new page.  It calls formChanged() to see if any
//            form fields were changed since the form was last saved. If so, it
//            displays a confirm dialog identical to the onbeforeunload event
//            warning the user that all pending changes will be lost if user
//            continues.  

//            If user chooses to continue,  or if there are no pending changes, it
//            transfers to the URL provided.  If URL is null, no transfer is
//            attempted, but the function return value indicates what action would
//            have been taken had the URL existed.

//            This function is used in conjunction with the following HTML construct,
//            which handles this issue for both the back button and <A href=>:
//              onbeforeunload='if (formChanged(document.getElementById("mainForm")))
//              return("Changes you made have NOT been saved, and will be lost.")'>

//            It must be called for onclick events in place of windows.location.href
//            because an unknown error is thrown if user Cancels the onbeforeunload
//            dialog to stay on the page.

// Arguments: objForm - the formname to be checked for field changes
//            URL - web address of page to which transfer should occur.  Reserved
//                  value "*PREVOUS*" transfers to the page that opened current
//                  page.  Null suppresses any transer.

//  Returns:  True if leaving current page, false if staying on current page.
// ----------------------------------------------------------------------------------

   var leave = true;                                        // If no pending changes, we're leaving

   // If unsaved changes were found, ask if user still wants to leave
   var changed = formChanged(objForm);
   if (changed) {
      var leave = confirm("Are you sure you want to navigate away from this page?\n\n" + 
                          'Changes you made have NOT been saved, and will be lost.\n\n' +
                          'Press OK to continue, or Cancel to stay on the current page.')
   }

   if (!!URL && leave) {
      formChanged.override = true;                          // Since user has agreed, override onbeforeunload formChanged
      if (URL.indexOf("*PREVIOUS*") >= 0)                   // If URL is *PREVIOUS*, go to window that opened us
         openPreviousWindow;
      else
         location.replace(URL);                             // Replace current window with provided URL
   }
   return leave;                                            // Indicate decision to leave
}
//--------------------------------------------------------------------------------------------------

function openPreviousWindow() {

// Purpose: Close current window and focus on the window that opened us.
// Note that it won't work if containing document appears in a frameset.
// ---------------------------------------------------------------------

   if (self.opener) {                                       // If window that opened us is available
      opener.focus();                                       // Put focus on that window
      self.close();                                         // And close current window
      return true;
   } 
   else
      alert("Previous window is no longer open!");
   return false;
}
//--------------------------------------------------------------------------------------------------

function addLoadEvents(func) {

// Purpose:  Add a new window onload event without overwriting any
//           existing onload events.

// Argument: func - the function to be added to onload events
// ---------------------------------------------------------------

   var oldOnload = window.onload;                           // Remember existing onload functions

   if (typeof window.onload != 'function') {                // If none already exist
       window.onload = func;                                // This becomes the first
   }
   else {
       window.onload = function() {                         // Add new function to existing ones
          oldOnload();
          func();
       }
   }
}
//--------------------------------------------------------------------------------------------------

function addEvent(obj,eventType,fn) {

// Purpose:  addEvent is a cross-browser function that adds a function to a
//           particular event of a named object (IE and Gecko-based browsers).

// Arguments:
//    'obj'       is the object whose event you want to affect.
//    'eventType' contains the name of the event, for example: 'click', 
//                'mouseover', 'load', 'submit', etc., without the 'on...' prefix.
//    'fn'        is a reference to a function to call whenever the event
//                fires.  One argument, the event object, will be passed to
//                that 'fn'

// Usage examples:
//    addEvent(document.getElementById('foo'),'click',doSomething );
//    addEvent(obj,'mouseover',function(){ alert('hello!'); });
// ---------------------------------------------------------------------------

   if (obj.attachEvent)                                     // Handle IE browsers
      obj.attachEvent('on'+eventType,function() { fn.apply(window.event.srcElement); });
   else
      obj.addEventListener(eventType,fn,false);             // Handle all other browsers
}
//--------------------------------------------------------------------------------------------------

function removeEvent(obj,eventType,fn) {

// Purpose: removeEvent is the counterpart to addEvent.  Its a cross-browser
//          function that removes a function added by addEvent.

// Arguments:
//    'obj'       is the object whose event you want to affect.
//    'eventType' contains the name of the event, for example: 'click', 
//                'mouseover', 'load', 'submit', etc., without the 'on...'.
//    'fn'        is a reference to a function to call whenever the event
//                fires.  One argument, the event object, will be passed to
//                that 'fn'
// -------------------------------------------------------------------------

   if (obj.detachEvent)                                     // Handle IE browsers
      obj.detachEvent('on'+eventType,function() { fn.apply(window.event.srcElement); });
   else
      obj.removeEventListener(eventType,fn,false);          // Handle all other browsers
}
//--------------------------------------------------------------------------------------------------

function translateRightClick(myEvent) {

// Convert a right click into a left click
// ---------------------------------------

   var target = getEventTarget(myEvent);
   if (target.tagName == "A" || target.tagName == "IMG")    // If target is an anchor or image
      if (!myEvent) {                                       // For IE browser
         window.event.returnValue = false;                  // Cancel the right click
         target.click();                                    // Left click the target instead
      }
      else {                                                // Gecko-based browsers
         myEvent.preventDefault();                          // Cancel the right click
         var evt = document.createEvent("MouseEvents");     // Create new event (won't do event.click on anchors)
         evt.initMouseEvent("click",true,true,window,0,0,0,myEvent.clientX,myEvent.clientY,false,false,false,false,0,null);
         target.dispatchEvent(evt);                         // Fake a target.click
      }       
   return false;                                            // Cancel the right-click
}
//--------------------------------------------------------------------------------------------------

function disableAllStatusMsgs() {

// Purpose: Clear status messages for all links on page.
// -----------------------------------------------------

   for (var count = 0; count < document.links.length; count++)
      document.links[count].onmouseover = blankStatus ;
   return true;
}
//--------------------------------------------------------------------------------------------------

function blankStatus() {

// Purpose: Clear the status bar at the bottom of browser window.
// --------------------------------------------------------------

   window.status = "";
   return true;
}
//--------------------------------------------------------------------------------------------------

function cursorloc(myEvent) {

// Remember cursor location when clicking on anchor or img
// -------------------------------------------------------

   var target = getEventTarget(myEvent);
   if (target.tagName == "A" || target.tagName == "IMG" ||
       (target.tagName == "SPAN" && target.parentNode.tagName == "A")) {
      cursor.x = myEvent.clientX;
      cursor.y = myEvent.clientY;
   }
   return true;
}
//--------------------------------------------------------------------------------------------------

function hideMenu() {

// Hide and PopupMenus existing on this page
// -----------------------------------------

   var stmenu = document.getElementById("stmenu");
   if (stmenu)
      stmenu.style.visibility="hidden";

   var drmenu = document.getElementById("drmenu");
   if (drmenu)
      drmenu.style.visibility="hidden";
   return true;
}
//--------------------------------------------------------------------------------------------------

function getEventTarget(myEvent) {

// Cross-browser function to identify the target of the most recent event.

// Gecko passes the event as the only argument to event handlers,and
// stores the HTML element on which the event took place in event.target.

// IE stores the latest event in window.event,not in an argument,and
// stores the HTML element on which the event took place in event.srcElement.
// --------------------------------------------------------------------------

   myEvent = myEvent || window.event;                          // Identify the event
   var targ = myEvent.target || myEvent.srcElement;            // Identify the event's target
   if (targ.nodeType == 3)                                     // Defeat Gecko event on text nodes
      targ = targ.parentNode;
   return targ;
}
//--------------------------------------------------------------------------------------------------

function Left(str, n) {

// Purpose: Provides Left() function analagous to VB

// Arguments: str - source string
//            n   - number of characters to extract

// Returns: n characters from left end of str
// ----------------------------------------------------------------------

   var myStr = str + ''                                     // Ensure str is a string
   if (n <= 0)                                              // Any characters requested?
       return "";                                           // No, return empty string
   else if (n > myStr.length)
       return myStr;                                        // Return entire string
   else
       return myStr.substr(0,n);                            // Return leftmost n chars
}
//--------------------------------------------------------------------------------------------------

function Right(str, n) {

// Purpose: Provides Right() function analagous to VB

// Arguments: str - source string
//            n   - number of characters to extract

// Returns: n characters from right end of str
// ----------------------------------------------------------------------

   var myStr = str + ''                                     // Ensure str is a string
   if (n <= 0)                                              // Any characters requested?
       return "";                                           // No, return empty string
   else {
      var iLen = myStr.length;
      if (n > iLen)
         return myStr;                                      // Return entire string
      else
         return myStr.substr(iLen - n);                     // Return rightmost n chars
    }
}
//--------------------------------------------------------------------------------------------------

function cancelEvent(myEvent) {

// Generic function to cancel an event
// -----------------------------------

   var Event;
   var target = getEventTarget(myEvent);
   if (window.event) {                                   // For IE browser
      Event = window.event;
      Event.returnValue = false;                         // Cancel the event
   }
   else {                                                // Gecko-based browsers
      Event = myEvent;
      myEvent.preventDefault();                          // Cancel the event
   }
   Event.cancelBubble = true;                            // Prevent event from bubbling
   return false;
}
//--------------------------------------------------------------------------------------------------

function toggleBranch(branch,img) {

// Toggle a hierarchy tree branch and rotator image open or closed
// ---------------------------------------------------------------

   var objBranch = document.getElementById(branch).style;
   var objImg = document.getElementById(img);

   if(objBranch.display == "block") {        // If currently expanded
      objBranch.display = "none";            // Collapse branch
      objImg.src = collapsed.src;
   }
   else {
      objBranch.display = "block";           // Expand branch
      objImg.src = expanded.src;
   }
}
//--------------------------------------------------------------------------------------------------

function toggleTools(area) {

// Toggle tools window visibility & button image
//----------------------------------------------

   var objArea = document.getElementById(area).style;
   var objIcon = document.getElementById('tool1');

   if(objArea.display == "block") {          // If currently visible
      objArea.display = "none";              // Make area invisible
      objIcon.src = "Images/Tool_Icon.gif";  // Show tool area icon
      objIcon.title = "View report options"; // Change tooltip text
   }
   else {
      objArea.display = "block";             // Make area visible
      objIcon.src = "Images/No_Tool_Icon.gif";  // Hide tool area icon
      objIcon.title = "Hide report options"; // Change tooltip text
   }
}
//--------------------------------------------------------------------------------------------------

function showTabbedPage(displayId,activeTab) {

// Purpose:   This function is called by page tabs. It:
//              1. Hides all pages with an element type of span and a class
//                 of tabbedPage.
//              2. Displays the page whose id matches the displayId.
//              3. Sets value and orig_value of reserved field "_activePage_" 
//                 to displayId to tell server which page was active on submit.
//              4. Resets the active tab's appearance to inactive, then sets
//                 the calling tab's appearance to active.

// Arguments: displayId: the id of the page(s) to be displayed.
//            activeTab: the tab element object to be made active (can be null)

// Returns:   true if able to swap displayed pages, false otherwise.
//  ---------------------------------------------------------------------------

   if (!document.getElementsByTagName) return false;        // Make sure browser supports js

   var field,fieldClassName,fieldDisplay,allfields,i;

   //--------------------------------------
   // Display/hide the tabbed page elements
   //--------------------------------------

   allfields = getElementsByClassName("tabbedPage","span");
   for (i=0; i < allfields.length; i++) {
      field = allfields[i];
      if (field.id == displayId)
         field.style.display = "block";                     // Set requested page to visible
      else
         field.style.display = "none";                      // Hide all other pages
   }

   //--------------------------------------------
   // Reset field _activePage_ value to displayId
   //--------------------------------------------

   field = document.getElementById("_activePage_");
   if (!!field) {                                           // If field exists
      field.value = displayId;                              // Set its value to currently-displayed page's id
      field.orig_Value = displayId;                         // Prevent form change detection
   }

   //----------------------
   // Change the active tab
   //----------------------

   allfields = getElementsByClassName("activeTab","li");
   for (i=0; i < allfields.length; i++) {
      allfields[i].className = "inactiveTab";               // Change each active tab's class to inactiveTab
   }

   if (activeTab) activeTab.className = "activeTab";        // Change clicked tab's class to activeTab
   return true;
}
//--------------------------------------------------------------------------------------------------

function getElementsByClassName(strClass, strTag, objContElm) {

// Purpose: Gets an array of DOM elements matching a list of one or more
//          classnames, optionally having a particular tag name or container.

// Arguments:
//    strClass:   string containing a list of desired class(es), delimited
//                either by spaces or '|'
//    strTag:     Optional (defaults to '*') tag name to limit the search
//                to a specific tag (e.g., 'a' for links).
//    objContElm: Optional (defaults to document) container inside of which
//                to search elements.

// Returns:
//    An array of elements that qualify, can be empty.
//---------------------------------------------------------------------------

   // Set default values for optional arguments
   strTag = strTag || "*";
   objContElm = objContElm || document;

   // Get collection of objects that qualify by tag and container
   var objColl = objContElm.getElementsByTagName(strTag);
   if (!objColl.length && strTag=="*" && objContElm.all)
      objColl = objContElm.all;

   var arr = new Array();                                   // Create return array
   var delim = strClass.indexOf('|')!=-1 ? '|' : ' ';       // Determine class delimiter used
   var arrClass = strClass.split(delim);                    // Split class string on delimiter

   // Loop through all objects that qualify by tag and container
   for (var i=0,j=objColl.length; i<j; i++) {
      var arrObjClass = objColl[i].className.split(' ');    // Split collection on classname
      if (delim==' ' && arrClass.length > arrObjClass.length) continue;  // Jump to next loop iteration
      var c = 0;

      compareLoop:
      for (var k = 0, l = arrObjClass.length; k < l; k++) {
         for (var m = 0, n = arrClass.length; m < n; m++) {
            if (arrClass[m] == arrObjClass[k]) c++;
            if ((delim=='|' && c==1) || (delim==' ' && c==arrClass.length)) {
               arr.push(objColl[i]);                        // Add this object to array
               break compareLoop;                           // Break the outer loop
            }
         }
      }
   }
   return arr;                                              // Return array of objects
}
//--------------------------------------------------------------------------------------------------

function openHelpWindow(strUrl) {

// Purpose: Opens a 500x800 Help Window to display a context specific html page

// Arguments:
//    strUrl:  Web address of page to open in new window

// Returns:
//    None
//---------------------------------------------------------------------------
   var opts = "toolbar=no,status=no,location=no,menubar=no,resizable=yes,height=500,width=800,scrollbars=yes";

   win = window.open("", "Help", opts);
   win.focus();
   win.location = strUrl;
}
//--------------------------------------------------------------------------------------------------

function openNamedWindow(strName,strUrl) {

// Purpose: Opens a new 500x800 Window with given name to display an html page

// Arguments:
//    strName: Name to be given to this window
//    strUrl:  Web address of page to open in new window

// Returns:
//    None
//---------------------------------------------------------------------------

   var opts = "toolbar=no,status=no,location=no,menubar=no,resizable=yes,height=500,width=800,scrollbars=yes";

   win = window.open("", strName, opts);
   win.focus();
   win.location = strUrl;
}
//--------------------------------------------------------------------------------------------------

function getVPSize() {

// Purpose: Return object containing available browser viewport size in px
//------------------------------------------------------------------------

   var d = document.viewport.getDimensions();

   // Figure out how wide to make the table
   var w = d.width-60;                                  // Leave room for shaded box around table

   // Figure out how high to make the table
   var h;
   var maxH = d.height-85;                              // Subtract for shaded box around table +/-

   // Adjust available height for presence of navbar, title, page selectors, tabs, footnotes, tech detail, footer
   h = ($('navbar_container')) ? maxH - ($('navbar_container').getHeight()) : maxH;
   h = ($('reportTitle')) ? h - ($('reportTitle').getHeight()) : h;
   h = ($('toggle_minus').visible()) ? h - ($('toggle_slide').getHeight()) : h;
   h = ($('grid')) ? h - ($('grid').getHeight()) : h;      // Evidence of grid or graph page tabs
   h = ($('graph') && $('graph').visible()) ? h-10 : h;    // Leave additional room below graph display
   h = ($('footnotes')) ? h - ($('footnotes').getHeight()) : h;
   h = ($('footer_container')) ? h - ($('footer_container').getHeight()) : h;

   return $H({vpHeight: h, vpWidth: w});
}
//--------------------------------------------------------------------------------------------------

function adjustForSliderActivation() {

// Purpose: Adjust grid and/or graph on open/close dimension slider change

// Arguments: none

// Returns: void
//------------------------------------------------------------------------

   if ($('gridView') && (($('grid') && $('grid').visible()) || $('grid') == undefined)) {
      fxheader();
   }

   var charts = $$('[id^="Chart_"][id$="_Div"]');
   charts.each(function(chart) {
      chart.setStyle({'height':((charts.size()>2) ? 
         parseInt((getVPSize().get('vpHeight'))/2) : 
         getVPSize().get('vpHeight'))+'px'});
   });
}
//--------------------------------------------------------------------------------------------------

function onLoadSetup(sTabOverride, bDown2) {

// Purpose: Code that runs after report.asp document load but before anything else

// Arguments:
//   sTabOverride: url-based active tab override value
//   bDown2: boolean determining if there is a down2 col

// Returns: void
//--------------------------------------------------------------------------------

   // Determine active tab
   Cookie.init({ name: 'RPSuite' });
   var sTab = Cookie.getData('activeTab'); 
   if (sTab == undefined) {sTab = 'graph';}
   sTab = (sTabOverride.length>0 ? sTabOverride : sTab);
   showTabbedPage(sTab,$(sTab));
   
   // Set up grid with scrolling and manual col width adjustment capability
   if ($('gridView')) {
      fxheaderClean();
      fxheaderInit('gridView', (bDown2.toUpperCase() == 'TRUE'?2:1) );
      fxheader();
   }
   
   // Set up click events to save sticky tabs for next display
   if ($('grid')) {
      $('grid').observe('click',function() {
         if ($('gridView:scroller:fx')) { fxheader(); }
         Cookie.init({ name: 'RPSuite' });
         Cookie.setData('activeTab',$('grid').id);
      });
   }
   if ($('graph')) {
      $('graph').observe('click',function() {
         Cookie.init({ name: 'RPSuite' });
         Cookie.setData('activeTab',$('graph').id);
//         FusionCharts.printManager.enabled(true);
      });
   }
   
   // Set up browser viewport resize event 
   Event.observe(window, 'resize', function() {
      if ($('gridView:scroller:fx')) {
         fxheaderResize();
      }
   });

   if (sTab == 'graph') {
      FusionCharts.printManager.enabled(true);
   }
}
//--------------------------------------------------------------------------------------------------

function dhtmlLoad(url,type) {

// Purpose:   Since all activity is displayed within a container, loading
//            javascript, css, etc., via head tags is not optimal for html
//            returned via AJAX calls. This function allows page contents
//            generated by asp programs to dynamically load components as
//            needed.
//
// Arguments: url of the file to load.  It can be absolute or relative.
//            type: type of code file to load
//                  0: Javascript
//                  1: CSS
//
// Returns:   void
//-----------------------------------------------------------------

   var head;
   var elem = null;

   head = $$('head')[0];
   if (head != undefined) {
      switch (type) {
         case 0:
            elem = new Element('script', { type: 'text/javascript', src: url });
            break;
         case 1:
            elem = new Element('link', { type: 'text/css', rel: 'stylesheet', href: url });
            break;
         default:
      }
      if (elem != undefined) { head.appendChild(elem); }
   }
}

