WorkspaceToDOM Includes Insertion Markers
See original GitHub issueProblem statement
If workspaceToDom is called while an insertion marker is visible, the insertion marker is included and can become a ‘real’ block.
Expected Behavior
workspaceToDom should ignore insertion markers, as they are UI only.
Actual Behavior
If workspaceToDom is called while an insertion marker is visible, the insertion marker is included and can become a ‘real’ block.
Steps to Reproduce
This is probably a bit of a tough one to run into ‘in the wild’… we ran into it due to a timing issue with Blockly as nested in a React component where we run workspaceToDom
in order to save the XML to the store, then repopulate the workspace from that ‘changed’ XML before the insertion marker can be deleted. However, to verify the issue, I believe you can just do:
- Add a listener to the workspace to run workspaceToDom when it changes.
- Begin dragging the child out of a top-level block
- While the insertion marker is still visible, check the output of workspaceToDom.
(This may require a bit of playing around… we specifically encountered it by dragging the block and holding it for a little while.)
Operating System and Browser
- Desktop Chrome
I expect it applies to other browsers, but haven’t tested it.
Additional Information
I realize this is a pretty obscure scenario that only really occurs in scenarios like ours wherein we use React to try to make Blockly behave like a controlled component; however, I do believe this still constitutes a legitimate bug.
I nearly just made a PR to fix this, but I wanted advice on whether it would be accepted/whether this was an appropriate solution. For the record, my fix is just a simple fix to workspaceToDom
to skip insertion markers:
Blockly.Xml.workspaceToDom = function(workspace, opt_noId) {
var xml = Blockly.Xml.utils.createElement('xml');
var variablesElement = Blockly.Xml.variablesToDom(
Blockly.Variables.allUsedVarModels(workspace));
if (variablesElement.hasChildNodes()) {
xml.appendChild(variablesElement);
}
var comments = workspace.getTopComments(true);
for (var i = 0, comment; comment = comments[i]; i++) {
xml.appendChild(comment.toXmlWithXY(opt_noId));
}
var blocks = workspace.getTopBlocks(true);
for (var i = 0, block; block = blocks[i]; i++) {
if (!block.isInsertionMarker_) {
xml.appendChild(Blockly.Xml.blockToDomWithXY(block, opt_noId));
}
}
return xml;
};
We may wind up just implementing this in our own fork, but I wanted to run it by you guys first to see if this was something you wanted a fix for and/or if my fix is appropriate or if there would be a more appropriate one.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:8 (3 by maintainers)
Top GitHub Comments
Suggest having blockToDom return an empty DocumentFragment. The caller can append that to the DOM and it will quietly disappear without a trace.
@NeilFraser What’s your opinion on this one?
The fifth option is to throw an error.
I’m leaning toward option 1. My reasons: