Avatar billede razser Nybegynder
03. april 2005 - 11:06 Der er 11 kommentarer og
1 løsning

Venstre-menu med rekursiv funktion

På et website trækker jeg top-menupunkter ud af en database (pages.mdb).

Felterne i databasen hedder:

PageID  ParentPageID    MenuText.
1        0      Et eller andet
2        0      Et eller andet
3        1      Et eller andet
4        2      Et eller andet
5        3      Et eller andet
etc.

PageID er sidens unikke ID; ParentPageID viser hvor siden hører til (værdien er 0 for hovedmenu-punkter), og MenuText er teksten på menu-punktet (fx. Om os, Produkter, Kontakt etc.)

Når man klikker på et hovedmenupunkt, skal undermenupunkterne hertil vises i venstre side. Klikker man på et undermenupunkt, hvor der er tilknytter et 3. niveau vises disse, når man klikker på menu-punktet (som en træstruktur).

Menupunktet skal være markeret, når man klikker på det, og det er vigtigt, at alt kan ske ved brug af kun én ID - med andre ord en rekursiv funktion, der fastlægger hvor i "hierkarkiet" menupunktet er, og som kan udvides med flere niveauer.

Er der nogen, der har et bud på hvordan man kan konstruere en sådan funktion?

(Jeg vil helst undgå JavaScript - hvis muligt).
Avatar billede jsc Nybegynder
03. april 2005 - 11:12 #1
jeg har lavet en engang... prøver lige at se om jeg kan støve den op.

/jsc
Avatar billede jsc Nybegynder
03. april 2005 - 11:14 #2
prøv at tjek den her:

http://sixhoej.dk/dl/menu.zip

/jsc
Avatar billede razser Nybegynder
03. april 2005 - 11:25 #3
Tak for svaret. Det er dog ikke lige det jeg eftersøger, eftersom jeg kun benytter en tabel til alle menupunkterne. Det er samtidigt væsentligt for opgaven, at der kun er én ID i adresselinien. I dit eksempel kan adresselinien blive meget lang, hvis der er endnu flere niveuaer ... (menu.asp?view=HTX&view2=Lektier&site=Lektier) ...
Avatar billede jsc Nybegynder
03. april 2005 - 11:32 #4
ja, det er selvfølgelig rigtigt... jeg venter lige med at komme med en løsning, hvis der er andre der har en.

/jsc
Avatar billede weiland Nybegynder
03. april 2005 - 14:04 #5
Hvis du får overleveret et PageID fra adresselinien, kan venstremenuen klares således:
Det er faktisk en temmelig omstændelig proces :-) Hvert fald som jeg løser det... men det kan sikkert gøres smartere...

Du skal først finde antallet af niveauer og deres ID-numre.


if request(PageID) <> "" then
   
    'finder ud af antallet af niveauer og deres ID-numre
   
    Set rsOpslag = MyConn.Execute("SELECT * FROM Pages WHERE PageId = "& PageID &"")
   
        strParent = ""& rsOpslag("PageID") &"§"
        strParent = strParent & ""& GetParent(rsOpslag("ParentPageID")) &""
       
        '§-tegnet er skrevet mellem alle tal
        'vi fjerner det sidste §
        strParent = left(strParent,len(strParent)-1)
       
        'hvornår kommer der et §-tegn (fra højre)?
        LastSign = InStrRev(strParent,"§")
       
        'hvis der er ikke er noget §-tegn, er der klikket på et niveau0-link
        if LastSign = 0 then
            LevelOneID = strParent
            LevelTwoID = ""
        else
            'ParentID er det sidste tal
            LevelOneID = Mid(strParent,LastSign+1)
           
            'Niveau2 er det næstsidste tal
            'vi fjerner LevelOneID og det sidste §
            strParent = left(strParent,len(strParent)-(len(LevelOneID)+1))
           
            'sætter tilgæld et § ind i starten
            strParent = "§" & strParent
           
            'hvornår kommer der et §-tegn (fra højre)?
            LastSign = InStrRev(strParent,"§")
       
            'Niveau2 er nu det sidste tal
            LevelTwoID = Mid(strParent,LastSign+1)
           
                'hvis længden af strParent nu er længere end en karakter (altså §)
                'så er der også et niveau3
                if len(strParent) > 1 then
               
                    'Niveau3 er det næstsidste tal
                    'vi fjerner LevelTwoID og det sidste §
                    strParent = left(strParent,len(strParent)-(len(LevelTwoID)+1))
       
                    'hvornår kommer der et §-tegn (fra højre)?
                    LastSign = InStrRev(strParent,"§")
                   
                    'Niveau3 er nu det sidste tal
                    LevelThreeID = Mid(strParent,LastSign+1)
                       
                        'hvis længden af strParent nu er længere end en karakter (altså §)
                        'så er der også et niveau4
                        if len(strParent) > 1 then
                       
                            'Niveau4 er det næstsidste tal
                            'vi fjerner LevelThreeID og det sidste §
                            strParent = left(strParent,len(strParent)-(len(LevelThreeID)+1))
               
                            'hvornår kommer der et §-tegn (fra højre)?
                            LastSign = InStrRev(strParent,"§")
                           
                            'Niveau4 er nu det sidste tal
                            LevelFourID = Mid(strParent,LastSign+1)
                        end if
                   
                end if
           
        end if

    rsOpslag.Close
    Set rsOpslag = Nothing
end if

I ovenstående bruges en rekursiv funktion, der hedder GetParent. Den ser således ud:

Function GetParent(Id)
Dim strParent
   
  'finder niveau0 til den aktuelle side, hvis et ID er angivet
      SQL = "SELECT PageID,ParentPageID FROM Pages WHERE (PageID = "& Id &")"
      Set oRS = MyConn.Execute(SQL)
          If oRS.EOF Or oRS.BOF OR (Id = 0) then
              strParent = ""
          Else
              While not oRS.EOF
                    strParent = strParent & ""& oRS("PageID") &"§"
                  If not GetParent(oRS("ParentPageId")) = "" Then
                      strParent = strParent & GetParent(oRS("ParentPageId")) & ""
                  End If
              oRS.MoveNext
              wend
          End If
      oRS.Close
      Set oRS = Nothing
     
      GetParent = strParent
End Function


Når du således har fundet antallet af niveauer og deres ID-numre, så går du videre med:

SelectedPage = request("PageID")
if SelectedPage <> "" then
   
   
        response.write "<div class=""menu"">"

                response.write LevelTwo(SelectedPage)

        response.write "</div>"

end if


Der kaldes en funktion, som hedder LevelTwo. Den ser således ud:


Function LevelTwo(PageID)

    'vi finder niveau2 sider til den valgte side. De skrives i menuen

    SQL = "SELECT * FROM Pages WHERE ParentPageID = "& LevelOneID &" "
   

    Set rsLevelTwo = MyConn.Execute(SQL)
           
    while not rsLevelTwo.eof
   
        strLevelTwo = strLevelTwo & "<div class=""LevelTwo"">"
        strLevelTwo = strLevelTwo & "<a href=""default.asp?PageID="& rsLevelTwo("PageID") &""""
           
            if cint(rsLevelTwo("PageID")) = cint(request("PageID")) then
                strLevelTwo = strLevelTwo & " class=""SelectedLevelTwo"""
            end if
                       
                       
            strLevelTwo = strLevelTwo & ">"& rsLevelTwo("Title") &""
            strLevelTwo = strLevelTwo & "</a>"
            strLevelTwo = strLevelTwo & "</div>"
               
            if LevelTwoID <> "" then
                if cint(LevelTwoID) = cint(rsLevelTwo("PageID")) then
                    strLevelTwo = strLevelTwo & ""& LevelThree(rsLevelTwo("PageID")) &""
                end if
            end if
               
               
    rsLevelTwo.MoveNext
    wend
           
       
    rsLevelTwo.Close
    Set rsLevelTwo = Nothing
   
    LevelTwo = strLevelTwo

End Function

Bemærk, at hvis cint(LevelTwoID) = cint(rsLevelTwo("PageID")), så kaldes funktionen LevelThree, som til forveksling ligner

funktionen LevelTwo:

Function LevelThree(PageID)

    'vi finder undersider til den valgte. De skrives i menuen

    SQL = "SELECT * FROM Pages WHERE ParentPageID = "& PageID &""   

    Set rsLevelThree = MyConn.Execute(SQL)
       
        while not rsLevelThree.eof
            strLevelThree = strLevelThree & "<div class=""LevelThree"">"
            strLevelThree = strLevelThree & "<a href=""default.asp?PageID="& rsLevelThree("PageID") &""""
   

            if cint(rsLevelThree("PageID")) = cint(request("PageID")) then
                strLevelThree = strLevelThree & " class=""SelectedLevelThree"""
            end if
                       
           
            strLevelThree = strLevelThree & ">&#8226; "& rsLevelThree("Title") &""
            strLevelThree = strLevelThree & "</a>"
            strLevelThree = strLevelThree & "</div>"
               
            if LevelThreeID <> "" then
                if cint(LevelThreeID) = cint(rsLevelThree("PageID")) then
                    strLevelThree = strLevelThree & ""& LevelFour(rsLevelThree("PageID")) &""
                end if
            end if
                           
            rsLevelThree.MoveNext
            wend
               
   
       
        rsLevelThree.Close
        Set rsLevelThree = Nothing
   
        LevelThree = strLevelThree

End Function


På tilsvarende vis kaldes her funktionen LevelFour. Og sådan kan man blive ved.... :-)
Fremhævningen af menupunktet sker ved tildeling af en css-class, fx class="SelectedLevelThree"
Avatar billede razser Nybegynder
03. april 2005 - 18:47 #6
Tak for besvarelsen. Det virker helt efter beskrivelsen. Så læg blot et svar.

Måske er det muligt at optimere scriptet til kun at indeholde én funktion - i stedet for at lave en for hvert niveau.....?

Noget med: for x= 1 to ubound(PageID)
strLevel = strLevel + 1
....
..
.

Sluttelig: Ved du "tilfældigvis" hvordan man i topmenuen kan genbruge informationen om, hvilke undermenupunkter, der hører derunder - sådan at forstå, at når man klikker på et menupunkt i venstre-menuen, så highlightes hovedmenupunktet i topmenuen også??
Avatar billede jsc Nybegynder
03. april 2005 - 18:50 #7
hvis du ikke vil have flere variabler i URL'en, så kunne du måske bruge en "referer"

/jsc
Avatar billede weiland Nybegynder
03. april 2005 - 18:53 #8
Tja, hvis du laver sådan en funktion, så giver jeg DIG 200 points :-)

hmmm.... highlightning af hovedmenupunktet? Det må så være LevelOneID, hvis vi kigger på det ovenstående..
Og når du kender LevelOneID, så er det jo bare at sammenligne..

if hovedmenupunkt = LevelOneID then....
Avatar billede jsc Nybegynder
03. april 2005 - 18:54 #9
ja, det kunne være man selv skulle igang (en opfording)...

/jsc
Avatar billede razser Nybegynder
03. april 2005 - 19:17 #10
-> weiland: jeg skal nok sige til, hvis det nogen sinde lykkes at lave funktionen om til én ;-)

Jeg er ikke helt med ang. highlight af hovedmenupunktet - vil dog gerne oprette det som et nyt spørgsmål.

Jeg kan ikke rigtigt se hvor i f.eks. Function LevelThree(PageID), at det enkelte menupunkt hører under et givent hovedmenupunkt. Skal der lægges en streng ind som man requester i topmenu-siden (jeg benytter include-filer)?

If Cint(rs("PageID")) = Cint(strPageID) OR ".....xxx....."  Then
Avatar billede weiland Nybegynder
04. april 2005 - 16:41 #11
Det er her, at man finder LevelOneID:

Set rsOpslag = MyConn.Execute("SELECT * FROM Pages WHERE PageId = "& PageID &"")
   
        strParent = ""& rsOpslag("PageID") &"§"
        strParent = strParent & ""& GetParent(rsOpslag("ParentPageID")) &""
       
        '§-tegnet er skrevet mellem alle tal
        'vi fjerner det sidste §
        strParent = left(strParent,len(strParent)-1)
       
        'hvornår kommer der et §-tegn (fra højre)?
        LastSign = InStrRev(strParent,"§")
       
        'hvis der er ikke er noget §-tegn, er der klikket på et niveau0-link
        if LastSign = 0 then
            LevelOneID = strParent
            LevelTwoID = ""
        else
            'ParentID er det sidste tal
            LevelOneID = Mid(strParent,LastSign+1)


LevelOneID's er kendetegnet ved, at de har ParentPageID = 0
Altså lissom dine topmenupunkter.
LevelOneID'erne sog topmenupunterne er med andre ord identiske.

Hvis du skal se, hvilket topmenupunkt der skal fremhæves, skal du således sammenligne med det LevelOneID, som ovenstående finder frem til.

if topmenupunkt = LevelOneID then
  response.write "<b>topmenupunkt</b>"
else
  response.write "topmenupunkt"
end if
Avatar billede razser Nybegynder
04. april 2005 - 21:13 #12
-> weiland, tak for hjælpen :)

Du bedes lægge et svar på http://www.eksperten.dk/spm/606466 - der er ekstra-points...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester