From 946c0998c699d76103d7bcf33bf80a50db800880 Mon Sep 17 00:00:00 2001 From: monzwe <172489948+monzwe@users.noreply.github.com> Date: Mon, 4 May 2026 15:13:56 +0200 Subject: [PATCH] Read alternative hike details from Google Sheet --- assets/css/custom-styles.css | 16 ++ assets/js/count.js | 426 +++++++++++++++++------------------ deutsch.html | 44 +++- english.html | 44 +++- espagnol.html | 46 +++- index.html | 43 ++++ 6 files changed, 402 insertions(+), 217 deletions(-) diff --git a/assets/css/custom-styles.css b/assets/css/custom-styles.css index eb1e452..7c2866e 100644 --- a/assets/css/custom-styles.css +++ b/assets/css/custom-styles.css @@ -39,6 +39,22 @@ font-style: italic; font-weight: lighter; } + +/* Style for additional hikes details */ + +#cards { + border: 1px solid #fde5cb; + border-left-width: 0.3125rem; + border-radius: 0.3125rem 0.1875rem 0.1875rem 0.3125rem; + border-left-color: #fff; + padding: 0rem 0.9375rem 0rem 0.625rem; + margin: 0 1.25rem 0 0.3125rem; +} + +.card p { + margin: 0 5px 18px 5px; +} + /*! * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) diff --git a/assets/js/count.js b/assets/js/count.js index 6240f4a..b9629de 100644 --- a/assets/js/count.js +++ b/assets/js/count.js @@ -1,214 +1,214 @@ -;(function() { - 'use strict'; - if (window.goatcounter && window.goatcounter.vars) - window.goatcounter = window.goatcounter.vars - else - window.goatcounter = window.goatcounter || {} - var s = document.querySelector('script[data-goatcounter]') - if (s && s.dataset.goatcounterSettings) { - try { var set = JSON.parse(s.dataset.goatcounterSettings) } - catch (err) { console.error('invalid JSON in data-goatcounter-settings: ' + err) } - for (var k in set) - if (['no_onload', 'no_events', 'allow_local', 'allow_frame', 'path', 'title', 'referrer', 'event'].indexOf(k) > -1) - window.goatcounter[k] = set[k] - } - var enc = encodeURIComponent - var get_data = function(vars) { - var data = { - p: (vars.path === undefined ? goatcounter.path : vars.path), - r: (vars.referrer === undefined ? goatcounter.referrer : vars.referrer), - t: (vars.title === undefined ? goatcounter.title : vars.title), - e: !!(vars.event || goatcounter.event), - s: [window.screen.width, window.screen.height, (window.devicePixelRatio || 1)], - b: is_bot(), - q: location.search, - } - var rcb, pcb, tcb - if (typeof(data.r) === 'function') rcb = data.r - if (typeof(data.t) === 'function') tcb = data.t - if (typeof(data.p) === 'function') pcb = data.p - if (is_empty(data.r)) data.r = document.referrer - if (is_empty(data.t)) data.t = document.title - if (is_empty(data.p)) data.p = get_path() - if (rcb) data.r = rcb(data.r) - if (tcb) data.t = tcb(data.t) - if (pcb) data.p = pcb(data.p) - return data - } - var is_empty = function(v) { return v === null || v === undefined || typeof(v) === 'function' } - var is_bot = function() { - var w = window, d = document - if (w.callPhantom || w._phantom || w.phantom) - return 150 - if (w.__nightmare) - return 151 - if (d.__selenium_unwrapped || d.__webdriver_evaluate || d.__driver_evaluate) - return 152 - if (navigator.webdriver) - return 153 - return 0 - } - var urlencode = function(obj) { - var p = [] - for (var k in obj) - if (obj[k] !== '' && obj[k] !== null && obj[k] !== undefined && obj[k] !== false) - p.push(enc(k) + '=' + enc(obj[k])) - return '?' + p.join('&') - } - var warn = function(msg) { - if (console && 'warn' in console) - console.warn('goatcounter: ' + msg) - } - var get_endpoint = function() { - var s = document.querySelector('script[data-goatcounter]') - if (s && s.dataset.goatcounter) - return s.dataset.goatcounter - return (goatcounter.endpoint || window.counter) - } - var get_path = function() { - var loc = location, - c = document.querySelector('link[rel="canonical"][href]') - if (c) { - var a = document.createElement('a') - a.href = c.href - if (a.hostname.replace(/^www\./, '') === location.hostname.replace(/^www\./, '')) - loc = a - } - return (loc.pathname + loc.search) || '/' - } - var on_load = function(f) { - if (document.body === null) - document.addEventListener('DOMContentLoaded', function() { f() }, false) - else - f() - } - goatcounter.filter = function() { - if ('visibilityState' in document && document.visibilityState === 'prerender') - return 'visibilityState' - if (!goatcounter.allow_frame && location !== parent.location) - return 'frame' - if (!goatcounter.allow_local && location.hostname.match(/(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/)) - return 'localhost' - if (!goatcounter.allow_local && location.protocol === 'file:') - return 'localfile' - if (localStorage && localStorage.getItem('skipgc') === 't') - return 'disabled with #toggle-goatcounter' - return false - } - window.goatcounter.url = function(vars) { - var data = get_data(vars || {}) - if (data.p === null) - return - data.rnd = Math.random().toString(36).substr(2, 5) - var endpoint = get_endpoint() - if (!endpoint) - return warn('no endpoint found') - return endpoint + urlencode(data) - } - window.goatcounter.count = function(vars) { - var f = goatcounter.filter() - if (f) - return warn('not counting because of: ' + f) - var url = goatcounter.url(vars) - if (!url) - return warn('not counting because path callback returned null') - var img = document.createElement('img') - img.src = url - img.style.position = 'absolute' - img.style.bottom = '0px' - img.style.width = '1px' - img.style.height = '1px' - img.loading = 'eager' - img.setAttribute('alt', '') - img.setAttribute('aria-hidden', 'true') - var rm = function() { if (img && img.parentNode) img.parentNode.removeChild(img) } - img.addEventListener('load', rm, false) - document.body.appendChild(img) - } - window.goatcounter.get_query = function(name) { - var s = location.search.substr(1).split('&') - for (var i = 0; i < s.length; i++) - if (s[i].toLowerCase().indexOf(name.toLowerCase() + '=') === 0) - return s[i].substr(name.length + 1) - } - window.goatcounter.bind_events = function() { - if (!document.querySelectorAll) - return - var send = function(elem) { - return function() { - goatcounter.count({ - event: true, - path: (elem.dataset.goatcounterClick || elem.name || elem.id || ''), - title: (elem.dataset.goatcounterTitle || elem.title || (elem.innerHTML || '').substr(0, 200) || ''), - referrer: (elem.dataset.goatcounterReferrer || elem.dataset.goatcounterReferral || ''), - }) - } - } - Array.prototype.slice.call(document.querySelectorAll("*[data-goatcounter-click]")).forEach(function(elem) { - if (elem.dataset.goatcounterBound) - return - var f = send(elem) - elem.addEventListener('click', f, false) - elem.addEventListener('auxclick', f, false) - elem.dataset.goatcounterBound = 'true' - }) - } - window.goatcounter.visit_count = function(opt) { - on_load(function() { - opt = opt || {} - opt.type = opt.type || 'html' - opt.append = opt.append || 'body' - opt.path = opt.path || get_path() - opt.attr = opt.attr || {width: '200', height: (opt.no_branding ? '60' : '80')} - opt.attr['src'] = get_endpoint() + 'er/' + enc(opt.path) + '.' + enc(opt.type) + '?' - if (opt.no_branding) opt.attr['src'] += '&no_branding=1' - if (opt.style) opt.attr['src'] += '&style=' + enc(opt.style) - if (opt.start) opt.attr['src'] += '&start=' + enc(opt.start) - if (opt.end) opt.attr['src'] += '&end=' + enc(opt.end) - var tag = {png: 'img', svg: 'img', html: 'iframe'}[opt.type] - if (!tag) - return warn('visit_count: unknown type: ' + opt.type) - if (opt.type === 'html') { - opt.attr['frameborder'] = '0' - opt.attr['scrolling'] = 'no' - } - var d = document.createElement(tag) - for (var k in opt.attr) - d.setAttribute(k, opt.attr[k]) - var p = document.querySelector(opt.append) - if (!p) - return warn('visit_count: append not found: ' + opt.append) - p.appendChild(d) - }) - } - if (location.hash === '#toggle-goatcounter') { - if (localStorage.getItem('skipgc') === 't') { - localStorage.removeItem('skipgc', 't') - alert('GoatCounter tracking is now ENABLED in this browser.') - } - else { - localStorage.setItem('skipgc', 't') - alert('GoatCounter tracking is now DISABLED in this browser until ' + location + ' is loaded again.') - } - } - if (!goatcounter.no_onload) - on_load(function() { - // 1. Page is visible, count request. - // 2. Page is not yet visible; wait until it switches to 'visible' and count. - // See #487 - if (!('visibilityState' in document) || document.visibilityState === 'visible') - goatcounter.count() - else { - var f = function(e) { - if (document.visibilityState !== 'visible') - return - document.removeEventListener('visibilitychange', f) - goatcounter.count() - } - document.addEventListener('visibilitychange', f) - } - - if (!goatcounter.no_events) - goatcounter.bind_events() - }) +;(function() { + 'use strict'; + if (window.goatcounter && window.goatcounter.vars) + window.goatcounter = window.goatcounter.vars + else + window.goatcounter = window.goatcounter || {} + var s = document.querySelector('script[data-goatcounter]') + if (s && s.dataset.goatcounterSettings) { + try { var set = JSON.parse(s.dataset.goatcounterSettings) } + catch (err) { console.error('invalid JSON in data-goatcounter-settings: ' + err) } + for (var k in set) + if (['no_onload', 'no_events', 'allow_local', 'allow_frame', 'path', 'title', 'referrer', 'event'].indexOf(k) > -1) + window.goatcounter[k] = set[k] + } + var enc = encodeURIComponent + var get_data = function(vars) { + var data = { + p: (vars.path === undefined ? goatcounter.path : vars.path), + r: (vars.referrer === undefined ? goatcounter.referrer : vars.referrer), + t: (vars.title === undefined ? goatcounter.title : vars.title), + e: !!(vars.event || goatcounter.event), + s: [window.screen.width, window.screen.height, (window.devicePixelRatio || 1)], + b: is_bot(), + q: location.search, + } + var rcb, pcb, tcb + if (typeof(data.r) === 'function') rcb = data.r + if (typeof(data.t) === 'function') tcb = data.t + if (typeof(data.p) === 'function') pcb = data.p + if (is_empty(data.r)) data.r = document.referrer + if (is_empty(data.t)) data.t = document.title + if (is_empty(data.p)) data.p = get_path() + if (rcb) data.r = rcb(data.r) + if (tcb) data.t = tcb(data.t) + if (pcb) data.p = pcb(data.p) + return data + } + var is_empty = function(v) { return v === null || v === undefined || typeof(v) === 'function' } + var is_bot = function() { + var w = window, d = document + if (w.callPhantom || w._phantom || w.phantom) + return 150 + if (w.__nightmare) + return 151 + if (d.__selenium_unwrapped || d.__webdriver_evaluate || d.__driver_evaluate) + return 152 + if (navigator.webdriver) + return 153 + return 0 + } + var urlencode = function(obj) { + var p = [] + for (var k in obj) + if (obj[k] !== '' && obj[k] !== null && obj[k] !== undefined && obj[k] !== false) + p.push(enc(k) + '=' + enc(obj[k])) + return '?' + p.join('&') + } + var warn = function(msg) { + if (console && 'warn' in console) + console.warn('goatcounter: ' + msg) + } + var get_endpoint = function() { + var s = document.querySelector('script[data-goatcounter]') + if (s && s.dataset.goatcounter) + return s.dataset.goatcounter + return (goatcounter.endpoint || window.counter) + } + var get_path = function() { + var loc = location, + c = document.querySelector('link[rel="canonical"][href]') + if (c) { + var a = document.createElement('a') + a.href = c.href + if (a.hostname.replace(/^www\./, '') === location.hostname.replace(/^www\./, '')) + loc = a + } + return (loc.pathname + loc.search) || '/' + } + var on_load = function(f) { + if (document.body === null) + document.addEventListener('DOMContentLoaded', function() { f() }, false) + else + f() + } + goatcounter.filter = function() { + if ('visibilityState' in document && document.visibilityState === 'prerender') + return 'visibilityState' + if (!goatcounter.allow_frame && location !== parent.location) + return 'frame' + if (!goatcounter.allow_local && location.hostname.match(/(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/)) + return 'localhost' + if (!goatcounter.allow_local && location.protocol === 'file:') + return 'localfile' + if (localStorage && localStorage.getItem('skipgc') === 't') + return 'disabled with #toggle-goatcounter' + return false + } + window.goatcounter.url = function(vars) { + var data = get_data(vars || {}) + if (data.p === null) + return + data.rnd = Math.random().toString(36).substr(2, 5) + var endpoint = get_endpoint() + if (!endpoint) + return warn('no endpoint found') + return endpoint + urlencode(data) + } + window.goatcounter.count = function(vars) { + var f = goatcounter.filter() + if (f) + return warn('not counting because of: ' + f) + var url = goatcounter.url(vars) + if (!url) + return warn('not counting because path callback returned null') + var img = document.createElement('img') + img.src = url + img.style.position = 'absolute' + img.style.bottom = '0px' + img.style.width = '1px' + img.style.height = '1px' + img.loading = 'eager' + img.setAttribute('alt', '') + img.setAttribute('aria-hidden', 'true') + var rm = function() { if (img && img.parentNode) img.parentNode.removeChild(img) } + img.addEventListener('load', rm, false) + document.body.appendChild(img) + } + window.goatcounter.get_query = function(name) { + var s = location.search.substr(1).split('&') + for (var i = 0; i < s.length; i++) + if (s[i].toLowerCase().indexOf(name.toLowerCase() + '=') === 0) + return s[i].substr(name.length + 1) + } + window.goatcounter.bind_events = function() { + if (!document.querySelectorAll) + return + var send = function(elem) { + return function() { + goatcounter.count({ + event: true, + path: (elem.dataset.goatcounterClick || elem.name || elem.id || ''), + title: (elem.dataset.goatcounterTitle || elem.title || (elem.innerHTML || '').substr(0, 200) || ''), + referrer: (elem.dataset.goatcounterReferrer || elem.dataset.goatcounterReferral || ''), + }) + } + } + Array.prototype.slice.call(document.querySelectorAll("*[data-goatcounter-click]")).forEach(function(elem) { + if (elem.dataset.goatcounterBound) + return + var f = send(elem) + elem.addEventListener('click', f, false) + elem.addEventListener('auxclick', f, false) + elem.dataset.goatcounterBound = 'true' + }) + } + window.goatcounter.visit_count = function(opt) { + on_load(function() { + opt = opt || {} + opt.type = opt.type || 'html' + opt.append = opt.append || 'body' + opt.path = opt.path || get_path() + opt.attr = opt.attr || {width: '200', height: (opt.no_branding ? '60' : '80')} + opt.attr['src'] = get_endpoint() + 'er/' + enc(opt.path) + '.' + enc(opt.type) + '?' + if (opt.no_branding) opt.attr['src'] += '&no_branding=1' + if (opt.style) opt.attr['src'] += '&style=' + enc(opt.style) + if (opt.start) opt.attr['src'] += '&start=' + enc(opt.start) + if (opt.end) opt.attr['src'] += '&end=' + enc(opt.end) + var tag = {png: 'img', svg: 'img', html: 'iframe'}[opt.type] + if (!tag) + return warn('visit_count: unknown type: ' + opt.type) + if (opt.type === 'html') { + opt.attr['frameborder'] = '0' + opt.attr['scrolling'] = 'no' + } + var d = document.createElement(tag) + for (var k in opt.attr) + d.setAttribute(k, opt.attr[k]) + var p = document.querySelector(opt.append) + if (!p) + return warn('visit_count: append not found: ' + opt.append) + p.appendChild(d) + }) + } + if (location.hash === '#toggle-goatcounter') { + if (localStorage.getItem('skipgc') === 't') { + localStorage.removeItem('skipgc', 't') + alert('GoatCounter tracking is now ENABLED in this browser.') + } + else { + localStorage.setItem('skipgc', 't') + alert('GoatCounter tracking is now DISABLED in this browser until ' + location + ' is loaded again.') + } + } + if (!goatcounter.no_onload) + on_load(function() { + // 1. Page is visible, count request. + // 2. Page is not yet visible; wait until it switches to 'visible' and count. + // See #487 + if (!('visibilityState' in document) || document.visibilityState === 'visible') + goatcounter.count() + else { + var f = function(e) { + if (document.visibilityState !== 'visible') + return + document.removeEventListener('visibilitychange', f) + goatcounter.count() + } + document.addEventListener('visibilitychange', f) + } + + if (!goatcounter.no_events) + goatcounter.bind_events() + }) })(); \ No newline at end of file diff --git a/deutsch.html b/deutsch.html index d6100fb..95cb4f6 100644 --- a/deutsch.html +++ b/deutsch.html @@ -6,7 +6,7 @@ language: de ---
-
+
Hello
Ciao
Bonjour
@@ -45,6 +45,14 @@


Nehmen Sie auch ausreichend Wasser mit, da es entlang der Wanderwege auf dem Salève keine Quellen gibt.

+

Zusätzliche Wanderungen

+

Manchmal organisieren wir eine zusätzlichen Treffpunkt, um den Süden des Salève fernab von der Seilbahn zu erkunden. + Nur für erfahrene Wanderer, die bereits mit uns den Salève bestiegen haben. + Einzelheiten werden 1-2 Tage im voraus hier angekündigt, je nach Wetterbedingungen. +

+ +
+
Der Verein lehnt jede Verantwortung für Unfälle ab.
@@ -59,4 +67,38 @@

var options = {'weekday': 'long', 'month': 'long', 'day': '2-digit', 'year': 'numeric'}; var date = d.toLocaleString('de-DE', options); document.getElementById('nextMeeting').innerHTML = "Nächste Wanderung: "+date.toString(); + + const scriptUrl = "https://script.google.com/macros/s/AKfycbxrDnesoYawPLQHClhvAdgQ99RgiN-gSm2uwStbYuDarsovduTptgTzfamoxxQPuR5X/exec"; + + async function loadHikes() { + const container = document.getElementById("cards"); + container.innerHTML = "

Einen Moment...

"; + + try { + const response = await fetch(scriptUrl); + const hikes = await response.json(); + + container.innerHTML = ""; + + hikes.forEach(hike => { + const card = document.createElement("div"); + card.className = "card"; + + card.innerHTML = ` +

${hike.Rdv || ""}
+ ${hike.Stops || ""}
+ ${hike.Details || ""}

+ `; + + container.appendChild(card); + }); + + } catch (err) { + console.error(err); + container.innerHTML = "

Oops.

"; + } + } + + loadHikes(); + diff --git a/english.html b/english.html index 31b5d00..0113afe 100644 --- a/english.html +++ b/english.html @@ -7,7 +7,7 @@ language: en ---
-
+
Hello
Ciao
Bonjour
@@ -42,6 +42,14 @@


Be sure to bring enough water as there are no sources along the hiking paths on the Salève.

+

Additional hikes

+

Sometimes we organise a second meet-up point to explore the south of Mont Salève, far from the cable car. + These hikes are for experienced hikers only, who have walked up the Salève with us before. + Details are announced here 1-2 days in advance, depending on weather conditions. +

+ +
+
The association declines all responsibility in the event of an accident.
@@ -56,4 +64,38 @@

var options = {'weekday': 'long', 'month': 'long', 'day': '2-digit', 'year': 'numeric'}; var date = d.toLocaleString('en-US', options); document.getElementById('nextMeeting').innerHTML = "Next hike: "+date.toString(); + + const scriptUrl = "https://script.google.com/macros/s/AKfycbxrDnesoYawPLQHClhvAdgQ99RgiN-gSm2uwStbYuDarsovduTptgTzfamoxxQPuR5X/exec"; + + async function loadHikes() { + const container = document.getElementById("cards"); + container.innerHTML = "

Loading ...

"; + + try { + const response = await fetch(scriptUrl); + const hikes = await response.json(); + + container.innerHTML = ""; + + hikes.forEach(hike => { + const card = document.createElement("div"); + card.className = "card"; + + card.innerHTML = ` +

${hike.Rdv || ""}
+ ${hike.Stops || ""}
+ ${hike.Details || ""}

+ `; + + container.appendChild(card); + }); + + } catch (err) { + console.error(err); + container.innerHTML = "

Oops.

"; + } + } + + loadHikes(); + diff --git a/espagnol.html b/espagnol.html index 3ce19d5..bbbe4e6 100644 --- a/espagnol.html +++ b/espagnol.html @@ -6,7 +6,7 @@ language: es ---
-
+
Hello
Ciao
Bonjour
@@ -43,6 +43,14 @@


Lleve también suficiente agua, ya que no hay manantiales en los senderos de la Salève.

+

Excursiones adicionales

+

En ocasiones, organizamos un segundo punto de encuentro para explorar la zona sur del Mont Salève, lejos del teleférico. + Estas excursiones son solo para excursionistas experimentados que ya hayan subido al Salève con nosotros. + Los detalles se anuncian aquí con 1-2 días de antelación, dependiendo de la previsión meteorológica. +

+ +
+
La asociación declina toda responsabilidad en caso de accidente.
@@ -56,5 +64,39 @@

} var options = {'weekday': 'long', 'month': 'long', 'day': '2-digit', 'year': 'numeric'}; var date = d.toLocaleString('es-ES', options); -document.getElementById('nextMeeting').innerHTML = "Próximo senderismo: "+date.toString(); +document.getElementById('nextMeeting').innerHTML = "Próxima excursión: "+date.toString(); + + const scriptUrl = "https://script.google.com/macros/s/AKfycbxrDnesoYawPLQHClhvAdgQ99RgiN-gSm2uwStbYuDarsovduTptgTzfamoxxQPuR5X/exec"; + + async function loadHikes() { + const container = document.getElementById("cards"); + container.innerHTML = "

Cargando ...

"; + + try { + const response = await fetch(scriptUrl); + const hikes = await response.json(); + + container.innerHTML = ""; + + hikes.forEach(hike => { + const card = document.createElement("div"); + card.className = "card"; + + card.innerHTML = ` +

${hike.Rdv || ""}
+ ${hike.Stops || ""}
+ ${hike.Details || ""}

+ `; + + container.appendChild(card); + }); + + } catch (err) { + console.error(err); + container.innerHTML = "

Oops.

"; + } + } + + loadHikes(); + diff --git a/index.html b/index.html index 5132277..3f946cb 100644 --- a/index.html +++ b/index.html @@ -45,6 +45,15 @@


Emportez également suffisament d'eau car il n'y a pas de sources le long des sentiers du Salève.

+ +

Randos alternatives

+

Parfois nous organisons un rendez-vous supplémentaire pour explorer le sud du Salève, loin du téléphérique. + Les détails sont confirmés ici 1-2 jours avant, selon la météo. Ces sorties sont + réservées aux randonneurs initiés qui sont déjà montés au Salève avec nous. +

+ +
+