Blockly Factory: Update Workspace Factory Tab (#562)

* Updated tab in blockly factory to reflect changes made to workspace factory, changes mainly in index.html and wfactory_init.js

* Added tab for workspace editing mode

* Changed font size in dropdown menu

* Added class for options inputs to add event listeners more easily
This commit is contained in:
Emma Dauterman
2016-08-17 15:56:30 -07:00
committed by picklesrus
parent 55aa5b804a
commit 7b854f85a4
7 changed files with 236 additions and 79 deletions

View File

@@ -497,7 +497,7 @@ AppController.prototype.init = function() {
this.addBlockFactoryEventListeners();
// Workspace Factory init.
FactoryInit.initWorkspaceFactory(this.workspaceFactoryController);
WorkspaceFactoryInit.initWorkspaceFactory(this.workspaceFactoryController);
};

View File

@@ -313,7 +313,7 @@ td {
width: 30%;
}
#category_section {
#toolbox_div, #preload_div {
width: 20%;
}
@@ -388,16 +388,17 @@ td {
}
/* Links inside the dropdown */
.dropdown-content a {
color: black;
display: block;
padding: 12px 16px;
text-decoration: none;
.dropdown-content a, .dropdown-content label {
color: black;
display: block;
font-size: small;
padding: 12px 16px;
text-decoration: none;
}
/* Change color of dropdown links on hover */
.dropdown-content a:hover {
background-color: #f1f1f1;
/* Change color of dropdown links on hover. */
.dropdown-content a:hover, .dropdown-content label:hover {
background-color: #f1f1f1
}
/* Show the dropdown menu */

View File

@@ -125,21 +125,42 @@
<div id="workspaceFactoryContent">
<p>
<input type="file" id="input_import" class="inputfile" class="large"></input>
<label for="input_import" class="buttonStyle large">Import</label>
<button id="button_export" class="large">Export</button>
<button id="button_print" class="large">Print</button>
<button id="button_clear" class="large">Clear</button>
<div class="dropdown">
<button id="button_import">Import</button>
<div id="dropdownDiv_import" class="dropdown-content">
<input type="file" id="input_importToolbox" class="inputfile"></input>
<label for="input_importToolbox">Toolbox</label>
<input type="file" id="input_importPreload" class="inputfile"</input>
<label for="input_importPreload">Workspace Blocks</label>
</div>
</div>
<div class="dropdown">
<button id="button_export">Export</button>
<div id="dropdownDiv_export" class="dropdown-content">
<a id='dropdown_exportToolbox'>Toolbox</a>
<a id='dropdown_exportPreload'>Workspace Blocks</a>
<a id='dropdown_exportOptions'>Inject Options</a>
<a id='dropdown_exportAll'>All</a>
</div>
</div>
<button id="button_print">Print Toolbox</button>
<button id="button_clear">Clear Toolbox</button>
</p>
<section id="createDiv">
<h3>Workspace Editor:</h3>
<p>Drag blocks into your toolbox.</p>
<p id="editHelpText">Drag blocks into your toolbox:</p>
<table id='workspaceTabs' style="width:auto">
<td id="tab_toolbox" class="tabon">Toolbox</td>
<td id="tab_preload" class="taboff">Workspace</td>
</table>
<section id="toolbox_section">
<div id="toolbox_blocks" class="content"></div>
<div id='disable_div'></div>
</section>
<aside id="category_section">
<aside id="toolbox_div">
<table id="categoryTable" style="width:auto">
<td id="tab_help">Your categories will appear here</td>
</table>
@@ -161,24 +182,60 @@
<p>&nbsp;</p>
<div class='dropdown'>
<button id="button_editCategory" class="large">Edit Category</button>
<button id="button_editCategory">Edit Category</button>
<div id="dropdownDiv_editCategory" class="dropdown-content">
<a id='dropdown_name'>Name</a>
<a id='dropdown_color'>Color</a>
</div>
</div>
<div class='dropdown'>
<button id="button_editShadow" class="large">Edit Block</button>
<div id="dropdownDiv_editShadowAdd" class="dropdown-content">
<a id='dropdown_addShadow'>Add Shadow</a>
</div>
<div id="dropdownDiv_editShadowRemove" class="dropdown-content">
<a id='dropdown_removeShadow'>Remove Shadow</a>
</div>
</div>
</aside>
<div class='dropdown'>
<button id="button_editShadow">Edit Block</button>
<div id="dropdownDiv_editShadowAdd" class="dropdown-content">
<a id='dropdown_addShadow'>Add Shadow</a>
</div>
<div id="dropdownDiv_editShadowRemove" class="dropdown-content">
<a id='dropdown_removeShadow'>Remove Shadow</a>
</div>
</div>
<aside id='preload_div' style='display:none'>
<p>Configure the <a href="https://developers.google.com/blockly/guides/get-started/web">options</a> for your Blockly inject call.</p>
<button class="small" id="button_standardOptions">Standard Options</button>
<form id="workspace_options">
<input type="checkbox" id="option_collapse_checkbox" class="optionsInput">Collapsible Blocks<br>
<input type="checkbox" id="option_comments_checkbox" class="optionsInput">Comments for Blocks<br>
<input type="checkbox" id="option_css_checkbox" class="optionsInput">Use Blockly CSS<br>
<input type="checkbox" id="option_disable_checkbox" class="optionsInput">Disabled Blocks<br>
<input type="checkbox" id="option_grid_checkbox" class="optionsInput">Use Grid<br>
<div id="grid_options" name="grid" style="display:none">
Spacing <input type="text" id="gridOption_spacing_text" class="optionsInput"value="0"><br>
Length <input type="text" id="gridOption_length_text" class="optionsInput" value="1"><br>
Color <input type="text" id="gridOption_colour_text" class="optionsInput" value="#888"><br>
<input type="checkbox" id="gridOption_snap_checkbox" class="optionsInput" value="grid_snap_checkbox">Snap<br>
</div>
Max Blocks <input type="text" id="option_maxBlocks_text" class="optionsInput" value="Infinity"><br>
Path to Blockly Media <input type="text" id="option_media_text" class="optionsInput"><br>
<input type="checkbox" id="option_readOnly_checkbox" class="optionsInput">Read Only<br>
<input type="checkbox" id="option_rtl_checkbox" class="optionsInput">Layout with RTL<br>
<input type="checkbox" id="option_scrollbars_checkbox" class="optionsInput">Scrollbars<br>
<input type="checkbox" id="option_sounds_checkbox" class="optionsInput">Sounds<br>
<input type="checkbox" id="option_trashcan_checkbox" class="optionsInput">Trashcan<br>
<input type="checkbox" id="option_zoom_checkbox" class="optionsInput">Zoom<br>
<div id="zoom_options" name="zoom" style="display:none">
<input type="checkbox" id="zoomOption_controls_checkbox" class="optionsInput">Zoom Controls<br>
<input type="checkbox" id="zoomOption_wheel_checkbox" class="optionsInput">Zoom Wheel<br>
Start Scale <input type="text" id="zoomOption_startScale_text" class="optionsInput" name="startScale" value="1.0"><br>
Max Scale <input type="text" id="zoomOption_maxScale_text" class="optionsInput" value="3"><br>
Min Scale <input type="text" id="zoomOption_minScale_text" class="optionsInput" value="0.3"><br>
Scale Speed <input type="text" id="zoomOption_scaleSpeed_text" class="optionsInput" value="1.2"><br>
</div>
</form>
</aside>
</section>
<aside id="previewDiv">

View File

@@ -195,16 +195,10 @@ td {
}
/* Links inside the dropdown */
.dropdown-content a {
color: black;
display: block;
padding: 12px 16px;
text-decoration: none;
}
.dropdown-content label {
.dropdown-content a, .dropdown-content label {
color: black;
display: block;
font-size: small;
padding: 12px 16px;
text-decoration: none;
}

View File

@@ -305,7 +305,7 @@ WorkspaceFactoryController.prototype.clearAndLoadElement = function(id) {
// Mark all shadow blocks laoded and order blocks as if shown in a flyout.
this.view.markShadowBlocks(this.model.getShadowBlocksInWorkspace
(this.toolboxWorkspace.getAllBlocks()));
this.toolboxWorkspace.cleanUp_();
this.toolboxWorkspace.cleanUp();
// Update category editing buttons.
this.view.updateState(this.model.getIndexByElementId
@@ -441,7 +441,7 @@ WorkspaceFactoryController.prototype.updatePreview = function() {
WorkspaceFactoryController.prototype.saveStateFromWorkspace = function() {
if (this.selectedMode == WorkspaceFactoryController.MODE_TOOLBOX) {
// If currently editing the toolbox.
this.model.getSelected().saveFromWorkspace(toolboxWorkspace);
this.model.getSelected().saveFromWorkspace(this.toolboxWorkspace);
} else if (this.selectedMode == WorkspaceFactoryController.MODE_PRELOAD) {
// If currently editing the pre-loaded workspace.
this.model.savePreloadXml
@@ -675,6 +675,7 @@ WorkspaceFactoryController.prototype.importFile = function(file, importMode) {
return;
}
var controller = this;
var reader = new FileReader();
// To be executed when the reader has read the file.
@@ -722,7 +723,7 @@ WorkspaceFactoryController.prototype.importToolboxFromTree_ = function(tree) {
// No categories present.
// Load all the blocks into a single category evenly spaced.
Blockly.Xml.domToWorkspace(tree, this.toolboxWorkspace);
this.toolboxWorkspace.cleanUp_();
this.toolboxWorkspace.cleanUp();
// Convert actual shadow blocks to user-generated shadow blocks.
this.convertShadowBlocks();
@@ -747,7 +748,7 @@ WorkspaceFactoryController.prototype.importToolboxFromTree_ = function(tree) {
}
// Evenly space the blocks.
this.toolboxWorkspace.cleanUp_();
this.toolboxWorkspace.cleanUp();
// Convert actual shadow blocks to user-generated shadow blocks.
this.convertShadowBlocks();

View File

@@ -18,20 +18,20 @@
* limitations under the License.
*/
/**
* @fileoverview Contains the init functions for the workspace factory tab.
* Adds click handlers to buttons and dropdowns, adds event listeners for
* keydown events and Blockly events, and configures the initial setup of
* the page.
*
* @author Emma Dauterman (evd2014)
*/
/**
* @fileoverview Contains the init functions for the workspace factory tab.
* Adds click handlers to buttons and dropdowns, adds event listeners for
* keydown events and Blockly events, and configures the initial setup of
* the page.
*
* @author Emma Dauterman (evd2014)
*/
/**
* Namespace for workspace factory initialization methods.
* @namespace
*/
FactoryInit = {};
WorkspaceFactoryInit = {};
/**
* Initialization for workspace factory tab.
@@ -39,7 +39,7 @@ FactoryInit = {};
* @param {!FactoryController} controller The controller for the workspace
* factory tab.
*/
FactoryInit.initWorkspaceFactory = function(controller) {
WorkspaceFactoryInit.initWorkspaceFactory = function(controller) {
// Disable category editing buttons until categories are created.
document.getElementById('button_remove').disabled = true;
document.getElementById('button_up').disabled = true;
@@ -50,6 +50,10 @@ FactoryInit.initWorkspaceFactory = function(controller) {
this.initColorPicker_(controller);
this.addWorkspaceFactoryEventListeners_(controller);
this.assignWorkspaceFactoryClickHandlers_(controller);
this.addWorkspaceFactoryOptionsListeners_(controller);
// Check standard options and apply the changes to update the view.
controller.setStandardOptionsAndUpdate();
};
/**
@@ -59,7 +63,7 @@ FactoryInit.initWorkspaceFactory = function(controller) {
* @param {!FactoryController} controller The controller for the workspace
* factory tab.
*/
FactoryInit.initColorPicker_ = function(controller) {
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
@@ -147,7 +151,20 @@ FactoryInit.initColorPicker_ = function(controller) {
* @param {!FactoryController} controller The controller for the workspace
* factory tab.
*/
FactoryInit.assignWorkspaceFactoryClickHandlers_ = function(controller) {
WorkspaceFactoryInit.assignWorkspaceFactoryClickHandlers_ =
function(controller) {
document.getElementById('tab_toolbox').addEventListener
('click',
function() {
controller.setMode(WorkspaceFactoryController.MODE_TOOLBOX);
});
document.getElementById('tab_preload').addEventListener
('click',
function() {
controller.setMode(WorkspaceFactoryController.MODE_PRELOAD);
});
document.getElementById('button_add').addEventListener
('click',
function() {
@@ -181,11 +198,42 @@ FactoryInit.assignWorkspaceFactoryClickHandlers_ = function(controller) {
controller.removeElement();
});
document.getElementById('dropdown_exportToolbox').addEventListener
('click',
function() {
controller.exportXmlFile(WorkspaceFactoryController.MODE_TOOLBOX);
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('dropdown_exportOptions').addEventListener
('click',
function() {
controller.exportOptionsFile();
document.getElementById('dropdownDiv_export').classList.remove("show");
});
document.getElementById('dropdown_exportAll').addEventListener
('click',
function() {
controller.exportXmlFile(WorkspaceFactoryController.MODE_TOOLBOX);
controller.exportXmlFile(WorkspaceFactoryController.MODE_PRELOAD);
controller.exportOptionsFile();
document.getElementById('dropdownDiv_export').classList.remove("show");
});
document.getElementById('button_export').addEventListener
('click',
function() {
controller.exportConfig();
});
document.getElementById('dropdownDiv_export').classList.toggle("show");
document.getElementById('dropdownDiv_import').classList.remove("show");
})
document.getElementById('button_print').addEventListener
('click',
@@ -248,16 +296,33 @@ FactoryInit.assignWorkspaceFactoryClickHandlers_ = function(controller) {
remove("show");
});
document.getElementById('input_import').addEventListener
document.getElementById('button_import').addEventListener
('click',
function() {
document.getElementById('dropdownDiv_import').classList.toggle("show");
document.getElementById('dropdownDiv_export').classList.remove("show");
});
document.getElementById('input_importToolbox').addEventListener
('change',
function(event) {
controller.importFile(event.target.files[0]);
function() {
controller.importFile(event.target.files[0],
WorkspaceFactoryController.MODE_TOOLBOX);
document.getElementById('dropdownDiv_import').classList.remove("show");
});
document.getElementById('input_importPreload').addEventListener
('change',
function() {
controller.importFile(event.target.files[0],
WorkspaceFactoryController.MODE_PRELOAD);
document.getElementById('dropdownDiv_import').classList.remove("show");
});
document.getElementById('button_clear').addEventListener
('click',
function() {
controller.clear();
controller.clearToolbox();
});
document.getElementById('dropdown_addShadow').addEventListener
@@ -281,6 +346,11 @@ FactoryInit.assignWorkspaceFactoryClickHandlers_ = function(controller) {
document.getElementById('button_editShadow').disabled = true;
}
});
document.getElementById('button_standardOptions').addEventListener
('click', function() {
controller.setStandardOptionsAndUpdate();
});
};
/**
@@ -290,7 +360,7 @@ FactoryInit.assignWorkspaceFactoryClickHandlers_ = function(controller) {
* @param {!FactoryController} controller The controller for the workspace
* factory tab.
*/
FactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
WorkspaceFactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
// Use up and down arrow keys to move categories.
// TODO(evd2014): When merge with next CL for editing preloaded blocks, make
// sure mode is toolbox.
@@ -305,18 +375,19 @@ FactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
});
// Add change listeners for toolbox workspace in workspace factory.
controller.toolboxWorkspace.addChangeListener(
function(e) {
controller.toolboxWorkspace.addChangeListener(function(e) {
// Listen for Blockly move and delete events to update preview.
// Not listening for Blockly create events because causes the user to drop
// blocks when dragging them into workspace. Could cause problems if ever
// load blocks into workspace directly without calling updatePreview.
if (e.type == Blockly.Events.MOVE || e.type == Blockly.Events.DELETE) {
if (e.type == Blockly.Events.MOVE || e.type == Blockly.Events.DELETE ||
e.type == Blockly.Events.CHANGE) {
controller.saveStateFromWorkspace();
controller.updatePreview();
}
// Listen for Blockly UI events to correctly enable the "Edit Block"
// button. Only enable "Edit Block" when a block is selected and it has a
// Listen for Blockly UI events to correctly enable the "Edit Block" button.
// Only enable "Edit Block" when a block is selected and it has a
// surrounding parent, meaning it is nested in another block (blocks that
// are not nested in parents cannot be shadow blocks).
if (e.type == Blockly.Events.MOVE || (e.type == Blockly.Events.UI &&
@@ -330,8 +401,7 @@ FactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
document.getElementById('button_editShadow').disabled = false;
Blockly.selected.setWarningText(null);
} else {
if (selected != null &&
controller.isUserGenShadowBlock(selected.id)) {
if (selected != null && controller.isUserGenShadowBlock(selected.id)) {
// Provide warning if shadow block is moved and is no longer a valid
// shadow block.
@@ -343,9 +413,8 @@ FactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
document.getElementById('button_editShadow').disabled = false;
} else {
// No block selected that is a shadow block or could be a valid
// shadow block.
// Disable block editing.
// No block selected that is a shadow block or could be a valid shadow
// block. Disable block editing.
document.getElementById('button_editShadow').disabled = true;
document.getElementById('dropdownDiv_editShadowRemove').classList.
remove("show");
@@ -362,3 +431,38 @@ FactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
}
});
};
/**
* Add listeners for workspace factory options input elements.
* @private
*
* @param {!FactoryController} controller The controller for the workspace
* factory tab.
*/
WorkspaceFactoryInit.addWorkspaceFactoryOptionsListeners_ =
function(controller) {
// Checking the grid checkbox displays grid options.
document.getElementById('option_grid_checkbox').addEventListener('change',
function(e) {
document.getElementById('grid_options').style.display =
document.getElementById('option_grid_checkbox').checked ?
'block' : 'none';
});
// Checking the grid checkbox displays zoom options.
document.getElementById('option_zoom_checkbox').addEventListener('change',
function(e) {
document.getElementById('zoom_options').style.display =
document.getElementById('option_zoom_checkbox').checked ?
'block' : 'none';
});
// Generate new options every time an options input is updated.
var optionsElements = document.getElementsByClassName('optionsInput');
for (var i = 0; i < optionsElements.length; i++) {
optionsElements[i].addEventListener('change', function() {
controller.generateNewOptions();
});
}
};

View File

@@ -21,8 +21,8 @@
/**
* Controls the UI elements for workspace factory, mainly the category tabs.
* Also includes downloading files because that interacts directly with the DOM.
* Depends on FactoryController (for adding mouse listeners). Tabs for each
* category are stored in tab map, which associates a unique ID for a
* Depends on WorkspaceFactoryController (for adding mouse listeners). Tabs for
* each category are stored in tab map, which associates a unique ID for a
* category with a particular tab.
*
* @author Emma Dauterman (edauterman)
@@ -349,28 +349,28 @@ WorkspaceFactoryView.prototype.unmarkShadowBlock = function(block) {
* editing in.
*
* @param {!string} mode The mode being switched to
* (FactoryController.MODE_TOOLBOX or FactoryController.MODE_PRELOAD).
* (WorkspaceFactoryController.MODE_TOOLBOX or WorkspaceFactoryController.MODE_PRELOAD).
*/
WorkspaceFactoryView.prototype.setModeSelection = function(mode) {
document.getElementById('tab_preload').className = mode ==
FactoryController.MODE_PRELOAD ? 'tabon' : 'taboff';
WorkspaceFactoryController.MODE_PRELOAD ? 'tabon' : 'taboff';
document.getElementById('preload_div').style.display = mode ==
FactoryController.MODE_PRELOAD ? 'block' : 'none';
WorkspaceFactoryController.MODE_PRELOAD ? 'block' : 'none';
document.getElementById('tab_toolbox').className = mode ==
FactoryController.MODE_TOOLBOX ? 'tabon' : 'taboff';
WorkspaceFactoryController.MODE_TOOLBOX ? 'tabon' : 'taboff';
document.getElementById('toolbox_div').style.display = mode ==
FactoryController.MODE_TOOLBOX ? 'block' : 'none';
WorkspaceFactoryController.MODE_TOOLBOX ? 'block' : 'none';
};
/**
* Updates the help text above the workspace depending on the selected mode.
*
* @param {!string} mode The selected mode (FactoryController.MODE_TOOLBOX or
* FactoryController.MODE_PRELOAD).
* @param {!string} mode The selected mode (WorkspaceFactoryController.MODE_TOOLBOX or
* WorkspaceFactoryController.MODE_PRELOAD).
*/
WorkspaceFactoryView.prototype.updateHelpText = function(mode) {
var helpText = 'Drag your blocks into your ' + (mode ==
FactoryController.MODE_TOOLBOX ? 'toolbox: ' : 'pre-loaded workspace: ');
WorkspaceFactoryController.MODE_TOOLBOX ? 'toolbox: ' : 'pre-loaded workspace: ');
document.getElementById('editHelpText').textContent = helpText;
};