Files
P42_UI/core/baseClasses/Controller.js
2025-10-25 20:23:43 +00:00

173 lines
5.1 KiB
JavaScript
Executable File

/**
* @category Core
* @subcategory Application
*/
class Controller {
static _template = null;
static _contents = [];
static _currentContent = null;
/**
*
*/
constructor() { }
/**
*
*/
destructor() {}
/**
* @async
* @param {*} name
* @param {*} args
* @param {*} data
* @returns {View}
*/
loadView(name, args, data) {
args = args || {};
args.name = name+'.html';
args.className = name.split('/').pop();
args.onContentLoaded = args.onContentLoaded || this.appendHTML;
args.path = app.config.router.viewsPath;
let request = app.Assets.loadHtml(args);
return request.then(args.onContentLoaded.bind(this, args, data));
}
/**
*
* @param {*} args
* @param {*} data
* @param {*} html
* @returns {View}
*/
appendHTML(args,data, html) {
if(!args.target) {
args.target = document.body;
} else {
if(typeof args.target == 'string') {
let selector = null;
let content = document.body;
let crumbs = args.target.split('@')
if(crumbs.length > 1) {
let targetId = crumbs.pop()
content = Controller._contents.find(o => o.view._sparcId == targetId).view.el;
}
selector = crumbs.join('@');
args.target = content.querySelector(selector);
}
}
let container = document.createElement('div');
container.innerHTML = Controller.processTemplate(args.name, html, data);
let parent = args.target;
parent.innerHTML = '';
while(container.children.length > 0) {
parent.appendChild(container.children[0]);
}
let view = new app.LoadedClasses[args.className]();
view._className = args.name.replace('.html', '');
Controller._currentContent = view;
Controller._contents.push({view: view, dom: parent, type: 'nested'});
view.el = parent;
view.el.setAttribute('sparc-id', view._sparcId);
view._controller = this;
//view.DOMContentLoaded(data);
return view;
}
/**
*
* @param {*} content
*/
unloadView(content) {
app.events.clear(content.view._sparcId);
Controller._contents = Controller._contents.filter(o => o.view._sparcId != content.view._sparcId);
content.view.DOMContentRemoved();
content.view.el.remove();
}
/**
*
* @param {*} name
* @param {*} args
*/
loadModel(name, args) { }
/**
*
* @param {*} id
* @returns {View}
*/
static getContentById(id) { return Controller._contents.find(o => o.view._sparcId == id); }
/**
*
* @param {*} name
* @param {*} html
* @param {*} templateData
* @returns {string}
*/
static processTemplate(name, html, templateData) {
// Define a function inside of which templateData keys will become local variables
// AND where templateData values will become those variable values ;-)
// Drawback is that complex expression
function evalaluateTemplate(tpl, params) {
var interpretor = Function(...Object.keys(params), 'return('+tpl+');' );
return interpretor(...Object.values(params));
}
// Define a function inside of which a string of a variable name becomes that variable
// and where we check tht the corresponding (evaluable) expression in templateData is defined
function checkExpression(varname, params) {
var code = ' try{var t=typeof('+varname+');} catch(e){ t="badexpr"; } return(t)';
var interpretor = Function(...Object.keys(params), code );
return interpretor(...Object.values(params));
}
// Preflight check to avoid template crashes on undefined expressions
const rgxp = /\$\{(.*?)\}/gm;
let m = null;
templateData = templateData || {};
while ((m = rgxp.exec(html)) !== null) {
let safeType = checkExpression(m[1],templateData);
if(safeType == 'undefined') {
// variable undefined in templateData: add an empty one
console.warn(`In template ${name}, ${m[1]} is not defined !`);
templateData[m[1]]='';
} else if(safeType == 'badexpr') {
// unevaluable expression : remove it from template
console.warn(`In template ${name}, Bad expression: ${m[1]}`);
var escsearch = m[1].replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
var replrexp = new RegExp('\\$\\{'+escsearch+'\\}','gm')
html = html.replace(replrexp,'');
}
}
// Now that all remaining expressions are OK, evaluate the template via backtits !
return(evalaluateTemplate('`' + html + '`', templateData));
}
}
app.registerClass("Controller", Controller);