For the MDN documentation website we have written this jsonToDOM
function and I was wondering how you all would improve it. It takes a json structure and creates DOM elements out of it and appends it to the document. It is written in such a way that the user has to pass the window/document as they might run this code from a scope which has no access to window
object (Browser addons for example)
This is an example of how I use it: https://gist.github.com/Noitidart/9523055#file-_ff-addon-snippet-createmenuwithsubmenuandattachtowidget-js-L6
jsonToDOM.namespaces = {
html: 'http://www.w3.org/1999/xhtml',
xul: 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'
};
jsonToDOM.defaultNamespace = jsonToDOM.namespaces.html;
function jsonToDOM(xml, doc, nodes) {
function namespace(name) {
var m = /^(?:(.*):)?(.*)$/.exec(name);
return [jsonToDOM.namespaces[m[1]], m[2]];
}
function tag(name, attr) {
if (Array.isArray(name)) {
var frag = doc.createDocumentFragment();
Array.forEach(arguments, function (arg) {
if (!Array.isArray(arg[0]))
frag.appendChild(tag.apply(null, arg));
else
arg.forEach(function (arg) {
frag.appendChild(tag.apply(null, arg));
});
});
return frag;
}
var args = Array.slice(arguments, 2);
var vals = namespace(name);
var elem = doc.createElementNS(vals[0] || jsonToDOM.defaultNamespace, vals[1]);
for (var key in attr) {
var val = attr[key];
if (nodes && key == 'key')
nodes[val] = elem;
vals = namespace(key);
if (typeof val == 'function')
elem.addEventListener(key.replace(/^on/, ''), val, false);
else
elem.setAttributeNS(vals[0] || '', vals[1], val);
}
args.forEach(function(e) {
try {
elem.appendChild(
Object.prototype.toString.call(e) == '[object Array]'
?
tag.apply(null, e)
:
e instanceof doc.defaultView.Node
?
e
:
doc.createTextNode(e)
);
} catch (ex) {
elem.appendChild(doc.createTextNode(ex));
}
});
return elem;
}
return tag.apply(null, xml);
}