From 394b618a6796cee73cdac9835dcb5a3e450ddb62 Mon Sep 17 00:00:00 2001 From: Emma Dauterman Date: Thu, 18 Aug 2016 15:41:26 -0700 Subject: [PATCH] Blockly Factory: Import Blocks to Workspace Factory (#566) * Can import blocks in JSON and Javascript to generate new category in toolbox workspace * Added try/catch to file reading * Added comment to getDefinedBlocks in generator and changed name * Use random color for imported category and use different call to update toolbox * Nit removed extra line --- demos/blocklyfactory/factory_utils.js | 2 +- demos/blocklyfactory/index.html | 5 ++ .../workspacefactory/wfactory_controller.js | 49 ++++++++++++++++++- .../workspacefactory/wfactory_generator.js | 19 +++++++ .../workspacefactory/wfactory_init.js | 14 ++++++ 5 files changed, 86 insertions(+), 3 deletions(-) diff --git a/demos/blocklyfactory/factory_utils.js b/demos/blocklyfactory/factory_utils.js index d8d004c04..35a677d68 100644 --- a/demos/blocklyfactory/factory_utils.js +++ b/demos/blocklyfactory/factory_utils.js @@ -836,7 +836,7 @@ FactoryUtils.parseJsonBlockDefs = function(blockDefsString) { * * @param {!string} blockDefsString - Block definition(s). * @param {!string} format - Block definition format ('JSON' or 'JavaScript'). - * @return {!Element} Array of block types defined. + * @return {!Array} Array of block types defined. */ FactoryUtils.defineAndGetBlockTypes = function(blockDefsString, format) { var blockTypes = []; diff --git a/demos/blocklyfactory/index.html b/demos/blocklyfactory/index.html index 2630e441d..c7792cd37 100644 --- a/demos/blocklyfactory/index.html +++ b/demos/blocklyfactory/index.html @@ -132,6 +132,10 @@ + + + + @@ -710,6 +714,7 @@ + diff --git a/demos/blocklyfactory/workspacefactory/wfactory_controller.js b/demos/blocklyfactory/workspacefactory/wfactory_controller.js index 40af136e2..10fce767b 100644 --- a/demos/blocklyfactory/workspacefactory/wfactory_controller.js +++ b/demos/blocklyfactory/workspacefactory/wfactory_controller.js @@ -34,6 +34,8 @@ * @author Emma Dauterman (evd2014) */ + goog.require('FactoryUtils'); + /** * Class for a WorkspaceFactoryController * @constructor @@ -43,7 +45,8 @@ * @param {!string} previewDiv Name of div to inject preview workspace in. */ WorkspaceFactoryController = function(toolboxName, toolboxDiv, previewDiv) { - var toolbox = document.getElementById(toolboxName); + // Toolbox XML element for the editing workspace. + this.toolbox = document.getElementById(toolboxName); // Workspace for user to drag blocks in for a certain category. this.toolboxWorkspace = Blockly.inject(toolboxDiv, @@ -53,7 +56,7 @@ WorkspaceFactoryController = function(toolboxName, toolboxDiv, previewDiv) { colour: '#ccc', snap: true}, media: '../../media/', - toolbox: toolbox, + toolbox: this.toolbox, }); // Workspace for user to preview their changes. @@ -1132,3 +1135,45 @@ WorkspaceFactoryController.prototype.generateNewOptions = function() { (this.generator.generateToolboxXml())); }; +/** + * Imports blocks from a file, generating a category in the toolbox workspace + * to allow the user to use imported blocks in the toolbox and in pre-loaded + * blocks. + * + * @param {!File} file File object for the blocks to import. + * @param {!string} format The format of the file to import, either 'JSON' or + * 'JavaScript'. + */ +WorkspaceFactoryController.prototype.importBlocks = + function(file, format) { + // Generate category name from file name. + var categoryName = file.name + ' blocks'; + + var controller = this; + var reader = new FileReader(); + + // To be executed when the reader has read the file. + reader.onload = function() { + try { + // Define blocks using block types from file. + var blockTypes = FactoryUtils.defineAndGetBlockTypes(reader.result, format); + var blocks = controller.generator.getDefinedBlocks(blockTypes); + + // Generate category XML and append to toolbox. + var categoryXml = FactoryUtils.generateCategoryXml(blocks, categoryName); + // Get random color for category between 0 and 360. Gives each imported + // category a different color. + var randomColor = Math.floor(Math.random() * 360); + categoryXml.setAttribute('colour', randomColor); + controller.toolbox.appendChild(categoryXml); + controller.toolboxWorkspace.updateToolbox(controller.toolbox); + } catch (e) { + alert('Cannot read blocks from file.'); + window.console.log(e); + } + } + + // Read the file asynchronously. + reader.readAsText(file); +}; + diff --git a/demos/blocklyfactory/workspacefactory/wfactory_generator.js b/demos/blocklyfactory/workspacefactory/wfactory_generator.js index 3f3cf374f..37725b0c2 100644 --- a/demos/blocklyfactory/workspacefactory/wfactory_generator.js +++ b/demos/blocklyfactory/workspacefactory/wfactory_generator.js @@ -28,6 +28,8 @@ * @author Emma Dauterman (evd2014) */ +goog.require('FactoryUtils'); + /** * Class for a WorkspaceFactoryGenerator * @constructor @@ -179,3 +181,20 @@ WorkspaceFactoryGenerator.prototype.setShadowBlocksInHiddenWorkspace_ = } }; +/** + * Given a set of block types, gets the Blockly.Block objects for each block + * type. + * + * @param {!Array} blockTypes Array of blocks that have been defined. + * @return {!Array} Array of Blockly.Block objects corresponding + * to the array of blockTypes. + */ +WorkspaceFactoryGenerator.prototype.getDefinedBlocks = function(blockTypes) { + var blocks = []; + for (var i = 0; i < blockTypes.length ; i++) { + blocks.push(FactoryUtils.getDefinedBlock(blockTypes[i], + this.hiddenWorkspace)); + } + return blocks; +}; + diff --git a/demos/blocklyfactory/workspacefactory/wfactory_init.js b/demos/blocklyfactory/workspacefactory/wfactory_init.js index 96ca6f2f4..89249b2be 100644 --- a/demos/blocklyfactory/workspacefactory/wfactory_init.js +++ b/demos/blocklyfactory/workspacefactory/wfactory_init.js @@ -319,6 +319,20 @@ document.getElementById('button_import').addEventListener document.getElementById('dropdownDiv_import').classList.remove("show"); }); + document.getElementById('input_importCategoryJson').addEventListener + ('change', + function() { + controller.importBlocks(event.target.files[0],'JSON'); + document.getElementById('dropdownDiv_import').classList.remove("show"); + }); + + document.getElementById('input_importCategoryJs').addEventListener + ('change', + function() { + controller.importBlocks(event.target.files[0],'JavaScript'); + document.getElementById('dropdownDiv_import').classList.remove("show"); + }); + document.getElementById('button_clear').addEventListener ('click', function() {