From e8e8de93bbb48c387d9b6fa0ad224d614a3ff14b Mon Sep 17 00:00:00 2001 From: Sean Lip Date: Tue, 22 Nov 2016 17:58:37 -0800 Subject: [PATCH] Handle the finer points for setting focus correctly after deleting blocks from the workspace. --- accessible/block-options-modal.component.js | 9 +++- accessible/block-options-modal.service.js | 11 ++--- accessible/tree.service.js | 53 ++++++++++----------- accessible/workspace.component.js | 6 ++- 4 files changed, 42 insertions(+), 37 deletions(-) diff --git a/accessible/block-options-modal.component.js b/accessible/block-options-modal.component.js index 0aeb69969..f13bc466e 100644 --- a/accessible/block-options-modal.component.js +++ b/accessible/block-options-modal.component.js @@ -65,13 +65,16 @@ blocklyApp.BlockOptionsModalComponent = ng.core.Component({ this.modalIsVisible = false; this.actionButtonsInfo = []; this.activeActionButtonIndex = 0; + this.onCancelCallback = null; var that = this; this.blockOptionsModalService.registerPreShowHook( - function(newActionButtonsInfo) { + function(newActionButtonsInfo, onCancelCallback) { that.modalIsVisible = true; that.actionButtonsInfo = newActionButtonsInfo; that.activeActionButtonIndex = 0; + that.onCancelCallback = onCancelCallback; + that.keyboardInputService.setOverride({ // Tab key: no-op. '9': function(evt) { @@ -92,11 +95,15 @@ blocklyApp.BlockOptionsModalComponent = ng.core.Component({ if (that.activeActionButtonIndex < that.actionButtonsInfo.length) { that.actionButtonsInfo[that.activeActionButtonIndex].action(); + } else { + that.onCancelCallback(); } + that.hideModal(); }, // Escape key: closes the modal. '27': function() { + that.onCancelCallback(); that.hideModal(); }, // Up key: navigates to the previous item in the list. diff --git a/accessible/block-options-modal.service.js b/accessible/block-options-modal.service.js index 7411acb96..3df6a1aa8 100644 --- a/accessible/block-options-modal.service.js +++ b/accessible/block-options-modal.service.js @@ -32,19 +32,19 @@ blocklyApp.BlockOptionsModalService = ng.core.Class({ 'before it can be shown.'); }; this.modalIsShown = false; - this.onHideCallback = null; + this.onCancelCallback = null; }], registerPreShowHook: function(preShowHook) { this.preShowHook = function() { - preShowHook(this.actionButtonsInfo); + preShowHook(this.actionButtonsInfo, this.onCancelCallback); }; }, isModalShown: function() { return this.modalIsShown; }, - showModal: function(actionButtonsInfo, onHideCallback) { + showModal: function(actionButtonsInfo, onCancelCallback) { this.actionButtonsInfo = actionButtonsInfo; - this.onHideCallback = onHideCallback; + this.onCancelCallback = onCancelCallback; if (this.preShowHook) { this.preShowHook(); @@ -53,8 +53,5 @@ blocklyApp.BlockOptionsModalService = ng.core.Class({ }, hideModal: function() { this.modalIsShown = false; - if (this.onHideCallback) { - this.onHideCallback(); - } } }); diff --git a/accessible/tree.service.js b/accessible/tree.service.js index fee342d08..601e06dbf 100644 --- a/accessible/tree.service.js +++ b/accessible/tree.service.js @@ -42,34 +42,18 @@ blocklyApp.TreeService = ng.core.Class({ } ], // Returns a list of all top-level workspace tree nodes on the page. - getWorkspaceTreeNodes_: function() { - return Array.from(document.querySelectorAll('ol.blocklyWorkspaceTree')); + getWorkspaceFocusTargets_: function() { + return Array.from( + document.querySelectorAll('.blocklyWorkspaceFocusTarget')); }, getSidebarButtonNodes_: function() { return Array.from(document.querySelectorAll('button.blocklySidebarButton')); }, // Returns a list of all top-level tree nodes on the page. getAllTreeNodes_: function() { - return this.getWorkspaceTreeNodes_().concat( + return this.getWorkspaceFocusTargets_().concat( this.getSidebarButtonNodes_()); }, - isTopLevelWorkspaceTree: function(treeId) { - return this.getWorkspaceTreeNodes_().some(function(tree) { - return tree.id == treeId; - }); - }, - getNodeToFocusOnWhenTreeIsDeleted: function(deletedTreeId) { - // This returns the node to focus on after the deletion happens. - // We shift focus to the next tree (which may be a button in the sidebar). - var trees = this.getAllTreeNodes_(); - for (var i = 0; i < trees.length; i++) { - if (trees[i].id == deletedTreeId) { - if (i + 1 < trees.length) { - return trees[i + 1]; - } - } - } - }, focusOnCurrentTree_: function(treeId) { var trees = this.getAllTreeNodes_(); for (var i = 0; i < trees.length; i++) { @@ -224,12 +208,13 @@ blocklyApp.TreeService = ng.core.Class({ console.error('Could not handle deletion of block.' + blockRootNode); }, notifyUserAboutCurrentTree_: function(treeId) { - var workspaceTreeNodes = this.getWorkspaceTreeNodes_(); - for (var i = 0; i < workspaceTreeNodes.length; i++) { - if (workspaceTreeNodes[i].id == treeId) { + var workspaceFocusTargets = this.getWorkspaceFocusTargets_(); + for (var i = 0; i < workspaceFocusTargets.length; i++) { + if (workspaceFocusTargets[i].tagName == 'OL' && + workspaceFocusTargets[i].id == treeId) { this.notificationsService.setStatusMessage( 'Now in workspace group ' + (i + 1) + ' of ' + - workspaceTreeNodes.length); + workspaceFocusTargets.length); } } }, @@ -252,12 +237,26 @@ blocklyApp.TreeService = ng.core.Class({ // - Otherwise, it sets the correct new active desc for the current tree. var treeId = this.getTreeIdForBlock(block.id); if (this.isIsolatedTopLevelBlock_(block)) { - var nextNodeToFocusOn = this.getNodeToFocusOnWhenTreeIsDeleted(treeId); + // Find the node to focus on after the deletion happens. + var nextNodeToFocusOn = null; + var focusTargets = this.getWorkspaceFocusTargets_(); + for (var i = 0; i < focusTargets.length; i++) { + if (focusTargets[i].id == treeId) { + if (i + 1 < focusTargets.length) { + nextNodeToFocusOn = focusTargets[i + 1]; + } else if (i > 0) { + nextNodeToFocusOn = focusTargets[i - 1]; + } + break; + } + } this.clearActiveDesc(treeId); deleteBlockFunc(); // Invoke a digest cycle, so that the DOM settles. setTimeout(function() { + nextNodeToFocusOn = nextNodeToFocusOn || document.getElementById( + 'blocklyEmptyWorkspaceButton'); nextNodeToFocusOn.focus(); }); } else { @@ -313,6 +312,7 @@ blocklyApp.TreeService = ng.core.Class({ translationIdForText: 'MARK_SPOT_BEFORE', action: function() { that.clipboardService.markConnection(block.previousConnection); + that.focusOnBlock(block.id); }, isDisabled: function() { return !block.previousConnection; @@ -320,6 +320,7 @@ blocklyApp.TreeService = ng.core.Class({ }, { action: function() { that.clipboardService.markConnection(block.nextConnection); + that.focusOnBlock(block.id); }, translationIdForText: 'MARK_SPOT_AFTER', isDisabled: function() { @@ -391,8 +392,6 @@ blocklyApp.TreeService = ng.core.Class({ }]; this.blockOptionsModalService.showModal(actionButtonsInfo, function() { - // TODO(sll): If there are no blocks in the workspace, focus on the - // entire workspace instead. that.focusOnBlock(block.id); }); }, diff --git a/accessible/workspace.component.js b/accessible/workspace.component.js index 014a33824..5d658d200 100644 --- a/accessible/workspace.component.js +++ b/accessible/workspace.component.js @@ -32,7 +32,7 @@ blocklyApp.WorkspaceComponent = ng.core.Component({
    @@ -43,7 +43,9 @@ blocklyApp.WorkspaceComponent = ng.core.Component({

    There are no blocks in the workspace. -