Agenda items weergeven
Ik wil graag een agenda view bouwen. Mijn idee is om een weekoverzicht (ma t/m zo) te maken waarop elke dag afspraken staan. De afspraken worden grafisch weergegeven, met een div waar je op kunt klikken.
Wat het lastig maakt is dat op eenzelfde dag afspraken kunnen overlappen. Daarvoor dacht ik heel handig een CSS grid layout te kunnen gebruiken. Het raster heeft dan in de Y-as de minuten met grid-template-rows, en de kolommen nemen dan autmatisch weinig plaats in doordat CSS ze automatisch in de kolommen plaatst waar nog ruimte is met grid-auto-flow.
Alleen, het algoritme achter dense houdt de afspraken 1 kolom breed, ook al is er meer plaats als afspraken niet (zo veel) overlappen, bijvoorbeeld bij #afspraak-3.
Als ik dit vergelijk met Outlook, dan doet Outlook dat een stuk slimmer.
Ik heb zitten Googelen naar een algoritme voor het gedrag van Outlook, met steekwoorden als "greedy", maar ik kan niets vinden dat lijkt op hoe Outlook het doet.
De agendatabel is heel simpel, met tijdstempels 'van' en 'tot', een kolom 'id' en een kolom 'onderwerp'.
Hoe reken je zo iets uit in PHP?
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
+----+----+----+----+----+----+----+
| ma | di | wo | do | vr | za | zo |
+----+----+----+----+----+----+----+
| [] | [] | | | [] | [] | |
| | [] | [] | | [] | | |
| | [] | | [] | | [] | |
+----+----+----+----+----+----+----+
| ma | di | wo | do | vr | za | zo |
+----+----+----+----+----+----+----+
| [] | [] | | | [] | [] | |
| | [] | [] | | [] | | |
| | [] | | [] | | [] | |
+----+----+----+----+----+----+----+
Wat het lastig maakt is dat op eenzelfde dag afspraken kunnen overlappen. Daarvoor dacht ik heel handig een CSS grid layout te kunnen gebruiken. Het raster heeft dan in de Y-as de minuten met grid-template-rows, en de kolommen nemen dan autmatisch weinig plaats in doordat CSS ze automatisch in de kolommen plaatst waar nog ruimte is met grid-auto-flow.
Code (php)
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
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
<!DOCTYPE html>
<html>
<head>
<style>
.agenda {
width: 16em;
height: 350px;
background-color: whitesmoke;
border: 1px solid lightgrey;
display: inline-grid;
grid-template-rows: repeat(calc(24 * 60), 1fr);
grid-auto-flow: dense;
}
.afspraak {border: 1px solid grey;}
#afspraak-1 {grid-row: calc(calc(60 * 10) + 30)
/ calc(calc(60 * 12) + 10);}
#afspraak-2 {grid-row: calc(calc(60 * 11) + 15)
/ calc(calc(60 * 11) + 30);}
#afspraak-3 {grid-row: calc(calc(60 * 15) + 15)
/ calc(calc(60 * 20) + 30);}
</style>
</head>
<body>
<div class="agenda">
<div class="afspraak" id="afspraak-1">a</div>
<div class="afspraak" id="afspraak-2">t</div>
<div class="afspraak" id="afspraak-3">j</div>
</div>
</body>
</html>
<html>
<head>
<style>
.agenda {
width: 16em;
height: 350px;
background-color: whitesmoke;
border: 1px solid lightgrey;
display: inline-grid;
grid-template-rows: repeat(calc(24 * 60), 1fr);
grid-auto-flow: dense;
}
.afspraak {border: 1px solid grey;}
#afspraak-1 {grid-row: calc(calc(60 * 10) + 30)
/ calc(calc(60 * 12) + 10);}
#afspraak-2 {grid-row: calc(calc(60 * 11) + 15)
/ calc(calc(60 * 11) + 30);}
#afspraak-3 {grid-row: calc(calc(60 * 15) + 15)
/ calc(calc(60 * 20) + 30);}
</style>
</head>
<body>
<div class="agenda">
<div class="afspraak" id="afspraak-1">a</div>
<div class="afspraak" id="afspraak-2">t</div>
<div class="afspraak" id="afspraak-3">j</div>
</div>
</body>
</html>
Alleen, het algoritme achter dense houdt de afspraken 1 kolom breed, ook al is er meer plaats als afspraken niet (zo veel) overlappen, bijvoorbeeld bij #afspraak-3.
Als ik dit vergelijk met Outlook, dan doet Outlook dat een stuk slimmer.
Ik heb zitten Googelen naar een algoritme voor het gedrag van Outlook, met steekwoorden als "greedy", maar ik kan niets vinden dat lijkt op hoe Outlook het doet.
De agendatabel is heel simpel, met tijdstempels 'van' en 'tot', een kolom 'id' en een kolom 'onderwerp'.
Hoe reken je zo iets uit in PHP?
Ik heb geen Outlook, maar ik vermoed dat je wenst wat (bijvoorbeeld) de Thunderbird kalender ook doet: afspraak 3 had nu de volle breedte moeten pakken (daar waar 1+2 beide de helft krijgen omdat ze deels hetzelfde tijdvak beslaan)?
Geen idee hoe (of) je dit met puur CSS op kunt lossen. Wat je met PHP kun doen is natuurlijk door alle afspraken heen lopen (van+tot tijden chronologisch), en zelf "slots" gaan bepalen. Als een afspraak begint kijk je welk "slot" (laagste nummer) vrij is, en daarin plaats je die afspraak. Als de afspraak eindigt maak je het slot weer leeg (zodat het voor een volgende afspraak hergebruikt kan worden. Op het eind weet je zo hoeveel slots je over de dag heen maximaal nodig hebt (dit met name voor de CSS / breedte berekening). Per afspraak kun je dan weer uit gaan rekenen welk deel van de kolombreedte je nodig hebt (bij 1 slot de volle breedte = 100%, bij 2 de helft = 50%, bij 3 slots 33.333%, enz). Je kauwt de HTML dus behoorlijk uit, en positioneert de boel redelijk absoluut (met procenten) in de <div> voor de betreffende dag.
Geen idee hoe (of) je dit met puur CSS op kunt lossen. Wat je met PHP kun doen is natuurlijk door alle afspraken heen lopen (van+tot tijden chronologisch), en zelf "slots" gaan bepalen. Als een afspraak begint kijk je welk "slot" (laagste nummer) vrij is, en daarin plaats je die afspraak. Als de afspraak eindigt maak je het slot weer leeg (zodat het voor een volgende afspraak hergebruikt kan worden. Op het eind weet je zo hoeveel slots je over de dag heen maximaal nodig hebt (dit met name voor de CSS / breedte berekening). Per afspraak kun je dan weer uit gaan rekenen welk deel van de kolombreedte je nodig hebt (bij 1 slot de volle breedte = 100%, bij 2 de helft = 50%, bij 3 slots 33.333%, enz). Je kauwt de HTML dus behoorlijk uit, en positioneert de boel redelijk absoluut (met procenten) in de <div> voor de betreffende dag.
Je kunt een grid template gebruiken:
https://css-tricks.com/building-a-conference-schedule-with-css-grid/
OVerlappende afspraken zou je binnen de grid met een flexbox kunnen afhandelen:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
(Deze cheatsheet is sowieso wel een permanente bookmark waard.)
https://css-tricks.com/building-a-conference-schedule-with-css-grid/
OVerlappende afspraken zou je binnen de grid met een flexbox kunnen afhandelen:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
(Deze cheatsheet is sowieso wel een permanente bookmark waard.)
Bedankt voor het meedenken.
Ik gebruik nu een grid, met "grid-template-rows: repeat(288, 1fr);" voor een cell per 5 minuten, en "grid-auto-flow: dense;" om de kolommen goed te krijgen. Het is werkbaar, maar ik zou het er liever uit hebben zien als de 1e link van Ward / Thunderbird / Outlook.
Achter de link wordt gebruik gemaakt van "grid-column: track-2-start / track-3-end; /* spanning two tracks! */", maar hoe bereken je dat voor een dynamische view?
Flexbox klinkt interessant, en ik ken de link, maar hoe zet je dat in voor een agenda layout, als de overlappende afspraken elkaar ook gedeeltelijk overlappen?
Ik gebruik nu een grid, met "grid-template-rows: repeat(288, 1fr);" voor een cell per 5 minuten, en "grid-auto-flow: dense;" om de kolommen goed te krijgen. Het is werkbaar, maar ik zou het er liever uit hebben zien als de 1e link van Ward / Thunderbird / Outlook.
Achter de link wordt gebruik gemaakt van "grid-column: track-2-start / track-3-end; /* spanning two tracks! */", maar hoe bereken je dat voor een dynamische view?
Flexbox klinkt interessant, en ik ken de link, maar hoe zet je dat in voor een agenda layout, als de overlappende afspraken elkaar ook gedeeltelijk overlappen?
Grid valt toch een beetje tegen, dacht ik een achtergrondje in te kunnen stellen met linear-gradients voor wat lijnen, lijnen de CSS grid childs niet uit met de CSS achtergrond, waardoor het misschien nog efficienter is om CSS grid te vervangen voor eigen percentages (maar dan moet ik het helemaal zelf uitrekenen).
Toevoeging op 14/09/2021 10:05:29:
Sommige dingen zijn een kwestie van wennen... het coordinatensysteem met CSS Grid begint natuurlijk vanaf 1, niet vanaf 0... nu past het perfect.
Toevoeging op 14/09/2021 10:05:29:
Sommige dingen zijn een kwestie van wennen... het coordinatensysteem met CSS Grid begint natuurlijk vanaf 1, niet vanaf 0... nu past het perfect.




