diff --git a/accessible/app.component.js b/accessible/app.component.js index b78b5977b..7023a25cf 100644 --- a/accessible/app.component.js +++ b/accessible/app.component.js @@ -29,6 +29,9 @@ blocklyApp.AppView = ng.core .Component({ selector: 'blockly-app', template: ` +
@@ -44,21 +47,29 @@ blocklyApp.AppView = ng.core - + + + + `, directives: [blocklyApp.ToolboxComponent, blocklyApp.WorkspaceComponent], pipes: [blocklyApp.TranslatePipe], - // The clipboard, tree and utils services are declared here, so that all - // components in the application use the same instance of the service. + // All 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.TreeService, - blocklyApp.UtilsService] + blocklyApp.ClipboardService, blocklyApp.NotificationsService, + blocklyApp.TreeService, blocklyApp.UtilsService] }) .Class({ - constructor: [function() {}] + constructor: [blocklyApp.NotificationsService, function(_notificationsService) { + this.notificationsService = _notificationsService; + }], + getStatusMessage: function() { + return this.notificationsService.getStatusMessage(); + } }); diff --git a/accessible/clipboard.service.js b/accessible/clipboard.service.js index 4ae568b26..84b0b4f52 100644 --- a/accessible/clipboard.service.js +++ b/accessible/clipboard.service.js @@ -24,12 +24,15 @@ blocklyApp.ClipboardService = ng.core .Class({ - constructor: [blocklyApp.UtilsService, function(_utilsService) { + constructor: [ + blocklyApp.NotificationsService, blocklyApp.UtilsService, + function(_notificationsService, _utilsService) { this.clipboardBlockXml_ = null; this.clipboardBlockPreviousConnection_ = null; this.clipboardBlockNextConnection_ = null; this.clipboardBlockOutputConnection_ = null; this.markedConnection_ = null; + this.notificationsService = _notificationsService; this.utilsService = _utilsService; }], areConnectionsCompatible_: function(blockConnection, connection) { @@ -93,23 +96,17 @@ blocklyApp.ClipboardService = ng.core }, markConnection: function(connection) { this.markedConnection_ = connection; - alert(Blockly.Msg.MARKED_SPOT_MSG); + this.notificationsService.setStatusMessage(Blockly.Msg.MARKED_SPOT_MSG); }, cut: function(block) { - this.copy(block, false); + this.copy(block); block.dispose(true); }, - copy: function(block, announce) { + copy: function(block) { this.clipboardBlockXml_ = Blockly.Xml.blockToDom(block); this.clipboardBlockPreviousConnection_ = block.previousConnection; this.clipboardBlockNextConnection_ = block.nextConnection; this.clipboardBlockOutputConnection_ = block.outputConnection; - - if (announce) { - alert( - Blockly.Msg.COPIED_BLOCK_MSG + - this.utilsService.getBlockDescription(block)); - } }, pasteFromClipboard: function(inputConnection) { var connection = inputConnection; @@ -133,9 +130,9 @@ blocklyApp.ClipboardService = ng.core default: connection.connect(reconstitutedBlock.outputConnection); } - alert( - Blockly.Msg.PASTED_BLOCK_FROM_CLIPBOARD_MSG + - this.utilsService.getBlockDescription(reconstitutedBlock)); + this.notificationsService.setStatusMessage( + this.utilsService.getBlockDescription(reconstitutedBlock) + ' ' + + Blockly.Msg.PASTED_BLOCK_FROM_CLIPBOARD_MSG); return reconstitutedBlock.id; }, pasteToMarkedConnection: function(block) { diff --git a/accessible/messages.js b/accessible/messages.js index 022de027b..5c52019a0 100644 --- a/accessible/messages.js +++ b/accessible/messages.js @@ -62,8 +62,11 @@ Blockly.Msg.FOR = 'for'; Blockly.Msg.STATEMENT = 'statement'; Blockly.Msg.VALUE = 'value'; Blockly.Msg.CUT_BLOCK_MSG = 'Cut block: '; -Blockly.Msg.COPIED_BLOCK_MSG = 'Copied block to clipboard: '; -Blockly.Msg.PASTED_BLOCK_FROM_CLIPBOARD_MSG = 'Pasted block from clipboard: '; -Blockly.Msg.PASTED_BLOCK_TO_MARKED_SPOT_MSG = 'Pasted block to marked spot: '; +Blockly.Msg.COPIED_BLOCK_MSG = 'copied'; +Blockly.Msg.PASTED_BLOCK_FROM_CLIPBOARD_MSG = 'pasted'; +Blockly.Msg.PASTED_BLOCK_TO_MARKED_SPOT_MSG = 'moved to marked spot'; Blockly.Msg.MARKED_SPOT_MSG = 'Marked spot'; Blockly.Msg.BLOCK_MOVED_TO_MARKED_SPOT_MSB = 'Block moved to marked spot: '; +Blockly.Msg.TOOLBOX_BLOCK = 'toolbox block'; +Blockly.Msg.WORKSPACE_BLOCK = 'workspace block'; +Blockly.Msg.SUBMENU_INDICATOR = 'move right to view submenu'; diff --git a/accessible/notifications.service.js b/accessible/notifications.service.js new file mode 100644 index 000000000..5bcf497f3 --- /dev/null +++ b/accessible/notifications.service.js @@ -0,0 +1,44 @@ +/** + * AccessibleBlockly + * + * Copyright 2016 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Angular2 Service that notifies the user about actions that + * they have taken, by updating an ARIA live region. + * @author sll@google.com (Sean Lip) + */ + +blocklyApp.NotificationsService = ng.core + .Class({ + constructor: [function() { + this.statusMessage_ = ''; + }], + getStatusMessage: function() { + return this.statusMessage_; + }, + setStatusMessage: function(newMessage) { + // Introduce a temporary status message, so that if, e.g., two "copy" + // operations are done in succession, both messages will be read. + this.statusMessage_ = ''; + + var that = this; + setTimeout(function() { + that.statusMessage_ = newMessage; + }); + } + }); diff --git a/accessible/toolbox-tree.component.js b/accessible/toolbox-tree.component.js index 948388c1b..0bd31ac8f 100644 --- a/accessible/toolbox-tree.component.js +++ b/accessible/toolbox-tree.component.js @@ -30,39 +30,31 @@ blocklyApp.ToolboxTreeComponent = ng.core template: `
    1. -
    2. - -
        -
      1. - -
      2. -
      3. - -
      4. -
      5. - -
      6. -
      +
    3. + +
    4. +
    5. + +
    6. +
    7. +
  • @@ -82,19 +74,20 @@ blocklyApp.ToolboxTreeComponent = ng.core }) .Class({ constructor: [ - blocklyApp.ClipboardService, blocklyApp.TreeService, blocklyApp.UtilsService, - function(_clipboardService, _treeService, _utilsService) { - // ClipboardService and UtilsService are app-wide singleton services. - // TreeService is from the parent ToolboxComponent. - this.infoBlocks = Object.create(null); + blocklyApp.ClipboardService, blocklyApp.NotificationsService, + blocklyApp.TreeService, blocklyApp.UtilsService, + function( + _clipboardService, _notificationsService, + _treeService, _utilsService) { this.clipboardService = _clipboardService; + this.notificationsService = _notificationsService; this.treeService = _treeService; this.utilsService = _utilsService; }], ngOnInit: function() { var elementsNeedingIds = ['blockSummaryLabel']; if (this.displayBlockMenu) { - elementsNeedingIds = elementsNeedingIds.concat(['listItem', 'label', + elementsNeedingIds = elementsNeedingIds.concat(['blockSummarylabel', 'workspaceCopy', 'workspaceCopyButton', 'blockCopy', 'blockCopyButton', 'sendToSelected', 'sendToSelectedButton']); } @@ -123,11 +116,15 @@ blocklyApp.ToolboxTreeComponent = ng.core var that = this; setTimeout(function() { that.treeService.focusOnBlock(newBlockId); - alert('Added block to workspace: ' + blockDescription); + that.notificationsService.setStatusMessage( + blockDescription + ' copied to workspace. ' + + 'Now on copied block in workspace.'); }); }, copyToClipboard: function() { - this.clipboardService.copy(this.block, true); + this.clipboardService.copy(this.block); + this.notificationsService.setStatusMessage( + this.getBlockDescription() + ' ' + Blockly.Msg.COPIED_BLOCK_MSG); }, copyToMarkedSpot: function() { var blockDescription = this.getBlockDescription(); @@ -154,7 +151,9 @@ blocklyApp.ToolboxTreeComponent = ng.core that.treeService.initActiveDesc(oldDestinationTreeId); } - alert('Block copied to marked spot: ' + blockDescription); + that.notificationsService.setStatusMessage( + blockDescription + ' copied to marked spot. ' + + 'Now on copied block in workspace.'); }); } }); diff --git a/accessible/toolbox.component.js b/accessible/toolbox.component.js index 44b4449a9..a20d6c152 100644 --- a/accessible/toolbox.component.js +++ b/accessible/toolbox.component.js @@ -40,7 +40,7 @@ blocklyApp.ToolboxComponent = ng.core [ngClass]="{blocklyHasChildren: true, blocklyActiveDescendant: tree.getAttribute('aria-activedescendant') == idMap['Parent' + i]}" *ngFor="#category of toolboxCategories; #i=index" aria-level="1" - [attr.aria-label]="getCategoryAriaLabel(category.attributes.name.value)"> + [attr.aria-label]="getCategoryAriaLabel(category)">