// Copyright (c) 2000-2007 by Brix Networks, Inc.  All rights reserved.
// Unauthorized reproduction, modification, distribution, transmission,
// republication, display or performance is strictly prohibited.
//
// $Id: guiTools.js,v 1.33.10.1 2007/01/10 20:00:11 build Exp $

var navTimers = new Array();

// A browser reference object.
function BrowserObj() {

  var ua, s, i;

  this.isIE    = false;
  this.isNS    = false;
  this.version = null;

  ua = navigator.userAgent;

  s = "MSIE";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isIE = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  s = "Netscape6/";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  // Treat any other "Gecko" browser as NS 6.1.

  s = "Gecko";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = 6.1;
    return;
  }
}

var browser = new BrowserObj();

function addSelList(newItemValue, newItemName, selListOptions) {

  // This function also accepts 2 additional optional values:
  // allowDupes (true|false) and addItemLimit (number).

  var allowDupes = true;
  if (arguments.length > 3) {
      allowDupes = arguments[3];
  }

  // The fifth argument is a limit on the number of items which
  // can be added to the list.
  // Default value of 0 means no limits.
  var addItemLimit = 0;
  if (arguments.length > 4) {
      addItemLimit = arguments[4];
  }

  // See if the item is already in the list
  if (!allowDupes) {
    for (var i = 0; i < selListOptions.length; i++) {
        if (selListOptions[i].value == newItemValue) {
	    return true;
        }
    }
  }

  var packed = false;
  var i = 0;
  if ((newItemValue.length == 0) || (newItemValue == "null")) {
    return false;
  } else if (addItemLimit > 0 && selListOptions.length >= addItemLimit) {
    var limit_reached = 'This list has a limit of ' + addItemLimit + ' items.\n';
    limit_reached += 'To add a new item, remove one of the existing items first.';

    alert(limit_reached);
    return false;
  }

  var newSelOption = new Option(newItemName, newItemValue);
  if ((selListOptions.length == 1) && (selListOptions[0].value == "null")) {
    selListOptions[0] = newSelOption;
  } else {
    selListOptions[selListOptions.length] = newSelOption;
  }

  return true;
}

function delSelList(selectObject, all) {
  var optionList = selectObject.options;

  if (all) {
      optionList.length = 0;
  } else if ((optionList.length == 0) || 
      ((optionList.length == 1) &&
       (optionList[0].value == "null"))) {
    return;
  } else {
    var tempArray = new Array();
    for (var i = 0; i < optionList.length; i++) {
      if (!optionList[i].selected) {
          tempArray[tempArray.length] =
	      new Option(optionList[i].text, optionList[i].value);
      }
    }
    optionList.length = 0;
    for (var i = 0; i < tempArray.length; i++) {
      optionList[i] = tempArray[i];
    }
    return;
  }
}

function optSort(a,b) {
  var aTxt = a.text;
  var bTxt = b.text;

  if (aTxt < bTxt) {
    return -1; 
  }
  return 1;
}

function sortSelLists() {
  var tempList = new Array();
  for (var i = 0; i < arguments.length; i++) {
    var mySel       = arguments[i];
    var myOpts      = mySel.options;
    tempList.length = 0;
    for (var j = 0; j < myOpts.length; j++) {
      tempList[j] = myOpts[j];
    }
    tempList.sort(optSort);
    delSelList(mySel, 1);
    for (var j = 0; j < tempList.length; j++) {
      myOpts[j] = tempList[j];
    }
  }
}

function prepSelLists() {
  for (var i=0; i < arguments.length; i++) {
    for (var j = 0; j < arguments[i].options.length; j++) {
      arguments[i].options[j].selected = true;
    }
  }
}

function combineSelLists(targetSel) {
  for (var i = 1; i < arguments.length; i++) {
    if (arguments[i].options.length == 0)
      continue;
    prepSelLists(arguments[i]);
    moveOption(arguments[i], targetSel);
  }
  for (var i = 0; i < targetSel.options.length; i++) {
      targetSel.options[i].selected = false;
  }
}

function find_and_pack_selects(myForm) {
  for (var i=0; i < myForm.elements.length; i++) {
      if (myForm.elements[i].type == 'select-multiple' && ! myForm.elements[i].disabled) {
          prepSelLists(myForm.elements[i]);
      }
  }
}

function radioFollow(radioObject, radioValue) {
  for (var i=0; i<radioObject.length; i++) {
    if (radioObject[i].value == radioValue) {
      radioObject[i].checked = true;
    } else {
      radioObject[i].checked = false;
    }
  }
}

// moveOption
// Given source and target select object lists, moveOption identifies the 
// selected options in the source list and transfers them to the target
// list. If no items are selected, the function exits quietly.
// The allowDupes flag determines whether or not the function will push
// an option onto a list that already contains that option's value.
function moveOption (sourceSelect, targetSelect) {
  var sourceOptions   = sourceSelect.options;
  var targetOptions   = targetSelect.options
  var tempTargetList  = new Array();
  var selectedOptions = new Array();
  var remainOptions   = new Array();
  var allowDupes      = true;
  var targetValues    = new Array();

  if (arguments.length == 3) {
      allowDupes = arguments[2];
  }
  if (!allowDupes) {
    for (var i = 0; i < targetOptions.length; i++) {
        targetValues[targetOptions[i].value] = true;
    }
  }
  

  if (sourceSelect.selectedIndex == -1) {
    return;
  } else {
    for (var i = 0; i < sourceOptions.length; i++) {
      if ((sourceOptions[i].selected) &&
          (sourceOptions[i].value != 'null'))
      {
        selectedOptions[selectedOptions.length] =
          new Option(sourceOptions[i].text, sourceOptions[i].value, true, true);
      }
      else if ((!sourceOptions[i].selected) &&
               (sourceOptions[i].value != 'null'))
      {
        remainOptions[remainOptions.length] =
          new Option(sourceOptions[i].text, sourceOptions[i].value);
      }
    }
  }

  if (selectedOptions.length != 0) {
    var targetOffset = targetOptions.length;
    if ((targetOptions.length == 1) && (targetOptions[0].value == "null")) {
      targetOffset = 0;
    }
    for (var i = 0; i < selectedOptions.length; i++) {
      if(!targetValues[selectedOptions[i].value]) {
        targetOptions[targetOffset+i] = selectedOptions[i];
      }
    }
    sourceOptions.length = 0;
    for (var i = 0; i < remainOptions.length; i++) {
      sourceOptions[i] = remainOptions[i];
    }

    // This is a throwaway assignment. NS 4.x will crash unless delSelList is
    // actually assigned to a variable.
    var foo = delSelList(sourceSelect);
  }

  return;
}

// copyOption
// Given source and target select object lists, moveOption identifies the 
// selected options in the source list and copies them to the target
// list. If no items are selected, the function exits quietly.
// The allowDupes flag determines whether or not the function will push
// an option onto a list that already contains that option's value.
function copyOption( sourceSelect, targetSelect, allowDupes ) {
  var sourceOptions   = sourceSelect.options;
  var targetOptions   = targetSelect.options
  var selectedOptions = new Array();
  var targetValues    = new Array();

  if (sourceSelect.selectedIndex == -1) {
    return;
  } else {
    if (!allowDupes) {
      for (var i = 0; i < targetOptions.length; i++) {
        targetValues[targetOptions[i].value] = true;
      }
    }

    for (var i = 0; i < sourceOptions.length; i++) {
      if ((sourceOptions[i].selected) &&
          (sourceOptions[i].value != 'null'))
      {
        if (!targetValues[sourceOptions[i].value]) {
          selectedOptions[selectedOptions.length] =
            new Option(sourceOptions[i].text, sourceOptions[i].value);
        }
	sourceOptions[i].selected = false;
      }
    }
  }

  if (selectedOptions.length != 0) {
    var targetOffset = targetOptions.length;
    if ((targetOptions.length == 1) && (targetOptions[0].value == "null")) {
      targetOffset = 0;
    }
    for (var i = 0; i < selectedOptions.length; i++) {
      targetOptions[targetOffset+i] = selectedOptions[i];
    }
  }
}

// reorderOption
// Hand it an option list and a direction, and this function will move the
// currently selected option one slot in the specified direction, where 'up'
// indiciates a move towards the beginning of the list and 'down' indicates
// a move towrds the end.
function reorderOption(sourceSelect, direction) {
  if ((direction != 'up') && (direction != 'down')) {
    return;
  }

  var optionList = sourceSelect.options;

  if ((optionList.length == 0) ||
      ((sourceSelect.selectedIndex == 0) && (direction == 'up')) ||
      ((sourceSelect.selectedIndex == (optionList.length - 1)) &&
       (direction == 'down')))
  {
    return;
  }

  var index = sourceSelect.selectedIndex;

  if (index != -1) {
    if (direction == 'down') {
      var tempOption = new Option(optionList[index+1].text, optionList[index+1].value);
      optionList[index+1] = new Option(optionList[index].text, optionList[index].value, true, true);
      optionList[index]   = tempOption;
      sourceSelect.selectedIndex = index + 1;
    } else {
      var tempOption = new Option(optionList[index-1].text, optionList[index-1].value);
      optionList[index-1] = new Option(optionList[index].text, optionList[index].value, true, true);
      optionList[index]   = tempOption;
      sourceSelect.selectedIndex = index - 1;
    }
  } else {
    return;
  }

  return;
}

// setChecks
// Given a form object and a name prefix, this function will scan the form
// and attempt to set the 'checked' value of elements whose names bear the
// name prefix to 'true'. An optional third argument can be sent; this
// consists of a _hash(!)_ list of specific element names that bear the 
// name prefix. In the event that this "true list" list is sent, only
// those items named in the list will be set to 'true'. All other elements
// that bear the name prefix will be set to 'false'.
function setChecks(myForm, namePrefix, trueList) {
    var pattern = new RegExp("^" + namePrefix + ".*$");    

    for (var i = 0; i < myForm.elements.length; i++) {
        if (myForm.elements[i].name.match(pattern)) {
            if (trueList != null && trueList.length > 0) {
	        for (var j = 0; j < trueList.length; j++) {
		    if (myForm.elements[i].name == trueList[j]) {
		        myForm.elements[i].checked = true;
			break;
                    } else {
		        myForm.elements[i].checked = false;
                    }
                }
            } else {
                myForm.elements[i].checked = true;
            }
        }
    }    
}

function findOffSetX(myObj) {
    if (!myObj) return 0;
    var offset = 0;
    offset += myObj.offsetLeft + findOffSetX(myObj.offsetParent);
    return offset;
}

function findOffSetY(myObj) {
    if (!myObj) return 0;
    var offset = 0;
    offset += myObj.offsetTop + findOffSetY(myObj.offsetParent);
    return offset;
}

function findAnchor(anchorID) {
    for (var i = 0; i < document.anchors.length; i++) {
        if (document.anchors[i].id == anchorID) {
           return document.anchors[i];
        }
    }
    return null;
}

// switchEC
// This function is a helper function for expando-collapso regions. It uses a
// simple RegEx to determine a root style-class name and swaps between two
// suffixes-- "-expanded" and "-collapsed". If the RegEx does not find either
// of these prefixes on the name of the incoming element's style-class, it
// just exits quietly.
function switchEC(myElement) {
    var classInfo = myElement.className.match(/(.*)-expanded$/);
    if (classInfo != null) {
        myElement.className = classInfo[1] + '-collapsed';
    } else {
        classInfo = myElement.className.match(/(.*)-collapsed$/);
	if (classInfo != null) {
	    myElement.className = classInfo[1] + '-expanded';
	}
    }
}

// hoverSwitch
function hoverSwitch(divID, toggle) {
    if (toggle == 1) {
        navTimers[divID] = setTimeout("hoverCheck('" + divID + "');", 500);
    } else {
        for (timeID in navTimers) {
            clearTimeout(navTimers[timeID]);
        }
    }
}

// hoverCheck
function hoverCheck(divID) {
    var myDiv     = document.getElementById(divID);
    var classInfo = myDiv.className.match(/(.*)-collapsed$/);
    if ((navTimers[divID] === undefined) || (navTimers == null)) {
        return;
    }
    if (classInfo != null) {
        switchEC(myDiv);
    }
}

// divSizer
// Part of our workaround for IEs lack of position:fixed support; resizes divs
// to fit the viewable area.
function divSizer() {
    var navDiv  = document.getElementById('navigation');
    var siteDiv = document.getElementById('sitecontent');

    var windowWidth;
    var navDivWidth;

    if (browser.isIE) {
        windowWidth = document.body.clientWidth;
        navDivWidth = navDiv.clientWidth;
        siteDiv.style.width = windowWidth - navDivWidth - 10;
    } else {
        windowWidth = window.innerWidth;
        var navDivStyle = getComputedStyle(navDiv, "");
        navDivWidth = parseFloat(navDivStyle.getPropertyValue("width"));
        siteDiv.style.setProperty("width", ((windowWidth - navDivWidth - 11)+"px"), "");
    }
}

// ShowHelp
// Opens a window to the help system.
function ShowHelp(strUrl) {
  var strHelpOptions = "location=no";
  strHelpOptions += ",toolbar=no";
  strHelpOptions += ",menubar=no";
  strHelpOptions += ",status=yes";
  strHelpOptions += ",scrollbars=yes";
  strHelpOptions += ",resizable=yes";
  strHelpOptions += ",top=0";
  strHelpOptions += ",left=0";
  strHelpOptions += ",width=700";
  strHelpOptions += ",height=400";

  window.open(strUrl, "Help", strHelpOptions);
}

// Popup window for viewing multi-point lists.
// Called from the file upload UI in ComboBox
function showTargetList(URL) {
    var conf = 'width=300,height=400,directories=no,location=no,menubar=no,resizable=yes,scrollbars=yes,status=no,toolbar=no';
    var targetListWindow = window.open(URL, 'viewlist', conf);

    if(targetListWindow) {
	targetListWindow.focus();
    }
}

// Toggle between the basic and advanced upload options.
function toggleUploadOptions(state, param_name, max_list) {
    var more_list = [ 'more_1_', 'more_3_', 'remove_all_button_' ];
    if (! max_list) more_list.push('more_2_');

    var i, more_display, less_display;

    if (state == 'more') {
	more_display = 'inline';
	less_display = 'none';
    } else {
	more_display = 'none';
	less_display = 'inline';
    }

    var element_name, element;

    for (i = 0; i < more_list.length; i++) {
	element_name = more_list[i] + param_name;
	if (element = document.getElementById(element_name)) {
	    element.style.display = more_display;
	}
    }

    element_name = 'less_1_' + param_name;
    if (element = document.getElementById(element_name)) {
	element.style.display = less_display;
    }
}

function clean_whitespace(myEl) {
  var tempVal = myEl.value.match(/^\s*(.+?)\s*$/);

  if (tempVal) 
      myEl.value  = tempVal[1];
}

// IP address validation.
// Makes sure the address is of the 4 quad syntax (non-cidr).
// A defined optional type value of 'subnet' validates the address as a subnet value.
// String must be clean of whitespaces.
function is_ip(address, address_type) {
    var i;
    var ip_match = address.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);

    if (! ip_match || ip_match.length != 5) {
	return false;
    }

    // Remember, the first value of a match is the entire match itself,
    //   followed by the individual matches that we are interested in.
    for (i = 1; i < 5; i++) {
	if (! (ip_match[i] >= 0 && ip_match[i] <= 255)) {
	    return false;
	}
    }

    // Validate a subnet using (log(256 - quad) / log(2)) == <integer value>
    if (address_type == 'subnet') {
	for (i = 1; i < 5; i++) {
	    result = Math.log(256 - ip_match[i]) / Math.log(2);
	    if (result != Math.floor(result)) {
		return false;
	    }
	}
    }

    return true;
}

// Check to see if the address is 0.0.0.0 or loopback.
function is_special_ip(address) {

    if (address.match(/^127\./))
	return true;

    if (address == '0.0.0.0')
	return true;

    return false;

}

// Checks to see if the given single CIDR value is within proper range.
function is_cidr(cidr) {

    if (cidr == 31)
	return false;

    if (cidr >= 0 && cidr <= 32)
	return true;

    return false;

}

