Merge branch 'develop' into single_field_blocks

This commit is contained in:
Rachel Fenichel
2019-11-12 11:52:03 -08:00
committed by GitHub
42 changed files with 1004 additions and 419 deletions

View File

@@ -660,8 +660,12 @@ Blockly.BlockSvg.prototype.setCollapsed = function(collapsed) {
Blockly.BlockSvg.prototype.tab = function(start, forward) {
var tabCursor = new Blockly.TabNavigateCursor();
tabCursor.setCurNode(Blockly.ASTNode.createFieldNode(start));
var action = forward ?
Blockly.navigation.ACTION_NEXT : Blockly.navigation.ACTION_PREVIOUS;
var nextNode = forward ? tabCursor.next() : tabCursor.prev();
tabCursor.onBlocklyAction(action);
var nextNode = tabCursor.getCurNode();
if (nextNode) {
var nextField = /** @type {!Blockly.Field} */ (nextNode.getLocation());
nextField.showEditor();
@@ -1752,11 +1756,5 @@ Blockly.BlockSvg.prototype.getHeightWidth = function() {
* @package
*/
Blockly.BlockSvg.prototype.highlightForReplacement = function(add) {
if (add) {
Blockly.utils.dom.addClass(/** @type {!Element} */ (this.svgGroup_),
'blocklyReplaceable');
} else {
Blockly.utils.dom.removeClass(/** @type {!Element} */ (this.svgGroup_),
'blocklyReplaceable');
}
this.pathObject.updateReplacementHighlight(add);
};

View File

@@ -51,6 +51,42 @@ Blockly.Bubble = function(workspace, content, shape, anchorXY,
this.content_ = content;
this.shape_ = shape;
/**
* Method to call on resize of bubble.
* @type {?function()}
* @private
*/
this.resizeCallback_ = null;
/**
* Method to call on move of bubble.
* @type {?function()}
* @private
*/
this.moveCallback_ = null;
/**
* Mouse down on bubbleBack_ event data.
* @type {?Blockly.EventData}
* @private
*/
this.onMouseDownBubbleWrapper_ = null;
/**
* Mouse down on resizeGroup_ event data.
* @type {?Blockly.EventData}
* @private
*/
this.onMouseDownResizeWrapper_ = null;
/**
* Describes whether this bubble has been disposed of (nodes and event
* listeners removed from the page) or not.
* @type {boolean}
* @package
*/
this.disposed = false;
var angle = Blockly.Bubble.ARROW_ANGLE;
if (this.workspace_.RTL) {
angle = -angle;
@@ -72,29 +108,6 @@ Blockly.Bubble = function(workspace, content, shape, anchorXY,
this.positionBubble_();
this.renderArrow_();
this.rendered_ = true;
if (!workspace.options.readOnly) {
Blockly.bindEventWithChecks_(
this.bubbleBack_, 'mousedown', this, this.bubbleMouseDown_);
if (this.resizeGroup_) {
Blockly.bindEventWithChecks_(
this.resizeGroup_, 'mousedown', this, this.resizeMouseDown_);
}
}
/**
* Method to call on resize of bubble.
* @type {?function()}
* @private
*/
this.resizeCallback_ = null;
/**
* Method to call on move of bubble.
* @type {?function()}
* @private
*/
this.moveCallback_ = null;
};
/**
@@ -124,15 +137,15 @@ Blockly.Bubble.ARROW_BEND = 4;
Blockly.Bubble.ANCHOR_RADIUS = 8;
/**
* Wrapper function called when a mouseUp occurs during a drag operation.
* @type {Array.<!Array>}
* Mouse up event data.
* @type {?Blockly.EventData}
* @private
*/
Blockly.Bubble.onMouseUpWrapper_ = null;
/**
* Wrapper function called when a mouseMove occurs during a drag operation.
* @type {Array.<!Array>}
* Mouse move event data.
* @type {?Blockly.EventData}
* @private
*/
Blockly.Bubble.onMouseMoveWrapper_ = null;
@@ -278,6 +291,15 @@ Blockly.Bubble.prototype.createDom_ = function(content, hasResize) {
} else {
this.resizeGroup_ = null;
}
if (!this.workspace_.options.readOnly) {
this.onMouseDownBubbleWrapper_ = Blockly.bindEventWithChecks_(
this.bubbleBack_, 'mousedown', this, this.bubbleMouseDown_);
if (this.resizeGroup_) {
this.onMouseDownResizeWrapper_ = Blockly.bindEventWithChecks_(
this.resizeGroup_, 'mousedown', this, this.resizeMouseDown_);
}
}
this.bubbleGroup_.appendChild(content);
return this.bubbleGroup_;
};
@@ -782,16 +804,15 @@ Blockly.Bubble.prototype.setColour = function(hexColour) {
* Dispose of this bubble.
*/
Blockly.Bubble.prototype.dispose = function() {
if (this.onMouseDownBubbleWrapper_) {
Blockly.unbindEvent_(this.onMouseDownBubbleWrapper_);
}
if (this.onMouseDownResizeWrapper_) {
Blockly.unbindEvent_(this.onMouseDownResizeWrapper_);
}
Blockly.Bubble.unbindDragEvents_();
// Dispose of and unlink the bubble.
Blockly.utils.dom.removeNode(this.bubbleGroup_);
this.bubbleGroup_ = null;
this.bubbleArrow_ = null;
this.bubbleBack_ = null;
this.resizeGroup_ = null;
this.workspace_ = null;
this.content_ = null;
this.shape_ = null;
this.disposed = true;
};
/**

View File

@@ -61,6 +61,34 @@ Blockly.Comment = function(block) {
*/
this.cachedText_ = '';
/**
* Mouse up event data.
* @type {?Blockly.EventData}
* @private
*/
this.onMouseUpWrapper_ = null;
/**
* Wheel event data.
* @type {?Blockly.EventData}
* @private
*/
this.onWheelWrapper_ = null;
/**
* Change event data.
* @type {?Blockly.EventData}
* @private
*/
this.onChangeWrapper_ = null;
/**
* Input event data.
* @type {?Blockly.EventData}
* @private
*/
this.onInputWrapper_ = null;
this.createIcon();
};
Blockly.utils.object.inherits(Blockly.Comment, Blockly.Icon);
@@ -137,21 +165,24 @@ Blockly.Comment.prototype.createEditor_ = function() {
// Ideally this would be hooked to the focus event for the comment.
// However doing so in Firefox swallows the cursor for unknown reasons.
// So this is hooked to mouseup instead. No big deal.
Blockly.bindEventWithChecks_(textarea, 'mouseup', this, this.startEdit_,
true, true);
this.onMouseUpWrapper_ = Blockly.bindEventWithChecks_(
textarea, 'mouseup', this, this.startEdit_, true, true);
// Don't zoom with mousewheel.
Blockly.bindEventWithChecks_(textarea, 'wheel', this, function(e) {
e.stopPropagation();
});
Blockly.bindEventWithChecks_(textarea, 'change', this, function(_e) {
if (this.cachedText_ != this.model_.text) {
Blockly.Events.fire(new Blockly.Events.BlockChange(
this.block_, 'comment', null, this.cachedText_, this.model_.text));
}
});
Blockly.bindEventWithChecks_(textarea, 'input', this, function(_e) {
this.model_.text = textarea.value;
});
this.onWheelWrapper_ = Blockly.bindEventWithChecks_(
textarea, 'wheel', this, function(e) {
e.stopPropagation();
});
this.onChangeWrapper_ = Blockly.bindEventWithChecks_(
textarea, 'change', this, function(_e) {
if (this.cachedText_ != this.model_.text) {
Blockly.Events.fire(new Blockly.Events.BlockChange(
this.block_, 'comment', null, this.cachedText_, this.model_.text));
}
});
this.onInputWrapper_ = Blockly.bindEventWithChecks_(
textarea, 'input', this, function(_e) {
this.model_.text = textarea.value;
});
setTimeout(textarea.focus.bind(textarea), 0);
@@ -271,7 +302,22 @@ Blockly.Comment.prototype.disposeBubble_ = function() {
Blockly.Warning.prototype.disposeBubble.call(this);
return;
}
if (this.onMouseUpWrapper_) {
Blockly.unbindEvent_(this.onMouseUpWrapper_);
this.onMouseUpWrapper_ = null;
}
if (this.onWheelWrapper_) {
Blockly.unbindEvent_(this.onWheelWrapper_);
this.onWheelWrapper_ = null;
}
if (this.onChangeWrapper_) {
Blockly.unbindEvent_(this.onChangeWrapper_);
this.onChangeWrapper_ = null;
}
if (this.onInputWrapper_) {
Blockly.unbindEvent_(this.onInputWrapper_);
this.onInputWrapper_ = null;
}
this.bubble_.dispose();
this.bubble_ = null;
this.textarea_ = null;

View File

@@ -44,6 +44,41 @@ Blockly.Menu = function() {
* @private
*/
this.highlightedIndex_ = -1;
/**
* Mouse over event data.
* @type {?Blockly.EventData}
* @private
*/
this.mouseOverHandler_ = null;
/**
* Click event data.
* @type {?Blockly.EventData}
* @private
*/
this.clickHandler_ = null;
/**
* Mouse enter event data.
* @type {?Blockly.EventData}
* @private
*/
this.mouseEnterHandler_ = null;
/**
* Mouse leave event data.
* @type {?Blockly.EventData}
* @private
*/
this.mouseLeaveHandler_ = null;
/**
* Key down event data.
* @type {?Blockly.EventData}
* @private
*/
this.onKeyDownWrapper_ = null;
};
Blockly.utils.object.inherits(Blockly.Menu, Blockly.Component);
@@ -73,7 +108,7 @@ Blockly.Menu.prototype.createDom = function() {
Blockly.Menu.prototype.focus = function() {
var el = this.getElement();
if (el) {
el.focus();
el.focus({preventScroll:true});
Blockly.utils.dom.addClass(el, 'focused');
}
};
@@ -147,7 +182,6 @@ Blockly.Menu.prototype.attachEvents_ = function() {
'mouseenter', this, this.handleMouseEnter_, true);
this.mouseLeaveHandler_ = Blockly.bindEventWithChecks_(el,
'mouseleave', this, this.handleMouseLeave_, true);
this.onKeyDownWrapper_ = Blockly.bindEventWithChecks_(el,
'keydown', this, this.handleKeyEvent);
};
@@ -157,11 +191,26 @@ Blockly.Menu.prototype.attachEvents_ = function() {
* @private
*/
Blockly.Menu.prototype.detachEvents_ = function() {
Blockly.unbindEvent_(this.mouseOverHandler_);
Blockly.unbindEvent_(this.clickHandler_);
Blockly.unbindEvent_(this.mouseEnterHandler_);
Blockly.unbindEvent_(this.mouseLeaveHandler_);
Blockly.unbindEvent_(this.onKeyDownWrapper_);
if (this.mouseOverHandler_) {
Blockly.unbindEvent_(this.mouseOverHandler_);
this.mouseOverHandler_ = null;
}
if (this.clickHandler_) {
Blockly.unbindEvent_(this.clickHandler_);
this.clickHandler_ = null;
}
if (this.mouseEnterHandler_) {
Blockly.unbindEvent_(this.mouseEnterHandler_);
this.mouseEnterHandler_ = null;
}
if (this.mouseLeaveHandler_) {
Blockly.unbindEvent_(this.mouseLeaveHandler_);
this.mouseLeaveHandler_ = null;
}
if (this.onKeyDownWrapper_) {
Blockly.unbindEvent_(this.onKeyDownWrapper_);
this.onKeyDownWrapper_ = null;
}
};
// Child component management.

View File

@@ -44,6 +44,34 @@ goog.require('Blockly.utils.style');
Blockly.tree.TreeControl = function(toolbox, config) {
this.toolbox_ = toolbox;
/**
* Focus event data.
* @type {?Blockly.EventData}
* @private
*/
this.onFocusWrapper_ = null;
/**
* Blur event data.
* @type {?Blockly.EventData}
* @private
*/
this.onBlurWrapper_ = null;
/**
* Click event data.
* @type {?Blockly.EventData}
* @private
*/
this.onClickWrapper_ = null;
/**
* Key down event data.
* @type {?Blockly.EventData}
* @private
*/
this.onKeydownWrapper_ = null;
Blockly.tree.BaseNode.call(this, '', config);
// The root is open and selected by default.
@@ -272,10 +300,8 @@ Blockly.tree.TreeControl.prototype.attachEvents_ = function() {
'focus', this, this.handleFocus_);
this.onBlurWrapper_ = Blockly.bindEvent_(el,
'blur', this, this.handleBlur_);
this.onClickWrapper_ = Blockly.bindEventWithChecks_(el,
'click', this, this.handleMouseEvent_);
this.onKeydownWrapper_ = Blockly.bindEvent_(el,
'keydown', this, this.handleKeyEvent_);
};
@@ -285,10 +311,22 @@ Blockly.tree.TreeControl.prototype.attachEvents_ = function() {
* @private
*/
Blockly.tree.TreeControl.prototype.detachEvents_ = function() {
Blockly.unbindEvent_(this.onFocusWrapper_);
Blockly.unbindEvent_(this.onBlurWrapper_);
Blockly.unbindEvent_(this.onClickWrapper_);
Blockly.unbindEvent_(this.onKeydownWrapper_);
if (this.onFocusWrapper_) {
Blockly.unbindEvent_(this.onFocusWrapper_);
this.onFocusWrapper_ = null;
}
if (this.onBlurWrapper_) {
Blockly.unbindEvent_(this.onBlurWrapper_);
this.onBlurWrapper_ = null;
}
if (this.onClickWrapper_) {
Blockly.unbindEvent_(this.onClickWrapper_);
this.onClickWrapper_ = null;
}
if (this.onKeydownWrapper_) {
Blockly.unbindEvent_(this.onKeydownWrapper_);
this.onKeydownWrapper_ = null;
}
};
/**

View File

@@ -166,6 +166,7 @@ Blockly.ContextMenu.hide = function() {
Blockly.ContextMenu.currentBlock = null;
if (Blockly.ContextMenu.eventWrapper_) {
Blockly.unbindEvent_(Blockly.ContextMenu.eventWrapper_);
Blockly.ContextMenu.eventWrapper_ = null;
}
};

View File

@@ -129,6 +129,13 @@ Blockly.Field = function(value, opt_validator, opt_config) {
*/
this.mouseDownWrapper_ = null;
/**
* Constants associated with the source block's renderer.
* @type {Blockly.blockRendering.ConstantProvider}
* @protected
*/
this.constants_ = null;
opt_config && this.configure_(opt_config);
this.setValue(value);
opt_validator && this.setValidator(opt_validator);
@@ -257,24 +264,6 @@ Blockly.Field.prototype.EDITABLE = true;
*/
Blockly.Field.prototype.SERIALIZABLE = false;
/**
* Point size of text. Should match blocklyText's font-size in CSS.
* @const {number}
*/
Blockly.Field.FONTSIZE = 11;
/**
* Text font weight. Should match blocklyText's font-weight in CSS.
* @const {string}
*/
Blockly.Field.FONTWEIGHT = 'normal';
/**
* Text font family. Should match blocklyText's font-family in CSS.
* @const {string}
*/
Blockly.Field.FONTFAMILY = 'sans-serif';
/**
* Process the configuration map passed to the field.
* @param {!Object} config A map of options used to configure the field. See
@@ -303,6 +292,9 @@ Blockly.Field.prototype.setSourceBlock = function(block) {
throw Error('Field already bound to a block.');
}
this.sourceBlock_ = block;
if (block.workspace.rendered) {
this.constants_ = block.workspace.getRenderer().getConstants();
}
};
/**
@@ -661,8 +653,9 @@ Blockly.Field.prototype.updateWidth = function() {
Blockly.Field.prototype.updateSize_ = function() {
var textWidth = Blockly.utils.dom.getFastTextWidth(
/** @type {!SVGTextElement} */ (this.textElement_),
Blockly.Field.FONTSIZE, Blockly.Field.FONTWEIGHT,
Blockly.Field.FONTFAMILY);
this.constants_.FIELD_TEXT_FONTSIZE,
this.constants_.FIELD_TEXT_FONTWEIGHT,
this.constants_.FIELD_TEXT_FONTFAMILY);
var totalWidth = textWidth;
if (this.borderRect_) {
totalWidth += Blockly.Field.X_PADDING;

View File

@@ -330,9 +330,11 @@ Blockly.FieldAngle.prototype.dropdownCreate_ = function() {
// a click handler on the drag surface to update the value if the surface
// is clicked.
this.clickSurfaceWrapper_ =
Blockly.bindEventWithChecks_(circle, 'click', this, this.onMouseMove_, true, true);
Blockly.bindEventWithChecks_(circle, 'click', this, this.onMouseMove_,
true, true);
this.moveSurfaceWrapper_ =
Blockly.bindEventWithChecks_(circle, 'mousemove', this, this.onMouseMove_, true, true);
Blockly.bindEventWithChecks_(circle, 'mousemove', this, this.onMouseMove_,
true, true);
return svg;
};
@@ -343,12 +345,15 @@ Blockly.FieldAngle.prototype.dropdownCreate_ = function() {
Blockly.FieldAngle.prototype.dropdownDispose_ = function() {
if (this.clickWrapper_) {
Blockly.unbindEvent_(this.clickWrapper_);
this.clickWrapper_ = null;
}
if (this.clickSurfaceWrapper_) {
Blockly.unbindEvent_(this.clickSurfaceWrapper_);
this.clickSurfaceWrapper_ = null;
}
if (this.moveSurfaceWrapper_) {
Blockly.unbindEvent_(this.moveSurfaceWrapper_);
this.moveSurfaceWrapper_ = null;
}
this.gauge_ = null;
this.line_ = null;

View File

@@ -334,7 +334,7 @@ Blockly.FieldColour.prototype.showEditor_ = function() {
this, this.dropdownDispose_.bind(this));
// Focus so we can start receiving keyboard events.
this.picker_.focus();
this.picker_.focus({preventScroll:true});
};
/**
@@ -487,7 +487,7 @@ Blockly.FieldColour.prototype.onMouseMove_ = function(e) {
* @private
*/
Blockly.FieldColour.prototype.onMouseEnter_ = function() {
this.picker_.focus();
this.picker_.focus({preventScroll:true});
};
/**
@@ -610,18 +610,23 @@ Blockly.FieldColour.prototype.dropdownCreate_ = function() {
Blockly.FieldColour.prototype.dropdownDispose_ = function() {
if (this.onClickWrapper_) {
Blockly.unbindEvent_(this.onClickWrapper_);
this.onClickWrapper_ = null;
}
if (this.onMouseMoveWrapper_) {
Blockly.unbindEvent_(this.onMouseMoveWrapper_);
this.onMouseMoveWrapper_ = null;
}
if (this.onMouseEnterWrapper_) {
Blockly.unbindEvent_(this.onMouseEnterWrapper_);
this.onMouseEnterWrapper_ = null;
}
if (this.onMouseLeaveWrapper_) {
Blockly.unbindEvent_(this.onMouseLeaveWrapper_);
this.onMouseLeaveWrapper_ = null;
}
if (this.onKeyDownWrapper_) {
Blockly.unbindEvent_(this.onKeyDownWrapper_);
this.onKeyDownWrapper_ = null;
}
this.picker_ = null;
this.highlightedIndex_ = null;

View File

@@ -516,8 +516,9 @@ Blockly.FieldDropdown.prototype.renderSelectedImage_ = function(imageJson) {
var arrowWidth = Blockly.utils.dom.getFastTextWidth(
/** @type {!SVGTSpanElement} */ (this.arrow_),
Blockly.Field.FONTSIZE, Blockly.Field.FONTWEIGHT,
Blockly.Field.FONTFAMILY);
this.constants_.FIELD_TEXT_FONTSIZE,
this.constants_.FIELD_TEXT_FONTWEIGHT,
this.constants_.FIELD_TEXT_FONTFAMILY);
var imageHeight = Number(imageJson.height);
var imageWidth = Number(imageJson.width);
@@ -552,8 +553,9 @@ Blockly.FieldDropdown.prototype.renderSelectedText_ = function() {
// Height and width include the border rect.
this.size_.height = Blockly.Field.BORDER_RECT_DEFAULT_HEIGHT;
this.size_.width = Blockly.utils.dom.getFastTextWidth(this.textElement_,
Blockly.Field.FONTSIZE, Blockly.Field.FONTWEIGHT,
Blockly.Field.FONTFAMILY) +
this.constants_.FIELD_TEXT_FONTSIZE,
this.constants_.FIELD_TEXT_FONTWEIGHT,
this.constants_.FIELD_TEXT_FONTFAMILY) +
Blockly.Field.X_PADDING;
};

View File

@@ -245,7 +245,7 @@ Blockly.FieldMultilineInput.prototype.widgetCreate_ = function() {
var htmlInput = /** @type {HTMLTextAreaElement} */ (document.createElement('textarea'));
htmlInput.className = 'blocklyHtmlInput blocklyHtmlTextAreaInput';
htmlInput.setAttribute('spellcheck', this.spellcheck_);
var fontSize = (Blockly.Field.FONTSIZE * scale) + 'pt';
var fontSize = (this.constants_.FIELD_TEXT_FONTSIZE * scale) + 'pt';
div.style.fontSize = fontSize;
htmlInput.style.fontSize = fontSize;
var borderRadius = (Blockly.FieldTextInput.BORDERRADIUS * scale) + 'px';

View File

@@ -91,6 +91,13 @@ Blockly.FieldTextInput = function(opt_value, opt_validator, opt_config) {
* @type {?boolean}
*/
this.fullBlockClickTarget_ = false;
/**
* Blur input event data.
* @type {?Blockly.EventData}
* @private
*/
this.onBlurInputWrapper_ = null;
};
Blockly.utils.object.inherits(Blockly.FieldTextInput, Blockly.Field);
@@ -319,7 +326,7 @@ Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) {
this.isBeingEdited_ = true;
if (!quietInput) {
this.htmlInput_.focus();
this.htmlInput_.focus({preventScroll:true});
this.htmlInput_.select();
}
};
@@ -336,7 +343,7 @@ Blockly.FieldTextInput.prototype.widgetCreate_ = function() {
htmlInput.className = 'blocklyHtmlInput';
htmlInput.setAttribute('spellcheck', this.spellcheck_);
var fontSize =
(Blockly.Field.FONTSIZE * this.workspace_.scale) + 'pt';
(this.constants_.FIELD_TEXT_FONTSIZE * this.workspace_.scale) + 'pt';
div.style.fontSize = fontSize;
htmlInput.style.fontSize = fontSize;
var borderRadius =
@@ -411,6 +418,9 @@ Blockly.FieldTextInput.prototype.bindInputEvents_ = function(htmlInput) {
this.onKeyInputWrapper_ =
Blockly.bindEventWithChecks_(
htmlInput, 'input', this, this.onHtmlInputChange_);
this.onBlurInputWrapper_ =
Blockly.bindEventWithChecks_(
htmlInput, 'blur', this, this.onHtmlInputBlur_);
};
/**
@@ -420,9 +430,15 @@ Blockly.FieldTextInput.prototype.bindInputEvents_ = function(htmlInput) {
Blockly.FieldTextInput.prototype.unbindInputEvents_ = function() {
if (this.onKeyDownWrapper_) {
Blockly.unbindEvent_(this.onKeyDownWrapper_);
this.onKeyDownWrapper_ = null;
}
if (this.onKeyInputWrapper_) {
Blockly.unbindEvent_(this.onKeyInputWrapper_);
this.onKeyInputWrapper_ = null;
}
if (this.onBlurInputWrapper_) {
Blockly.unbindEvent_(this.onBlurInputWrapper_);
this.onBlurInputWrapper_ = null;
}
};
@@ -468,6 +484,16 @@ Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(_e) {
}
};
/**
* Handle blur for the editor.
* @param {!Event} _e Focus event.
* @protected
*/
Blockly.FieldTextInput.prototype.onHtmlInputBlur_ = function(_e) {
Blockly.WidgetDiv.hide();
Blockly.DropDownDiv.hideWithoutAnimation();
};
/**
* Set the html input value and the field's internal value. The difference
* between this and ``setValue`` is that this also updates the html input

View File

@@ -847,3 +847,15 @@ Blockly.Flyout.prototype.placeNewBlock_ = function(oldBlock) {
block.moveBy(finalOffset.x, finalOffset.y);
return block;
};
/**
* Handles the given action.
* This is only triggered when keyboard accessibility mode is enabled.
* @param {!Blockly.Action} action The action to be handled.
* @return {boolean} True if the flyout handled the action, false otherwise.
* @package
*/
Blockly.Flyout.prototype.onBlocklyAction = function(action) {
var cursor = this.workspace_.getCursor();
return cursor.onBlocklyAction(action);
};

View File

@@ -87,6 +87,13 @@ Blockly.FlyoutButton = function(workspace, targetWorkspace, xml, isLabel) {
* @private
*/
this.cssClass_ = xml.getAttribute('web-class') || null;
/**
* Mouse up event data.
* @type {?Blockly.EventData}
* @private
*/
this.onMouseUpWrapper_ = null;
};
/**
@@ -106,13 +113,6 @@ Blockly.FlyoutButton.prototype.width = 0;
*/
Blockly.FlyoutButton.prototype.height = 0;
/**
* Opaque data that can be passed to Blockly.unbindEvent_.
* @type {Array.<!Array>}
* @private
*/
Blockly.FlyoutButton.prototype.onMouseUpWrapper_ = null;
/**
* Create the button elements.
* @return {!SVGElement} The button's SVG group.

View File

@@ -162,7 +162,7 @@ Blockly.Gesture = function(e, creatorWorkspace) {
/**
* A handle to use to unbind a mouse move listener at the end of a drag.
* Opaque data returned from Blockly.bindEventWithChecks_.
* @type {Array.<!Array>}
* @type {?Blockly.EventData}
* @protected
*/
this.onMoveWrapper_ = null;
@@ -170,7 +170,7 @@ Blockly.Gesture = function(e, creatorWorkspace) {
/**
* A handle to use to unbind a mouse up listener at the end of a drag.
* Opaque data returned from Blockly.bindEventWithChecks_.
* @type {Array.<!Array>}
* @type {?Blockly.EventData}
* @protected
*/
this.onUpWrapper_ = null;
@@ -483,12 +483,14 @@ Blockly.Gesture.prototype.doStart = function(e) {
// dragged, the block was moved, the parent workspace zoomed, etc.
this.startWorkspace_.resize();
}
this.startWorkspace_.markFocused();
this.mostRecentEvent_ = e;
// Hide chaff also hides the flyout, so don't do it if the click is in a
// flyout.
Blockly.hideChaff(!!this.flyout_);
this.startWorkspace_.markFocused();
this.mostRecentEvent_ = e;
Blockly.Tooltip.block();
if (this.targetBlock_) {

View File

@@ -78,18 +78,16 @@ Blockly.inject = function(container, opt_options) {
Blockly.user.keyMap.setKeyMap(options.keyMap);
Blockly.init_(workspace);
// Keep focus on the first workspace so entering keyboard navigation looks correct.
Blockly.mainWorkspace = workspace;
Blockly.svgResize(workspace);
subContainer.addEventListener('focus', function() {
subContainer.addEventListener('focusin', function() {
Blockly.mainWorkspace = workspace;
});
subContainer.addEventListener('blur', function() {
Blockly.mainWorkspace = null;
});
return workspace;
};
@@ -127,7 +125,8 @@ Blockly.createDom_ = function(container, options) {
'xmlns:html': Blockly.utils.dom.HTML_NS,
'xmlns:xlink': Blockly.utils.dom.XLINK_NS,
'version': '1.1',
'class': 'blocklySvg'
'class': 'blocklySvg',
'tabindex': '0'
}, container);
/*
<defs>
@@ -183,7 +182,6 @@ Blockly.createMainWorkspace_ = function(svg, options, blockDragSurface,
// A null translation will also apply the correct initial scale.
mainWorkspace.translate(0, 0);
Blockly.mainWorkspace = mainWorkspace;
if (!options.readOnly && !mainWorkspace.isMovable()) {
// Helper function for the workspaceChanged callback.
@@ -253,7 +251,9 @@ Blockly.createMainWorkspace_ = function(svg, options, blockDragSurface,
case Blockly.Events.BLOCK_CREATE:
case Blockly.Events.BLOCK_MOVE:
var object = mainWorkspace.getBlockById(e.blockId);
object = object.getRootBlock();
if (object) {
object = object.getRootBlock();
}
break;
case Blockly.Events.COMMENT_CREATE:
case Blockly.Events.COMMENT_MOVE:
@@ -311,7 +311,7 @@ Blockly.createMainWorkspace_ = function(svg, options, blockDragSurface,
object.moveBy(deltaX, deltaY);
}
if (e) {
if (!e.group) {
if (!e.group && object) {
console.log('WARNING: Moved object in bounds but there was no' +
' event group. This may break undo.');
}

View File

@@ -24,6 +24,7 @@
goog.provide('Blockly.Cursor');
goog.require('Blockly.navigation');
/**
* Class for a cursor.
@@ -94,10 +95,42 @@ Blockly.Cursor.prototype.hide = function() {
}
};
/**
* Handles the given action.
* This is only triggered when keyboard navigation is enabled.
* @param {!Blockly.Action} action The action to be handled.
* @return {boolean} True if the action has been handled, false otherwise.
*/
Blockly.Cursor.prototype.onBlocklyAction = function(action) {
// If we are on a field give it the option to handle the action
if (this.getCurNode() &&
this.getCurNode().getType() === Blockly.ASTNode.types.FIELD &&
this.getCurNode().getLocation().onBlocklyAction(action)) {
return true;
}
switch (action.name) {
case Blockly.navigation.actionNames.PREVIOUS:
this.prev();
return true;
case Blockly.navigation.actionNames.OUT:
this.out();
return true;
case Blockly.navigation.actionNames.NEXT:
this.next();
return true;
case Blockly.navigation.actionNames.IN:
this.in();
return true;
default:
return false;
}
};
/**
* Find the next connection, field, or block.
* @return {Blockly.ASTNode} The next element, or null if the current node is
* not set or there is no next value.
* @protected
*/
Blockly.Cursor.prototype.next = function() {
var curNode = this.getCurNode();
@@ -122,6 +155,7 @@ Blockly.Cursor.prototype.next = function() {
* Find the in connection or field.
* @return {Blockly.ASTNode} The in element, or null if the current node is
* not set or there is no in value.
* @protected
*/
Blockly.Cursor.prototype.in = function() {
var curNode = this.getCurNode();
@@ -146,6 +180,7 @@ Blockly.Cursor.prototype.in = function() {
* Find the previous connection, field, or block.
* @return {Blockly.ASTNode} The previous element, or null if the current node
* is not set or there is no previous value.
* @protected
*/
Blockly.Cursor.prototype.prev = function() {
var curNode = this.getCurNode();
@@ -170,6 +205,7 @@ Blockly.Cursor.prototype.prev = function() {
* Find the out connection, field, or block.
* @return {Blockly.ASTNode} The out element, or null if the current node is
* not set or there is no out value.
* @protected
*/
Blockly.Cursor.prototype.out = function() {
var curNode = this.getCurNode();

View File

@@ -39,6 +39,26 @@ Blockly.FlyoutCursor = function() {
};
Blockly.utils.object.inherits(Blockly.FlyoutCursor, Blockly.Cursor);
/**
* Handles the given action.
* This is only triggered when keyboard navigation is enabled.
* @param {!Blockly.Action} action The action to be handled.
* @return {boolean} True if the action has been handled, false otherwise.
* @override
*/
Blockly.FlyoutCursor.prototype.onBlocklyAction = function(action) {
switch (action.name) {
case Blockly.navigation.actionNames.PREVIOUS:
this.prev();
return true;
case Blockly.navigation.actionNames.NEXT:
this.next();
return true;
default:
return false;
}
};
/**
* Find the next connection, field, or block.
* @return {Blockly.ASTNode} The next element, or null if the current node is

View File

@@ -749,8 +749,8 @@ Blockly.navigation.onKeyPress = function(e) {
};
/**
* Execute any actions on the flyout, workspace, or toolbox that correspond to
* the given action.
* Decides which actions to handle depending on keyboard navigation and readonly
* states.
* @param {!Blockly.Action} action The current action.
* @return {boolean} True if the action has been handled, false otherwise.
*/
@@ -775,92 +775,44 @@ Blockly.navigation.onBlocklyAction = function(action) {
/**
* Handles the action or dispatches to the appropriate action handler.
* @param {!Blockly.Action} action The current action
* @param {!Blockly.Action} action The action to handle.
* @return {boolean} True if the action has been handled, false otherwise.
* @private
*/
Blockly.navigation.handleActions_ = function(action) {
var workspace = Blockly.getMainWorkspace();
if (action.name === Blockly.navigation.actionNames.TOGGLE_KEYBOARD_NAV) {
if (action.name == Blockly.navigation.actionNames.TOOLBOX ||
Blockly.navigation.currentState_ == Blockly.navigation.STATE_TOOLBOX) {
return Blockly.navigation.toolboxOnAction_(action);
} else if (action.name == Blockly.navigation.actionNames.TOGGLE_KEYBOARD_NAV) {
Blockly.navigation.disableKeyboardAccessibility();
return true;
} else if (action.name === Blockly.navigation.actionNames.TOOLBOX) {
if (!workspace.getToolbox()) {
Blockly.navigation.focusFlyout_();
} else {
Blockly.navigation.focusToolbox_();
}
return true;
} else if (Blockly.navigation.currentState_ === Blockly.navigation.STATE_WS) {
var curNode = workspace.getCursor().getCurNode();
var actionHandled = false;
if (curNode && curNode.getType() === Blockly.ASTNode.types.FIELD) {
actionHandled = curNode.getLocation().onBlocklyAction(action);
}
if (!actionHandled) {
actionHandled = Blockly.navigation.workspaceOnAction_(action);
}
return actionHandled;
} else if (Blockly.navigation.currentState_ === Blockly.navigation.STATE_FLYOUT) {
} if (Blockly.navigation.currentState_ == Blockly.navigation.STATE_WS) {
return Blockly.navigation.workspaceOnAction_(action);
} else if (Blockly.navigation.currentState_ == Blockly.navigation.STATE_FLYOUT) {
return Blockly.navigation.flyoutOnAction_(action);
} else if (Blockly.navigation.currentState_ === Blockly.navigation.STATE_TOOLBOX) {
return Blockly.navigation.toolboxOnAction_(action);
}
return false;
};
/**
* Handle all actions performed on the workspace.
* @param {!Blockly.Action} action The action to handle.
* @return {boolean} True if the action has been handled, false otherwise.
* @private
*/
Blockly.navigation.workspaceOnAction_ = function(action) {
var workspace = Blockly.getMainWorkspace();
switch (action.name) {
case Blockly.navigation.actionNames.PREVIOUS:
workspace.getCursor().prev();
return true;
case Blockly.navigation.actionNames.OUT:
workspace.getCursor().out();
return true;
case Blockly.navigation.actionNames.NEXT:
workspace.getCursor().next();
return true;
case Blockly.navigation.actionNames.IN:
workspace.getCursor().in();
return true;
case Blockly.navigation.actionNames.INSERT:
Blockly.navigation.modify_();
return true;
case Blockly.navigation.actionNames.MARK:
Blockly.navigation.handleEnterForWS_();
return true;
case Blockly.navigation.actionNames.DISCONNECT:
Blockly.navigation.disconnectBlocks_();
return true;
default:
return false;
}
};
/**
* Handle all actions performed on the flyout.
* Handles the given action for the flyout.
* @param {!Blockly.Action} action The action to handle.
* @return {boolean} True if the action has been handled, false otherwise.
* @private
*/
Blockly.navigation.flyoutOnAction_ = function(action) {
var workspace = Blockly.getMainWorkspace();
var toolbox = workspace.getToolbox();
var flyout = toolbox ? toolbox.flyout_ : workspace.getFlyout();
if (flyout && flyout.onBlocklyAction(action)) {
return true;
}
switch (action.name) {
case Blockly.navigation.actionNames.PREVIOUS:
Blockly.navigation.getFlyoutCursor_().prev();
return true;
case Blockly.navigation.actionNames.OUT:
Blockly.navigation.focusToolbox_();
return true;
case Blockly.navigation.actionNames.NEXT:
Blockly.navigation.getFlyoutCursor_().next();
return true;
case Blockly.navigation.actionNames.MARK:
Blockly.navigation.insertFromFlyout();
return true;
@@ -873,24 +825,60 @@ Blockly.navigation.flyoutOnAction_ = function(action) {
};
/**
* Handle all actions performeed on the toolbox.
* Handles the given action for the toolbox.
* @param {!Blockly.Action} action The action to handle.
* @return {boolean} True if the action has been handled, false otherwise.
* @private
*/
Blockly.navigation.toolboxOnAction_ = function(action) {
if (action.name === Blockly.navigation.actionNames.EXIT) {
Blockly.navigation.focusWorkspace_();
return true;
}
var toolbox = Blockly.getMainWorkspace().getToolbox();
var handled = toolbox.onBlocklyAction(action);
if (!handled && action.name === Blockly.navigation.actionNames.IN) {
Blockly.navigation.focusFlyout_();
var workspace = Blockly.getMainWorkspace();
var toolbox = workspace.getToolbox();
var handled = toolbox ? toolbox.onBlocklyAction(action) : false;
if (handled) {
return true;
}
return handled;
if (action.name === Blockly.navigation.actionNames.TOOLBOX) {
if (!workspace.getToolbox()) {
Blockly.navigation.focusFlyout_();
} else {
Blockly.navigation.focusToolbox_();
}
return true;
} else if (action.name === Blockly.navigation.actionNames.IN) {
Blockly.navigation.focusFlyout_();
return true;
} else if (action.name === Blockly.navigation.actionNames.EXIT) {
Blockly.navigation.focusWorkspace_();
return true;
}
return false;
};
/**
* Handles the given action for the workspace.
* @param {!Blockly.Action} action The action to handle.
* @return {boolean} True if the action has been handled, false otherwise.
* @private
*/
Blockly.navigation.workspaceOnAction_ = function(action) {
if (Blockly.getMainWorkspace().getCursor().onBlocklyAction(action)) {
return true;
}
switch (action.name) {
case Blockly.navigation.actionNames.INSERT:
Blockly.navigation.modify_();
return true;
case Blockly.navigation.actionNames.MARK:
Blockly.navigation.handleEnterForWS_();
return true;
case Blockly.navigation.actionNames.DISCONNECT:
Blockly.navigation.disconnectBlocks_();
return true;
default:
return false;
}
};
/**

View File

@@ -136,6 +136,27 @@ Blockly.blockRendering.ConstantProvider = function() {
*/
this.JAGGED_TEETH_WIDTH = 6;
/**
* Point size of text. Should match blocklyText's font-size in CSS.
* @type {number}
* @const
*/
this.FIELD_TEXT_FONTSIZE = 11;
/**
* Text font weight. Should match blocklyText's font-weight in CSS.
* @type {string}
* @const
*/
this.FIELD_TEXT_FONTWEIGHT = 'normal';
/**
* Text font family. Should match blocklyText's font-family in CSS.
* @type {string}
* @const
*/
this.FIELD_TEXT_FONTFAMILY = 'sans-serif';
/**
* The ID of the emboss filter, or the empty string if no filter is set.
* @type {string}

View File

@@ -111,3 +111,12 @@ Blockly.blockRendering.IPathObject.prototype.updateInsertionMarker;
* @package
*/
Blockly.blockRendering.IPathObject.prototype.updateMovable;
/**
* Add or remove styling that shows that if the dragging block is dropped, this
* block will be replaced. If a shadow block, it will disappear. Otherwise it
* will bump.
* @param {boolean} enable True if styling should be added.
* @package
*/
Blockly.blockRendering.IPathObject.prototype.updateReplacementHighlight;

View File

@@ -451,6 +451,12 @@ Blockly.blockRendering.RenderInfo.prototype.addElemSpacing_ = function() {
* @protected
*/
Blockly.blockRendering.RenderInfo.prototype.getInRowSpacing_ = function(prev, next) {
if (!prev) {
// Statement input padding.
if (next && Blockly.blockRendering.Types.isStatementInput(next)) {
return this.constants_.STATEMENT_INPUT_PADDING_LEFT;
}
}
// Between inputs and the end of the row.
if (prev && Blockly.blockRendering.Types.isInput(prev) && !next) {
if (Blockly.blockRendering.Types.isExternalInput(prev)) {

View File

@@ -221,3 +221,15 @@ Blockly.blockRendering.PathObject.prototype.updateMovable = function(enable) {
this.setClass_('blocklyDraggable', enable);
};
/**
* Add or remove styling that shows that if the dragging block is dropped, this
* block will be replaced. If a shadow block, it will disappear. Otherwise it
* will bump.
* @param {boolean} enable True if styling should be added.
* @package
*/
Blockly.blockRendering.PathObject.prototype.updateReplacementHighlight =
function(enable) {
/* eslint-disable indent */
this.setClass_('blocklyReplaceable', enable);
}; /* eslint-enable indent */

View File

@@ -41,6 +41,26 @@ Blockly.zelos.ConstantProvider = function() {
this.GRID_UNIT = 4;
/**
* @override
*/
this.SMALL_PADDING = this.GRID_UNIT;
/**
* @override
*/
this.MEDIUM_PADDING = 2 * this.GRID_UNIT;
/**
* @override
*/
this.MEDIUM_LARGE_PADDING = 3 * this.GRID_UNIT;
/**
* @override
*/
this.LARGE_PADDING = 4 * this.GRID_UNIT;
/**
* @override
*/
@@ -76,10 +96,21 @@ Blockly.zelos.ConstantProvider = function() {
*/
this.STATEMENT_BOTTOM_SPACER = -this.NOTCH_HEIGHT;
/**
* Minimum statement input spacer width.
* @type {number}
*/
this.STATEMENT_INPUT_SPACER_MIN_WIDTH = 30 * this.GRID_UNIT;
/**
* @override
*/
this.AFTER_STATEMENT_BOTTOM_ROW_MIN_HEIGHT = this.LARGE_PADDING * 2;
this.STATEMENT_INPUT_PADDING_LEFT = 4 * this.GRID_UNIT;
/**
* @override
*/
this.AFTER_STATEMENT_BOTTOM_ROW_MIN_HEIGHT = 7 * this.GRID_UNIT;
/**
* @override
@@ -91,6 +122,11 @@ Blockly.zelos.ConstantProvider = function() {
*/
this.EMPTY_INLINE_INPUT_HEIGHT = 8 * this.GRID_UNIT;
/**
* @override
*/
this.DUMMY_INPUT_MIN_HEIGHT = 6 * this.GRID_UNIT;
/**
* The ID of the highlight glow filter, or the empty string if no filter is
* set.

View File

@@ -109,148 +109,6 @@ Blockly.zelos.RenderInfo.prototype.computeBounds_ = function() {
}
};
/**
* @override
*/
Blockly.zelos.RenderInfo.prototype.getInRowSpacing_ = function(prev, next) {
if (!prev || !next) {
// No need for padding at the beginning or end of the row if the
// output shape is dynamic.
if (this.outputConnection && this.outputConnection.isDynamicShape) {
return this.constants_.NO_PADDING;
}
}
if (!prev) {
// Between an editable field and the beginning of the row.
if (next && Blockly.blockRendering.Types.isField(next) && next.isEditable) {
return this.constants_.MEDIUM_PADDING;
}
// Inline input at the beginning of the row.
if (next && Blockly.blockRendering.Types.isInlineInput(next)) {
return this.constants_.MEDIUM_LARGE_PADDING;
}
if (next && Blockly.blockRendering.Types.isStatementInput(next)) {
return this.constants_.STATEMENT_INPUT_PADDING_LEFT;
}
// Anything else at the beginning of the row.
return this.constants_.LARGE_PADDING;
}
// Spacing between a non-input and the end of the row.
if (!Blockly.blockRendering.Types.isInput(prev) && !next) {
// Between an editable field and the end of the row.
if (Blockly.blockRendering.Types.isField(prev) && prev.isEditable) {
return this.constants_.MEDIUM_PADDING;
}
// Padding at the end of an icon-only row to make the block shape clearer.
if (Blockly.blockRendering.Types.isIcon(prev)) {
return (this.constants_.LARGE_PADDING * 2) + 1;
}
if (Blockly.blockRendering.Types.isHat(prev)) {
return this.constants_.NO_PADDING;
}
// Establish a minimum width for a block with a previous or next connection.
if (Blockly.blockRendering.Types.isPreviousOrNextConnection(prev)) {
return this.constants_.LARGE_PADDING;
}
// Between rounded corner and the end of the row.
if (Blockly.blockRendering.Types.isLeftRoundedCorner(prev)) {
return this.constants_.MIN_BLOCK_WIDTH;
}
// Between a jagged edge and the end of the row.
if (Blockly.blockRendering.Types.isJaggedEdge(prev)) {
return this.constants_.NO_PADDING;
}
// Between noneditable fields and icons and the end of the row.
return this.constants_.LARGE_PADDING;
}
// Between inputs and the end of the row.
if (Blockly.blockRendering.Types.isInput(prev) && !next) {
if (Blockly.blockRendering.Types.isExternalInput(prev)) {
return this.constants_.NO_PADDING;
} else if (Blockly.blockRendering.Types.isInlineInput(prev)) {
return this.constants_.LARGE_PADDING;
} else if (Blockly.blockRendering.Types.isStatementInput(prev)) {
return this.constants_.NO_PADDING;
}
}
// Spacing between a non-input and an input.
if (!Blockly.blockRendering.Types.isInput(prev) &&
next && Blockly.blockRendering.Types.isInput(next)) {
// Between an editable field and an input.
if (prev.isEditable) {
if (Blockly.blockRendering.Types.isInlineInput(next)) {
return this.constants_.MEDIUM_PADDING;
} else if (Blockly.blockRendering.Types.isExternalInput(next)) {
return this.constants_.MEDIUM_PADDING;
}
} else {
if (Blockly.blockRendering.Types.isInlineInput(next)) {
return this.constants_.MEDIUM_LARGE_PADDING;
} else if (Blockly.blockRendering.Types.isExternalInput(next)) {
return this.constants_.MEDIUM_LARGE_PADDING;
} else if (Blockly.blockRendering.Types.isStatementInput(next)) {
return this.constants_.LARGE_PADDING;
}
}
return this.constants_.LARGE_PADDING - 1;
}
// Spacing between an icon and an icon or field.
if (Blockly.blockRendering.Types.isIcon(prev) &&
next && !Blockly.blockRendering.Types.isInput(next)) {
return this.constants_.LARGE_PADDING;
}
// Spacing between an inline input and a field.
if (Blockly.blockRendering.Types.isInlineInput(prev) &&
next && !Blockly.blockRendering.Types.isInput(next)) {
// Editable field after inline input.
if (next.isEditable) {
return this.constants_.MEDIUM_PADDING;
} else {
// Noneditable field after inline input.
return this.constants_.LARGE_PADDING;
}
}
if (Blockly.blockRendering.Types.isLeftSquareCorner(prev) && next) {
// Spacing between a hat and a corner
if (Blockly.blockRendering.Types.isHat(next)) {
return this.constants_.NO_PADDING;
}
// Spacing between a square corner and a previous or next connection
if (Blockly.blockRendering.Types.isPreviousConnection(next) ||
Blockly.blockRendering.Types.isNextConnection(next)) {
return next.notchOffset;
}
}
// Spacing between a rounded corner and a previous or next connection.
if (Blockly.blockRendering.Types.isLeftRoundedCorner(prev) && next) {
if (Blockly.blockRendering.Types.isPreviousConnection(next) ||
Blockly.blockRendering.Types.isNextConnection(next)) {
return next.notchOffset - this.constants_.CORNER_RADIUS;
}
}
// Spacing between two fields of the same editability.
if (!Blockly.blockRendering.Types.isInput(prev) &&
next && !Blockly.blockRendering.Types.isInput(next) &&
(prev.isEditable == next.isEditable)) {
return this.constants_.LARGE_PADDING;
}
// Spacing between anything and a jagged edge.
if (next && Blockly.blockRendering.Types.isJaggedEdge(next)) {
return this.constants_.LARGE_PADDING;
}
return this.constants_.MEDIUM_PADDING;
};
/**
* @override
*/
@@ -291,10 +149,10 @@ Blockly.zelos.RenderInfo.prototype.getSpacerRowHeight_ = function(
return this.constants_.EMPTY_BLOCK_SPACER_HEIGHT;
}
// Top and bottom rows act as a spacer so we don't need any extra padding.
if ((Blockly.blockRendering.Types.isTopRow(prev) && !prev.hasPreviousConnection)) {
if ((Blockly.blockRendering.Types.isTopRow(prev))) {
return this.constants_.NO_PADDING;
}
if ((Blockly.blockRendering.Types.isBottomRow(next) && !next.hasNextConnection)) {
if ((Blockly.blockRendering.Types.isBottomRow(next))) {
return this.constants_.NO_PADDING;
}
return this.constants_.MEDIUM_PADDING;

View File

@@ -81,7 +81,7 @@ Blockly.TouchGesture = function(e, creatorWorkspace) {
* A handle to use to unbind the second touch start or pointer down listener
* at the end of a drag.
* Opaque data returned from Blockly.bindEventWithChecks_.
* @type {Array.<!Array>}
* @type {?Blockly.EventData}
* @private
*/
this.onStartWrapper_ = null;

View File

@@ -49,6 +49,21 @@ goog.require('Blockly.WorkspaceComment');
*/
Blockly.WorkspaceCommentSvg = function(workspace, content, height, width,
opt_id) {
/**
* Mouse up event data.
* @type {?Blockly.EventData}
* @private
*/
this.onMouseUpWrapper_ = null;
/**
* Mouse move event data.
* @type {?Blockly.EventData}
* @private
*/
this.onMouseMoveWrapper_ = null;
// Create core elements for the block.
/**
* @type {SVGElement}

View File

@@ -1874,7 +1874,7 @@ Blockly.WorkspaceSvg.prototype.setBrowserFocus = function() {
}
try {
// Focus the workspace SVG - this is for Chrome and Firefox.
this.getParentSvg().focus();
this.getParentSvg().focus({preventScroll:true});
} catch (e) {
// IE and Edge do not support focus on SVG elements. When that fails
// above, get the injectionDiv (the workspace's parent) and focus that
@@ -1886,7 +1886,7 @@ Blockly.WorkspaceSvg.prototype.setBrowserFocus = function() {
} catch (e) {
// setActive support was discontinued in Edge so when that fails, call
// focus instead.
this.getParentSvg().parentNode.focus();
this.getParentSvg().parentNode.focus({preventScroll:true});
}
}
};

View File

@@ -39,6 +39,20 @@ var CustomFields = CustomFields || {};
*/
CustomFields.FieldPitch = function(text) {
CustomFields.FieldPitch.superClass_.constructor.call(this, text);
/**
* Click event data.
* @type {?Blockly.EventData}
* @private
*/
this.clickWrapper_ = null;
/**
* Move event data.
* @type {?Blockly.EventData}
* @private
*/
this.moveWrapper_ = null;
};
Blockly.utils.object.inherits(CustomFields.FieldPitch, Blockly.FieldTextInput);
@@ -112,8 +126,15 @@ CustomFields.FieldPitch.prototype.dropdownCreate_ = function() {
* @private
*/
CustomFields.FieldPitch.prototype.dropdownDispose_ = function() {
Blockly.unbindEvent_(this.clickWrapper_);
Blockly.unbindEvent_(this.moveWrapper_);
if (this.clickWrapper_) {
Blockly.unbindEvent_(this.clickWrapper_);
this.clickWrapper_ = null;
}
if (this.moveWrapper_) {
Blockly.unbindEvent_(this.moveWrapper_);
this.moveWrapper_ = null;
}
this.imageElement_ = null;
};
/**

26
externs/goog-externs.js Normal file
View File

@@ -0,0 +1,26 @@
/**
* @license
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Externs for goog.
* @externs
*/
/**
* @type {!Object}
*/
var goog = {};

View File

@@ -32,8 +32,10 @@ var path = require('path');
var fs = require('fs');
var rimraf = require('rimraf');
var execSync = require('child_process').execSync;
var through2 = require('through2');
var closureCompiler = require('google-closure-compiler').gulp();
var closureDeps = require('google-closure-deps');
var packageJson = require('./package.json');
var argv = require('yargs').argv;
@@ -183,7 +185,7 @@ gulp.task('build-core', function () {
dependency_mode: 'PRUNE',
entry_point: './core-requires.js',
js_output_file: 'blockly_compressed.js',
externs: './externs/svg-externs.js',
externs: ['./externs/svg-externs.js', './externs/goog-externs.js'],
define: defines
}, argv.verbose, argv.strict))
.pipe(prependHeader())
@@ -217,6 +219,7 @@ goog.provide('Blockly.Warning');`;
.pipe(stripApacheLicense())
.pipe(compile({
dependency_mode: 'NONE',
externs: ['./externs/goog-externs.js'],
js_output_file: 'blocks_compressed.js'
}, argv.verbose, argv.strict))
.pipe(gulp.replace('\'use strict\';', '\'use strict\';\n\n\n'))
@@ -245,6 +248,7 @@ goog.provide('Blockly.utils.string');`;
`${provides}goog.provide('Blockly.${namespace}');`))
.pipe(compile({
dependency_mode: 'NONE',
externs: ['./externs/goog-externs.js'],
js_output_file: `${language}_compressed.js`
}, argv.verbose, argv.strict))
.pipe(gulp.replace('\'use strict\';', '\'use strict\';\n\n\n'))
@@ -338,27 +342,37 @@ if (this.IS_NODE_JS) {
document.write('<script>this.BLOCKLY_BOOT(this);</script>');
}
`;
const file = 'blockly_uncompressed.js';
// Run depswriter.py and which scans the core directory and writes out a ``goog.addDependency`` line for each file.
const cmd = `python ./node_modules/google-closure-library/closure/bin/build/depswriter.py \
--root_with_prefix="./core ../core" > ${file}`;
execSync(cmd, { stdio: 'inherit' });
const requires = `goog.addDependency("base.js", [], []);\n\n// Load Blockly.\ngoog.require('Blockly.requires')\n`;
let deps = [];
return gulp.src('core/**/**/*.js')
.pipe(through2.obj((file, _enc, cb) => {
deps.push(closureDeps.parser.parseFile(file.path).dependency);
cb(null);
}))
.on('end', () => {
const graph = new closureDeps.depGraph.Graph(deps);
let addDependency = [];
graph.depsByPath.forEach(dep => {
addDependency.push('goog.addDependency(' + [
'"' + path.relative('./closure/goog', dep.path) + '"',
'[' + dep.closureSymbols
.map(s => `'${s}'`).join(', ') + ']',
'[' + dep.imports
.map(i => i.symOrPath)
.filter(i => i !== 'goog')
.sort()
.map(i => `'${i}'`).join(', ') + ']',
].join(', ') + ');');
});
const requires = `
goog.addDependency("base.js", [], []);
return gulp.src(file)
// Remove comments so we're compatible with the build.py script
.pipe(gulp.replace(/\/\/.*\n/gm, ''))
// Replace quotes to be compatible with build.py
.pipe(gulp.replace(/\'(.*\.js)\'/gm, '"$1"'))
// Remove last parameter to be compatible with build.py
.pipe(gulp.replace(/, \{\}\);/gm, ');'))
// Find the Blockly directory name and replace it with a JS variable.
// This allows blockly_uncompressed.js to be compiled on one computer and be
// used on another, even if the directory name differs.
.pipe(gulp.replace(/\.\.\/core/gm, `../../core`))
.pipe(gulp.insert.wrap(header, requires + footer))
.pipe(gulp.dest('./'));
// Load Blockly.
goog.require('Blockly.requires')
`;
fs.writeFileSync('blockly_uncompressed.js',
header + addDependency.join('\n') + requires + footer);
});
});
/**

View File

@@ -31,6 +31,7 @@
"RENAME_VARIABLE": "Преименувај променлива...",
"RENAME_VARIABLE_TITLE": "Преименувај ги сите променливи „%1“ во:",
"NEW_VARIABLE": "Создај променлива...",
"NEW_STRING_VARIABLE": "Создај променлива на низа...",
"NEW_VARIABLE_TYPE_TITLE": "Тип на новата променлива:",
"NEW_VARIABLE_TITLE": "Назив на новата променлива:",
"VARIABLE_ALREADY_EXISTS": "Променлива со име '%1' веќе постои.",
@@ -66,13 +67,16 @@
"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "излези од јамката",
"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "продолжи со следното повторување на јамката",
"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Излези од содржечката јамка.",
"CONTROLS_IF_TOOLTIP_1": "Ако вредноста е вистинита, исполни некои наредби.",
"CONTROLS_IF_MSG_IF": "ако",
"CONTROLS_IF_MSG_ELSEIF": "инаку ако",
"CONTROLS_IF_MSG_ELSE": "инаку",
"CONTROLS_IF_IF_TOOLTIP": "Додава, отстранува или прередува делови за прераспоредување на овој блок „ако“.",
"CONTROLS_IF_ELSEIF_TOOLTIP": "Додај услов кон „ако“ блокот.",
"IOS_OK": "ОК",
"IOS_CANCEL": "Откажи",
"IOS_ERROR": "Грешка",
"IOS_PROCEDURES_ADD_INPUT": "+ Додај влез",
"IOS_PROCEDURES_ALLOW_STATEMENTS": "Дозволи тврдења",
"IOS_VARIABLES_ADD_VARIABLE": "+ Додај променлива",
"IOS_VARIABLES_ADD_BUTTON": "Додај",
@@ -139,17 +143,34 @@
"MATH_ONLIST_TOOLTIP_MEDIAN": "Дава медијана од броевите на списокот.",
"MATH_ONLIST_OPERATOR_MODE": "модул на списокот",
"MATH_ONLIST_TOOLTIP_MODE": "Дава список на најзастапен(и) елемент(и) на списокот.",
"MATH_ONLIST_OPERATOR_RANDOM": "случајна ставка од списокот",
"TEXT_JOIN_TITLE_CREATEWITH": "создај текст со",
"TEXT_CREATE_JOIN_TITLE_JOIN": "поврзи",
"TEXT_CREATE_JOIN_TOOLTIP": "Додај, отстрани или пререди ги деловите за прераспоредување на овој блок „текст“.",
"TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Додај ставка кон текстот.",
"TEXT_LENGTH_TITLE": "должина на %1",
"TEXT_ISEMPTY_TITLE": "%1 е празен",
"TEXT_INDEXOF_TITLE": "во текст %1 %2 %3",
"TEXT_CHARAT_TITLE": "во текст %1 %2",
"TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "во текстот",
"TEXT_COUNT_MESSAGE0": "пресметка на %1 во %2",
"TEXT_REPLACE_MESSAGE0": "замени го %1 со %2 во %3",
"LISTS_CREATE_EMPTY_TITLE": "создај празен список",
"LISTS_CREATE_WITH_INPUT_WITH": "создај список со",
"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "список",
"LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Додај, отстрани или пререди ги деловите за прераспоредување на овој блок „список“.",
"LISTS_CREATE_WITH_ITEM_TOOLTIP": "Додај ставка кон списокот.",
"LISTS_LENGTH_TITLE": "должина на %1",
"LISTS_ISEMPTY_TITLE": "%1 е празен",
"LISTS_INLIST": "во списокот",
"LISTS_GET_INDEX_REMOVE": "отстрани",
"LISTS_GET_INDEX_FROM_END": "# од крајот",
"LISTS_GET_INDEX_FIRST": "прв",
"LISTS_GET_INDEX_LAST": "последен",
"LISTS_GET_INDEX_RANDOM": "случаен",
"LISTS_SET_INDEX_SET": "задај",
"LISTS_SET_INDEX_INSERT": "вметни на",
"LISTS_SET_INDEX_INPUT_TO": "како",
"LISTS_SORT_TITLE": "подреди %1 %2 %3",
"VARIABLES_GET_CREATE_SET": "Создај „задавање на %1“",
"VARIABLES_SET": "задај %1 на %2",
@@ -161,6 +182,7 @@
"PROCEDURES_DEFRETURN_RETURN": "назад",
"PROCEDURES_ALLOW_STATEMENTS": "дозволи тврдења",
"PROCEDURES_CALLNORETURN_HELPURL": "https://mk.wikipedia.org/wiki/Потпрограма",
"PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Додај, отстрани или пренареди ги влезните параметри за оваа функција.",
"PROCEDURES_CREATE_DO": "Создај го '%1'",
"WORKSPACE_ARIA_LABEL": "Работен простор на Blockly"
}

View File

@@ -18,7 +18,8 @@
"佛壁灯",
"Htq110219891",
"Ambeta",
"A Chinese Wikipedian"
"A Chinese Wikipedian",
"沈澄心"
]
},
"VARIABLES_DEFAULT_NAME": "项目",
@@ -376,5 +377,6 @@
"PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause",
"PROCEDURES_IFRETURN_WARNING": "警告:这个块只能在函数内部使用。",
"WORKSPACE_COMMENT_DEFAULT_TEXT": "说点什么...",
"WORKSPACE_ARIA_LABEL": "Blockly工作区",
"COLLAPSED_WARNINGS_WARNING": "已收起的信息块内包含警告。"
}

View File

@@ -11,7 +11,8 @@
"Dnowba",
"Dnow",
"和平至上",
"Jessica1213"
"Jessica1213",
"沈澄心"
]
},
"VARIABLES_DEFAULT_NAME": "項目",
@@ -357,6 +358,6 @@
"PROCEDURES_IFRETURN_TOOLTIP": "如果值為 true則返回第二個值。",
"PROCEDURES_IFRETURN_WARNING": "警告:這個區塊只可以在定義函式時使用。",
"WORKSPACE_COMMENT_DEFAULT_TEXT": "來說些事情...",
"WORKSPACE_ARIA_LABEL": "Blockly 工作區",
"WORKSPACE_ARIA_LABEL": "Blockly工作區",
"COLLAPSED_WARNINGS_WARNING": "收合含有警告的區塊。"
}

269
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "blockly",
"version": "2.20190722.0-develop",
"version": "3.20191014.0-develop",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -2105,6 +2105,18 @@
"requires": {
"graceful-fs": "^4.1.11",
"through2": "^2.0.3"
},
"dependencies": {
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dev": true,
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
}
}
},
"fs.realpath": {
@@ -2815,17 +2827,17 @@
}
},
"google-closure-compiler": {
"version": "20190618.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20190618.0.0.tgz",
"integrity": "sha512-f5zJQSWnlawuQlGo9TxcuprBGxIS5ksikj/pjDxdlRTXWt3dOKqEFA3CN8QshNYDl6oEjtO/ehiNx64fqEgkUA==",
"version": "20191027.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20191027.0.0.tgz",
"integrity": "sha512-W8MVm/fUg6pPVDHbkP2R8HmeLXNVkjhQHwFpikAhRnF8znhjn7e78V+VXYUiOnjBwDGP1/We1sGk4QGMYY2UfA==",
"dev": true,
"requires": {
"chalk": "2.x",
"google-closure-compiler-java": "^20190618.0.0",
"google-closure-compiler-js": "^20190618.0.0",
"google-closure-compiler-linux": "^20190618.0.0",
"google-closure-compiler-osx": "^20190618.0.0",
"google-closure-compiler-windows": "^20190618.0.0",
"google-closure-compiler-java": "^20191027.0.0",
"google-closure-compiler-js": "^20191027.0.0",
"google-closure-compiler-linux": "^20191027.0.0",
"google-closure-compiler-osx": "^20191027.0.0",
"google-closure-compiler-windows": "^20191027.0.0",
"minimist": "1.x",
"vinyl": "2.x",
"vinyl-sourcemaps-apply": "^0.2.0"
@@ -2840,43 +2852,144 @@
}
},
"google-closure-compiler-java": {
"version": "20190618.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20190618.0.0.tgz",
"integrity": "sha512-y6gAyJHMH5k2SM0qj/lyErEjmFGMvcT3glcx5Lsrl99CGwImJY0gDi+Cy9S0pczZvLG+wUW33AEfEW9MtdRZ6A==",
"version": "20191027.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20191027.0.0.tgz",
"integrity": "sha512-3C0bRnXOp9yYbb6Qm0FqWm53xDmuRRB90tAA57rYzpreZg96Kxz2moVGcoYBh4jFlBkLIywHjV+AWYMaXA3lSQ==",
"dev": true
},
"google-closure-compiler-js": {
"version": "20190618.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-js/-/google-closure-compiler-js-20190618.0.0.tgz",
"integrity": "sha512-Xc/84uN00GLUzRwWx25Lg11VuSTz/1odWy0d+pM3F/26fXqi16ZhhkVoe6VVFklSSMVDyGTPAH0ZkyfZhinKhA==",
"version": "20191027.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-js/-/google-closure-compiler-js-20191027.0.0.tgz",
"integrity": "sha512-D3UHBQ0fbPl3VZ2BDK4OWfqDzp/q1FywwEQBbC2qrEKa6Q1wYJRSSY21z+xwscQ1qyPHZjdqIIPXTBrnJvP0WQ==",
"dev": true
},
"google-closure-compiler-linux": {
"version": "20190618.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20190618.0.0.tgz",
"integrity": "sha512-idWJ/sFmOSYfCmDbCVMcaBX2NCUCxukjt2UzT5PJmpoVLmJuwwoVbpQZVfvgRvEH4bLzvvcvJRfn5nIiODjjaQ==",
"version": "20191027.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20191027.0.0.tgz",
"integrity": "sha512-zWg+3UdqhsFOkP895azl9ioFOx+JZVFHdETZwhO59PA+zTNTulZqDCX6wqq8YFRoO3HKvYfedUp7Cp+jdaELnA==",
"dev": true,
"optional": true
},
"google-closure-compiler-osx": {
"version": "20190618.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20190618.0.0.tgz",
"integrity": "sha512-OzXMW+hKq76NJt9MIRQhV7pHTzHISCXtg+LZUPcqNT+V/tcvOlrSaflokmvyJPzEVk889QArYp8JgZ7mqHuY5g==",
"version": "20191027.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20191027.0.0.tgz",
"integrity": "sha512-Ko/+43oeMD8u6MhKMGPhx61B5e2lR5+C9pzlhnibQwuXuDVcp2ruFbblhWBXiT2FrStTX65SZzFvza0bRVYikA==",
"dev": true,
"optional": true
},
"google-closure-compiler-windows": {
"version": "20190618.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20190618.0.0.tgz",
"integrity": "sha512-2qzY/fQneEg+zFvRGoNeJkAY6VU5OcmBT37l+xTBGQvy/AauCLWltSGcOYNEi7Qd3OEBVIcAJ+CzNOV9s3jfwA==",
"version": "20191027.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20191027.0.0.tgz",
"integrity": "sha512-kAzGFGaeAL9qsieotjb5qq5SsYD2Vwtl7aCeIVUnzWyNfhz7WZCmAMSGwGdtaShfM+4uzOwG1mahtPWasTaBxg==",
"dev": true,
"optional": true
},
"google-closure-library": {
"version": "20190618.0.0",
"resolved": "https://registry.npmjs.org/google-closure-library/-/google-closure-library-20190618.0.0.tgz",
"integrity": "sha512-V0RbatvAmCfdOTeTXXbXklGU1hgPus8YkpjyaMBmoCcajgtk9vL+SsRhD1Ntk6QNkbzD9WGKLdyovMw7NJ8VnA==",
"dev": true
"google-closure-deps": {
"version": "20190121.0.0",
"resolved": "https://registry.npmjs.org/google-closure-deps/-/google-closure-deps-20190121.0.0.tgz",
"integrity": "sha512-UdFzI/6sQt2q66GFO9M/DRw/F5dk8TY7JRav54jsK+VORRoTfjH99xvHqEva4BOZ2+JdzG9IoTcH0nyIOAbxfQ==",
"dev": true,
"requires": {
"argparse": "^1.0.9",
"google-closure-compiler": "^20181008.0.0",
"yargs": "^12.0.2"
},
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"dev": true
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"dev": true,
"requires": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
}
},
"google-closure-compiler": {
"version": "20181008.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20181008.0.0.tgz",
"integrity": "sha512-XmJIasXHyy4kirthlsuDev2LZcXjYXWfOHwHdCLUQnfJH8T2sxWDNjFLQycaCIXwQLOyw2Kem38VgxrYfG0hzg==",
"dev": true,
"requires": {
"chalk": "^1.0.0",
"google-closure-compiler-linux": "^20181008.0.0",
"google-closure-compiler-osx": "^20181008.0.0",
"minimist": "^1.2.0",
"vinyl": "^2.0.1",
"vinyl-sourcemaps-apply": "^0.2.0"
}
},
"google-closure-compiler-linux": {
"version": "20181008.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20181008.0.0.tgz",
"integrity": "sha512-k8njGfH2uzWJiRPPvUxM7MJB28gPrf4kI2bbuiF0gJk/1arXcWCPGjLD6pzCU0UylMy52MUXLgsIpRorqf2brw==",
"dev": true,
"optional": true
},
"google-closure-compiler-osx": {
"version": "20181008.0.0",
"resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20181008.0.0.tgz",
"integrity": "sha512-xzf/yH/4MXdb6GbP84iHnpcVCOPBbH0gMVOs0JhR/KbrQh+DlJU+Y8Z/DQzTkw9HgD650R2/WZmBknURyg9OTw==",
"dev": true,
"optional": true
},
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
"dev": true
},
"yargs": {
"version": "12.0.5",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
"integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
"dev": true,
"requires": {
"cliui": "^4.0.0",
"decamelize": "^1.2.0",
"find-up": "^3.0.0",
"get-caller-file": "^1.0.1",
"os-locale": "^3.0.0",
"require-directory": "^2.1.1",
"require-main-filename": "^1.0.1",
"set-blocking": "^2.0.0",
"string-width": "^2.0.0",
"which-module": "^2.0.0",
"y18n": "^3.2.1 || ^4.0.0",
"yargs-parser": "^11.1.1"
}
}
}
},
"graceful-fs": {
"version": "4.2.2",
@@ -3063,6 +3176,18 @@
"concat-with-sourcemaps": "^1.0.0",
"through2": "^2.0.0",
"vinyl": "^2.0.0"
},
"dependencies": {
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dev": true,
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
}
}
},
"gulp-insert": {
@@ -3158,6 +3283,18 @@
"concat-stream": "^1.6.2",
"lodash.template": "^4.4.0",
"through2": "^2.0.3"
},
"dependencies": {
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dev": true,
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
}
}
},
"gulplog": {
@@ -3192,6 +3329,23 @@
"function-bind": "^1.1.1"
}
},
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true
}
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -5210,6 +5364,18 @@
"remove-bom-buffer": "^3.0.0",
"safe-buffer": "^5.1.0",
"through2": "^2.0.3"
},
"dependencies": {
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dev": true,
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
}
}
},
"remove-trailing-separator": {
@@ -6102,13 +6268,12 @@
"dev": true
},
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz",
"integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==",
"dev": true,
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
"readable-stream": "2 || 3"
}
},
"through2-filter": {
@@ -6119,6 +6284,18 @@
"requires": {
"through2": "~2.0.0",
"xtend": "~4.0.0"
},
"dependencies": {
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dev": true,
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
}
}
},
"time-stamp": {
@@ -6195,6 +6372,18 @@
"dev": true,
"requires": {
"through2": "^2.0.3"
},
"dependencies": {
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dev": true,
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
}
}
},
"tough-cookie": {
@@ -6511,6 +6700,18 @@
"value-or-function": "^3.0.0",
"vinyl": "^2.0.0",
"vinyl-sourcemap": "^1.1.0"
},
"dependencies": {
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dev": true,
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
}
}
},
"vinyl-sourcemap": {

View File

@@ -55,8 +55,8 @@
"eslint": "^5.13.0",
"eslint-plugin-es5": "^1.4.1",
"fs": "0.0.1-security",
"google-closure-compiler": "^20190618.0.0",
"google-closure-library": "^20190618.0.0",
"google-closure-compiler": "^20191027.0.0",
"google-closure-deps": "20190121.0.0",
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-insert": "^0.5.0",
@@ -71,6 +71,7 @@
"pngjs": "^3.4.0",
"selenium-standalone": "^6.16.0",
"rimraf": "^2.6.3",
"through2": "^3.0.1",
"typescript-closure-tools": "^0.0.7",
"webdriverio": "^5.11.5",
"yargs": "^14.0.0"

View File

@@ -78,6 +78,7 @@ COMPILATION_COMMAND="java -jar $COMPILER --js='$BLOCKLY_ROOT/tests/compile/main.
--js='$BLOCKLY_ROOT/blocks/**.js' \
--js='$BLOCKLY_ROOT/generators/**.js' \
--generate_exports \
--externs $BLOCKLY_ROOT/externs/goog-externs.js \
--externs $BLOCKLY_ROOT/externs/svg-externs.js \
--compilation_level ADVANCED_OPTIMIZATIONS \
--language_in ECMASCRIPT5_STRICT \

View File

@@ -228,6 +228,11 @@ suite('Text Input Fields', function() {
scale: 1
}
};
field.constants_ = {
FIELD_TEXT_FONTSIZE: 11,
FIELD_TEXT_FONTWEIGHT: 'normal',
FIELD_TEXT_FONTFAMILY: 'sans-serif'
};
Blockly.WidgetDiv.DIV = document.createElement('div');
this.stub = sinon.stub(field, 'resizeEditor_');
};

View File

@@ -54,8 +54,9 @@ function svgToPng_(data, width, height, callback) {
* Create an SVG of the blocks on the workspace.
* @param {!Blockly.WorkspaceSvg} workspace The workspace.
* @param {!Function} callback Callback.
* @param {string=} customCss Custom CSS to append to the SVG.
*/
function workspaceToSvg_(workspace, callback) {
function workspaceToSvg_(workspace, callback, customCss) {
// Go through all text areas and set their value.
var textAreas = document.getElementsByTagName("textarea");
@@ -87,7 +88,7 @@ function workspaceToSvg_(workspace, callback) {
var css = [].slice.call(document.head.querySelectorAll('style'))
.filter(function(el) { return /\.blocklySvg/.test(el.innerText); })[0];
var style = document.createElement('style');
style.innerHTML = css.innerText;
style.innerHTML = css.innerText + '\n' + customCss;
svg.insertBefore(style, svg.firstChild);
var svgAsXML = (new XMLSerializer).serializeToString(svg);

View File

@@ -37,6 +37,10 @@
width: 100%;
height: 500px;
}
.output {
height: 500px;
}
</style>
</head>
@@ -145,6 +149,18 @@
<iframe id="pxtblockly" src="./pxtblockly.html"></iframe>
</div>
</div>
<div class="row">
<div class="col">
<div id="zelosout">
<h2>Zelos Rendering</h2>
<img id="zelosoutput" class="output" />
</div>
<div id="pxtblocklyout">
<h2>PXT-Blockly Rendering</h2>
<img id="pxtblocklyoutput" class="output" />
</div>
</div>
</div>
</div>
<script type="text/javascript">
@@ -156,6 +172,25 @@
selector.value = hash.substring(1);
}
window.addEventListener('message', function (msg) {
var data = msg.data;
if (data.type === 'svg') {
var output = document.getElementById(data.from + 'output');
output.src = data.text;
}
});
var current = 'zelos';
var pause = false;
document.getElementById('pxtblocklyout').style.display = 'none';
setInterval(function () {
if (!pause) {
document.getElementById(current + 'out').style.display = 'none';
current = current == 'zelos' ? 'pxtblockly' : 'zelos';
document.getElementById(current + 'out').style.display = 'block';
}
}, 1000);
pxtblockly.addEventListener('load', function () {
updateWorkspaces(selector.value);
});
@@ -179,8 +214,14 @@
if (rawFile.status === 200 || rawFile.status == 0) {
var xml = rawFile.responseText;
if (xml) {
pxtblockly.contentWindow.postMessage(xml, '*');
zelos.contentWindow.postMessage(xml, '*');
pxtblockly.contentWindow.postMessage({
type: 'post',
xml: xml
}, '*');
zelos.contentWindow.postMessage({
type: 'post',
xml: xml
}, '*');
}
}
}
@@ -195,10 +236,12 @@
} else if (e.keyCode === 39) {
selector.selectedIndex = selector.selectedIndex + 1;
updateWorkspaces(selector.value);
} else if (e.keyCode === 32) {
pause = !pause;
}
});
</script>
</body>
</html>
</html>

View File

@@ -4,6 +4,7 @@
<script type="text/javascript" src="https://unpkg.com/pxt-blockly@2.1.12/blockly_compressed.js"></script>
<script type="text/javascript" src="https://unpkg.com/pxt-blockly@2.1.12/blocks_compressed.js"></script>
<script type="text/javascript" src="https://unpkg.com/pxt-blockly@2.1.12/msg/messages.js"></script>
<script type="text/javascript" src="../../playgrounds/screenshot.js"></script>
</head>
<body>
@@ -12,7 +13,11 @@
var blocklyDiv = document.getElementById('blocklyDiv');
var workspace;
window.addEventListener('message', function (msg) {
var xml = msg.data;
var data = msg.data;
if (data.type !== 'post') {
return;
}
var xml = data.xml;
try {
if (workspace) {
workspace.dispose();
@@ -26,13 +31,25 @@
drag: true,
wheel: false,
},
zoom: {
wheel: true,
startScale: 2,
}
});
try {
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xml), workspace);
var topBlock = workspace.getTopBlocks()[0];
workspaceToSvg_(workspace, function (datauri) {
window.parent.postMessage({
type: 'svg',
from: 'pxtblockly',
text: datauri
}, '*');
});
} catch { }
});
</script>
</body>
</html>
</html>

View File

@@ -4,13 +4,26 @@
<script type="text/javascript" src="../../../blockly_uncompressed.js"></script>
<script type="text/javascript" src="https://unpkg.com/pxt-blockly@2.1.12/blocks_compressed.js"></script>
<script type="text/javascript" src="https://unpkg.com/pxt-blockly@2.1.12/msg/messages.js"></script>
<script type="text/javascript" src="../../playgrounds/screenshot.js"></script>
<style>
.blocklyText {
<style id="blocklycss">
.blocklyText,
.blocklyHtmlInput {
font-family: "Helvetica Neue", "Segoe UI", Helvetica, sans-serif;
font-weight: bold;
font-size: 12pt;
}
.blocklyNonEditableText>text,
.blocklyEditableText>text,
.blocklyNonEditableText>g>text,
.blocklyEditableText>g>text {
fill: #575E75;
}
.blocklyHtmlInput {
color: #575E75;
}
</style>
</head>
@@ -26,7 +39,11 @@
var blocklyDiv = document.getElementById('blocklyDiv');
var workspace;
window.addEventListener('message', function (msg) {
var xml = msg.data;
var data = msg.data;
if (data.type !== 'post') {
return;
}
var xml = data.xml;
try {
if (workspace) {
workspace.dispose();
@@ -41,11 +58,25 @@
drag: true,
wheel: false,
},
zoom: {
wheel: true,
startScale: 2,
}
});
try {
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xml), workspace);
} catch { }
var topBlock = workspace.getTopBlocks()[0];
workspaceToSvg_(workspace, function (datauri) {
window.parent.postMessage({
type: 'svg',
from: 'zelos',
text: datauri
}, '*');
}, document.getElementById('blocklycss').innerText);
} catch (err) {
console.error(err);
}
});
</script>
</body>