173 lines
5.1 KiB
JavaScript
Executable File
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); |