Refactor how activeDescendant is set. Introduce helper functions to ensure that calls like pasteAbove() preserve the focus.

This commit is contained in:
Sean Lip
2016-06-17 17:42:51 -07:00
parent 41f6f50b77
commit 3ca593273a
5 changed files with 106 additions and 74 deletions

View File

@@ -51,7 +51,7 @@ blocklyApp.WorkspaceTreeComponent = ng.core
<li [id]="idMap['pasteBelow']" role="treeitem"
[attr.aria-labelledBy]="generateAriaLabelledByAttr(idMap['pasteBelowButton'], 'blockly-button', !hasNextConnection(block) || !isCompatibleWithClipboard(block.nextConnection))"
[attr.aria-level]="level+2" aria-selected=false>
<button [id]="idMap['pasteBelowButton']" (click)="clipboardService.pasteFromClipboard(block.nextConnection)"
<button [id]="idMap['pasteBelowButton']" (click)="pasteBelow(block)"
[disabled]="!hasNextConnection(block) || !isCompatibleWithClipboard(block.nextConnection)">
{{'PASTE_BELOW'|translate}}
</button>
@@ -59,7 +59,7 @@ blocklyApp.WorkspaceTreeComponent = ng.core
<li [id]="idMap['pasteAbove']" role="treeitem"
[attr.aria-labelledBy]="generateAriaLabelledByAttr(idMap['pasteAboveButton'], 'blockly-button', !hasPreviousConnection(block) || !isCompatibleWithClipboard(block.previousConnection))"
[attr.aria-level]="level+2" aria-selected=false>
<button [id]="idMap['pasteAboveButton']" (click)="clipboardService.pasteFromClipboard(block.previousConnection)"
<button [id]="idMap['pasteAboveButton']" (click)="pasteAbove(block)"
[disabled]="!hasPreviousConnection(block) || !isCompatibleWithClipboard(block.previousConnection)">
{{'PASTE_ABOVE'|translate}}
</button>
@@ -94,7 +94,8 @@ blocklyApp.WorkspaceTreeComponent = ng.core
<div *ngFor="#inputBlock of block.inputList; #i = index">
<blockly-field *ngFor="#field of inputBlock.fieldRow" [field]="field"></blockly-field>
<blockly-workspace-tree *ngIf="inputBlock.connection && inputBlock.connection.targetBlock()"
[block]="inputBlock.connection.targetBlock()" [level]="level">
[block]="inputBlock.connection.targetBlock()" [level]="level"
[tree]="tree">
</blockly-workspace-tree>
<li #inputList [attr.aria-level]="level + 1" [id]="idMap['inputList' + i]"
[attr.aria-labelledBy]="generateAriaLabelledByAttr('blockly-menu', idMap['inputMenuLabel' + i])"
@@ -123,14 +124,13 @@ blocklyApp.WorkspaceTreeComponent = ng.core
<blockly-workspace-tree *ngIf= "block.nextConnection && block.nextConnection.targetBlock()"
[block]="block.nextConnection.targetBlock()"
[level]="level">
[level]="level" [tree]="tree">
</blockly-workspace-tree>
`,
directives: [blocklyApp.FieldComponent, ng.core.forwardRef(function() {
return blocklyApp.WorkspaceTreeComponent;
})],
// The 'tree' input is only passed down at the top level.
inputs: ['block', 'level', 'tree'],
inputs: ['block', 'level', 'tree', 'isTopLevel'],
pipes: [blocklyApp.TranslatePipe]
})
.Class({
@@ -142,13 +142,14 @@ blocklyApp.WorkspaceTreeComponent = ng.core
this.treeService = _treeService;
this.utilsService = _utilsService;
}],
ngOnInit: function() {
getElementsNeedingIds_: function() {
var elementsNeedingIds = ['blockSummary', 'listItem', 'label',
'cutListItem', 'cutButton', 'copyListItem', 'copyButton',
'pasteBelow', 'pasteBelowButton', 'pasteAbove', 'pasteAboveButton',
'markBelow', 'markBelowButton', 'markAbove', 'markAboveButton',
'sendToSelectedListItem', 'sendToSelectedButton', 'delete',
'deleteButton'];
for (var i = 0; i < this.block.inputList.length; i++) {
var inputBlock = this.block.inputList[i];
if (inputBlock.connection && !inputBlock.connection.targetBlock()) {
@@ -157,21 +158,39 @@ blocklyApp.WorkspaceTreeComponent = ng.core
'markSpotButton' + i, 'paste' + i, 'pasteButton' + i]);
}
}
this.idMap = this.utilsService.generateIds(elementsNeedingIds);
return elementsNeedingIds;
},
ngOnInit: function() {
var elementsNeedingIds = this.getElementsNeedingIds_();
this.idMap = {}
this.idMap['parentList'] = this.utilsService.generateUniqueId();
for (var i = 0; i < elementsNeedingIds.length; i++) {
this.idMap[elementsNeedingIds[i]] =
this.block.id + elementsNeedingIds[i];
}
},
ngAfterViewInit: function() {
// If this is a top-level tree in the workspace, set its active
// If this is a top-level tree in the workspace, set its id and active
// descendant.
if (this.tree &&
(!this.tree.id ||
this.treeService.isTopLevelWorkspaceTree(this.tree.id))) {
if (this.tree && this.isTopLevel && !this.tree.id) {
this.tree.id = this.utilsService.generateUniqueId();
}
if (this.tree && this.isTopLevel &&
!this.treeService.getActiveDescId(this.tree.id)) {
this.treeService.setActiveDesc(
document.getElementById(this.idMap['parentList']),
this.tree);
}
},
hasPreviousConnection: function(block) {
return Boolean(block.previousConnection);
},
hasNextConnection: function(block) {
return Boolean(block.nextConnection);
},
isCompatibleWithClipboard: function(connection) {
return this.clipboardService.isClipboardCompatibleWithConnection(
connection);
@@ -181,6 +200,18 @@ blocklyApp.WorkspaceTreeComponent = ng.core
return topBlock.id == block.id;
});
},
pasteAbove: function(block) {
var that = this;
this.treeService.runWhilePreservingFocus(function() {
that.clipboardService.pasteFromClipboard(block.previousConnection);
}, this.tree.id);
},
pasteBelow: function(block) {
var that = this;
this.treeService.runWhilePreservingFocus(function() {
that.clipboardService.pasteFromClipboard(block.nextConnection);
}, this.tree.id);
},
cutToClipboard: function(block) {
if (this.isTopLevelBlock(block)) {
nextNodeToFocusOn = this.treeService.getNodeToFocusOnWhenTreeIsDeleted(
@@ -192,7 +223,7 @@ blocklyApp.WorkspaceTreeComponent = ng.core
this.clipboardService.cut(block);
}
},
deleteBlock: function(block, cutToClipboard) {
deleteBlock: function(block) {
if (this.isTopLevelBlock(block)) {
nextNodeToFocusOn = this.treeService.getNodeToFocusOnWhenTreeIsDeleted(
this.tree.id);
@@ -207,12 +238,6 @@ blocklyApp.WorkspaceTreeComponent = ng.core
return this.utilsService.generateAriaLabelledByAttr(
mainLabel, secondLabel, isDisabled);
},
hasPreviousConnection: function(block) {
return Boolean(block.previousConnection);
},
hasNextConnection: function(block) {
return Boolean(block.nextConnection);
},
sendToMarkedSpot: function(block) {
this.clipboardService.pasteToMarkedConnection(block, false);