server/assets/development/scripts/home.js

413 lines
10 KiB
JavaScript
Raw Permalink Normal View History

/**
* Utils
*/
function createEl(className = false, elName = "div") {
let el = document.createElement(elName);
if (className != false) {
el.className = className;
}
return el;
}
/**
* Nav management
*/
2020-07-23 10:43:20 +00:00
let navOpened = false;
let oldNavText = "";
let oldNavIcon = "";
2020-07-23 10:43:20 +00:00
let navEnabler = document.getElementById('nav-enabler');
let navEnablerText = document.getElementById('nav-enabler-text');
let navEnablerIcon = document.getElementById('nav-enabler-icon');
let navContent = document.getElementById('nav-content');
let navAll = document.getElementById('nav-all')
2020-07-23 10:43:20 +00:00
let mosaic = document.getElementById('mosaic');
let mosaicCount = document.getElementById('mosaic-count');
let tags = []
2020-08-17 10:25:10 +00:00
let navEnablerExists = false
function closeMenu() {
navEnablerText.textContent = oldNavText;
navEnablerIcon.style.transform = "rotate(0deg)";
navContent.style.maxHeight = null;
}
navEnabler.onclick = async () => {
2020-08-17 10:25:10 +00:00
navEnablerExists = true
if (!navOpened) {
// open the menu
2020-07-23 10:43:20 +00:00
oldNavText = navEnablerText.textContent;
navEnablerText.textContent = "Minimiser le menu";
navEnablerIcon.style.transform = "rotate(90eg)";
navContent.style.maxHeight = navContent.scrollHeight + "px";
} else {
2020-08-17 10:25:10 +00:00
closeMenu()
}
2020-08-17 10:25:10 +00:00
navOpened = !navOpened
}
/**
* Content rendering
*/
/**
* Shuffle organization
*/
2020-09-06 10:25:25 +00:00
function shuffle(array, seed = {}) {
let newSeed = {}
let currentIndex = array.length, temporaryValue, randomIndex
while (0 !== currentIndex) {
2020-09-06 10:25:25 +00:00
if (seed[currentIndex] === undefined) {
randomIndex = Math.floor(Math.random() * currentIndex)
} else {
randomIndex = seed[currentIndex.toString()]
}
newSeed[currentIndex.toString()] = randomIndex
2020-09-06 10:25:25 +00:00
currentIndex -= 1
temporaryValue = array[currentIndex]
array[currentIndex] = array[randomIndex]
array[randomIndex] = temporaryValue
}
2020-09-06 10:25:25 +00:00
if (newSeed.length == 0) {
newSeed = null
}
return [array, newSeed]
}
/**
* Filter & Sort actions
*/
const randomBtn = document.getElementById('random-btn')
const sortBtn = document.getElementById('sort-btn')
2020-09-06 10:25:25 +00:00
const seedStorageKey = 'fva_shuffle_seed'
let originalRandom = ''
let sort = false
2020-09-06 10:25:25 +00:00
let seed = {}
// the user want to sort randomly
randomBtn.onclick = () => {
if (sort) {
2020-09-06 10:25:25 +00:00
organizations = JSON.parse(originalRandom)
enableTag(currentTag, true)
sort = false
randomBtn.classList.add('enabled')
sortBtn.classList.remove('enabled')
}
}
// the user want to sort by name
sortBtn.onclick = () => {
if (!sort) {
// sort by name
organizations = organizations.sort((a, b) => {
var textA = a.name.toUpperCase()
var textB = b.name.toUpperCase()
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
})
enableTag(currentTag, true)
sort = true
sortBtn.classList.add('enabled')
randomBtn.classList.remove('enabled')
}
}
function renderNavItem(tag) {
/*
<div class="nav-item">
<div class="nav-icon">
<i class="fas fa-music"></i>
</div>
<div class="nav-item-content">
<div class="nav-title">
Danse et musique
</div>
<div class="nav-access">
<i class="fas fa-chevron-right"></i>
</div>
</div>
</div>
*/
2020-07-23 10:43:20 +00:00
let navItem = createEl('nav-item');
let navIcon = createEl('nav-icon');
let icon = createEl(tag.icon, 'i');
2020-07-23 10:43:20 +00:00
navIcon.appendChild(icon);
navItem.appendChild(navIcon);
2020-07-23 10:43:20 +00:00
let navItemContent = createEl('nav-item-content');
let navTitle = createEl('nav-title');
navTitle.textContent = tag.name;
navItemContent.appendChild(navTitle);
2020-07-23 10:43:20 +00:00
let navAccess = createEl('nav-access');
let chevronIcon = createEl('fas fa-chevron-right', 'i');
navAccess.appendChild(chevronIcon);
navItemContent.appendChild(navTitle);
navItemContent.appendChild(navAccess);
navItem.appendChild(navItemContent);
2020-07-23 10:43:20 +00:00
return navItem;
}
2020-07-15 20:32:42 +00:00
function setAttributes(node, attrs) {
for (var key in attrs) {
attr = document.createAttribute(key)
attr.value = attrs[key]
node.attributes.setNamedItem(attr)
}
}
function renderCard(organization) {
2020-07-21 14:41:07 +00:00
let card = createEl('card', 'a')
// image
2020-07-21 14:41:07 +00:00
let image = createEl('card-image-container')
let imageTag = createEl('card-image')
imageTag.style = `background-image: url('${mediaBaseUrl + '/' + organization.thumbnail}')`
image.appendChild(imageTag)
card.appendChild(image)
let content = createEl('card-content')
let upperContent = createEl()
let titleContainer = createEl('card-title-container')
let title = createEl('card-title', 'h2')
title.textContent = organization.name
titleContainer.appendChild(title)
let icon = createEl('card-icon')
2020-07-19 13:26:57 +00:00
if (Array.isArray(organization.tags) && organization.tags.length > 0) {
let tag = tags.filter(tag => organization.tags[0] === tag._id)[0]
// icon.innerHTML = `<svg
// aria-hidden="true"
// focusable="false"
// role="img"
// xmlns="http://www.w3.org/2000/svg"
// viewBox="0 0 ${tag.icon.width} ${tag.icon.height}">
// <path fill="currentColor" d="${tag.icon.path}"></path>
// </svg>`
icon.innerHTML = tag.iconHTML
2020-07-19 13:26:57 +00:00
}
titleContainer.appendChild(icon)
upperContent.appendChild(titleContainer)
let description = createEl('card-description')
2020-07-15 20:32:42 +00:00
description.textContent = organization.description
let goTo = "/association/" + organization.slug
if (isProposed) {
2020-07-21 14:41:07 +00:00
goTo += "?version=proposed"
2020-07-19 13:26:57 +00:00
}
2020-07-21 14:41:07 +00:00
// let link = createEl('card-link')
// let aTag = createEl('card-link', 'a')
// aTag.href =
// aTag.textContent = "En savoir plus"
// description.appendChild(aTag)
2020-07-19 13:26:57 +00:00
upperContent.appendChild(description)
//link.appendChild(aTag)
content.appendChild(upperContent)
2020-07-19 13:26:57 +00:00
//content.appendChild(link)
card.appendChild(content)
2020-07-15 20:32:42 +00:00
2020-07-21 14:41:07 +00:00
card.href = goTo
2020-09-06 10:25:25 +00:00
card.setAttribute('data-organization-id', organization._id)
2020-07-21 14:41:07 +00:00
// card.onclick = () => {
// window.location = goTo
// }
2020-09-06 10:25:25 +00:00
card.onclick = (e) => {
e.preventDefault()
window.sessionStorage[scrollPointStorageKey] = organization._id
window.location.href = goTo
}
return card
}
let currentTag = null
let currentCardContainer = null
function enableTag(node, sortOperation = false, initialOperation = false) {
let all = node.id === 'nav-all'
let tagId = ''
if (!all) {
tagId = node.attributes['data-tag-id'].value
}
let data = organizations
.filter(orga => orga.tags.filter(id => id === tagId).length > 0 || all)
renderMosaic(data)
node.className += ' enabled'
if (currentTag !== null) {
currentTag.className = currentTag.className.replace('enabled', '')
}
currentTag = node
2020-08-17 10:25:10 +00:00
if (!sortOperation) {
if (data === undefined || data === null || data.length <= 0) {
mosaicCount.textContent = "Aucune association listée"
} else if (data.length === 1) {
mosaicCount.textContent = "Une association listée"
} else {
mosaicCount.textContent = data.length + " associations listées"
}
// close the menu if on mobile
if (navEnablerExists && !initialOperation) {
navOpened = !navOpened
closeMenu()
document.getElementsByClassName('content')[0].scrollIntoView(true)
} else {
if (window.scrollY() > 300 && !initialOperation) {
document.getElementsByClassName('content')[0].scrollIntoView(true)
}
}
2020-08-17 10:25:10 +00:00
}
}
/***
* Is a element in the view ?
*/
function posY(elm) {
var test = elm, top = 0;
while(!!test && test.tagName.toLowerCase() !== "body") {
top += test.offsetTop;
test = test.offsetParent;
}
return top;
}
function viewPortHeight() {
var de = document.documentElement;
if(!!window.innerWidth)
{ return window.innerHeight; }
else if( de && !isNaN(de.clientHeight) )
{ return de.clientHeight; }
return 0;
}
function scrollY() {
if( window.pageYOffset ) { return window.pageYOffset; }
return Math.max(document.documentElement.scrollTop, document.body.scrollTop);
}
function isVisible(elm) {
var vpH = viewPortHeight(), // Viewport Height
st = scrollY(), // Scroll Top
y = posY(elm);
return !(y > (vpH + st));
}
/**
* RenderMosaic
* (take all the organizations we want to render)
* Render only the first 5 elements
* Set the focus point on the last - 1 of theses elements
* When the focus point is on screen we load the next 5 elements
*/
let rendering = true
let page = 0
let elementsPerPage = 5
let focusPoint = null
let focusElementPos = 2
let cardContainer = null
let currentOrganizations = []
let pageCount = 0
function renderPage() {
rendering = true
let data = currentOrganizations.slice(page * elementsPerPage, (page + 1) * elementsPerPage)
data.forEach((orga, index) => {
let card = renderCard(orga)
cardContainer.appendChild(card)
if (index === data.length - focusElementPos) {
focusPoint = card
}
})
rendering = false
}
function renderMosaic(data) {
cardContainer = createEl('card-container')
// 1 - parse all the data
// 2 - for each
currentOrganizations = data
page = 0
pageCount = Math.floor(data.length / elementsPerPage)
renderPage()
if (currentCardContainer !== null) {
mosaic.removeChild(currentCardContainer)
}
currentCardContainer = cardContainer
mosaic.appendChild(cardContainer)
}
const scrollPointStorageKey = 'fva_scroll_point'
window.onscroll = () => {
2020-09-06 10:25:25 +00:00
//window.sessionStorage[scrollPointStorageKey] = window.scrollY()
if (focusPoint != null && isVisible(focusPoint) && !rendering) {
if (page + 1 < pageCount + 1) {
page++
renderPage()
}
}
}
/**
* Fetch tags and register click handler
*/
window.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('#nav-content .nav-item').forEach(node => {
node.onclick = () => enableTag(node)
if (node.id === 'nav-all') {
return
}
tags.push({
_id: node.attributes['data-tag-id'].value,
iconHTML: node.querySelector('.nav-icon').innerHTML
})
})
2020-09-06 10:25:25 +00:00
// by default we render the cards with the random behaviour
seed = window.sessionStorage[seedStorageKey] == null ? {} : JSON.parse(window.sessionStorage[seedStorageKey])
let res = shuffle(organizations, seed)
organizations = res[0]
originalRandom = JSON.stringify(organizations)
seed = res[1]
enableTag(navAll, false, true)
2020-09-06 10:25:25 +00:00
window.sessionStorage.setItem(seedStorageKey, JSON.stringify(seed))
// if (window.sessionStorage[scrollPointStorageKey] != null) {
// let organizationFocus = document
// .querySelectorAll('.card-container .card')
// console.log(organizationFocus)
// organizationFocus = organizationFocus
// .filter(e => e.getAttribute('data-organization-id') === window.sessionStorage[scrollPointStorageKey])
// if (organizationFocus.length > 0) {
// organizationFocus.scrollIntoView(true)
// }
// }
})