Newsgroup: it.comp.www.php
Titolo: Modified Preorder Tree Traversal

Devo realizzare un menu come questo:
http://www.bonacinapierantonio.it/test/dicssmenu.html
Ho abbandonato la soluzione "Adjacency List Model" in favore della
soluzione "Modified Preorder Tree Traversal"
Tra i vari esempi ho trovato questa pagina che penso sia un
suggerimento per semplificarmi la vita dei tag LI e UL.
http://dev.mysql.com/tech-resources/articles/hierarchical-data.html
codice PHP:
CREATE TABLE nested_category (
category_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
lft INT NOT NULL,
rgt INT NOT NULL
);
INSERT INTO nested_category
VALUES(1,'ELECTRONICS',1,20),(2,'TELEVISIONS',2,9),(3,'TUBE',3,4),
(4,'LCD',5,6),(5,'PLASMA',7,8),(6,'PORTABLE ELECTRONICS',10,19),
(7,'MP3 PLAYERS',11,14),(8,'FLASH',12,13),
(9,'CD PLAYERS',15,16),(10,'2 WAY RADIOS',17,18);
E la query che mostra la profondita' dei nodi:
codice PHP:
SELECT 
node.name
, (COUNT(
parent.name
) - 1) AS depth
FROM nested_category AS node,
nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY 
node.name
ORDER BY node.lft;
+----------------------+-------+
| name                 | depth |
+----------------------+-------+
| ELECTRONICS          |     0 |
| TELEVISIONS          |     1 |
| TUBE                 |     2 |
| LCD                  |     2 |
| PLASMA               |     2 |
| PORTABLE ELECTRONICS |     1 |
| MP3 PLAYERS          |     2 |
| FLASH                |     3 |
| CD PLAYERS           |     2 |
| 2 WAY RADIOS         |     2 |
+----------------------+-------+
Il testo indica questa query come quella per partire a generare i tag
UL e LI ma io non ci arrivo.
Mi date una mano ?

 Mi date una mano ?
non sai quanto mi fa piacere vedere che qualcuno chiama questo tipo di
albero in questo modo..
comunque e' semplice leggendo la lista se la profondita' e' identica a
quella dell'elemento precedente i due elementi sono all'interno dello
stesso ramo se cresce si crea un nuovo ramo se decresce si chiude il ramo
in cui ci si trova..
ELECTRONICS 0
  TELEVISIONS 1
    TUBE 2
    LCD 2 
    PLASMA 2
  PORTABLE ELECTRONICS 1
    MP3 PLAYERS 2
      FLASH 3
    CD PLAYERS 2
    2 WAY RADIOS 2
-- 
www.iuz-lab.info

 soluzione "Modified Preorder Tree Traversal"
La ricorsione è bella, concisa, elegante ed ha anche un
certo fascino intrinseco.
Le ha tutte insomma, *tranne una*: Le prestazioni (intese
come uso di memoria, overhead, efficienza).
Io non la userei quasi mai, tranne nei casi in cui
la dimensione del problema è tale per cui i drawback
sono - al lato pratico - inesistenti.
Un "menu" è uno di questi casi.
Se stai generando un *MENU*, esagerando davvero, quante voci
avrà al massimo ... 30 ? 40 ? 100 (CENTO VOCI DISTINTE ???).
Non ci pensare nemmeno. Salva per ciascun record il suo parent,
costruisci una procedura ricorsiva per ricostruire l'albero.
( A meno che non sia un esercizio didattico ) ... nel qual caso,
il ragionamento salta.
(IMHO)
Se vuoi una mano... ho già fatto la stessa IDENTICA cosa.
ciao, f.

io ho risulto cosi' pero' ora ho un problema con i css:
<style type="text/css">
	body {
	behavior:url("csshover.htc");
	}
 
	* {
	font-family:Verdana, Arial, Helvetica, sans-serif;
	font-size:10px;
	}
	ul,li,a {
	display:block;
	margin:0;
	padding:0;
	}
	ul {
	width:127px;
	background:#e6e6e6;
	list-style:none;
	border-top-width: 0px;
	border-right-width: 0px;
	border-bottom-width: 0px;
	border-left-width: 0px;
	border-top-style: none;
	border-right-style: none;
	border-bottom-style: none;
	border-left-style: none;
	}
	li {
	position:relative;
	padding:0px;
	z-index:9;
	margin: 0px;
	width: 125px;
	}
		li.folder	{
	border: 1px solid #0000FF;
}		
		li.folder ul {
	position:absolute;
	left:120px; /* IE */
	top:5px;
	background-color: #e6e6e6;
		}		
			li.folder>ul {
	left:120px;
} /* others */
	a {
	width:125px;
	}
		li>a { width:125px; } /* others */
	li a.submenu {
 
	}
	/* regular hovers */
	a:hover {
		border-color:#FF0000;
	}
		li.folder a:hover {
		}
 
	/* hovers with specificity */
 
	li.folder:hover { z-index:10; }		
 
	ul ul, li:hover ul ul {
	display:none;
	}
	li:hover ul, li:hover li:hover ul {
		display:block;
	}		
	</style>
<?
$db_host = "localhost";
$db_user = "root";
$db_password = "";
$db_name = "t3";
$db = mysql_connect($db_host, $db_user, $db_password);
if ($db == FALSE)
die ("Errore nella connessione.");
mysql_select_db($db_name, $db)
or die ("Errore nella selezione del database.");
 
$sql = 'SELECT node.*, (COUNT(
parent.name
) - 1) AS depth FROM
main_menu AS node, main_menu AS parent WHERE node.lft BETWEEN
parent.lft AND parent.rgt AND parent.category_id !=1 GROUP BY
node.category_id ORDER BY node.lft  ';
 
 
 
 
   $result = mysql_query($sql,$db);     
 
$last_depth = -1;
$output= '<ul id="menu">';   
while(   $rs = mysql_fetch_array($result)             ) {
  $current_depth = $rs['depth'];  
 
  if ($last_depth > $current_depth) {
    $output .= str_repeat('</ul></li>', ($last_depth -
$current_depth));
  }
 
  $ha_figli = $rs['rgt'] - $rs['lft'] -1;
  $output .= '<li class="folder"><a href="#"><img border=0
src="etichetta.php?txt='.
$rs['name'].'&background='.$rs['background'].'&font_color='.$rs['font_color'].'&ha_figli='.$ha_figli.'">';
  if ($rs['rgt'] - 1 != $rs['lft']) {
    $output .= '</img></a><ul>';
  } else {
    $output .= '</img></a></li>';
  }
  $last_depth = $current_depth;
}
echo $output . '</ul>';
 
 ?>
vedi anche:
http://forum.html.it/forum/showthread.php?s=&threadid=1014797

 certo fascino intrinseco.
Hey, qui sei OT per queste cose!
Spostati sulla gerarchia it.sesso.* ...
Ciao ;-)
Tristan

 Spostati sulla gerarchia it.sesso.* ...
;)
Lo farò.  Nel frattempo ti consiglio la seguente lettura:
"Goedel, Escher, Bach: Un'eterna Ghirlanda Brillante".
Insomma, questo:
http://tinyurl.com/z76ak
Leggilo, e vedrai che anche i sogni di notte saranno ricorsivi,
autoreferenzianti, ed un po' indeterminati.
;))))
ciao, f.

Ciao a tutti.
Sbatto la testa per questo problema
Se devo aggiungere una foglia ad un nodo uso la seguente query:
LOCK TABLE nested_category WRITE;
SELECT @myLeft := lft FROM nested_category
WHERE name = '2 WAY RADIOS';
UPDATE nested_category SET rgt = rgt + 2 WHERE rgt > @myLeft;
UPDATE nested_category SET lft = lft + 2 WHERE lft > @myLeft;
INSERT INTO nested_category(name, lft, rgt) VALUES('FRS', @myLeft + 1,
@myLeft + 2);
UNLOCK TABLES;
Pero' se il nodo ha gia' foglie la nuova foglia viene inserita come
prima a sinistra.
Io la vorrei inserire come prima a destra (cioe' come ultima).
Idee ?

 Idee ?
si..
valore sinistro uguale a quello destro dell'ultimo nodo a sinistra del nodo
padre piu' uno e destro come quello destro del nodo padre (naturalmente
incrementando la dovuta parte destra dell'albero di uno).. ma non so' se ho
capito il problema e descritto bene quello che volevo dire..
-- 
www.iuz-lab.info