Last active
October 30, 2019 07:48
-
-
Save plugn/8a898203e4ff0b047136ace273d64b94 to your computer and use it in GitHub Desktop.
XML/JSON/DOM Template Engine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @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