diff --git a/block-lexical-variables/README.md b/block-lexical-variables/README.md index cc85493..135fdb2 100644 --- a/block-lexical-variables/README.md +++ b/block-lexical-variables/README.md @@ -83,13 +83,17 @@ in scope for that getter according to which blocks it is within. ![A picture of a setter block with a dropdown](readme-media/set-with-dropdown.png "Setter with dropdown") ![A picture of a setter block within another block](readme-media/set-within-scope.png "Setter with dropdown") -###Getter +### Getter **Block type: 'lexical_variable_get'** - Exactly analogous to the setter block. ![A picture of a getter block](readme-media/get.png "Getter") ![A picture of a getter block with a dropdown](readme-media/get-with-dropdown.png "Getter with dropdown") ![A picture of a getter block within another block](readme-media/get-within-scope.png "Getter with dropdown") +### Disabling invalid getter/setter blocks + +By default, getter and setter blocks remain enabled even if their selected variable is out of scope or doesn’t exist. You can change this behavior so that invalid blocks are automatically disabled by passing the `disableInvalidBlocks` option when initializing the plugin as demonstrated in the [Usage](#usage) section. + ## Loops ### For **Block type: 'controls_for'** - A block which enables a `for` loop @@ -161,6 +165,19 @@ const workspace = Blockly.inject(...); // Load lexical variable plugin LexicalVariablesPlugin.init(workspace); ``` + +You can also pass an options object to customize the plugin’s behavior: + +```js +LexicalVariablesPlugin.init(workspace, { + disableInvalidBlocks: true, +}); +```` + +**Available options:** +- `disableInvalidBlocks` *(boolean, default: false)* + Automatically disable variable getter/setter blocks when they reference a variable that is out of scope or doesn’t exist. + Note that unlike with standard Blockly, you should **not** use a custom toolbox category for your variables, as this would interfere with the way that variables are declared and used with this plugin. Just create an ordinary Variables category, if you want, and diff --git a/block-lexical-variables/src/core.js b/block-lexical-variables/src/core.js index 1a58dad..7c39377 100644 --- a/block-lexical-variables/src/core.js +++ b/block-lexical-variables/src/core.js @@ -30,8 +30,9 @@ export class LexicalVariablesPlugin { /** * @param workspace + * @param options */ - static init(workspace) { + static init(workspace, options) { // TODO(ewpatton): We need to make sure this is reentrant. const rendererName = workspace.getRenderer().getClassName(); const themeName = workspace.getTheme().getClassName(); @@ -55,6 +56,7 @@ export class LexicalVariablesPlugin { workspace.svgBubbleCanvas_); flydown.init(workspace); flydown.autoClose = true; // Flydown closes after selecting a block + workspace.disableInvalidBlocks = options?.disableInvalidBlocks || false; } static Flydown = Flydown; diff --git a/block-lexical-variables/src/warningHandler.js b/block-lexical-variables/src/warningHandler.js index df3effd..38c9add 100644 --- a/block-lexical-variables/src/warningHandler.js +++ b/block-lexical-variables/src/warningHandler.js @@ -115,6 +115,12 @@ export class ErrorCheckers { if (block.workspace.isDragging && block.workspace.isDragging()) { return false; // wait until the user is done dragging to check validity. } + + // Don't disable blocks that are being dragged from toolbox or aren't fully rendered + if (block.isInFlyout || !block.workspace || block.workspace.isFlyout || !block.rendered) { + return false; + } + for (let i=0; i {}) + chai.assert.equal(block.isEnabled(), enabled); + } + }) + + test('should be disabled if variable doesn\'t exits', function() { + const xml = Blockly.utils.xml.textToDom( + '' + + ' ' + + ' do_something' + + ' ' + + ' ' + + ' global name' + + ' ' + + ' ' + + ' ' + + '' + ); + + this.assertBlockEnabled(xml, false) + }) + + test('shouldn\'t be disabled if variable does exits', function() { + const xml = Blockly.utils.xml.textToDom( + '' + + ' ' + + ' name' + + ' ' + + ' ' + + ' do_something' + + ' ' + + ' ' + + ' global name' + + ' ' + + ' ' + + ' ' + + '' + ); + + this.assertBlockEnabled(xml, true) + }) + + test('should be disabled for lexical out of scope', function() { + const xml = Blockly.utils.xml.textToDom('' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' a' + + ' b' + + ' ' + + ' ' + + ' b' + + ' ' + + ' ' + + ' ' + + ' ' + + ' a' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ''); + this.assertBlockEnabled(xml, false) + this.assertBlockEnabled(xml, true, 'b') + }) + + test('should not be disabled if disableInvalidBlocks = false', function() { + this.workspace.disableInvalidBlocks = false; + const xml = Blockly.utils.xml.textToDom( + '' + + ' ' + + ' do_something' + + ' ' + + ' ' + + ' global name' + + ' ' + + ' ' + + ' ' + + '' + ); + + this.assertBlockEnabled(xml, true) + }) + }) +}) +