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
This commit is contained in:
Emma Dauterman
2016-08-18 15:41:26 -07:00
committed by picklesrus
parent 00c04688da
commit 394b618a67
5 changed files with 86 additions and 3 deletions

View File

@@ -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<!Element>} Array of block types defined.
*/
FactoryUtils.defineAndGetBlockTypes = function(blockDefsString, format) {
var blockTypes = [];

View File

@@ -132,6 +132,10 @@
<label for="input_importToolbox">Toolbox</label>
<input type="file" id="input_importPreload" class="inputfile"</input>
<label for="input_importPreload">Workspace Blocks</label>
<input type="file" id="input_importCategoryJson" class="inputfile"</input>
<label for="input_importCategoryJson">Blocks from JSON</label>
<input type="file" id="input_importCategoryJs" class="inputfile"</input>
<label for="input_importCategoryJs">Blocks from Javascript</label>
</div>
</div>
@@ -710,6 +714,7 @@
<sep></sep>
<category name="Variables" colour="330" custom="VARIABLE"></category>
<category name="Functions" colour="290" custom="PROCEDURE"></category>
<sep></sep>
</xml>
</body>

View File

@@ -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);
};

View File

@@ -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<!Element>} blockTypes Array of blocks that have been defined.
* @return {!Array<!Blockly.Block>} 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;
};

View File

@@ -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() {