Search code examples
javascriptblockly

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.


Solution

  • 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.