'use strict'; window.initBlock = initBlock; let template; let data = {}; let reload; // Blocks Initialization. function initBlock(blockName = '', selector = '', cb) { reload = function () { document.querySelectorAll(selector).forEach((el) => cb(el)); } reload(); } // Data Updates Listeners. (function () { const block = getQueryParams().block; loadDataOptions(); listenToDataOptionsUpdates(); function listenToDataOptionsUpdates() { window.addEventListener('message', function (event) { const message = event.data; const prefix = 'dataUpdate:'; if (typeof message !== "string" || !message.startsWith(prefix)) { return; } try { data = JSON.parse(message.substring(prefix.length)); updateBlock({data}); } catch (e) { console.log('Error parsing incoming data.', e); } }); } function getQueryParams() { const urlParams = new URLSearchParams(window.location.search); const params = {}; for (const [key, value] of urlParams) { params[key] = value; } return params; } function loadDataOptions() { const queryParameters = new URLSearchParams({ block, name: getQueryParams().data || 'default' }); fetch(`/data?${queryParameters}`) .then((response) => response.json()) .then((response) => { data = response.data; // Update state. updateBlock({data}); }) } // Listen to Template updates. initSocket(); function initSocket() { const socket = window.io.connect('', {query: `block=${block}`}); socket.on('error', function (err) { console.log(err); }); // socket.on('connect', function () { // console.log('user connected', socket.id) // }); socket.on('templateUpdate', function (args) { updateBlock({template: args.template}); }); socket.on('scriptUpdate', function (args) { const tag = updateTag('block-script'); tag.onload = () => { updateBlock({template: args.template}); } }); socket.on('styleUpdate', function (args) { updateTag('block-stylesheet'); }); } function updateTag(id) { const tag = document.getElementById(id); const wrapper = tag.parentNode; let clone; let attr; if (tag.tagName === 'SCRIPT') { clone = document.createElement('script'); clone.type = 'text/javascript'; attr = 'src'; } else if (tag.tagName === 'LINK') { clone = document.createElement('link'); clone.rel = 'stylesheet'; attr = 'href'; } clone.id = id; // Add version to the stylesheet URL, make sure we override the cache and already existing version there. clone[attr] = tag[attr].replace(/(\?v=)[^&]+/, `$1${Date.now()}`); tag.remove(); wrapper.append(clone); return clone; } function updateBlock(args = {}) { if (args.template) { template = args.template; // Update state. } if (args.data) { data = args.data; // Update state. } if (!template) { return; } renderBlock(template, data || {}, document.getElementById("hbs-container")); } function renderBlock(templateHbs, jsonData, target) { const template = Handlebars.compile(templateHbs); /** * Handlebars Helpers */ Handlebars.registerHelper('esc_attr', function (attr) { return attr; }); Handlebars.registerHelper('esc_url', function (attr) { return attr; }); Handlebars.registerHelper('esc_html', function (attr) { return attr; }); Handlebars.registerHelper('base_url', function () { const list = ['block']; if (block) { list.push(block.substr(1)); } return ['', ...list, ''].join('/'); }); let html; try { html = template(jsonData); } catch (e) { html = `

Syntax Error:

${e.toString()}
`; } target.innerHTML = html; if (reload) { reload(); } } })();