<pedrocorreia.net ⁄>
corner
<mySearch ⁄> <mySearch ⁄>

corner
 
corner
<mySnippets order="rand" ⁄> <mySnippets order="rand" ⁄>

corner
 
corner
<myContacts ⁄> <myContacts ⁄>

<email ⁄>


pc@pedrocorreia.net

<windows live messenger ⁄>


pedrojacorreia@hotmail.com

<myCurriculum type="pdf" ⁄>


Download
corner
 
corner
<myBlog show="last" ⁄> <myBlog show="last" ⁄>

corner
 
corner
<myNews show="rand" ⁄> <myNews show="rand" ⁄>

corner
 
corner
<myNews type="cat" ⁄> <myNews type="cat" ⁄>

corner
 
corner
<myQuote order="random" ⁄> <myQuote order="random" ⁄>

corner
 
corner
<myPhoto order="random" ⁄> <myPhoto order="random" ⁄>

<pedrocorreia.net ⁄>
corner
 
corner
<myAdSense ⁄> <myAdSense ⁄>

corner
 
corner
<myVisitorsMap ⁄> <myVisitorsMap ⁄>

corner
 
 

<Menus em árvore dinâmicos ⁄ >




clicks: 24015 24015 2007-04-15 2007-04-15 goto mySnippets mySnippets php  Download  Bookmark This Bookmark This



Uma simples busca, passando o pleonasmo, em qualquer motor de busca será suficiente para encontrar alguns menus em javascript já pré-feitos (alguns a pagar, outros nem por isso) e de alguma relativa fácil adaptação às nossas necessidades, alguns até têm uma interface toda gira para que ninguem suje as mãos com javascript nem queime pestanas a ler a documentação, mas programador(a) que é programador(a) gosta é disso!

Este snippet irá ser dividido em duas partes completamente distintas (porém têm a mesma finalidade... confuso? também me pareceu quando escrevi):

- na 1ª parte irei basear-me num script que permite construir o menu em esquema de árvore, consequentemente terão de efectuar o download do script neste link e descompactar todos os ficheiros. No site encontram-se alguns exemplos de possiveis menus, visto que os menus podem ser totalmente configuráveis através da manipulacação do css;

- na 2ª parte irei demonstrar uma possivel maneira de construir a árvore (mas não tão funcional nem atractiva à vista(tm) ;)) mas recursivamente;



Já dizia o outro ... vamos por partes ...


Como dito anteriormente a 1ª parte irá ser baseado no script que terão de fazer o download, o código javascript para a construção do menu é fácil e intuitivo, como irão ver mais abaixo; bem como a sua customização é feita toda através de ficheiros css que poderão ser facilmente editáveis e consequentemente personalizáveis, sendo que o ficheiro que fizemos o download já traz alguns exemplos, 3 para ser mais especifico.

Uma possivel implementação para a construção árvore podia ser deste tipo:
  1. var myCustomTree1=new jktreeview("tree1");
  2.  
  3. var no1=myCustomTree1.addItem("Menu 1","" );
  4. var no2=myCustomTree1.addItem("Menu 2","" );
  5. var no3=myCustomTree1.addItem("Menu 1.1",no1,"http://www.pedrocorreia.net");
  6. var no4=myCustomTree1.addItem("Menu 2.1",no2 ,"http://www.slbenfica.pt");
  7.  
  8. myCustomTree1.treetop.draw(); //REQUIRED LINE: Initalize tree



Quite easy, right? Mas se o menu começar a crescer começa a tornar-se complicado gerir tudo e ao longo de várias páginas ainda mais trabalhoso irá ser (digo eu).

Olhando um pouco para o código vemos que existe ali um padrão, cada nó tem uma descrição, um link e se o proprio nó pertence a outro nó, passando a ser uma folha desse nó e assim consecutivamente (leaf-node), se um nó pertence a outro nó, entao parece claro que temos de saber qual a identificação daquele nó, sendo que o outro campo que poderá não estar tão visivel, mas facilmente intuível, é o campo identificador, vulgo chave primária.
Assumimos que as nós principais (raiz) não pertencem a ninguém e como tal têm o valor 0 no campo que indica a quem aquele nó especifico pertence.


Bem tanta lenga-lenga até agora e de dinâmico só viram a palavra escrita no titulo, irá ser aqui que a parte dinâmica do titulo (até agora esquecida :)) irá entrar, e que tal deixarmos o dirty work todo para o PHP? Quanto menos andarmos a meter as mãos em javascript, melhor, e se isso nos permitir configurar o menu no resto do site, poupando assim trabalho e possiveis enganos, melhor ainda.

Continuando ainda com a lenga-lenga ... como devem ter reparado no exemplo de cima, na construção do javascript podem facilmente identificar o necessário à construção do menu: vamos dizer qual é o nome do nó, o seu link (caso assim seja necessário) e quem é que o nó pertence.

Recorrendo um pouco a pseudocódigo, imaginemos que tems a seguinte estrutura na BD: tabela(id, pertence, descricao, link), para construir um menu com dois nós e duas folhas cada, poderia ser assim:
(1,0,"Menu 1",NULL);
(2,0,"Menu 2",NULL);
(3,1,"Menu 1.1","http://www.pedrocorreia.net");
(4,2,"Menu 1.2","http://www.slbenfica.pt");

A base de dados utilizada será o mysql, porém seria também perfeitamente possivel usar outra qualquer maneira de armazenamento, seja xml, csv, txt, [you name it]. Uma possivel estrutura seria:
  1. -- Table "navegacao" DDL
  2. CREATE TABLE `navegacao` (
  3. `id` tinyint(4) NOT NULL AUTO_INCREMENT,
  4. `pertence` tinyint(4) NOT NULL DEFAULT '0',
  5. `descricao` varchar(50) NOT NULL DEFAULT '',
  6. `link` varchar(75) DEFAULT NULL,
  7. PRIMARY KEY (`id`)
  8. ) ENGINE=MyISAM DEFAULT CHARSET=latin1;



Para questões de exemplo mais adiante, vamos preencher a tabela com alguns valores de teste (mas fica tudo junto, para não causar confusão):
  1. INSERT INTO navegacao (id, pertence, descricao, link) VALUES (1, 0, "Menu 1", "NULL");
  2. INSERT INTO navegacao (id, pertence, descricao, link) VALUES (2, 0, "Menu 2", "NULL");
  3. INSERT INTO navegacao (id, pertence, descricao, link) VALUES (3, 0, "Menu 3", "NULL");
  4. INSERT INTO navegacao (id, pertence, descricao, link) VALUES (4, 0, "Menu 4", "NULL");
  5. INSERT INTO navegacao (id, pertence, descricao, link) VALUES (5, 1, "Menu 1.1", "NULL");
  6. INSERT INTO navegacao (id, pertence, descricao, link) VALUES (6, 2, "Menu 2.1", "http://www.iol.pt");
  7. INSERT INTO navegacao (id, pertence, descricao, link) VALUES (7, 3, "Menu 2.3", "http://www.portugaldiario.iol.pt");
  8. INSERT INTO navegacao (id, pertence, descricao, link) VALUES (8, 4, "Menu 2.4", "http://www.record.pt");
  9. INSERT INTO navegacao (id, pertence, descricao, link) VALUES (10, 0, "Menu 5", "NULL");
  10. INSERT INTO navegacao (id, pertence, descricao, link) VALUES (9, 10, "Menu 5.1", "http://www.pedrocorreia.net");
  11. INSERT INTO navegacao (id, pertence, descricao, link) VALUES(11, 5, "Menu 1.1.1", "http://www.abola.pt");



Para a ligação à base dados, será usado um ficheiro chamado connection.php
  1. <?php
  2. /**
  3. * Efectuar ligação à BD
  4. *
  5. * @return ligação
  6. */
  7. function connectDB(){
  8. $db = mysql_connect("db_server", "db_username", "db_password");
  9. mysql_select_db("db_name",$db) or die("<b><br>Impossivel aceder á base de dados</b><BR>");
  10. return $db;
  11. }
  12. ?>



A construção do javascript necessário, ficará a cargo do DoMenu.php
  1. <?php
  2.  
  3. /**
  4. * Construir menu
  5. *
  6. * @param String $tabela
  7. * @param String $treeName
  8. * @param String $div
  9. * @return String
  10. */
  11. function DoMenu($tabela,$treeName,$div){
  12. $db=connectDB();
  13.  
  14. $sql=mysql_query("Select id, descricao, link, pertence From $tabela");
  15.  
  16. while($myrow=mysql_fetch_array($sql)){
  17. $content.=DoMenuNode($treeName,$myrow["id"],$myrow["descricao"],$myrow["pertence"],$myrow["link"]);
  18. }
  19. mysql_close($db);
  20.  
  21. return "
  22. var $treeName=new jktreeview(\"$div\");\r\n
  23. $content
  24. $treeName.treetop.draw(); //REQUIRED LINE: Initalize tree\r\n
  25. ";
  26. }
  27.  
  28. /**
  29. * Construir nó (função auxiliar da função DoMenu)
  30. *
  31. * @param String $treeName
  32. * @param int $nodeNumber
  33. * @param String $nodeDescription
  34. * @param int $nodeBelongsTo
  35. * @param String $nodeLink
  36. * @return String
  37. */
  38. function DoMenuNode($treeName,$nodeNumber,$nodeDescription,$nodeBelongsTo,$nodeLink){
  39. $nodeBelongsTo=($nodeBelongsTo>0)?"no$nodeBelongsTo":"\"\"";
  40. $nodeLink=($nodeLink)?(",\"$nodeLink\""):"";
  41.  
  42. return "var no$nodeNumber=$treeName.addItem(\"$nodeDescription\",$nodeBelongsTo $nodeLink);\r\n";
  43. }
  44.  
  45. ?>




Visto que este snippet se divide em 2 partes, irei de seguida explicar a 2ª parte e só depois mostrar o html para "juntar" as peças.



Esta 2ª parte a única coisa em comum com a 1ª parte, é que teoricamente ambas constroem menus, se bem que é 1 elogio chamar a este exemplo 1 menu, é quanto muito um encadeamento de palavras indentadas :). Não oferecendo dúvidas que obviamente a 1ª parte é melhor, porém o objectivo desta 2ª parte é tentar demonstrar outra maneira de construir a árvore mas recorrendo ao uso da recursividade (se isto traz pesadelos a alguém, peço desde já desculpas, a malta do Haskell é que deve estar contente).


A estrutura da base de dados será exactamente a mesma da 1ª parte.


Irá ser criado um ficheiro diferente para não gerar confusão, por exemplo DoMenuRecursive.php
  1. <?php
  2. /**
  3. * Construir menu recursivamente
  4. *
  5. * @param String $tabela
  6. * @param String $parent
  7. * @param String $level
  8. * @return String
  9. */
  10. function DoMenuRecursive($tabela, $parent=0, $level=0){
  11. $indent = "";
  12. if(!$db) $db=connectDB();
  13.  
  14. for ($i=0; $i<$level; $i++) $indent .= "[+]"; //fazer "identação"
  15.  
  16. $sql = mysql_query("SELECT id, descricao, link FROM $tabela WHERE pertence='$parent'");
  17. while ($myrow = mysql_fetch_array($sql)){
  18. $descricao=$myrow["descricao"];
  19. $link=$myrow["link"];
  20. $nodeName="lnkNode_$myrow[id]";
  21.  
  22. $node=(!$myrow["link"])?$descricao:DoHref($link,$descricao,$nodeName,"_blank");
  23. $str.="$indent $node<br>";
  24. $str.=DoMenuRecursive($tabela,$myrow["id"], intval($level) + 1);
  25. }
  26.  
  27. return $str;
  28. }
  29. /**
  30. * Construir <a> (função auxiliar da função DoRecursiveMenu)
  31. *
  32. * @param String $hrefLink
  33. * @param String $hrefDescription
  34. * @param String $hrefName
  35. * @param String $hrefTarget
  36. * @param String $hrefClass
  37. * @param String $hrefStyle
  38. * @return String
  39. */
  40. function DoHref($hrefLink,$hrefDescription,$hrefName,$hrefTarget="",$hrefClass="",$hrefStyle=""){
  41. $hrefClass=(!$hrefClass)?$hrefClass:" class='$hrefClass' ";
  42. $hrefStyle=(!$hrefStyle)?$hrefStyle:" style='$hrefStyle' ";
  43. $hrefTarget=(!$hrefTarget)?$hrefTarget:" target='$hrefTarget' ";
  44. $hrefAlt=" alt='$hrefDescription' title='$hrefDescription' ";
  45. $hrefName=(!$hrefName)?$hrefName:" name='$hrefName' id='$hrefName' ";
  46.  
  47. return "<a href='$hrefLink' $hrefAlt $hrefClass $hrefStyle $hrefTarget $hrefName>$hrefDescription</a>";
  48. }
  49. ?>









Last but not the least ... lets glue all things together!

  1. <!doctype html public "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  2. <html>
  3. <head>
  4. <title>Tree View</title>
  5.  
  6. <link rel="stylesheet" type="text/css" href="css/multi/tree.css">
  7. <script type="text/javascript" src="build/yahoo.js" ></script>
  8. <script type="text/javascript" src="build/event.js"></script>
  9. <script type="text/javascript" src="build/treeview.js" ></script>
  10. <script type="text/javascript" src="build/jktreeview.js" ></script>
  11.  
  12. <!-- Below is Style sheet for demos. Removed if desired -->
  13. <style type="text/css">
  14. body {font: normal 11px verdana, sans-serif; color: #333; line-height: 19px;}
  15. a { text-decoration: underline; color: #46546C; }
  16. a:hover { text-decoration: underline; color: #4d77c3; }
  17. #tree1 {width:250px;padding: 10px;float:left;}
  18. #tree2 {width:250px;padding: 10px;float:left;}
  19. #tree3 {width:250px;padding: 10px;float:left;}
  20. </style>
  21. </head>
  22.  
  23. <body>
  24.  
  25. <h2>Folding TreeView Menu demo: <a href="http://www.javascriptkit.com/script/treeview/">More info</a></h2>
  26.  
  27. <!--Empty DIV tags to contain the treeview demos -->
  28. <div id="tree1"><!-- exemplo da tree 1--></div>
  29. <div id="tree2"><!-- exemplo da tree 2--></div>
  30. <div id="tree3" class="treemenu"><!-- exemplo da tree 3--></div>
  31.  
  32. <script type="text/javascript">
  33. <?php
  34. //todo o código daqui para cima é fornecido no ficheiro de exemplo ...
  35. //aqui vai o nosso código ...
  36. include_once("DoMenu.php");
  37. include_once("DoMenuRecursive.php");
  38. include_once("Connection.php");
  39.  
  40.  
  41.  
  42. echo DoMenu("navegacao","myCustomTree1","tree1");
  43. echo DoMenu("navegacao","myCustomTree2","tree2");
  44. echo DoMenu("navegacao","myCustomTree3","tree3");
  45. ?>
  46. </script>
  47.  
  48. <div style="clear:both">
  49. <h2>Implementação recursiva, but no so visualy ... pretty ;)</h2>
  50. <?php
  51. echo DoMenuRecursive("navegacao");
  52. ?>
  53. </div>
  54. </body>
  55. </html>




Como repararam um dos parametros das funções responsáveis pela construção do menu (no php) é a própria tabela, logo poderão possuir várias tabelas para menus, diferentes em cada página, sem ter que andar a colocar tudo no mesmo menu, ou então alterando o código poderão adaptá-lo facilmente para que seja tudo controlado na mesma tabela, e essa tabela ter por exemplo um campo que indica que aquela página terá certos itens, outra página terá outros, etc, etc.


Tendo em conta os valores que inserimos na tabela, deverão ver uma página algo semalhante a esta:

Exemplo dos Menus
nota: não, a descrição dos menus não está errada, por ex: o Menu 2.3 pertence ao Menu 3, com aquela descrição pela lógica deveria pertencer ao Menu 2, caso não tenham reparado isto aquando da inserção dos dados, é somente para mostrar que não interessa a ordem pela qual os valores vão inseridos ...



Qualquer erro/ dúvida é só dizer!









clicks: 24015 24015 2007-04-15 2007-04-15 goto mySnippets mySnippets php  Download  Bookmark This Bookmark This