Avatar billede tchami Nybegynder
25. august 2003 - 08:55 Der er 22 kommentarer og
3 løsninger

Træstruktur menu hentet fra MySQL DB

Hej,

Nu har jeg i lang tid været lidt utilfreds med min nuværende måde at udskrive min menu på, og efter at have læst flere artikler om emnet må jeg give fortabt. Jeg kan simpelthen ikke overskue hvordan det gøres smartere.

Min tabel ser således ud:

pid # parent_pid # menu_sortorder # node
1  #    0     #    1      #  0
2  #    0    #    2      #  0
3  #    0    #    3      #  0
4  #    0    #    4      #  0
5  #    0    #    5      #  0
6  #    0    #    6      #  0
7  #    1    #    1      #  1
8  #    1    #    2      #  1
9  #    8    #    1      #  2
10  #    8    #    1      #  2

"pid" er bare et auto-id, "parent_pid" er den enkelte pids parent id (og altså 0 hvis der ikke er en parent), "menu_sortorder" er den rækkefølge de står i og endelig er "node" det node-level den enkelte pid står på. Ud fra overstående tabel skulle der gerne komme dette ud:

Velkommen
    - Dansk sub 
        - dansk sub sub 
        - dansk asdasd 
    - Dansk sub 2 
Dansk Hovedpunkt 2

Det går også fint i øjeblikket, men jeg bruger en rekursiv funktion hvilket betyder at jeg får en masse sql opslag og det vil jeg egentlig gerne slippe for. Nuværende kode ser (meget pseudo agtigt) ud sådan her

Sub subWriteMenu(med parametre)

    strSelectMenuItemsSQL = SQL-sætning...
    Set objMenuRS = Conn.Execute(strSelectMenuItemsSQL)

        Do While Not objMenuRS.EOF OR objMenuRS.BOF

            Response.Write menupunkt info..
            Call subWriteMenu(med parametre)

        objMenuRS.MoveNext
        Loop

    objMenuRS.Close
    Set objMenuRS = Nothing

End Sub

Det er simpelthent for dumt jo, så 200 point til den der kan hjælpe mig.
Avatar billede hnteknik Novice
25. august 2003 - 09:35 #1
>>tchami

Jeg tror, at jeg har skrevet om det andetsteds her på siten.

http://www.dhtmlcentral.com/projects/coolmenus/
har et udmærket script til dannelse af træstrukturer.

Det er faktisk den samme menu som de anvender her på Eksperten

Jeg har lavet en rutine til indlæsning og rettelse af træstrukturen baseret på data fra MYSQL.

Thomas has his own example on how to get data from a database:
http://www.dhtmlcentral.com/projects/coolmenus/examples/asp-example/jscript.asp

Henrik
Avatar billede eagleeye Praktikant
25. august 2003 - 09:36 #2
Du må ud i sådan SQL som denne, dog kan den ikke Tage X antal dybter som en rekrusiv funktion kan så den er lave med 1 hovemenu og 2 submenuer som du har vist:

SQL = "SELECT T1.pid, T1.navn as navn1, T2.pid, T2.navn as navn2 T3.pid, T3.navn as navn3 FROM (tblMenuItem AS T1 LEFT JOIN tblMenuItem AS T2 ON tblMenuItem.pid = T2.parent_pid) LEFT JOIN tblMenuItem AS T3 ON T2.pid = T3.parent_pid WHERE T1.parent_pid=0 ORDER BY T1.menu_sortorder, T2.menu_sortorder, T3.menu_sortorder;"

Set rs = Connection.Execute(SQL)

oldMenu1 = ""
oldMenu2 = ""
do while not rs.EOF
  if oldMenu1 <> rs("navn1") then
    Response.Write rs("navn1") & "<br>"
    oldMenu1 = rs("navn1")
  end if
  if oldMenu2 <> rs("navn2") then
    Response.Write "&nbsp;&nbsp;&nbsp;-" & rs("navn2") & "<br>"
    oldMenu2 = rs("navn2")
  end if

  Response.Write "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-" & rs("navn3") & "<br>"
  rs.Movenext
loop
Avatar billede eagleeye Praktikant
25. august 2003 - 09:38 #3
Glemte at skrive jeg er ikke helt sikker på ORDER BY delen virekr som den skal, da den laver ORDER på det hele og ikke laver ORDER på en lille de af gangen.
Avatar billede tchami Nybegynder
25. august 2003 - 09:43 #4
hnteknik > Det er coolmenus jeg bruger, så jeg vil meget gerne se den rutine du bruger. Har også godt set på det eksempel han har lavet, men syntes der var et eller andet ved det der ikke duede... Hmm, checker lige igen.

eagleeye > Tak for svaret, men den skal kunne tage X antal dybder :/
Avatar billede eagleeye Praktikant
25. august 2003 - 09:50 #5
Når du bringer X eller uendelig ind i billedet så har du automatisk sagt rekursiv. Du kan udvide mit script til 10 levels
Avatar billede eagleeye Praktikant
25. august 2003 - 09:50 #6
og så er 10 = X.
Avatar billede hnteknik Novice
25. august 2003 - 09:51 #7
>>tchami

Jeg har koden derhjemme. Flyr dig den i aften.
Min er lidt udvidet, da den dles håndterer 5 sikkerhedsniveauer og gemmer resultatet i en appl. variabel så den kun skal læses ved opdatering og hvis variablen er nullet af serveren.

Henrik
Avatar billede hnteknik Novice
25. august 2003 - 09:55 #8
Hvis du anvender Coolmenus, så tager den jo højde for det 'recursive' og du skal blot sørge for at fodre scriptet med data fra databassen.
Avatar billede tchami Nybegynder
25. august 2003 - 10:02 #9
>>hnteknik  Ja det gør den, men det er jo kun i det øjeblik at man udskriver dhtml-menuen. Hvis du f.eks. ville bruge den til at udskrive et sitemap på skærmen duer det ikke er jeg bange for. Har lige testet eksemplet fra dhtmlcentral.com og her kommer outputtet til at se således ud:

oCMenu.makeMenu('m1','','1','0')
oCMenu.makeMenu('m76','','2','0')
oCMenu.makeMenu('m77','','6','0')
oCMenu.makeMenu('m78','','5','0')
oCMenu.makeMenu('m79','','4','0')
oCMenu.makeMenu('m80','','3','0')
oCMenu.makeMenu('m73','m1','1','1')
oCMenu.makeMenu('m75','m1','2','1')
oCMenu.makeMenu('m74','m73','1','2')
oCMenu.makeMenu('m94','m73','2','2')

Det er jo fint nok så længe det er dhtml-menuen, men når det bare er selve træstrukturen der skal udskrives skulle den jo se således ud:

oCMenu.makeMenu('m1','','1','0')
oCMenu.makeMenu('m73','m1','1','1')
oCMenu.makeMenu('m74','m73','1','2')
oCMenu.makeMenu('m94','m73','2','2')
oCMenu.makeMenu('m75','m1','2','1')
oCMenu.makeMenu('m76','','2','0')
oCMenu.makeMenu('m77','','6','0')
oCMenu.makeMenu('m78','','5','0')
oCMenu.makeMenu('m79','','4','0')
oCMenu.makeMenu('m80','','3','0')

men det kan man (læs jeg) i hvert fald ikke få den til.

>> eagleeye Hmmm, det har du selvfølgelig ret i, men kunne man ikke f.eks. lave et opslag der fandt max node og derefter opbygge én sql-sætning? Det er godt to opslag, men langt færre end nu hvor den laver et opslag pr. record.
Avatar billede eagleeye Praktikant
25. august 2003 - 10:07 #10
hnteknik, du skal da have smidt data fra DB'en ind i cool menu så bliver det vel også rekrusive kald for det eller kan coolmenu acceptere et array som DB layoutet der er vist?
Avatar billede eagleeye Praktikant
25. august 2003 - 10:08 #11
tchami >> Jo man kan slå op og se hvor max dybten er da du har kolonnen note.
Så kan m,an lave et script som ud fra den note laver en SQL sætning som kan hendte det hele.
Avatar billede hnteknik Novice
25. august 2003 - 10:14 #12
>>tchami

Ååååååh der er en site oversigt du er ude efter.
Jeg bruger ikke selv sådan en, men den kan vel effektivt laves ved at
læse variablerne ind i en array og sortér det ud recursivt ( og så gemme det i en appl. variabel (for hvert sikkerhedsniveau)).

Det må jeg lige tænke over - jeg er som sagt på arbejde.

Henrik
Avatar billede hnteknik Novice
25. august 2003 - 10:22 #13
>>eagleeye
Jeg mener at coolmenu selv sørger for det recursive. Jeg checkede lige en af kundernes webstrukturer - jo den finder selv ud af det recursive:

oM.makeMenu('m1','','Forside','webpage/showpage.asp?SCID=2')
oM.makeMenu('m8','m1','Hvem er vi ?','')
oM.makeMenu('m9','m1','Medlemskab','')
oM.makeMenu('m75','m1','Hvis du er Ny','webpage/showpage.asp?scID=28')
oM.makeMenu('m15','m8','Bestyrelsen','webpage/showpage.asp?scID=13')
oM.makeMenu('m16','m8','Vedtægter','webpage/showpage.asp?scID=14')
oM.makeMenu('m17','m8','Tillidsorganisation','webpage/showpage.asp?scID=27')
oM.makeMenu('m79','m8','Hvem er vi ?','webpage/showpage.asp?scID=15')
oM.makeMenu('m11','m9','Indmeldelse','webpage/showpage.asp?scID=18')
oM.makeMenu('m12','m9','Udmeldelse','webpage/showpage.asp?scID=19')
oM.makeMenu('m13','m9','Kontingent','webpage/showpage.asp?scID=20')
oM.makeMenu('m14','m9','Link til YYY,'','','','','','','','','','','','var abc=window.open("http://www.zzz.dk/","abc","width=800,height=600,scrollbars=yes,location=yes,resizable=yes,status=yes,menubar=yes,toolbar=yes");abc.window.focus();')
oM.makeMenu('m0','','Log ind','/adm/apw.asp')

Hvis man vil lave strukturen ud fra en arraysortering, kan man jo kigge i
coolmenus sscriptcode og blive inspireret.

Henrik
Avatar billede tchami Nybegynder
25. august 2003 - 10:24 #14
eagleeye >> Mmm, håber ikke det er for meget at spørge om, men har du en idé til hvordan det så gøres?

hnteknik >> God arbejdslyst, jeg venter med spænding på svar.
Avatar billede eagleeye Praktikant
25. august 2003 - 10:34 #15
Ja jeg har et bud på koden som er helt utestet.

Prøv i første omgang at tjekke den laver en rigtig SQL sætning. Denne vil starte med T0 og ikke T1 som skrivet før.

Jeg kan kigge på det senere i eftermiddag..



SQL = SELECT max(node) FROM tblMenuItem"
Set rs = Conn.Execute(SQL)
maxNode = int(rs(0))

SQL = "SELECT "
for i = 0 to maxNode
  if i > 0 then SQL = SQL & ", "
  SQL = SQL "T" & i & ".navn as navn" & i "
next
SQL = SQL " FROM "
for i = 1 to maxNode
  SQL = SQL & "("
for i = 0 to maxNode-1
  if i = 0
    SQL = SQL & "tblMenuItem AS T" & i & " LEFT JOIN tblMenuItem AS T" & (i+1) & " ON T" & i & ".pid = T" & (i+1) & ".parent_pid"
  else
    SQL = SQL & ") LEFT JOIN tblMenuItem AS T" & (i+1) & " ON T" & i & ".pid = T" & (i+1) & ".parent_pid"
  end if
next
SQL = SQL & " WHERE T0.parent_pid=0 "
SQL = SQL & " ORDER BY "
for i = 0 to maxNode
  if i > 0 then SQL = SQL & ", "
  SQL = SQL & "T" & i
next

Response.Write SQL

Set rs = Connection.Execute(SQL)

redim oldMenu(maxNode)
do while not rs.EOF
  for i = 0 to ubound(oldMenu)
    if oldMenu(i) <> rs("navn"&i) then
      for t = 0 to i
        Response.Write "&npsp;&nbsp;"
      next
      if i > 0 then Response.Write "-"
      Response.Write rs("navn"&i) & "<br>"
      oldMenu(i) = rs("navn"&i)
    end if
  next
 
  rs.Movenext
loop
Avatar billede hnteknik Novice
25. august 2003 - 10:44 #16
>>tchami

Det du søger tror jeg svarer til hvad COOLjsTree PRO er i stand til

http://javascript.cooldev.com/scripts/cooltreepro/
COOLjsTree PRO -- possibility to keep tree structure in database

Som sagt må det kunne svare sig at læse det hele ind i en array og danne en ny array ved recursive kald ned i den første og derefter bruge den anden array til whatever script.

Henrik
Avatar billede hnteknik Novice
25. august 2003 - 12:21 #17
Der er lidt læsestof om jeres SQL forsøg her:

http://www.4guysfromrolla.com/webtech/sqlguru/q022000-2.shtml
Avatar billede hnteknik Novice
25. august 2003 - 12:36 #18
Avatar billede tchami Nybegynder
25. august 2003 - 13:34 #19
Takker mange gange for spændende læsestof Henrik, men jeg tror jeg prøver eagleeyes idé, selvom det godt nok er en noget drilsk sql-sætning (som jeg i hvert fald ikke lige på stående fod kan overskue)..
Avatar billede hnteknik Novice
25. august 2003 - 13:53 #20
Jamen god fornøjelse. Ellers skal man over i noget XML eller Access 2000.

Jeg går ned på lavt blus mht javascript recursiv sortering

Henrik
Avatar billede eagleeye Praktikant
25. august 2003 - 15:21 #21
Jeg er kommet i tanke om en anden metode som bruger et array og et recordset.
Bemrærk: Koden er utestet..


Set rs = Server.CreateObject("ADODB.RecordSet")
SQL = "SELECT pid, parent_pid, menu_sortorder, node, navn FROM tblMenuItems"
rs.Open SQL, Conn,1,3

rs.Filter = "parent_pid='0'"
rs.Sort = "menu_sortorder"

parent_pid_arr = rs.GetRows()

for i = 0 to ubound(parent_pid_arr,2)
  main_pid = parent_pid_arr(0,i)
  respone.write parent_pid_arr(4,i) & "<br>"
  makeTree (main_pid, 1)

next


sub makeTree(parent_id, level)
  rs.Filter = "parent_pid='" & parent_id & "' AND pid>'0'"
  do while not rs.EOF
    id=rs("pid")
    rs("pid") = 0
    for i = 0 to level
      Response.Write "&nbsp;&nbsp;"
    end if
    Response.Write "-" & rs("navn")
    makeTree (id,level+1)
    rs.Filter = "parent_pid='" & parent_id & "' AND pid>'0'"
    if not rs.EOF then
      'Jeg er lidt i tvivl om denne movenext ikke måske skal fjernes,
      'men i første omgang skal den med.
      rs.Movenext
    end if
  loop
end sub



Jeg vil selv lige prøve dette stidste styk kode når jeg kommer hjem.
Avatar billede thomas_yde Nybegynder
25. august 2003 - 16:04 #22
Jamen til dette er det oplagt at bruge en rekursiv funktion, og som activedeveloper.dk har skrevet en artikel omkring:
http://activedeveloper.dk/aspdigital/2001081401.asp


koden for de dovne:
Et lille eksempel herpå laver vi et lille rekursivt system.
Systemet er lig det der bruges i mange menusystemer

id      headline  parentid
autoid  tekst      tal

parentid skal forståes som værende den id vores record hører under. Hvis fx. en record er sub til en record med id=10, så vil skal der stå 10 i parentid. Hvis vores record er toppunkt, så skal der stå 0 i parentid

Nu begynder scriptet. Det vil løbende blive forklaret.

<%
'\\ først hentes data ind og ligges i et array
sqlTable = "SELECT id,headline,parentid FROM tabel"

'\\ connection til db
con = DIN_CONNECTION_HER
set rs = server.createobject("adodb.recordset")
rs.open sqlTable, con

if not rs.eof then
  arrRecords = rs.getrows()
  '\\ som noget nyt kalder vi en funktion til at vise vores records.
  response.write buildTop(arrRecords)
end if
rs.Close
Set rs = Nothing

'\\ først vores funktion der henter alle toppunkter ud
function buildTop(arrRecords)
  strDisplayTop = ""
    for i=0 to ubound(arrResult,2)
    '\\ hent records hvor parentid = 0
    if arrRecords (2,i) = 0 then
      strDisplayTop = strDisplayTop & arrRecords(1,i) & "<br>" & vbcrlf
      strDisplayTop = strDisplayTop & buildSub(arrRecords,arrRecords(0,i),0)
    end if
  next
  buildTop = strDisplayTop
end function

'\\ vores funktion til at bygge subs
function buildSub(arrRecords,intParentid,intIndent)
  for j=0 to ubound(arrResult,2)
    '\\ her looper vi igennem vores array for at finde de records
    '\\ der er sub til vores parent record
    if arrRecords(2,j) = intParentid then
      '\\ her opbygger vi vores "indrykning"
      strIndent = ""
      for x=0 to intIndent
        strIndent = strIndent & "&nbsp;"
      next
      '\\ og her opbygges vores streng med subs, samt henter subs til subs ... osv
      strDisplaySub = strDisplaySub & arrRecords(1,j) & "<br>" & vbcrlf
      strDisplaySub = strDisplaySub & buildSub(arrRecords,arrRecords(0,j),intIndent+1)
    end if
  next
  buildSub = strDisplaySub
end function
%>
Avatar billede tchami Nybegynder
26. august 2003 - 15:33 #23
Thomas' løsning ser ud til at virke helt perfekt :) Én select og jeg får det udskrevet som jeg vil.

>> Thomas Yde smid et svar og jeg deler pointene mellem jer
Avatar billede thomas_yde Nybegynder
26. august 2003 - 17:16 #24
Det var så lidt.
Avatar billede hnteknik Novice
26. august 2003 - 21:18 #25
Fint nok - takker

Jeg ville recursivt sortere arrRecords over i en resultarray og
ja fodre den til scriptet i cooltree. Det ville tja se mere cool ud med en interaktiv site oversigt. Jeg mener ikke pro udgaven er freeware. Happy programming

Henrik
"The best way to accelerate Lotus Notes is at 9.8 m/s^2 "
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