Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[JavaScript] Inhoudsopgave bouwen

Pagina: 1
Acties:

  • Vinze
  • Registratie: Augustus 2006
  • Laatst online: 20-11 10:29
Ik heb een array met een aantal objecten, en hiervan moet een nested list (inhoudsopgave) gemaakt worden. Ik kom er alleen niet uit hoe ik die (recursieve?) functie moet bouwen.

De array ziet er als volgt uit:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
var list = [
    {id: 1, level: 1, title: 'Header #1'},
    {id: 2, level: 2, title: 'Subheader #2'},
    {id: 3, level: 3, title: 'Subsubheader #3'},
    {id: 4, level: 2, title: 'Subheader #4'},
    {id: 5, level: 3, title: 'Subsubheader #5'},
    {id: 6, level: 1, title: 'Header #6'},
    {id: 7, level: 2, title: 'Subheader #7'},
    {id: 8, level: 3, title: 'Subsubheader #8'},
    {id: 9, level: 2, title: 'Subheader #9'}
];


En uiteindelijk moet hier het volgende uitkomen:
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
<ul>
    <li>Header #1
        <ul>
            <li>Subheader #2
                <ul>
                    <li>Subsubheader #3</li>
                </ul>
            </li>
            <li>Subheader #4
                <ul>
                    <li>Subsubheader #5</li>
                </ul>
            </li>
        </ul>
    </li>
    <li>Header #6
        <ul>
            <li>Subheader #7
                <ul>
                    <li>Subsubheader #8</li>
                </ul>
            </li>
            <li>Subheader #9</li>
        </ul>
    </li>
</ul>


Ik zoek geen kant-en-klaar script, maar kan iemand me in de juiste richting wijzen? Ik heb echt geen flauw idee waar ik moet beginnen om dit klaar te spelen..

Op internet is wel veel te vinden, maar dit werkt allemaal met parent/child velden, en helaas krijg ik het ook niet voor elkaar om dat uit deze lijst te genereren..

[ Voor 6% gewijzigd door Vinze op 10-09-2013 15:48 ]


  • DXaroth
  • Registratie: Maart 2011
  • Laatst online: 24-08 19:58
Vinze schreef op dinsdag 10 september 2013 @ 15:45:
Ik heb een array met een aantal objecten, en hiervan moet een nested list (inhoudsopgave) gemaakt worden. Ik kom er alleen niet uit hoe ik die (recursieve?) functie moet bouwen.

De array ziet er als volgt uit:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
var list = [
    {id: 1, level: 1, title: 'Header #1'},
    {id: 2, level: 2, title: 'Subheader #2'},
    {id: 3, level: 3, title: 'Subsubheader #3'},
    {id: 4, level: 2, title: 'Subheader #4'},
    {id: 5, level: 3, title: 'Subsubheader #5'},
    {id: 6, level: 1, title: 'Header #6'},
    {id: 7, level: 2, title: 'Subheader #7'},
    {id: 8, level: 3, title: 'Subsubheader #8'},
    {id: 9, level: 2, title: 'Subheader #9'}
];
Beetje ongemakkelijke manier van dingen noteren, want er is niet echt een verband dat aangeeft waar onder de subheader hoeft...

Je functie hoeft in theorie niet recursive te zijn, je loopt over de items, en doet het volgende: (er van uitgaande dat je aanneemt dat level begint op 0)

1) is level hoger dan de vorige, zo ja: <ul>\n<li> item
2) indien level gelijk is dan de vorige: </li>\n<li> item
3) indien level lager is dan de vorige: </ul>\n</li>\n voor elk level dat we omlaag gaan, gevolgd door <li> item

Daarmee kom je denk ik al aardig in de buurt.. het is jammer dat je de javascript notatie niet kan aanpassen; dan kan je er gewoon nested lists van maken..

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 03:08
Je kunt de lijst vrij eenvoudig omzetten naar een hiërarchische representatie, door aan elk item een lijst van children te geven. Je kunt die children vinden door de lijst te doorlopen en elk item steeds aan het vorige item van één level erboven toe te voegen:
JavaScript:
1
2
3
4
5
6
7
var root = { children: [] }
var level = [ root ]
for (var i = 0; i < list.length; ++i) {
   level[list[i].level - 1].children.push(list[i])
   level[list[i].level] = list[i]
   list[i].children = []
}

... produceert deze datastructuur:
JavaScript:
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
root = {
    children: [{
        id: 1,
        level: 1,
        title: "Header #1",
        children: [{
            id: 2,
            level: 2,
            title: "Subheader #2",
            children: [{
                id: 3,
                level: 3,
                title: "Subsubheader #3",
                children: []
            }]
        }, {
            id: 4,
            level: 2,
            title: "Subheader #4",
            children: [{
                id: 5,
                level: 3,
                title: "Subsubheader #5",
                children: []
            }]
        }]
    }, {
        id: 6,
        level: 1,
        title: "Header #6",
        children: [{
            id: 7,
            level: 2,
            title: "Subheader #7",
            children: [{
                id: 8,
                level: 3,
                title: "Subsubheader #8",
                children: []
            }]
        }, {
            id: 9,
            level: 2,
            title: "Subheader #9",
            children: []
        }]
    }]
}

Nu is het eenvoudig om met een recursieve procedure de gewenste HTML code (of beter: de DOM structuur direct) te genereren.

  • creator1988
  • Registratie: Januari 2007
  • Laatst online: 22-11 19:09
Dit doet het voor alle niveau-dieptes:

JavaScript:
1
2
3
4
5
list.reduce(function(v, l) {
  if (v && l.level > v.level) 'children' in v ? v.children.push(l) : v.children = [l]
  return l
})
list.filter(function(l) { return l.level === 1 })

  • Vinze
  • Registratie: Augustus 2006
  • Laatst online: 20-11 10:29
Hartstikke bedankt! Ik ben weer uit de brand geholpen :)
Die list maken is nu geen probleem meer!

Edit: Ik ben er toch nog niet helemaal, probeer nu direct de hiërarchische lijst te maken maar hij zegt dat children undefined is bij het stukje: level[item.level - 1].children.push(item)
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var i = 1
var root = { children: [] } 
var level = [ root ]
                
var output = html.replace(/<h\s*[0-3]>(.*?)<\/h[0-3]>/gi, function(header) {
    var headerparts = header.match(/<h\s*([0-3])>(.*?)<\/h[0-3]>/)
    
    var item = {
        'id': i++,
        'level': parseInt(headerparts[1]),
        'title': headerparts[2],
        'children': []
    }

    level[item.level - 1].children.push(item) 
    level[item.level] = item
})

[ Voor 76% gewijzigd door Vinze op 10-09-2013 22:01 ]


  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Vinze schreef op dinsdag 10 september 2013 @ 20:20:
Edit: Ik ben er toch nog niet helemaal, probeer nu direct de hiërarchische lijst te maken maar hij zegt dat children undefined is bij het stukje: level[item.level - 1].children.push(item)
En daarnaast gebruik je ook nog regular expressions om HTML te parsen. Foei! Begin eens met daar af te stappen en gewoon de DOM tree te gebruiken.

Daarnaast is het opzetten van een document outline wel een tikkie complexer dan gewoon te kijken naar headings die in document order voor komen. De HTML5 sectioning elementen spelen daar ook een belangrijke rol.

[ Voor 19% gewijzigd door R4gnax op 10-09-2013 21:53 ]


  • Vinze
  • Registratie: Augustus 2006
  • Laatst online: 20-11 10:29
Deze HTML is een string gegenereerd vanuit markdown door marked.js, vandaar dat ik regex gebruik.

Ik heb trouwens ook al gevonden waarom hij faalt: wanneer de eerst gevonden header niet een h1 (level 1) is, maar bijvoorbeeld een h2 of h3, dan probeert hij leven[1].children te vullen, welke dus niet bestaat.. Ik blijf nog even een en ander proberen :)

[ Voor 57% gewijzigd door Vinze op 10-09-2013 22:17 ]


  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Vinze schreef op dinsdag 10 september 2013 @ 21:57:
Deze HTML is een string gegenereerd vanuit markdown door marked.js, vandaar dat ik regex gebruik.
Nog steeds geen excuus. Je kunt altijd de browser dit naar een DOM tree laten parsen via een DocumentFragment.
Pagina: 1