created a function and a HTML structure to populate the DOM from a JSON object
This commit is contained in:
parent
4941ce5aaf
commit
d14988146b
1 changed files with 258 additions and 43 deletions
|
@ -37,6 +37,7 @@
|
|||
}
|
||||
table#view_table thead th {
|
||||
text-align: center;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
table#view_table thead th:first-child {
|
||||
font-weight: bold;
|
||||
|
@ -44,6 +45,14 @@
|
|||
table#view_table thead th.me {
|
||||
font-weight: bold;
|
||||
}
|
||||
table#view_table thead th img {
|
||||
display: block;
|
||||
margin: auto;
|
||||
margin-bottom: 1em;
|
||||
border-radius: 50%;
|
||||
max-width: 4em;
|
||||
max-height: 4em;
|
||||
}
|
||||
|
||||
table#view_table tbody tr {
|
||||
border-bottom: 1px solid #dddddd;
|
||||
|
@ -55,6 +64,8 @@
|
|||
table#view_table tbody th span {
|
||||
font-size: 0.8em;
|
||||
font-weight: normal;
|
||||
display: inline-block;
|
||||
margin-left: 0.33em;
|
||||
}
|
||||
table#view_table tbody tr:nth-of-type(odd) {
|
||||
background-color: var(--colour_lightgrey);
|
||||
|
@ -113,68 +124,272 @@
|
|||
<body>
|
||||
<table id="view_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<!-- Group name -->
|
||||
Les abeilles en test
|
||||
</th>
|
||||
<tr id="view_table_thead_headers">
|
||||
<th id="view_table_thead_name"></th>
|
||||
<!-- For-each group member -->
|
||||
<th>Alice</th>
|
||||
<th class="me">Moi (Loulou)</th>
|
||||
<th>Bob</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- For-each date -->
|
||||
<tr>
|
||||
<th>
|
||||
Date #1
|
||||
<br>
|
||||
<span title="1🏠 + 1🚅">🇸🇪 2</span>
|
||||
<span title="1🏠">🗼 1</span>
|
||||
</th>
|
||||
<!-- For-each group member -->
|
||||
<td>
|
||||
<span class="where">
|
||||
🗼
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td class="me">
|
||||
<span class="where">
|
||||
🇸🇪
|
||||
<i class="modifier modifier-bottom modifier-cross">🚅</i>
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="where">
|
||||
🥨
|
||||
<i class="modifier modifier-top modifier-cross">🏠</i>
|
||||
<i class="modifier modifier-bottom modifier-cross">🚅</i>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>
|
||||
<!-- Total -->
|
||||
3 group members
|
||||
</th>
|
||||
<th id="view_table_tfoot_total"></th>
|
||||
|
||||
<!-- Colspan = number of members -->
|
||||
<th colspan="3"></th>
|
||||
<th id="view_table_tfoot_filler"></th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
So far, this group has planned between 2022-08-01 and 2024-11-25.
|
||||
So far, this group has planned between
|
||||
<span id="view_first_filled_date"></span>
|
||||
and
|
||||
<span id="view_last_filled_date"></span>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="index.html">Take me home!</a>
|
||||
</p>
|
||||
|
||||
<template id="row_date">
|
||||
<tr>
|
||||
<th></th>
|
||||
<!-- For-each group member = availability -->
|
||||
</tr>
|
||||
</template>
|
||||
<template id="cell_availability">
|
||||
<td>
|
||||
<span class="where"></span>
|
||||
</td>
|
||||
</template>
|
||||
<template id="modifier_cannot_host">
|
||||
<i class="modifier modifier-top modifier-cross" title="Cannot host">🏠</i>
|
||||
</template>
|
||||
<template id="modifier_cannot_travel">
|
||||
<i class="modifier modifier-bottom modifier-cross" title="Cannot travel">🚅</i>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
var userUid = 1;
|
||||
var viewData = {
|
||||
view: {
|
||||
name: "Le groupe des abeilles",
|
||||
numberOfGroupMembers: 3,
|
||||
firstFilledDate: "2023-05-06",
|
||||
lastFilledDate: "2025-01-31"
|
||||
},
|
||||
members: [
|
||||
{
|
||||
uid: 1,
|
||||
displayName: "Louis",
|
||||
avatar: "https://static.david-david-studio.com/image/24511.jpg"
|
||||
},
|
||||
{
|
||||
uid: 2,
|
||||
displayName: "Mathilde",
|
||||
avatar: "https://tinder.com/static/tinder.png"
|
||||
},
|
||||
{
|
||||
uid: 3,
|
||||
displayName: "Louis",
|
||||
avatar: "https://www.aprifel.com/wp-content/uploads/2019/02/potiron.jpg"
|
||||
}
|
||||
],
|
||||
dates: [
|
||||
{
|
||||
date: "2024-08-01",
|
||||
membersAvailability: [
|
||||
{
|
||||
memberUid: 1,
|
||||
location: "🇸🇪",
|
||||
canHost: true,
|
||||
canTravel: true
|
||||
},
|
||||
{
|
||||
memberUid: 2,
|
||||
location: "🗼",
|
||||
canHost: true,
|
||||
canTravel: true
|
||||
},
|
||||
{
|
||||
memberUid: 3,
|
||||
location: "🥨",
|
||||
canHost: true,
|
||||
canTravel: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
date: "2024-08-02",
|
||||
membersAvailability: [
|
||||
{
|
||||
memberUid: 1,
|
||||
location: "🗼",
|
||||
canHost: false,
|
||||
canTravel: true
|
||||
},
|
||||
{
|
||||
memberUid: 2,
|
||||
location: "🗼",
|
||||
canHost: true,
|
||||
canTravel: true
|
||||
},
|
||||
{
|
||||
memberUid: 3,
|
||||
location: "🥨",
|
||||
canHost: true,
|
||||
canTravel: false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
function data2dom(data) {
|
||||
// Retrieve common DOM elements
|
||||
var headerRow = document.getElementById("view_table_thead_headers");
|
||||
var tbody = document.getElementById("view_table").querySelector("tbody");
|
||||
|
||||
// Prepared data
|
||||
var numberOfDisplayedMembers = data.members.length;
|
||||
|
||||
// Static: update header
|
||||
document.getElementById("view_table_thead_name").textContent = data.view.name;
|
||||
|
||||
// Static: update footer
|
||||
let strViewMembersCount = data.view.numberOfGroupMembers + " group member";
|
||||
if(data.view.numberOfGroupMembers > 1) strViewMembersCount += "s";
|
||||
document.getElementById("view_table_tfoot_total").textContent = strViewMembersCount;
|
||||
document.getElementById("view_table_tfoot_filler").setAttribute("colspan", numberOfDisplayedMembers);
|
||||
|
||||
// Static: update below table
|
||||
document.getElementById("view_first_filled_date").textContent = data.view.firstFilledDate;
|
||||
document.getElementById("view_last_filled_date").textContent = data.view.lastFilledDate;
|
||||
|
||||
// For each member
|
||||
data.members.forEach(element => {
|
||||
let newCell = document.createElement("th");
|
||||
let displayName;
|
||||
|
||||
if(element.uid == userUid) {
|
||||
displayName = "Me (" + element.displayName + ")";
|
||||
newCell.classList.add("me");
|
||||
}
|
||||
else {
|
||||
displayName = element.displayName;
|
||||
}
|
||||
|
||||
if(element.avatar) {
|
||||
let newAvatar = document.createElement("img");
|
||||
newAvatar.setAttribute("src", element.avatar);
|
||||
newAvatar.setAttribute("alt", "Photo for " + element.displayName);
|
||||
newCell.appendChild(newAvatar);
|
||||
}
|
||||
let newTextData = document.createTextNode(displayName);
|
||||
newCell.appendChild(newTextData);
|
||||
|
||||
headerRow.appendChild(newCell);
|
||||
});
|
||||
// For each date
|
||||
const rowDateTemplate = document.getElementById("row_date");
|
||||
const cellAvailabilityTemplate = document.getElementById("cell_availability");
|
||||
const modifierCannotHostTemplate = document.getElementById("modifier_cannot_host");
|
||||
const modifierCannotTravelTemplate = document.getElementById("modifier_cannot_travel");
|
||||
data.dates.forEach(element => {
|
||||
let clonedRow = rowDateTemplate.content.cloneNode(true);
|
||||
|
||||
let header = clonedRow.querySelector("th");
|
||||
let headerName = document.createTextNode(element.date);
|
||||
header.appendChild(headerName);
|
||||
|
||||
let locations = [];
|
||||
element.membersAvailability.forEach(availability => {
|
||||
// Creating the DOM
|
||||
let clonedCell = cellAvailabilityTemplate.content.cloneNode(true);
|
||||
if(userUid == availability.memberUid) {
|
||||
clonedCell.children[0].classList.add("me");
|
||||
}
|
||||
let whereSpan = clonedCell.querySelector("span.where");
|
||||
let locationText = document.createTextNode(availability.location);
|
||||
whereSpan.appendChild(locationText);
|
||||
|
||||
if(!availability.canHost) {
|
||||
let clonedModifier = modifierCannotHostTemplate.content.cloneNode(true);
|
||||
whereSpan.appendChild(clonedModifier);
|
||||
}
|
||||
if(!availability.canTravel) {
|
||||
let clonedModifier = modifierCannotTravelTemplate.content.cloneNode(true);
|
||||
whereSpan.appendChild(clonedModifier);
|
||||
}
|
||||
|
||||
clonedRow.children[0].appendChild(clonedCell);
|
||||
|
||||
// Aggregating data per location, for totals
|
||||
let existingLocations = locations.filter(e => e.location === availability.location);
|
||||
if(existingLocations.length < 1) {
|
||||
locations.push({
|
||||
location: availability.location,
|
||||
membersAvailable: 0,
|
||||
hostsAvailable: 0,
|
||||
travellersAvailable: 0
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Update other locations if member can travel
|
||||
element.membersAvailability.forEach(availability => {
|
||||
locations.forEach(existingLocation => {
|
||||
if(existingLocation.location == availability.location) {
|
||||
existingLocation.membersAvailable++;
|
||||
if(availability.canHost) {
|
||||
existingLocation.hostsAvailable++;
|
||||
}
|
||||
}
|
||||
else if(availability.canTravel) {
|
||||
existingLocation.membersAvailable++;
|
||||
existingLocation.travellersAvailable++;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if(locations.length > 0) {
|
||||
header.appendChild(document.createElement("br"));
|
||||
}
|
||||
locations.sort((a, b) => {
|
||||
if(a.membersAvailable > b.membersAvailable) {
|
||||
return -1;
|
||||
}
|
||||
else if(a.membersAvailable < b.membersAvailable) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}).forEach(location => {
|
||||
let spanLocation = document.createElement("span");
|
||||
spanLocation.textContent = location.location + location.membersAvailable;
|
||||
|
||||
let title = [location.location + ": "];
|
||||
if(location.hostsAvailable > 0) {
|
||||
title.push(location.hostsAvailable + "🏠");
|
||||
}
|
||||
if(location.travellersAvailable > 0) {
|
||||
title.push(location.travellersAvailable + "🚅");
|
||||
}
|
||||
let neitherHostNorTraveller = location.membersAvailable - location.hostsAvailable - location.travellersAvailable;
|
||||
if(neitherHostNorTraveller > 0) {
|
||||
title.push(neitherHostNorTraveller);
|
||||
}
|
||||
spanLocation.setAttribute("title", title.join(" "));
|
||||
|
||||
header.appendChild(spanLocation);
|
||||
});
|
||||
|
||||
tbody.appendChild(clonedRow);
|
||||
});
|
||||
}
|
||||
|
||||
data2dom(viewData);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue