Skip to content

Instantly share code, notes, and snippets.

@plugn
Last active October 30, 2019 07:48
Show Gist options
  • Save plugn/8a898203e4ff0b047136ace273d64b94 to your computer and use it in GitHub Desktop.
Save plugn/8a898203e4ff0b047136ace273d64b94 to your computer and use it in GitHub Desktop.
XML/JSON/DOM Template Engine
/**
* @title XML/JSON/DOM Template Engine
* @author Max L Dolgov, bananafishbone at gmail dot com
* @copyright Max L Dolgov
**/
(function($){
var jxt = {
xmlNS : {
'XUL' : 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul',
'XHTML' : 'http://www.w3.org/1999/xhtml'
},
keyNS : 'XUL', // 'XHTML'
baseData : {},
nodeAppend: function ( node, hostNode ) {
try {
var elms = node.documentElement.childNodes;
for (var i = 0; i < elms.length; i++) {
var item = elms[i];
if ('#text' == item.nodeName) { continue; }
hostNode.appendChild(hostNode.ownerDocument.importNode(elms[i], true));
}
} catch (e) {
$.log( ' nodeAppend() exception: ' + e.message + ' @ ' + e.lineNumber );
}
},
parseSpecials : function(what) {
return what.replace(/\/\/(content|locale|skin)/mg, 'chrome://'+$.APPNAME+'/$1');
},
parse : function(tplHtml, dataHash) {
var html = this.parseSpecials(tplHtml);
for (var key in dataHash)
html = html.replace( (new RegExp('#\\{' + key + '\\}','g')), (''+dataHash[key]+'').replace( /"/gm, '\\"' ).replace(/^\/\/(content|locale|skin)/mg, 'chrome://'+$.APPNAME+'/$1') );
return html;
},
buildValue : function(sValue) {
if (/^\s*$/.test(sValue)) { return(null); }
if (/^(true|false)$/i.test(sValue)) { return(sValue.toLowerCase() === "true"); }
if (isFinite(sValue)) { return(parseFloat(sValue)); }
if (isFinite(Date.parse(sValue))) { return(new Date(sValue)); }
return(sValue);
},
jxon2dom : function( jxon, ctx ) {
try {
if ('undefined' == typeof ctx || !ctx)
ctx = document.createDocumentFragment();
var objType, nodeName, nodeAttrs;
if ('string' == (typeof jxon).toLowerCase()) {
objType = 'string';
} else if ('object' == (typeof jxon).toLowerCase()) {
objType = 'object';
if (jxon.constructor == Array)
objType = 'array';
}
switch (objType) {
case 'string':
var textNode = document.createTextNode( String(jxon).replace(/\(plugmagicbr\)/gm, '\n') );
ctx.appendChild(textNode);
break;
case 'object':
jxon.nodeValue = jxon.hasOwnProperty('nodeValue')? jxon.nodeValue : null;
for (var k in jxon)
if ('nodeValue' != k) {
nodeName = k;
nodeAttrs = jxon[ k ];
}
var elm = document.createElementNS(this.xmlNS[this.keyNS], nodeName);
for (var a in nodeAttrs) {
var rAttr = (null===nodeAttrs[a])? '' : String(nodeAttrs[a]).replace(/\(plugmagicbr\)/gm, '\n');
elm.setAttribute(a, rAttr);
}
if (jxon.nodeValue) {
elm = $.util.jxt.jxon2dom(jxon.nodeValue, elm);
}
ctx.appendChild( elm );
break;
case 'array':
var node;
for (var i=0; i<jxon.length; i++) {
node = jxon[ i ];
ctx = $.util.jxt.jxon2dom(jxon[ i ], ctx);
}
break;
}
return ctx;
} catch (e) {
$.log('jxon2dom() exception: ' + e.message + ' @ ' + e.lineNumber);
}
},
dom2jxon: function(oXML) {
try {
var rElm = {}, sTxtContent = '';
switch(oXML.nodeType) {
case Node.DOCUMENT_NODE:
case Node.DOCUMENT_FRAGMENT_NODE:
if (oXML.hasChildNodes()) {
var iXMLChild, oChild, oChilds = [], oValue;
for (var iChildId = 0; iChildId < oXML.childNodes.length; iChildId++) {
iXMLChild = oXML.childNodes.item(iChildId);
oChild = $.util.jxt.dom2jxon(iXMLChild);
if (null !== oChild)
oChilds.push(oChild)
}
if (oChilds.length == 1)
oValue = oChilds[0];
else if (oChilds.length > 0)
oValue = oChilds;
}
return oValue;
break;
case Node.ELEMENT_NODE:
var attrs = {};
if (oXML.hasAttributes()) {
for (var nLength=0; nLength < oXML.attributes.length; nLength++) {
var iAttr = oXML.attributes.item(nLength);
var aKey = iAttr.nodeName;
var aValue = $.util.jxt.buildValue(iAttr.value.replace(/^\s+|\s+$/g, ""));
attrs[aKey] = aValue;
}
}
rElm[oXML.nodeName] = attrs;
// rElm.nodeValue = null;
if (oXML.hasChildNodes()) {
var iXMLChild, oChild, oChilds = [];
for (var iChildId = 0; iChildId < oXML.childNodes.length; iChildId++) {
iXMLChild = oXML.childNodes.item(iChildId);
oChild = $.util.jxt.dom2jxon(iXMLChild);
if (null !== oChild)
oChilds.push(oChild)
}
if (oChilds.length == 1)
rElm.nodeValue = oChilds[0];
else if (oChilds.length > 0)
rElm.nodeValue = oChilds;
}
return rElm;
break;
case Node.TEXT_NODE: // 3
sTxtContent += oXML.nodeValue.replace(/^\s+|\s+$/g, "");
return $.util.jxt.buildValue(sTxtContent);
break;
case Node.CDATA_SECTION_NODE: // 4
sTxtContent += oXML.nodeValue;
return $.util.jxt.buildValue(sTxtContent);
break;
default:
return null;
}
} catch(e) {
$.log('jxt.dom2jxon() exception : ' + e.message + ' @ ' + e.lineNumber);
}
},
render: function(template, tData, tNS) {
try {
if (!template) return null;
var data = (tData? tData : {}), tname, tplSet;
for (var prop in $.util.jxt.baseData)
data[prop] = $.util.jxt.baseData[prop];
tNS = ('undefined' != typeof tNS)? (Object.keys($.util.jxt.xmlNS).indexOf(tNS) != -1? tNS : 'XUL') : 'XUL';
if ('object' !== typeof template) {
$.log('jxt.render(): template is not Object')
return false;
}
tplSet = template;
tname = 'template';
var li = tplSet[tname],
liTxt = JSON.stringify(li);
var hListTxt = '';
var idx = liTxt.search( /(['"]+)#\{_\}(['"]+)/g );
if (-1 != idx && data.list && data.list.length) {
var litem = '' + tname.replace(/list$/g, '') + 'item';
var litemTxt = JSON.stringify(tplSet[litem]);
var lmCache = [];
for (var i=0; i < data.list.length; i++){
var rs = data.list[i];
for (var prop in data){
if ('list'==prop || /^APP/gm.test(prop) || 'ADDONID'==prop) continue;
rs['/'+prop] = data[prop];
}
var ji = $.util.jxt.parse(litemTxt, rs);
var jo = JSON.parse(ji);
if ('object' == (typeof jo).toLowerCase())
lmCache.push(jo);
}
if (lmCache.length==1) lmCache = lmCache[0];
hListTxt = liTxt.replace(liTxt.substr(idx,6), JSON.stringify(lmCache));
hListTxt = $.util.jxt.parse(hListTxt, data);
} else {
hListTxt = $.util.jxt.parse(liTxt, data);
}
var hList = JSON.parse( hListTxt.replace(/#\{[a-zA-Z0-9_\.:\/-]*?\}/mg,'') );
var rList = ('object' == (typeof hList).toLowerCase())? hList : null;
this.keyNS = tNS;
var domF = $.util.jxt.jxon2dom( rList );
this.keyNS = 'XUL';
return domF;
} catch (e) {
$.log('jxt.render() exception : ' + e.message + ' @ ' + e.lineNumber );
}
}
}
$.util.jxt = jxt;
})( this['_APP_NAME__plugbar'] );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment