From fceba91c6caead8240174b3fe3b2947f57ddd791 Mon Sep 17 00:00:00 2001 From: Sean Lip Date: Thu, 19 Jan 2017 17:12:15 -0800 Subject: [PATCH] Clean up workspace.component.js. When moving a block from one place to another, move all blocks after it too, and adjust the active descs accordingly. --- accessible/tree.service.js | 30 +++-- accessible/utils.service.js | 1 + accessible/workspace-block.component.js | 140 +++++++++++------------- accessible/workspace.component.js | 6 + 4 files changed, 87 insertions(+), 90 deletions(-) diff --git a/accessible/tree.service.js b/accessible/tree.service.js index db047c375..36248e013 100644 --- a/accessible/tree.service.js +++ b/accessible/tree.service.js @@ -42,7 +42,7 @@ blocklyApp.TreeService = ng.core.Class({ this.utilsService = utilsService; // The suffix used for all IDs of block root elements. - this.BLOCK_ROOT_ID_SUFFIX_ = 'blockRoot'; + this.BLOCK_ROOT_ID_SUFFIX_ = blocklyApp.BLOCK_ROOT_ID_SUFFIX; // Maps tree IDs to the IDs of their active descendants. this.activeDescendantIds_ = {}; // Array containing all the sidebar button elements. @@ -245,7 +245,8 @@ blocklyApp.TreeService = ng.core.Class({ }, safelyRemoveBlock_: function(block, deleteBlockFunc) { // Runs the given deleteBlockFunc (which should have the effect of deleting - // the given block) and then does one of two things: + // the given block, and possibly others after it) and then does one of two + // things: // - If the deleted block was an isolated top-level block, this means the // current tree has no more blocks after the deletion. So, pick a new // tree to focus on. @@ -284,11 +285,10 @@ blocklyApp.TreeService = ng.core.Class({ var blockRootElement = document.getElementById(blockRootId); // Find the new active desc for the current tree by trying the following - // possibilities in order: the parent, the next sibling, and the previous - // sibling. + // possibilities in order: the parent, and the previous sibling. (The + // next sibling would be moved together with the moved block.) var newActiveDesc = this.getParentLi_(blockRootElement) || - this.getNextSiblingLi_(blockRootElement) || this.getPreviousSiblingLi_(blockRootElement); this.clearActiveDesc(treeId); @@ -356,7 +356,7 @@ blocklyApp.TreeService = ng.core.Class({ var newBlockId = that.blockConnectionService.attachToMarkedConnection( block); that.safelyRemoveBlock_(block, function() { - block.dispose(true); + block.dispose(false); }); // Invoke a digest cycle, so that the DOM settles. @@ -373,14 +373,20 @@ blocklyApp.TreeService = ng.core.Class({ // that was originally first, not second as might be expected. // Here, we double-check to ensure that all affected trees have // an active desc set. - if (document.getElementById(oldDestinationTreeId) && - !that.getActiveDescId(oldDestinationTreeId)) { + if (document.getElementById(oldDestinationTreeId)) { + var activeDescId = that.getActiveDescId(oldDestinationTreeId); + var activeDescTreeId = null; + if (activeDescId) { + var oldDestinationBlock = that.getContainingBlock_( + document.getElementById(activeDescId)); + activeDescTreeId = that.getTreeIdForBlock( + oldDestinationBlock); + if (activeDescTreeId != oldDestinationTreeId) { + that.clearActiveDesc(oldDestinationTreeId); + } + } that.initActiveDesc(oldDestinationTreeId); } - if (document.getElementById(newDestinationTreeId) && - !that.getActiveDescId(newDestinationTreeId)) { - that.initActiveDesc(newDestinationTreeId); - } } that.notificationsService.speak( diff --git a/accessible/utils.service.js b/accessible/utils.service.js index 5fe565ea5..aea954419 100644 --- a/accessible/utils.service.js +++ b/accessible/utils.service.js @@ -27,6 +27,7 @@ var blocklyApp = {}; blocklyApp.ID_FOR_EMPTY_WORKSPACE_BTN = 'blocklyEmptyWorkspaceBtn'; +blocklyApp.BLOCK_ROOT_ID_SUFFIX = '-blockRoot'; blocklyApp.UtilsService = ng.core.Class({ constructor: [function() {}], diff --git a/accessible/workspace-block.component.js b/accessible/workspace-block.component.js index 70383576a..8f05a14a2 100644 --- a/accessible/workspace-block.component.js +++ b/accessible/workspace-block.component.js @@ -18,49 +18,53 @@ */ /** - * @fileoverview Angular2 Component that details how Blockly.Block's are - * rendered in the workspace in AccessibleBlockly. Also handles any - * interactions with the blocks. + * @fileoverview Angular2 Component representing a Blockly.Block in the + * workspace. * @author madeeha@google.com (Madeeha Ghori) */ blocklyApp.WorkspaceBlockComponent = ng.core.Component({ selector: 'blockly-workspace-block', template: ` -
  • - +
  • @@ -90,13 +94,11 @@ blocklyApp.WorkspaceBlockComponent = ng.core.Component({ } ], ngOnInit: function() { - var SUPPORTED_FIELDS = [ - Blockly.FieldTextInput, Blockly.FieldDropdown, - Blockly.FieldCheckbox]; + var SUPPORTED_FIELDS = [Blockly.FieldTextInput, Blockly.FieldDropdown]; this.inputListAsFieldSegments = this.block.inputList.map(function(input) { - // Converts the input to a list of field segments. Each field segment - // represents a user-editable field, prefixed by any number of - // non-editable fields. + // Converts the input list to an array of field segments. Each field + // segment represents a user-editable field, prefixed by an arbitrary + // number of non-editable fields. var fieldSegments = []; var bufferedFields = []; @@ -131,60 +133,42 @@ blocklyApp.WorkspaceBlockComponent = ng.core.Component({ return fieldSegments; }); - // Make a list of all the id keys. - this.idKeys = ['blockRoot', 'blockSummary', 'listItem', 'label']; - - // Generate a list of action buttons. - this.fieldButtonsInfo = [{ - baseIdKey: 'markSpot', - translationIdForText: 'MARK_THIS_SPOT', - action: function(connection) { - that.blockConnectionService.markConnection(connection); - }, - isDisabled: function() { - return false; - } - }]; + // Generate unique IDs for elements in this component. + this.componentIds = {}; + this.componentIds.blockRoot = + this.block.id + blocklyApp.BLOCK_ROOT_ID_SUFFIX; + this.componentIds.blockSummary = this.block.id + '-blockSummary'; var that = this; - this.fieldButtonsInfo.forEach(function(buttonInfo) { - for (var i = 0; i < that.block.inputList.length; i++) { - that.idKeys.push( - buttonInfo.baseIdKey + i, buttonInfo.baseIdKey + 'Button' + i); + this.componentIds.inputs = this.block.inputList.map(function(input, i) { + var idsToGenerate = ['inputLi', 'fieldLabel']; + if (input.connection && !input.connection.targetBlock()) { + idsToGenerate.push('actionButtonLi', 'actionButton', 'buttonLabel'); } + + var inputIds = {}; + idsToGenerate.forEach(function(idBaseString) { + inputIds[idBaseString] = [that.block.id, i, idBaseString].join('-'); + }); + + return inputIds; }); - for (var i = 0; i < this.block.inputList.length; i++) { - var blockInput = this.block.inputList[i]; - that.idKeys.push( - 'inputList' + i, 'inputMenuLabel' + i, 'listItem' + i, - 'fieldLabel' + i); - } - }, - ngDoCheck: function() { - // Generate a unique id for each id key. This needs to be done every time - // changes happen, but after the first ng-init, in order to force the - // element ids to change in cases where, e.g., a block is inserted in the - // middle of a sequence of blocks. - this.idMap = {}; - for (var i = 0; i < this.idKeys.length; i++) { - this.idMap[this.idKeys[i]] = this.block.id + this.idKeys[i]; - } }, ngAfterViewInit: function() { - // If this is a top-level tree in the workspace, set its id and active - // descendant. (Note that a timeout is needed here in order to trigger - // Angular change detection.) + // If this is a top-level tree in the workspace, ensure that it has an + // active descendant. (Note that a timeout is needed here in order to + // trigger Angular change detection.) var that = this; setTimeout(function() { - if (that.tree && that.level === 0 && !that.tree.id) { - that.tree.id = 'blockly-' + Blockly.utils.genUid(); - } - if (that.tree && that.level === 0 && - !that.treeService.getActiveDescId(that.tree.id)) { - that.treeService.setActiveDesc(that.idMap['blockRoot'], that.tree.id); + if (that.level === 0 && !that.treeService.getActiveDescId(that.tree.id)) { + that.treeService.setActiveDesc( + that.componentIds.blockRoot, that.tree.id); } }); }, + addInteriorLink: function(connection) { + this.blockConnectionService.markConnection(connection); + }, getBlockDescription: function() { var blockDescription = this.utilsService.getBlockDescription(this.block); @@ -197,9 +181,6 @@ blocklyApp.WorkspaceBlockComponent = ng.core.Component({ return blockDescription; } }, - generateAriaLabelledByAttr: function(mainLabel, secondLabel) { - return mainLabel + (secondLabel ? ' ' + secondLabel : ''); - }, getBlockNeededLabel: function(blockInput) { // The input type name, or 'any' if any official input type qualifies. var inputTypeLabel = ( @@ -209,5 +190,8 @@ blocklyApp.WorkspaceBlockComponent = ng.core.Component({ blockInput.type == Blockly.NEXT_STATEMENT ? Blockly.Msg.BLOCK : Blockly.Msg.VALUE); return inputTypeLabel + ' ' + blockTypeLabel + ' needed:'; + }, + generateAriaLabelledByAttr: function(mainLabel, secondLabel) { + return mainLabel + (secondLabel ? ' ' + secondLabel : ''); } }); diff --git a/accessible/workspace.component.js b/accessible/workspace.component.js index 39d395d0e..b6150a956 100644 --- a/accessible/workspace.component.js +++ b/accessible/workspace.component.js @@ -32,6 +32,7 @@ blocklyApp.WorkspaceComponent = ng.core.Component({