site-manual-notifier/static/js/control.js

233 lines
8.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

var loadingNewData = false;
var indexFromWebSocket = false;
var acceptingRemoteSettings = true;
var currentForm = document.getElementById('currentForm');
var backgroundForm = document.getElementById('backgroundForm');
var currentDisplayIndex = 0;
var nbsp = ' ';
var preview_frame = document.getElementById('preview_frame');
var preview_url = window.location.origin + window.location.pathname.replace(/control\/?$/, 'display/?test=1') + window.location.hash;
preview_frame.setAttribute('src', preview_url);
setTimeout(
() => sendThroughWebSocket(JSON.stringify({
type: 'SettingsRequest'
})),
50
);
function handleMessage(message) {
if (message.type == 'MessageBroadcast')
try {
handleBroadcastedMessage(JSON.parse(message.message));
} catch (e) {
console.error(message);
console.error(e);
}
}
function handleBroadcastedMessage(message) {
if (message.type == 'SettingsRequest')
sendThroughWebSocket(JSON.stringify({
type: 'Settings',
settings: putForm(backgroundForm, getSettings())
}));
else if ((message.type == 'NewSettings') || (message.type == 'Settings' && acceptingRemoteSettings)) {
acceptingRemoteSettings = true;
applyLoadedSettings(message.settings);
updateSendFields();
applyLoadedSettings(message.settings);
acceptingRemoteSettings = false;
}
console.log(message);
}
function downloadTextFile(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
function putForm(form, settings) {
for (let keyPair of Array.from((new FormData(form)).entries()))
settings[keyPair[0]] = keyPair[1];
return settings;
}
function getSettings() {
var settings = {};
for (let form of Array.from(document.querySelectorAll('form.form')))
putForm(form, settings);
settings.templateParams = getTemplateParameters();
return settings;
}
function saveSettings() {
var token = window.location.hash.substr(1);
downloadTextFile(
`manual-notifier_settings_${token}.json`,
JSON.stringify(putForm(backgroundForm, getSettings()))
);
}
function loadSettings(input) {
var file = input.files[0];
input.value = null;
if (file) {
var fr = new FileReader();
fr.onload = () => {
var text = fr.result;
applyLoadedSettings(JSON.parse(text));
};
fr.readAsText(file);
}
}
function loadBackgroundMedia(input) {
if (!input) {
var backgroundMediaHidden = document.getElementById('backgroundMediaHidden');
backgroundMediaHidden.value = '';
updateMediaPreviewAfterChange();
broadcastBackgroundChanges();
} else {
var file = input.files[0];
input.value = null;
var fr = new FileReader();
fr.readAsDataURL(file);
fr.onloadend = () => {
var backgroundMediaHidden = document.getElementById('backgroundMediaHidden');
backgroundMediaHidden.value = fr.result;
updateMediaPreviewAfterChange();
broadcastBackgroundChanges();
};
}
}
function updateMediaPreviewAfterChange() {
var mediaPreview = document.getElementById('mediaPreview');
var backgroundMediaHidden = document.getElementById('backgroundMediaHidden');
var backgroundMediaString = backgroundMediaHidden.value;
mediaPreview.style.backgroundColor = document.getElementById('backgroundColor').value;
if (backgroundMediaString == '') {
mediaPreview.innerHTML = 'No media.';
} else if (backgroundMediaString.startsWith('data:image/')) {
mediaPreview.innerHTML = `<img src="${backgroundMediaString}" style="width: 100%;">`;
} else if (backgroundMediaString.startsWith('data:video/')) {
mediaPreview.innerHTML = `<video src="${backgroundMediaString}" controls playsinline autoplay muted loop style="width: 100%;">`;
} else {
mediaPreview.innerHTML = 'Incompatible type.';
}
}
setTimeout(updateMediaPreviewAfterChange, 100);
function applyLoadedSettings(settings) {
loadingNewData = true;
for (var setting of Object.entries(settings)) {
var key = setting[0];
var value = setting[1];
var field = document.querySelector(`[name="${key}"]`);
if (!!field) {
if (field.type == 'radio' || field.type == 'checkbox') {
field = document.querySelector(`[name="${key}"][value="${value}"]`);
field.checked = true;
} else {
field.value = value;
}
}
}
updateMediaPreviewAfterChange();
loadingNewData = false;
if (!acceptingRemoteSettings)
broadcastBackgroundChanges(); // only once
}
function broadcastChanges(backgrounded) {
if (!loadingNewData)
sendThroughWebSocket(JSON.stringify({
type: 'NewSettings',
settings: backgrounded ? putForm(backgroundForm, getSettings()) : getSettings()
}));
}
broadcastBackgroundChanges = () => broadcastChanges(true);
var escapeHtml = (unsafe) => (unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;"));
var form_send = document.getElementById('form_send');
var form_send_fields = document.getElementById('form_send_fields');
function getTemplateParametersFrom(input) {
return input.value.match(/\{.+?\}/g);
}
function getTemplateParameters() {
var params = ['primaryText', 'secondaryText'].map(x => document.getElementById(x)).flatMap(x => getTemplateParametersFrom(x)).filter(x => x !== null);
return Array.from(new Set(params)).sort();
}
Element.prototype.insertChildAtIndex = function (child, index) {
if (!index) index = 0;
if (index >= this.children.length || index < 0)
this.appendChild(child);
else
this.insertBefore(child, this.children[index]);
}
function updateSendFields() {
var currentTemplateParameters = getTemplateParameters();
var onScreenTemplateParametersSet = new Set(Array.from(document.getElementsByClassName('variable-field')).map(
it => it.id).map(x => x.split('_', 2)[1]).map(x => `{${x}}`));
var currentTemplateParametersSet = new Set(currentTemplateParameters);
var fieldsToRemove = new Set([...onScreenTemplateParametersSet].filter(x => !currentTemplateParametersSet.has(x)));
var fieldsToAdd = new Set([...currentTemplateParametersSet].filter(x => !onScreenTemplateParametersSet.has(x)));
for (let fieldNameLonger of Array.from(fieldsToRemove)) {
let fieldName = fieldNameLonger.substr(1, fieldNameLonger.length - 2);
let fieldId = `variableField_${fieldName}`;
let field = document.getElementById(fieldId);
let parent = field.parentNode;
parent.removeChild(field);
}
for (let fieldNameLonger of Array.from(fieldsToAdd).sort()) {
let fieldName = fieldNameLonger.substr(1, fieldNameLonger.length - 2);
let containerId = `variableField_${fieldName}`;
let fieldId = `${containerId}_field`;
let labelId = `${containerId}_label`;
let container = document.createElement('div');
container.setAttribute('id', containerId);
container.classList.add('variable-field');
form_send_fields.insertChildAtIndex(container, currentTemplateParameters.indexOf(fieldName));
let label = document.createElement('label');
label.setAttribute('id', labelId);
label.setAttribute('for', fieldId);
label.setAttribute('class', 'f6 b db mb1 mt3 sans-serif mid-gray');
label.innerText = fieldName;
let field = document.createElement('input');
field.setAttribute('type', 'text');
field.setAttribute('id', fieldId);
field.setAttribute('name', containerId);
field.setAttribute('class', 'w-100 f5 pv3 ph3 bg-light-gray bn');
field.setAttribute('onkeyup', 'broadcastChanges()');
field.setAttribute('onkeydown', 'broadcastChanges()');
field.setAttribute('onchange', 'broadcastChanges()');
container.appendChild(label);
container.appendChild(field);
}
}
updateSendFields();
function sendToDisplay() {
sendThroughWebSocket(JSON.stringify({
type: 'SendToDisplay',
settings: putForm(backgroundForm, getSettings())
}));
}