Very quick readability pass on Blockly Factory.

This commit is contained in:
Neil Fraser
2016-10-06 19:53:48 -07:00
parent 415c6ed65e
commit e95c437919
17 changed files with 422 additions and 617 deletions

View File

@@ -36,6 +36,7 @@ goog.require('goog.string');
goog.require('goog.ui.PopupColorPicker');
goog.require('goog.ui.ColorPicker');
/**
* Controller for the Blockly Factory
* @constructor
@@ -78,7 +79,7 @@ AppController.EXPORTER = 'EXPORTER';
/**
* Tied to the 'Import Block Library' button. Imports block library from file to
* Block Factory. Expects user to upload a single file of JSON mapping each
* block type to its xml text representation.
* block type to its XML text representation.
*/
AppController.prototype.importBlockLibraryFromFile = function() {
var self = this;
@@ -90,14 +91,14 @@ AppController.prototype.importBlockLibraryFromFile = function() {
var file = files.files[0];
var fileReader = new FileReader();
// Create a map of block type to xml text from the file when it has been
// Create a map of block type to XML text from the file when it has been
// read.
fileReader.addEventListener('load', function(event) {
var fileContents = event.target.result;
// Create empty object to hold the read block library information.
var blockXmlTextMap = Object.create(null);
try {
// Parse the file to get map of block type to xml text.
// Parse the file to get map of block type to XML text.
blockXmlTextMap = self.formatBlockLibraryForImport_(fileContents);
} catch (e) {
var message = 'Could not load your block library file.\n'
@@ -124,12 +125,12 @@ AppController.prototype.importBlockLibraryFromFile = function() {
/**
* Tied to the 'Export Block Library' button. Exports block library to file that
* contains JSON mapping each block type to its xml text representation.
* contains JSON mapping each block type to its XML text representation.
*/
AppController.prototype.exportBlockLibraryToFile = function() {
// Get map of block type to xml.
// Get map of block type to XML.
var blockLib = this.blockLibraryController.getBlockLibrary();
// Concatenate the xmls, each separated by a blank line.
// Concatenate the XMLs, each separated by a blank line.
var blockLibText = this.formatBlockLibraryForExport_(blockLib);
// Get file name.
var filename = prompt('Enter the file name under which to save your block ' +
@@ -144,11 +145,10 @@ AppController.prototype.exportBlockLibraryToFile = function() {
};
/**
* Converts an object mapping block type to xml to text file for output.
* Converts an object mapping block type to XML to text file for output.
* @param {!Object} blockXmlMap - Object mapping block type to XML.
* @return {string} XML text containing the block XMLs.
* @private
*
* @param {!Object} blockXmlMap - Object mapping block type to xml.
* @return {string} Xml text containing the block xmls.
*/
AppController.prototype.formatBlockLibraryForExport_ = function(blockXmlMap) {
// Create DOM for XML.
@@ -156,29 +156,28 @@ AppController.prototype.formatBlockLibraryForExport_ = function(blockXmlMap) {
'xmlns':"http://www.w3.org/1999/xhtml"
});
// Append each block node to xml dom.
// Append each block node to XML DOM.
for (var blockType in blockXmlMap) {
var blockXmlDom = Blockly.Xml.textToDom(blockXmlMap[blockType]);
var blockNode = blockXmlDom.firstElementChild;
xmlDom.appendChild(blockNode);
}
// Return the xml text.
// Return the XML text.
return Blockly.Xml.domToText(xmlDom);
};
/**
* Converts imported block library to an object mapping block type to block xml.
* @private
*
* @param {string} xmlText - String representation of an xml with each block as
* Converts imported block library to an object mapping block type to block XML.
* @param {string} xmlText String representation of an XML with each block as
* a child node.
* @return {!Object} object mapping block type to xml text.
* @return {!Object} Object mapping block type to XML text.
* @private
*/
AppController.prototype.formatBlockLibraryForImport_ = function(xmlText) {
var xmlDom = Blockly.Xml.textToDom(xmlText);
// Get array of xmls. Use an asterisk (*) instead of a tag name for the XPath
// Get array of XMLs. Use an asterisk (*) instead of a tag name for the XPath
// selector, to match all elements at that level and get all factory_base
// blocks.
var blockNodes = goog.dom.xml.selectNodes(xmlDom, '*');
@@ -190,7 +189,7 @@ AppController.prototype.formatBlockLibraryForImport_ = function(xmlText) {
// Populate map.
for (var i = 0, blockNode; blockNode = blockNodes[i]; i++) {
// Add outer xml tag to the block for proper injection in to the
// Add outer XML tag to the block for proper injection in to the
// main workspace.
// Create DOM for XML.
var xmlDom = goog.dom.createDom('xml', {
@@ -198,7 +197,7 @@ AppController.prototype.formatBlockLibraryForImport_ = function(xmlText) {
});
xmlDom.appendChild(blockNode);
var xmlText = Blockly.Xml.domToText(xmlDom);
xmlText = Blockly.Xml.domToText(xmlDom);
// All block types should be lowercase.
var blockType = this.getBlockTypeFromXml_(xmlText).toLowerCase();
@@ -209,12 +208,11 @@ AppController.prototype.formatBlockLibraryForImport_ = function(xmlText) {
};
/**
* Extracts out block type from xml text, the kind that is saved in block
* Extracts out block type from XML text, the kind that is saved in block
* library storage.
* @param {string} xmlText A block's XML text.
* @return {string} The block type that corresponds to the provided XML text.
* @private
*
* @param {!string} xmlText - A block's xml text.
* @return {string} The block type that corresponds to the provided xml text.
*/
AppController.prototype.getBlockTypeFromXml_ = function(xmlText) {
var xmlDom = Blockly.Xml.textToDom(xmlText);
@@ -233,8 +231,7 @@ AppController.prototype.getBlockTypeFromXml_ = function(xmlText) {
/**
* Add click handlers to each tab to allow switching between the Block Factory,
* Workspace Factory, and Block Exporter tab.
*
* @param {!Object} tabMap - Map of tab name to div element that is the tab.
* @param {!Object} tabMap Map of tab name to div element that is the tab.
*/
AppController.prototype.addTabHandlers = function(tabMap) {
var self = this;
@@ -247,10 +244,9 @@ AppController.prototype.addTabHandlers = function(tabMap) {
/**
* Set the selected tab.
* @private
*
* @param {string} tabName AppController.BLOCK_FACTORY,
* AppController.WORKSPACE_FACTORY, or AppController.EXPORTER
* @private
*/
AppController.prototype.setSelected_ = function(tabName) {
this.lastSelectedTab = this.selectedTab;
@@ -259,11 +255,10 @@ AppController.prototype.setSelected_ = function(tabName) {
/**
* Creates the tab click handler specific to the tab specified.
* @private
*
* @param {string} tabName AppController.BLOCK_FACTORY,
* AppController.WORKSPACE_FACTORY, or AppController.EXPORTER
* @return {Function} The tab click handler.
* @return {!Function} The tab click handler.
* @private
*/
AppController.prototype.makeTabClickHandler_ = function(tabName) {
var self = this;
@@ -453,7 +448,6 @@ AppController.prototype.assignExporterChangeListeners = function() {
/**
* If given checkbox is checked, display given elements. Otherwise, hide.
*
* @param {!Element} checkbox - Input element of type checkbox.
* @param {!Array.<!Element>} elementArray - Array of elements to show when
* block is checked.
@@ -640,21 +634,21 @@ AppController.prototype.confirmLeavePage = function() {
* Initialize Blockly and layout. Called on page load.
*/
AppController.prototype.init = function() {
// Blockly factory has a dependency on bits of closure that core blockly
// doesn't have. When you run this from file:// without a copy of closure,
// Blockly factory has a dependency on bits of Closure that core Blockly
// doesn't have. When you run this from file:// without a copy of Closure,
// it breaks it non-obvious ways. Warning about this for now until the
// dependency is broken.
// TODO: #668.
if (!window.goog.dom.xml) {
alert('Sorry: Closure dependency not found. We are working on removing ' +
'this dependency. In the meantime, you can use our hosted demo\n ' +
'this dependency. In the meantime, you can use our hosted demo\n ' +
'https://blockly-demo.appspot.com/static/demos/blocklyfactory/index.html' +
'\nor use these instructions to continue running locally:\n' +
'https:developers.google.com/blockly/guides/modify/web/closure');
return;
}
// Handle Blockly Storage with App Engine
// Handle Blockly Storage with App Engine.
if ('BlocklyStorage' in window) {
this.initializeBlocklyStorage();
}
@@ -698,5 +692,3 @@ AppController.prototype.init = function() {
// Workspace Factory init.
WorkspaceFactoryInit.initWorkspaceFactory(this.workspaceFactoryController);
};

View File

@@ -37,11 +37,11 @@ goog.require('BlockExporterView');
goog.require('BlockExporterTools');
goog.require('goog.dom.xml');
/**
* BlockExporter Controller Class
* @constructor
*
* @param {!BlockLibrary.Storage} blockLibStorage - Block Library Storage.
* @constructor
*/
BlockExporterController = function(blockLibStorage) {
// BlockLibrary.Storage object containing user's saved blocks.
@@ -61,7 +61,6 @@ BlockExporterController = function(blockLibStorage) {
/**
* Set the block library storage object from which exporter exports.
*
* @param {!BlockLibraryStorage} blockLibStorage - Block Library Storage object
* that stores the blocks.
*/
@@ -72,7 +71,6 @@ BlockExporterController.prototype.setBlockLibraryStorage =
/**
* Get the block library storage object from which exporter exports.
*
* @return {!BlockLibraryStorage} blockLibStorage - Block Library Storage object
* that stores the blocks.
*/
@@ -126,11 +124,7 @@ BlockExporterController.prototype.export = function() {
var genStubs = this.tools.getGeneratorCode(blockXmlMap,
language);
// Get the correct file extension.
if (language == 'JavaScript') {
var fileType = 'javascript';
} else {
var fileType = 'plain';
}
var fileType = (language == 'JavaScript') ? 'javascript' : 'plain';
// Download the file.
FactoryUtils.createAndDownloadFile(
genStubs, generatorStub_filename, fileType);
@@ -185,9 +179,8 @@ BlockExporterController.prototype.selectAllBlocks = function() {
};
/**
* Returns the category xml containing all blocks in the block library.
*
* @return {Element} Xml for a category to be used in toolbox.
* Returns the category XML containing all blocks in the block library.
* @return {Element} XML for a category to be used in toolbox.
*/
BlockExporterController.prototype.getBlockLibraryCategory = function() {
return this.tools.generateCategoryFromBlockLib(this.blockLibStorage);
@@ -270,8 +263,7 @@ BlockExporterController.prototype.selectUsedBlocks = function() {
/**
* Set the array that holds the block types used in workspace factory.
*
* @param {!Array.<!string>} usedBlockTypes - Block types used in
* @param {!Array.<string>} usedBlockTypes - Block types used in
*/
BlockExporterController.prototype.setUsedBlockTypes =
function(usedBlockTypes) {
@@ -293,10 +285,9 @@ BlockExporterController.prototype.updatePreview = function() {
};
/**
* Returns a map of each selected block's type to its corresponding xml.
*
* @return {!Object} a map of each selected block's type (a string) to its
* corresponding xml element.
* Returns a map of each selected block's type to its corresponding XML.
* @return {!Object} A map of each selected block's type (a string) to its
* corresponding XML element.
*/
BlockExporterController.prototype.getSelectedBlockXmlMap = function() {
var blockTypes = this.view.getSelectedBlockTypes();
@@ -305,8 +296,7 @@ BlockExporterController.prototype.getSelectedBlockXmlMap = function() {
/**
* Get block definition code in the selected format for selected blocks.
*
* @return {!string} The concatenation of each selected block's language code
* @return {string} The concatenation of each selected block's language code
* in the format specified in export settings.
*/
BlockExporterController.prototype.getBlockDefinitionsOfSelected = function() {
@@ -320,8 +310,7 @@ BlockExporterController.prototype.getBlockDefinitionsOfSelected = function() {
/**
* Get generator stubs in the selected language for selected blocks.
*
* @return {!string} The concatenation of each selected block's generator stub
* @return {string} The concatenation of each selected block's generator stub
* in the language specified in export settings.
*/
BlockExporterController.prototype.getGeneratorStubsOfSelected = function() {
@@ -332,4 +321,3 @@ BlockExporterController.prototype.getGeneratorStubsOfSelected = function() {
var language = document.getElementById('exportLanguage').value;
return this.tools.getGeneratorCode(blockXmlMap, language);
};

View File

@@ -20,8 +20,8 @@
/**
* @fileoverview Javascript for the BlockExporter Tools class, which generates
* block definitions and generator stubs for given block types. Also generates
* toolbox xml for the exporter's workspace. Depends on the FactoryUtils for
* block definitions and generator stubs for given block types. Also generates
* toolbox XML for the exporter's workspace. Depends on the FactoryUtils for
* its code generation functions.
*
* @author quachtina96 (Tina Quach)
@@ -35,6 +35,7 @@ goog.require('BlockOption');
goog.require('goog.dom');
goog.require('goog.dom.xml');
/**
* Block Exporter Tools Class
* @constructor
@@ -58,17 +59,16 @@ BlockExporterTools = function() {
};
/**
* Get Blockly Block object from xml that encodes the blocks used to design
* Get Blockly Block object from XML that encodes the blocks used to design
* the block.
* @private
*
* @param {!Element} xml - Xml element that encodes the blocks used to design
* the block. For example, the block xmls saved in block library.
* @return {!Blockly.Block} - Root block (factory_base block) which contains
* @param {!Element} xml XML element that encodes the blocks used to design
* the block. For example, the block XMLs saved in block library.
* @return {!Blockly.Block} Root block (factory_base block) which contains
* all information needed to generate block definition or null.
* @private
*/
BlockExporterTools.prototype.getRootBlockFromXml_ = function(xml) {
// Render xml in hidden workspace.
// Render XML in hidden workspace.
this.hiddenWorkspace.clear();
Blockly.Xml.domToWorkspace(xml, this.hiddenWorkspace);
// Get root block.
@@ -78,9 +78,8 @@ BlockExporterTools.prototype.getRootBlockFromXml_ = function(xml) {
/**
* Return the given language code of each block type in an array.
*
* @param {!Object} blockXmlMap - Map of block type to xml.
* @param {string} definitionFormat - 'JSON' or 'JavaScript'
* @param {!Object} blockXmlMap Map of block type to XML.
* @param {string} definitionFormat 'JSON' or 'JavaScript'
* @return {string} The concatenation of each block's language code in the
* desired format.
*/
@@ -100,9 +99,9 @@ BlockExporterTools.prototype.getBlockDefinitions =
} else {
// Append warning comment and write to console.
var code = '// No block definition generated for ' + blockType +
'. Could not find root block in xml stored for this block.';
'. Could not find root block in XML stored for this block.';
console.log('No block definition generated for ' + blockType +
'. Could not find root block in xml stored for this block.');
'. Could not find root block in XML stored for this block.');
}
} else {
// Append warning comment and write to console.
@@ -123,9 +122,8 @@ BlockExporterTools.prototype.getBlockDefinitions =
/**
* Return the generator code of each block type in an array in a given language.
*
* @param {!Object} blockXmlMap - Map of block type to xml.
* @param {string} generatorLanguage - e.g.'JavaScript', 'Python', 'PHP', 'Lua',
* @param {!Object} blockXmlMap Map of block type to XML.
* @param {string} generatorLanguage E.g. 'JavaScript', 'Python', 'PHP', 'Lua',
* 'Dart'
* @return {string} The concatenation of each block's generator code in the
* desired format.
@@ -160,10 +158,9 @@ BlockExporterTools.prototype.getGeneratorCode =
/**
* Evaluates block definition code of each block in given object mapping
* block type to xml. Called in order to be able to create instances of the
* block type to XML. Called in order to be able to create instances of the
* blocks in the exporter workspace.
*
* @param {!Object} blockXmlMap - Map of block type to xml.
* @param {!Object} blockXmlMap Map of block type to XML.
*/
BlockExporterTools.prototype.addBlockDefinitions = function(blockXmlMap) {
var blockDefs = this.getBlockDefinitions(blockXmlMap, 'JavaScript');
@@ -171,11 +168,10 @@ BlockExporterTools.prototype.addBlockDefinitions = function(blockXmlMap) {
};
/**
* Pulls information about all blocks in the block library to generate xml
* Pulls information about all blocks in the block library to generate XML
* for the selector workpace's toolbox.
*
* @param {!BlockLibraryStorage} blockLibStorage - Block Library Storage object.
* @return {!Element} Xml representation of the toolbox.
* @param {!BlockLibraryStorage} blockLibStorage Block Library Storage object.
* @return {!Element} XML representation of the toolbox.
*/
BlockExporterTools.prototype.generateToolboxFromLibrary
= function(blockLibStorage) {
@@ -211,11 +207,10 @@ BlockExporterTools.prototype.generateToolboxFromLibrary
};
/**
* Generate xml for the workspace factory's category from imported block
* Generate XML for the workspace factory's category from imported block
* definitions.
*
* @param {!BlockLibraryStorage} blockLibStorage - Block Library Storage object.
* @return {!Element} Xml representation of a category.
* @param {!BlockLibraryStorage} blockLibStorage Block Library Storage object.
* @return {!Element} XML representation of a category.
*/
BlockExporterTools.prototype.generateCategoryFromBlockLib =
function(blockLibStorage) {
@@ -241,9 +236,8 @@ BlockExporterTools.prototype.generateCategoryFromBlockLib =
* Generate selector dom from block library storage. For each block in the
* library, it has a block option, which consists of a checkbox, a label,
* and a fixed size preview workspace.
*
* @param {!BlockLibraryStorage} blockLibStorage - Block Library Storage object.
* @param {!string} blockSelectorID - ID of the div element that will contain
* @param {string} blockSelectorID - ID of the div element that will contain
* the block options.
* @return {!Object} Map of block type to Block Option object.
*/
@@ -264,7 +258,7 @@ BlockExporterTools.prototype.createBlockSelectorFromLib =
// Append each block option's dom to the selector.
var blockOptions = Object.create(null);
for (var blockType in blockXmlMap) {
// Get preview block's xml.
// Get preview block's XML.
var block = FactoryUtils.getDefinedBlock(blockType, this.hiddenWorkspace);
var previewBlockXml = Blockly.Xml.workspaceToDom(this.hiddenWorkspace);
@@ -278,4 +272,3 @@ BlockExporterTools.prototype.createBlockSelectorFromLib =
}
return blockOptions;
};

View File

@@ -33,11 +33,11 @@ goog.require('BlockExporterTools');
goog.require('BlockOption');
goog.require('goog.dom');
/**
* BlockExporter View Class
* @param {!Object} blockOptions Map of block types to BlockOption objects.
* @constructor
*
* @param {!Object} blockOptions - Map of block types to BlockOption objects.
*/
BlockExporterView = function(blockOptions) {
// Map of block types to BlockOption objects to select from.
@@ -47,8 +47,7 @@ BlockExporterView = function(blockOptions) {
/**
* Set the block options in the selector of this instance of
* BlockExporterView.
*
* @param {!Object} blockOptions - Map of block types to BlockOption objects.
* @param {!Object} blockOptions Map of block types to BlockOption objects.
*/
BlockExporterView.prototype.setBlockOptions = function(blockOptions) {
this.blockOptions = blockOptions;
@@ -56,9 +55,8 @@ BlockExporterView.prototype.setBlockOptions = function(blockOptions) {
/**
* Updates the helper text.
*
* @param {string} newText - New helper text.
* @param {boolean} opt_append - True if appending to helper Text, false if
* @param {string} newText New helper text.
* @param {boolean} opt_append True if appending to helper Text, false if
* replacing.
*/
BlockExporterView.prototype.updateHelperText = function(newText, opt_append) {
@@ -81,8 +79,7 @@ BlockExporterView.prototype.listSelectedBlocks = function() {
/**
* Selects a given block type in the selector.
*
* @param {string} blockType - Type of block to selector.
* @param {string} blockType Type of block to selector.
*/
BlockExporterView.prototype.select = function(blockType) {
this.blockOptions[blockType].setSelected(true);
@@ -90,8 +87,7 @@ BlockExporterView.prototype.select = function(blockType) {
/**
* Deselects a block in the selector.
*
* @param {!Blockly.Block} block - Type of block to add to selector workspce.
* @param {!Blockly.Block} block Type of block to add to selector workspce.
*/
BlockExporterView.prototype.deselect = function(blockType) {
this.blockOptions[blockType].setSelected(false);
@@ -110,8 +106,7 @@ BlockExporterView.prototype.deselectAllBlocks = function() {
/**
* Given an array of selected blocks, selects these blocks in the view, marking
* the checkboxes accordingly.
*
* @param {Array.<Blockly.Block>} blockTypes - Array of block types to select.
* @param {Array.<Blockly.Block>} blockTypes Array of block types to select.
*/
BlockExporterView.prototype.setSelectedBlockTypes = function(blockTypes) {
for (var i = 0, blockType; blockType = blockTypes[i]; i++) {
@@ -121,8 +116,7 @@ BlockExporterView.prototype.setSelectedBlockTypes = function(blockTypes) {
/**
* Returns array of selected blocks.
*
* @return {!Array.<!string>} Array of all selected block types.
* @return {!Array.<string>} Array of all selected block types.
*/
BlockExporterView.prototype.getSelectedBlockTypes = function() {
var selectedTypes = [];

View File

@@ -38,14 +38,14 @@ goog.require('BlockLibraryStorage');
goog.require('BlockLibraryView');
goog.require('BlockFactory');
/**
* Block Library Controller Class
* @constructor
*
* @param {string} blockLibraryName - Desired name of Block Library, also used
* @param {string} blockLibraryName Desired name of Block Library, also used
* to create the key for where it's stored in local storage.
* @param {!BlockLibraryStorage} opt_blockLibraryStorage - optional storage
* @param {!BlockLibraryStorage} opt_blockLibraryStorage Optional storage
* object that allows user to import a block library.
* @constructor
*/
BlockLibraryController = function(blockLibraryName, opt_blockLibraryStorage) {
this.name = blockLibraryName;
@@ -58,9 +58,8 @@ BlockLibraryController = function(blockLibraryName, opt_blockLibraryStorage) {
/**
* Returns the block type of the block the user is building.
* @private
*
* @return {string} The current block's type.
* @private
*/
BlockLibraryController.prototype.getCurrentBlockType = function() {
var rootBlock = FactoryUtils.getRootBlock(BlockFactory.mainWorkspace);
@@ -72,8 +71,7 @@ BlockLibraryController.prototype.getCurrentBlockType = function() {
/**
* Removes current block from Block Library and updates the save and delete
* buttons so that user may save block to library and but not delete.
*
* @param {string} blockType - Type of block.
* @param {string} blockType Type of block.
*/
BlockLibraryController.prototype.removeFromBlockLibrary = function() {
var blockType = this.getCurrentBlockType();
@@ -85,8 +83,7 @@ BlockLibraryController.prototype.removeFromBlockLibrary = function() {
/**
* Updates the workspace to show the block user selected from library
*
* @param {string} blockType - Block to edit on block factory.
* @param {string} blockType Block to edit on block factory.
*/
BlockLibraryController.prototype.openBlock = function(blockType) {
if (blockType) {
@@ -102,7 +99,6 @@ BlockLibraryController.prototype.openBlock = function(blockType) {
/**
* Returns type of block selected from library.
*
* @return {string} Type of block selected.
*/
BlockLibraryController.prototype.getSelectedBlockType = function() {
@@ -143,7 +139,7 @@ BlockLibraryController.prototype.saveToBlockLibrary = function() {
return;
}
// Create block xml.
// Create block XML.
var xmlElement = goog.dom.createDom('xml');
var block = FactoryUtils.getRootBlock(BlockFactory.mainWorkspace);
xmlElement.appendChild(Blockly.Xml.blockToDomWithXY(block));
@@ -167,8 +163,7 @@ BlockLibraryController.prototype.saveToBlockLibrary = function() {
/**
* Checks to see if the given blockType is already in Block Library
*
* @param {string} blockType - Type of block.
* @param {string} blockType Type of block.
* @return {boolean} Boolean indicating whether or not block is in the library.
*/
BlockLibraryController.prototype.has = function(blockType) {
@@ -177,7 +172,7 @@ BlockLibraryController.prototype.has = function(blockType) {
};
/**
* Populates the dropdown menu.
* Populates the dropdown menu.
*/
BlockLibraryController.prototype.populateBlockLibrary = function() {
this.view.clearOptions();
@@ -190,19 +185,17 @@ BlockLibraryController.prototype.populateBlockLibrary = function() {
};
/**
* Return block library mapping block type to xml.
*
* @return {Object} Object mapping block type to xml text.
* Return block library mapping block type to XML.
* @return {Object} Object mapping block type to XML text.
*/
BlockLibraryController.prototype.getBlockLibrary = function() {
return this.storage.getBlockXmlTextMap();
};
/**
* Return stored xml of a given block type.
*
* @param {!string} blockType - The type of block.
* @return {!Element} Xml element of a given block type or null.
* Return stored XML of a given block type.
* @param {string} blockType The type of block.
* @return {!Element} XML element of a given block type or null.
*/
BlockLibraryController.prototype.getBlockXml = function(blockType) {
return this.storage.getBlockXml(blockType);
@@ -210,7 +203,6 @@ BlockLibraryController.prototype.getBlockXml = function(blockType) {
/**
* Set the block library storage object from which exporter exports.
*
* @param {!BlockLibraryStorage} blockLibStorage - Block Library Storage
* object.
*/
@@ -221,8 +213,7 @@ BlockLibraryController.prototype.setBlockLibraryStorage
/**
* Get the block library storage object from which exporter exports.
*
* @return {!BlockLibraryStorage} blockLibStorage - Block Library Storage object
* @return {!BlockLibraryStorage} blockLibStorage Block Library Storage object
* that stores the blocks.
*/
BlockLibraryController.prototype.getBlockLibraryStorage = function() {
@@ -231,7 +222,6 @@ BlockLibraryController.prototype.getBlockLibraryStorage = function() {
/**
* Get the block library storage object from which exporter exports.
*
* @return {boolean} True if the Block Library is empty, false otherwise.
*/
BlockLibraryController.prototype.hasEmptyBlockLibrary = function() {
@@ -240,8 +230,7 @@ BlockLibraryController.prototype.hasEmptyBlockLibrary = function() {
/**
* Get all block types stored in block library.
*
* @return {!Array<!string>} Array of block types.
* @return {!Array.<string>} Array of block types.
*/
BlockLibraryController.prototype.getStoredBlockTypes = function() {
return this.storage.getBlockTypes();
@@ -258,7 +247,6 @@ BlockLibraryController.prototype.setNoneSelected = function() {
* If there are unsaved changes to the block in open in Block Factory
* and the block is not the starter block, check if user wants to proceed,
* knowing that it will cause them to lose their changes.
*
* @return {boolean} Whether or not to proceed.
*/
BlockLibraryController.prototype.warnIfUnsavedChanges = function() {
@@ -272,9 +260,7 @@ BlockLibraryController.prototype.warnIfUnsavedChanges = function() {
/**
* Add select handler for an option of a given block type. The handler will to
* update the view and the selected block accordingly.
*
* @param {!string} blockType - The type of block represented by the option is
* for.
* @param {string} blockType The type of block represented by the option is for.
*/
BlockLibraryController.prototype.addOptionSelectHandler = function(blockType) {
var self = this;
@@ -327,7 +313,6 @@ BlockLibraryController.prototype.addOptionSelectHandlers = function() {
/**
* Update the save and delete buttons based on the current block type of the
* block the user is currently editing.
*
* @param {boolean} Whether changes to the block have been saved.
*/
BlockLibraryController.prototype.updateButtons = function(savedChanges) {

View File

@@ -29,13 +29,13 @@
goog.provide('BlockLibraryStorage');
/**
* Represents a block library's storage.
* @constructor
*
* @param {string} blockLibraryName - Desired name of Block Library, also used
* @param {string} blockLibraryName Desired name of Block Library, also used
* to create the key for where it's stored in local storage.
* @param {Object} opt_blocks - Object mapping block type to xml.
* @param {Object} opt_blocks Object mapping block type to XML.
* @constructor
*/
BlockLibraryStorage = function(blockLibraryName, opt_blocks) {
// Add prefix to this.name to avoid collisions in local storage.
@@ -85,9 +85,8 @@ BlockLibraryStorage.prototype.clear = function() {
/**
* Saves block to block library.
*
* @param {string} blockType - Type of block.
* @param {Element} blockXML - The block's XML pulled from workspace.
* @param {string} blockType Type of block.
* @param {Element} blockXML The block's XML pulled from workspace.
*/
BlockLibraryStorage.prototype.addBlock = function(blockType, blockXML) {
var prettyXml = Blockly.Xml.domToPrettyText(blockXML);
@@ -96,19 +95,17 @@ BlockLibraryStorage.prototype.addBlock = function(blockType, blockXML) {
/**
* Removes block from current block library (this.blocks).
*
* @param {string} blockType - Type of block.
* @param {string} blockType Type of block.
*/
BlockLibraryStorage.prototype.removeBlock = function(blockType) {
delete this.blocks[blockType];
};
/**
* Returns the xml of given block type stored in current block library
* Returns the XML of given block type stored in current block library
* (this.blocks).
*
* @param {string} blockType - Type of block.
* @return {Element} The xml that represents the block type or null.
* @param {string} blockType Type of block.
* @return {Element} The XML that represents the block type or null.
*/
BlockLibraryStorage.prototype.getBlockXml = function(blockType) {
var xml = this.blocks[blockType] || null;
@@ -120,11 +117,10 @@ BlockLibraryStorage.prototype.getBlockXml = function(blockType) {
/**
* Returns map of each block type to its corresponding xml stored in current
* Returns map of each block type to its corresponding XML stored in current
* block library (this.blocks).
*
* @param {Array.<!string>} blockTypes - Types of blocks.
* @return {!Object} Map of block type to corresponding xml.
* @param {!Array.<string>} blockTypes Types of blocks.
* @return {!Object} Map of block type to corresponding XML.
*/
BlockLibraryStorage.prototype.getBlockXmlMap = function(blockTypes) {
var blockXmlMap = {};
@@ -138,7 +134,6 @@ BlockLibraryStorage.prototype.getBlockXmlMap = function(blockTypes) {
/**
* Returns array of all block types stored in current block library.
*
* @return {!Array.<string>} Array of block types stored in library.
*/
BlockLibraryStorage.prototype.getBlockTypes = function() {
@@ -147,7 +142,6 @@ BlockLibraryStorage.prototype.getBlockTypes = function() {
/**
* Checks to see if block library is empty.
*
* @return {boolean} True if empty, false otherwise.
*/
BlockLibraryStorage.prototype.isEmpty = function() {
@@ -159,8 +153,7 @@ BlockLibraryStorage.prototype.isEmpty = function() {
/**
* Returns array of all block types stored in current block library.
*
* @return {!Array.<string>} Map of block type to corresponding xml text.
* @return {!Array.<string>} Map of block type to corresponding XML text.
*/
BlockLibraryStorage.prototype.getBlockXmlTextMap = function() {
return this.blocks;
@@ -169,8 +162,7 @@ BlockLibraryStorage.prototype.getBlockXmlTextMap = function() {
/**
* Returns boolean of whether or not a given blockType is stored in block
* library.
*
* @param {string} blockType - Type of block.
* @param {string} blockType Type of block.
* @return {boolean} Whether or not blockType is stored in block library.
*/
BlockLibraryStorage.prototype.has = function(blockType) {

View File

@@ -32,6 +32,7 @@ goog.provide('BlockLibraryView');
goog.require('goog.dom');
goog.require('goog.dom.classlist');
/**
* BlockLibraryView Class
* @constructor
@@ -68,8 +69,7 @@ BlockLibraryView.prototype.hide = function() {
/**
* Creates a node of a given element type and appends to the node with given id.
*
* @param {!string} blockType - Type of block.
* @param {string} blockType - Type of block.
* @param {boolean} selected - Whether or not the option should be selected on
* the dropdown.
*/
@@ -93,7 +93,6 @@ BlockLibraryView.prototype.addOption = function(blockType, selected) {
/**
* Sets a given block type to selected and all other blocks to deselected.
* If null, deselects all blocks.
*
* @param {string} blockTypeToSelect - Type of block to select or null.
*/
BlockLibraryView.prototype.setSelectedBlockType = function(blockTypeToSelect) {
@@ -111,10 +110,9 @@ BlockLibraryView.prototype.setSelectedBlockType = function(blockTypeToSelect) {
/**
* Selects a given option.
* @private
*
* @param {!Element} option - HTML 'a' element in the dropdown that represents
* @param {!Element} option HTML 'a' element in the dropdown that represents
* a particular block type.
* @private
*/
BlockLibraryView.prototype.selectOption_ = function(option) {
goog.dom.classlist.add(option, 'dropdown-content-selected');
@@ -122,10 +120,9 @@ BlockLibraryView.prototype.selectOption_ = function(option) {
/**
* Deselects a given option.
* @private
*
* @param {!Element} option - HTML 'a' element in the dropdown that represents
* @param {!Element} option HTML 'a' element in the dropdown that represents
* a particular block type.
* @private
*/
BlockLibraryView.prototype.deselectOption_ = function(option) {
goog.dom.classlist.remove(option, 'dropdown-content-selected');
@@ -135,10 +132,9 @@ BlockLibraryView.prototype.deselectOption_ = function(option) {
* Updates the save and delete buttons to represent how the current block will
* be saved by including the block type in the button text as well as indicating
* whether the block is being saved or updated.
*
* @param {!string} blockType - The type of block being edited.
* @param {boolean} isInLibrary - Whether the block type is in the library.
* @param {boolean} savedChanges - Whether changes to block have been saved.
* @param {string} blockType The type of block being edited.
* @param {boolean} isInLibrary Whether the block type is in the library.
* @param {boolean} savedChanges Whether changes to block have been saved.
*/
BlockLibraryView.prototype.updateButtons =
function(blockType, isInLibrary, savedChanges) {
@@ -193,7 +189,6 @@ BlockLibraryView.prototype.removeSelectedOption = function() {
/**
* Returns block type of selected block.
*
* @return {string} Type of block selected.
*/
BlockLibraryView.prototype.getSelectedBlockType = function() {
@@ -204,7 +199,6 @@ BlockLibraryView.prototype.getSelectedBlockType = function() {
/**
* Returns selected option.
*
* @return {!Element} HTML 'a' element that is the option for a block type.
*/
BlockLibraryView.prototype.getSelectedOption = function() {
@@ -222,5 +216,3 @@ BlockLibraryView.prototype.clearOptions = function() {
}
}
};

View File

@@ -30,16 +30,16 @@
goog.provide('BlockOption');
goog.require('goog.dom');
/**
* BlockOption Class
* A block option includes checkbox, label, and div element that shows a preview
* of the block.
* @constructor
*
* @param {!Element} blockSelector - Scrollable div that will contain the
* block options for the selector.
* @param {!string} blockType - Type of block for which to create an option.
* @param {string} blockType - Type of block for which to create an option.
* @param {!Element} previewBlockXml - Xml element containing the preview block.
* @constructor
*/
var BlockOption = function(blockSelector, blockType, previewBlockXml) {
// The div to contain the block option.
@@ -65,7 +65,6 @@ var BlockOption = function(blockSelector, blockType, previewBlockXml) {
/**
* Creates the dom for a single block option. Includes checkbox, label, and div
* in which to inject the preview block.
*
* @return {!Element} Root node of the selector dom which consists of a
* checkbox, a label, and a fixed size preview workspace per block.
*/
@@ -157,8 +156,7 @@ BlockOption.prototype.centerBlock = function() {
/**
* Selects or deselects the block option.
*
* @param {!boolean} selected - True if selecting option, false if deselecting
* @param {!boolean} selected True if selecting option, false if deselecting
* option.
*/
BlockOption.prototype.setSelected = function(selected) {
@@ -170,12 +168,9 @@ BlockOption.prototype.setSelected = function(selected) {
/**
* Returns boolean telling whether or not block is selected.
*
* @return {!boolean} True if selecting option, false if deselecting
* option.
*/
BlockOption.prototype.isSelected = function() {
return this.selected;
};

View File

@@ -61,7 +61,7 @@ BlockFactory.UNNAMED = 'unnamed';
BlockFactory.oldDir = null;
/*
* The starting xml for the Block Factory main workspace. Contains the
* The starting XML for the Block Factory main workspace. Contains the
* unmovable, undeletable factory_base block.
*/
BlockFactory.STARTER_BLOCK_XML_TEXT = '<xml><block type="factory_base" ' +
@@ -256,10 +256,10 @@ BlockFactory.isStarterBlock = function() {
var rootBlock = FactoryUtils.getRootBlock(BlockFactory.mainWorkspace);
// The starter block does not have blocks nested into the factory_base block.
return !(rootBlock.getChildren().length > 0 ||
// The starter block's name is the default, 'block_type'.
rootBlock.getFieldValue('NAME').trim().toLowerCase() != 'block_type' ||
// The starter block has no connections.
rootBlock.getFieldValue('CONNECTIONS') != 'NONE' ||
// The starter block has automatic inputs.
rootBlock.getFieldValue('INLINE') != 'AUTO');
// The starter block's name is the default, 'block_type'.
rootBlock.getFieldValue('NAME').trim().toLowerCase() != 'block_type' ||
// The starter block has no connections.
rootBlock.getFieldValue('CONNECTIONS') != 'NONE' ||
// The starter block has automatic inputs.
rootBlock.getFieldValue('INLINE') != 'AUTO');
};

View File

@@ -33,9 +33,9 @@
*/
goog.provide('FactoryUtils');
/**
* Get block definition code for the current block.
*
* @param {string} blockType - Type of block.
* @param {!Blockly.Block} rootBlock - RootBlock from main workspace in which
* user uses Block Factory Blocks to create a custom block.
@@ -58,10 +58,9 @@ FactoryUtils.getBlockDefinition = function(blockType, rootBlock, format, workspa
/**
* Get the generator code for a given block.
*
* @param {!Blockly.Block} block - Rendered block in preview workspace.
* @param {string} generatorLanguage - 'JavaScript', 'Python', 'PHP', 'Lua',
* 'Dart'.
* @param {!Blockly.Block} block Rendered block in preview workspace.
* @param {string} generatorLanguage 'JavaScript', 'Python', 'PHP', 'Lua',
* 'Dart'.
* @return {string} Generator code for multiple blocks.
*/
FactoryUtils.getGeneratorStub = function(block, generatorLanguage) {
@@ -261,7 +260,6 @@ FactoryUtils.formatJson_ = function(blockType, rootBlock) {
* @param {string} blockType Name of block.
* @param {!Blockly.Block} rootBlock Factory_base block.
* @param {!Blockly.Workspace} workspace - Where the root block lives.
* @return {string} Generated language code.
* @private
*/
@@ -642,7 +640,6 @@ FactoryUtils.escapeString = function(string) {
/**
* Return the uneditable container block that everything else attaches to in
* given workspace
*
* @param {!Blockly.Workspace} workspace - where the root block lives
* @return {Blockly.Block} root block
*/
@@ -661,8 +658,7 @@ FactoryUtils.getRootBlock = function(workspace) {
/**
* Hides element so that it's invisible and doesn't take up space.
*
* @param {string} elementID - ID of element to hide.
* @param {string} elementID ID of element to hide.
*/
FactoryUtils.hide = function(elementID) {
document.getElementById(elementID).style.display = 'none';
@@ -670,8 +666,7 @@ FactoryUtils.hide = function(elementID) {
/**
* Un-hides an element.
*
* @param {string} elementID - ID of element to hide.
* @param {string} elementID ID of element to hide.
*/
FactoryUtils.show = function(elementID) {
document.getElementById(elementID).style.display = 'block';
@@ -679,8 +674,7 @@ FactoryUtils.show = function(elementID) {
/**
* Hides element so that it's invisible but still takes up space.
*
* @param {string} elementID - ID of element to hide.
* @param {string} elementID ID of element to hide.
*/
FactoryUtils.makeInvisible = function(elementID) {
document.getElementById(elementID).visibility = 'hidden';
@@ -688,8 +682,7 @@ FactoryUtils.makeInvisible = function(elementID) {
/**
* Makes element visible.
*
* @param {string} elementID - ID of element to hide.
* @param {string} elementID ID of element to hide.
*/
FactoryUtils.makeVisible = function(elementID) {
document.getElementById(elementID).visibility = 'visible';
@@ -697,9 +690,9 @@ FactoryUtils.makeVisible = function(elementID) {
/**
* Create a file with the given attributes and download it.
* @param {string} contents - The contents of the file.
* @param {string} filename - The name of the file to save to.
* @param {string} fileType - The type of the file to save.
* @param {string} contents The contents of the file.
* @param {string} filename The name of the file to save to.
* @param {string} fileType The type of the file to save.
*/
FactoryUtils.createAndDownloadFile = function(contents, filename, fileType) {
var data = new Blob([contents], {type: 'text/' + fileType});
@@ -718,11 +711,10 @@ FactoryUtils.createAndDownloadFile = function(contents, filename, fileType) {
/**
* Get Blockly Block by rendering pre-defined block in workspace.
*
* @param {!Element} blockType - Type of block that has already been defined.
* @param {!Blockly.Workspace} workspace - Workspace on which to render
* @param {!Element} blockType Type of block that has already been defined.
* @param {!Blockly.Workspace} workspace Workspace on which to render
* the block.
* @return {!Blockly.Block} the Blockly.Block of desired type.
* @return {!Blockly.Block} The Blockly.Block of desired type.
*/
FactoryUtils.getDefinedBlock = function(blockType, workspace) {
workspace.clear();
@@ -731,8 +723,7 @@ FactoryUtils.getDefinedBlock = function(blockType, workspace) {
/**
* Parses a block definition get the type of the block it defines.
*
* @param {!string} blockDef - A single block definition.
* @param {string} blockDef A single block definition.
* @return {string} Type of block defined by the given definition.
*/
FactoryUtils.getBlockTypeFromJsDefinition = function(blockDef) {
@@ -748,10 +739,9 @@ FactoryUtils.getBlockTypeFromJsDefinition = function(blockDef) {
/**
* Generates a category containing blocks of the specified block types.
*
* @param {!Array.<Blockly.Block>} blocks - Blocks to include in the category.
* @param {string} categoryName - Name to use for the generated category.
* @return {Element} - Category xml containing the given block types.
* @param {!Array.<!Blockly.Block>} blocks Blocks to include in the category.
* @param {string} categoryName Name to use for the generated category.
* @return {!Element} Category XML containing the given block types.
*/
FactoryUtils.generateCategoryXml = function(blocks, categoryName) {
// Create category DOM element.
@@ -774,9 +764,8 @@ FactoryUtils.generateCategoryXml = function(blocks, categoryName) {
/**
* Parses a string containing JavaScript block definition(s) to create an array
* in which each element is a single block definition.
*
* @param {!string} blockDefsString - JavaScript block definition(s).
* @return {!Array.<string>} - Array of block definitions.
* @param {string} blockDefsString JavaScript block definition(s).
* @return {!Array.<string>} Array of block definitions.
*/
FactoryUtils.parseJsBlockDefinitions = function(blockDefsString) {
var blockDefArray = [];
@@ -800,10 +789,9 @@ FactoryUtils.parseJsBlockDefinitions = function(blockDefsString) {
* in which each element is a single block definition. Expected input is
* one or more block definitions in the form of concatenated, stringified
* JSON objects.
*
* @param {!string} blockDefsString - String containing JSON block
* @param {string} blockDefsString String containing JSON block
* definition(s).
* @return {!Array.<string>} - Array of block definitions.
* @return {!Array.<string>} Array of block definitions.
*/
FactoryUtils.parseJsonBlockDefinitions = function(blockDefsString) {
var blockDefArray = [];
@@ -831,10 +819,9 @@ FactoryUtils.parseJsonBlockDefinitions = function(blockDefsString) {
/**
* Define blocks from imported block definitions.
*
* @param {!string} blockDefsString - Block definition(s).
* @param {!string} format - Block definition format ('JSON' or 'JavaScript').
* @return {!Array<!Element>} Array of block types defined.
* @param {string} blockDefsString Block definition(s).
* @param {string} format Block definition format ('JSON' or 'JavaScript').
* @return {!Array.<!Element>} Array of block types defined.
*/
FactoryUtils.defineAndGetBlockTypes = function(blockDefsString, format) {
var blockTypes = [];
@@ -886,48 +873,46 @@ FactoryUtils.injectCode = function(code, id) {
};
/**
* Returns whether or not two blocks are the same based on their xml. Expects
* xml with a single child node that is a factory_base block, the xml found on
* Returns whether or not two blocks are the same based on their XML. Expects
* XML with a single child node that is a factory_base block, the XML found on
* Block Factory's main workspace.
*
* @param {!Element} blockXml1 - An xml element with a single child node that
* @param {!Element} blockXml1 An XML element with a single child node that
* is a factory_base block.
* @param {!Element} blockXml2 - An xml element with a single child node that
* @param {!Element} blockXml2 An XML element with a single child node that
* is a factory_base block.
* @return {boolean} Whether or not two blocks are the same based on their xml.
* @return {boolean} Whether or not two blocks are the same based on their XML.
*/
FactoryUtils.sameBlockXml = function(blockXml1, blockXml2) {
// Each xml element should contain a single child element with a 'block' tag
if (goog.string.caseInsensitiveCompare(blockXml1.tagName, 'xml') ||
goog.string.caseInsensitiveCompare(blockXml2.tagName, 'xml')) {
throw new Error('Expected two xml elements, recieved elements with tag ' +
'names: ' + blockXml1.tagName + ' and ' + blockXml2.tagName + '.');
}
// Each XML element should contain a single child element with a 'block' tag
if (goog.string.caseInsensitiveCompare(blockXml1.tagName, 'xml') ||
goog.string.caseInsensitiveCompare(blockXml2.tagName, 'xml')) {
throw new Error('Expected two XML elements, recieved elements with tag ' +
'names: ' + blockXml1.tagName + ' and ' + blockXml2.tagName + '.');
}
// Compare the block elements directly. The xml tags may include other meta
// information we want to igrore.
var blockElement1 = blockXml1.getElementsByTagName('block')[0];
var blockElement2 = blockXml2.getElementsByTagName('block')[0];
// Compare the block elements directly. The XML tags may include other meta
// information we want to igrore.
var blockElement1 = blockXml1.getElementsByTagName('block')[0];
var blockElement2 = blockXml2.getElementsByTagName('block')[0];
if (!(blockElement1 && blockElement2)) {
throw new Error('Could not get find block element in xml.');
}
if (!(blockElement1 && blockElement2)) {
throw new Error('Could not get find block element in XML.');
}
var blockXmlText1 = Blockly.Xml.domToText(blockElement1);
var blockXmlText2 = Blockly.Xml.domToText(blockElement2);
var blockXmlText1 = Blockly.Xml.domToText(blockElement1);
var blockXmlText2 = Blockly.Xml.domToText(blockElement2);
// Strip white space.
blockXmlText1 = blockXmlText1.replace(/\s+/g, '');
blockXmlText2 = blockXmlText2.replace(/\s+/g, '');
// Strip white space.
blockXmlText1 = blockXmlText1.replace(/\s+/g, '');
blockXmlText2 = blockXmlText2.replace(/\s+/g, '');
// Return whether or not changes have been saved.
return blockXmlText1 == blockXmlText2;
// Return whether or not changes have been saved.
return blockXmlText1 == blockXmlText2;
};
/*
* Checks if a block has a variable field. Blocks with variable fields cannot
* be shadow blocks.
*
* @param {Blockly.Block} block The block to check if a variable field exists.
* @return {boolean} True if the block has a variable field, false otherwise.
*/
@@ -942,9 +927,8 @@ FactoryUtils.hasVariableField = function(block) {
* Checks if a block is a procedures block. If procedures block names are
* ever updated or expanded, this function should be updated as well (no
* other known markers for procedure blocks beyond name).
*
* @param {Blockly.Block} block The block to check.
* @return {boolean} True if hte block is a procedure block, false otherwise.
* @return {boolean} True if the block is a procedure block, false otherwise.
*/
FactoryUtils.isProcedureBlock = function(block) {
return block &&
@@ -959,7 +943,6 @@ FactoryUtils.isProcedureBlock = function(block) {
* Returns whether or not a modified block's changes has been saved to the
* Block Library.
* TODO(quachtina96): move into the Block Factory Controller once made.
*
* @param {!BlockLibraryController} blockLibraryController - Block Library
* Controller storing custom blocks.
* @return {boolean} True if all changes made to the block have been saved to
@@ -979,4 +962,3 @@ FactoryUtils.savedBlockChanges = function(blockLibraryController) {
}
return false;
};

View File

@@ -325,7 +325,7 @@
</label>
<input id="files" type="file" name="files"
accept="application/xml">
<button id="localSaveButton" title="Save block library xml to a local file.">
<button id="localSaveButton" title="Save block library XML to a local file.">
<span>Download Block Library</span>
</button>
</td>

View File

@@ -34,6 +34,7 @@
*/
goog.provide('StandardCategories');
// Map of standard category information necessary to add a standard category
// to the toolbox.
StandardCategories.categoryMap = Object.create(null);
@@ -392,4 +393,3 @@ StandardCategories.coreBlockTypes = ["controls_if", "logic_compare",
"lists_getSublist", "lists_split", "lists_sort", "variables_set",
"procedures_defreturn", "procedures_ifreturn", "procedures_defnoreturn",
"procedures_callreturn"];

View File

@@ -37,13 +37,13 @@
goog.require('FactoryUtils');
goog.require('StandardCategories');
/**
* Class for a WorkspaceFactoryController
* @param {string} toolboxName Name of workspace toolbox XML.
* @param {string} toolboxDiv Name of div to inject toolbox workspace in.
* @param {string} previewDiv Name of div to inject preview workspace in.
* @constructor
*
* @param {!string} toolboxName Name of workspace toolbox XML.
* @param {!string} toolboxDiv Name of div to inject toolbox workspace in.
* @param {!string} previewDiv Name of div to inject preview workspace in.
*/
WorkspaceFactoryController = function(toolboxName, toolboxDiv, previewDiv) {
// Toolbox XML element for the editing workspace.
@@ -131,9 +131,8 @@ WorkspaceFactoryController.prototype.addCategory = function() {
* Helper method for addCategory. Adds a category to the view given a name, ID,
* and a boolean for if it's the first category created. Assumes the category
* has already been created in the model. Does not switch to category.
*
* @param {!string} name Name of category being added.
* @param {!string} id The ID of the category being added.
* @param {string} name Name of category being added.
* @param {string} id The ID of the category being added.
*/
WorkspaceFactoryController.prototype.createCategory = function(name) {
// Create empty category
@@ -148,9 +147,8 @@ WorkspaceFactoryController.prototype.createCategory = function(name) {
* Given a tab and a ID to be associated to that tab, adds a listener to
* that tab so that when the user clicks on the tab, it switches to the
* element associated with that ID.
*
* @param {!Element} tab The DOM element to add the listener to.
* @param {!string} id The ID of the element to switch to when tab is clicked.
* @param {string} id The ID of the element to switch to when tab is clicked.
*/
WorkspaceFactoryController.prototype.addClickToSwitch = function(tab, id) {
var self = this;
@@ -192,7 +190,6 @@ WorkspaceFactoryController.prototype.transferFlyoutBlocksToCategory =
* Attached to "-" button. Checks if the user wants to delete
* the current element. Removes the element and switches to another element.
* When the last element is removed, it switches to a single flyout mode.
*
*/
WorkspaceFactoryController.prototype.removeElement = function() {
// Check that there is a currently selected category to remove.
@@ -239,8 +236,7 @@ WorkspaceFactoryController.prototype.removeElement = function() {
/**
* Gets a valid name for a new category from the user.
*
* @param {!string} promptString Prompt for the user to enter a name.
* @param {string} promptString Prompt for the user to enter a name.
* @return {string} Valid name for a new category, or null if cancelled.
*/
WorkspaceFactoryController.prototype.promptForNewCategoryName =
@@ -252,20 +248,19 @@ WorkspaceFactoryController.prototype.promptForNewCategoryName =
}
} while (this.model.hasCategoryByName(name));
return name;
}
};
/**
* Switches to a new tab for the element given by ID. Stores XML and blocks
* to reload later, updates selected accordingly, and clears the workspace
* and clears undo, then loads the new element.
*
* @param {!string} id ID of tab to be opened, must be valid element ID.
* @param {string} id ID of tab to be opened, must be valid element ID.
*/
WorkspaceFactoryController.prototype.switchElement = function(id) {
// Disables events while switching so that Blockly delete and create events
// don't update the preview repeatedly.
Blockly.Events.disable();
// Caches information to reload or generate xml if switching to/from element.
// Caches information to reload or generate XML if switching to/from element.
// Only saves if a category is selected.
if (this.model.getSelectedId() != null && id != null) {
this.model.getSelected().saveFromWorkspace(this.toolboxWorkspace);
@@ -279,8 +274,7 @@ WorkspaceFactoryController.prototype.switchElement = function(id) {
/**
* Switches to a new tab for the element by ID. Helper for switchElement.
* Updates selected, clears the workspace and clears undo, loads a new element.
*
* @param {!string} id ID of category to load
* @param {string} id ID of category to load
*/
WorkspaceFactoryController.prototype.clearAndLoadElement = function(id) {
// Unselect current tab if switching to and from an element.
@@ -314,32 +308,29 @@ WorkspaceFactoryController.prototype.clearAndLoadElement = function(id) {
/**
* Tied to "Export" button. Gets a file name from the user and downloads
* the corresponding configuration xml to that file.
*
* @param {!string} exportMode The type of file to export
* the corresponding configuration XML to that file.
* @param {string} exportMode The type of file to export
* (WorkspaceFactoryController.MODE_TOOLBOX for the toolbox configuration,
* and WorkspaceFactoryController.MODE_PRELOAD for the pre-loaded workspace
* configuration)
*/
WorkspaceFactoryController.prototype.exportXmlFile = function(exportMode) {
// Get file name.
// Get file name.
var fileName = prompt('File Name for ' + (exportMode ==
WorkspaceFactoryController.MODE_TOOLBOX ? 'toolbox XML: ' :
'pre-loaded workspace XML: '));
if (!fileName) { // If cancelled
if (!fileName) { // If cancelled.
return;
}
// Generate XML.
if (exportMode == WorkspaceFactoryController.MODE_TOOLBOX) {
// Export the toolbox XML.
var configXml = Blockly.Xml.domToPrettyText
(this.generator.generateToolboxXml());
this.hasUnsavedToolboxChanges = false;
} else if (exportMode == WorkspaceFactoryController.MODE_PRELOAD) {
// Export the pre-loaded block XML.
var configXml = Blockly.Xml.domToPrettyText
(this.generator.generateWorkspaceXml());
this.hasUnsavedPreloadChanges = false;
@@ -400,8 +391,8 @@ WorkspaceFactoryController.prototype.updatePreview = function() {
// Only update the toolbox if not in read only mode.
if (!this.model.options['readOnly']) {
// Get toolbox XML.
var tree = Blockly.Options.parseToolboxTree
(this.generator.generateToolboxXml());
var tree = Blockly.Options.parseToolboxTree(
this.generator.generateToolboxXml());
// No categories, creates a simple flyout.
if (tree.getElementsByTagName('category').length == 0) {
@@ -456,8 +447,8 @@ WorkspaceFactoryController.prototype.saveStateFromWorkspace = function() {
this.hasUnsavedPreloadChanges = true;
}
this.model.savePreloadXml
(Blockly.Xml.workspaceToDom(this.toolboxWorkspace));
this.model.savePreloadXml(
Blockly.Xml.workspaceToDom(this.toolboxWorkspace));
}
};
@@ -465,8 +456,7 @@ WorkspaceFactoryController.prototype.saveStateFromWorkspace = function() {
* Used to completely reinject the preview workspace. This should be used only
* when switching from simple flyout to categories, or categories to simple
* flyout. More expensive than simply updating the flyout or toolbox.
*
* @param {!Element} tree of xml elements
* @param {!Element} Tree of XML elements
* @package
*/
WorkspaceFactoryController.prototype.reinjectPreview = function(tree) {
@@ -491,7 +481,7 @@ WorkspaceFactoryController.prototype.changeCategoryName = function() {
// Get new name from user.
var newName = this.promptForNewCategoryName('What do you want to change this'
+ ' category\'s name to?');
if (!newName) { // If cancelled.
if (!newName) { // If cancelled.
return;
}
// Change category name.
@@ -506,8 +496,7 @@ WorkspaceFactoryController.prototype.changeCategoryName = function() {
* below the currently selected element (offset categories away from the
* current element). Updates state to enable the correct element editing
* buttons.
*
* @param {int} offset The index offset from the currently selected element
* @param {number} offset The index offset from the currently selected element
* to swap with. Positive if the element to be swapped with is below, negative
* if the element to be swapped with is above.
*/
@@ -534,10 +523,9 @@ WorkspaceFactoryController.prototype.moveElement = function(offset) {
/**
* Moves a element to a specified index and updates the model and view
* accordingly. Helper functions throw an error if indexes are out of bounds.
*
* @param {!Element} element The element to move.
* @param {int} newIndex The index to insert the element at.
* @param {int} oldIndex The index the element is currently at.
* @param {number} newIndex The index to insert the element at.
* @param {number} oldIndex The index the element is currently at.
*/
WorkspaceFactoryController.prototype.moveElementToIndex = function(element,
newIndex, oldIndex) {
@@ -548,8 +536,7 @@ WorkspaceFactoryController.prototype.moveElementToIndex = function(element,
/**
* Changes the color of the selected category. Return if selected element is
* a separator.
*
* @param {!string} color The color to change the selected category. Must be
* @param {string} color The color to change the selected category. Must be
* a valid CSS string.
*/
WorkspaceFactoryController.prototype.changeSelectedCategoryColor =
@@ -575,7 +562,7 @@ WorkspaceFactoryController.prototype.loadCategory = function() {
var name = prompt('Enter the name of the category you would like to import '
+ '(Logic, Loops, Math, Text, Lists, Colour, Variables, or Functions)');
if (!name) {
return; // Exit if cancelled.
return; // Exit if cancelled.
}
} while (!this.isStandardCategoryName(name));
@@ -586,7 +573,6 @@ WorkspaceFactoryController.prototype.loadCategory = function() {
/**
* Loads a Standard Category by name and switches to it. Leverages
* StandardCategories. Returns if cannot load standard category.
*
* @param {string} name Name of the standard category to load.
*/
WorkspaceFactoryController.prototype.loadCategoryByName = function(name) {
@@ -659,12 +645,11 @@ WorkspaceFactoryController.prototype.loadStandardToolbox = function() {
this.addSeparator();
this.loadCategoryByName('Variables');
this.loadCategoryByName('Functions');
}
};
/**
* Given the name of a category, determines if it's the name of a standard
* category (case insensitive).
*
* @param {string} name The name of the category that should be checked if it's
* in StandardCategories categoryMap
* @return {boolean} True if name is a standard category name, false otherwise.
@@ -706,12 +691,11 @@ WorkspaceFactoryController.prototype.addSeparator = function() {
* this function loads that XML to the workspace to be edited further. This
* function switches mode to whatever the import mode is. Catches errors from
* file reading and prints an error message alerting the user.
*
* @param {string} file The path for the file to be imported into the workspace.
* Should contain valid toolbox XML.
* @param {!string} importMode The mode corresponding to the type of file the
* user is importing (WorkspaceFactoryController.MODE_TOOLBOX or
* WorkspaceFactoryController.MODE_PRELOAD).
* Should contain valid toolbox XML.
* @param {string} importMode The mode corresponding to the type of file the
* user is importing (WorkspaceFactoryController.MODE_TOOLBOX or
* WorkspaceFactoryController.MODE_PRELOAD).
*/
WorkspaceFactoryController.prototype.importFile = function(file, importMode) {
// Exit if cancelled.
@@ -737,8 +721,8 @@ WorkspaceFactoryController.prototype.importFile = function(file, importMode) {
var hasToolboxElements = controller.model.hasElements() ||
controller.toolboxWorkspace.getAllBlocks().length > 0;
if (hasToolboxElements &&
!confirm('Are you sure you want to import? You will lose your '
+ 'current toolbox. ')) {
!confirm('Are you sure you want to import? You will lose your ' +
'current toolbox.')) {
return;
}
// Import toolbox XML.
@@ -750,8 +734,8 @@ WorkspaceFactoryController.prototype.importFile = function(file, importMode) {
// Confirm that the user wants to override their current blocks.
if (controller.toolboxWorkspace.getAllBlocks().length > 0 &&
!confirm('Are you sure you want to import? You will lose your '
+ 'current workspace blocks. ')) {
!confirm('Are you sure you want to import? You will lose your ' +
'current workspace blocks.')) {
return;
}
@@ -761,12 +745,12 @@ WorkspaceFactoryController.prototype.importFile = function(file, importMode) {
// Throw error if invalid mode.
throw new Error("Unknown import mode: " + importMode);
}
} catch(e) {
alert('Cannot load XML from file.');
console.log(e);
} finally {
} catch(e) {
alert('Cannot load XML from file.');
console.log(e);
} finally {
Blockly.Events.enable();
}
}
}
// Read the file asynchronously.
@@ -777,9 +761,8 @@ WorkspaceFactoryController.prototype.importFile = function(file, importMode) {
* Given a XML DOM tree, loads it into the toolbox editing area so that the
* user can continue editing their work. Assumes that tree is in valid toolbox
* XML format. Assumes that the mode is MODE_TOOLBOX.
* @private
*
* @param {!Element} tree XML tree to be loaded to toolbox editing area.
* @private
*/
WorkspaceFactoryController.prototype.importToolboxFromTree_ = function(tree) {
// Clear current editing area.
@@ -853,45 +836,42 @@ WorkspaceFactoryController.prototype.importToolboxFromTree_ = function(tree) {
* Given a XML DOM tree, loads it into the pre-loaded workspace editing area.
* Assumes that tree is in valid XML format and that the selected mode is
* MODE_PRELOAD.
*
* @param {!Element} tree XML tree to be loaded to pre-loaded block editing
* area.
* area.
*/
WorkspaceFactoryController.prototype.importPreloadFromTree_ = function(tree) {
this.clearAndLoadXml_(tree);
this.model.savePreloadXml(tree);
this.updatePreview();
}
};
/**
* Given a XML DOM tree, loads it into the pre-loaded workspace editing area.
* Assumes that tree is in valid XML format and that the selected mode is
* MODE_PRELOAD.
*
* @param {!Element} tree XML tree to be loaded to pre-loaded block editing
* area.
* area.
*/
WorkspaceFactoryController.prototype.importPreloadFromTree_ = function(tree) {
this.clearAndLoadXml_(tree);
this.model.savePreloadXml(tree);
this.saveStateFromWorkspace();
this.updatePreview();
}
};
/**
* Given a XML DOM tree, loads it into the pre-loaded workspace editing area.
* Assumes that tree is in valid XML format and that the selected mode is
* MODE_PRELOAD.
*
* @param {!Element} tree XML tree to be loaded to pre-loaded block editing
* area.
* area.
*/
WorkspaceFactoryController.prototype.importPreloadFromTree_ = function(tree) {
this.clearAndLoadXml_(tree);
this.model.savePreloadXml(tree);
this.saveStateFromWorkspace();
this.updatePreview();
}
};
/**
* Clears the editing area completely, deleting all categories and all
@@ -925,7 +905,6 @@ WorkspaceFactoryController.prototype.clearAll = function() {
* and visually marked as shadow blocks, allowing the user to move and edit
* them (which would be impossible with actual shadow blocks). Updates the
* preview when done.
*
*/
WorkspaceFactoryController.prototype.addShadow = function() {
// No block selected to make a shadow block.
@@ -946,10 +925,9 @@ WorkspaceFactoryController.prototype.addShadow = function() {
/**
* Sets a block and all of its children to be user-generated shadow blocks,
* both in the model and view.
* @private
*
* @param {!Blockly.Block} block The block to be converted to a user-generated
* shadow block.
* @private
*/
WorkspaceFactoryController.prototype.addShadowForBlockAndChildren_ =
function(block) {
@@ -972,7 +950,6 @@ WorkspaceFactoryController.prototype.addShadowForBlockAndChildren_ =
* If the currently selected block is a user-generated shadow block, this
* function makes it a normal block again, removing it from the list of
* shadow blocks and loading the workspace again. Updates the preview again.
*
*/
WorkspaceFactoryController.prototype.removeShadow = function() {
// No block selected to modify.
@@ -992,14 +969,13 @@ WorkspaceFactoryController.prototype.removeShadow = function() {
/**
* Given a unique block ID, uses the model to determine if a block is a
* user-generated shadow block.
*
* @param {!string} blockId The unique ID of the block to examine.
* @param {string} blockId The unique ID of the block to examine.
* @return {boolean} True if the block is a user-generated shadow block, false
* otherwise.
*/
WorkspaceFactoryController.prototype.isUserGenShadowBlock = function(blockId) {
return this.model.isShadowBlock(blockId);
}
};
/**
* Call when importing XML containing real shadow blocks. This function turns
@@ -1030,8 +1006,7 @@ WorkspaceFactoryController.prototype.convertShadowBlocks = function() {
* Sets the currently selected mode that determines what the toolbox workspace
* is being used to edit. Updates the view and then saves and loads XML
* to and from the toolbox and updates the help text.
*
* @param {!string} tab The type of tab being switched to
* @param {string} tab The type of tab being switched to
* (WorkspaceFactoryController.MODE_TOOLBOX or
* WorkspaceFactoryController.MODE_PRELOAD).
*/
@@ -1076,7 +1051,6 @@ WorkspaceFactoryController.prototype.setMode = function(mode) {
* Clears the toolbox workspace and loads XML to it, marking shadow blocks
* as necessary.
* @private
*
* @param {!Element} xml The XML to be loaded to the workspace.
*/
WorkspaceFactoryController.prototype.clearAndLoadXml_ = function(xml) {
@@ -1097,7 +1071,7 @@ WorkspaceFactoryController.prototype.setStandardOptionsAndUpdate = function() {
this.view.setBaseOptions();
this.view.setCategoryOptions(this.model.hasElements());
this.generateNewOptions();
};
};
/**
* Generates a new options object for injecting a Blockly workspace based
@@ -1114,9 +1088,8 @@ WorkspaceFactoryController.prototype.generateNewOptions = function() {
/**
* Generates a new options object for injecting a Blockly workspace based on
* user input.
* @private
*
* @return {!Object} Blockly injection options object.
* @private
*/
WorkspaceFactoryController.prototype.readOptions_ = function() {
var optionsObj = Object.create(null);
@@ -1199,13 +1172,11 @@ WorkspaceFactoryController.prototype.readOptions_ = function() {
* 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
* @param {string} format The format of the file to import, either 'JSON' or
* 'JavaScript'.
*/
WorkspaceFactoryController.prototype.importBlocks =
function(file, format) {
WorkspaceFactoryController.prototype.importBlocks = function(file, format) {
// Generate category name from file name.
var categoryName = file.name;
@@ -1254,9 +1225,8 @@ WorkspaceFactoryController.prototype.importBlocks =
/*
* Updates the block library category in the toolbox workspace toolbox.
*
* @param {!Element} categoryXml XML for the block library category.
* @param {!Array<!string>} libBlockTypes Array of block types from the block
* @param {!Array.<string>} libBlockTypes Array of block types from the block
* library.
*/
WorkspaceFactoryController.prototype.setBlockLibCategory =
@@ -1283,8 +1253,7 @@ WorkspaceFactoryController.prototype.setBlockLibCategory =
/**
* Return the block types used in the custom toolbox and pre-loaded workspace.
*
* @return {!Array.<!string>} Block types used in the custom toolbox and
* @return {!Array.<string>} Block types used in the custom toolbox and
* pre-loaded workspace.
*/
WorkspaceFactoryController.prototype.getAllUsedBlockTypes = function() {
@@ -1295,7 +1264,6 @@ WorkspaceFactoryController.prototype.getAllUsedBlockTypes = function() {
* Determines if a block loaded in the workspace has a definition (if it
* is a standard block, is defined in the block library, or has a definition
* imported).
*
* @param {!Blockly.Block} block The block to examine.
*/
WorkspaceFactoryController.prototype.isDefinedBlock = function(block) {
@@ -1318,7 +1286,6 @@ WorkspaceFactoryController.prototype.warnForUndefinedBlocks_ = function() {
/*
* Determines if a standard variable category is in the custom toolbox.
*
* @return {boolean} True if a variables category is in use, false otherwise.
*/
WorkspaceFactoryController.prototype.hasVariablesCategory = function() {
@@ -1327,7 +1294,6 @@ WorkspaceFactoryController.prototype.hasVariablesCategory = function() {
/**
* Determines if a standard procedures category is in the custom toolbox.
*
* @return {boolean} True if a procedures category is in use, false otherwise.
*/
WorkspaceFactoryController.prototype.hasProceduresCategory = function() {
@@ -1336,7 +1302,6 @@ WorkspaceFactoryController.prototype.hasProceduresCategory = function() {
/**
* Determines if there are any unsaved changes in workspace factory.
*
* @return {boolean} True if there are unsaved changes, false otherwise.
*/
WorkspaceFactoryController.prototype.hasUnsavedChanges = function() {

View File

@@ -19,7 +19,7 @@
*/
/**
* @fileoverview Generates the configuration xml used to update the preview
* @fileoverview Generates the configuration XML used to update the preview
* workspace or print to the console or download to a file. Leverages
* Blockly.Xml and depends on information in the model (holds a reference).
* Depends on a hidden workspace created in the generator to load saved XML in
@@ -30,6 +30,7 @@
goog.require('FactoryUtils');
/**
* Class for a WorkspaceFactoryGenerator
* @constructor
@@ -49,11 +50,10 @@ WorkspaceFactoryGenerator = function(model) {
};
/**
* Generates the xml for the toolbox or flyout with information from
* Generates the XML for the toolbox or flyout with information from
* toolboxWorkspace and the model. Uses the hiddenWorkspace to generate XML.
* Save state of workspace in model (saveFromWorkspace) before calling if
* changes might have been made to the selected category.
*
* @param {!Blockly.workspace} toolboxWorkspace Toolbox editing workspace where
* blocks are added by user to be part of the toolbox.
* @return {!Element} XML element representing toolbox or flyout corresponding
@@ -117,7 +117,6 @@ WorkspaceFactoryGenerator.prototype.generateToolboxXml = function() {
* Generates XML for the workspace (different from generateConfigXml in that
* it includes XY and ID attributes). Uses a workspace and converts user
* generated shadow blocks to actual shadow blocks.
*
* @return {!Element} XML element representing toolbox or flyout corresponding
* to toolbox workspace.
*/
@@ -133,16 +132,14 @@ WorkspaceFactoryGenerator.prototype.generateWorkspaceXml = function() {
generatedXml.setAttribute('id', 'workspaceBlocks');
generatedXml.setAttribute('style', 'display:none');
return generatedXml;
};
};
/**
* Generates a string representation of the options object for injecting the
* workspace and starter code.
*
* @return {!string} String representation of starter code for injecting.
* @return {string} String representation of starter code for injecting.
*/
WorkspaceFactoryGenerator.prototype.generateInjectString = function() {
var addAttributes = function(obj, tabChar) {
if (!obj) {
return '{}\n';
@@ -183,27 +180,25 @@ WorkspaceFactoryGenerator.prototype.generateInjectString = function() {
'/* Load blocks to workspace. */\n' +
'Blockly.Xml.domToWorkspace(workspace, workspaceBlocks);';
return finalStr;
}
};
/**
* Loads the given XML to the hidden workspace and sets any user-generated
* shadow blocks to be actual shadow blocks.
* @private
*
* @param {!Element} xml The XML to be loaded to the hidden workspace.
* @private
*/
WorkspaceFactoryGenerator.prototype.loadToHiddenWorkspace_ = function(xml) {
this.hiddenWorkspace.clear();
Blockly.Xml.domToWorkspace(xml, this.hiddenWorkspace);
this.setShadowBlocksInHiddenWorkspace_();
}
};
/**
/**
* Encodes blocks in the hidden workspace in a XML DOM element. Very
* similar to workspaceToDom, but doesn't capture IDs. Uses the top-level
* blocks loaded in hiddenWorkspace.
* @private
*
* @param {!Element} xmlDom Tree of XML elements to be appended to.
*/
WorkspaceFactoryGenerator.prototype.appendHiddenWorkspaceToDom_ =
@@ -220,7 +215,6 @@ WorkspaceFactoryGenerator.prototype.appendHiddenWorkspaceToDom_ =
* actual shadow blocks. This is done so that blockToDom records them as
* shadow blocks instead of regular blocks.
* @private
*
*/
WorkspaceFactoryGenerator.prototype.setShadowBlocksInHiddenWorkspace_ =
function() {
@@ -235,9 +229,8 @@ 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
* @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) {
@@ -248,4 +241,3 @@ WorkspaceFactoryGenerator.prototype.getDefinedBlocks = function(blockTypes) {
}
return blocks;
};

View File

@@ -37,7 +37,6 @@ WorkspaceFactoryInit = {};
/**
* Initialization for workspace factory tab.
*
* @param {!FactoryController} controller The controller for the workspace
* factory tab.
*/
@@ -59,75 +58,76 @@ WorkspaceFactoryInit.initWorkspaceFactory = function(controller) {
/**
* Initialize the color picker in workspace factory.
* @private
*
* @param {!FactoryController} controller The controller for the workspace
* factory tab.
* @private
*/
WorkspaceFactoryInit.initColorPicker_ = function(controller) {
// Array of Blockly category colors, variety of hues with saturation 45%
// and value 65% as specified in Blockly Developer documentation:
// https://developers.google.com/blockly/guides/create-custom-blocks/define-blocks
var colors = ['#A65C5C',
'#A6635C',
'#A66A5C',
'#A6725C',
'#A6795C',
'#A6815C',
'#A6885C',
'#A6905C',
'#A6975C',
'#A69F5C',
'#A6A65C',
'#9FA65C',
'#97A65C',
'#90A65C',
'#88A65C',
'#81A65C',
'#79A65C',
'#6FA65C',
'#66A65C',
'#5EA65C',
'#5CA661',
'#5CA668',
'#5CA66F',
'#5CA677',
'#5CA67E',
'#5CA686',
'#5CA68D',
'#5CA695',
'#5CA69C',
'#5CA6A4',
'#5CA1A6',
'#5C9AA6',
'#5C92A6',
'#5C8BA6',
'#5C83A6',
'#5C7CA6',
'#5C74A6',
'#5C6AA6',
'#5C61A6',
'#5E5CA6',
'#665CA6',
'#6D5CA6',
'#745CA6',
'#7C5CA6',
'#835CA6',
'#8B5CA6',
'#925CA6',
'#9A5CA6',
'#A15CA6',
'#A65CA4',
'#A65C9C',
'#A65C95',
'#A65C8D',
'#A65C86',
'#A65C7E',
'#A65C77',
'#A65C6F',
'#A65C66',
'#A65C61',
'#A65C5E'];
var colors = [
'#A65C5C',
'#A6635C',
'#A66A5C',
'#A6725C',
'#A6795C',
'#A6815C',
'#A6885C',
'#A6905C',
'#A6975C',
'#A69F5C',
'#A6A65C',
'#9FA65C',
'#97A65C',
'#90A65C',
'#88A65C',
'#81A65C',
'#79A65C',
'#6FA65C',
'#66A65C',
'#5EA65C',
'#5CA661',
'#5CA668',
'#5CA66F',
'#5CA677',
'#5CA67E',
'#5CA686',
'#5CA68D',
'#5CA695',
'#5CA69C',
'#5CA6A4',
'#5CA1A6',
'#5C9AA6',
'#5C92A6',
'#5C8BA6',
'#5C83A6',
'#5C7CA6',
'#5C74A6',
'#5C6AA6',
'#5C61A6',
'#5E5CA6',
'#665CA6',
'#6D5CA6',
'#745CA6',
'#7C5CA6',
'#835CA6',
'#8B5CA6',
'#925CA6',
'#9A5CA6',
'#A15CA6',
'#A65CA4',
'#A65C9C',
'#A65C95',
'#A65C8D',
'#A65C86',
'#A65C7E',
'#A65C77',
'#A65C6F',
'#A65C66',
'#A65C61',
'#A65C5E'
];
// Create color picker with specific set of Blockly colors.
var colorPicker = new goog.ui.ColorPicker();
@@ -141,16 +141,15 @@ WorkspaceFactoryInit.initColorPicker_ = function(controller) {
goog.events.listen(popupPicker, 'change', function(e) {
controller.changeSelectedCategoryColor(popupPicker.getSelectedColor());
document.getElementById('dropdownDiv_editCategory').classList.remove
("show");
('show');
});
};
/**
* Assign click handlers for workspace factory.
* @private
*
* @param {!FactoryController} controller The controller for the workspace
* factory tab.
* @private
*/
WorkspaceFactoryInit.assignWorkspaceFactoryClickHandlers_ =
function(controller) {
@@ -169,35 +168,35 @@ WorkspaceFactoryInit.assignWorkspaceFactoryClickHandlers_ =
document.getElementById('button_add').addEventListener
('click',
function() {
document.getElementById('dropdownDiv_add').classList.toggle("show");
document.getElementById('dropdownDiv_add').classList.toggle('show');
});
document.getElementById('dropdown_newCategory').addEventListener
('click',
function() {
controller.addCategory();
document.getElementById('dropdownDiv_add').classList.remove("show");
document.getElementById('dropdownDiv_add').classList.remove('show');
});
document.getElementById('dropdown_loadCategory').addEventListener
('click',
function() {
controller.loadCategory();
document.getElementById('dropdownDiv_add').classList.remove("show");
document.getElementById('dropdownDiv_add').classList.remove('show');
});
document.getElementById('dropdown_separator').addEventListener
('click',
function() {
controller.addSeparator();
document.getElementById('dropdownDiv_add').classList.remove("show");
document.getElementById('dropdownDiv_add').classList.remove('show');
});
document.getElementById('dropdown_loadStandardToolbox').addEventListener
('click',
function() {
controller.loadStandardToolbox();
document.getElementById('dropdownDiv_add').classList.remove("show");
document.getElementById('dropdownDiv_add').classList.remove('show');
});
document.getElementById('button_remove').addEventListener
@@ -210,21 +209,21 @@ WorkspaceFactoryInit.assignWorkspaceFactoryClickHandlers_ =
('click',
function() {
controller.exportXmlFile(WorkspaceFactoryController.MODE_TOOLBOX);
document.getElementById('dropdownDiv_export').classList.remove("show");
document.getElementById('dropdownDiv_export').classList.remove('show');
});
document.getElementById('dropdown_exportPreload').addEventListener
('click',
function() {
controller.exportXmlFile(WorkspaceFactoryController.MODE_PRELOAD);
document.getElementById('dropdownDiv_export').classList.remove("show");
document.getElementById('dropdownDiv_export').classList.remove('show');
});
document.getElementById('dropdown_exportOptions').addEventListener
('click',
function() {
controller.exportInjectFile();
document.getElementById('dropdownDiv_export').classList.remove("show");
document.getElementById('dropdownDiv_export').classList.remove('show');
});
document.getElementById('dropdown_exportAll').addEventListener
@@ -233,16 +232,16 @@ WorkspaceFactoryInit.assignWorkspaceFactoryClickHandlers_ =
controller.exportInjectFile();
controller.exportXmlFile(WorkspaceFactoryController.MODE_TOOLBOX);
controller.exportXmlFile(WorkspaceFactoryController.MODE_PRELOAD);
document.getElementById('dropdownDiv_export').classList.remove("show");
document.getElementById('dropdownDiv_export').classList.remove('show');
});
document.getElementById('button_export').addEventListener
('click',
function() {
document.getElementById('dropdownDiv_export').classList.toggle("show");
document.getElementById('dropdownDiv_load').classList.remove("show");
document.getElementById('dropdownDiv_export').classList.toggle('show');
document.getElementById('dropdownDiv_load').classList.remove('show');
document.getElementById('dropdownDiv_importBlocks').classList.
remove("show");
remove('show');
});
document.getElementById('button_up').addEventListener
@@ -261,7 +260,7 @@ WorkspaceFactoryInit.assignWorkspaceFactoryClickHandlers_ =
('click',
function() {
document.getElementById('dropdownDiv_editCategory').classList.
toggle("show");
toggle('show');
});
document.getElementById('dropdown_name').addEventListener
@@ -269,25 +268,25 @@ WorkspaceFactoryInit.assignWorkspaceFactoryClickHandlers_ =
function() {
controller.changeCategoryName();
document.getElementById('dropdownDiv_editCategory').classList.
remove("show");
remove('show');
});
document.getElementById('button_importBlocks').addEventListener
document.getElementById('button_importBlocks').addEventListener
('click',
function() {
document.getElementById('dropdownDiv_importBlocks').classList.
toggle("show");
document.getElementById('dropdownDiv_export').classList.remove("show");
document.getElementById('dropdownDiv_load').classList.remove("show");
toggle('show');
document.getElementById('dropdownDiv_export').classList.remove('show');
document.getElementById('dropdownDiv_load').classList.remove('show');
});
document.getElementById('button_load').addEventListener
('click',
function() {
document.getElementById('dropdownDiv_load').classList.toggle("show");
document.getElementById('dropdownDiv_export').classList.remove("show");
document.getElementById('dropdownDiv_load').classList.toggle('show');
document.getElementById('dropdownDiv_export').classList.remove('show');
document.getElementById('dropdownDiv_importBlocks').classList.
remove("show");
remove('show');
});
document.getElementById('input_loadToolbox').addEventListener
@@ -295,7 +294,7 @@ document.getElementById('button_importBlocks').addEventListener
function() {
controller.importFile(event.target.files[0],
WorkspaceFactoryController.MODE_TOOLBOX);
document.getElementById('dropdownDiv_load').classList.remove("show");
document.getElementById('dropdownDiv_load').classList.remove('show');
});
document.getElementById('input_loadPreload').addEventListener
@@ -303,7 +302,7 @@ document.getElementById('button_importBlocks').addEventListener
function() {
controller.importFile(event.target.files[0],
WorkspaceFactoryController.MODE_PRELOAD);
document.getElementById('dropdownDiv_load').classList.remove("show");
document.getElementById('dropdownDiv_load').classList.remove('show');
});
document.getElementById('input_importBlocksJson').addEventListener
@@ -311,7 +310,7 @@ document.getElementById('button_importBlocks').addEventListener
function() {
controller.importBlocks(event.target.files[0],'JSON');
document.getElementById('dropdownDiv_importBlocks').classList.
remove("show");
remove('show');
});
document.getElementById('input_importBlocksJs').addEventListener
@@ -319,16 +318,16 @@ document.getElementById('button_importBlocks').addEventListener
function() {
controller.importBlocks(event.target.files[0],'JavaScript');
document.getElementById('dropdownDiv_importBlocks').classList.
remove("show");
remove('show');
});
document.getElementById('button_clear').addEventListener
('click',
function() {
document.getElementById('dropdownDiv_importBlocks').classList.
remove("show");
document.getElementById('dropdownDiv_export').classList.remove("show");
document.getElementById('dropdownDiv_load').classList.remove("show");
remove('show');
document.getElementById('dropdownDiv_export').classList.remove('show');
document.getElementById('dropdownDiv_load').classList.remove('show');
controller.clearAll();
});
@@ -367,10 +366,9 @@ document.getElementById('button_importBlocks').addEventListener
/**
* Add event listeners for workspace factory.
* @private
*
* @param {!FactoryController} controller The controller for the workspace
* factory tab.
* @private
*/
WorkspaceFactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
// Use up and down arrow keys to move categories.
@@ -547,7 +545,6 @@ WorkspaceFactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
/**
* Display or hide the add shadow button.
*
* @param {boolean} show True if the add shadow button should be shown, false
* otherwise.
*/
@@ -558,25 +555,22 @@ WorkspaceFactoryInit.displayAddShadow_ = function(show) {
/**
* Display or hide the remove shadow button.
*
* @param {boolean} show True if the remove shadow button should be shown, false
* otherwise.
*/
WorkspaceFactoryInit.displayRemoveShadow_ = function(show) {
document.getElementById('button_removeShadow').style.display =
show ? 'inline-block' : 'none';
}
};
/**
* Add listeners for workspace factory options input elements.
* @private
*
* @param {!FactoryController} controller The controller for the workspace
* factory tab.
* @private
*/
WorkspaceFactoryInit.addWorkspaceFactoryOptionsListeners_ =
function(controller) {
// Checking the grid checkbox displays grid options.
document.getElementById('option_grid_checkbox').addEventListener('change',
function(e) {

View File

@@ -63,7 +63,6 @@ WorkspaceFactoryModel = function() {
/**
* Given a name, determines if it is the name of a category already present.
* Used when getting a valid category name from the user.
*
* @param {string} name String name to be compared against.
* @return {boolean} True if string is a used category name, false otherwise.
*/
@@ -79,7 +78,6 @@ WorkspaceFactoryModel.prototype.hasCategoryByName = function(name) {
/**
* Determines if a category with the 'VARIABLE' tag exists.
*
* @return {boolean} True if there exists a category with the Variables tag,
* false otherwise.
*/
@@ -89,7 +87,6 @@ WorkspaceFactoryModel.prototype.hasVariables = function() {
/**
* Determines if a category with the 'PROCEDURE' tag exists.
*
* @return {boolean} True if there exists a category with the Procedures tag,
* false otherwise.
*/
@@ -100,7 +97,6 @@ WorkspaceFactoryModel.prototype.hasProcedures = function() {
/**
* Determines if the user has any elements in the toolbox. Uses the length of
* toolboxList.
*
* @return {boolean} True if elements exist, false otherwise.
*/
WorkspaceFactoryModel.prototype.hasElements = function() {
@@ -109,7 +105,6 @@ WorkspaceFactoryModel.prototype.hasElements = function() {
/**
* Given a ListElement, adds it to the toolbox list.
*
* @param {!ListElement} element The element to be added to the list.
*/
WorkspaceFactoryModel.prototype.addElementToList = function(element) {
@@ -126,8 +121,7 @@ WorkspaceFactoryModel.prototype.addElementToList = function(element) {
/**
* Given an index, deletes a list element and all associated data.
*
* @param {int} index The index of the list element to delete.
* @param {number} index The index of the list element to delete.
*/
WorkspaceFactoryModel.prototype.deleteElementFromList = function(index) {
// Check if index is out of bounds.
@@ -148,24 +142,22 @@ WorkspaceFactoryModel.prototype.deleteElementFromList = function(index) {
* is empty. Should be called when removing the last element from toolbox list.
* If the toolbox list is empty, selected stores the XML for the single flyout
* of blocks displayed.
*
*/
WorkspaceFactoryModel.prototype.createDefaultSelectedIfEmpty = function() {
if (this.toolboxList.length == 0) {
this.flyout = new ListElement(ListElement.TYPE_FLYOUT);
this.selected = this.flyout;
}
}
};
/**
* Moves a list element to a certain position in toolboxList by removing it
* and then inserting it at the correct index. Checks that indices are in
* bounds (throws error if not), but assumes that oldIndex is the correct index
* for list element.
*
* @param {!ListElement} element The element to move in toolboxList.
* @param {int} newIndex The index to insert the element at.
* @param {int} oldIndex The index the element is currently at.
* @param {number} newIndex The index to insert the element at.
* @param {number} oldIndex The index the element is currently at.
*/
WorkspaceFactoryModel.prototype.moveElementToIndex = function(element, newIndex,
oldIndex) {
@@ -176,12 +168,11 @@ WorkspaceFactoryModel.prototype.moveElementToIndex = function(element, newIndex,
}
this.deleteElementFromList(oldIndex);
this.toolboxList.splice(newIndex, 0, element);
}
};
/**
* Returns the ID of the currently selected element. Returns null if there are
* no categories (if selected == null).
*
* @return {string} The ID of the element currently selected.
*/
WorkspaceFactoryModel.prototype.getSelectedId = function() {
@@ -192,7 +183,6 @@ WorkspaceFactoryModel.prototype.getSelectedId = function() {
* Returns the name of the currently selected category. Returns null if there
* are no categories (if selected == null) or the selected element is not
* a category (in which case its name is null).
*
* @return {string} The name of the category currently selected.
*/
WorkspaceFactoryModel.prototype.getSelectedName = function() {
@@ -201,7 +191,6 @@ WorkspaceFactoryModel.prototype.getSelectedName = function() {
/**
* Returns the currently selected list element object.
*
* @return {ListElement} The currently selected ListElement
*/
WorkspaceFactoryModel.prototype.getSelected = function() {
@@ -210,7 +199,6 @@ WorkspaceFactoryModel.prototype.getSelected = function() {
/**
* Sets list element currently selected by id.
*
* @param {string} id ID of list element that should now be selected.
*/
WorkspaceFactoryModel.prototype.setSelectedById = function(id) {
@@ -220,12 +208,10 @@ WorkspaceFactoryModel.prototype.setSelectedById = function(id) {
/**
* Given an ID of a list element, returns the index of that list element in
* toolboxList. Returns -1 if ID is not present.
*
* @param {!string} id The ID of list element to search for.
* @return {int} The index of the list element in toolboxList, or -1 if it
* @param {string} id The ID of list element to search for.
* @return {number} The index of the list element in toolboxList, or -1 if it
* doesn't exist.
*/
WorkspaceFactoryModel.prototype.getIndexByElementId = function(id) {
for (var i = 0; i < this.toolboxList.length; i++) {
if (this.toolboxList[i].id == id) {
@@ -237,8 +223,7 @@ WorkspaceFactoryModel.prototype.getIndexByElementId = function(id) {
/**
* Given the ID of a list element, returns that ListElement object.
*
* @param {!string} id The ID of element to search for.
* @param {string} id The ID of element to search for.
* @return {ListElement} Corresponding ListElement object in toolboxList, or
* null if that element does not exist.
*/
@@ -254,8 +239,7 @@ WorkspaceFactoryModel.prototype.getElementById = function(id) {
/**
* Given the index of a list element in toolboxList, returns that ListElement
* object.
*
* @param {int} index The index of the element to return.
* @param {number} index The index of the element to return.
* @return {ListElement} The corresponding ListElement object in toolboxList.
*/
WorkspaceFactoryModel.prototype.getElementByIndex = function(index) {
@@ -266,8 +250,7 @@ WorkspaceFactoryModel.prototype.getElementByIndex = function(index) {
};
/**
* Returns the xml to load the selected element.
*
* Returns the XML to load the selected element.
* @return {!Element} The XML of the selected element, or null if there is
* no selected element.
*/
@@ -277,8 +260,7 @@ WorkspaceFactoryModel.prototype.getSelectedXml = function() {
/**
* Return ordered list of ListElement objects.
*
* @return {!Array<!ListElement>} ordered list of ListElement objects
* @return {!Array.<!ListElement>} ordered list of ListElement objects
*/
WorkspaceFactoryModel.prototype.getToolboxList = function() {
return this.toolboxList;
@@ -286,9 +268,8 @@ WorkspaceFactoryModel.prototype.getToolboxList = function() {
/**
* Gets the ID of a category given its name.
*
* @param {string} name Name of category.
* @return {int} ID of category
* @return {number} ID of category
*/
WorkspaceFactoryModel.prototype.getCategoryIdByName = function(name) {
for (var i = 0; i < this.toolboxList.length; i++) {
@@ -313,8 +294,7 @@ WorkspaceFactoryModel.prototype.clearToolboxList = function() {
/**
* Class for a ListElement
* Adds a shadow block to the list of shadow blocks.
*
* @param {!string} blockId The unique ID of block to be added.
* @param {string} blockId The unique ID of block to be added.
*/
WorkspaceFactoryModel.prototype.addShadowBlock = function(blockId) {
this.shadowBlocks.push(blockId);
@@ -323,8 +303,7 @@ WorkspaceFactoryModel.prototype.addShadowBlock = function(blockId) {
/**
* Removes a shadow block ID from the list of shadow block IDs if that ID is
* in the list.
*
* @param {!string} blockId The unique ID of block to be removed.
* @param {string} blockId The unique ID of block to be removed.
*/
WorkspaceFactoryModel.prototype.removeShadowBlock = function(blockId) {
for (var i = 0; i < this.shadowBlocks.length; i++) {
@@ -337,8 +316,7 @@ WorkspaceFactoryModel.prototype.removeShadowBlock = function(blockId) {
/**
* Determines if a block is a shadow block given a unique block ID.
*
* @param {!string} blockId The unique ID of the block to examine.
* @param {string} blockId The unique ID of the block to examine.
* @return {boolean} True if the block is a user-generated shadow block, false
* otherwise.
*/
@@ -354,10 +332,9 @@ WorkspaceFactoryModel.prototype.isShadowBlock = function(blockId) {
/**
* Given a set of blocks currently loaded, returns all blocks in the workspace
* that are user generated shadow blocks.
*
* @param {!<Blockly.Block>} blocks Array of blocks currently loaded.
* @return {!<Blockly.Block>} Array of user-generated shadow blocks currently
* loaded.
* loaded.
*/
WorkspaceFactoryModel.prototype.getShadowBlocksInWorkspace =
function(workspaceBlocks) {
@@ -373,9 +350,8 @@ WorkspaceFactoryModel.prototype.getShadowBlocksInWorkspace =
/**
* Adds a custom tag to a category, updating state variables accordingly.
* Only accepts 'VARIABLE' and 'PROCEDURE' tags.
*
* @param {!ListElement} category The category to add the tag to.
* @param {!string} tag The custom tag to add to the category.
* @param {string} tag The custom tag to add to the category.
*/
WorkspaceFactoryModel.prototype.addCustomTag = function(category, tag) {
// Only update list elements that are categories.
@@ -395,7 +371,6 @@ WorkspaceFactoryModel.prototype.addCustomTag = function(category, tag) {
/**
* Have basic pre-loaded workspace working
* Saves XML as XML to be pre-loaded into the workspace.
*
* @param {!Element} xml The XML to be saved.
*/
WorkspaceFactoryModel.prototype.savePreloadXml = function(xml) {
@@ -404,7 +379,6 @@ WorkspaceFactoryModel.prototype.savePreloadXml = function(xml) {
/**
* Gets the XML to be pre-loaded into the workspace.
*
* @return {!Element} The XML for the workspace.
*/
WorkspaceFactoryModel.prototype.getPreloadXml = function() {
@@ -413,7 +387,6 @@ WorkspaceFactoryModel.prototype.getPreloadXml = function() {
/**
* Sets a new options object for injecting a Blockly workspace.
*
* @param {Object} options Options object for injecting a Blockly workspace.
*/
WorkspaceFactoryModel.prototype.setOptions = function(options) {
@@ -424,8 +397,7 @@ WorkspaceFactoryModel.prototype.setOptions = function(options) {
* Returns an array of all the block types currently being used in the toolbox
* and the pre-loaded blocks. No duplicates.
* TODO(evd2014): Move pushBlockTypesToList to FactoryUtils.
*
* @return {!Array<!string>} Array of block types currently being used.
* @return {!Array.<string>} Array of block types currently being used.
*/
WorkspaceFactoryModel.prototype.getAllUsedBlockTypes = function() {
var blockTypeList = [];
@@ -466,8 +438,7 @@ WorkspaceFactoryModel.prototype.getAllUsedBlockTypes = function() {
/**
* Adds new imported block types to the list of current imported block types.
*
* @param {!Array<!string>} blockTypes Array of block types imported.
* @param {!Array.<string>} blockTypes Array of block types imported.
*/
WorkspaceFactoryModel.prototype.addImportedBlockTypes = function(blockTypes) {
this.importedBlockTypes = this.importedBlockTypes.concat(blockTypes);
@@ -475,8 +446,7 @@ WorkspaceFactoryModel.prototype.addImportedBlockTypes = function(blockTypes) {
/**
* Updates block types in block library.
*
* @param {!Array<!string>} blockTypes Array of block types in block library.
* @param {!Array.<string>} blockTypes Array of block types in block library.
*/
WorkspaceFactoryModel.prototype.updateLibBlockTypes = function(blockTypes) {
this.libBlockTypes = blockTypes;
@@ -485,8 +455,7 @@ WorkspaceFactoryModel.prototype.updateLibBlockTypes = function(blockTypes) {
/**
* Determines if a block type is defined as a standard block, in the block
* library, or as an imported block.
*
* @param {!string} blockType Block type to check.
* @param {string} blockType Block type to check.
* @return {boolean} True if blockType is defined, false otherwise.
*/
WorkspaceFactoryModel.prototype.isDefinedBlockType = function(blockType) {
@@ -499,8 +468,7 @@ WorkspaceFactoryModel.prototype.isDefinedBlockType = function(blockType) {
/**
* Checks if any of the block types are already defined.
*
* @param {!Array<!string>} blockTypes Array of block types.
* @param {!Array.<string>} blockTypes Array of block types.
* @return {boolean} True if a block type in the array is already defined,
* false if none of the blocks are already defined.
*/
@@ -511,7 +479,7 @@ WorkspaceFactoryModel.prototype.hasDefinedBlockTypes = function(blockTypes) {
}
}
return false;
}
};
/**
* Class for a ListElement.
@@ -539,7 +507,6 @@ ListElement.TYPE_FLYOUT = 'flyout';
/**
* Saves a category by updating its XML (does not save XML for
* elements that are not categories).
*
* @param {!Blockly.workspace} workspace The workspace to save category entry
* from.
*/
@@ -555,7 +522,6 @@ ListElement.prototype.saveFromWorkspace = function(workspace) {
/**
* Changes the name of a category object given a new name. Returns if
* not a category.
*
* @param {string} name New name of category.
*/
ListElement.prototype.changeName = function (name) {
@@ -569,8 +535,7 @@ ListElement.prototype.changeName = function (name) {
/**
* Sets the color of a category. If tries to set the color of something other
* than a category, returns.
*
* @param {!string} color The color that should be used for that category.
* @param {string} color The color that should be used for that category.
*/
ListElement.prototype.changeColor = function (color) {
if (this.type != ListElement.TYPE_CATEGORY) {
@@ -582,7 +547,6 @@ ListElement.prototype.changeColor = function (color) {
/**
* Makes a copy of the original element and returns it. Everything about the
* copy is identical except for its ID.
*
* @return {!ListElement} The copy of the ListElement.
*/
ListElement.prototype.copy = function() {

View File

@@ -28,13 +28,12 @@
* @author Emma Dauterman (edauterman)
*/
goog.require('FactoryUtils');
/**
* Class for a WorkspaceFactoryView
* @constructor
*/
goog.require('FactoryUtils');
/**
* Class for a WorkspaceFactoryView
* @constructor
*/
WorkspaceFactoryView = function() {
// For each tab, maps ID of a ListElement to the td DOM element.
this.tabMap = Object.create(null);
@@ -42,9 +41,8 @@ WorkspaceFactoryView = function() {
/**
* Adds a category tab to the UI, and updates tabMap accordingly.
*
* @param {!string} name The name of the category being created
* @param {!string} id ID of category being created
* @param {string} name The name of the category being created
* @param {string} id ID of category being created
* @return {!Element} DOM element created for tab
*/
WorkspaceFactoryView.prototype.addCategoryRow = function(name, id) {
@@ -70,9 +68,8 @@ WorkspaceFactoryView.prototype.addCategoryRow = function(name, id) {
/**
* Deletes a category tab from the UI and updates tabMap accordingly.
*
* @param {!string} id ID of category to be deleted.
* @param {!string} name The name of the category to be deleted.
* @param {string} id ID of category to be deleted.
* @param {string} name The name of the category to be deleted.
*/
WorkspaceFactoryView.prototype.deleteElementRow = function(id, index) {
// Delete tab entry.
@@ -98,18 +95,16 @@ WorkspaceFactoryView.prototype.addEmptyCategoryMessage = function() {
document.getElementById('categoryHeader').textContent =
'Your categories will appear here';
}
}
};
/**
* Given the index of the currently selected element, updates the state of
* the buttons that allow the user to edit the list elements. Updates the edit
* and arrow buttons. Should be called when adding or removing elements
* or when changing to a new element or when swapping to a different element.
*
* TODO(evd2014): Switch to using CSS to add/remove styles.
*
* @param {int} selectedIndex The index of the currently selected category,
* -1 if no categories created.
* @param {number} selectedIndex The index of the currently selected category,
* -1 if no categories created.
* @param {ListElement} selected The selected ListElement.
*/
WorkspaceFactoryView.prototype.updateState = function(selectedIndex, selected) {
@@ -128,9 +123,8 @@ WorkspaceFactoryView.prototype.updateState = function(selectedIndex, selected) {
/**
* Determines the DOM id for a category given its name.
*
* @param {!string} name Name of category
* @return {!string} ID of category tab
* @param {string} name Name of category
* @return {string} ID of category tab
*/
WorkspaceFactoryView.prototype.createCategoryIdName = function(name) {
return 'tab_' + name;
@@ -138,8 +132,7 @@ WorkspaceFactoryView.prototype.createCategoryIdName = function(name) {
/**
* Switches a tab on or off.
*
* @param {!string} id ID of the tab to switch on or off.
* @param {string} id ID of the tab to switch on or off.
* @param {boolean} selected True if tab should be on, false if tab should be
* off.
*/
@@ -154,7 +147,6 @@ WorkspaceFactoryView.prototype.setCategoryTabSelection =
/**
* Used to bind a click to a certain DOM element (used for category tabs).
* Taken directly from code.js
*
* @param {string|!Element} e1 tab element or corresponding id string
* @param {!Function} func Function to be executed on click
*/
@@ -169,31 +161,28 @@ WorkspaceFactoryView.prototype.bindClick = function(el, func) {
/**
* Creates a file and downloads it. In some browsers downloads, and in other
* browsers, opens new tab with contents.
*
* @param {!string} filename Name of file
* @param {string} filename Name of file
* @param {!Blob} data Blob containing contents to download
*/
WorkspaceFactoryView.prototype.createAndDownloadFile =
function(filename, data) {
var clickEvent = new MouseEvent("click", {
"view": window,
"bubbles": true,
"cancelable": false
});
var a = document.createElement('a');
a.href = window.URL.createObjectURL(data);
a.download = filename;
a.textContent = 'Download file!';
a.dispatchEvent(clickEvent);
};
var clickEvent = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': false
});
var a = document.createElement('a');
a.href = window.URL.createObjectURL(data);
a.download = filename;
a.textContent = 'Download file!';
a.dispatchEvent(clickEvent);
};
/**
* Given the ID of a certain category, updates the corresponding tab in
* the DOM to show a new name.
*
* @param {!string} newName Name of string to be displayed on tab
* @param {!string} id ID of category to be updated
*
* @param {string} newName Name of string to be displayed on tab
* @param {string} id ID of category to be updated
*/
WorkspaceFactoryView.prototype.updateCategoryName = function(newName, id) {
this.tabMap[id].textContent = newName;
@@ -204,15 +193,14 @@ WorkspaceFactoryView.prototype.updateCategoryName = function(newName, id) {
* Moves a tab from one index to another. Adjusts index inserting before
* based on if inserting before or after. Checks that the indexes are in
* bounds, throws error if not.
*
* @param {!string} id The ID of the category to move.
* @param {int} newIndex The index to move the category to.
* @param {int} oldIndex The index the category is currently at.
* @param {string} id The ID of the category to move.
* @param {number} newIndex The index to move the category to.
* @param {number} oldIndex The index the category is currently at.
*/
WorkspaceFactoryView.prototype.moveTabToIndex =
function(id, newIndex, oldIndex) {
var table = document.getElementById('categoryTable');
// Check that indexes are in bounds
// Check that indexes are in bounds.
if (newIndex < 0 || newIndex >= table.rows.length || oldIndex < 0 ||
oldIndex >= table.rows.length) {
throw new Error('Index out of bounds when moving tab in the view.');
@@ -234,23 +222,21 @@ WorkspaceFactoryView.prototype.moveTabToIndex =
/**
* Given a category ID and color, use that color to color the left border of the
* tab for that category.
*
* @param {!string} id The ID of the category to color.
* @param {!string} color The color for to be used for the border of the tab.
* @param {string} id The ID of the category to color.
* @param {string} color The color for to be used for the border of the tab.
* Must be a valid CSS string.
*/
WorkspaceFactoryView.prototype.setBorderColor = function(id, color) {
var tab = this.tabMap[id];
tab.style.borderLeftWidth = "8px";
tab.style.borderLeftStyle = "solid";
tab.style.borderLeftWidth = '8px';
tab.style.borderLeftStyle = 'solid';
tab.style.borderColor = color;
};
/**
* Given a separator ID, creates a corresponding tab in the view, updates
* tab map, and returns the tab.
*
* @param {!string} id The ID of the separator.
* @param {string} id The ID of the separator.
* @param {!Element} The td DOM element representing the separator.
*/
WorkspaceFactoryView.prototype.addSeparatorTab = function(id) {
@@ -275,7 +261,6 @@ WorkspaceFactoryView.prototype.addSeparatorTab = function(id) {
* toolbox workspace, depending on the value of disable. Used when switching
* to/from separators where the user shouldn't be able to drag blocks into
* the workspace.
*
* @param {boolean} disable True if the workspace should be disabled, false
* if it should be enabled.
*/
@@ -293,7 +278,6 @@ WorkspaceFactoryView.prototype.disableWorkspace = function(disable) {
/**
* Determines if the workspace should be disabled. The workspace should be
* disabled if category is a separator or has VARIABLE or PROCEDURE tags.
*
* @return {boolean} True if the workspace should be disabled, false otherwise.
*/
WorkspaceFactoryView.prototype.shouldDisableWorkspace = function(category) {
@@ -302,7 +286,7 @@ WorkspaceFactoryView.prototype.shouldDisableWorkspace = function(category) {
category.custom == 'VARIABLE' || category.custom == 'PROCEDURE');
};
/*
/**
* Removes all categories and separators in the view. Clears the tabMap to
* reflect this.
*/
@@ -320,8 +304,7 @@ WorkspaceFactoryView.prototype.clearToolboxTabs = function() {
* Given a set of blocks currently loaded user-generated shadow blocks, visually
* marks them without making them actual shadow blocks (allowing them to still
* be editable and movable).
*
* @param {!<Blockly.Block>} blocks Array of user-generated shadow blocks
* @param {!Array.<!Blockly.Block>} blocks Array of user-generated shadow blocks
* currently loaded.
*/
WorkspaceFactoryView.prototype.markShadowBlocks = function(blocks) {
@@ -334,9 +317,8 @@ WorkspaceFactoryView.prototype.markShadowBlocks = function(blocks) {
* Visually marks a user-generated shadow block as a shadow block in the
* workspace without making the block an actual shadow block (allowing it
* to be moved and edited).
*
* @param {!Blockly.Block} block The block that should be marked as a shadow
* block (must be rendered).
* block (must be rendered).
*/
WorkspaceFactoryView.prototype.markShadowBlock = function(block) {
// Add Blockly CSS for user-generated shadow blocks.
@@ -346,7 +328,6 @@ WorkspaceFactoryView.prototype.markShadowBlock = function(block) {
block.setWarningText('Shadow blocks must be nested inside' +
' other blocks to be displayed.');
}
if (FactoryUtils.hasVariableField(block)) {
block.setWarningText('Cannot make variable blocks shadow blocks.');
}
@@ -354,9 +335,8 @@ WorkspaceFactoryView.prototype.markShadowBlock = function(block) {
/**
* Removes visual marking for a shadow block given a rendered block.
*
* @param {!Blockly.Block} block The block that should be unmarked as a shadow
* block (must be rendered).
* block (must be rendered).
*/
WorkspaceFactoryView.prototype.unmarkShadowBlock = function(block) {
// Remove Blockly CSS for user-generated shadow blocks.
@@ -368,9 +348,8 @@ WorkspaceFactoryView.prototype.unmarkShadowBlock = function(block) {
/**
* Sets the tabs for modes according to which mode the user is currenly
* editing in.
*
* @param {!string} mode The mode being switched to
* (WorkspaceFactoryController.MODE_TOOLBOX or WorkspaceFactoryController.MODE_PRELOAD).
* @param {string} mode The mode being switched to
* (WorkspaceFactoryController.MODE_TOOLBOX or WorkspaceFactoryController.MODE_PRELOAD).
*/
WorkspaceFactoryView.prototype.setModeSelection = function(mode) {
document.getElementById('tab_preload').className = mode ==
@@ -385,17 +364,16 @@ WorkspaceFactoryView.prototype.setModeSelection = function(mode) {
/**
* Updates the help text above the workspace depending on the selected mode.
*
* @param {!string} mode The selected mode (WorkspaceFactoryController.MODE_TOOLBOX or
* WorkspaceFactoryController.MODE_PRELOAD).
* @param {string} mode The selected mode (WorkspaceFactoryController.MODE_TOOLBOX or
* WorkspaceFactoryController.MODE_PRELOAD).
*/
WorkspaceFactoryView.prototype.updateHelpText = function(mode) {
if (mode == WorkspaceFactoryController.MODE_TOOLBOX) {
var helpText = 'Drag blocks into the workspace to configure the toolbox '
+ 'in your custom workspace.';
var helpText = 'Drag blocks into the workspace to configure the toolbox ' +
'in your custom workspace.';
} else {
var helpText = 'Drag blocks into the workspace to pre-load them in your '
+ 'custom workspace.'
var helpText = 'Drag blocks into the workspace to pre-load them in your ' +
'custom workspace.'
}
document.getElementById('editHelpText').textContent = helpText;
};
@@ -407,7 +385,7 @@ WorkspaceFactoryView.prototype.updateHelpText = function(mode) {
WorkspaceFactoryView.prototype.setBaseOptions = function() {
// Set basic options.
document.getElementById('option_css_checkbox').checked = true;
document.getElementById('option_infiniteBlocks_checkbox').checked = true;
document.getElementById('option_infiniteBlocks_checkbox').checked = true;
document.getElementById('option_maxBlocks_number').value = 100;
document.getElementById('option_media_text').value =
'https://blockly-demo.appspot.com/static/media/';
@@ -439,7 +417,6 @@ WorkspaceFactoryView.prototype.setBaseOptions = function() {
/**
* Updates category specific options depending on if there are categories
* currently present. Updates checkboxes and text fields in the view.
*
* @param {boolean} hasCategories True if categories are present, false if all
* blocks are displayed in a single flyout.
*/
@@ -449,4 +426,4 @@ WorkspaceFactoryView.prototype.setCategoryOptions = function(hasCategories) {
document.getElementById('option_disable_checkbox').checked = hasCategories;
document.getElementById('option_scrollbars_checkbox').checked = hasCategories;
document.getElementById('option_trashcan_checkbox').checked = hasCategories;
}
};