Multi-select drop downs and mutator alternatives

450 views
Skip to first unread message

Antoine Lever

unread,
Jun 4, 2019, 7:25:28 AM6/4/19
to Blockly
I am writing a call rule engine that produces JSON. One of the call rules allows the selection of one or more days of the week. I understand that drop downs don't allow multiple selection unfortunately, so I'm working on a mutator alternative. Ideally, the user would set the number of days they would like to select in the mutator cog and then that number of drop down lists would appear in the block. The resulting JSON needs to return "day": "1,2,3,4" where 1 is Monday etc.

This is what I have so far:

function addWeekdays(toolboxText) {
   toolboxText += '</category><category name="Week days">';

    Blockly.Blocks["num"] = {
       init: function() {
           this.jsonInit({
               name: "test",
               message0: "Days %1",
               args0: [
                   {
                       type: "field_dropdown",
                       name: "days",
                       options: [
                           ["Monday", "1"],
                           ["Tuesday", "2"],
                           ["Wednesday", "3"],
                           ["Thursday", "4"],
                           ["Friday", "5"],
                           ["Saturday", "6"],
                           ["Sunday", "7"],
                       ],
                   },
               ],
           });
           this.setNextStatement = true;
           this.setPreviousStatement = true;
       },
   };

    Blockly.Blocks["List"] = {
       init: function() {
           this.jsonInit({
               name: "other",
               message0: "Here goes %1",
               args0: [{ type: "num", name: "test" }],
           });
           this.itemCount_ = 1;
           this.setMutator(new Blockly.Mutator(["num"]));
       },
       mutationToDom: function() {
           var a = document.createElement("mutation");
           var c = this.getFieldValue("count");
           a.setAttribute("count", c);
           console.log("c=", c);
           return a;
       },
       domToMutation: function(a) {
           // this.itemCount_ = parseInt(a.getAttribute("items"));
           console.log("a=", parseInt(a.getAttribute("count")));
       },
       decompose: function(workspace) {
           var topBlock = Blockly.Block.obtain(workspace, "num");
           topBlock.initSvg();
           console.log(this.getFieldValue("count"));
           return topBlock;
       },
   };

    return (toolboxText += `<block type="List"></block>`);
}


Beka Westberg

unread,
Jun 4, 2019, 10:37:21 AM6/4/19
to Blockly
Hello,

This sounds like a cool project! Did you have a specific question about it or a part you're stuck on? Otherwise if you're good I'd love to see a pic/gif of the block in action!

--Beka

Antoine Lever

unread,
Jun 4, 2019, 11:57:01 AM6/4/19
to blo...@googlegroups.com
Hello Beka,

Thanks for getting back to me and sorry that I wasn't clear enough. I don't know how to write the mutation code so that the user can input a single number e.g. 5 and then mutate a block to include 5 copies of a drop down list. Do you know where I can find a similar example or where I should start looking?

Thank you.

--
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/e6a1642f-a683-4e0d-a341-9b29c909dbfc%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Beka Westberg

unread,
Jun 4, 2019, 12:33:18 PM6/4/19
to Blockly
Ah ok that makes sense!

I would look at the lists_create_with block. It works by counting the number of 'item' blocks the mutator contains, but it could easily be changed to simply use a number field. Note that you won't need the saveConnections function, since you are handling dropdowns and not inputs.

Here's a gif of the block in action.

I think it's also worth mentioning that you don't necessarily need the mutator bubble to use a mutator. You could have a block that looks like this: 

MultiDates_Block.jpg

And have the updateShape method be triggered in the same manner the math_number_property block uses. But I think both methods for adding/removing days would work great!

I hope that gives you a good starting point, if you have any further questions please reply!
Beka
To unsubscribe from this group and stop receiving emails from it, send an email to blo...@googlegroups.com.
Message has been deleted

Antoine Lever

unread,
Jun 7, 2019, 3:44:55 PM6/7/19
to blo...@googlegroups.com
Hello Beka,

That is really helpful, thank you. I've managed to get something to work. 

Using Javascript I can define my dropdown so that the included function is called whenever a new selection is made:

Blockly.Blocks["test1"] = {
init: function() {
let count = new Blockly.FieldDropdown(
[
["1", "1"],
["2", "2"],
["3", "3"],
["4", "4"],
["5", "5"],
["6", "6"],
["7", "7"],
],
function(a) {
this.sourceBlock_.updateShape_(a);
},
);
this.appendDummyInput("Antoine")
.appendField("Count:")
.appendField(count, "count")
.appendField(new Blockly.FieldDropdown(day))
.appendField("The rest of the block");
},

Is it possible to do the same using JSON instead?

thank you!!

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/7cbe9298-5548-488c-bcb1-c539a116bb83%40googlegroups.com.

Beka Westberg

unread,
Jun 7, 2019, 4:11:55 PM6/7/19
to Blockly
As with the onClick parameter of a image field, validators (which is what your dropdown function is) can only be defined using JavaScript or a JSON extension because JSON cannot store functions :/

It would be pretty easy to create a JSON extension for this using the setValidator() function though!

I hope that helps!
Beka

Coda Highland

unread,
Jun 7, 2019, 4:23:22 PM6/7/19
to blo...@googlegroups.com
Check out the documentation on extensions and mutators:


This should be what you're looking for!

/s/ Adam

On Fri, Jun 7, 2019 at 2:44 PM Antoine Lever <ale...@omniis.com> wrote:
Thank you Beka, that works really well. I've managed to get it working using blocks defined in Javascript like this:

Blockly.Blocks["test2"] = {
init: function() {
this.appendDummyInput("Antoine")
.appendField("If it is ")
.appendField(new Blockly.FieldDropdown(day))
.appendField(
new Blockly.FieldImage(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAgVBMVEX///8BAQEAAADb29vPz8/e3t7n5+fZ2dn7+/t3d3f8/Pybm5v19fVKSkqnp6eqqqrJycm6urqKioqDg4NSUlK2trZfX18mJiZzc3Pl5eVpaWkXFxdXV1fT09OhoaE4ODiTk5MdHR1CQkJLS0sODg4zMzMkJCQbGxs9PT3CwsItLS1uPk0RAAAHCklEQVR4nO2deX+iPBDHS6wWFQRExdZjvWqr7/8FPuC11hUIc+Tok98/u3xaQr4NZJKZZPLy4uTk5OTk5OTk5OTk5OTk5OTk5OTk5OQEk59Ldx3o1QuCIFmu0m63+zEfjebT/D/pcJl0guA30MbL4WQtSjQLh/1DoLuKcLWjNLugeE915UwH77rr2lxBMq1i+5dzmnR017mB3pONHNxPzD+Dlu6aS6mTjGZN+W5NGUamt2Sv3c1ueFdI4UleFnfup4uebopy+Yc5pPUeW3JrbPcafSPxbpDHpYmM0YyE7wrZN20wMKbDuzHqZrpXnNHyXRgPurmuak+IG/CGuH3TzVbIj1j4LoxD/V3OIh++yFu8ppf5QCfWy+ev2Brwiii6OgE7IS/fmTHUN1yN+PnOjJEmwFQNYIE40WH/g09VgKcOp60csMXcxTwiirFiwPGJj948lF6q/hj7KhvwAilWCieOQ/WABWJXGaKyTvSR8UMR4lQTYI44V2I19AHmL+pWQSvqekUviBN2QC2dzD3iBzPgxUwoMIAll9zejbHeFjxBso5u2voBC0Q+/02wMwCwQGSbMH4aAZgjfjKZRa124l5cNkPRjF5GQgwYADsFoAbz8PRSiFdyQD80pgULiT054coowLwVp8SAC3M+wrOEWJAC+hsEYNlaE1w0VexICTH9aD7Mareeqp2gEFNCQNRoreJ94iq3uT4wH2FFz95Cfd2Edj++fTCw+FElIbxkQgfjEbm8gqkNPXEkii4iJ4WMhFSzYaQp5CP0xIykESOkrWck9MSKgnBmMqEgaERsEzITrtCA/jfWucZmLc6uNzQhamAlQ4gtHTsX7s3xdeAlXCMJCfyHvIQednTaJagCMyFuKtzJzCfEGQx8P8NO6OGGbiOKGnAThgj/8PsOaKZ+/MNpD0/lI9baULyk7G3oiSGcEON/+lsBdkL4axrQVICdEB6LInlJ+Qk9eMx0SvN8fsI5lJDo+fyEe+BuqXeaYBO3tah8QrXQc18pQpJHAIc1qT2EWxghwaj79HgFhF8wi0j1eAWEsA8xJooYKiFMIIRLewg9sYQQDm0i3AAAe5Pi6RJ2qSrEe1Yp4Vv9vaL0ufeXIKdisJb7+4rotUZxqZshiOvulRwawwgl3yC+RWaFOrKEgJ2KgeQnAilbXtKEgPWKiV2EgHCwrLEwghDk3JddBGUIIWDsnd7HnCqshRLC2mpA1mXI+vMNacOwedmWEWbNy7aMEBBks4zQa1y0LxsaNYSw+bDN3/56Qtmwk7WE58mTPfYQMLmwrKcBrBi2jPD3W4vfb/EBozZZj7chhICRt2WzJ0Cke2mXtQDMgA82tSHIi2GZJwrg1rfMmwhYvxdIrn4Wh3adyhee1d4ayxICci3IbjiUcMxXxS0k3fq1lWgOKB+ZYSaUqwMkMmNXdA208OsgGXuqu1SxFgMWIaVZ86UoBgzLPYjdSnJ7PD/hGpa2xqLVJt8gwJeBPYSgMH4xnqB5PP+6NuBnaNHKvQya53wqLLEWIyCgPStowfsRZCfYNc83eBX0yx87CBEbLgZ27EZAJFeg2dPCvWdGYE44oUhKY/SuIJLMSeyEKwTgS2f/YNu85pfM9lAI3LEmBFsuzN5hSZFbiJsQmWSwJxvs1kWI364u6/rWRojO4ILKEMVPSJBxAO9y480aQZAs6pzw0lBrgTUVZ/XRf2e+/DQ0h1/4Bmfg2dEcuodMMc+ZRYkqZZtnKmFGdc7OAZdWjS1fG+FxCaiBDR/hhi7Z7puZWQUpc0JfM7HD7GHSKVGMsYe0xyQFGJ8UPgD6tNQd7XGXkvH0xoiIMkEhwwoRJBsiFcMJAoZlSqZIRfcgspg7heDRpioZlbGcMsPuX90d5EgRMMJcglN9VMsnCWMQSGRc53gbcbxF5TAQLQOOKPGYDykxobfBJL6SENalgefjPiyop3lsI+Axe2nED50vqgLAU0ZTxuNx6yZiCgBPu9o0tWIOqObwPH+iB1FRC56k51tUCKjplE7uM+V+SrnpF8yG/l8dMC4ICKD6c51bn+omU0JkfIPtcqnrUoWYc02XajRQ86Zyzehl9LrnRxQ8PhlpsR8smxsJeq9aIy12nIxC7KgdvwClbF9jXnCX1nUP1GLCwpgXuuE7cbShoqO4W7BBtJVJZJGSM6rlFPRnpO2YF7ZLNfcwjwpWhIjFB6jJxleJjDEvJjWig3miQYaGLD5A9YPsBlpMMXHP4t4pp7+XREE/hEEWd4UrU1/PH/Lbq/A+hC1hHk6/HqbvBpmHGvmt8WgvF6k//1Y26rfswbuo89rfflUsSbj9aP29jK14OZ/Jf02Wm6rFJpthEqvxgfLq7RAN+pPw+HVuuHUWToaDKFn8BjYnJycnJycnJycnJycnJycnJ6f/h/4DBwyDo6r6rjQAAAAASUVORK5CYII=",
15,
15,
"+",
function onClick_Image() {
this.sourceBlock_.addDay_();
},
),
)

I simply inserted an image which, when clicked runs .addDay() which adds another dropdown list field into my block.

My question now is, will this work if I define my block in JSON? This doesn't work:

consts.days = block["args0"][options]["options"];
block["message0"] += `%${counter++}`;
block["args0"].push({
name: "image",
type: "field_image",
src: consts.plus,
width: 15,
height: 15,
alt: "+",
onClick: function() {
console.log("It works");
},
});

No matter what I name the onClick function, it won't run. I've tried everything I can think of from here: https://developers.google.com/blockly/reference/js/Blockly.FieldImage

Please help! Thank you.
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/65facf09-7231-48f7-8115-f97710b65050%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages