function com_genesisuk_collapsibleList(strContainerName, fMutex, fTitleExpands, xEventCallback, xExpanderClickCallback)
{
  this.strListContainerName = strContainerName;
  this.fMutexMode = fMutex;
  this.fTitleExpands = fTitleExpands;
  this.xEventCallback = xEventCallback;
  this.xExpanderClickCallback = xExpanderClickCallback;
  this._lastSelectedDIV = null;
  this.aSubItems = [];
  
  this.SetActiveListContainerName = function(strName) {
    this.strListContainerName = strName;
  };
  
  this.SetMutexMode = function(fEnabled) {
    this.fMutexMode = fEnabled;
  };

  this.SetTitleExpandMode = function(fEnabled) {
    this.fTitleExpands = fEnabled;
  };

  this.SetEventCallbackFunction = function(func) {
    this.xEventCallback = func;
  };

  this.SetExpanderClickCallback = function(func) {
    this.xExpanderClickCallback = func;
  };

  this.ClearListContainer = function() {
    ClearContainerByName(this.strListContainerName);
  }

  this.AddListItem = function(strTitle, strURL, fJSURL) {
    var cont = $('#' + this.strListContainerName).get(0);
    if (!cont)
      return null;
    var newItemDiv = document.createElement("div");

    //Create the expander
    var expander    = document.createElement("span");
    var expanderImg = document.createElement("img");
    expander._class    = this;
    expanderImg._class = this;
    expander.setAttribute("class", "listItem_expander");
    expander.className = "listItem_expander";
    expander.style.cursor = "default";
    expander.onclick = this._expander_toggleItems;
    expanderImg.setAttribute("src", "/i/plus.gif");
    expander.appendChild(expanderImg);
  
    //Create the item title
    var titleDiv  = document.createElement("div");
    var titleLink = document.createElement("a");
    titleDiv._class  = this;
    titleLink._class = this;
    titleDiv.setAttribute("class", "listItem_title");
    titleDiv.className = "listItem_title";
    titleDiv.appendChild(expander);
    if (fJSURL)
    {
      if (fTitleExpands)
      {
        titleLink.onclick  = function() {
          var func = this._class._title_expandItems;
          func.apply(this);
          eval(strURL);
        };
      }
      else
        titleLink.onclick = new Function(strURL);
      titleLink.setAttribute("href", "javascript:;");
    }
    else
    {
      if (fTitleExpands)
        titleLink.onclick = this._title_expandItems;
      titleLink.setAttribute("href", strURL);
    }
    titleLink.appendChild(document.createTextNode(strTitle));
    titleDiv.appendChild(titleLink);
  
    //Create the subitem container
    var itemsDiv = document.createElement("div");
    itemsDiv._class = this;
    itemsDiv.setAttribute("name",  "listItem_subItemsList");
    itemsDiv.setAttribute("id",    "listItem_subItemsList");
    itemsDiv.setAttribute("class", "listItem_subItemsList");
    itemsDiv.className = "listItem_subItemsList";
    itemsDiv.style.display = "none";
    this._setVisibleFlag($(itemsDiv), false);
    
    //Add the elements to the new item
    newItemDiv.appendChild(titleDiv);
    newItemDiv.appendChild(itemsDiv);
    
    //Add the new item to the list
    cont.appendChild(newItemDiv);
    
    if (this.xEventCallback)
      this.xEventCallback("ADD_ITEM", newItemDiv);
    
    return newItemDiv;
  };

  this.AddSubItem = function(itemNode, uniqueID, itemName, itemURL, fJSURL) {
    var cont = $('#' + this.strListContainerName).get(0);
    if (!cont || !itemNode)
      return;
    var itemsCont = $(itemNode).children('#listItem_subItemsList').get(0);
    if (!itemsCont)
      return;
    var newLink = document.createElement("a");
    newLink._class = this;
    if (fJSURL)
    {
      newLink.onclick = new Function(itemURL);
      newLink.setAttribute("href", "javascript:;");
    }
    else
      newLink.setAttribute("href", itemURL);
    newLink.appendChild(document.createTextNode(itemName));
    var div = document.createElement("div");
    div.appendChild(newLink);
    itemsCont.appendChild(div);
  
    //Add the DIV to the internal list
    var objItemRef = new Object();
    objItemRef._div    = div;
    objItemRef._uid    = uniqueID;
    objItemRef._parent = itemNode;
    this.aSubItems.push(objItemRef);
    
    if (this.xEventCallback)
      this.xEventCallback("ADD_SUBITEM", itemName);
  };

  this.AddSubItemByName = function(uniqueID, strListItemName, strSubItemTitle, strSubItemURL, fJSURL) {
    var item = GetItemByName(this.strListItemName);
    if (item)
      this.AddSubItem(item, uniqueID, strSubItemTitle, strSubItemURL, fJSURL);
  };

  this.ExpandItem = function(itemNode) {
    if (!itemNode)
      return;
    var itemsCont = $(itemNode).children('#listItem_subItemsList');
    if (!itemsCont)
      return;
    if (!this._isVisible(itemsCont))
    {
      this._setVisibleFlag(itemsCont, true);
      itemsCont.show('fast');
      var expanderImg = $(itemNode.firstChild.firstChild.firstChild);
      if (expanderImg)
        expanderImg.attr("src", "/i/minus.gif");
      if (this.xEventCallback)
        this.xEventCallback("EXPAND", itemNode);
      if (this.fMutexMode)
        this._collapseOtherItems(itemNode);
    }
  };

  this.ExpandItemByName = function(strItemName) {
    var item = GetItemByName(strItemName);
    if (item)
      this.ExpandItem(item);
  };

  this.CollapseItem = function(itemNode) {
    if (!itemNode)
      return;
    var itemsCont = $(itemNode).children('#listItem_subItemsList');
    if (!itemsCont)
      return;
    if (this._isVisible(itemsCont))
    {
      this._setVisibleFlag(itemsCont, false);
      itemsCont.hide('fast');
      var expanderImg = $(itemNode.firstChild.firstChild.firstChild);
      if (expanderImg)
        expanderImg.attr("src", "/i/plus.gif");
      if (this.xEventCallback)
        this.xEventCallback("COLLAPSE", itemNode);
    }
  };

  this.CollapseItemByName = function(strItemName) {
    var item = GetItemByName(strItemName);
    if (item)
      this.CollapseItem(item);
  };

  this.GetItemByName = function(strName) {
    var cont = $('#' + this.strListContainerName).get(0);
    if (!cont)
      return null;
    for (var i = 0; i < cont.childNodes.length; i++)
    {
      var anchorTag = cont.childNodes[i].firstChild.childNodes[1];
      for (var j = 0; j < anchorTag.childNodes.length; j++)
      {
        if ((anchorTag.childNodes[j].nodeType == 3) && (anchorTag.childNodes[j].nodeValue.toUpperCase() == strName.toUpperCase()))
          return cont.childNodes[i];
      }
    }
    return null;
  };
  
  this.SelectItemByUID = function(strUID, fExpandParent) {
    var div        = null;
    var parentNode = null;
    for (var i = 0; i < this.aSubItems.length; i++)
    {
      if (this.aSubItems[i]._uid.toUpperCase() == strUID.toUpperCase())
      {
        div        = this.aSubItems[i]._div;
        parentNode = this.aSubItems[i]._parent;
        break;
      }
    }
    if (div)
    {
      if (this._lastSelectedDIV)
        this._lastSelectedDIV.className = "";
      div.className = "selected";
      this._lastSelectedDIV = div;
      if (fExpandParent)
        this.ExpandItem(parentNode);
      return true;
    }
    else
      return false;
  };
  
  this.DeselectAllItems = function() {
    for (var i = 0; i < this.aSubItems.length; i++)
      this.aSubItems[i]._div.className = "";
  };

  this.GetItemStates = function() {
    var cont = $('#' + this.strListContainerName).get(0);
    if (!cont)
      return null;
    var itemStates = "";
    for (var i = 0; i < cont.childNodes.length; i++)
      itemStates += this._isVisible($(cont.childNodes[i].childNodes[1])) ? "1" : "0";
    return itemStates;
  };

  this.SetItemStates = function(itemStates) {
    var cont = $('#' + this.strListContainerName).get(0);
    if (!cont)
      return;
    if (itemStates.length != cont.childNodes.length)
      return;
    for (var i = 0; i < itemStates.length; i++)
    {
      if (itemStates.substring(i, i + 1) == "1")
        this.ExpandItem(cont.childNodes[i]);
      else
        this.CollapseItem(cont.childNodes[i]);
    }
  };

  this._expander_toggleItems = function() {
    var itemsDiv = $(this.parentNode.parentNode).children('#listItem_subItemsList');
    if (!itemsDiv)
      return;
    var fHidden = !this._class._isVisible(itemsDiv);
    this._class._setVisibleFlag(itemsDiv, fHidden);
    if (fHidden)
      itemsDiv.show('fast');
    else
      itemsDiv.hide('fast');
    var expanderImg = this.firstChild;
    if (expanderImg)
      expanderImg.setAttribute("src", fHidden ?  "/i/minus.gif" : "/i/plus.gif");
    if (this._class.xExpanderClickCallback)
      this._class.xExpanderClickCallback(fHidden ?  "EXPAND" : "COLLAPSE", itemsDiv.get(0).parentNode);
    if (this._class.xEventCallback)
      this._class.xEventCallback(fHidden ?  "EXPAND" : "COLLAPSE", itemsDiv.get(0).parentNode);
    if (this._class.fMutexMode)
      this._class._collapseOtherItems(itemsDiv.get(0).parentNode);
  };

  this._title_expandItems = function() {
    var itemsDiv = $(this.parentNode.parentNode).children('#listItem_subItemsList');
    if (!itemsDiv)
      return;
    this._class._setVisibleFlag(itemsDiv, true);
    itemsDiv.show('fast');
    var expanderImg = this.parentNode.firstChild.firstChild;
    if (expanderImg)
      expanderImg.setAttribute("src", "/i/minus.gif");
    if (this._class.xExpanderClickCallback)
      this._class.xExpanderClickCallback("COLLAPSE", itemsDiv.get(0).parentNode);
    if (this._class.xEventCallback)
      this._class.xEventCallback("COLLAPSE", itemsDiv.get(0).parentNode);
    if (this._class.fMutexMode)
      this._class._collapseOtherItems(itemsDiv.get(0).parentNode);
  };

  this._collapseOtherItems = function(expandedItem) {
    var cont = $('#' + this.strListContainerName).get(0);
    if (!cont)
      return;
    for (var i = 0; i < cont.childNodes.length; i++)
    {
      if (cont.childNodes[i] != expandedItem)
      {
        var subItemsDiv = $(cont.childNodes[i].childNodes[1]);
        var expanderImg = $(cont.childNodes[i].firstChild.firstChild.firstChild);
        if (subItemsDiv && expanderImg)
        {
          if (this._isVisible(subItemsDiv))
          {
            this._setVisibleFlag(subItemsDiv, false);
            subItemsDiv.fadeOut('fast');
            expanderImg.attr("src", "/i/plus.gif");
            if (this.xEventCallback)
              this.xEventCallback("COLLAPSE", cont.childNodes[i]);
          }
        }
      }
    }
  };
  
  this._setVisibleFlag = function(jqEl, fVisible) {
    jqEl.data('visible', fVisible);
  };
  
  this._isVisible = function(jqEl) {
    return jqEl.data('visible');
  };
}

