From fa7bf14b74972e0e3aa2076e65d8cfdd0010d194 Mon Sep 17 00:00:00 2001 From: Donna Wu Date: Mon, 25 Jun 2012 18:42:08 +0800 Subject: [PATCH 1/3] [General] Change Sandbox URL when export and import project --- src/js/projects.js | 74 +++++++++++++++++++++++++++++++++++++-------- src/js/serialize.js | 2 +- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/js/projects.js b/src/js/projects.js index 66f69467..de7905c7 100644 --- a/src/js/projects.js +++ b/src/js/projects.js @@ -348,16 +348,25 @@ $(function () { * used to create a project, such as: { "name": XXX, "theme":XXXX } * @param {function()=} success Success callback. * @param {function(FileError)=} error Error callback. - * @param {ADMNode}[optional] design An ADM design used to create a project. + * @param {Object}[optional] data Extra data provided to create project, may contains: + * { + * "pid": pid, + * "design": design + * .... + * } * * success callback passed the pid of the new created project. * error callback passed the generated file error. * * @return {None}. */ - pmUtils.createProject = function (properties, success, error, design) { + pmUtils.createProject = function (properties, success, error, data) { var newPid, successHandler, buildDesign, errorHandler; - newPid = pmUtils.getValidPid(); + if (data && data.pid) { + newPid = data.pid; + } else { + newPid = pmUtils.getValidPid(); + } buildDesign = function () { var newDesign, newPage, config; // build a new design @@ -383,8 +392,8 @@ $(function () { pmUtils.setProperties(newPid, properties); pmUtils.setProperty(newPid, "accessDate", new Date()); - if (design && (design instanceof ADMNode)) { - ADM.setDesignRoot(design); + if (data && data.design && (data.design instanceof ADMNode)) { + ADM.setDesignRoot(data.design); } else { ADM.setDesignRoot(buildDesign()); } @@ -498,7 +507,9 @@ $(function () { successHandler = function (result) { var design, project; project = $.rib.JSONToProj(result); - design = project.design; + if (project && project.design) { + design = project.design; + } if (design && (design instanceof ADMNode)) { // set current pid as active pid pmUtils._activeProject = pid; @@ -598,14 +609,32 @@ $(function () { * @return {Bool} True if success, false when fails. */ pmUtils.exportProject = function () { - var pid, pInfo, design, obj, resultProject; + var pid, pInfo, design, obj, resultProject, extraHandler; pid = pmUtils.getActive(); pInfo = pmUtils._projectsInfo[pid]; if (!pInfo) { console.error("Error: Invalid pid for project"); } - design = ADM.getDesignRoot(); - obj = $.rib.ADMToJSONObj(design); + // deep copy of current design + design = ADM.copySubtree(ADM.getDesignRoot()); + extraHandler = function (node, object) { + var props, p, value, pType, rootUrl, projectDir; + // change sandbox URL + rootUrl = $.rib.fsUtils.fs.root.toURL(); + projectDir = rootUrl.replace(/\/$/, "") + pmUtils.ProjectDir + "/" + pid + "/"; + props = node.getProperties(); + for (p in props) { + value = props[p]; + pType = BWidget.getPropertyType(node.getType(), p); + if (pType === "url-uploadable") { + value = value.replace(projectDir, "{projectFolder}"); + value = value.replace(rootUrl, "{fsRoot}"); + // change the related object + object.properties[p] = value; + } + } + }; + obj = $.rib.ADMToJSONObj(design, extraHandler); // Following is for the serializing part if (typeof obj === "object") { obj.pInfo = pInfo; @@ -641,8 +670,29 @@ $(function () { var reader = new FileReader(); reader.onloadend = function(e) { - var properties, design, resultProject; - resultProject = $.rib.zipToProj(e.target.result); + var properties, design, designData, + resultProject, extraHandler, newPid; + // new pid for imported project + newPid = pmUtils.getValidPid(); + // extra Handler when build ADM tree + extraHandler = function (node, obj) { + var props, p, value, pType, projectDir, rootUrl; + rootUrl = $.rib.fsUtils.fs.root.toURL(); + projectDir = rootUrl.replace(/\/$/, "") + pmUtils.ProjectDir + "/" + newPid + "/"; + props = node.getProperties(); + for (p in props) { + value = props[p]; + pType = BWidget.getPropertyType(node.getType(), p); + if (pType === "url-uploadable") { + value = value.replace("{projectFolder}", projectDir); + value = value.replace("{fsRoot}", rootUrl); + // set the new value for the property + node.setProperty(p, value); + } + } + }; + designData = $.rib.zipToProj(e.target.result); + resultProject = $.rib.JSONToProj(designData, extraHandler); if (!resultProject) { alert("Invalid imported project."); return; @@ -652,7 +702,7 @@ $(function () { design = resultProject.design; if (design && (design instanceof ADMNode)) { - $.rib.pmUtils.createProject(properties, success, error, design); + $.rib.pmUtils.createProject(properties, success, error, {"pid": newPid, "design": design}); } else { console.error("Imported project failed"); error && error(); diff --git a/src/js/serialize.js b/src/js/serialize.js index 5baeab2b..d7fa7333 100644 --- a/src/js/serialize.js +++ b/src/js/serialize.js @@ -404,7 +404,7 @@ $(function() { } catch (e) { designData = data; } - return JSONToProj(designData); + return designData; } /******************************************************* From a61d22c817dc4e4f441bcca44281e550038ea358 Mon Sep 17 00:00:00 2001 From: Donna Wu Date: Fri, 29 Jun 2012 17:27:37 +0800 Subject: [PATCH 2/3] [General] Fix bug for fsUtils.pathToUrl --- src/js/fs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/fs.js b/src/js/fs.js index e3af3659..4b4794e8 100644 --- a/src/js/fs.js +++ b/src/js/fs.js @@ -157,7 +157,7 @@ $(function() { console.log("String type is needed for file which is to be read."); return false; } - var url = fsUtils.fs.root.toURL() + path; + var url = fsUtils.fs.root.toURL() + path.replace(/^\//, ""); return url; }, From af0e9686b95d8fc317014d2f93bc0ada5026c492 Mon Sep 17 00:00:00 2001 From: Donna Wu Date: Fri, 29 Jun 2012 17:29:17 +0800 Subject: [PATCH 3/3] [FileIO] Export uploaded files, import related files --- src/js/projects.js | 72 ++++++++++++++++++++++++++++++++++++++----- src/js/serialize.js | 74 ++++++++++++++++++++++++++++----------------- 2 files changed, 111 insertions(+), 35 deletions(-) diff --git a/src/js/projects.js b/src/js/projects.js index de7905c7..885c1a27 100644 --- a/src/js/projects.js +++ b/src/js/projects.js @@ -670,28 +670,49 @@ $(function () { var reader = new FileReader(); reader.onloadend = function(e) { - var properties, design, designData, - resultProject, extraHandler, newPid; + var properties, design, designData, designRule, + copyRule, copyFiles, data, zip, successHandler, + resultProject, extraHandler, newPid, projectDir, rootUrl; + data = e.target.result; // new pid for imported project newPid = pmUtils.getValidPid(); + designRule = /\.(json|rib)$/i; + copyRule = /^images\//i; + copyFiles = []; + try { + zip = new ZipFile(data); + zip.filelist.forEach(function(zipInfo, idx, array){ + if (designRule.test(zipInfo.filename)) { + designData = zip.extract(zipInfo.filename); + } + if (copyRule.test(zipInfo.filename)) { + copyFiles.push(zipInfo.filename); + } + }); + } catch (e) { + // tried to use as json + console.log(e); + console.warn("Failed to parse imported file as zip, try JSON."); + designData = data; + } + + rootUrl = $.rib.fsUtils.fs.root.toURL(); + projectDir = pmUtils.ProjectDir + "/" + newPid + "/"; // extra Handler when build ADM tree extraHandler = function (node, obj) { - var props, p, value, pType, projectDir, rootUrl; - rootUrl = $.rib.fsUtils.fs.root.toURL(); - projectDir = rootUrl.replace(/\/$/, "") + pmUtils.ProjectDir + "/" + newPid + "/"; + var props, p, value, pType; props = node.getProperties(); for (p in props) { value = props[p]; pType = BWidget.getPropertyType(node.getType(), p); if (pType === "url-uploadable") { - value = value.replace("{projectFolder}", projectDir); + value = value.replace("{projectFolder}", $.rib.fsUtils.pathToUrl(projectDir)); value = value.replace("{fsRoot}", rootUrl); // set the new value for the property node.setProperty(p, value); } } }; - designData = $.rib.zipToProj(e.target.result); resultProject = $.rib.JSONToProj(designData, extraHandler); if (!resultProject) { alert("Invalid imported project."); @@ -700,9 +721,44 @@ $(function () { // Get properties from imported file properties = resultProject.pInfo || {"name":"Imported Project"}; design = resultProject.design; + successHandler = function () { + var copyHandler, count; + if (copyFiles.length <= 0) { + success && success(); + return; + } + count = 0; + copyHandler = function (dirEntry) { + if (!dirEntry.isDirectory) { + console.error(dirEntry.fullPath + " is not a directory to save files in sandbox."); + return; + } + // copy needed files to sandbox + $.each(copyFiles, function(i, fileName) { + $.rib.fsUtils.write(projectDir + fileName, zip.extract(fileName), function (newFile) { + count++; + if (count === copyFiles.length) { + success && success(); + } + }, function(e) { + count++; + console.error("Error when copy " + projectDir + fileName + " to sandbox."); + $.rib.fsUtils.onError(e); + }, false, true); + }); + } + $.rib.fsUtils.pathToEntry(projectDir + "images", copyHandler, function(e) { + // if "images/" directory not exist then create it + if (e.code === FileError.NOT_FOUND_ERR) { + $.rib.fsUtils.mkdir(projectDir + "images", copyHandler); + } else { + $.rib.fsUtils.onError(e); + } + }); + }; if (design && (design instanceof ADMNode)) { - $.rib.pmUtils.createProject(properties, success, error, {"pid": newPid, "design": design}); + $.rib.pmUtils.createProject(properties, successHandler, error, {"pid": newPid, "design": design}); } else { console.error("Imported project failed"); error && error(); diff --git a/src/js/serialize.js b/src/js/serialize.js index d7fa7333..d4217cf2 100644 --- a/src/js/serialize.js +++ b/src/js/serialize.js @@ -386,27 +386,6 @@ $(function() { } } - /* - * This function is to find valid design.json in imported file and build ADMTree according it - */ - function zipToProj(data) { - var zip, designData, ribRule; - // Accept file subffixed with ".json" or ".rib" - ribRule = /\.(json|rib)$/i; - try { - zip = new ZipFile(data); - zip.filelist.forEach(function(zipInfo, idx, array) { - // use file suffixed with ".json" or ".rib", case insensitive - if (ribRule.test(zipInfo.filename)) { - designData = zip.extract(zipInfo.filename); - } - }); - } catch (e) { - designData = data; - } - return designData; - } - /******************************************************* * ADM to JSON Direction ******************************************************/ @@ -647,7 +626,8 @@ $(function() { 'src/css/images/icons-36-black.png', 'src/css/images/icon-search-black.png', 'src/css/images/web-ui-fw_noContent.png', - 'src/css/images/web-ui-fw_volume_icon.png' + 'src/css/images/web-ui-fw_volume_icon.png', + 'src/css/images/widgets/tizen_image.svg' ]; function getDefaultHeaderFiles (type) { @@ -684,22 +664,63 @@ $(function() { files.push(iconPath); } ribFile && zip.add(projName + ".json", ribFile); - resultHTML = generateHTML(); + resultHTML = generateHTML(null, function (admNode, domNode) { + var props, p, value, pType, rootUrl, newPath, attrName, attrValue; + // change sandbox URL for index.html + rootUrl = $.rib.fsUtils.fs.root.toURL(); + props = admNode.getProperties(); + for (p in props) { + value = props[p]; + pType = BWidget.getPropertyType(admNode.getType(), p); + // if the value type is url-uploadable, and value is in sandbox + if ((pType === "url-uploadable") && (value.indexOf(rootUrl) === 0)) { + // put all sandbox images as "images/fileName" + newPath = "images" + value.substr(value.lastIndexOf('/'), value.length); + // add the image file to the needed list + files.push({"src":value, + "dst":newPath}); + // change the attribute for serialized DOM element + attrName = BWidget.getPropertyHTMLAttribute(admNode.getType(), p); + if (typeof attrName === "object") { + if (typeof attrName.value === "function") { + attrValue = attrName.value(newPath); + } else { + attrValue = attrName.value[newPath]; + } + attrName = attrName.name; + } else { + attrValue = newPath; + } + domNode.attr(attrName, attrValue); + } + } + }); resultHTML && zip.add("index.html", resultHTML.html); // projName now is the whole package name projName = projName + '.' + type; i = 0; files.forEach(function (file, index) { + var req, srcPath, dstPath; // We have to do ajax request not using jquery as we can't get "arraybuffer" response from jquery - var req = window.ActiveXObject ? new window.ActiveXObject( "Microsoft.XMLHTTP" ): new XMLHttpRequest(); + req = window.ActiveXObject ? new window.ActiveXObject( "Microsoft.XMLHTTP" ): new XMLHttpRequest(); + if ((typeof file === "object") && file.dst && file.src) { + srcPath = file.src; + dstPath = file.dst; + } else if(typeof file === "string") { + srcPath = file; + dstPath = file; + } else { + console.error("Envalid path for exported Zip."); + return; + } req.onload = function() { var uIntArray = new Uint8Array(this.response); var charArray = new Array(uIntArray.length); for (var j = 0; j < uIntArray.length; j ++) { charArray[j] = String.fromCharCode(uIntArray[j]); } - zip.add(file, btoa(charArray.join('')), {base64:true}); + zip.add(dstPath, btoa(charArray.join('')), {base64:true}); if (i === files.length - 1){ var content = zip.generate(true); exportFile(projName, content, true); @@ -707,7 +728,7 @@ $(function() { i++; } try { - req.open("GET", file, true); + req.open("GET", srcPath, true); req.responseType = 'arraybuffer'; } catch (e) { alert(e); @@ -743,7 +764,6 @@ $(function() { // Export serialization functions into $.rib namespace $.rib.ADMToJSONObj = ADMToJSONObj; $.rib.JSONToProj = JSONToProj; - $.rib.zipToProj = zipToProj; $.rib.getDefaultHeaders = getDefaultHeaders; $.rib.getDesignHeaders = getDesignHeaders;