Live (In a Volcano) community card game.
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.
 
 
 
 

222 lines
6.9 KiB

// dtp-display-engine.js
// Copyright (C) 2022 DTP Technologies, LLC
// License: Apache-2.0
'use strict';
import DtpLog from './dtp-log.js';
export default class DtpDisplayEngine {
constructor ( ) {
this.processors = { };
this.log = new DtpLog('DtpDisplayEngine');
this.log.debug('constructor', 'DTP Display Engine instance created');
}
/**
* Register a named Display List processor plugin. This lets client objects
* define their own Display List processor classes and resiter them. Server
* code can then execute actions on named processors in the client.
* @param {*} name The name of the DL processor being registered.
* @param {*} processor The custom DL processor being registered.
*/
registerProcessor (name, processor) {
this.processors[name] = processor;
}
/**
* Unregisters a named Display List processing plugin.
* @param {String} name The name of the DL processor to be unregistered.
*/
unregisterProcessor (name) {
if (!this.processors[name]) {
return;
}
delete this.processors[name];
}
/**
* Executes a Display List to implement view changes requested by the server.
* These can arrive from an HTTP request, via socket.io, or generated in code
* and passed in.
* @param {DtpDisplayList} displayList
*/
async executeDisplayList (displayList) {
try {
displayList.commands.forEach((command) => {
const processor = command.processor ? this.processors[command.processor] : this;
this.log.debug(command.action, 'action', command);
processor[command.action](displayList, command);
});
} catch (error) {
this.log.error('executeDisplayList', 'failed to apply DisplayEngine updates', { error });
UIkit.modal.alert(`Failed to apply updates: ${error.message}`);
}
}
/*
* action: addElement
* selector: Specifies the container element to insertAdjacentHTML
* where: 'beforebegin', 'afterbegin', 'beforeend', 'afterend'
* html: the HTML content to insert at the container as specified
*/
async addElement (displayList, command) {
const container = document.querySelector(command.selector);
if (!container) {
console.debug('displayList.addElement has failed', { command });
return;
}
container.insertAdjacentHTML(command.params.where, command.params.html);
}
async setTextContent (displayList, command) {
const elements = document.querySelectorAll(command.selector);
if (!elements || (elements.length === 0)) {
this.log.error('setTextContent', 'failed to find target elements', { command });
return;
}
elements.forEach((element) => {
element.textContent = command.params.text;
});
}
async setInputValue (displayList, command) {
const elements = document.querySelectorAll(command.selector);
if (!elements || (elements.length === 0)) {
this.log.error('setInputValue', 'failed to find target elements', { command });
return;
}
elements.forEach((element) => {
element.value = command.params.value;
});
}
/*
* action: replaceElement
* selector: Specifies the element to be replaced
* html: replaces the whole specified element
*/
async replaceElement (displayList, command) {
const element = document.querySelector(command.selector);
if (!element) {
console.debug('displayList.replaceElement has failed to find requested element', { command });
return;
}
element.outerHTML = command.params.html;
}
/*
* action: removeElement
* selector: Specifies the element(s) to be removed
*/
async removeElement (displayList, command) {
const elements = document.querySelectorAll(command.selector);
if (!elements || !elements.length) {
console.debug('displayList.removeElement has failed', { command });
return;
}
elements.forEach((element) => {
element.parentElement.removeChild(element);
});
}
/*
* action: setAttribute
* selector: Specifies the element(s) for which an attribute's value should be set
* name: the name of the attribute to be set
* value: the value to be set on the named attribute
*/
async setAttribute (displayList, command) {
const elements = document.querySelectorAll(command.selector);
if (!elements || !elements.length) {
console.debug('displayList.setAttribute has failed', { command });
return;
}
elements.forEach((element) => {
element.setAttribute(command.params.name, command.params.value);
});
}
/*
* action: removeAttribute
* selector: specifies the element(s) from which an attribute is to be removed
* name: the name of the attribute to be removed
*/
async removeAttribute (displayList, command) {
const elements = document.querySelectorAll(command.selector);
if (!elements || !elements.length) {
console.debug('displayList.removeAttribute has failed', { command });
return;
}
elements.forEach((element) => {
element.removeAttribute(command.params.name);
});
}
/*
* action: addClass
* selector: Specifies the element(s) for which style class(es) should be added
* name: the class name to add to the classList
*/
async addClass (displayList, command) {
const elements = document.querySelectorAll(command.selector);
if (!elements || !elements.length) {
console.debug('displayList.addClass has failed', { command });
return;
}
elements.forEach((element) => {
element.classList.add(command.params.add);
});
}
/*
* action: removeClass
* selector: Specifies the element(s) for which style class(es) should be removed
* name: the class name to remove from the classList
*/
async removeClass (displayList, command) {
const elements = document.querySelectorAll(command.selector);
if (!elements || !elements.length) {
console.debug('displayList.removeClass has failed', { command });
return;
}
elements.forEach((element) => {
element.classList.remove(command.params.remove);
});
}
/*
* action: replaceClass
* selector: Specifies the elements for which class replacement should occur
* remove: the class name to remove from the classList
* add: the class name to add to the classList
*/
async replaceClass (displayList, command) {
const elements = document.querySelectorAll(command.selector);
if (!elements || !elements.length) {
console.debug('displayList.replaceClass has failed', { command });
return;
}
elements.forEach((element) => {
element.classList.remove(command.params.remove);
element.classList.add(command.params.add);
});
}
async showNotification (displayList, command) {
UIkit.notification(command.params);
}
async showModal (displayList, command) {
UIkit.modal.dialog(command.params.html);
}
async navigateTo (displayList, command) {
window.location = command.params.href;
}
async reload ( ) {
window.location.reload();
}
}