{"id":38,"date":"2025-12-29T21:43:59","date_gmt":"2025-12-29T21:43:59","guid":{"rendered":"https:\/\/jazzfluencers.nl\/?page_id=38"},"modified":"2026-02-17T08:11:44","modified_gmt":"2026-02-17T08:11:44","slug":"tour","status":"publish","type":"page","link":"https:\/\/jazzfluencers.nl\/en\/tour\/","title":{"rendered":"Tour dates"},"content":{"rendered":"\n<h2 class=\"section-title\">Tour Dates<\/h2>\n<div class=\"tour-table-wrap\" aria-label=\"Tour dates\">\n\n  <table class=\"tour-table\">\n    <tbody id=\"bit-tour-body\">\n      <tr class=\"tour-year\">\n        <td colspan=\"6\"><strong>Shows laden&#8230;<\/strong><\/td>\n      <\/tr>\n    <\/tbody>\n  <\/table>\n\n  <script>\n    (function () {\n      \/\/ 1) Bandsintown app id (die had je al)\n      const APP_ID = \"f88fe811fe34e09014c2259caf93c83d\";\n\n      \/\/ 2) Probeer eerst met Bandsintown artist id (zoals in je widget)\n      const ARTIST_ID = \"id_15533268\";\n\n      \/\/ 3) Fallback: artiestnaam (alleen als id endpoint niet werkt)\n      const ARTIST_NAME_FALLBACK = \"Boris van der Lek and the JazzFluencers\";\n\n      const tbody = document.getElementById(\"bit-tour-body\");\n\n      function escapeHtml(str) {\n        return String(str ?? \"\")\n          .replaceAll(\"&\", \"&amp;\")\n          .replaceAll(\"<\", \"&lt;\")\n          .replaceAll(\">\", \"&gt;\")\n          .replaceAll('\"', \"&quot;\")\n          .replaceAll(\"'\", \"&#039;\");\n      }\n\n      \/\/ Nederlandse \u201cjan feb mrt \u2026\u201d\n      const months = [\"jan\",\"feb\",\"mrt\",\"apr\",\"mei\",\"jun\",\"jul\",\"aug\",\"sep\",\"okt\",\"nov\",\"dec\"];\n\n      function formatDateNL(iso) {\n        \/\/ iso like 2026-11-18T20:00:00 or 2026-11-18\n        const d = new Date(iso);\n        const day = String(d.getDate()).padStart(2, \"0\");\n        const mon = months[d.getMonth()];\n        return `${day} ${mon}`;\n      }\n\n      function formatTime(iso) {\n        const d = new Date(iso);\n        const hh = String(d.getHours()).padStart(2, \"0\");\n        const mm = String(d.getMinutes()).padStart(2, \"0\");\n        \/\/ als tijd niet bekend is, geeft Date vaak 00:00, dan tonen we leeg\n        if (hh === \"00\" && mm === \"00\") return \"\";\n        return `${hh}:${mm}`;\n      }\n\n      function yearFrom(iso) {\n        return new Date(iso).getFullYear();\n      }\n\n      function buildRow(ev) {\n        \/\/ Venue + city\n        const venue = ev?.venue?.name || \"\";\n        const city = ev?.venue?.city || \"\";\n\n        \/\/ Start datetime\n        const startsAt = ev?.starts_at || ev?.datetime || ev?.startsAt || ev?.date || \"\";\n        const dateTxt = startsAt ? formatDateNL(startsAt) : \"\";\n        const timeTxt = startsAt ? formatTime(startsAt) : \"\";\n\n        \/\/ Ticket \/ info link:\n        \/\/ Bandsintown geeft vaak 'url' (event pagina) en soms 'offers' (tickets)\n        let infoUrl = ev?.url || \"\";\n        if (Array.isArray(ev?.offers) && ev.offers.length) {\n          const ticketOffer = ev.offers.find(o => (o?.type || \"\").toLowerCase() === \"tickets\") || ev.offers[0];\n          if (ticketOffer?.url) infoUrl = ticketOffer.url;\n        }\n\n        \/\/ Event naam: gebruik description\/lineup\/title als die er is, anders leeg\n        \/\/ (Als je altijd \u201cAlbum Release Tour\u201d wil, zet dan hieronder const eventName = \"Album Release Tour\";)\n        const eventName = ev?.title || ev?.description || \"Album Release Tour\";\n\n        return `\n          <tr>\n            <td data-label=\"Datum\">${escapeHtml(dateTxt)}<\/td>\n            <td data-label=\"Event\">${escapeHtml(eventName)}<\/td>\n            <td data-label=\"Locatie\">${escapeHtml(venue)}<\/td>\n            <td data-label=\"Plaats\">${escapeHtml(city)}<\/td>\n            <td data-label=\"Tijd\">${escapeHtml(timeTxt)}<\/td>\n            <td data-label=\"Info\">\n              ${infoUrl ? `<a class=\"textlink\" href=\"${escapeHtml(infoUrl)}\" target=\"_blank\" rel=\"noopener\">info<\/a>` : \"\"}\n            <\/td>\n          <\/tr>\n        `;\n      }\n\n      function render(events) {\n        if (!Array.isArray(events) || events.length === 0) {\n          tbody.innerHTML = `\n            <tr class=\"tour-year\"><td colspan=\"6\"><strong>Geen shows gevonden<\/strong><\/td><\/tr>\n          `;\n          return;\n        }\n\n        \/\/ Alleen komende + verleden zoals jij wil? Jij wilde alles in de widget: display-limit all\n        \/\/ Hier laten we alles zien en sorteren oplopend.\n        events.sort((a, b) => {\n          const da = new Date(a?.starts_at || a?.datetime || 0).getTime();\n          const db = new Date(b?.starts_at || b?.datetime || 0).getTime();\n          return da - db;\n        });\n\n        let html = \"\";\n        let currentYear = null;\n\n        for (const ev of events) {\n          const startsAt = ev?.starts_at || ev?.datetime || \"\";\n          if (!startsAt) continue;\n\n          const y = yearFrom(startsAt);\n          if (y !== currentYear) {\n            currentYear = y;\n            html += `\n              <tr class=\"tour-year\">\n                <td colspan=\"6\"><strong>${escapeHtml(String(currentYear))}<\/strong><\/td>\n              <\/tr>\n            `;\n          }\n          html += buildRow(ev);\n        }\n\n        tbody.innerHTML = html || `\n          <tr class=\"tour-year\"><td colspan=\"6\"><strong>Geen bruikbare events gevonden<\/strong><\/td><\/tr>\n        `;\n      }\n\n      async function fetchEventsByArtistPath(artistPath) {\n        const url = `https:\/\/rest.bandsintown.com\/${artistPath}\/events?app_id=${encodeURIComponent(APP_ID)}`;\n        const res = await fetch(url, { method: \"GET\" });\n        if (!res.ok) throw new Error(\"Bandsintown fetch failed\");\n        return await res.json();\n      }\n\n      (async function init() {\n        try {\n          \/\/ poging 1: artist id\n          const events = await fetchEventsByArtistPath(`artists\/${encodeURIComponent(ARTIST_ID)}`);\n          if (Array.isArray(events)) {\n            render(events);\n            return;\n          }\n          throw new Error(\"Unexpected response\");\n        } catch (e1) {\n          try {\n            \/\/ poging 2: fallback op artiestnaam\n            const events2 = await fetchEventsByArtistPath(`artists\/${encodeURIComponent(ARTIST_NAME_FALLBACK)}`);\n            render(events2);\n          } catch (e2) {\n            tbody.innerHTML = `\n              <tr class=\"tour-year\">\n                <td colspan=\"6\"><strong>Shows konden niet laden<\/strong><\/td>\n              <\/tr>\n            `;\n          }\n        }\n      })();\n    })();\n  <\/script>\n\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Tour Dates Shows laden&#8230;<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"ngg_post_thumbnail":0,"footnotes":""},"class_list":["post-38","page","type-page","status-publish","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/jazzfluencers.nl\/en\/wp-json\/wp\/v2\/pages\/38","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jazzfluencers.nl\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/jazzfluencers.nl\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/jazzfluencers.nl\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jazzfluencers.nl\/en\/wp-json\/wp\/v2\/comments?post=38"}],"version-history":[{"count":35,"href":"https:\/\/jazzfluencers.nl\/en\/wp-json\/wp\/v2\/pages\/38\/revisions"}],"predecessor-version":[{"id":340,"href":"https:\/\/jazzfluencers.nl\/en\/wp-json\/wp\/v2\/pages\/38\/revisions\/340"}],"wp:attachment":[{"href":"https:\/\/jazzfluencers.nl\/en\/wp-json\/wp\/v2\/media?parent=38"}],"curies":[{"name":"WP","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}