Newsgroup: it.comp.lang.javascript
Titolo: disegnare un albero

Ciao,
ho un albero descritto da due array
id = new Array("1","2","3","4")
parent = new Array("4","0","2","2")
.2
.  3
.  4
.    1
in partica per ogni nodo dico qual'è il suo genitore, sapendo che se
il genitore è =0 allora si tratta della radice. Ora vorrei scrivere
una funzione che dati i due array stampi l'albero usando una lista.
a)il primo passo è trovare la radice, quindi attraverso l'array
parent, se trovo uno zero so che l'elmento in quella stessa posizione
dell'array id è la radice, creo l'opportuna stringa. Nessun problema.
b)Boh! Mi son fermato qui, ho provato diverse strade, ma nulla che
funzioni davvero, qualche suggerimento? Ho l'impressione che non sia
complicato ma npon riesco a vederne una via d'uscita
Grazie
Alex

Non mi pare una gran bella struttura dati per descrivere un albero, ma 
questo è il mio parere che volevo condividere prima di proseguire.
Un metodo abbastanza iterativo con un po' di ricorsione:
(base)
1) cerco il nodo con padre 0
2) scrivo quel nodo (ricavato da "id")
(passo)
3) incremento la profondità di 1
4) cerco in parent il nodo trovato precedentemente
5) scrivo quei nodi (ricavati da "id") figli del nodo precedente
6) ricorsione sui nodi trovati
Spero aiuti!

 complicato ma npon riesco a vederne una via d'uscita
Domani ci penso :-) Per prima cosa guarda in giro penso sia un problema
abbastanza comune. Mi azzardo anche io a dire che la struttura dati non
è il massimo, farei un array 2D
// id, parent_id
var datatable = [
    [1,0],
    [2,0],
    [3,2],
    [4,3],
    [5,3],
    [6,2],
    [7,0]
];
E ricordati che in javascript puoi usare arguments.callee in modo da
mantenere il valore tra varie chiamate alla funzione, altrimenti con la
ricorsione saresti fregato.
Ciao.
-- 
--
FABIO SERRA
Per rispondere in e-mail sostituire "invalid" con "faser"
*Questo testo deve essere valutato secondo il senso della RFC-3*
------------------

 complicato ma npon riesco a vederne una via d'uscita
Una volta che hai una struttura gerarchica, il resto viene da sè. Ci sono
due modi per scrivere il codice: tramite scrittura diretta sull'output
stream, oppure tramite DOM API.
Nel primo caso, sarebbe qualcosa del tipo:
 
	function listWriter( data ){
		document.write("<ul>");
 
		for (var i = 0;i < data.length;i++)
			if ( data[i].constructor == Array ){
				listWriter( data[i] );
			}else{
				document.write("<li>"+data[i]+"</li>");
			}
		document.write("</ul>");
 
	}
E dovresti richiamare la funzione nel punto esatto in cui vuoi che l'albero
venga generato:
<body>
	<script type="text/javascript">listWriter( tree )</script>
</body>
Nel secondo caso, sarebbe qualcosa del genere:
	function listBuilder( data, pn ){
		var ul 	= document.createElement("ul"),
			li	= null;
 
		pn.appendChild(ul);
		for (var i = 0;i < data.length;i++)
			if ( data[i].constructor == Array ){
				listBuilder( data[i], li );
			}else{
				li = document.createElement("li");				
				ul.appendChild(li).appendChild( document.createTextNode(data[i]) );
			}
 
	}
E la sua esecuzione sarebbe tipo:
	window.onload = function(){
		listBuilder( data, document.body );
	}
Con questo dovresti avere più o meno tutto ciò che ti serve per il tuo
proposito. Ovviamente al posto delle stringhe puoi anche utilizzare oggetti
custom e cose del genere.
-- 
"Non è una guerra.. è uno sterminio.. loro stanno a noi come 
uomini contro i  vermi.. draghi contro i lupi.. 
O uomini che cavalcano draghi e lanciano lupi addosso ai vermi!"

 stream, oppure tramite DOM API.
Con la struttura gerarchica già pronta, e soprattutto avendo già il
livello (insomma avevo tutto :-), in battuta mi è venuta così:
http://faser.net/public/tmp/js_tree/tree.html
Ciao.

 
http://faser.net/public/tmp/js_tree/tree.html
E' sinceramente un approccio che non condivido. Anche se magari può
dipendere dalle casistiche.


Ringrazio da subito tutti!
Non speravo in un supporto così ricco, vi ringrazio ancora e vi farò
sapere come vanno le cose
Saluti e buon 25 aprile!
Alex

Grazie ZERO,
per me che sono un pessimo principiante in termini di programmazione
questa soluzione è più chiara. MI rimane il problema di passare dalla
struttura dati che ho io (di tipo tabellare come suggeriva faser) a
quella che suggerischi tu. Soprattutto perchè poi questa struttura
(dopo averla magari opportunamente modificata) devo salvarla in una
relazione del mio db che ha proprio la struttura:
ID     TOPIC
-----  -----------
1         2
2         0
3         2
4         3
Grazie a tutti

 quella che suggerischi tu. 
Appunto è quello il problema. Non ho nulla di pronto, ma mi sà che serve
anche a me. La prima cosa che faccio e ti conviene fare è cercare
l'algoritmo migliore (ma APB ha dato la strada giusta), anche in altri
linguaggi, tanto è una cosa abbastanza comune.
Io comunque passerei sempre ad una struttura di array 2D come ho detto,
in pratica la stessa cosa che mi restituisce Oracle. In questo modo
lavorando sempre su un "recorset" mi viene più facile dopo inserire e
modificare il db.
Se trovi qualcosa fammi sapere :-)
Ciao.


 relazione del mio db che ha proprio la struttura:
Salvarla nuovamente tutta in blocco? Non ti converrebbe salvare unicamente
le modifiche che effettui, magari volta volta? Certo, dipende sempre dal
contesto (che ancora non è del tutto chiaro) e dalla mole di dati; e da
come "decidi" di passare i dati al server.


Qui un idea su come affrontare il problema in php. Non ho ancora
testato la cosa cmq mi sembra ragionevole.
http://www.sitepoint.com/article/hierarchical-data-database
Ciao
Alex

 ricorsione saresti fregato.
.. E perché mai?
O meglio, forse devo capire cosa intendi per "fregato".
-- 
"Non č una guerra.. č uno sterminio.. loro stanno a noi come 


Cerco di descrivere meglio il mio caso:
-ho una tabella che contiene un certoi numero di oggetti presi da un db
-devo definire una struttura a albero di questi oggetti ad es. dicendo
l'oggetto pippo è un figlio di pluto, ecc...
-Una volta che la struttura è stata definita la salvo in una relazione
del db "piatta" del tipo id-parent (come quella di cui si è parlato
nei post precedenti).
Se qualcuno ha suggerimenti in proposito son felice di accoglierli
perchè è un bel pò che cerco strade diverse e non ne sono venuto a
capo.
Io ho pensato di usare js per definire la struttura (magari usando una
finestra di pop up per avere sempre la lista dal quale andare a
recuperare gli oggetti disponibili), da qui il mio problema di
disegnare l'albero in modo da poter fare modifiche alla struttura dati
e fare il refresh di tutto l'albero dopo ogni modifica.
Grazie molte per l'aiuto
Ciao

 capo.
Ho capito. Ho fatto una cosa simile, ma con ColdFusion + Flash e sono
30 righe in tutto, purtroppo farlo via js diventa più complesso.
Dipende dal tempo che hai a disposizione e dal grado di qualità dei
widget che vuoi raggiungere.
Il concetto è quindi che da una parte hai la lista di tutti gli
elementi e li sposti da un'altra parte in modo da creare la gerarchia.
Per prima cosa ti serve un "oggetto" che gestisca un albero, il drag &
drop degli elementi etc.
Prova a vedere se dojotoolkit ti può essere d'aiuto
http://archive.dojotoolkit.org/nightly/tests/widget/tree/
o cose simili.
Una volta che l'hai creato fai il post e la inserisci nel db. Qui è la
parte più semplice.
Rimane sempre il problema che devi creare l'albero partendo dalla
struttura piatta (a meno che il tuo database non abbia un connect by
prior come Oracle o Stored Procedure per creare relazioni gerarchiche)
e questo avvalersi di js potrebbe essere una buona idea anche se in
caso di molti record annidati non ho idea di come potrebbe reggere a n
livelli di ricorsione. Puoi quindi anche seguire la strada di creare la
struttura ad albero via linguaggio server-side.
Per quanto riguarda semplicemente disegnare l'albero, avendo già la
struttura dati, in HTML la cosa più veloce è usare <ul> e <li> come
ad esempio qui:
http://kryogenix.org/code/browser/aqlists/
Conclusione: sono vari step, decidi da dove vuoi partire.

 nei post precedenti).
Quindi, una volta che hai diciamo le tue liste UL nell'HTML, che hai
"l'albero" realizzato visivamente, cosa ci devi fare? Quali sono le
operazioni che da attuare, e in che modo interagisci con il tree?
Dato che poi si parla di "salvare" nuovamente i dati, significa che i dati
verranno modificati in un qualche modo.
Anche qui, l'approccio da usare varia rispetto a ciò che s'intende fare
ovviamente.
Da quanto poi ho capito tu vorresti salvare i dati nuovamente in blocco. Ha
senso? Sempre relativamente alla mole di dati, e al tipo di operazioni che
vengono attuate sull'albero, potrebbe essere più indicato salvare "on
demand", ovvero nel momento in cui modifichi il singolo dato, magari
utilizzando XmlHttpRequest (tanto, mi par di capire, che di una web
application stiamo parlando. O no?).
