Popup instead of browser dialog, for prompt() block, when using JS-Interpreter

341 views
Skip to first unread message

Swix

unread,
Apr 17, 2023, 7:19:18 AM4/17/23
to Blockly
I have the following code to ensure that the alert() and prompt() blocks are in the acorn-js interpreter's scope:

function initApi(interpreter, globalObject) {
  // Add an API function for the alert() block.
  var wrapper = function(text) {
return alert(arguments.length ? text : '');
  };
  interpreter.setProperty(globalObject, 'alert',
  interpreter.createNativeFunction(wrapper));

  // Add an API function for the prompt() block.
  wrapper = function(text) {
return prompt(text);
  };
  interpreter.setProperty(globalObject, 'prompt',
  interpreter.createNativeFunction(wrapper));

  // Add an API function for the printToOutput() block.
  wrapper = function(text) {
return printToOutput(text);
  };
  interpreter.setProperty(globalObject, 'printToOutput',
  interpreter.createNativeFunction(wrapper));
}

However, I would like the alert() and prompt() to be a popup and not the browser dialog box. 

I have imported the following js code to help me with this task:

However, this doesn't work for the prompt() block, but does for things like creating a new variable.

Can anyone point me in the direction of how I can get the prompt() block using the popup instead of the default browser based dialog?

Swix

unread,
Apr 17, 2023, 9:16:46 AM4/17/23
to Blockly
When I say prompt() block, i mean it doesn't work for the  "Prompt for text/number with message" block, as when this block is executed, the browser's normal prompt dialogue box is displayed when asking the user to enter a value. However, the custom dialogue popup shows for prompts such as entering a variable name when creating a new variable.

How can I ensure that when the "Prompt for text/number with message" is executed, it will show the custom popup and not the regular browser dialogue?

Thank you, I really hope someone can help me with this.  

Beka Westberg

unread,
Apr 17, 2023, 2:37:38 PM4/17/23
to Blockly
Hello!

So the dialogs associated with variables and such are called via `Blockly.dialog` The custom-dialogs-demo changes what the dialogs look like using `setAlert`, `setConfirm`, and `setPrompt`, so then `Blockly.dialog.prompt` (for example) shows the custom dialog instead of the default one.

However, the "prompt for text/number with message" block using the `window.prompt` function, rather than `Blockly.dialog.prompt`, so it's not hitting the custom dialogs.

I think your best option for fixing this is to change your `initApi` method to specify your `CustomDialog` prompts rather than the `window.prompt`.

Here's an example:
```
function initApi(interpreter, globalObject) {
  // Note that to use the `CustomDialog` as shown in the demo
          // we need to make this async  (i.e. take a callback)
  wrapper = function(text, callback) {
CustomDialog.show(text, {
                  showInput: true,
                  showOkay: true,
                  onOkay: function() {
                    callback(CustomDialog.inputField.value);
                  },
                  showCancel: true,
                  onCancel: function() {
                    callback(null);
                  },
                });
  };
  interpreter.setProperty(globalObject, 'prompt',
                  // Here we are calling `createAsyncFunction` instead of `createNativeFunction`
  interpreter.createAsyncFunction(wrapper));
}
```

I think that should work how you want it to! But the `initApi` function may not be entirely correct, since I've never used the `CustomDialog` or async functions with the interpreter before. But hopefully it gives you a place to start =)

I hope that helps! If you have any further questions please reply!
--Beka

Swix

unread,
Apr 18, 2023, 4:50:20 AM4/18/23
to Blockly
Thank you so much for your help.

So, in my initAPI function I replaced the code:

  // Add an API function for the prompt() block.
  wrapper = function(text) {
return prompt(text);
  };
  interpreter.setProperty(globalObject, "prompt",
  interpreter.createNativeFunction(wrapper));

with your code:

          // Note that to use the `CustomDialog` as shown in the demo
          // we need to make this async  (i.e. take a callback)
  wrapper = function(text, callback) {
CustomDialog.show(text, {
                  showInput: true,
                  showOkay: true,
                  onOkay: function() {
                    callback(CustomDialog.inputField.value);
                  },
                  showCancel: true,
                  onCancel: function() {
                    callback(null);
                  },
                });
  };
  interpreter.setProperty(globalObject, 'prompt',
                  // Here we are calling `createAsyncFunction` instead of `createNativeFunction`
  interpreter.createAsyncFunction(wrapper));

And the create variable prompt used the custom prompt, just like before, and the "prompt for text/number with message" block does now also call the custom prompt, however there are two issues I cannot fix:

1) The custom prompt that loads when the "prompt for text/number with message" block is executed, contains the labels (and inputted data) of the create new variable prompt.
2) When entering data into this prompt and clicking ok, the program stops running, with the error: caught TypeError: Cannot read properties of undefined (reading 'showInput'). Therefore it doesn't take the inputted data and store it in the variable attached to the "prompt for text/number with message" block, and doesn't continue to execute the rest of the blocks.

I really appreciated your help yesterday and wonder if you could spare a moment once more to point me in the correct direction for a solution as I'm a little stuck.

Thank you again

Beka Westberg

unread,
Apr 18, 2023, 1:53:35 PM4/18/23
to blo...@googlegroups.com
Ah yep, looks like I got the parameters to `CustomDialog.show` slightly incorrect. It's `(title, message, options`. So I think you want:

```
wrapper = function(text, callback) {
  CustomDialog.show('Prompt', text, {

    showInput: true,
    showOkay: true,
    onOkay: function() {
      callback(CustomDialog.inputField.value);
    },
    showCancel: true,
    onCancel: function() {
      callback(null);
    },
  });
 };
```

Hope that helps! Best of luck =)
--Beka

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/63b3524f-4bff-4ce6-8461-c383462fce63n%40googlegroups.com.

Swix

unread,
Apr 18, 2023, 2:53:22 PM4/18/23
to Blockly
Thank you so much again.
I've just tried to implement and it now shows the correct text label when requesting a user input! Thanks! However, when the "Prompt for text/number with message" block is executed, with a variable block attached, when an input is given, and the ok button pressed, the next block doesn't execute. 
So, once the custom dialogue is closed, it doesn't appear to allow the rest of the blocks to run. 😕

Swix

unread,
Apr 18, 2023, 3:35:07 PM4/18/23
to Blockly
Actually I think I've got an error elsewhere! and that your solution has worked for my prompt problem!

Thank you so much!!!

Beka Westberg

unread,
Apr 18, 2023, 3:40:27 PM4/18/23
to blo...@googlegroups.com
Happy to help =) Best of luck with your project! If you have any further questions always feel free to ask.

Best wishes,
--Beka

Reply all
Reply to author
Forward
0 new messages