Update blockToDom types to include document fragments (#4280)

This commit is contained in:
alschmiedt
2020-09-16 10:51:09 -07:00
committed by GitHub
parent d70d896a9f
commit 22d598484f
8 changed files with 33 additions and 20 deletions

View File

@@ -927,11 +927,15 @@ Blockly.BlockSvg.prototype.dispose = function(healStack, animate) {
/**
* Encode a block for copying.
* @return {!Blockly.ICopyable.CopyData} Copy metadata.
* @return {?Blockly.ICopyable.CopyData} Copy metadata, or null if the block is
* an insertion marker.
* @package
*/
Blockly.BlockSvg.prototype.toCopyData = function() {
var xml = Blockly.Xml.blockToDom(this, true);
if (this.isInsertionMarker_) {
return null;
}
var xml = /** @type {!Element} */ (Blockly.Xml.blockToDom(this, true));
// Copy only the selected block and internal blocks.
Blockly.Xml.deleteNext(xml);
// Encode start position in XML.

View File

@@ -272,9 +272,11 @@ Blockly.onKeyDown = function(e) {
*/
Blockly.copy_ = function(toCopy) {
var data = toCopy.toCopyData();
Blockly.clipboardXml_ = data.xml;
Blockly.clipboardSource_ = data.source;
Blockly.clipboardTypeCounts_ = data.typeCounts;
if (data) {
Blockly.clipboardXml_ = data.xml;
Blockly.clipboardSource_ = data.source;
Blockly.clipboardTypeCounts_ = data.typeCounts;
}
};
/**

View File

@@ -115,7 +115,8 @@ Blockly.Connection.prototype.connect_ = function(childConnection) {
// Displaced shadow blocks dissolve rather than reattaching or bumping.
if (orphanBlock.isShadow()) {
// Save the shadow block so that field values are preserved.
shadowDom = Blockly.Xml.blockToDom(orphanBlock);
// This cast assumes that a block can not be both a shadow block and an insertion marker.
shadowDom = /** @type {!Element} */ (Blockly.Xml.blockToDom(orphanBlock));
orphanBlock.dispose(false);
orphanBlock = null;
} else if (parentConnection.type == Blockly.INPUT_VALUE) {

View File

@@ -948,7 +948,8 @@ Blockly.Flyout.prototype.placeNewBlock_ = function(oldBlock) {
}
// Create the new block by cloning the block in the flyout (via XML).
var xml = Blockly.Xml.blockToDom(oldBlock, true);
// This cast assumes that the oldBlock can not be an insertion marker.
var xml = /** @type {!Element} */ (Blockly.Xml.blockToDom(oldBlock, true));
// The target workspace would normally resize during domToBlock, which will
// lead to weird jumps. Save it for terminateDrag.
targetWorkspace.setResizesEnabled(false);

View File

@@ -25,7 +25,7 @@ Blockly.ICopyable = function() {};
/**
* Encode for copying.
* @return {!Blockly.ICopyable.CopyData} Copy metadata.
* @return {?Blockly.ICopyable.CopyData} Copy metadata.
*/
Blockly.ICopyable.prototype.toCopyData;

View File

@@ -606,7 +606,8 @@ Blockly.Trashcan.prototype.onDelete_ = function(event) {
if (this.workspace_.options.maxTrashcanContents <= 0) {
return;
}
if (event.type == Blockly.Events.BLOCK_DELETE &&
// Must check that the tagName exists since oldXml can be a DocumentFragment.
if (event.type == Blockly.Events.BLOCK_DELETE && event.oldXml.tagName &&
event.oldXml.tagName.toLowerCase() != 'shadow') {
var cleanedXML = this.cleanBlockXML_(event.oldXml);
if (this.contents_.indexOf(cleanedXML) != -1) {

View File

@@ -1326,13 +1326,16 @@ Blockly.WorkspaceSvg.prototype.highlightBlock = function(id, opt_state) {
/**
* Paste the provided block onto the workspace.
* @param {!Element} xmlBlock XML block element.
* @param {!Element|!DocumentFragment} xmlBlock XML block element or an empty
* DocumentFragment if the block was an insertion marker.
*/
Blockly.WorkspaceSvg.prototype.paste = function(xmlBlock) {
if (!this.rendered || xmlBlock.getElementsByTagName('block').length >=
if (!this.rendered || !xmlBlock.tagName || xmlBlock.getElementsByTagName('block').length >=
this.remainingCapacity()) {
return;
}
// The check above for tagName rules out the possibility of this being a DocumentFragment.
xmlBlock = /** @type {!Element} */ (xmlBlock);
if (this.currentGesture_) {
this.currentGesture_.cancel(); // Dragging while pasting? No.
}

View File

@@ -74,15 +74,15 @@ Blockly.Xml.variablesToDom = function(variableList) {
* Encode a block subtree as XML with XY coordinates.
* @param {!Blockly.Block} block The root block to encode.
* @param {boolean=} opt_noId True if the encoder should skip the block ID.
* @return {!Element} Tree of XML elements.
* @return {!Element|!DocumentFragment} Tree of XML elements or an empty document
* fragment if the block was an insertion marker.
*/
Blockly.Xml.blockToDomWithXY = function(block, opt_noId) {
if (block.isInsertionMarker()) { // Skip over insertion markers.
block = block.getChildren(false)[0];
if (!block) {
// Disappears when appended. Cast to ANY b/c DocumentFragment -> Element
// is invalid. We have to cast to ANY in between.
return /** @type{?} */ (new DocumentFragment());
// Disappears when appended.
return new DocumentFragment();
}
}
@@ -138,7 +138,8 @@ Blockly.Xml.allFieldsToDom_ = function(block, element) {
* Encode a block subtree as XML.
* @param {!Blockly.Block} block The root block to encode.
* @param {boolean=} opt_noId True if the encoder should skip the block ID.
* @return {!Element} Tree of XML elements.
* @return {!Element|!DocumentFragment} Tree of XML elements or an empty document
* fragment if the block was an insertion marker.
*/
Blockly.Xml.blockToDom = function(block, opt_noId) {
// Skip over insertion markers.
@@ -147,9 +148,8 @@ Blockly.Xml.blockToDom = function(block, opt_noId) {
if (child) {
return Blockly.Xml.blockToDom(child);
} else {
// Disappears when appended. Cast to ANY b/c DocumentFragment -> Element
// is invalid. We have to cast to ANY in between.
return /** @type{?} */ (new DocumentFragment());
// Disappears when appended.
return new DocumentFragment();
}
}
@@ -808,7 +808,8 @@ Blockly.Xml.domToField_ = function(block, fieldName, xml) {
/**
* Remove any 'next' block (statements in a stack).
* @param {!Element} xmlBlock XML block element.
* @param {!Element|!DocumentFragment} xmlBlock XML block element or an empty
* DocumentFragment if the block was an insertion marker.
*/
Blockly.Xml.deleteNext = function(xmlBlock) {
for (var i = 0, child; (child = xmlBlock.childNodes[i]); i++) {