Nesse artigo vou mostrar como criar um TreeView igual ao OutLook 2010.

Layout do Menu
Figura 1. Layout do Menu

Para construir o TreeView vamos utilizar recursividade. Cada item pode ter nenhuns ou muitos filhos, e cada filho também pode ter nenhuns ou muitos filhos.

Abaixo a figura do modelo de classes.

Modelo da Classe
Figura 2. Modelo da Classe

Classe MenuTreeView.

  • Id: Identificador da classe.
  • Recipient: Elemento aonde vai ser construído o TreeView.
  • Items: Nós do TreeView.
  • LastSelectedItem: Último nó selecionado.
  • OnSelectedIndex: Evento quando algum nó é selecionado.

Classe ItemMenuTreeView.

  • Id: Identificador da classe.
  • Text: Texto do nó.
  • Value: Valor do nó.
  • UrlImagem: Imagem do nó.
  • Tooltip: Tooltip do nó
  • IsOpen: Indica se o nó está expandido ou recolhido.
  • Items: Nós filhos.
  • ObjTr: Elemento TR do HTML.
  • ObjArrowImage: Elemento IMG do Html.
  • oMenuTreeView: Objeto da classe MenuTreeView.
  • Parent: Pai do nó.
function MenuTreeView(id, recipient) {
    this.Id = id;
    this.Recipient = recipient;
    
    this.Items = [];

    this.LastSelectedItem;

    this.OnSelectedIndex;
}

function ItemMenuTreeView(id, text, value, urlImagem, tooltip, isExpand) {
    this.Id = id;
    this.Text = text;
    this.Value = value;
    this.UrlImagem = urlImagem;
    this.Tooltip = tooltip;
    this.IsOpen = isExpand;
    this.Items = [];

    this.ObjTr;
    this.ObjArrowImage;

    this.oMenuTreeView;

    this.Parent;
}
Listagem 1. Construtores

Os métodos que criaremos agora são para adicionar e remover os nós.

  • ItemMenuTreeView.prototype.AddItem: Adiciona um nó filho.
  • ItemMenuTreeView.prototype.ClearItems: Limpa a coleção de nós.
  • MenuTreeView.prototype.AddItem: Adiciona um nó filho.
  • MenuTreeView.prototype.ClearItems: Limpa a coleção de nós.
MenuTreeView.prototype.AddItem = function (id, text, value, urlImagem, 
tooltip, isExpand) {
    var index = this.Items.length;

    this.Items[index] = new ItemMenuTreeView(id, text, value, urlImagem, 
tooltip, isExpand);
    this.Items[index].oMenuTreeView = this;
    this.Items[index].Parent = this;

    return this.Items[index];
};

MenuTreeView.prototype.ClearItems = function () {
    this.Items = null;
    this.Items = [];
};

ItemMenuTreeView.prototype.AddItem = function (id, text, value, urlImagem, 
tooltip, isExpand) {
    var index = this.Items.length;

    this.Items[index] = new ItemMenuTreeView(id, text, value, urlImagem, 
tooltip, isExpand);
    this.Items[index].oMenuTreeView = this.oMenuTreeView;
    this.Items[index].Parent = this;

    return this.Items[index];
};

ItemMenuTreeView.prototype.ClearItems = function () {
    this.Items = null;
    this.Items = [];
};
Listagem 2. Adicionando nós

Agora vamos criar os métodos que serão chamados quando os eventos OnMouseOver, OnMouseOut, OnClick, OnDblClick forem disparados.

  • ItemMenuTreeView.prototype.item_OnMouseOver: Quando o mouse passa sobre o objeto.
  • ItemMenuTreeView.prototype.item_OnMouseOut: Quando o mouse deixa de estar em cima do objeto.
  • ItemMenuTreeView.prototype.item_OnClick: Seleciona o nó.
  • ItemMenuTreeView.prototype.item_OnDblClick: Expandi ou recolhe os nós filhos.
ItemMenuTreeView.prototype.item_OnMouseOver = function (element) {
    element.style.backgroundColor = "#FFE6A0";
};

ItemMenuTreeView.prototype.item_OnMouseOut = function (element) {
    element.style.backgroundColor = "";
};

ItemMenuTreeView.prototype.item_Click = function (element) {
    if (this.oMenuTreeView.LastSelectedItem != null) {
        this.oMenuTreeView.LastSelectedItem.ObjTr.bgColor = '';
    }

    this.oMenuTreeView.LastSelectedItem = this;
    this.oMenuTreeView.LastSelectedItem.ObjTr.bgColor = '#BEBEBE';

    if (this.oMenuTreeView.OnSelectedIndex != null) {
        this.oMenuTreeView.OnSelectedIndex();
    }
};

ItemMenuTreeView.prototype.item_DblClick = function () {
    if (this.ObjArrowImage != null) {
        if (this.IsOpen == false) {
            this.IsOpen = true;
            this.ObjArrowImage.src = 'Imagens/Seta1.png';
            this.Expand();
        }
        else {
            this.IsOpen = false;
            this.ObjArrowImage.src = 'Imagens/Seta2.png';
            this.Collapse();
        }
    }
};
Listagem 3. Eventos

Os próximos métodos servem para expandir e recolher os nós filhos do TreeView.

  • ItemMenuTreeView.prototype.Expand: Expande os nós filhos.
  • ItemMenuTreeView.prototype.Collapse: Recolhe os nós filhos.
ItemMenuTreeView.prototype.Expand = function () {
    for (var index = 0; index < this.Items.length; index++) {
        if (window.ActiveXObject) {
            this.Items[index].ObjTr.style.display = 'block';
        }
        else {
            this.Items[index].ObjTr.style.display = 'table-row';
        }

        if (this.Items[index].IsOpen == true) {
            this.Items[index].Expand();
        }
    }
}

ItemMenuTreeView.prototype.Collapse = function () {
    for (var index = 0; index < this.Items.length; index++) {
        this.Items[index].ObjTr.style.display = 'none';
        this.Items[index].Collapse();
    }
}
Listagem 4. Expandir e Recolher
MenuTreeView.prototype.Create = function () {
    var objTable = document.createElement('TABLE');
    var objTBody = document.createElement('TBODY');

    objTable.style.width = '100%';
    objTable.cellPadding = 2;
    objTable.cellSpacing = 0;
    objTable.border = 0;
    objTable.style.whiteSpace = 'nowrap';

    var self = this;

    for (var index = 0; index < this.Items.length; index++) {
        this.Items[index].Create(objTBody, this.Items[index], '');
    }

    objTable.appendChild(objTBody);
    this.Recipient.appendChild(objTable);
}; 

ItemMenuTreeView.prototype.Create = function (objTBody, 
    objItemMenuTreeView, space, isOpen) {
    var objTr = document.createElement('TR');

    objTr.id = objItemMenuTreeView.Id;
    objTr.title = objItemMenuTreeView.Tooltip;
    objTr.style.cursor = 'default';

    objTr.onmouseover = function () { objItemMenuTreeView.item_OnMouseOver(this); }
    objTr.onmouseout = function () { objItemMenuTreeView.item_OnMouseOut(this); }
    objTr.onclick = function () { objItemMenuTreeView.item_Click(this); }
    objTr.ondblclick = function () { objItemMenuTreeView.item_DblClick(); }

    //################# TEXT #######################
    var textTd = document.createElement('TD');
    var objSpan = document.createElement('SPAN');
    var objSpace = document.createElement('LABEL');
    var objImg = document.createElement('IMG');
    var objLabel = document.createElement('LABEL');
    var objSpace2 = document.createElement('LABEL');
    var imageImg = document.createElement('IMG');

    textTd.style.whiteSpace = 'nowrap';

    if (objItemMenuTreeView.IsOpen) {
        objImg.src = 'Imagens/Seta1.png';
    }
    else {
        objImg.src = 'Imagens/Seta2.png';
    }

    if (isOpen != null) {
        if (isOpen) {
            if (window.ActiveXObject) {
                objTr.style.display = 'block';
            }
            else {
                objTr.style.display = 'table-row';
            }
        }
        else {
            objTr.style.display = 'none';
        }
    }

    objLabel.innerHTML = ' ' + objItemMenuTreeView.Text;
    objLabel.className = 'itemMenuTreeViewLabel';

    objSpace.innerHTML = space;

    objSpan.appendChild(objSpace);

    if (objItemMenuTreeView.Items.length > 0) {
        objItemMenuTreeView.ObjArrowImage = objImg;
        objSpan.appendChild(objImg);
    }

    imageImg.src = objItemMenuTreeView.UrlImagem;
    objSpace2.innerHTML = ' ';

    objSpan.appendChild(objSpace2);
    objSpan.appendChild(imageImg);
    objSpan.appendChild(objLabel);
    textTd.appendChild(objSpan);
    objTr.appendChild(textTd);
    //################# TEXT #######################

    objTBody.appendChild(objTr);

    objItemMenuTreeView.ObjTr = objTr;

    for (var index = 0; index < objItemMenuTreeView.Items.length; index++) {
        objItemMenuTreeView.Create(objTBody, objItemMenuTreeView.Items[index], 
        space + '   ', objItemMenuTreeView.IsOpen);
    }
};
Listagem 5. Criando o TreeView
<html>
<head>
  <title>TreeView</title>
  <link rel="stylesheet" href="MainStyleSheet.css" type="text/css" />

  <script language="javascript" type="text/javascript" 
  src="MenuTreeView.js"></script>
  <script language="javascript" type="text/javascript">
      var oMenuTreeView;

      function document_OnLoad() {
          oMenuTreeView = new MenuTreeView('oMenuTreeView', 
          document.getElementById('recipientDIV'));
          oMenuTreeView.OnSelectedIndex = oMenuTreeView_SelectedIndex;


          var caixaEntrada = oMenuTreeView.AddItem('caixaEntrada', 
          'Caixa de Entrada', '0', 
						    'Imagens/Image1.png', '1 E-mail', true);

          caixaEntrada.AddItem('pasta1', 'Pasta 1', '4', 
          'Imagens/pasta.gif', 'Pasta', true);

          var caixaSaida = oMenuTreeView.AddItem('caixaSaida', 
          'Caixa de Saída', '1', 
						  'Imagens/Image2.png', '2 E-mail', true);

          caixaSaida.AddItem('pasta2', 'Pasta 2', '4', 
          'Imagens/pasta.gif', 'Pasta', true);

          oMenuTreeView.AddItem('itensExcluido', 'Itens excluídos', '2', 
					            'Imagens/Image3.png', '3 E-mail', true);

          var rascunhos = oMenuTreeView.AddItem('rascunhos', 'Rascunhos', 
											    '3', 'Imagens/Image4.png', '', true);

          rascunhos.AddItem('pasta3', 'Pasta 3', '4', 
          'Imagens/pasta.gif', 'Pasta', true);
          rascunhos.AddItem('pasta4', 'Pasta 4', '5', '
          Imagens/pasta.gif', 'Pasta', true);

          oMenuTreeView.Create();
      }

      function oMenuTreeView_SelectedIndex() {
          document.getElementById('clickLabel').innerHTML = oMenuTreeView.LastSelectedItem.Text;
      }
  </script>
</head>
<body onload="document_OnLoad();" >
    <div id="recipientDIV" style="height:200px;width:150px" class="borda">
    </div>
    <label id="clickLabel"></label>
</body>
</html>
Listagem 6. HTML da página
Exemplo Completo
Figura 3. Exemplo Completo