mirror of
https://github.com/google/blockly.git
synced 2026-01-08 09:30:06 +01:00
Fix tree focus issues.
This commit is contained in:
@@ -63,10 +63,5 @@ blocklyApp.AppView = ng.core
|
||||
blocklyApp.UtilsService]
|
||||
})
|
||||
.Class({
|
||||
constructor: [blocklyApp.TreeService, function(_treeService) {
|
||||
this.treeService = _treeService;
|
||||
}],
|
||||
ngAfterViewInit: function() {
|
||||
this.treeService.initTreeRegistry();
|
||||
}
|
||||
constructor: [function() {}]
|
||||
});
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
blocklyApp.TreeService = ng.core
|
||||
.Class({
|
||||
constructor: function() {
|
||||
// A list of all trees in the application.
|
||||
this.treeRegistry = [];
|
||||
// Keeping track of the last key pressed. If the user presses
|
||||
// enter (to edit a text input or press a button), the keyboard
|
||||
// focus shifts to that element. In the next keystroke, if the user
|
||||
@@ -36,52 +34,66 @@ blocklyApp.TreeService = ng.core
|
||||
// to shift focus back to the tree as a whole.
|
||||
this.previousKey_ = null;
|
||||
},
|
||||
initTreeRegistry: function() {
|
||||
this.treeRegistry = [];
|
||||
this.treeRegistry.push(document.getElementById('blockly-toolbox-tree'));
|
||||
// TODO(sll): Extend this to handle injected toolbar buttons.
|
||||
this.treeRegistry.push(document.getElementById('clear-workspace'));
|
||||
|
||||
// Focus on the toolbox tree.
|
||||
this.treeRegistry[0].focus();
|
||||
getToolboxTreeNode_: function() {
|
||||
return document.getElementById('blockly-toolbox-tree');
|
||||
},
|
||||
isTreeInRegistry: function(treeId) {
|
||||
return this.treeRegistry.some(function(tree) {
|
||||
getWorkspaceTreeNodes_: function() {
|
||||
// Returns a list of all the top-level workspace tree nodes on the page.
|
||||
return Array.from(document.querySelectorAll('ol.blocklyWorkspaceTree'));
|
||||
},
|
||||
getAllTreeNodes_: function() {
|
||||
// Returns a list of all top-level tree nodes on the page.
|
||||
var trees = [];
|
||||
|
||||
trees.push(document.getElementById('blockly-toolbox-tree'));
|
||||
// TODO(sll): Extend this to handle injected toolbar buttons.
|
||||
if (blocklyApp.workspace.topBlocks_.length > 0) {
|
||||
trees.push(document.getElementById('clear-workspace'));
|
||||
}
|
||||
|
||||
trees = trees.concat(this.getWorkspaceTreeNodes_());
|
||||
return trees;
|
||||
},
|
||||
focusOnToolbox: function() {
|
||||
this.getToolboxTreeNode_().focus();
|
||||
},
|
||||
isTopLevelWorkspaceTree: function(treeId) {
|
||||
return this.getWorkspaceTreeNodes_().some(function(tree) {
|
||||
return tree.id == treeId;
|
||||
});
|
||||
},
|
||||
addTreeToRegistry: function(tree) {
|
||||
this.treeRegistry.push(tree);
|
||||
},
|
||||
deleteTreeFromRegistry: function(treeId) {
|
||||
// Shift focus to the next tree (if it exists), otherwise shift focus
|
||||
// to the previous tree.
|
||||
var movedToNextTree = this.goToNextTree(treeId);
|
||||
if (!movedToNextTree) {
|
||||
this.goToPreviousTree(treeId);
|
||||
}
|
||||
|
||||
// Delete the tree from the tree registry.
|
||||
for (var i = 0; i < this.treeRegistry.length; i++) {
|
||||
if (this.treeRegistry[i].id == treeId) {
|
||||
this.treeRegistry.splice(i, 1);
|
||||
break;
|
||||
getNodeToFocusOnWhenTreeIsDeleted: function(deletedTreeId) {
|
||||
// This returns the node to focus on after the deletion happens.
|
||||
// We shift focus to the next tree (if it exists), otherwise we shift
|
||||
// focus to the previous tree.
|
||||
var workspaceTrees = this.getWorkspaceTreeNodes_();
|
||||
for (var i = 0; i < workspaceTrees.length; i++) {
|
||||
if (workspaceTrees[i].id == deletedTreeId) {
|
||||
if (i + 1 < workspaceTrees.length) {
|
||||
return workspaceTrees[i + 1];
|
||||
} else if (i > 0) {
|
||||
return workspaceTrees[i - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.getToolboxTreeNode_();
|
||||
},
|
||||
goToNextTree: function(treeId) {
|
||||
for (var i = 0; i < this.treeRegistry.length - 1; i++) {
|
||||
if (this.treeRegistry[i].id == treeId) {
|
||||
this.treeRegistry[i + 1].focus();
|
||||
var trees = this.getAllTreeNodes_();
|
||||
for (var i = 0; i < trees.length - 1; i++) {
|
||||
if (trees[i].id == treeId) {
|
||||
trees[i + 1].focus();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
goToPreviousTree: function(treeId) {
|
||||
for (var i = this.treeRegistry.length - 1; i > 0; i--) {
|
||||
if (this.treeRegistry[i].id == treeId) {
|
||||
this.treeRegistry[i - 1].focus();
|
||||
var trees = this.getAllTreeNodes_();
|
||||
for (var i = trees.length - 1; i > 0; i--) {
|
||||
if (trees[i].id == treeId) {
|
||||
trees[i - 1].focus();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,12 +161,12 @@ blocklyApp.WorkspaceTreeComponent = ng.core
|
||||
this.idMap['parentList'] = this.utilsService.generateUniqueId();
|
||||
},
|
||||
ngAfterViewInit: function() {
|
||||
// If this is a top-level tree in the workspace, add it to the tree
|
||||
// registry and set its active descendant.
|
||||
// If this is a top-level tree in the workspace, set its active
|
||||
// descendant.
|
||||
if (this.tree &&
|
||||
(!this.tree.id || !this.treeService.isTreeInRegistry(this.tree.id))) {
|
||||
(!this.tree.id ||
|
||||
!this.treeService.isTopLevelWorkspaceTree(this.tree.id))) {
|
||||
this.tree.id = this.utilsService.generateUniqueId();
|
||||
this.treeService.addTreeToRegistry(this.tree);
|
||||
this.treeService.setActiveDesc(
|
||||
document.getElementById(this.idMap['parentList']),
|
||||
this.tree);
|
||||
@@ -183,18 +183,25 @@ blocklyApp.WorkspaceTreeComponent = ng.core
|
||||
},
|
||||
cutToClipboard: function(block) {
|
||||
if (this.isTopLevelBlock(block)) {
|
||||
this.treeService.deleteTreeFromRegistry(this.tree.id);
|
||||
nextNodeToFocusOn = this.treeService.getNodeToFocusOnWhenTreeIsDeleted(
|
||||
this.tree.id);
|
||||
this.clipboardService.cut(block);
|
||||
nextNodeToFocusOn.focus();
|
||||
} else {
|
||||
// TODO(sll): Change the active descendant of the tree.
|
||||
this.clipboardService.cut(block);
|
||||
}
|
||||
|
||||
this.clipboardService.cut(block);
|
||||
},
|
||||
deleteBlock: function(block, cutToClipboard) {
|
||||
if (this.isTopLevelBlock(block)) {
|
||||
this.treeService.deleteTreeFromRegistry(this.tree.id);
|
||||
nextNodeToFocusOn = this.treeService.getNodeToFocusOnWhenTreeIsDeleted(
|
||||
this.tree.id);
|
||||
block.dispose(true);
|
||||
nextNodeToFocusOn.focus();
|
||||
} else {
|
||||
// TODO(sll): Change the active descendant of the tree.
|
||||
block.dispose(true);
|
||||
}
|
||||
|
||||
// TODO(sll): Change the active descendant of the tree.
|
||||
block.dispose(true);
|
||||
},
|
||||
generateAriaLabelledByAttr: function(mainLabel, secondLabel, isDisabled) {
|
||||
return this.utilsService.generateAriaLabelledByAttr(
|
||||
@@ -210,9 +217,14 @@ blocklyApp.WorkspaceTreeComponent = ng.core
|
||||
this.clipboardService.pasteToMarkedConnection(block, false);
|
||||
|
||||
if (this.isTopLevelBlock(block)) {
|
||||
this.treeService.deleteTreeFromRegistry(this.tree.id);
|
||||
nextNodeToFocusOn = this.treeService.getNodeToFocusOnWhenTreeIsDeleted(
|
||||
this.tree.id);
|
||||
block.dispose(true);
|
||||
nextNodeToFocusOn.focus();
|
||||
} else {
|
||||
// TODO(sll): Change the active descendant of the tree.
|
||||
block.dispose(true);
|
||||
}
|
||||
block.dispose(true);
|
||||
|
||||
alert('Block moved to marked spot: ' + block.toString());
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ blocklyApp.WorkspaceComponent = ng.core
|
||||
|
||||
<div *ngIf="workspace">
|
||||
<ol #tree *ngFor="#block of workspace.topBlocks_; #i = index"
|
||||
tabIndex="0" role="group" class="blocklyTree"
|
||||
tabIndex="0" role="group" class="blocklyTree blocklyWorkspaceTree"
|
||||
[attr.aria-labelledby]="workspaceTitle.id"
|
||||
(keydown)="onKeypress($event, tree)">
|
||||
<blockly-workspace-tree [level]=1 [block]="block" [tree]="tree">
|
||||
@@ -71,14 +71,14 @@ blocklyApp.WorkspaceComponent = ng.core
|
||||
}],
|
||||
clearWorkspace: function() {
|
||||
this.workspace.clear();
|
||||
this.treeService.initTreeRegistry();
|
||||
this.treeService.focusOnToolbox();
|
||||
},
|
||||
onWorkspaceToolbarKeypress: function(event) {
|
||||
onWorkspaceToolbarKeypress: function(e) {
|
||||
this.treeService.onWorkspaceToolbarKeypress(
|
||||
event, document.activeElement.id);
|
||||
e, document.activeElement.id);
|
||||
},
|
||||
onKeypress: function(event, tree){
|
||||
this.treeService.onKeypress(event, tree);
|
||||
onKeypress: function(e, tree) {
|
||||
this.treeService.onKeypress(e, tree);
|
||||
},
|
||||
isWorkspaceEmpty: function() {
|
||||
return !this.workspace.topBlocks_.length;
|
||||
|
||||
Reference in New Issue
Block a user