function getVarById(id) {
  e = document.getElementById(id);
  if (e) {
    return e.value; 
  }
  return false;
}

function setVarById(id,value,immediate) {
  e = document.getElementById(id);
  if (e) {
    e.value = value;
    if (immediate) {
      document.millstone.submit();
    }
    return false; 
  }
  return true;
}

function listContainsInt(list,number) {
  a = list.split(",");

  for (i=0;i<a.length;i++) {
    if (a[i] == number) return true;
  }
  
  return false;
}

function listAddInt(list,number) {

  if (listContainsInt(list,number)) 
    return list;
    
  if (list == "") return number;
  else return list + "," + number;
}

function listRemoveInt(list,number) {

  retval = "";
  a = list.split(',');

  for (i=0;i<a.length;i++) {
    if (a[i] != number) {
      if (i == 0) retval += a[i];
      else retval += "," + a[i];
    }
  }
  
  return retval;
}

// ==========================================================================
// CSS class name handling functions
// ==========================================================================

function toUnselectedClassName(currentName) {
	if (currentName) {
		i = currentName.lastIndexOf("-selected");
		if (i>=0) {
			return currentName.substring(0,i);
		}
		i = currentName.lastIndexOf("-highlighted");
		if (i>=0) {
			return currentName.substring(0,i);
		}
	}
	return currentName;
}

function toSelectedClassName(currentName) {
	if (currentName) {
		i = currentName.lastIndexOf("-selected");
		if (i>=0) {
			return currentName;
		}		
	}
	return currentName+"-selected";
}

function toHighlightClassName(currentName) {
	if (currentName) {
		i = currentName.lastIndexOf("-highlighted");
		if (i>=0) {
			return currentName;
		}		
	}
	return currentName+"-highlighted";
}

// ==========================================================================
// Element handling functions
// ==========================================================================

function disableElement(element) {
        if (element != null) {
            element.disabled = true;
        }
}

function enableElement(element) {
        if (element != null) {
			element.disabled = false;        
        }
}

function hideElement(element) {
        if (element != null) {
            element.style.display="none";
        }
}

function showElement(element) {
        if (element != null) {
			element.style.display="";        
        }
}

function isElementVisible(element) {
        if (element != null) {
			return (element.style.display != "none");        
        }
        return false;
}

function toggleElement(element) {
        if (element != null) {
        	if (isElementVisible(element)) {
				hideElement(element);
			} else {
				showElement(element);
			}
        }
}

function hideElementById(id) {
    	hideElement(document.getElementById(id));
}

function showElementById(id) {
    	showElement(document.getElementById(id));
}

function toggleElementById(id) {
    	toggleElement(document.getElementById(id));
}

// --------------------------------------------------------------------------
// Input controlling table row selection changes state.
//
// Params:
// inputid      Id of the INPUT containing the selection state
// key          Key identifying item connected to this table row
// unselected   Class of the unselected row
// selected     Class of the selected row
// immediate    "true" iff the table is in immediate mode
// mode         "single" or "multi"
// --------------------------------------------------------------------------
function tableSelClick(inputid,key,immediate,mode) {
  prev = value = getVarById(inputid);
  // Change selection value
  if (mode == "multi") {
    if (listContainsInt(value,key)) 
      value = listRemoveInt(value,key);
    else 
      value = listAddInt(value,key);
  } else 
    value = key;
  setVarById(inputid,value);
  // In single select mode change remove old selections
  if (mode == "single") {
    keys = prev.split(",");
    for (i=0;i<keys.length;i++) {
      tr = document.getElementById("" + inputid + "_" + keys[i]);
      if (tr) 
        tr.className = toUnselectedClassName(tr.className);
    }
  }
  // Update visual state of the current item
  tr = document.getElementById("" + inputid + "_" + key);
  if (tr) {
    if (listContainsInt(value,key))
      tr.className = toSelectedClassName(tr.className); 
    else 
      tr.className = toUnselectedClassName(tr.className);
  }
  // Submit if in immediate mode  
  if (immediate) 
    document.millstone.submit();
}

// --------------------------------------------------------------------------
// Input controlling tree item selection changes state.
//
// Params:
// inputid      Id of the INPUT containing the selection state
// key          Key identifying item
// immediate    "true" iff the table is in immediate mode
// mode         "single" or "multi"
// --------------------------------------------------------------------------

function treeSelClick(inputid,key,immediate,mode) {
  prev = value = getVarById(inputid);
  // Change selection value
  if (mode == "multi") {
    if (listContainsInt(value,key)) 
      value = listRemoveInt(value,key);
    else 
      value = listAddInt(value,key);
  } else 
    value = key;
  setVarById(inputid,value);
  // In single select mode change remove old selections
  if (mode == "single") {
    keys = prev.split(",");
    for (i=0;i<keys.length;i++) {
      itemElement = document.getElementById("" + inputid + "_" + keys[i]);
      if (itemElement)
        itemElement.className = toUnselectedClassName(itemElement.className);
    }
  }
  // Update visual state of the current item
  itemElement = document.getElementById("" + inputid + "_" + key);
  if (itemElement) {
    if (listContainsInt(value,key))
      itemElement.className = toSelectedClassName(itemElement.className);
    else 
      itemElement.className = toUnselectedClassName(itemElement.className);
  }
  // Submit if in immediate mode  
  if (immediate) 
    document.millstone.submit();
}

// --------------------------------------------------------------------------
// Input controlling tree item expansion/collapsion changes state.
//
// Params:
// expandid     Id of the INPUT containing the expansion state
// collapseid   Id of the INPUT containing the collapsion state
// key          Key identifying item
// immediate    "true" iff the table is in immediate mode
// --------------------------------------------------------------------------

function treeExpClick(expandid,collapseid,key,immediate) {

  var expanded = getVarById(expandid);
  var collapsed = getVarById(collapseid);

  var expandedImg = document.getElementById(collapseid+"_IMG");
  var collapsedImg = document.getElementById(expandid+"_IMG");
  var img = document.getElementById("img" + expandid + "_" + key);  

  var childElement = document.getElementById("" + expandid + "_" + key);

  isCollapsed = (!childElement) || (!isElementVisible(childElement));

  if (isCollapsed) {
    // Remove from collapsion list
    if (listContainsInt(collapsed,key)) {
      collapsed = listRemoveInt(collapsed,key);
    }
    setVarById(collapseid,collapsed);
    // Add to expanded list
    if (!listContainsInt(expanded,key)) {
       expanded = listAddInt(expanded,key);
    }  
    setVarById(expandid,expanded);
  // Collapse the item
  } else {
    // Remove from expansion list
    if (listContainsInt(expanded,key)) {
      expanded = listRemoveInt(expanded,key);
    }
    setVarById(expandid,expanded);

    // Add to collapsion list
    if (!listContainsInt(collapsed,key)) {
       collapsed = listAddInt(collapsed,key);
    }  
    setVarById(collapseid,collapsed);
  }
// Update visual state of the current item  
  if (childElement && img) {
    if (listContainsInt(expanded,key)) {
      showElement(childElement);
      if (expandedImg) {
        img.src = expandedImg.src;      
      }
    } else {
      hideElement(childElement);
      if (collapsedImg) {
        img.src = collapsedImg.src;      
      }
    }
  } else {
      // Fetch the missing items
      document.millstone.submit();
  }
}