diff --git a/src/js/serialize.js b/src/js/serialize.js index bc802fb5..303e44a2 100644 --- a/src/js/serialize.js +++ b/src/js/serialize.js @@ -28,18 +28,27 @@ var DEBUG = true, }); }, - generateHTML = function () { - var doc = constructNewDocument($.rib.getDefaultHeaders()); + /** + * Generate HTML from ADM tree. + * + * @param {ADMNode} design ADM design root to be serialized. + * @param {function(ADMNode, DOMElement)=} handler Extra handler for each node. + * + * @return {Object} return the generated object contains the relative html string + */ + generateHTML = function (design, handler) { + design = design || ADM.getDesignRoot(); + var doc = constructNewDocument($.rib.getDefaultHeaders(design)); function renderClean(admNode, domNode) { $(domNode).data('uid', admNode.getUid()); if (domNode.hasClass("rib-remove")) { domNode.replaceWith(domNode.text()); } + handler && handler(admNode, domNode); }; - serializeADMSubtreeToDOM(ADM.getDesignRoot(), $(doc).find('body'), - renderClean); + serializeADMSubtreeToDOM(design, $(doc).find('body'), renderClean); return { doc: doc, html: formatHTML(xmlserializer.serializeToString(doc)) }; @@ -279,70 +288,67 @@ $(function() { * AMD design root to this design, which sends a designReset event. * * @param {Object} obj The JSON object to parse + * @param {function(ADMNode, Object)=} eachHandler Extra handler for each pair of + * ADM node and the related object. + * * @return {ADMNode/null} the design build from the text if success, null if failed. */ - function JSONToProj(text) { - var result, design, parsedObject, resultProject = {}; + function JSONToProj(text, eachHandler) { + var result, design, parsedObject, resultProject = {}, add_child; - function add_child(parent, nodes) { - if (typeof(nodes) !== "object") { - return false; - } + add_child = function (node, srcObject) { + var children, child, zone, + properties, childNode, + item, val, result, i; - if (typeof(nodes.length) == "undefined") { + if ((typeof srcObject !== "object") || !(node instanceof ADMNode)) { return false; } + properties = srcObject.properties; + try { + // Set properties for current node + for (item in properties) { + // parser the properties and set the value to the node + val = properties[item]; + // if we can't get value, we set item's value as default + if (!val){ + val = node.getPropertyDefault(item); + } - var child, childType, zone, - properties = {}, - item, val, node, result, i; - - for (i = 0; i < nodes.length; i++) { - node = nodes[i]; - childType = node.type; - zone = node.zone; - properties = node.properties; - try { - child = ADM.createNode(childType, true); + // NOTE: It's important that we pass "true" for the fourth + // parameter here (raw) to disable "property hook" + // functions like the grid one that adds or removes child + // Block elements based on the property change + node.setProperty(item, val, null, true); + } + // Scan children nodes + children = srcObject.children; + for (i = 0; i < children.length; i++) { + child = children[i]; + childNode = ADM.createNode(child.type, true); // add child node to current node - if (!parent.addChildToZone(child, zone)) { - dumplog("add child type "+ childType + " failed"); + if (!node.addChildToZone(childNode, child.zone)) { + dumplog("add child type "+ child.type + " failed"); return false; } - - // set properties of child - for (item in properties) { - // parser the properties and set the value to the node - val = properties[item]; - // if we can't get value, we set item's value as default - if (!val){ - val = child.getPropertyDefault(item); - } - - // NOTE: It's important that we pass "true" for the fourth - // parameter here (raw) to disable "property hook" - // functions like the grid one that adds or removes child - // Block elements based on the property change - child.setProperty(item, properties[item], null, true); - } - }catch (e) { - if (!confirm("Error creating " + childType + - (item ? " when setting property '" + - item + "'" : "") + " - " + e + - ".\n\nContinue loading the design?")) - return false; - } - - if (node.children.length !== 0) { - result = add_child(child, node.children); + result = add_child(childNode, child); if (!result) { return false; } } + }catch (e) { + if (!confirm("Error when " + (i ? " adding new child '" + + child.type + "'" : "setting property '" + + item + "'") + " - " + e + + ".\n\nContinue loading the design?")) + return false; } + // call extra handler for each relative pair + eachHandler && eachHandler(node, srcObject); return true; - } + }; + /************************ add_child function end *************************/ try { parsedObject = $.parseJSON(text); @@ -360,7 +366,7 @@ $(function() { // add children in ADM try { - result = add_child(design, parsedObject.children); + result = add_child(design, parsedObject); } catch(e) { result = null; alert("Invalid design file."); @@ -402,7 +408,15 @@ $(function() { /******************************************************* * ADM to JSON Direction ******************************************************/ - function ADMToJSONObj(ADMTreeNode) { + /** + * Serialize ADMTree to an common javascript Object. + * + * @param {ADMNode} ADMTreeNode ADM node to be serialized. + * @param {function(ADMNode, Object)=} handler Extra handler for each pair of + * ADM node and the related object. + * @return {Bool} return the serialized Object if success, null when fails + */ + function ADMToJSONObj(ADMTreeNode, handler) { ADMTreeNode = ADMTreeNode || ADM.getDesignRoot(); if (ADMTreeNode instanceof ADMNode) { // Save staff in ADMNode @@ -417,9 +431,11 @@ $(function() { children = ADMTreeNode.getChildren(); if (children.length > 0) { for (i = 0; i < children.length; i++) { - JSObject.children[i] = ADMToJSONObj(children[i]); + JSObject.children[i] = ADMToJSONObj(children[i], handler); } } + // run handler to handle every node + handler && handler(ADMTreeNode, JSObject); return JSObject; } else { console.log("warning: children of ADMNode must be ADMNode"); @@ -427,7 +443,9 @@ $(function() { } } - function getDefaultHeaders() { + function getDefaultHeaders(design) { + var i, props, el, designRoot; + designRoot = design || ADM.getDesignRoot(); var i, props, el; $.rib.defaultHeaders = $.rib.defaultHeaders || []; @@ -435,7 +453,7 @@ $(function() { if ($.rib.defaultHeaders.length > 0) return $.rib.defaultHeaders; - props = ADM.getDesignRoot().getProperty('metas'); + props = designRoot.getProperty('metas'); for (i in props) { // Skip design only header properties if (props[i].hasOwnProperty('designOnly') && props[i].designOnly) { @@ -454,7 +472,7 @@ $(function() { el = el + '>'; $.rib.defaultHeaders.push(el); } - props = ADM.getDesignRoot().getProperty('libs'); + props = designRoot.getProperty('libs'); for (i in props) { // Skip design only header properties if (props[i].hasOwnProperty('designOnly') && props[i].designOnly) { @@ -467,7 +485,7 @@ $(function() { el = el + '>'; $.rib.defaultHeaders.push(el); } - props = ADM.getDesignRoot().getProperty('css'); + props = designRoot.getProperty('css'); for (i in props) { // Skip design only header properties if (props[i].hasOwnProperty('designOnly') && props[i].designOnly) {