diff --git a/accessible/app.component.js b/accessible/app.component.js index 2a8b75218..f81481fc4 100644 --- a/accessible/app.component.js +++ b/accessible/app.component.js @@ -55,11 +55,18 @@ blocklyApp.AppView = ng.core `, directives: [blocklyApp.ToolboxComponent, blocklyApp.WorkspaceComponent], pipes: [blocklyApp.TranslatePipe], - // The clipboard and utils services are declared here, so that all + // The clipboard, tree and utils services are declared here, so that all // components in the application use the same instance of the service. // https://www.sitepoint.com/angular-2-components-providers-classes-factories-values/ - providers: [blocklyApp.ClipboardService, blocklyApp.UtilsService] + providers: [ + blocklyApp.ClipboardService, blocklyApp.TreeService, + blocklyApp.UtilsService] }) .Class({ - constructor: function() {} + constructor: [blocklyApp.TreeService, function(_treeService) { + this.treeService = _treeService; + }], + ngAfterViewInit: function() { + this.treeService.initTreeRegistry(); + } }); diff --git a/accessible/toolbox.component.js b/accessible/toolbox.component.js index f6e8009d1..5240812f4 100644 --- a/accessible/toolbox.component.js +++ b/accessible/toolbox.component.js @@ -66,8 +66,7 @@ blocklyApp.ToolboxComponent = ng.core `, - directives: [blocklyApp.ToolboxTreeComponent], - providers: [blocklyApp.TreeService], + directives: [blocklyApp.ToolboxTreeComponent] }) .Class({ constructor: [ diff --git a/accessible/tree.service.js b/accessible/tree.service.js index 27f5aebfe..3e54e054f 100644 --- a/accessible/tree.service.js +++ b/accessible/tree.service.js @@ -18,8 +18,8 @@ */ /** - * @fileoverview Angular2 Service that handles all tree keyboard navigation. - * A separate TreeService is constructed for each tree in the application. + * @fileoverview Angular2 Service that handles tree keyboard navigation. + * This is a singleton service for the entire application. * * @author madeeha@google.com (Madeeha Ghori) */ @@ -27,8 +27,8 @@ blocklyApp.TreeService = ng.core .Class({ constructor: function() { - blocklyApp.debug && console.log('making a new tree service'); - this.trees = document.getElementsByClassName('blocklyTree'); + // 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,6 +36,57 @@ 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(); + }, + isTreeInRegistry: function(treeId) { + return this.treeRegistry.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; + } + } + }, + goToNextTree: function(treeId) { + for (var i = 0; i < this.treeRegistry.length - 1; i++) { + if (this.treeRegistry[i].id == treeId) { + this.treeRegistry[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(); + return true; + } + } + return false; + }, // Make a given node the active descendant of a given tree. setActiveDesc: function(node, tree, keepFocus) { blocklyApp.debug && console.log('setting activeDesc for tree ' + tree.id); @@ -62,7 +113,8 @@ blocklyApp.TreeService = ng.core return document.getElementById(activeDescendantId); }, onWorkspaceToolbarKeypress: function(e, treeId) { - blocklyApp.debug && console.log(e.keyCode + 'inside TreeService onWorkspaceToolbarKeypress'); + blocklyApp.debug && console.log( + e.keyCode + 'inside TreeService onWorkspaceToolbarKeypress'); switch (e.keyCode) { case 9: // 16,9: shift, tab @@ -79,29 +131,6 @@ blocklyApp.TreeService = ng.core break; } }, - goToNextTree: function(treeId, e) { - for (var i = 0; i < this.trees.length; i++) { - if (this.trees[i].id == treeId) { - if (i + 1 < this.trees.length) { - this.trees[i + 1].focus(); - } - break; - } - } - }, - goToPreviousTree: function(treeId, e) { - if (treeId == this.trees[0].id) { - return; - } - for (var i = (this.trees.length - 1); i >= 0; i--) { - if (this.trees[i].id == treeId) { - if (i - 1 < this.trees.length) { - this.trees[i - 1].focus(); - } - break; - } - } - }, onKeypress: function(e, tree) { var treeId = tree.id; var node = this.getActiveDesc(treeId); diff --git a/accessible/workspace-tree.component.js b/accessible/workspace-tree.component.js index 25cccc9b1..a58b6e35e 100644 --- a/accessible/workspace-tree.component.js +++ b/accessible/workspace-tree.component.js @@ -41,7 +41,7 @@ blocklyApp.WorkspaceTreeComponent = ng.core