/** * Loads a object from a XML specification. **/ Vn.Builder = new Class ({ objectMap: {} ,contexts: [] ,tags: {} ,root: null ,destroy: function () { for (var key in this.objectMap) { var object = this.objectMap[key]; if (object.destroy instanceof Function) this.objectMap[key].destroy (); } } ,addFromXml: function (xmlDocument) { if (!xmlDocument) return null; this.root = xmlDocument.documentElement; var html = this.loadNode (this.root, null, null, true); this.resolveProperties (); this.contexts = []; return html; } ,loadNode: function (node, parent, htmlParent, firstCall) { var klass = null; var tagName = null; var htmlNode = null; var context = null; if (node.tagName) { tagName = node.tagName.toLowerCase (); klass = Vn.customTags[tagName]; } if (klass) { var object = new klass (); var nodeId = node.getAttribute ('id'); if (htmlParent && object instanceof Htk.Widget) { if (nodeId) object.node.id = nodeId; htmlParent.appendChild (object.node); } if (nodeId) this.objectMap[nodeId] = object; if (!this.tags[tagName]) this.tags[tagName] = []; this.tags[tagName].push (object); context = { node: node ,parent: parent ,object: object ,klass: klass }; this.contexts.push (context); } else if (htmlParent || firstCall) { if (tagName) { htmlNode = document.createElement (tagName); var a = node.attributes; for (var i = 0; i < a.length; i++) htmlNode.setAttribute (a[i].nodeName, a[i].nodeValue); } else htmlNode = document.importNode (node, false); if (htmlParent) htmlParent.appendChild (htmlNode); } if (node.tagName) { var childs = node.childNodes; if (childs) for (var i = 0; i < childs.length; i++) this.loadNode (childs[i], context, htmlNode, false); } return htmlNode; } ,replaceFunc: function (token) { return token.charAt(1).toUpperCase (); } ,resolveProperties: function () { for (var i = 0; i < this.contexts.length; i++) { var c = this.contexts[i]; var a = c.node.attributes; for (var j = 0; j < a.length; j++) { var prop = a[j].nodeName.replace (/-./g, this.replaceFunc); this.setProperty (c, prop, a[j].nodeValue); } if (c.parent) { var parentProperty = c.node.getAttribute ('property'); if (!parentProperty) parentProperty = c.parent.klass.Child; if (parentProperty) this.setProperty (c.parent, parentProperty, c.object); if (c.klass.Parent) this.setProperty (c, c.klass.Parent, c.parent.object); } c.object.loadXml (this, c.node); } } ,setProperty: function (c, propName, value) { var prop = c.klass.Properties[propName]; if (!prop || !value) return; switch (prop.type) { case Boolean: value = (/^(true|1)$/i).test (value); break; case Number: value = 0 + new Number (value); break; case String: case Function: break; default: if (prop.type instanceof Function) { if (typeof value == 'string') value = this.get (value); if (!(value instanceof prop.type)) return; } else if (prop.enumType) value = prop.enumType[value]; } if (value !== undefined) c.object[propName] = value; } ,get: function (objectId) { return this.objectMap[objectId]; } ,getObjects: function (tagName) { if (this.tags[tagName]) return this.tags[tagName]; return []; } });