You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

184 lines
4.2 KiB

'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 = `<div style="max-width: 1280px; margin: 1rem auto;">
<h1 style="all: unset; font-size: 1.5rem; font-weight: bold; display: block;">Syntax Error:</h1>
<pre style="all: unset; padding: 10px 15px; background-color: #ffe6e6; border: 1px solid red; border-radius: 0.25rem; overflow: auto; display: block; white-space: pre;">${e.toString()}</pre>
</div>`;
}
target.innerHTML = html;
if (reload) {
reload();
}
}
})();