/* @@BEGIN_COPYRIGHT@@ */
/* Licensed Internal Code - Property of IBM */
/* 3931 3932 Licensed Internal Code */
/* (C) Copyright IBM Corp. 2000, 2022 All Rights Reserved. */
/* @@END_COPYRIGHT@@ */
/*********************************************************** {COPYRIGHT-TOP} ***
* Licensed Materials - Property of IBM
* Tivoli Presentation Services
*
*
************************************************************ {COPYRIGHT-END} ***
*******************************************************************************/

/*******************************************************************************
* This file contains all of the javascript functions used by the WCL renderers
* during traditional execution when AJAX is not being used. The functions
* defined here must be stateless -- that is, no member variables can be defined,
* so all state information must be passed into the function as parameters.
*******************************************************************************/
var isIOS = navigator.userAgent.toLowerCase().match(/(ipad|iphone)/);
var MIN_COL_WIDTH = isIOS ? 50 : 30;
var MIN_ROWS_VISIBLE = 2;
var MAX_COL_WIDTH = 9999;


/**
 * Static delcaration of WTableData class.
 */
if ( !self.WTableData )
{
    self.WTableData = new WTableDataImpl();
}

function WTableDataImpl()  // @02
{
    this.tableColumns_ = null;
}


/** AWInputComponent **
 * action - the name of the action. do not encode because it is used as the
 *          value of a hidden input field.
 * formName - this encoded name of the form
 * wclhidden - the encoded name of the hidden field
 */
function frmAct(action, formName, wclhidden) {
   if (document != null && document.forms != null && formName != null) {
      var form = document.forms[formName];
      if (form != null) {
         eval( "form." + wclhidden + ".value = '" + action + "'" );
      }
   }
}

/** WNotebook **
 * formName - the encoded name of the form
 * actionName - the name of the action being performed
 * actionValue - the name of the component performing the action
 * actionNameEnc - the encoded name of the action being performed
 * wclhidden - the encoded name of the hidden field
 * wclanchor - the encoded name of the hidden field for the anchor
 */
function doNb(formName, actionName, actionValue, actionNameEnc, wclhidden, wclanchor) {
   return doSubmit(formName, actionName, actionValue, null, actionNameEnc, wclhidden, wclanchor);
}

/** WWizard **
 * formName - the encoded name of the form
 * actionName - the name of the action being performed
 * actionValue - the name of the component performing the action
 * actionNameEnc - the encoded name of the action being performed
 * wclhidden - the encoded name of the hidden field
 * wclanchor - the encoded name of the hidden field for the anchor
 */
function doWiz(formName, actionName, actionValue, actionNameEnc, wclhidden, wclanchor) {
   return doSubmit(formName, actionName, actionValue, null, actionNameEnc, wclhidden, wclanchor);
}

/** WTree (for the expand/collapse events) **
 * formName - the encoded name of the form
 * actionName - the name of the action being performed
 * actionValue - the name of the component performing the action
 * anchorName - the name of the anchor used when the page is refreshed
 * actionNameEnc - the encoded name of the action being performed
 * wclhidden - the encoded name of the hidden field
 * wclanchor - the encoded name of the hidden field for the anchor
 * idName - the encoded name of the hidden field that specifies which tree in the form is performing the action
 */
function doTree(formName, actionName, actionValue, anchorName, actionNameEnc, wclhidden, wclanchor, idName){
   if (document != null && document.forms != null && formName != null) {
      var form = document.forms[formName];
      if (form != null) {
         if(idName != null){
             eval("form." + idName + ".value = '" + idName + "'");
         }
      }
   }
   return doSubmit(formName, actionName, actionValue, anchorName, actionNameEnc, wclhidden, wclanchor);
}

/**
 * formName - the encoded name of the form
 * actionName - the name of the action being performed
 * actionValue - the name of the component performing the action
 * anchorName - the name of the anchor used when the page is refreshed
 * actionNameEnc - the encoded name of the action being performed
 * wclhidden - the encoded name of the hidden field
 * wclanchor - the encoded name of the hidden field for the anchor
 */
function doSubmit(formName, actionName, actionValue, anchorName, actionNameEnc, wclhidden, wclanchor) {
   if (document != null && document.forms != null && formName != null) {
      var form = document.forms[formName];
      if (form != null) {
         if (actionName != null) {
            eval("form." + actionNameEnc + ".value = '" + actionValue + "'");
            eval("form." + wclhidden + ".value = '" + actionName + "'");
         }

         // We have to store the anchor as a hidden field so that it gets passed
         // along when the form's method is GET.  (When the method is GET, the
         // parameters on the form's action are ignored!)  The date ensures we'll
         // have a unique URL so that a URL can be invoked twice consecutively.
         if (anchorName != null) {
            var aDate = new Date();
            eval("form." + wclanchor + ".value = '" + anchorName + '_' + aDate.getTime() + "'");
            var idx = form.action.indexOf('#');
            if (idx > -1) {
                // strip off the anchor that's already on the url
                form.action = form.action.substring(0, idx);
            }
            form.action += '#' + anchorName;
         }

         form.submit();
      }
   }
   return false;
}

 /** WTable **
  * formName - the encoded name of the form
  * anchorName - the name of the anchor used when the page is refreshed
  * wclanchor - the encoded name of the hidden field for the anchor
  */
 function doAnchor(formName, anchorName, wclanchor, dropDownId) {
    var dropDown = document.getElementById(dropDownId);
    var skip = false;
    if (dropDown) { // message box must be shown
         // See if we can skip this action (the --- Select Action --- is selected).

     if(dropDown.value.indexOf("/ExportData?exportId") != -1) {
       var url = dropDown.value;
       if (window.hmcTaskId) {
         url = url + '&launching-task-id=' + window.hmcTaskId;
       }
       window.open(url,'_blank');
       dropDown.selectedIndex = 0;
       skip = true;
     }else if (dropDown.selectedIndex != 0) {
           var option = dropDown.options[dropDown.selectedIndex];
           if (option){
             if (WClient.isBrowserInternetExplorer()) {
               if (option.message!=null) {
                 var message = option.getAttribute("message");
                 skip = !(confirm(message));
               }
           } else {
               if (option.hasAttribute("message")) {
                 var message = option.getAttribute("message");
                 skip = !(confirm(message));
           }
           }
         }
         }else{
       skip = true;
         }
    }

   if (!skip) {
      var form = document.forms[formName];
      if (form != null && anchorName != null && wclanchor != null) {
         var aDate = new Date().getTime();
         eval("form." + wclanchor + ".value = '" + aDate + "'");

         // remove existing anchorName
         var index = form.action.indexOf( "#" );
         if ( index != -1 )
         {
             form.action = form.action.substring( 0, index );
         }
         form.action += '#' + anchorName;

         var inputName = "wclAnchorHash";
         var input  = document.getElementById( inputName );
         if ( !input )
         {
             input = document.createElement( "INPUT" );
             with ( input )
             {
                 type  = "hidden";
                 id    = inputName;
                 name  = inputName;
             }
             form.appendChild( input );
         }
         input.value = anchorName;
      }
    }
    return !skip;
 }

/** WTable **
 * formName - the encoded name of the form
 * actionName - the name of the action being performed
 * actionValue - the name of the component performing the action
 * anchorName - the name of the anchor used when the page is refreshed
 * actionNameEnc - the encoded name of the action being performed
 * wclhidden - the encoded name of the hidden field
 * wclanchor - the encoded name of the hidden field for the anchor
 */
function doTbl(formName, actionName, actionValue, anchorName, actionNameEnc, wclhidden, wclanchor, event) {
   if ( event != null ) {
      //if user ctrl-/shift-/alt-clicked for table action, prevent action from opening new tab/window/etc
      if ( event.ctrlKey || event.shiftKey || event.altKey ) {
         if ( event.preventDefault ) {
            //W3C Model, Mozilla/Opera
            event.preventDefault();
            event.stopPropagation();
         } else {
            //Microsoft Model, IE
            event.returnValue = false;
            event.cancelBubble = true;
         }

         //if shift-click, turn actionValue "select(n)" into "select(multi-n)"
         if ( event.shiftKey && actionValue.indexOf("select") != -1 ) {
            var re = /(select\()(\d*\))/;
            actionValue = actionValue.replace(re, "$1multi-$2");
         }
      }//endIf
   }//endIf

   if (document != null && document.forms != null && formName != null) {
      var form = document.forms[formName];
      if (form != null) {
         if (actionName != null) {
            eval("form." + actionNameEnc + ".value = '" + actionValue + "'");
            eval("form." + wclhidden + ".value = '" + actionName + "'");
         }

         doAnchor(formName, anchorName, wclanchor);
         form.submit();
      }
      return false;
   }//endIf
}

/** WTable
 *
 * Mimic regular radio buttons/check boxes in tables so space
 * bar can be used.
 *
 * @param actionElement the anchorelement
 * @param event         keyPress Event
 */
function doTblKeyPress( actionElement, event ){
    //get the keycode
    if( event ){
        var wevent = new WEvent(event);
        //if space bar fire its onclick event
        if( wevent && actionElement && wevent.getKeyCode() == 32){
            if ( event.preventDefault ) {
                //W3C Model, Mozilla/Opera
                event.preventDefault();
                event.stopPropagation();
            } else {
                //Microsoft Model, IE
                event.returnValue = false;
                event.cancelBubble = true;
            }
            actionElement.onclick();
        }
    }
}

/** WTable (scrolling)**
 * setup table for scrolling
 */
function setupTable(dataBodyEnc, resetTable)
{
   var dataBody = document.getElementById(dataBodyEnc);
   if ( dataBody == null ) {
      return;
   }

   if (dataBody.offsetHeight > 0 || dataBody.parentNode.parentNode.offsetHeight > 0) {
      if ( resetTable == null ) {
         resetTable = false;
      } else if ( resetTable ) {
         minimizeTable(dataBodyEnc);
      }

      if ( !WClient.isBrowserInternetExplorer() ) {
         adjustTableHeight(dataBodyEnc);
      }

      var scrollPaneEnc = dataBody.getAttribute('SPID');
      var scrollPane = document.getElementById(scrollPaneEnc);
      if (scrollPane.getAttribute('H1BID')) {
         resizeDiv(scrollPaneEnc, resetTable);

         if ( WClient.isBrowserOpera() ) {
            var div = document.getElementById(scrollPaneEnc);
            var headBody2 = document.getElementById(div.getAttribute('H2BID'));
            headBody2.style.display = 'none';
            resizeDiv(scrollPaneEnc, false);
         }
      }

      if ( WClient.isBrowserInternetExplorer() ) {
         adjustTableHeight(dataBodyEnc);
      }

      // set scroll position for tasks
      setTimeout( "ensureIndexIsVisible('" + dataBodyEnc + "')", WClient.isBrowserInternetExplorer() ? 300 : 10 );
   }
   else
      setTimeout("setupTable('" + dataBodyEnc + "', " + resetTable + ")", 10);
}

/** WTable (scrolling)
 *  Handle scrollbar positioning for tasks ...
 */
function ensureIndexIsVisible( dataBodyEnc, currViewportPage ) {
    var dataBody = document.getElementById(dataBodyEnc);
    if ( !dataBody ) {
       return;
    } // end if
    if ( currViewportPage == null || currViewportPage === undefined ) {
      currViewportPage = dataBody.getAttribute('CVPG');
    }
    if ( !isNaN(parseInt(currViewportPage)) && parseInt(currViewportPage) !== -1 ) {
        var scrollPaneEnc = dataBody.getAttribute('SPID');
        var scrollPane    = document.getElementById(scrollPaneEnc);
        var viewRows      = parseInt(dataBody.getAttribute('RPV'));
        if ( (currViewportPage * viewRows) <= (dataBody.rows.length-1)  ) {
            scrollPane.scrollTop = dataBody.rows[ currViewportPage * viewRows ].offsetTop;
        }

    } // end if
} // ensureIndexIsVisible()

/** WTree (scrolling)
 *  Handle scrollbar positioning for tasks ...
 */
function ensureNodeIsVisible( treeID, nodeID, alignWithTop ) {
    var treeNode = document.getElementById(nodeID);
    if ( treeNode ) {
       treeNode.scrollIntoView(alignWithTop);
    }
/* scrollIntoView works in all tested browsers, so no need for this
    var treeDiv = document.getElementById(treeID);
    var treeNode = document.getElementById(nodeID);

    // if node or div not found, give up
    if ( !treeDiv || !treeNode ) {
       return;
    } // end if

    //HMC's TreeTag hacks an hmc:scrollpane around a wcl:WTree to handle AUIML trees defined with
    //a specific height/width.  The scrollpane is rendered as a div and should be one of the first
    //few (non wcl_ajax_container) DIV ancestors of the WTree DIV.
    // find parent scrollpane div; give up if not found in first 10 ancestors
    var i = 0;
    var parent = treeDiv;
    var scrollpane = null;
    while ( parent != null && scrollpane == null && i++ < 10 ) {
       parent = parent.parentNode;
       if ( parent.tagName == 'DIV' && parent.getAttribute("wcl_ajax_container") !== "true" ) {
          scrollpane = parent;
       }
    }
*/
} // ensureNodeIsVisible()

/** WTable
 * set table height based on set rows per viewport value
 */
function adjustTableHeight(dataBodyEnc) {
    wclajax_debug("-> adjustTableHeight("+dataBodyEnc+")");
    var dataBody = document.getElementById(dataBodyEnc);
    if ( !dataBody ) {
       return;
    }
    var scrollPaneEnc = dataBody.getAttribute('SPID');
    var scrollPane = document.getElementById(scrollPaneEnc);
    var actionBarEnc = dataBody.getAttribute('ABID');
    var actionBar = document.getElementById(actionBarEnc);
    var offset = actionBar ? actionBar.offsetHeight : 0;
    var viewRows = parseInt(dataBody.getAttribute('RPV'));
    var dviewRows = viewRows;
    var autorpv = dataBody.getAttribute('AUTORPV');
    var rpvMax  = parseInt(dataBody.getAttribute('RPVMAX'));
    var numRows = parseInt(dataBody.getAttribute('DR'));
    var prefHeight = parseInt(dataBody.getAttribute('PREFHT'));
    var maxViewRows = rpvMax;
    var isCTR = dataBody.getAttribute('CTR') == "true";

    var height = WClient.isBrowserOpera() ? dataBody.clientHeight : dataBody.offsetHeight;
    var rowHeight  = ( dataBody.rows.length == 0 ? 25 : (height / dataBody.rows.length) );
    var miscHeight = isCTR || WClient.isBrowserInternetExplorer() ? 0 : 3; //add misc space to account for hidden inputs, which mozilla doesnt completely hide

    var scrollParent = scrollPane.parentNode.parentNode;

   if (dataBody.rows.length == 0) {
       if (isCTR) {
           scrollPane.style.height = 0;
           scrollPane.height = 0;
       }
/* Do nothing for empty tables, renderer handles sizing the None area (which may not exist based on rendering options)
         //empty table row height
         var minRowsDisp = dataBody.getAttribute('MRD');
         var rowsPerPage = dataBody.getAttribute('RPP');
         minRowsDisp = Number(minRowsDisp) == 0 ? 4 : Number(minRowsDisp);
        var defaultOffsetHeight = dataBody.getAttribute('DOH');
        if ( defaultOffsetHeight == "0" ) {
          dViewRows = 0;
          offset = 0;
        } else {
          dViewRows = Math.min(minRowsDisp, Number(viewRows));
          offset = offset + defaultOffsetHeight;
        }
       //scrollPane.style.height = offset + ((dataBody.offsetHeight > 0 ? dataBody.offsetHeight : defaultOffsetHeight) * min)
          // 									    + (WClient.isBrowserMozilla() ? 3 : 0)
          // 									    + (WClient.isBrowserMozilla() ? min*6 : min);
*/
    } else {
      wclajax_debug("   adjustTableHeight: autorpv ["+autorpv+"] prefHeight ["+prefHeight+"] scrollParent.offsetHeight ["+scrollParent.offsetHeight+"]");
      if ( autorpv == 'true' || ( prefHeight > 0 && prefHeight < scrollParent.offsetHeight ) ) {
        //automatically calculate rpv if autorpv enabled or preferred height is
        //set and its less than the current height
        //need to autoresize if IE or no rpvmax given (not known by server yet) or
        //the viewport is too big for the number of rows we have, or we're
        //not showing as many rows possible
        //@hmc@ - support modern IE
        //if ( WClient.isBrowserInternetExplorer() || rpvMax <= 0 || viewRows > numRows || viewRows != rpvMax ) {
        var ie5ish = WClient.isBrowserInternetExplorer() && parseInt(WClient.getBrowserVersion()) < 10;
        wclajax_debug("   adjustTableHeight: ie5ish ["+ie5ish+"] rpvMax ["+rpvMax+"] viewRows ["+viewRows+"] numRows ["+numRows+"]");
        if ( rpvMax <= 0 || viewRows > numRows || viewRows != rpvMax ) {
          //flagged for auto-size
          scrollPane.style.height = offset + (rowHeight * numRows) + miscHeight;

          var miscSpace = 100;
          //var defaultScrollTop = ( WClient.isBrowserInternetExplorer() ) ? 70 : 55;
          var defaultScrollTop = 55;
          if (scrollParent) {
              var scrollTop = WUtilities.getTop(scrollParent, true);
              if ( scrollTop <= 0) {
                  scrollTop = defaultScrollTop;
              }
              //@hmc@ - support modern IE
              //var buffer =  ( WClient.isBrowserInternetExplorer() ) ? 20 : 15;
              var buffer =  ie5ish ? 20 : 15;
              miscSpace = ( scrollParent.offsetHeight - scrollPane.scrollHeight );//space occupied by table Header/Footer
              wclajax_debug("   adjustTableHeight: 1 miscSpace ["+miscSpace+"]");
              if ( prefHeight == 0 ) {
                  miscSpace = miscSpace + scrollTop + buffer; //+ vertical offset of table + browser-dependent buffer
                  wclajax_debug("   adjustTableHeight: 2 miscSpace ["+miscSpace+"]");
              }
              if ( miscSpace < 0 ) {
                  miscSpace = 100;
              }
          }

          wclajax_debug("   adjustTableHeight: 3 miscSpace ["+miscSpace+"]");

          //@hmc@ - support modern IE
          //dviewRows = ( ( ( prefHeight > 0 ) ? prefHeight : ( WClient.isBrowserInternetExplorer() ? document.body.offsetHeight : window.innerHeight ) ) - miscSpace ) / rowHeight;
          dviewRows = ( ( ( prefHeight > 0 ) ? prefHeight : ( ie5ish ? document.body.offsetHeight : window.innerHeight ) ) - miscSpace ) / rowHeight;
          viewRows = Math.floor(dviewRows);
          maxViewRows = viewRows;

          viewRows = Math.max(Math.min(MIN_ROWS_VISIBLE,numRows),Math.min(numRows, viewRows));   //min MIN_ROWS_VISIBLE rows (or numRows, if < MIN_ROWS_VISIBLE rows) visible
          dviewRows = Math.max(Math.min(MIN_ROWS_VISIBLE,numRows),Math.min(numRows, dviewRows)); //min MIN_ROWS_VISIBLE rows (or numRows, if < MIN_ROWS_VISIBLE rows) visible
        }

        wclajax_debug("   adjustTableHeight: dviewRows ["+dviewRows+"] viewRows ["+viewRows+"] maxViewRows ["+maxViewRows+"]");

        // ff4+ (mozilla 2.0) need to remove a few more pixels
        if ( WClient.isBrowserWebKit() || (WClient.isBrowserMozilla() && WClient.mozMajor >= 2) ) {
            var headBody2 = document.getElementById(scrollPane.getAttribute('H2BID'));
            miscHeight = miscHeight - 3; //- parseInt(headBody2.firstChild.clientHeight);
        }
      } else {
          var str = "   adjustTableHeight: viewRows ["+viewRows+"] numRows ["+numRows+"] -> ";
          //user-defined, static rows per viewport value
          viewRows = Math.min(numRows, viewRows);
          dviewRows = viewRows;
          str = str+"viewRows ["+viewRows+"] dviewRows ["+dviewRows+"]";
          wclajax_debug(str);
      }

      var height = offset + (rowHeight * dviewRows) + miscHeight;

      // @hmc - zRFE-445008: Allow task tables to grow to fill unused vertical space
      if (isCTR) {
        try {
          scrollPane.style.height = '100%';

          // Table's max height is found by calculating page height minus non-table-body content height. Non-page content
          // includes page margin, table header/footer, and other page content (text, inputs, buttons, etc).
          // Min height is RPV height (so do not update viewRow value, which updates hidden rpv input).
          var formBottom = document.getElementsByTagName("Form")[0].getBoundingClientRect().bottom; // hmcBannerFrame comes before FORM, so we can ignore it
          var tableBodyHeight = document.getElementById(dataBodyEnc.replace("DB", "TB")).getBoundingClientRect().height;
          var dataBodyHeight = dataBody.getBoundingClientRect().height;
          var bodyStyle = getComputedStyle(document.body);
          wclajax_debug(`   adjustTableHeight: formBottom = ${formBottom} tableBodyHeight = ${tableBodyHeight} dataBodyHeight = ${dataBodyHeight}`);

          var pageMarginHeight = (2 * parseInt(bodyStyle["margin-top"]));
          var tableHeaderFooterHeight = (tableBodyHeight - dataBodyHeight);
          var nonTableContentHeight = (formBottom - tableBodyHeight);
          var statusBarHeight = 10; // 10px misc space for Chrome/Edge/Firefox floating status bar
          wclajax_debug(`   adjustTableHeight: window.innerHeight = ${window.innerHeight} pageMarginHeight = ${pageMarginHeight} tableHeaderFooterHeight = ${tableHeaderFooterHeight} nonTableContentHeight = ${nonTableContentHeight}`);

          // min height is rpv height; max is window height minus non-table content. neither may be larger that data body height
          var minHeight = height;
          var maxHeight = window.innerHeight - pageMarginHeight - nonTableContentHeight - tableHeaderFooterHeight - statusBarHeight;
          height = Math.max(Math.min(maxHeight, dataBodyHeight), Math.min(minHeight, dataBodyHeight));
          wclajax_debug(`   adjustTableHeight:  minHeight = ${minHeight} maxHeight = ${maxHeight} height = ${height}`);
        } catch (e) {
        }
      }
      // @hmc - end

      scrollPane.style.height = height;
      scrollPane.height = height;
    }

    //hide scrollbar if all rows visible
    scrollPane.style.overflowX = "hidden";
    scrollPane.style.overflowY = (dataBody.rows.length == 0 || viewRows == numRows) ? "hidden" : "auto";

    wclajax_debug("<- adjustTableHeight: ["+viewRows+", "+maxViewRows+"]");
    return new Array(viewRows, maxViewRows);
}

/** WTable (scrolling)**
* handles resize of div
function resizeDiv(divID)
{
  var div = document.getElementById(divID);
  var headBody1 = document.getElementById(div.getAttribute('H1BID'));
  var headBody2 = document.getElementById(div.getAttribute('H2BID'));
  var tableStyle = headBody2.parentNode.style;
  var cellCount = headBody2.rows[0].cells.length-1;
  var widths = new Array(cellCount);

  tableStyle.tableLayout = 'auto';
  tableStyle.width = "auto";
  var sum = 0;
  if (window[divID + "_firstTime"] == undefined) {
       window[divID + "_firstTime"] = true;
     }
  for (var c = 0; c < cellCount; c++) {
      var head1 = headBody1.rows[0].cells[c];
      var head2 = headBody2.rows[0].cells[c];

     head2.firstChild.style.tableLayout = 'auto';
     if (head1.minWidth == undefined) {
       var cells = head1.firstChild.rows[0].cells;
           var minWidth = cells[0].firstChild.offsetWidth + 3;
           for (var i=1; i < cells.length; i++)
              minWidth += parseInt(cells[i].offsetWidth);
           head1.minWidth = minWidth;
    }
       widths[c] = head1.width != '' ? head1.width : head2.offsetWidth;
    if (widths[c] < head1.minWidth) {
      widths[c] = head1.minWidth;
    }
    if (window[divID + "_firstTime"]) {
      sum += parseInt(widths[c]);
      if (c == cellCount-1 && sum < div.clientWidth) {
            //widths[c] += div.clientWidth - sum;
            temp = parseInt(widths[c]) + (div.clientWidth - sum);
        widths[c] = temp.toString(10);
          }
    }
  }
  tableStyle.display = 'none';
  var temp = headBody2.rows[0].cells[0].offsetWidth;	//LC magic - this is needed for properly setting the display = 'none' style - only for Firefox
 // [#94601] Table does not resize when new column items or larger size are added to it - Changed tableStyle.tableLayout = 'fixed' to tableStyle.tableLayout = 'auto' for Firefox since it does not support elipsis;
  if(WClient.isBrowserMozilla())
       tableStyle.tableLayout = 'auto';
     else
       tableStyle.tableLayout = 'fixed';
  tableStyle.display = '';

  for (var c = 0; c < cellCount; c++) {
      var head1 = headBody1.rows[0].cells[c];
      var head2 = headBody2.rows[0].cells[c];

      head1.width = widths[c];
      head1.style.width = widths[c];
      head2.width = widths[c];
      head2.style.width = widths[c];
  }
  tableStyle.width = "";	// fixes last column resizing problem

  //@auiml - begin - needed for scrollable tree tables
  var children = div.childNodes[0].childNodes; //@auiml - ordering of table div child nodes is reversed in ajax //@auiml - changed index back to 0
  var dataBody = null;
  for (var i=0; i<children.length; i++)
  {
      if (children[i].getAttribute('SPID') != null)
      {
        dataBody = children[i];
        break;
      }
  }

  if (dataBody != null && dataBody.offsetHeight > 0)
  {
      var actionBarEnc = dataBody.getAttribute('ABID');
      var actionBar = document.getElementById(actionBarEnc);
      var offset = actionBar ? actionBar.offsetHeight : 0;
      var viewRows = dataBody.getAttribute('RPV');
      var numRows = dataBody.getAttribute('DR');

        var minRows = 1;
        if(numRows < minRows)
           numRows = minRows;

    //@auiml - scrollable treetable anchoring
     var hght = offset + ((dataBody.offsetHeight / dataBody.rows.length) * Math.min(numRows, viewRows));
      var selRow = -1;
      div.style.height = hght;
      var headerRowId = div.previousSibling.id;
     var tableName = headerRowId.substring(0,headerRowId.indexOf("_headerRow"));
     var tableContainer = null;
     if (document.getElementById(tableName+"_tableContainer"))
     {
       tableContainer = document.getElementById(tableName+"_tableContainer");
     tableContainer.setAttribute("TOTALHEIGHT", hght);
      }

    var rows = dataBody.childNodes;
    for (var i=0; i<rows.length; i++)
      {
         var images = rows[i].getElementsByTagName("IMG");
         if (images != null)
         {
            for (var j=0;j<images.length;j++)
            {
              var img = images[j];
              if (img.src.indexOf("tbl3.gif") > 0)
              {
                selRow=i;
                break;
              }
            }
         }
      }
      if (selRow < 0 ) 	//no selection
        div.scrollTop = 0;
    else 				//selection
       //don't scroll is selection is in current view
       if (selRow < viewRows -1)
         div.scrollTop = 0;
       else
           div.scrollTop = dataBody.offsetHeight/rows.length*selRow;
    //@auiml - end
  }
  window[divID + "_firstTime"] = false;
}
*/

/** WTable (scrolling)**
 * handles resize of div
 */
function resizeDiv(divID, resetTable)
{
   if ( resetTable == null ) {
      resetTable = false;
   }
   if ( WClient.isBrowserOpera() ) {    //opera call before IE as Opera may identify itself as IE
       resizeDivOpera(divID, resetTable);
   } else if ( WClient.isBrowserInternetExplorer() ) {
       resizeDivIE(divID, resetTable);
   } else {
       resizeDivMoz(divID, resetTable);
   }
}

/** WTableColumn (drag-n-drop)**
 * handles resize of table columns
 */
function tcDND(event, evtCode, columnId, divID)
{
   var wevent = new WEvent(event);
   var column = document.getElementById(columnId);

   switch (evtCode) {
   case 1: // mouseDown (grab)
      if (!column.isDragging)
      {
         var cells = column.firstChild.rows[0].cells;
         column.isDragging = true;
         column.startPosition = column.currentPosition = wevent.getPagePosition();
         column.startWidth = WUtilities.getWidth(column);
         // save document's mouse handlers
         document._onselectstart = document.onselectstart;
         document._onmousemove = document.onmousemove;
         document._onmouseup = document.onmouseup;
         document.body._cursor = document.body.style.cursor;
         // temporarily override document's mouse handlers
         document.onselectstart = new Function("event", "return false;");
         document.onmousemove = new Function("event", "return tcDND(event, 2, '" + columnId + "', '" + divID + "');");
         document.onmouseup = new Function("event", "return tcDND(event, 3, '" + columnId + "', '" + divID + "');");
         document.body.style.cursor = "e-resize";

         return false;
      }
      break;
   case 2: // mouseMove (drag)
      if (column.isDragging)
      {
         var mousePosition = wevent.getPagePosition();
         var difference = mousePosition.getX() - column.startPosition.getX();
         var div = document.getElementById(divID);
         if(div != null){
           var bidi = div.getAttribute("BIDI");

           if (bidi)
             difference = -difference;
         }

         column.width = Math.min(Math.max(column.startWidth + difference, column.minWidth), column.maxWidth) + "px";
         column.currentPosition = mousePosition;

         if(div != null){
           resizeDiv(divID, false);
         }

         return false;
      }
      break;
   case 3: // mouseUp (drop)
      if (column.isDragging)
      {
         column.isDragging = false;
         // restore document's mouse handlers
         document.onselectstart = document._onselectstart;
         document.onmousemove = document._onmousemove;
         document.onmouseup = document._onmouseup;
         document.body.style.cursor = document.body._cursor;
         // save width
         var input = column.firstChild.rows[0].lastChild.lastChild;

         input.value = column.width ? column.width : "-1";

         return false;
      }
      break;
   }
   return true;
}

/** WTableColumn
 *  returns a column's minWidth
 */
function getColumnMinWidth(column) {
   if ( column.minWidth ) {
      return column.minWidth;
   }
   return MIN_COL_WIDTH;
}

/** WTableColumn
 *  returns a column's maxWidth
 */
function getColumnMaxWidth(column) {
   if ( column.maxWidth ) {
      return column.maxWidth;
   }
   return MAX_COL_WIDTH;
}

/** WTableColumn
 *  initialize min/maxWidth values for the column at colIdx in the table inside of divID whose current width is width
 */
function initColumnMinMaxWidths(divID, colIdx, width) {
   var div = document.getElementById(divID);
   var headBody1 = document.getElementById(div.getAttribute('H1BID'));
   var column = headBody1.rows[0].cells[colIdx];

   //determine maxWidth
   var minWidth = MIN_COL_WIDTH;
   try {
      if ( ( column.getAttribute("justify") == "enlarge" && width > minWidth )
        || column.getAttribute("justify") == "none" )
      {
         minWidth = width;
      }
   } catch (e) {
      minWidth = MIN_COL_WIDTH;
   }
   column.minWidth = minWidth;

   //determine maxWidth
   var maxWidth = MAX_COL_WIDTH;
   try {
      if ( column.getAttribute("justify") == "shrink" || column.getAttribute("justify") == "none" ) {
         maxWidth = width;
      }
   } catch (e) {
      maxWidth = MAX_COL_WIDTH;
   }
   column.maxWidth = maxWidth;
}

/** WTableColumn (successive drag-n-drop)**
 * handles successive resize of table columns
 */
function tcSDND(event, evtCode, columnId, divID)
{
   var wevent = new WEvent(event);
   var column = document.getElementById(columnId);

   //init tableColumn id <-> columndIndex hash
   var div = document.getElementById(divID);
   if ( WTableData.tableColumns_ == null ) {
     WTableData.tableColumns_ = new Array();
   }
   if ( WTableData.tableColumns_[divID] == null ) {
      WTableData.tableColumns_[divID] = new Array();
      var headBody1 = document.getElementById(div.getAttribute('H1BID'));
      var cellCount = headBody1.rows[0].cells.length-1;
      for (var c = 0; c < cellCount; c++) {
         var head1 = headBody1.rows[0].cells[c];
         WTableData.tableColumns_[divID][c] = head1.id;
         WTableData.tableColumns_[divID][head1.id] = c;
      }
   }

   switch (evtCode) {
   case 1: // mouseDown (grab)
      if (!column.isDragging)
      {
         column.isDragging = true;
         column.startPosition = column.currentPosition = wevent.getPagePosition();
         column.startWidth = WUtilities.getWidth(column);
         // save document's mouse handlers
         document._onselectstart = document.onselectstart;
         document._onmousemove = document.onmousemove;
         document._onmouseup = document.onmouseup;
         document.body._cursor = document.body.style.cursor;
         // temporarily override document's mouse handlers
         document.onselectstart = new Function("event", "return false;");
         document.onmousemove = new Function("event", "return tcSDND(event, 2, '" + columnId + "', '" + divID + "');");
         document.onmouseup = new Function("event", "return tcSDND(event, 3, '" + columnId + "', '" + divID + "');");
         document.body.style.cursor = "e-resize";

         //loop over columns and ensure column's needed values are set
         for (var i=WTableData.tableColumns_[divID][column.id]-1; i >= 0; i--) {
            var currColumn = document.getElementById(WTableData.tableColumns_[divID][i]);
            currColumn.startWidth = WUtilities.getWidth(currColumn);
         }

         return false;
      }
      break;
   case 2: // mouseMove (drag)
      if (column.isDragging)
      {
         var mousePosition = wevent.getPagePosition();
         var difference = mousePosition.getX() - column.startPosition.getX();
         var bidi = document.getElementById(divID).getAttribute("BIDI");

         if (bidi)
            difference = -difference;

         columnWidth = column.startWidth + difference;
         column.currentPosition = mousePosition;

         if ( columnWidth < MIN_COL_WIDTH && WTableData.tableColumns_ != null && WTableData.tableColumns_[divID] != null ) {
            //successive shrinking
            var columnIndex = WTableData.tableColumns_[divID][columnId]; //get column index from table columns hash (init by setupTable)
            var i = 1;
            var done = false;
            var startWidth = column.startWidth;

            column.width = MIN_COL_WIDTH + "px";
            var cellPadding = ( WClient.isBrowserInternetExplorer() ) ? 0 : (parseInt(column.style.borderLeftWidth) + parseInt(column.style.borderRightWidth));
            if ( column.startWidth - parseInt(column.width) > 0 ) {
               column.startPosition = new Position(column.startPosition.getX() - (column.startWidth - parseInt(column.width) - cellPadding), column.startPosition.getY(), column.startPosition.getZ());
            }
            difference = difference + column.startWidth - parseInt(column.width);
            column.startWidth = parseInt(column.width);

            //may need to loop through columns if previous column is already minWidth
            while ( columnIndex-i >= 0 && !done ) {
               var prevColumn = document.getElementById(WTableData.tableColumns_[divID][columnIndex-i]);

               //if prevColumn is already minWidth, skip to column preceeding it
               if ( parseInt(prevColumn.width) <= MIN_COL_WIDTH ) {
                  prevColumn.width = MIN_COL_WIDTH + "px";
                  if ( prevColumn.startWidth - parseInt(prevColumn.width) > 0 ) {
                     column.startPosition = new Position(column.startPosition.getX() - (prevColumn.startWidth - parseInt(prevColumn.width) - cellPadding), column.startPosition.getY(), column.startPosition.getZ());
                  }
                  difference = difference + prevColumn.startWidth - parseInt(prevColumn.width);
                  prevColumn.startWidth = parseInt(prevColumn.width);
                  i++;
               } else {
                  prevColumn.isDragging = true;  //flag column as dragging, so that its width is properly stored by drop case (below)
                  prevColumn.width = Math.max(prevColumn.startWidth + difference, MIN_COL_WIDTH) + "px";
                  done = true;
               }
            }
         } else {
            column.width = columnWidth + "px";
         }

         resizeDiv(divID, false);

         return false;
      }
      break;
   case 3: // mouseUp (drop)
      if (column.isDragging)
      {
         column.isDragging = false;
         // restore document's mouse handlers
         document.onselectstart = document._onselectstart;
         document.onmousemove = document._onmousemove;
         document.onmouseup = document._onmouseup;
         document.body.style.cursor = document.body._cursor;
         // save width
         var input = column.firstChild.rows[0].lastChild.lastChild;

         input.value = column.width ? column.width : "-1";
         column.startWidth = WUtilities.getWidth(column);

         //loop over all isDragging columns, saving their width
         var colCount = WTableData.tableColumns_[divID].length;
         var done = false;
         for (var i=colCount-1; i >= 0; i--){
            var currColumn = document.getElementById(WTableData.tableColumns_[divID][i]);

            if ( i <= WTableData.tableColumns_[divID][column.id]-1 && !done) {
                if (currColumn.isDragging) {
                   currColumn.isDragging = false;
                   // save width
                   var input = currColumn.firstChild.rows[0].lastChild.lastChild;

                   input.value = currColumn.width ? currColumn.width : "-1";
                   currColumn.startWidth = WUtilities.getWidth(currColumn);
                } else {
                   done = true;
                }
            }

            currColumn.setAttribute("prefWidth", currColumn.width);
         }

         //save column widths if external method is defined
         if ( typeof saveColumnWidths == 'function' ) {
             saveColumnWidths(divID);
         }
         return false;
      }
      break;
   }
   return true;
}



/** WTable (scrolling)**
 * handles resize of div for IE
 */
function resizeDivIE(divID, resetTable)
{
   var div = document.getElementById(divID);
   var resizeOption = div.getAttribute("resizeOption") == null ? '' : div.getAttribute("resizeOption");
   var headBody1 = document.getElementById(div.getAttribute('H1BID'));
   var headBody2 = document.getElementById(div.getAttribute('H2BID'));
   var tableStyle = headBody2.parentNode.style;
   var cellCount = headBody2.rows[0].cells.length-1;
   var widths = new Array(cellCount);
   var init = ( headBody1.rows[0].cells[0].getAttribute("initWidth") == null );
   var preset =  ( init && headBody1.rows[0].cells[0].width != '' ) || ( resetTable && headBody1.rows[0].cells[0].getAttribute("prefWidth") != null );
   tableStyle.tableLayout = 'auto';

   var totalWidth = 0;
   var justifiedWidthShrink  = 0;    //width to play with when columns have to shrink
   var justifiedWidthEnlarge = 0;    //width to play with when columns have to enlarge

   if ( resetTable || init ) {
      if ( WClient.isBrowserVersion8Up() || WClient.isCompatibilityView() ) {
         for (var c = 0; c < cellCount; c++) {
            var head2 = headBody2.rows[0].cells[c];
            head2.style.display='none';
            head2.firstChild.style.tableLayout = 'auto';
            head2.style.display='';
         }
      }

      for (var c = 0; c < cellCount; c++) {
         var head1 = headBody1.rows[0].cells[c];
         var head2 = headBody2.rows[0].cells[c];

         head1.style.tableLayout = 'auto';
         head2.firstChild.style.tableLayout = 'auto';

         if ( preset && head1.getAttribute("prefWidth") == null ) {
            head1.setAttribute("prefWidth", head1.width);
         }

         widths[c] = ( preset ) ? head1.width : parseInt(head2.offsetWidth);
         totalWidth += widths[c];

         var justify = head1.getAttribute("justify");
         if ( justify == "shrink"  || justify == "shrinkAndEnlarge" ) {
           justifiedWidthShrink += widths[c];
         }
         if ( justify == "enlarge" || justify == "shrinkAndEnlarge" ) {
           justifiedWidthEnlarge += widths[c];
         }

         //init column min/maxWidth values
         if ( init ) {
            head1.setAttribute("initWidth", widths[c]);
            initColumnMinMaxWidths(divID, c, widths[c]);
         }
      }
   } else {
      for (var c = 0; c < cellCount; c++) {
         var head1 = headBody1.rows[0].cells[c];
         var head2 = headBody2.rows[0].cells[c];
         head2.firstChild.style.tableLayout = 'fixed';
         widths[c] = head1.width;
      }
   }

   tableStyle.display = 'none';
   tableStyle.tableLayout = 'fixed';
   tableStyle.display = '';

   //width to play with (because this table is either shrinking or enlarging)
   var tableWidth = headBody1.offsetWidth;
   var justifiedWidth = ( tableWidth - totalWidth < 0 ) ? justifiedWidthShrink : justifiedWidthEnlarge;

   var misc = 0;
   var cellSum = 0;
   for (var c = 0; c < cellCount; c++) {
       var head1 = headBody1.rows[0].cells[c];
       var head2 = headBody2.rows[0].cells[c];
       var shrunk = false;

       try {
           headBody1.rows[0].cells[c].firstChild.firstChild.firstChild.firstChild.height = '100%';
       } catch (e) {}

       //justify column
       if ( !preset && ( resetTable || init ) ) {
          if ( c == cellCount-1 && resizeOption == "WTableResizeLast" ) {
              shrunk = true;
              widths[c] = "100%";
          } else if ( c == cellCount-1 && resizeOption == "WTableResizeEndColumns" && tableWidth != totalWidth ) {
              widths[c] = Math.max(head1.offsetWidth,tableWidth-cellSum);
          } else if ( justifiedWidth > 0 && head1.getAttribute("justify") != "none" && tableWidth != totalWidth) {
              if ( ( tableWidth - totalWidth <  0  && head1.getAttribute("justify") != "enlarge" )
                || ( tableWidth - totalWidth >= 0  && head1.getAttribute("justify") != "shrink"  ) )
              {
                 widths[c] = widths[c] + Math.round( (tableWidth - totalWidth) * (widths[c] / justifiedWidth) );
                 if ( c == cellCount - 1 ) {
                    widths[c] = widths[c] - misc;
                 }
              }
              if ( widths[c] < getColumnMinWidth(head1) ) {
                 misc = misc + getColumnMinWidth(head1) - widths[c];
                 widths[c] = getColumnMinWidth(head1);
              }
          }
       }

       widths[c] = Math.max(MIN_COL_WIDTH, widths[c]);

       //head2.width = head1.width = widths[c];
       head2.width = head1.width = ( widths[c] != '' ) ? widths[c] : head1.width;
       cellSum = cellSum + parseInt(head2.width);
   }

   if ( resetTable || init ) {
      headBody2.setAttribute("initWidth", tableWidth);
   }

   //set table background to table header width
   if ( cellSum <= headBody2.getAttribute("initWidth") ) {
      // **MHB** Why is this necessary?
      // **MHB** Removing it corrects a table-rendering problem with task panels.
      // **MHB** Is it needed by the tree-style UI?  Commenting out the line ...
      // **MHB** ... does not appear to have any effect on the tree-style UI.
//    headBody2.parentNode.width = headBody2.getAttribute("initWidth");
   }

   //increase header row height, in case column headers contain breakrules
   try {
       var clientHeight = headBody1.rows[0].cells[0].clientHeight;
       for (var c = 0; c < cellCount; c++) {
           headBody1.rows[0].cells[c].firstChild.firstChild.firstChild.firstChild.height = clientHeight;
       }
   } catch (e) {}
}

/** WTable (scrolling)**
 * handles resize of div for Mozilla
 */
function resizeDivMoz(divID, resetTable)
{
   var div = document.getElementById(divID);
   var resizeOption = div.getAttribute("resizeOption") == null ? '' : div.getAttribute("resizeOption");
   var headBody1 = document.getElementById(div.getAttribute('H1BID'));
   var headBody2 = document.getElementById(div.getAttribute('H2BID'));
   var tableStyle  = headBody2.parentNode.style;
   var tableStyle1 = headBody1.style;
   var cellCount = headBody2.rows[0].cells.length-1;
   var widths = new Array(cellCount);
   var init = ( headBody1.rows[0].cells[0].getAttribute("initWidth") == null );
   var preset =  ( init && headBody1.rows[0].cells[0].width != '' ) || ( resetTable && headBody1.rows[0].cells[0].getAttribute("prefWidth") != null );
   var presetWidths = new Array(cellCount);

   var totalWidth = 0;

   div.style.width='0px';           //shrink div to content
   headBody1.style.width='0px';     //shrink header table to content
   headBody2.style.width='0px';     //shrink data table to content

   if ( resetTable || init ) {
      var justifiedWidthShrink  = 0;   //width to play with when columns have to shrink
      var justifiedWidthEnlarge = 0;   //width to play with when columns have to enlarge

      headBody2.setAttribute("initWidth", div.parentNode.clientWidth);

      for (var c = 0; c < cellCount; c++) {
         var head1 = headBody1.rows[0].cells[c];
         var head2 = headBody2.rows[0].cells[c];
         head2.firstChild.style.tableLayout = 'auto';

         if ( preset && head1.getAttribute("prefWidth") == null ) {
            head1.setAttribute("prefWidth", head1.width);
         }

         widths[c] = parseInt( ( preset ) ? head1.width
                                          : ( (resetTable) ? head1.getAttribute("initWidth") : head2.offsetWidth ) );

         totalWidth += widths[c];
         var justify = head1.getAttribute("justify");
         if ( justify == "shrink"  || justify == "shrinkAndEnlarge" ) {
           justifiedWidthShrink += widths[c];
         }
         if ( justify == "enlarge" || justify == "shrinkAndEnlarge" ) {
           justifiedWidthEnlarge += widths[c];
         }

         //init column min/maxWidth values
         if ( init ) {
            head1.setAttribute("initWidth", widths[c]);
            initColumnMinMaxWidths(divID, c, widths[c]);
         }
      }
   } else {
      //drag and drop resizing going on
      for (var c = 0; c < cellCount; c++) {
         var head1 = headBody1.rows[0].cells[c];
         var head2 = headBody2.rows[0].cells[c];
         head2.firstChild.style.tableLayout = 'fixed';
         widths[c] = parseInt(head1.width);
      }
   }

   //width to play with (because this table is either shrinking or enlarging)
   var justifiedWidth = ( headBody1.offsetWidth - totalWidth < 0 ) ? justifiedWidthShrink : justifiedWidthEnlarge;

   //disable autosizing
   tableStyle.tableLayout  = 'fixed';
   tableStyle1.tableLayout = 'fixed';
   div.style.width = '100%';
   headBody1.style.overflowX='hidden';
   headBody2.style.overflowX='hidden';

   //set fixed column widths
   var misc = 0;
   var cellSum = 0;
   for (var c = 0; c < cellCount; c++) {
      var head1 = headBody1.rows[0].cells[c];
      var head2 = headBody2.rows[0].cells[c];
      var shrunk = false;
      var cellPadding = ( WClient.isBrowserInternetExplorer() ) ? 0 : (parseInt(head1.style.borderLeftWidth) + parseInt(head1.style.borderRightWidth));

      try {
         headBody1.rows[0].cells[c].firstChild.firstChild.firstChild.firstChild.height = '100%';
      } catch (e) {}

      //justify column
      if ( head1.getAttribute("justify") != "none" && !preset && ( resetTable || init ) ) {
         var cellPadding = parseInt(head1.style.borderLeftWidth) + parseInt(head1.style.borderRightWidth);
         if ( c == cellCount-1 && resizeOption == "WTableResizeLast" ) {
            shrunk = true;
            widths[c] = "100%";
         } else if ( c == cellCount-1 && resizeOption == "WTableResizeEndColumns" && headBody1.offsetWidth != totalWidth ) {
            widths[c] = widths[c] + Math.round( (headBody1.offsetWidth - totalWidth) * (widths[c] / justifiedWidth) ) - cellPadding - misc;
         } else if ( justifiedWidth > 0 && headBody1.offsetWidth != totalWidth) {
            if ( ( headBody1.offsetWidth - totalWidth <  0  && head1.getAttribute("justify") != "enlarge" )
              || ( headBody1.offsetWidth - totalWidth >= 0  && head1.getAttribute("justify") != "shrink"  ) )
            {
               widths[c] = widths[c] + Math.round( (headBody1.offsetWidth - totalWidth) * (widths[c] / justifiedWidth) ) - cellPadding;
               if ( c == cellCount - 1 ) {
                   widths[c] = widths[c] - misc;
               }
            }
            if ( widths[c] < getColumnMinWidth(head1) ) {
               misc = misc + getColumnMinWidth(head1) - widths[c];
               widths[c] = getColumnMinWidth(head1);
            }
         }
      }

      widths[c] = Math.max(MIN_COL_WIDTH, widths[c]);
      cellSum = cellSum + parseInt(widths[c]) + parseInt(cellPadding);

      head1.width = widths[c];
      head2.width = head1.width;
      head2.firstChild.width = head1.width;
   }

   headBody2.width = Math.max(cellSum, headBody2.getAttribute("initWidth"));
   headBody2.style.marginRight = "0px";
   headBody2.style.paddingRight = "0px";
   div.firstChild.border="0px";

   //increase header row height, in case column headers contain breakrules
   try {
      var clientHeight = headBody1.rows[0].cells[0].clientHeight;
      for (var c = 0; c < cellCount; c++) {
         headBody1.rows[0].cells[c].firstChild.firstChild.firstChild.firstChild.height = clientHeight;
      }
   } catch (e) {}
}


/** WTable (scrolling)**
 * handles resize of div for Opera
 */
function resizeDivOpera(divID, resetTable)
{
   var div = document.getElementById(divID);
   var resizeOption = div.getAttribute("resizeOption") == null ? '' : div.getAttribute("resizeOption");
   var headBody1 = document.getElementById(div.getAttribute('H1BID'));
   var headBody2 = document.getElementById(div.getAttribute('H2BID'));
   var tableStyle  = headBody2.parentNode.style;
   var tableStyle1 = headBody1.style;
   var cellCount = headBody2.rows[0].cells.length-1;
   var widths = new Array(cellCount);
   var init = ( headBody1.rows[0].cells[0].width == '' );

   var divWidth = div.offsetWidth;
   var totalWidth = 0;

   var justifiedWidthShrink  = 0;    //width to play with when columns have to shrink
   var justifiedWidthEnlarge = 0;    //width to play with when columns have to enlarge

   //flag tables for autosize
   if ( resetTable || init ) {
      div.style.width         = '0px';
      div.style.overflow      = 'auto'
      headBody1.style.width   = '0px';
      headBody2.style.width   = '0px';
      tableStyle1.tableLayout = 'auto';

      //get auto-sized column widths
      for (var c = 0; c < cellCount; c++) {
         var head1 = headBody1.rows[0].cells[c];
         var head2 = headBody2.rows[0].cells[c];

         head1.style.tableLayout = 'auto';
         head2.firstChild.style.tableLayout = 'auto';

         widths[c] = ( resetTable && headBody1.rows[0].cells[0].width != '' ) ? head1.getAttribute("initWidth") : ( head2.offsetWidth == 0 ) ? head1.offsetWidth : head2.offsetWidth;
         totalWidth = parseInt(totalWidth) + parseInt(widths[c]);

         if ( head1.getAttribute("justify") != "none" ) {
            justifiedWidth += parseInt(widths[c]);
         }

         //init column min/maxWidth values
         if ( init ) {
            head1.setAttribute("initWidth", widths[c]);
            initColumnMinMaxWidths(divID, c, widths[c]);
         }
      }
   }

   //width to play with (because this table is either shrinking or enlarging)
   var justifiedWidth = ( headBody1.offsetWidth - totalWidth < 0 ) ? justifiedWidthShrink : justifiedWidthEnlarge;

   //disable autosizing
   tableStyle.display      = 'none';
   tableStyle.tableLayout  = 'fixed';
   tableStyle1.display     = 'none';
   tableStyle1.tableLayout = 'fixed';
   div.style.width='100%';
   var divWidth = div.offsetWidth;
   tableStyle.display      = '';
   tableStyle1.display     = '';

   if ( resetTable || init ) {
      //set fixed column widths
      var cellSum = 0;
      var misc = 0;
      for (var c = 0; c < cellCount; c++) {
         var head1 = headBody1.rows[0].cells[c];
         var head2 = headBody2.rows[0].cells[c];
         var shrunk = false;

         if ( c == cellCount-1 && resizeOption == "WTableResizeLast" ) {
            shrunk = true;
            widths[c] = "100%";
         } else if ( justifiedWidth > 0 && head1.getAttribute("justify") != "none" && divWidth != totalWidth ) {
            if ( ( headBody1.offsetWidth - totalWidth <  0  && head1.getAttribute("justify") != "enlarge" )
              || ( headBody1.offsetWidth - totalWidth >= 0  && head1.getAttribute("justify") != "shrink"  ) )
            {
               widths[c] = widths[c] + Math.round( (divWidth - totalWidth) * (widths[c] / justifiedWidth) );
               if ( c == cellCount - 1 ) {
                   widths[c] = widths[c] - misc;
               }
            }
            if ( widths[c] < getColumnMinWidth(head1) ) {
               misc = misc + getColumnMinWidth(head1) - widths[c];
            }
         }

         //the scrollbar may be overwriting the lastfew characters in the table, cant tell if scrollbar is visible though
         if ( div.scrollHeight > (div.offsetHeight + 20) && resizeOption != "WTableResizeLast" && head1.getAttribute("justify") != "none" && totalWidth >= (divWidth - 20) ) { //20 should be scrollar width
            widths[c] = widths[c] - ( 20 / cellCount ); //20 should be scrollar width
         }

         widths[c] = Math.max(getColumnMinWidth(head1), (!resetTable && !init) ? head1.width : widths[c]);

         head2.width = head1.width = widths[c];
         cellSum = parseInt(cellSum) + parseInt(head1.width);
      }

   } else {
      //set fixed column widths
      for (var c = 0; c < cellCount; c++) {
         var head1 = headBody1.rows[0].cells[c];
         var head2 = headBody2.rows[0].cells[c];
         var body2 = headBody2.nextSibling;

         var rowCount = body2.rows.length;
         //set fixed column widths
         for (var r = 0; r < rowCount; r++) {
            var cell        = body2.rows[r].cells[c];
            var cellStyle   = document.defaultView.getComputedStyle(cell, "");
            var cellPadding = parseInt(cellStyle.getPropertyValue("padding"));
            var shrunk = false;

            if ( c == cellCount-1 ) {
               shrunk = true;
               cell.width  = '100%';
               head2.width = head1.width;
            } else {
               cell.width  = head1.width - (2 * cellPadding);   //account for left & right cell padding
               head2.width = head1.width;
            }
         }

         if ( c == cellCount-1 ) {
            head1.width = head2.width;
         }
      }
   }

   //increase header row height, in case column headers contain breakrules
   for (var c = 0; c < cellCount; c++) {
       headBody1.rows[0].cells[c].firstChild.firstChild.firstChild.firstChild.height = headBody1.rows[0].cells[c].clientHeight;
   }
}


//enable/disable title attirbute for a specific column in the given table
//for Opera, title must be moved from the table cell to its first child (span)
function hoverTitle(divID, table, c, width, shrunk) {
   var div = document.getElementById(divID);
   var headBody1 = document.getElementById(div.getAttribute('H1BID'));
   var rowCount = table.rows.length;
   for (var r = 0; r < rowCount; r++) {
      var head1 = headBody1.rows[0].cells[c];
      var cell = table.rows[r].cells[c];
      var title = cell.getAttribute('title');
      if ( width < head1.getAttribute("initWidth") || shrunk ) {
         if ( title == null || title == '' ) {
            title = cell.getAttribute('disabled_title');
            if ( title == null ) {
               title = '';
            }
         }
         if ( WClient.isBrowserOpera() ) {
            cell.firstChild.setAttribute('title', title);
         } else {
            cell.setAttribute('title', title);
         }
      } else {
         if ( title != null && title != '' ) {
            cell.setAttribute('disabled_title', title);
         }
         if ( WClient.isBrowserOpera() ) {
            cell.firstChild.removeAttribute('title');
         } else {
            cell.removeAttribute('title');
         }
      }
   }
}


/** WTable (scrolling)**
 * handles resize of div for Mozilla
 */
function minimizeTable(dataBodyEnc)
{
   try {
      var dataBody = document.getElementById(dataBodyEnc);
      var divID = dataBody.getAttribute('SPID');
      var div = document.getElementById(divID);

      //shrink table down to 4 rows
      var actionBarEnc = dataBody.getAttribute('ABID');
      var actionBar = document.getElementById(actionBarEnc);
      var offset = actionBar ? actionBar.offsetHeight : 0;
      var height = WClient.isBrowserOpera() ? dataBody.clientHeight : dataBody.offsetHeight;
      var rowHeight = height / dataBody.rows.length;
      div.style.height = offset + (rowHeight * 4);

      var headBody1 = document.getElementById(div.getAttribute('H1BID'));
      var headBody2 = document.getElementById(div.getAttribute('H2BID'));

      //@hmc@ - support modern IE
      //if ( WClient.isBrowserInternetExplorer() ) {
      //   headBody2.parentNode.width = '100%';
      //}

      var preset = ( headBody1.rows[0].cells[0].getAttribute("prefWidth") != null );

      if ( !preset ) {
         headBody1.width = headBody2.width/10;
         headBody2.width = headBody2.width/10;
         headBody1.style.tableLayout = 'fixed';
         headBody2.style.tableLayout = 'fixed';
      }

      div.style.width='0px';           //shrink div to content

      var cellCount = headBody2.rows[0].cells.length-1;
      var hdrHeight = headBody2.rows[0].cells[0].clientHeight;
      for (var c = 0; c < cellCount; c++) {
         var head1 = headBody1.rows[0].cells[c];
         var head2 = headBody2.rows[0].cells[c];

         try {
            head1.firstChild.rows[0].lastChild.firstChild.height = '100%';
         } catch (e) {}

         if ( preset ) {
            head1.width = head1.getAttribute("prefWidth");
            head2.width = head1.getAttribute("prefWidth");
            head2.firstChild.width = head1.width;
            head1.style.width =  head1.width;
         } else if ( head1.getAttribute("justify") != "none" && head1.getAttribute("justify") != "shrink" ) {
            var width = (head1.getAttribute("initWidth") == null ? head1.width/100 : head1.getAttribute("initWidth")/100);
            head1.width = ( head1.width == '' ) ? '' : width;
            head2.width = ( head2.width == '' ) ? '' : width;
            head2.firstChild.width = width;
            head1.style.width =  width;
         }

         head1.firstChild.rows[0].lastChild.firstChild.height = hdrHeight;
      }

      if ( !preset ) {
         headBody1.width = '0px';
         headBody2.width = '0px';
         headBody1.width = headBody1.offsetWidth;
      }
   } catch (e) {
   }
}

/** WTable (quick filter)**
 * clears all other quick filter column checkboxes when all is selected
 */
function quickFilterSelectAll(elem)
{
   wclajax_debug("-> quickFilterSelectAll");
   if (elem.checked == true) {
      var divs = elem.parentNode.parentNode.childNodes;
      for (var i=3; i<divs.length; i++) {
         divs[i].firstChild.checked = false;
      }
   }
   quickFilterUpdateCurrentSelection(elem);
   wclajax_debug("<- quickFilterSelectAll");
}

/** WTable (quick filter)**
 * clears the all quick filter checkboxes when a column box is selected
 */
function quickFilterSelectColumn(elem)
{
   var all = elem.parentNode.parentNode.childNodes[2].firstChild;
   if (all.checked == true) {
      all.checked = false;
   }
   quickFilterUpdateCurrentSelection(elem);
}

/** WTable (quick filter)**
 * clears the all quick filter checkboxes when a column box is selected
 */
function quickFilterUpdateCurrentSelection(elem)
{
   var divs = elem.parentNode.parentNode.childNodes;
   var sel = "";
   for (var i=0; i<divs.length-2; i++) {
      var cbf = divs[i+2].firstChild;
      if (cbf && cbf.checked) {
         if (sel.length != 0) {
            sel += '-';
         }
         sel += i;
      }
   }
   elem.parentNode.parentNode.setAttribute("currSelected", sel);
}

/** WTable (quick filter)**
 * generate an onclick event in the text field to submit the quick filter
 */
function quickFilterGenerateOnClick(ahId, inputId)
{
   wclajax_debug("-> quickFilterGenerateOnClick");
   document.body.style.cursor='wait';
   if ( WClient.isBrowserWebKit()
   || ( WClient.isBrowserInternetExplorer() && parseInt(WClient.getBrowserVersion()) >= 10 ) )
   {
      //work around chrome bug by creating generic event and then setting keyCode on it
      var evt = document.createEvent("Events")
      evt.initEvent('keypress', true, true);
      evt.keyCode = 13;
      evt.which = 13;
      document.getElementById(inputId).dispatchEvent(evt);
   } else if ( KeyboardEvent ) {
      var evt = new KeyboardEvent('keypress', {
         bubbles: true,
         cancelable: true,
         keyCode: 13,
         which: 13
      });
      document.getElementById(inputId).dispatchEvent(evt);
   } else {
      var evt = document.createEventObject();
      evt.keyCode=13;
      document.getElementById(inputId).fireEvent('onkeypress', evt);
   }
   wclajax_debug("<- quickFilterGenerateOnClick");
}

/** WTable (quick filter)**
 * onclick action for the pulldown button, shows the settings div and sets the
 * document onclick to close the div
 */
function quickFilterPulldownOnClick(event, ahId, inputId, imgId, imgSrc) {
   if ( event == null ) {
      event = window.event;
   }

   //store params for document.onclick close (quickFilterSettingsHideAndSubmit)
   document.getElementById(imgId).src=imgSrc;
   document.qf_ahId = ahId;
   document.qf_imgId = imgId;
   document.qf_imgSrc = imgSrc;
   document.qf_inputId = inputId;

   var ah = document.getElementById(ahId);
   if ( ah && ah.style.display == 'none') {
      //enable display and define onclick actions
      ah.style.display = 'block';
      ah.onclick = quickFilterSettingsOnClick;
      document._onclick = document.onclick;
      document.onclick = quickFilterSettingsHideAndSubmit;

      //set closingTime timer and set closing timeout here in case user doesn't
      //mouseover the settings div
      var t = quickFilterSetClosingTime(ah);
      if (!WClient.isDeviceMobile()) {
         setTimeout("quickFilterSettingsHide('"+ahId+"', '"+inputId+"', '"+imgId+"', '"+imgSrc+"', "+t+")", 1000);
      }
   } else {
      ah.style.display = 'none';
   }

   //In FF3 after the settings window closed, a click on the settings button
   //would bubble up and launch document.onclick (quickFilterSettingsHideAndSubmit)
   //closing the window before it opened, so we stop the event from bubbling here
   stopEvent(event);
}

/** WTable (quick filter)**
 * onclick action for the settings div, prevents event from ubbling up to document
 * (which will close the div); stores parameters in the document for onclick close
 * action
 */
function quickFilterSettingsOnClick(event) {
   if ( event == null ) {
      event = window.event;
   }

   //Prevent settings popup from closing when clicking on it by preventing
   //event from bubbling up to document's onclick
   if (WClient.isBrowserInternetExplorer()) {
      event.cancelBubble = true;    // IE
   } else if (event.stopPropagation) {
      event.stopPropagation();      // DOM 2
   }
}

/** WTable (quick filter)**
 * onmouseover action for the settings div, keeps div visible and clears
 * closingTime timer
 */
function quickFilterSettingsOnMouseOver(ahId, inputId, imgId, imgSrc) {
   document.getElementById(imgId).src=imgSrc;
   var ah = document.getElementById(ahId);
   if ( ah ) {
      ah.style.display = 'block';
      quickFilterClearClosingTime(ah);
   }
}

/** WTable (quick filter)**
 * onmouseout action for the settings div, sets closingTime timer and sets timeout
 * to close div (quickFilterSettingsHide)
 */
function quickFilterSettingsOnMouseOut(ahId, inputId, imgId, imgSrc) {
   var ah = document.getElementById(ahId);
   if ( ah && ah.style.display == 'block' ) {
      var t = quickFilterSetClosingTime(ah);
      if (!WClient.isDeviceMobile()) {
          setTimeout("quickFilterSettingsHide('"+ahId+"', '"+inputId+"', '"+imgId+"', '"+imgSrc+"', "+t+")", 1000);
      }
   }
}

/** WTable (quick filter)**
 * hides settings div and submits filter if closingTime timer is still set to
 * the given timer value.  Timer value is updated while user moves mouse around
 * div so this assures the hide is only called once and occurs after the timeout
 * value.
 */
function quickFilterSettingsHide(ahId, inputId, imgId, imgSrc, time) {
   wclajax_debug("-> quickFilterSettingsHide");
   var ah = document.getElementById(ahId);
   if ( ah ) {
      //abort if closingTime doesn't equal given time
      var closingTime = quickFilterGetClosingTime(ah);
      if ( !closingTime || closingTime != time ) {
         return;
      }

      quickFilterSettingsHideAndSubmit(ahId, inputId, imgId, imgSrc);
   }
   wclajax_debug("<- quickFilterSettingsHide");
}

/** WTable (quick filter)**
 * hides settings div and submits the filter if the filter value has been set
 * and the filter settings have changed; also resets document.onclick to its
 * pre-settings div value
 */
function quickFilterSettingsHideAndSubmit(ahId, inputId, imgId, imgSrc) {
   wclajax_debug("-> quickFilterSettingsHideAndSubmit");
   var clickedOnInput = false;

   //typeof ahId == 'object' implies this method was called by document.onclick
   if ( typeof ahId == 'object' ) {
      //if user clicked on the input field, don't hide/submit
      var event = ahId;
      ahId = document.qf_ahId;
      imgId = document.qf_imgId;
      imgSrc = document.qf_imgSrc;
      inputId = document.qf_inputId;

      //we will abort if user clicked on the quick filter input field
      //var target = (window.event) ? event.srcElement : event.target;
      //if ( target.getAttribute('id') == inputId ) {
      //   clickedOnInput = true;
      //}
   }

   var ah = document.getElementById(ahId);
   if ( ah ) {
      //hide the div and update the pulldown icon
      ah.style.display = 'none';
      document.getElementById(imgId).src=imgSrc;

      //reset document.onclick action
      if ( typeof document._onclick == 'function' ) {
         document.onclick = document._onclick;
         document._onclick = null;
      }

      //abort if user clicked on the quick filter input field
      if ( clickedOnInput ) {
         quickFilterClearClosingTime( document.getElementById(ahId) );
         return;
      }

      //abort if Quick Filter pattern is undefined
      var filter = document.getElementById(inputId).getAttribute('filter');
      if ( !filter || filter == '' ) {
         return;
      }

      //generate enter keypress event on input field if column settings change
      var initSelected = ah.getAttribute("initSelected");
      var currSelected = ah.getAttribute("currSelected");
      if ( currSelected != null && initSelected != currSelected ) {
         var submitted = ah.getAttribute('submitted');
         if ( !submitted ) {
            ah.setAttribute('submitted', 'true');
            quickFilterGenerateOnClick(ahId, inputId);
         }
      }
   }
   wclajax_debug("<- quickFilterSettingsHideAndSubmit");
}


/** WTable (quick filter)**
 * sets closingTime timer, used by closing timeout to detect if settings div
 * should remain open
 */
function quickFilterSetClosingTime(ah) {
   var d = new Date();
   var t = d.getTime()
   ah.setAttribute('closingTime', t);
   return t;
}


/** WTable (quick filter)**
 * sets closingTime timer, used by closing timeout to detect if settings div
 * should remain open
 */
function quickFilterClearClosingTime(ah) {
   ah.setAttribute('closingTime', -1);
}


/** WTable (quick filter)**
 * returns closingTime timer
 */
function quickFilterGetClosingTime(ah) {
   return ah.getAttribute('closingTime');
}

/** WTable (quick filter)**
 * onclick action for the clear button, clears the filter input and submits the
 * quick filter
 */
function quickFilterClearOnClick(event, ahId, inputId) {
   if ( event == null ) {
      event = window.event;
   }

   var input = document.getElementById(inputId);
   var ah = document.getElementById(ahId);

   //if init filter was unset, just reset the value
   //otherwise clear and submit filter
   var filterSet = input.getAttribute("filterSet");
   if ( filterSet == 'false' ) {
      input.value = input.getAttribute("initValue");
   } else {
      input.value = '';

      var submitted = ah.getAttribute('submitted');
      if ( !submitted ) {
         ah.setAttribute('submitted', 'true');
         quickFilterGenerateOnClick(ahId, inputId);
      }
   }
}

function ecdButtonUpDown(elem, isUp) {
  if (elem.ariaLabelHandler) {
      clearTimeout(elem.ariaLabelHandler);
  }
  if (!elem.getAttribute('bak-aria-label')) {
      elem.setAttribute('bak-aria-label', elem.getAttribute('aria-label'));
  }
  elem.setAttribute('aria-label', elem.getAttribute('wcl-column-name')+' moved '+(isUp ? 'up' : 'down')+'.');
  if (isUp) {
      ecdButtonUp();
  } else {
      ecdButtonDown();
  }
  elem.focus();
  elem.ariaLabelHandler = setTimeout(function() {
      elem.setAttribute('aria-label', elem.getAttribute('bak-aria-label'));
      delete elem.ariaLabelHandler;
  }, 200);
  return false;
}

/** WTable (configure columns)**
 * reorders rows in the Configure Columns dialog
 * CITOrderNode - hidden input node that contains the order value
 * isAjaxEnabled - true is ajax-enabled
 * isAltRowEnabled - true if alt row highlighting used
 * isUp - true if moving targetNode up
 * previousSibling - targetNode's previousSibling
 * targetNode - row to move
 * nextSibling - targetNode's nextSibling
 */
function ecdUpdateList(CITOrderNode, isAjaxEnabled, isAltRowEnabled, isUp, previousSibling, targetNode, nextSibling, nextNextSibling) {
    var checked, div, values;
    if (isAjaxEnabled) {
        checked = targetNode.cells[1].firstChild.firstChild.firstChild.firstChild.checked;
    } else {
        checked = targetNode.cells[1].firstChild.firstChild.checked;
    }
    div = targetNode.parentNode.parentNode.parentNode;
    if(isUp) {
        targetNode.parentNode.insertBefore(targetNode, previousSibling);
    } else {
        if (nextNextSibling) {
            targetNode.parentNode.insertBefore(targetNode, nextNextSibling);
        } else {
            targetNode.parentNode.appendChild(targetNode);
        }
    }

    if (isAjaxEnabled) {
        targetNode.cells[1].firstChild.firstChild.firstChild.firstChild.checked = checked;
    } else {
        targetNode.cells[1].firstChild.firstChild.checked = checked;
    }
    div.scrollTop = targetNode.offsetTop;
    values = '';
    for (r=0; r < targetNode.parentNode.rows.length; r++) {
        if (isAjaxEnabled) {
            values += targetNode.parentNode.rows[r].cells[1].firstChild.firstChild.firstChild.firstChild.value + ',';
        } else {
            values += targetNode.parentNode.rows[r].cells[1].firstChild.firstChild.value + ',';
        }
    }
    if ( isAltRowEnabled ) {
        ecdUpdateRowClass(targetNode);
        ecdUpdateRowClass(isUp ? previousSibling : nextSibling);
    }

    CITOrderNode.value = values;
}
