Action list (#2959)

* Support keyboard navigation in read only mode
This commit is contained in:
alschmiedt
2019-09-03 16:11:06 -07:00
committed by GitHub
parent 5dc45be726
commit e620b1fde6
4 changed files with 104 additions and 12 deletions

View File

@@ -205,14 +205,23 @@ Blockly.svgResize = function(workspace) {
// are multiple workspaces and non-main workspaces are able to accept input.
Blockly.onKeyDown_ = function(e) {
var mainWorkspace = Blockly.mainWorkspace;
if (mainWorkspace.options.readOnly || Blockly.utils.isTargetInput(e) ||
if (Blockly.utils.isTargetInput(e) ||
(mainWorkspace.rendered && !mainWorkspace.isVisible())) {
// No key actions on readonly workspaces.
// When focused on an HTML text input widget, don't trap any keys.
// Ignore keypresses on rendered workspaces that have been explicitly
// hidden.
return;
}
if (mainWorkspace.options.readOnly) {
// When in read only mode handle key actions for keyboard navigation.
if (Blockly.keyboardAccessibilityMode) {
Blockly.navigation.onKeyPress(e);
}
return;
}
var deleteBlock = false;
if (e.keyCode == Blockly.utils.KeyCodes.ESC) {
// Pressing esc closes the context menu.

View File

@@ -288,7 +288,7 @@ Blockly.ASTNode.prototype.findPreviousEditableField_ = function(location,
var previousField = null;
var startIdx = opt_last ? fieldRow.length - 1 : fieldIdx - 1;
for (var i = startIdx, field; field = fieldRow[i]; i--) {
if (field.isCurrentlyEditable()) {
if (field.EDITABLE) {
previousField = field;
return Blockly.ASTNode.createFieldNode(previousField);
}
@@ -312,7 +312,7 @@ Blockly.ASTNode.prototype.findNextForInput_ = function() {
for (var i = curIdx + 1, input; input = block.inputList[i]; i++) {
var fieldRow = input.fieldRow;
for (var j = 0, field; field = fieldRow[j]; j++) {
if (field.isCurrentlyEditable()) {
if (field.EDITABLE) {
return Blockly.ASTNode.createFieldNode(field);
}
}
@@ -340,7 +340,7 @@ Blockly.ASTNode.prototype.findNextForField_ = function() {
for (var i = curIdx, input; input = block.inputList[i]; i++) {
var fieldRow = input.fieldRow;
while (fieldIdx < fieldRow.length) {
if (fieldRow[fieldIdx].isCurrentlyEditable()) {
if (fieldRow[fieldIdx].EDITABLE) {
return Blockly.ASTNode.createFieldNode(fieldRow[fieldIdx]);
}
fieldIdx++;
@@ -371,7 +371,7 @@ Blockly.ASTNode.prototype.findPrevForInput_ = function() {
}
var fieldRow = input.fieldRow;
for (var j = fieldRow.length - 1, field; field = fieldRow[j]; j--) {
if (field.isCurrentlyEditable()) {
if (field.EDITABLE) {
return Blockly.ASTNode.createFieldNode(field);
}
}
@@ -397,7 +397,7 @@ Blockly.ASTNode.prototype.findPrevForField_ = function() {
}
var fieldRow = input.fieldRow;
while (fieldIdx > -1) {
if (fieldRow[fieldIdx].isCurrentlyEditable()) {
if (fieldRow[fieldIdx].EDITABLE) {
return Blockly.ASTNode.createFieldNode(fieldRow[fieldIdx]);
}
fieldIdx--;
@@ -501,7 +501,7 @@ Blockly.ASTNode.prototype.findFirstFieldOrInput_ = function(block) {
for (var i = 0, input; input = inputs[i]; i++) {
var fieldRow = input.fieldRow;
for (var j = 0, field; field = fieldRow[j]; j++) {
if (field.isCurrentlyEditable()) {
if (field.EDITABLE) {
return Blockly.ASTNode.createFieldNode(field);
}
}

View File

@@ -837,13 +837,18 @@ Blockly.navigation.onKeyPress = function(e) {
var key = Blockly.user.keyMap.serializeKeyEvent(e);
var action = Blockly.user.keyMap.getActionByKeyCode(key);
var curNode = Blockly.navigation.cursor_.getCurNode();
var readOnly = Blockly.getMainWorkspace().options.readOnly;
var actionHandled = false;
if (action) {
if (curNode && curNode.getType() === Blockly.ASTNode.types.FIELD) {
actionHandled = curNode.getLocation().onBlocklyAction(action);
}
if (!actionHandled) {
if (!readOnly) {
if (curNode && curNode.getType() === Blockly.ASTNode.types.FIELD) {
actionHandled = curNode.getLocation().onBlocklyAction(action);
}
if (!actionHandled) {
actionHandled = Blockly.navigation.onBlocklyAction(action);
}
} else if (Blockly.navigation.READONLY_ACTION_LIST.indexOf(action) > -1) {
actionHandled = Blockly.navigation.onBlocklyAction(action);
}
}
@@ -1085,3 +1090,14 @@ Blockly.navigation.ACTION_TOOLBOX = new Blockly.Action(
*/
Blockly.navigation.ACTION_EXIT = new Blockly.Action(
Blockly.navigation.actionNames.EXIT, 'Close the current modal, such as a toolbox or field editor.');
/**
* List of actions that can be performed in read only mode.
* @type {!Array<!Blockly.Action>}
*/
Blockly.navigation.READONLY_ACTION_LIST = [
Blockly.navigation.ACTION_PREVIOUS,
Blockly.navigation.ACTION_OUT,
Blockly.navigation.ACTION_IN,
Blockly.navigation.ACTION_NEXT
];

View File

@@ -370,6 +370,73 @@ suite('Navigation', function() {
field.onBlocklyAction.restore();
Blockly.navigation.onBlocklyAction.restore();
});
suite('Test key press in read only mode', function() {
setup(function() {
Blockly.defineBlocksWithJsonArray([{
"type": "field_block",
"message0": "%1 %2",
"args0": [
{
"type": "field_dropdown",
"name": "NAME",
"options": [
[
"a",
"optionA"
]
]
},
{
"type": "input_value",
"name": "NAME"
}
],
"previousStatement": null,
"nextStatement": null,
"colour": 230,
"tooltip": "",
"helpUrl": ""
}]);
this.workspace = new Blockly.Workspace({readOnly: true});
Blockly.navigation.setCursor(this.workspace.cursor);
Blockly.mainWorkspace = this.workspace;
this.fieldBlock1 = this.workspace.newBlock('field_block');
Blockly.keyboardAccessibilityMode = true;
this.mockEvent = {
getModifierState: function() {
return false;
}
};
});
teardown(function() {
delete Blockly.Blocks['field_block'];
Blockly.mainWorkspace = null;
this.workspace.dispose();
});
test('Perform valid action for read only', function() {
var astNode = Blockly.ASTNode.createBlockNode(this.fieldBlock1);
this.workspace.cursor.setLocation(astNode);
this.mockEvent.keyCode = Blockly.utils.KeyCodes.S;
chai.assert.isTrue(Blockly.navigation.onKeyPress(this.mockEvent));
});
test('Perform invalid action for read only', function() {
var astNode = Blockly.ASTNode.createBlockNode(this.fieldBlock1);
this.workspace.cursor.setLocation(astNode);
this.mockEvent.keyCode = Blockly.utils.KeyCodes.I;
chai.assert.isFalse(Blockly.navigation.onKeyPress(this.mockEvent));
});
test('Try to perform action on a field', function() {
var field = this.fieldBlock1.inputList[0].fieldRow[0];
var astNode = Blockly.ASTNode.createFieldNode(field);
this.workspace.cursor.setLocation(astNode);
this.mockEvent.keyCode = Blockly.utils.KeyCodes.ENTER;
chai.assert.isFalse(Blockly.navigation.onKeyPress(this.mockEvent));
});
});
});
suite('Insert Functions', function() {