Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make an instance of a block of Blockly with Javascript?

I have done the following block with Blockly in a customBlocks.js file:

Blockly.Blocks['move_right'] = {
  init: function() {
    this.appendValueInput("PIXELS")
        .setCheck("Number")
        .appendField("move to right");
    this.setInputsInline(true);
    this.setPreviousStatement(true, null);
    this.setNextStatement(true, null);
    this.setColour(290);
    this.setTooltip('');
    this.setHelpUrl('http://www.example.com/');
  }
};

Blockly.JavaScript['move_right'] = function(block) {
  var value_pixels = Blockly.JavaScript.valueToCode(block, 'PIXELS', Blockly.JavaScript.ORDER_ATOMIC);
  // TODO: Assemble JavaScript into code variable.
  var codeMoveRight = "$(\"#moveDiv\").animate({\n " + 
                        "left: \"+=" + value_pixels + "px\"\n" +
                      "},1000);\n";  
  return codeMoveRight;
};

that moves a div to the right depending of how much pixels you set on it. You will have to put a math_number block inside move_right block to put the amount of pixels you want to move it.

I have on my html file a workspace variable that injects the Blockly workspace:

var workspace = Blockly.inject('blocklyDiv',
              {toolbox: document.getElementById('toolbox')});

What I want to do

It is to retrieve from JavaScript this amount of pixels one time the block have been displayed on the workspace of Blockly, not before.

What I have tried

  • I directly tried to access to the workspace variable from the console of my broser (Google Chrome) and could get the "child blocks" but not the value of them. As follows:

    console.log(workspace.topBlocks_[0].childBlocks_);
    
  • I also tried to translate the workspace to dom and then to text:

    var xml = Blockly.Xml.workspaceToDom(workspace);
    var xml_text = Blockly.Xml.domToText(xml); 
    console.log(xml_text);
    

    and here I can see that the value of the "child Block", I mean, the math_number block, it is stored on the text but I do not know how can I get it.

Why I want to achieve that?

Because what I want it is to check if the user has moved 300 pixels to the right. If so, then I will show a message in which I will put "You get it!".

My question

Is there a posibility to make an instance of that Block that I have put on the workspace and then get access to its pixels value with that instance?

EDIT:

I also could get the left value as @Oriol said doing:

$('#moveDiv').css('left');

but I did not put it here because it is using a property of Jquery (It does not matter at all, because it is a good option too, but not as intended). My intention it is to get an instance of a Block after put it on the Blockly workspace to operate later with it at any time.

like image 501
Francisco Romero Avatar asked Apr 08 '16 12:04

Francisco Romero


People also ask

How do you add a custom block Blockly?

Assuming your blocks don't fit in the existing categories, create a new JavaScript file. This new JavaScript file needs to be included in the list of <script ...> tags in the editor's HTML file. Note: Most of a block can be defined using the Blockly Developer Tools, instead of manually creating the code below. };

What is Blockly in JavaScript?

Blockly is a client-side library for the programming language JavaScript for creating block-based visual programming languages (VPLs) and editors. A project of Google, it is free and open-source software released under the Apache License 2.0.

Is Blockly the same as JavaScript?

To start off, Blockly is used by Javascript. It is a client-side library and creates block-based programming languages for editors. Blockly is not necessarily a programming language by itself, but instead, a library for Javascript and other programming languages. It is mainly used to make writing code easier.

How do you inject Blockly?

You can inject a Blockly workspace with a call to Blockly. inject(location, options) . The first argument tells Blockly where to inject the workspace in the DOM. The second argument is a dictionary of name-value pairs that is used for configuration.


1 Answers

There is a method setWarningText to show this kind of warnings. You could modify yor generator as follows:

Blockly.JavaScript['move_right'] = function(block) {
    var value_pixels = Blockly.JavaScript.valueToCode(block, 'PIXELS', Blockly.JavaScript.ORDER_ATOMIC);
    // TODO: Assemble JavaScript into code variable.
    var codeMoveRight = "$(\"#moveDiv\").animate({\n " + 
                    "left: \"+=" + value_pixels + "px\"\n" +
                  "},1000);\n";

    // You can show a blockly warning
    if( value_pixels >= 300 ) block.setWarningText("You get it!");

    // Or you can store its value elsewere...
    // myExternalVar = value_pixels;

    return codeMoveRight;
};

This will appear as a warning icon in the block itselfs.

In any case, if you want to "remember" this value_pixels variable, I believe the more easy way is to do it in the generator, as shown above. You can always store it in an external var accessible from your custom functions.

EDIT:

If you need to traverse the block structure for some other purpose, you may use:

  • Blockly.mainWorkspace.getTopBlocks(true); // To get the top-level blocks
  • An iteration over the top-level block list
  • block = block.nextConnection && block.nextConnection.targetBlock(); // To "descend" into the sub-blocks of a block, then iterate over them
  • if(block.type=="move_right") ... // To check for a particular block type

I hope this will give a start point, but the best way to learn about these "tricks" is reading the Blockly source code. Even as the code is generally well commented, AFAIK there is no way to autogenerate a document, and it is not available on the web neither.

like image 136
jrierab Avatar answered Oct 11 '22 00:10

jrierab