Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Poprawne generowanie zagnieżdżonych list ul
wiechol
post
Post #1





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 12.03.2006

Ostrzeżenie: (0%)
-----


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. ?>


Ten post edytował wiechol 20.08.2007, 19:34:12
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 4)
sf
post
Post #2





Grupa: Zarejestrowani
Postów: 1 597
Pomógł: 30
Dołączył: 19.02.2003
Skąd: Tychy

Ostrzeżenie: (0%)
-----


Jeśli w ten sposób nie umiesz sobie poradzić to spróbuj rekurencji. Zapis jest zdecydowanie krótszy, bez ifów.


--------------------
Zapraszam na mój php blog, tworzenie stron.
Go to the top of the page
+Quote Post
wiechol
post
Post #3





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 12.03.2006

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
slick101
post
Post #4





Grupa: Zarejestrowani
Postów: 1
Pomógł: 0
Dołączył: 28.10.2008

Ostrzeżenie: (0%)
-----


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?
Go to the top of the page
+Quote Post
Zyx
post
Post #5





Grupa: Zarejestrowani
Postów: 952
Pomógł: 154
Dołączył: 20.01.2007
Skąd: /dev/oracle

Ostrzeżenie: (0%)
-----


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.


--------------------
Specjalista ds. głupich i beznadziejnych, Zyx
Nowości wydawnicze: Open Power Collector 3.0.1.0 | Open Power Autoloader 3.0.3.0
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 19.08.2025 - 19:50