Importing and Exporting Blocks

5,343 views
Skip to first unread message

sarahv_21

unread,
Aug 3, 2015, 12:22:45 PM8/3/15
to Blockly
I do know about this link, but figuring out how to import and export blocks is still unclear to me:
https://developers.google.com/blockly/installation/overview#importing_and_exporting_blocks

If anyone could help or make this information more clear, I'd be most appreciative because I don't want to use the cloud storage aspect right now, if I don't have to, but still don't want people to lose their blocks.

Thanks,
Sarah

Blake

unread,
Aug 3, 2015, 12:49:36 PM8/3/15
to Blockly
Sarah,

The link you mentioned shows how to use the Blockly.Xml.workspaceToDom(workspace) and Blockly.Xml.domToWorkspace(workspace, xml) which are the basis for exporting and importing blocks via XML.

From a high level you can extend blockly using these methods to export the user's blocks to XML. Once you have the XML you can:
  1. allow the user to save the XML as a file. Example: http://jsfiddle.net/TechplexEngineer/geLvp6bo/
  2. display the XML in a textarea like the Blockly Code Demo does(https://blockly-demo.appspot.com/static/demos/code/index.html).
  3. allow the user to save the XML to their localstoarge in the browser.
My tool EasyJ does all three. You can check them out http://easyj.team5122.com/ Use the menu File > Export.. and File > Import..

Hope this helps.
Blake

--
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.
For more options, visit https://groups.google.com/d/optout.

Sarah Baldwin

unread,
Aug 3, 2015, 2:01:48 PM8/3/15
to blo...@googlegroups.com
Thank you, and yes that's almost exactly what I want to do.  Would you have any suggestions on how to accomplish the code for import and export buttons that would do the same as those links do with the drop down menu (1) and the tabs (2)?

Blake

unread,
Aug 3, 2015, 4:20:13 PM8/3/15
to Blockly
If I understand you correctly you are wondering how to take the output of workspaceToDomand put it in a textarea, and load from a textarea to the workspace.
I used jQuery to read and write the textareas.

The best example I can think of is to look at the source of what I did with EasyJ. You can see this code using your browser (right click on the page, view source or inspect element) the modals are loaded into the page via PHP so their respective javascript is just following the modal HTML. Not the best practice but easier for development.

Workspace to Textarea:
var xmlDom = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace);
var xmlText = Blockly.Xml.domToPrettyText(xmlDom);
$('.myOutputTextarea').val(xmlText).focus();

Textarea to Blockly Workspace:
function loadxml(xml) {
    if (typeof xml != "string" || xml.length < 5) {
        alert("No Input");
        return false;
        return;
    }
    try {
        var dom = Blockly.Xml.textToDom(xml);
        Blockly.mainWorkspace.clear();
        Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, dom);
        return true;
    } catch (e) {
        alert("Invalid xml");
        return false;
    }
}

$('#import .loadbtn').click(function() {
    var toload = $('#import .modal-body textarea').val();
    var success = loadxml(toload);
});

Hope this helps

Sarah Baldwin

unread,
Aug 3, 2015, 6:07:38 PM8/3/15
to blo...@googlegroups.com
Thank you sooo much! :) very helpful

Maziarser

unread,
Oct 2, 2017, 4:54:48 AM10/2/17
to Blockly
Hi Sarah,
Hi Blake,

As I understood, to export and import XML code into my workSpace, I need to have a textarea. 
With this regard, I have a question to make the code nicer to my user which is: 
Have you guys tried to add a code highlighter to the textarea?

I have tried a couple of ways:
1. I have tried "highlight" --> https://highlightjs.org/
2. I have tried "codemirror"  --> https://codemirror.net/

And I could have get the XML code highlighted, BUT the textarea will not act like a textarea after that (it is a div). So, you can not import it to the workspace anymore!!!

Do you know any solution to tackle this problem?

Maziar

Andrew n marshall

unread,
Oct 2, 2017, 11:54:20 AM10/2/17
to blo...@googlegroups.com
Hi Maziar,

Since you've tried CodeMirror, they have a getValue() method on the editor object that I think does what you want.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+unsubscribe@googlegroups.com.

Maziarser

unread,
Oct 2, 2017, 4:12:57 PM10/2/17
to Blockly
Hi Andrew,

Thanks for your helpful reply.

A way to encounter with this issue is to make an middle DIV called modifyCodeDiv:

<div id="modifyCodeDiv" contenteditable="true"></div>


modifyCodeDiv is getting the value of modifyCode textarea:

document.getElementById("modifyCodeDiv").innerHTML =
document.getElementById("modifyCode").value;


So, users can modify the code in the div modifyCodeDiv.


To execute the code, you need to send the value of modifyCodeDiv to modifyCode. As div does not have value attribute, you need to do:

var my_element = document.getElementById('modifyCodeDiv');      
var my_str = my_element.innerText || my_element.textContent; 

document.getElementById("modifyCode").value = my_str;


Furthermore, you can apply highlight.js to your div modifyCodeDiv.

Andrew n marshall

unread,
Oct 2, 2017, 6:20:44 PM10/2/17
to blo...@googlegroups.com
I was just pointing out the CodeMirror method getValue().  Your last message doesn't appear to use that.

// Create editor
var myCodeMirror = CodeMirror(document.body, {
 value: ""
 mode:  "php"
});
// or use CodeMirror.fromTextArea(myTextArea);

// Load code...
myCodeMirror.setValue(Blockly.PHP.workspaceToCode(workspace));

// Retrieve edited code...
var editedCode = myCodeMirror.getValue();





To unsubscribe from this group and stop receiving emails from it, send an email to blockly+unsubscribe@googlegroups.com.

Maziarser

unread,
Oct 4, 2017, 4:06:11 AM10/4/17
to Blockly
Hi Andrew,

That's really cool, thank you :)

To make it a complete example based on the previous conversation I did:

//define your variable:
var XMLCodeMirror = CodeMirror.fromTextArea($('#your textarea').get(0));

//loading from the textbox      
$('#button name').click(function() {
    var toload = XMLCodeMirror.getValue();

    var success = loadxml(toload);
});

function loadxml(xml) {
    if (typeof xml != "string" || xml.length < 5) {
        alert("No Input");
        return false;
        return;
    }
    try {
        var dom = Blockly.Xml.textToDom(xml);
        Blockly.mainWorkspace.clear();
        Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, dom);
        return true;
    } catch (e) {
        alert("Invalid xml");
        return false;
   }
}

Thanks again!
Maziar

Behrooz Tahanzadeh

unread,
Apr 17, 2018, 7:19:04 AM4/17/18
to Blockly
Hello!

I'm trying to do same thing but instead of clearing the workspace first, I wanna add the new document to it.
The problem is that there are some duplicated variable IDs.
Is there any solution to deal with that?

Thanks,
Behrooz

picklesrus

unread,
Apr 17, 2018, 8:11:01 AM4/17/18
to Blockly
Hi Behrooz,


If I understand correctly, you have blocks on a workspace, at least one of which is a variable with an id, let's say "myVar123"  and want to import more blocks from xml.  Does your xml contain a variable with id "myVar123" that you want to have a different id when you import?  Or is the problem something else?

Since there have been some changes in the variable id code recently, could you also tell us when you last synced and whether it was from master or develop?

Thanks,
picklesrus

Behrooz Tahanzadeh

unread,
Apr 19, 2018, 4:05:57 AM4/19/18
to Blockly
Hello

Yes, That's exactly the case. However I just wanted to skip the variables with same ID and keep the one already available in the workspace. So far I managed to do that by changing the code at core/xml.js#L416 (adding a try/catch statement).

Is the any native solution?

Thanks,
Behrooz

picklesrus

unread,
Apr 19, 2018, 11:22:50 AM4/19/18
to Blockly
There's xml.appendDomToWorkspace, but I don't think that's what you want - that's more about the position of the blocks you're adding (i.e. they won't end up right on top of each other if you have two of the same blocks in the same place)

So is the problem that you end up with seemingly duplicate variable getter blocks when you only want the original?  Or is there an error being thrown?
If it is the former, I would consider running a preprocess step on your xml before you import to strip out the blocks that you know are extraneous.  Blockly can't make those kind of decisions intelligently in a general way that works for all developers.  It takes the approach of if the block is in the xml, it will import it regardless of what is already in the workspace. You'll notice if you open the playground and import the same xml multiple times, you'll end up with blocks on top of each other, but with different block ids, but the same variable id. e.g. this xml:

  <variables>
    <variable type="" id="myVarId">pizza</variable>
  </variables>
  <block type="variables_get" id="getBlockId">
    <field name="VAR" id="myVarId" variabletype="">item</field>
  </block>
</xml>

Hacking core is also probably okay, but depending on what else you're doing in your application seems a bit risky.  e.g. If you're loading a project with multiple getters for the same variable into a clean workspace,  how do you know whether to accept the 2nd one you come across or not?

Although, now after writing this, I realize I still may be misunderstanding your question. If this doesn't help, can you provide sample xml for the blocks on your workspace and the xml of the blocks you want to import.

Thanks!
-picklesrus
Reply all
Reply to author
Forward
0 new messages