Bootstrap tabcollapse automatiseren

Pagina: 1
Acties:

  • TechDude
  • Registratie: Augustus 2016
  • Laatst online: 23-11-2024
Hallo,

Ik bouw al enige tijd aan een website die gebaseerd is op een Google map waarbij ik via Javascript markers invoeg met daaraan content gekoppeld uit een json-bestand. Wanneer een gebruiker klikt op een marker verschijnt onder de map een bootstrap accordion panel, die één of meerdere 'projecten' weergeven behorend bij de marker. Elk project panel heeft daarin een aantal tabs met content, die op hun beurt ook weer veranderen in een accordion op een mobiel scherm, een tab-collapse dus.

Dit principe heb ik inmiddels aardig werkende, maar ik stuit nog op een probleem waar ik, na weken van testen, even niet meer zelf uit kom:
Ik krijg namelijk alleen de tab-collapse panels uitgeklapt wanneer ik een blokje code met een check uitvoer en dat voor elke specifieke panel kopieer, terwijl ik dit graag met 1 blokje code wil automatiseren voor alle panels. Bij die check heb ik hier trouwens eerder hulp gehad via een ander topic.

Hieronder een overzichtje van de relevante code:
code:
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
function addMarkers(areas) {
    //Markers aanmaken...

        var theArea = areas[i];
    var theProjectCount = theArea.projects_count;

    function test() {
        //Panels aanmaken...
        
        tabsAndAccordion();
        checkTabState(theProjectCount);
    }

    google.maps.event.addListener(marker, "click", function(event) {
        test();
    }); 
}



function tabsAndAccordion() {
    $('#myTab0').tabCollapse({
        tabsClass: 'hidden-xs',
        accordionClass: 'visible-xs'
    });
    
    $('#myTab1').tabCollapse({
        tabsClass: 'hidden-xs',
        accordionClass: 'visible-xs'
    });
    
    $('#myTab2').tabCollapse({
        tabsClass: 'hidden-xs',
        accordionClass: 'visible-xs'
    });
    
    //etc...
};



function checkTabState(theProjectCount) {
    $('#collapse0').on('shown.bs.collapse', function () {
        var tc = $('#myTab0').data('bs.tabcollapse');
        tc.checkState();
    });
    
    $('#collapse1').on('shown.bs.collapse', function () {
        var tc = $('#myTab1').data('bs.tabcollapse');
        tc.checkState();
    });
    
    $('#collapse2').on('shown.bs.collapse', function () {
        var tc = $('#myTab2').data('bs.tabcollapse');
        tc.checkState();
    });

    //etc...

    
    
    //Een paar pogingen om te automatiseren via een loop, werkt niet:
    
    /* for(i = 0; i < theProjectCount; i++) {
        $('#collapse' + i).on('shown.bs.collapse', function () {
            var tc = $('#myTab' + i).data('bs.tabcollapse');
            tc.checkState();
        });
    } */
    
    /* var tc = [];

    for(i = 0; i < theProjectCount; i++) {  
        function pushTest(tabnr) {
            var result = $('#myTab' + tabnr).data('bs.tabcollapse');
            tc.push(result);    
            tc[tabnr].checkState();
        };
        
        $('#collapse' + i).on('shown.bs.collapse', pushTest(i));
    }; */
};


Zoals hierboven hoop ik duidelijk wordt voer ik dus de functie checkTabState() uit onclick op een marker, waarbij de 3 panels (#collapse0, 1 en 2) netjes uitklappen. Maar ik moet dus telkens dat blokje code kopiëren voor elk nieuw project en dus panel, dat is niet te doen. Dit probeer ik dus te automatiseren via een for-loop maar blijkbaar werkt dit niet. Wie kan me hierbij verder helpen? Alle hulp is welkom, alvast bedankt!

  • Harrie_
  • Registratie: Juli 2003
  • Niet online

Harrie_

⠀                  🔴 🔴 🔴 🔴 🔴

Kun je aangeven waarom de for-loop niet werkt? Blijft hij hangen in de loop? Vult hij var tc niet goed?

Hoeder van het Noord-Meierijse dialect


  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Je kan toch gewoon het stukje code aan een class hangen waar hij op triggert? In jQuery hoeven selectors namelijk niet per se aan id's te hangen! Vervolgens haal je het id op met iets als $(this).attr('id') oid om het id op te halen van het aangeklikte element.

En in jouw voorbeeldcode, geef je theProjectCount ook geen waarde, dus hij vergelijkt het getal met undefined en is dan dus gauw klaar. :+ Ook is een function binnen een function niet de bedoeling, denk ik? Maar goed, een for loop is niet nodig als je de selector op basis van een class gaat maken. ;)

[ Voor 48% gewijzigd door CH4OS op 07-09-2017 12:34 ]


  • TechDude
  • Registratie: Augustus 2016
  • Laatst online: 23-11-2024
@Harrie_ : De loop draait gewoon naar het aantal projecten (theProjectCount). Het gaat dus mis als ik het nummer van de id in een loop vervang voor variabele 'i'. Waarom precies is mij ook nog een raadsel, al heb ik ook het vermoeden dat het te maken heeft met het feit dat hij de loop één keer afdraait en blijft hangen bij het eind nummer (dus 2 in bovenstaand voorbeeld).
Zodra ik op een panel klik krijg ik in de console de foutmelding "tc is undefined". Vandaar dat ik die in de andere test in een array heb geprobeerd te stoppen. Die array vult hij wel maar het lost het probleem niet op.

@CH4OS : Dat zal ik nog eens proberen, dankje.

  • Harrie_
  • Registratie: Juli 2003
  • Niet online

Harrie_

⠀                  🔴 🔴 🔴 🔴 🔴

TechDude schreef op donderdag 7 september 2017 @ 13:04:
Zodra ik op een panel klik krijg ik in de console de foutmelding "tc is undefined". Vandaar dat ik die in de andere test in een array heb geprobeerd te stoppen. Die array vult hij wel maar het lost het probleem niet op.
En dat komt waarschijnlijk door wat @CH4OS zegt: namelijk dat theProjectCount geen waarde heeft?

Hoeder van het Noord-Meierijse dialect


  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Harrie_ schreef op donderdag 7 september 2017 @ 14:36:
En dat komt waarschijnlijk door wat @CH4OS zegt: namelijk dat theProjectCount geen waarde heeft?
tc is een andere variabele. Daarvan is dan wellicht de selector niet goed, gok ik zo, uitgaande van de voorbeeldcode.

EDIT:
Als ik naar de voorbeeldcode kijk: is er een data-bs.tabcollapse attribuut in de tag van de selector aanwezig, @TechDude? :)

EDIT2:
Zover ik kan zien, is de makkelijkste oplossing nog altijd door gebruik te maken van een selector op basis van een class, scheelt veel duplicate code. :)

[ Voor 31% gewijzigd door CH4OS op 07-09-2017 20:37 ]


Acties:
  • 0 Henk 'm!

  • TechDude
  • Registratie: Augustus 2016
  • Laatst online: 23-11-2024
Excuus, ik zie nu pas dat CH4OS zijn eerdere comment had aangevuld. Het staat niet in bovenstaand voorbeeld maar theProjectCount definieer ik eerder in addMarkers() en geef ik dus weer als parameter mee in checkTabState(). Als ik die vanuit checkTabState() even log in de console dan geeft hij gewoon netjes het aantal projecten weer, dus dat werkt wel.

var tc werkt dus prima wanneer ik de genummerde id aanroep, dus #myTab0, 1 etc, maar niet zodra ik er doorheen ga loopen. Ik zal straks even proberen via een class aan te roepen.

@CH4OS : Je vraag begrijp ik niet helemaal? Een panel link ziet er in HTML ongeveer uit als onderstaande code, letterlijk een tabcollapse-attribuut kan ik er niet in terug vinden...
code:
1
2
3
4
5
<a class="" data-toggle="collapse" data-parent="accordion" href="collapse0" aria-expanded="true">...</a>

<div id="collapse0" class="panel-collapse collapse in" aria-expanded="true">
//content...
</div>

Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

TechDude schreef op vrijdag 8 september 2017 @ 12:08:
var tc werkt dus prima wanneer ik de genummerde id aanroep, dus #myTab0, 1 etc, maar niet zodra ik er doorheen ga loopen. Ik zal straks even proberen via een class aan te roepen.
Dan heb je wat niet goed als je via de loop geen reactie krijgt maar als je het los aanroept wel krijgt. Toch is het handiger om aan te roepen middels een class, want dan kan je een boel duplicate code voorkomen. ;)
@CH4OS : Je vraag begrijp ik niet helemaal? Een panel link ziet er in HTML ongeveer uit als onderstaande code, letterlijk een tabcollapse-attribuut kan ik er niet in terug vinden...
code:
1
2
3
4
5
<a class="" data-toggle="collapse" data-parent="accordion" href="collapse0" aria-expanded="true">...</a>

<div id="collapse0" class="panel-collapse collapse in" aria-expanded="true">
//content...
</div>
Oke, maar in jouw voorbeeldcode doe je
JavaScript:
1
var result = $('#myTab' + tabnr).data('bs.tabcollapse');
De .data() functie returned de waarde van het opgegeven data-* attribuut. In het geval van .data('bs-tabcollapse') selecteert het dus onder water het data-bs.tabcollapse attribuut! Dat result dus undefined is, komt omdat het opgegeven data-attribuut niet bestaat.

[ Voor 3% gewijzigd door CH4OS op 08-09-2017 12:14 ]


Acties:
  • 0 Henk 'm!

  • skate master
  • Registratie: September 2004
  • Laatst online: 08:36

skate master

Autodesk Educator Expert

Het allemaal in en uitkloppen van een collapse object is niet zo lastig.
Volgens mij zoek je onderstaande code, tenzij ik je vraag verkeerd begrepen heb.
code:
1
2
3
4
5
6
7
8
9
$("#collapse_show").click(function(e) {
  e.preventDefault();
  $(".panel-collapse").collapse("show");
});

$("#collapse_hide").click(function(e) {
  e.preventDefault();
  $(".panel-collapse").collapse("hide");
});

Door middels bovenstaande code op een class te selecteren kun je eenvoudig alle items in / uit klappen.

Kun je hier wat mee?

Acties:
  • 0 Henk 'm!

  • TechDude
  • Registratie: Augustus 2016
  • Laatst online: 23-11-2024
@CH4OS : Net even snel via een class getest, zelfde probleem blijft. Ik krijg alleen geen error meer in de console.
Trouwens, als ik de schermbreedte op mobiel formaat iets versleep dan klapt de panel wel goed uit.. Dit probleem had ik dus al eerder en is destijds opgelost met dit blokje jQuery-code in checkTabState(). Zoals ik begrepen heb moeten de tabs zichtbaar zijn als je tabCollapse aanroept, anders kan hij niet kijken of de width groot genoeg is.
De .data() functie returned de waarde van het opgegeven data-* attribuut. In het geval van .data('bs-tabcollapse') selecteert het dus onder water het data-bs.tabcollapse attribuut! Dat result dus undefined is, komt omdat het opgegeven data-attribuut niet bestaat.
Hier wordt het mij dus wat wazig. Feit blijft dat #myTab0 dus wel dat attribuut selecteert maar #myTab + i niet.

@skate master : Dat in en uitklappen werkt ook wel, alleen niet zodra ik de handmatig ingevoerde jQuery-code voor elke tab wil automatiseren door er doorheen te loopen.

Ik wil trouwens 1 panel uitklappen, niet alle panels tegelijk, daarom vrees ik bij nader inzien dat een class sowieso niet gaat werken.

Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

TechDude schreef op vrijdag 8 september 2017 @ 13:02:
@CH4OS : Net even snel via een class getest, zelfde probleem blijft.
Laat is even wat code zien dan? Doe ook wat meer debugging, ik heb niet het idee dat je dat echt doet, eigenlijk.
Ik krijg alleen geen error meer in de console.
Met andere woorden, hetgeen je gebouwd hebt, werkt niet zoals bedoeld of er zit ergens een fout in, bijvoorbeeld omdat je de verkeerde selector hebt.
Hier wordt het mij dus wat wazig.
Pak dan de jQuery documentatie over .data er even bij. ;)
Feit blijft dat #myTab0 dus wel dat attribuut selecteert maar #myTab + i niet.
Wat krijg je als je het handmatig doet in de console? Eerst de variabele dus zetten in de console, daarna de selector en checken of je een length hebt groter dan 0? :)

Acties:
  • 0 Henk 'm!

  • TechDude
  • Registratie: Augustus 2016
  • Laatst online: 23-11-2024
Watvoor code wil je zien? Ik heb in de beginpost juist geprobeerd om alle niet relevante code eruit te laten om het overzichtelijk te houden. Alle tests die ik uitprobeer bewaar ik niet allemaal als ze niet werken. Via een PM kan ik je evt de bron wel doorgeven...
Met andere woorden, hetgeen je gebouwd hebt, werkt niet zoals bedoeld of er zit ergens een fout in, bijvoorbeeld omdat je de verkeerde selector hebt.
Ik zal ongetwijfeld iets niet goed doen, ik ben op moment nog niet echt vergevorderd met javascript, maar de meest simpele loop waarbij ik alleen het nummer vervang voor 'i', werkt al niet. Volgens mij zit daar iets anders achter dan een verkeerde selector (wat ik wegens mijn beperkte kennis misschien zelf nog niet in zie).
Wat krijg je als je het handmatig doet in de console? Eerst de variabele dus zetten in de console, daarna de selector en checken of je een length hebt groter dan 0? :)
console.log(tc); > direct na de var tc definitie en voor de checkState() regel: geeft een error 'undefined'. Bij de checkState() functie krijg ik "tc is undefined".
Als ik: console.log($('#myTab' + i)); > krijg ik: Object { context: HTMLDocument → ..., selector: "#myTab4" }
Dat is wel opvallend, volgens mij blijft hij hangen aan het eind van de loop, vandaar de 4 (ik heb 4 projecten onder de marker hangen die ik hiervoor heb getest). Volgens mij gaat het hier ergens mis.


console.log(tc) in de werkende code geeft in de console:
Object { options: Object, $tabs: Object, _accordionVisible: false, $accordion: Object[1] }
En wanneer ik klik op Object[1]:
<div#myTab0-accordion.panel-group.visible-xs>

Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

TechDude schreef op vrijdag 8 september 2017 @ 13:58:
Watvoor code wil je zien? Ik heb in de beginpost juist geprobeerd om alle niet relevante code eruit te laten om het overzichtelijk te houden.
Dan heb je niet alle relevante code gegeven, want niet alle variabelen worden gezet binnen de voorbeeldcode:
TechDude schreef op vrijdag 8 september 2017 @ 12:08:
Het staat niet in bovenstaand voorbeeld maar theProjectCount definieer ik eerder in addMarkers() en geef ik dus weer als parameter mee in checkTabState(). Als ik die vanuit checkTabState() even log in de console dan geeft hij gewoon netjes het aantal projecten weer, dus dat werkt wel.
Dus of je hebt te weinig voorbeeldcode gegeven of je hebt inderdaad een fout in de code, maar wat niet in de voorbeeldcode zit.
console.log(tc); > direct na de var tc definitie en voor de checkState() regel: geeft een error 'undefined'. Bij de checkState() functie krijg ik "tc is undefined".
Als ik: console.log($('#myTab' + i)); > krijg ik: Object { context: HTMLDocument → ..., selector: "#myTab4" }
Dat is wel opvallend, volgens mij blijft hij hangen aan het eind van de loop, vandaar de 4 (ik heb 4 projecten onder de marker hangen die ik hiervoor heb getest). Volgens mij gaat het hier ergens mis.
Heb je in de console van te voren ook gezet door hem even een vaste waarde te geven, bijvoorbeeld? :? Anders is het wel logisch, dat je niets terugkrijgt namelijk. #Mytabundefined zal je vast niet hebben. Maar nogmaals, voorkom duplicate code en maak de selector class-based. Dan hoeft het niet gelijk ook te werken, zoals je ook aangeeft, maar dan betekend dat dat het in de logica niet goed zit en de code dus niet doet wat je eigenlijk wel verwacht.

[ Voor 10% gewijzigd door CH4OS op 08-09-2017 15:33 ]


Acties:
  • 0 Henk 'm!

  • TechDude
  • Registratie: Augustus 2016
  • Laatst online: 23-11-2024
Dan heb je niet alle relevante code gegeven, want niet alle variabelen worden gezet binnen de voorbeeldcode:
Ik heb de code uit de beginpost iets aangevuld. theProjectCount slaat dus op het aantal projecten uit theArea. Dit is data afkomstig uit een json-bestand.
Mocht je meer willen zien, dan kan ik je het bronbestand PM-en. Het eigenlijke bestand bevat 100en regels code, maar dat post ik liever niet publiekelijk op dit forum.
Heb je in de console van te voren ook gezet door hem even een vaste waarde te geven, bijvoorbeeld? :?
Wat bedoel je met 'hem'? Zoals in de beginpost te zien werkt checkTabState() met de genummerde id's. Als ik theProjectCount vervang door bijvoorbeeld een '4', krijg ik dezelfde foutmelding: "tc is undefined".

Via een class had ik vorige week al getest, dat werkte niet maar volgens mij gaat dat ook niet werken omdat de aangeklikte panel moet uitklappen en de rest inklappen, hoe kan het script dat dan nog herkennen? Daarnaast heb ik een aanvullend script die ook reageert op de panels o.b.v. de unieke id's/nummers. Ik denk dus dat ik het met id's moet oplossen en het lijkt me sterk dat dat onmogelijk is?
Pagina: 1