[Javascript] Client-side boomstructuur doorlopen

Pagina: 1
Acties:

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
In een form heb ik de volgende select staan:
HTML:
1
2
3
4
5
6
7
8
9
10
<select>
<option value=23>Winkel</option>
<option value=28>&nbsp;Kleding</option>
<option value=56>&nbsp;&nbsp;Dames</option>
<option value=57>&nbsp;&nbsp;Heren</option>
<option value=61>&nbsp;&nbsp;&nbsp;Broeken</option>
<option value=62>&nbsp;&nbsp;&nbsp;Schoenen</option>
<option value=25>&nbsp;Electronica</option>
<option value=93>&nbsp;&nbsp;Computers</option>
</select>

Dit geeft de volgende HTML output:
code:
1
2
3
4
5
6
7
8
9
10
+----------------+
| Winkel         |
|   Kleding      |
|     Dames      |
|     Heren      |
|       Broeken  |
|       Schoenen |
|   Electronica  |
|     Computers  |
+----------------+

Je begrijpt, ik trek hier een boomstructuur uit een database. De values van de options zijn de id's van de categorien in de database.

Nu wil ik graag een tekstveld aan dit form toevoegen, waar het pad naar een node in komt te staan zodra ik een categorie in de select box aanklik. Met andere woorden: als ik op "Schoenen" klik, moet het tekstveld er als volgt uitzien:
code:
1
2
3
+-------------------------------------+
| Winkel > Kleding > Heren > Schoenen |
+-------------------------------------+

Om dit serverside te doen lukt me wel; via een recursieve functie loop ik de child - parent relaties na. Ik heb alleen problemen om hetzelfde clientside op te lossen.

Ik zit al lang te denken en heb een basis idee, maar weet te weinig van javascript om te weten of dit ook werkelijk kan. Vandaar mijn vraag of iedereen die er meer van weet mij zou kunnen vertellen of er mogelijkheden zijn om dit op te lossen, en zo ja - misschien kun je een hint geven?

Idee
• Om de select box te indenten, gebruik ik &nbsp Als de boom een level dieper gaat, komt er 1 &nbsp bij.
• Als er een categorie geselecteerd wordt, kijk ik hoeveel &nbsp's er voor deze categorie staan (Schoenen bijvoorbeeld heeft 3 &nbsp's)
• Vervolgens ga ik door de options omhoog en noteer de eerste categorie die ik tegenkom met een nbsp minder (in dit geval "Heren" met twee &nbsp's)
• Deze stap herhaal ik tot ik bovenin de boom ben, waar er geen &nbsp voor de categorie staat (hier: "Winkel").
• De categorien heb ik tijdens dit proces opgeslagen in een array. Deze array bevat nu het pad van de geselecteerde categorie tot aan de root categorie
• Ik draai de array om, om het pad van root >> naar geselecteerde categorie te krijgen.

Wie schiet hier gaten in of helpt mij op weg?

[ Voor 7% gewijzigd door Reveller op 03-07-2004 22:35 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • HunterPro
  • Registratie: Juni 2001
  • Niet online
als jij op basis van het URL dat lijstje kunt 'terughalen', of ergens verstopt in een <input type=hidden> die gegevens kunt meegeven, is het zeker mogelijk met javascript. Maar waarom zou je 't niet lekker makkelijk server-side oplossen? :)

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Uiteindelijk komt er een grote boom in die select box te staan. Om categorien te editten, selecteert de admin er een en klikt vervolgens op een "edit" knop die hem naar een edit pagina brengt. Maar omdat een grote boom snel onoverzichtelijk kan worden in zo'n simpele weergave als een select box, wil ik een extra check invoeren voor de admin om te zien welke categorie hij geselecteert heeft. Daarvoor is dus dat tekstveld bedoelt. Als ik op elke klik de pagina moet reloaden om het pad server-side uit te rekenen, is dat niet erg gebruiksvriendelijk (en snel)... :)

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Verwijderd

Er is niets mis met deze opzet, al zou je ook een Array naar de browser kunnen sturen en dan met DOM functies het dropdown menu maken. Om dat het pad naar de parent te zoeken is dan erg makkelijk, maar de opzet zoals jij beschrijft in je startpost werkt ook prima.

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Ik heb nu het volgende uitgevonden:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
het aantal options in de select box: 
* document.form.list.options.length

het aantal stappen van de geselecteerde categorie tot de top (Winkel):
* document.form.list.options.length - 
(document.form.list.options.length-selectedItem)

het nummer van het geselecteerde item:
* selectedItem = document.form.list.selectedIndex

en verder:
* selectedText = document.form.list.options[selectedItem].value;

Ik zit nog met een heleboel vragen - zit er al een dag mee maar kom niet echt verder. Ik hoop dat sommigen mij wat verder kunnen helpen:

• hoe tel ik het aantal spaces voor geselecteerde categorie? Met javascript zoeken op ' ' werkt niet
• hoe bouw ik de loop die terug naar de root gaat, langs de categorien die telkens 1 space minder hebben voor hun naam?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Verwijderd

hoe bouw ik de loop die terug naar de root gaat, langs de categorien die telkens 1 space minder hebben voor hun naam?
Klopt als een bus...

Zal ik je dan maar uit de brand helpen? Kijk maar eens goed naar de code...
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<script type="text/javascript">

  function getPath(o) {
    var i = o.selectedIndex + 1;
    var aRet = new Array();
    var iNumT = null;

    while ( i-- ) {
      var sHTML = o.options[i].innerHTML;
      // Vervang alle &nbsp; voor een gewone spatie...
      sText = sHTML.replace( /\&nbsp;/g, " " );
      var t = 0;
      // Hier gaan we bepalen hoeveel spaties er voor de
      // tekst staan.
      while (sText.charCodeAt( t ) == 32) {
        t++;
      }
      // De eerste keer bevat iNumT nog geen waarde
      // Dat is dus de eerste ronde. Dan zetten we iNumT. iNumT
      // geeft aan hoeveel spaties het volgende bovenliggende
      // item moet hebben. Als die twee waardes gelijk zijn, dan
      // is het 100% zeker dat dat item de parent is.
      // Dat controleren of een item een parent is, gebeurt bij
      // de if(t == iNumT)
      if (iNumT == null) {
        iNumT = t - 1;
        aRet.unshift( sText.substr( t ) );
        continue;
      }
      if (t == iNumT) {
        // Parent is gevonden, de volgende parent heeft 1 spatie
        // minder dan de huidige, daarom verlagen we iNumT met 1
        iNumT--;
        aRet.unshift( sText.substr( t ) );
        if (t == 0) {
          break;
        }
      }
    }

    var sRet = "";
    // Nu hebben we dus een array met het complete pad. Van dat
    // pad maken we hier een string zoals je die graag wil.

    // Bedankt voor het wakker schudden Blues...
    sRet = aRet.join(" > ");
    return (sRet);
  }
</script>

<select onchange="alert(getPath(this));">
  <option value=23>Winkel</option>
  <option value=28>&nbsp;Kleding</option>
  <option value=56>&nbsp;&nbsp;Dames</option>
  <option value=57>&nbsp;&nbsp;Heren</option>
  <option value=61>&nbsp;&nbsp;&nbsp;Broeken</option>
  <option value=62>&nbsp;&nbsp;&nbsp;Schoenen</option>
  <option value=25>&nbsp;Electronica</option>
  <option value=93>&nbsp;&nbsp;Computers</option>
</select>

[ Voor 55% gewijzigd door Verwijderd op 05-07-2004 15:17 ]


Verwijderd

code:
1
2
3
4
5
6
for (var i = 0; i < aRet.length; i++) {
      sRet += aRet[i];
      if (i != aRet.length - 1) {
        sRet += " > ";
      }
    }

Kan ook zo:
code:
1
sRet = aRet.join(' > ');



;)

Verwijderd

|:( O-)

  • oh,when?
  • Registratie: April 2000
  • Niet online

oh,when?

...

"You're only as good, as what you did last week."


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
@Jorgen - dank je wel! De code zoals in je voorlaatste post vermeld werkte niet. Maar toen ik de wijziging van Blues ongedaan maakte, werkte het perfect :)
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<script type="text/javascript">

  function getPath(o) {
    var i = o.selectedIndex + 1;
    var aRet = new Array();
    var iNumT = null;

    while ( i-- ) {
      var sHTML = o.options[i].innerHTML;
      // Vervang alle &nbsp; voor een gewone spatie...
      sText = sHTML.replace( /\&nbsp;/g, " " );
      var t = 0;
      // Hier gaan we bepalen hoeveel spaties er voor de
      // tekst staan.
      while (sText.charCodeAt( t ) == 32) {
        t++;
      }
      // De eerste keer bevat iNumT nog geen waarde
      // Dat is dus de eerste ronde. Dan zetten we iNumT. iNumT
      // geeft aan hoeveel spaties het volgende bovenliggende
      // item moet hebben. Als die twee waardes gelijk zijn, dan
      // is het 100% zeker dat dat item de parent is.
      // Dat controleren of een item een parent is, gebeurt bij
      // de if(t == iNumT)
      if (iNumT == null) {
        iNumT = t - 1;
        aRet.unshift( sText.substr( t ) );
        continue;
      }
      if (t == iNumT) {
        // Parent is gevonden, de volgende parent heeft 1 spatie
        // minder dan de huidige, daarom verlagen we iNumT met 1
        iNumT--;
        aRet.unshift( sText.substr( t ) );
        if (t == 0) {
          break;
        }
      }
    }

    var sRet = "";
    // Nu hebben we dus een array met het complete pad. Van dat
    // pad maken we hier een string zoals je die graag wil.

    for (var i = 0; i < aRet.length; i++) {
      sRet += aRet[i];
      if (i != aRet.length - 1) {
        sRet += " > ";
      }
    }

    return (sRet);
    slert(sRet);
  }
</script>

<select onchange="alert(getPath(this));">
  <option value=23>Winkel</option>
  <option value=28>&nbsp;Kleding</option>
  <option value=56>&nbsp;&nbsp;Dames</option>
  <option value=57>&nbsp;&nbsp;Heren</option>
  <option value=61>&nbsp;&nbsp;&nbsp;Broeken</option>
  <option value=62>&nbsp;&nbsp;&nbsp;Schoenen</option>
  <option value=25>&nbsp;Electronica</option>
  <option value=93>&nbsp;&nbsp;Computers</option>
</select>


Ik zit nu nog met een laatste probleem: in werkelijkheid heeft elke categorie twee spaties voor de naam staan, om de leesbaarheid te verduidelijken. Met andere woorden:
HTML:
1
2
3
4
5
6
7
8
9
10
<select>
<option value=23>Winkel</option>
<option value=28>&nbsp;&nbsp;Kleding</option>
<option value=56>&nbsp;&nbsp;&nbsp;&nbsp;Dames</option>
<option value=57>&nbsp;&nbsp;&nbsp;&nbsp;Heren</option>
<option value=61>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Broeken</option>
<option value=62>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Schoenen</option>
<option value=25>&nbsp;&nbsp;Electronica</option>
<option value=93>&nbsp;&nbsp;&nbsp;&nbsp;Computers</option>
</select>

in plaats van
HTML:
1
2
3
4
5
6
7
8
9
10
<select>
<option value=23>Winkel</option>
<option value=28>&nbsp;Kleding</option>
<option value=56>&nbsp;&nbsp;Dames</option>
<option value=57>&nbsp;&nbsp;Heren</option>
<option value=61>&nbsp;&nbsp;&nbsp;Broeken</option>
<option value=62>&nbsp;&nbsp;&nbsp;Schoenen</option>
<option value=25>&nbsp;Electronica</option>
<option value=93>&nbsp;&nbsp;Computers</option>
</select>

Ik moet dus telkens de categorie vinden met twee spaties minder dan de voorgaande, in plaats van slechts een spatie minder. Nu dacht ik jouw scriptje hierop te kunnen aanpassen door het volgende te veranderen
HTML:
1
2
3
4
5
if (iNumT == null) {
        iNumT = t - 2;  <----------- stond oorspronkelijk t - 1
        aRet.unshift( sText.substr( t ) );
        continue;
      }

Maar dit werkt niet. Wat doe ik verkeerd?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Verwijderd

1.) Bij mij werkte de code ook met die vieze manier van formatten, ipv join().

2.) Als je het commentaar gelezen had, dan was dit wel zo duidelijk... Lees onderstaand stuk code en je weet wat je nog meer moet aanpassen.

code:
1
2
3
4
5
6
7
8
9
      if (t == iNumT) {
        // Parent is gevonden, de volgende parent heeft 1 spatie
        // minder dan de huidige, daarom verlagen we iNumT met 1
        iNumT--;
        aRet.unshift( sText.substr( t ) );
        if (t == 0) {
          break;
        }
      }

Verwijderd

Maarreh...doet Array.join(' > ') het nou niet? Begrijp ik dat goed?

Verwijderd

Ik had in mijn post staan:

code:
1
join(" > ", aRet);


Dat moest natuurlijk zijn:

code:
1
sRet = aRet.join(" > ");


Ik ga ook niet meer helpen, want ik krijg niet echt het idee dat TS gemotiveerd is om zelf ook maar enige tijd in zijn probleem te steken. Roepen "het werkt niet" is niet voldoende.
Pagina: 1