Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
dakur committed Feb 4, 2025
1 parent 4e6ea29 commit e07a721
Showing 1 changed file with 244 additions and 8 deletions.
252 changes: 244 additions & 8 deletions scripts/administrativeUnitsMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,141 @@
}
*/

/* TODO: tohle skoro mám až na to že nejsem schopen rozjet přepínání vrstev */

document.addEventListener('DOMContentLoaded', async function () {
const { Map } = await google.maps.importLibrary("maps");
const map = await initializeMap();
const filters = initializeFilters(map);

// custom behavior for hnuti-brontosaurus page
// ideally, administrativeUnitsMap should export API, but there's no time play with it now
const unitBaseLinkEl = document.getElementById('about-structure-unit-base-link');
if (unitBaseLinkEl !== null) {
unitBaseLinkEl.addEventListener('click', () => // listen to base unit link as well
filters.displayLayer(document.getElementById('mapa-zakladni-clanky')));
}

window.addEventListener('load', () => { // finally once the page is loaded, check if a layer filter should be activated
const hash = window.location.hash.substring(1);

const selectedFilterLinkEl = hash !== ''
? document.querySelector(`.administrativeUnitsMap__filters #${hash}`)
: null;

if (selectedFilterLinkEl !== null) { // no filtering element with given hash found => do not filter
filters.displayLayer(selectedFilterLinkEl);

} else {
filters.displayAll();
}
});
});


/* MAP */

async function initializeMap()
{
const { Map, Data } = await google.maps.importLibrary("maps");
const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");

const mapEl = document.getElementById("map");
const administrativeUnits = JSON.parse(mapEl.getAttribute('data-administrativeUnits'));

const map = new Map(mapEl, {
center: { lat: 49.000, lng: 16.000 },
zoom: 8,
center: { lat: 49.7437572, lng: 15.3386383 }, // Czechia geographic center, see https://en.mapy.cz/s/gupehogeha
zoom: 7,
mapId: "b80d048e42b74f71",
});
const bounds = new google.maps.LatLngBounds();
let currentInfoWindow;

const markers = [];
const slugs = [];
const layers = new google.maps.MVCObject();
const layersObj = {};

// todo bulk add?
for (const unit of administrativeUnits) {

// collect slugs
const slug = resolveUnitTypeSlug(unit);
if ( !! slug && ! slugs.includes(slug)) {
slugs.push(slug);
}

// customize pin style
const color = resolveColor(unit);
const pinEl = new PinElement({
background: color,
glyphColor: color,
});

// set marker
const coords = { lat: unit.lat, lng: unit.lng };
const marker = new AdvancedMarkerElement({
map: map,
position: { lat: unit.lat, lng: unit.lng },
position: coords,
title: unit.name,
content: pinEl.element,
});
bounds.extend(new google.maps.LatLng(unit.lat, unit.lng));

// create info window
const infoWindow = new google.maps.InfoWindow({
content: buildInfoWindow(unit).outerHTML,
ariaLabel: unit.name,
});
marker.addListener('click', () => {
currentInfoWindow?.close();
currentInfoWindow = infoWindow;

infoWindow.open({
anchor: marker,
map,
})
});

// add to layer
if ( ! layersObj.hasOwnProperty(slug)) {
layersObj[slug] = [];
}
layersObj[slug].push(marker);
continue;
const markerVisibility = new google.maps.MVCObject();
markerVisibility.set("visible", true); // Default to visible
markerVisibility.bindTo("visible", layers, slug); // Sync with model
/*dataLayer.add({
geometry: coords,
properties: { type: resolveUnitTypeSlug(unit) }
});*/
//marker.bindTo('map', layers, slug);
/* console.log(slugs, layers.get('base'));
layers.bindTo(slug, marker);*/
//markers.push(marker);
markerVisibility.bindTo(slug, markerVisibility, "visible"); // Sync marker with markerVisibility
}

map.centerAndZoom();
});
map.fitBounds(bounds);

function resolveColor(unit) {
return {
displayLayer(filterSlug) {
/*const allVisible = typeof filterSlug === 'undefined';
markers.forEach(marker => {
const isVisible = allVisible || marker.type === filterSlug;
markers.set("visible_" + marker.type, isVisible);
});
return;*/
const allVisible = typeof filterSlug === 'undefined';
slugs.forEach(slug => {
//layers.set(slug, slug === filterSlug || allVisible/* ? map : null*/));
layersObj[slug].forEach(marker => marker.setMap(allVisible || slug === filterSlug ? map : null));
});
},
};
}

function resolveColor(unit)
{
// todo true colors
if (unit.isOfTypeClub) return "violet";
if (unit.isOfTypeBase) return "orange";
Expand All @@ -58,3 +161,136 @@ function resolveColor(unit) {
if (unit.isOfTypeChildren) return "pink";
throw new Error("Unsupported unit type");
}


function buildInfoWindow(unit)
{
const containerEl = document.createElement('div');
containerEl.id = 'infowindow';
containerEl.classList.add('administrativeUnitsMap__infoWindow')

if (unit.image !== null) {
const imageContainerEl = containerEl.appendChild(document.createElement('div'));
imageContainerEl.classList.add('administrativeUnitsMap__infoWindowImageContainer');
const imageEl = imageContainerEl.appendChild(document.createElement('img'));
imageEl.classList.add('administrativeUnitsMap__infoWindowImage');
imageEl.src = unit.image;
}

const contentEl = containerEl.appendChild(document.createElement('div'));
const metaEl = contentEl.appendChild(document.createElement('div'));

metaEl.innerHTML = resolveUnitTitle(unit);
metaEl.innerHTML += `<br>Adresa: ${unit.address}`;

if (unit.chairman !== null) {
metaEl.innerHTML += `<br>Předseda: ${unit.chairman}`;
}

if (unit.website !== null ) {
metaEl.innerHTML += `<br>Web: <a href="${unit.website}" target="_blank">${unit.website}</a>`
}

if (unit.email !== null) {
metaEl.innerHTML += `<br>E-mail: <a href="mailto:${unit.email}">${unit.email}</a>`;
}

if (unit.description !== null) {
const descriptionEl = contentEl.appendChild(document.createElement('p'));
descriptionEl.classList.add('administrativeUnitsMap__infoWindowDescription')
descriptionEl.innerHTML += unit.description;
}

return containerEl;
}

function resolveUnitTitle(unit)
{
const type = resolveUnitTypeLabel(unit);
if (type === null) {
return unit.name;
}

return `${unit.name}${type}`;
}

function resolveUnitTypeLabel(unit)
{
switch (true) {
case unit.isOfTypeClub:
return 'klub';

case unit.isOfTypeBase:
return 'základní článek';

case unit.isOfTypeRegional:
return 'regionální centrum';

case unit.isOfTypeOffice:
return 'ústředí';

case unit.isOfTypeChildren:
return 'dětský oddíl';
}

return null;
}

function resolveUnitTypeSlug(unit)
{
if (unit.isOfTypeClub) {
return 'club';

} else if (unit.isOfTypeBase) {
return 'base';

} else if (unit.isOfTypeRegional) {
return 'regional';

} else if (unit.isOfTypeOffice) {
return 'office';

} else if (unit.isOfTypeChildren) {
return 'children';

} else { // no option selected, fall back to Google Maps default marker
return;
}
}


/* FILTERS */

function initializeFilters({displayLayer: mapDisplayLayer})
{
const ActiveFilterSelector = 'administrativeUnitsMap__filter--active';

const filters = document.querySelectorAll('.administrativeUnitsMap__filter');

const updateFilterActiveState = (active) => {
filters.forEach(filterEl =>
filterEl.classList.remove(ActiveFilterSelector));

active.classList.add(ActiveFilterSelector);
}

const displayAll = () => {
updateFilterActiveState(document.getElementById('mapa-vse'));
mapDisplayLayer();
}
const displayLayer = (filterEl) => {
updateFilterActiveState(filterEl);
mapDisplayLayer(filterEl.dataset.slug);
};

// initialize filters (listen to click events)
filters.forEach(filterEl =>
filterEl.addEventListener('click', ev => {
window.history.pushState(null, '', filterEl.children[0].getAttribute('href'));
ev.preventDefault();

displayLayer(filterEl);
}));

return {displayAll, displayLayer};
}

0 comments on commit e07a721

Please sign in to comment.