Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Poprawne generowanie zagnieżdżonych list ul
Forum PHP.pl > Forum > PHP
wiechol
Witam

O jakiegoś czasu męczę się z problemem poprawnego generowania wielopoziomowych list.
Listy przedstawiają strukturę drzewiastą z bazy, a dokładniej kategorie i podkategorie.
Dotychczas stosowałem spacje by uzyskać pożądany efekt jednak teraz muszę skorzystać z list <ul><li> Podchodziłem do tego tematu już wiele razy jednak zawsze z marnymi rezultatami.

Na poniższym screenie graficzne przedstawienie problemu:

http://img145.imageshack.us/img145/6786/kategorieiw9.jpg

Po lewej mamy przedstawioną tabelkę z poprawnie wyglądającą listą kategorii(ustawioną za pomocą spacji) dodatkowo pokazałem tam dane z bazy. Po prawej natomiast widok poprawnie wyglądającej listy(Wpisana manualnie). Nie mam już siły na te listy więc proszę was o sugestie, pomoc w tym temacie.

Tablica kategorii wystarczy ją dodać przez include i objechać foreachem z magicznym kodem smile.gif

Dodatkowo podam jeszcze poprawny kod listy:


Kod
<ul>
    <li>Windows
        <ul>
            <li>Win  98
                <ul>
                    <li>Win 98 SE</li>
                </ul>
            </li>
            <li>Win XP
                <ul>
                    <li>Win XP Basic</li>
                    <li>Win Xp Profesional</li>
                </ul>
            </li>
            <li>Win Vista
                <ul>
                    <li>Win Vista Starter</li>
                    <li>Win Vista Home Basic</li>
                    <li>Win Vista Home Premium</li>
                    <li>Win Vista Business</li>
                    <li>Win Vista Enterprise</li>
                    <li>Win Vista Ultimate</li>
                </ul>
            </li>
            <li>Win 95</li>
        </ul>
    </li>
    <li>Linux
        <ul>
            <li>Debian</li>
            <li>Gentoo</li>
            <li>Mandriva Linux</li>
            <li>Ubuntu</li>
            <li>Slackware</li>
            <li>Red Hat Linux</li>
        </ul>
    </li>
    <li>Mac OS
        <ul>
            <li>Mac OS X 10.3 Panther</li>
            <li>Mac OS X 10.4 Tiger</li>
            <li>Mac OS X 10.5 Leopard</li>
        </ul>
    </li>
    <li>Testowa A
        <ul>
            <li>Testowa AB
                <ul>
                    <li>Testowa ABC
                        <ul>
                            <li>Testowa ABCD
                                <ul>
                                    <li>Testowa ABCDE</li>
                                </ul>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>


Najlepsze wyniki do jakich doszedłem to poprawne wyświetlanie list ale niepoprawne zagnieżdżanie:

  1. <?php
  2. function showHtmlLists(){
  3. include_once(ROOT_DIR.'kategorieArray.php');
  4. $li = '<ul>';
  5. $tmpLevel = 0;
  6. foreach($categories as $elem){
  7. if($elem['level'] > $tmpLevel){
  8. $li .='<ul>';
  9. }elseif($elem['level'] < $tmpLevel){
  10. $li .='</ul>';
  11. }
  12.  
  13. $li .= '<li>'.$elem['name'].'</li>';
  14.  
  15. $tmpLevel = $elem['level'];
  16. }
  17. $li .= str_repeat('</ul>', $tmpLevel);
  18. $li .= '</ul>';
  19.  
  20. return $li; 
  21. }
  22. ?>
sf
Jeśli w ten sposób nie umiesz sobie poradzić to spróbuj rekurencji. Zapis jest zdecydowanie krótszy, bez ifów.
wiechol
Próbowałem już z rekruencją jednak również z mizernymi skutkami, dzięki rekurencji generowana jest odpowiednia kolejność wyświetlania kategorii / podkategorii.

Na razie nie mam siły i czasu na zabawę w e if-y ,pod koniec projektu spróbuje sie jeszcze raz z tym zmierzyć.

Pozdrawiam
Wiktor

P.S Poprawiłem zamieszczoną powyżej tablice, Windowsy z kategorii Win Vista miały level 3 a powinny mieć 2.
slick101
Wiechol spadles mi z nieba. Mam identyczny problem:

nie potrafie zrobic tego, ze jezeli oba elementy sa w tej samej galezi, maja ten sam odstep (sa w tym samym submenu) jak zwal tak zwal, to aby na poczatku element ktory bedzie rodzicem (ktory bedzie mial pod soba inne pozycje wygenerowal sie jako:
  1. <?php
  2. <li>ta pozycja //tutaj znacznik nie jest zamykany bo bedzie submenu
  3.      <ul> //teraz otwieramy ul'a dla pozycji submenu
  4.             <li> sub pozycja 1</li> //te juz zamykamy
  5.             <li> sub pozycja 2</li> //te juz zamykamy
  6.      </ul> //teraz zamykamy ul'a dla pozycji submenu
  7. </li> //i dopiero zamykamy tego glownego li
  8. ?>

kolejne zagniezdzone <ul>:

http://i33.tinypic.com/dxy9gw.png

Oto kawalek kodu przy ktorym walcze:

  1. <?php
  2. function rosnaco($a, $b) {
  3.  return strcmp(strtolower($a["nazwa"]), strtolower($b["nazwa"]));
  4. }
  5. function malejaco($b, $a) {
  6.  return strcmp(strtolower($a["nazwa"]), strtolower($b["nazwa"]));
  7. }
  8.  
  9. function pokaz($id)
  10. {
  11.    global $wciecie, $t;
  12.    $wciecie++;
  13.    
  14.    $wynik = array();
  15.    foreach ($t as $element)
  16.    {
  17.        if ($element['rodzic'] == $id)
  18.        {
  19.            $wynik[] = $element;
  20.        }
  21.    }
  22.    usort($wynik, "rosnaco");
  23.    
  24.    foreach ($wynik as $element)
  25.    {
  26.        /* $odstep = str_repeat("&nbsp;&nbsp;&nbsp;", $wciecie-1);
  27.             echo "$odstep - {$element["nazwa"]}<br />";
  28.             pokaz($element["id"]); */
  29.  
  30.        echo ('<li>('.$wciecie.') - '.$element['nazwa'].'</li>');
  31.        pokaz($element['id']);
  32.    }
  33.    $wciecie--;
  34. }
  35.  
  36. //$wynik = mysql_query("SELECT menu_test.id, menu_test.id_rodzic, menu_test.link, menu_test.poziom, biblioteka.tytul
  37. FROM biblioteka biblioteka, menu_test menu_test WHERE menu_test.link = biblioteka.id");
  38.  
  39. $wynik = mysql_query("SELECT * FROM kategorie");
  40.  
  41. if ($wynik)
  42. {
  43.    while($dane = mysql_fetch_array($wynik))
  44.    {
  45.        //$t[] = array("id"=>$dane["id"], "rodzic"=>$dane["id_rodzic"], "nazwa"=>$dane["tytul"], "poziom"=>$dane["poziom"]);
  46.        $t[] = array("id"=>$dane["id"], "rodzic"=>$dane["rodzic"], "nazwa"=>$dane["nazwa"]);
  47.    }
  48. }
  49.  
  50. echo ('<strong>Korzeń menu:</strong>');
  51. echo ('<ul id="menu_component">');
  52. pokaz(0);
  53. echo ('</ul>');
  54. ?>


To co jest zakomentowane to moje modyfikacje ktorymi prosze sie nie sugerowac, domyslnie dla pomocy kod korzysta z tabeli Dariusza: http://scarlet00.republika.pl/kategorie.sql

Za cholere nie wiem gdzie przy tych foreach'ach powstawiac warunki if zeby mi generowaly to o czym napisalem. Prosze o jakas pomoc i z gory dziekuje.

Czy poradziles juz sobie z tym problemem i mozesz mi pomoc?
Zyx
slick101 -> z tak pobranych danych bez dodatkowej obróbki raczej drzewa nie wygenerujesz. Sposób zapisywania w bazie polecam zmienić, np. tak, by wykorzystywał algorytm przechodzenia drzewa zmodyfikowaną metodą preorder. Implementacja od strony kodu jest dość złożona, ale za to oferuje bardzo wydajne pobieranie. Podczas pobierania ponadto otrzymujesz informację o głębokości każdego węzła, którą można zastosować do wyświetlania. Algorytm jest wtedy bardzo prosty. W każdej iteracji pętli po liście pamiętamy obecny i poprzedni element listy. Postępujemy następująco (wiechol, przeczytaj uważnie, bo zauważyłem, że w Twoim kodzie próbujesz właśnie w takim kierunku iść - jeśli wszystko załapiesz, to problem masz rozwiązany):

1. Jeśli current.depth = previous.depth, wtedy zamykamy LI dla poprzedniego elementu, otwieramy znacznik LI dla nowego i wyświetlamy element current. Nie zamykamy go jednak.
2. Jeśli current.depth > previous.depth, oznacza to, że wchodzimy do podelementu. Otwieramy więc UL, w nim LI i w nim dopiero treść. Nie zamykamy go.
3. Jeśli current.depth < previous.depth, wracamy do wyższego poziomu. Musimy wtedy wykonać tyle zamknięć /UL i /LI, ile wynosi różnica między obiema głębokościami. Następnie otwieramy nowy LI i wyświetlamy current.

PS. System szablonów OPT posiada wbudowaną obsługę wyświetlania takich drzew smile.gif.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.