diff --git a/core/field_label.js b/core/field_label.js index 5dc434c92..822d476ab 100644 --- a/core/field_label.js +++ b/core/field_label.js @@ -11,13 +11,14 @@ */ 'use strict'; -goog.provide('Blockly.FieldLabel'); +goog.module('Blockly.FieldLabel'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Field'); -goog.require('Blockly.fieldRegistry'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.object'); +const Field = goog.require('Blockly.Field'); +const dom = goog.require('Blockly.utils.dom'); +const fieldRegistry = goog.require('Blockly.fieldRegistry'); +const {inherits} = goog.require('Blockly.utils.object'); +const {replaceMessageReferences} = goog.require('Blockly.utils'); /** @@ -26,12 +27,13 @@ goog.require('Blockly.utils.object'); * string. Defaults to an empty string if null or undefined. * @param {string=} opt_class Optional CSS class for the field's text. * @param {Object=} opt_config A map of options used to configure the field. - * See the [field creation documentation]{@link https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/label#creation} + * See the [field creation documentation]{@link + * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/label#creation} * for a list of properties this parameter supports. - * @extends {Blockly.Field} + * @extends {Field} * @constructor */ -Blockly.FieldLabel = function(opt_value, opt_class, opt_config) { +const FieldLabel = function(opt_value, opt_class, opt_config) { /** * The html class name to use for this field. * @type {?string} @@ -39,32 +41,31 @@ Blockly.FieldLabel = function(opt_value, opt_class, opt_config) { */ this.class_ = null; - Blockly.FieldLabel.superClass_.constructor.call( - this, opt_value, null, opt_config); + FieldLabel.superClass_.constructor.call(this, opt_value, null, opt_config); if (!opt_config) { // If the config was not passed use old configuration. this.class_ = opt_class || null; } }; -Blockly.utils.object.inherits(Blockly.FieldLabel, Blockly.Field); +inherits(FieldLabel, Field); /** * The default value for this field. * @type {*} * @protected */ -Blockly.FieldLabel.prototype.DEFAULT_VALUE = ''; +FieldLabel.prototype.DEFAULT_VALUE = ''; /** * Construct a FieldLabel from a JSON arg object, * dereferencing any string table references. * @param {!Object} options A JSON object with options (text, and class). - * @return {!Blockly.FieldLabel} The new field instance. + * @return {!FieldLabel} The new field instance. * @package * @nocollapse */ -Blockly.FieldLabel.fromJson = function(options) { - var text = Blockly.utils.replaceMessageReferences(options['text']); +FieldLabel.fromJson = function(options) { + const text = replaceMessageReferences(options['text']); // `this` might be a subclass of FieldLabel if that class doesn't override // the static fromJson method. return new this(text, undefined, options); @@ -75,13 +76,13 @@ Blockly.FieldLabel.fromJson = function(options) { * editable. This field should not. * @type {boolean} */ -Blockly.FieldLabel.prototype.EDITABLE = false; +FieldLabel.prototype.EDITABLE = false; /** * @override */ -Blockly.FieldLabel.prototype.configure_ = function(config) { - Blockly.FieldLabel.superClass_.configure_.call(this, config); +FieldLabel.prototype.configure_ = function(config) { + FieldLabel.superClass_.configure_.call(this, config); this.class_ = config['class']; }; @@ -89,10 +90,10 @@ Blockly.FieldLabel.prototype.configure_ = function(config) { * Create block UI for this label. * @package */ -Blockly.FieldLabel.prototype.initView = function() { +FieldLabel.prototype.initView = function() { this.createTextElement_(); if (this.class_) { - Blockly.utils.dom.addClass( + dom.addClass( /** @type {!SVGTextElement} */ (this.textElement_), this.class_); } }; @@ -103,7 +104,7 @@ Blockly.FieldLabel.prototype.initView = function() { * @return {?string} A valid string, or null if invalid. * @protected */ -Blockly.FieldLabel.prototype.doClassValidation_ = function(opt_newValue) { +FieldLabel.prototype.doClassValidation_ = function(opt_newValue) { if (opt_newValue === null || opt_newValue === undefined) { return null; } @@ -114,18 +115,20 @@ Blockly.FieldLabel.prototype.doClassValidation_ = function(opt_newValue) { * Set the CSS class applied to the field's textElement_. * @param {?string} cssClass The new CSS class name, or null to remove. */ -Blockly.FieldLabel.prototype.setClass = function(cssClass) { +FieldLabel.prototype.setClass = function(cssClass) { if (this.textElement_) { // This check isn't necessary, but it's faster than letting removeClass // figure it out. if (this.class_) { - Blockly.utils.dom.removeClass(this.textElement_, this.class_); + dom.removeClass(this.textElement_, this.class_); } if (cssClass) { - Blockly.utils.dom.addClass(this.textElement_, cssClass); + dom.addClass(this.textElement_, cssClass); } } this.class_ = cssClass; }; -Blockly.fieldRegistry.register('field_label', Blockly.FieldLabel); +fieldRegistry.register('field_label', FieldLabel); + +exports = FieldLabel; diff --git a/core/field_textinput.js b/core/field_textinput.js index b2153b65e..cfa891e34 100644 --- a/core/field_textinput.js +++ b/core/field_textinput.js @@ -10,27 +10,30 @@ */ 'use strict'; -goog.provide('Blockly.FieldTextInput'); +goog.module('Blockly.FieldTextInput'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.browserEvents'); -goog.require('Blockly.DropDownDiv'); -goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +const DropDownDiv = goog.require('Blockly.DropDownDiv'); +const Events = goog.require('Blockly.Events'); +const Field = goog.require('Blockly.Field'); +const KeyCodes = goog.require('Blockly.utils.KeyCodes'); +const Msg = goog.require('Blockly.Msg'); +const WidgetDiv = goog.require('Blockly.WidgetDiv'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +const aria = goog.require('Blockly.utils.aria'); +const browserEvents = goog.require('Blockly.browserEvents'); +const dom = goog.require('Blockly.utils.dom'); +const fieldRegistry = goog.require('Blockly.fieldRegistry'); +const userAgent = goog.require('Blockly.utils.userAgent'); +const {inherits} = goog.require('Blockly.utils.object'); +const {prompt: blocklyPrompt} = goog.require('Blockly'); +const {replaceMessageReferences} = goog.require('Blockly.utils'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockChange'); -goog.require('Blockly.Field'); -goog.require('Blockly.fieldRegistry'); -goog.require('Blockly.Msg'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.aria'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.KeyCodes'); -goog.require('Blockly.utils.object'); -goog.require('Blockly.utils.userAgent'); -goog.require('Blockly.WidgetDiv'); - -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.WorkspaceSvg'); /** @@ -41,12 +44,13 @@ goog.requireType('Blockly.WorkspaceSvg'); * changes to the field's value. Takes in a string & returns a validated * string, or null to abort the change. * @param {Object=} opt_config A map of options used to configure the field. - * See the [field creation documentation]{@link https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/text-input#creation} + * See the [field creation documentation]{@link + * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/text-input#creation} * for a list of properties this parameter supports. - * @extends {Blockly.Field} + * @extends {Field} * @constructor */ -Blockly.FieldTextInput = function(opt_value, opt_validator, opt_config) { +const FieldTextInput = function(opt_value, opt_validator, opt_config) { /** * Allow browser to spellcheck this field. * @type {boolean} @@ -54,8 +58,8 @@ Blockly.FieldTextInput = function(opt_value, opt_validator, opt_config) { */ this.spellcheck_ = true; - Blockly.FieldTextInput.superClass_.constructor.call(this, - opt_value, opt_validator, opt_config); + FieldTextInput.superClass_.constructor.call( + this, opt_value, opt_validator, opt_config); /** * The HTML input element. @@ -65,14 +69,14 @@ Blockly.FieldTextInput = function(opt_value, opt_validator, opt_config) { /** * Key down event data. - * @type {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @private */ this.onKeyDownWrapper_ = null; /** * Key input event data. - * @type {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @private */ this.onKeyInputWrapper_ = null; @@ -86,30 +90,30 @@ Blockly.FieldTextInput = function(opt_value, opt_validator, opt_config) { /** * The workspace that this field belongs to. - * @type {?Blockly.WorkspaceSvg} + * @type {?WorkspaceSvg} * @protected */ this.workspace_ = null; }; -Blockly.utils.object.inherits(Blockly.FieldTextInput, Blockly.Field); +inherits(FieldTextInput, Field); /** * The default value for this field. * @type {*} * @protected */ -Blockly.FieldTextInput.prototype.DEFAULT_VALUE = ''; +FieldTextInput.prototype.DEFAULT_VALUE = ''; /** * Construct a FieldTextInput from a JSON arg object, * dereferencing any string table references. * @param {!Object} options A JSON object with options (text, and spellcheck). - * @return {!Blockly.FieldTextInput} The new field instance. + * @return {!FieldTextInput} The new field instance. * @package * @nocollapse */ -Blockly.FieldTextInput.fromJson = function(options) { - var text = Blockly.utils.replaceMessageReferences(options['text']); +FieldTextInput.fromJson = function(options) { + const text = replaceMessageReferences(options['text']); // `this` might be a subclass of FieldTextInput if that class doesn't override // the static fromJson method. return new this(text, undefined, options); @@ -120,24 +124,24 @@ Blockly.FieldTextInput.fromJson = function(options) { * are not. Editable fields should also be serializable. * @type {boolean} */ -Blockly.FieldTextInput.prototype.SERIALIZABLE = true; +FieldTextInput.prototype.SERIALIZABLE = true; /** * Pixel size of input border radius. * Should match blocklyText's border-radius in CSS. */ -Blockly.FieldTextInput.BORDERRADIUS = 4; +FieldTextInput.BORDERRADIUS = 4; /** * Mouse cursor style when over the hotspot that initiates the editor. */ -Blockly.FieldTextInput.prototype.CURSOR = 'text'; +FieldTextInput.prototype.CURSOR = 'text'; /** * @override */ -Blockly.FieldTextInput.prototype.configure_ = function(config) { - Blockly.FieldTextInput.superClass_.configure_.call(this, config); +FieldTextInput.prototype.configure_ = function(config) { + FieldTextInput.superClass_.configure_.call(this, config); if (typeof config['spellcheck'] == 'boolean') { this.spellcheck_ = config['spellcheck']; } @@ -146,17 +150,17 @@ Blockly.FieldTextInput.prototype.configure_ = function(config) { /** * @override */ -Blockly.FieldTextInput.prototype.initView = function() { +FieldTextInput.prototype.initView = function() { if (this.getConstants().FULL_BLOCK_FIELDS) { // Step one: figure out if this is the only field on this block. // Rendering is quite different in that case. - var nFields = 0; - var nConnections = 0; + let nFields = 0; + let nConnections = 0; // Count the number of fields, excluding text fields - for (var i = 0, input; (input = this.sourceBlock_.inputList[i]); i++) { - for (var j = 0; (input.fieldRow[j]); j++) { - nFields ++; + for (let i = 0, input; (input = this.sourceBlock_.inputList[i]); i++) { + for (let j = 0; (input.fieldRow[j]); j++) { + nFields++; } if (input.connection) { nConnections++; @@ -184,7 +188,7 @@ Blockly.FieldTextInput.prototype.initView = function() { * @return {*} A valid string, or null if invalid. * @protected */ -Blockly.FieldTextInput.prototype.doClassValidation_ = function(opt_newValue) { +FieldTextInput.prototype.doClassValidation_ = function(opt_newValue) { if (opt_newValue === null || opt_newValue === undefined) { return null; } @@ -200,15 +204,16 @@ Blockly.FieldTextInput.prototype.doClassValidation_ = function(opt_newValue) { * the htmlInput_. * @protected */ -Blockly.FieldTextInput.prototype.doValueInvalid_ = function(_invalidValue) { +FieldTextInput.prototype.doValueInvalid_ = function(_invalidValue) { if (this.isBeingEdited_) { this.isTextValid_ = false; - var oldValue = this.value_; + const oldValue = this.value_; // Revert value when the text becomes invalid. this.value_ = this.htmlInput_.untypedDefaultValue_; - if (this.sourceBlock_ && Blockly.Events.isEnabled()) { - Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.BLOCK_CHANGE))( - this.sourceBlock_, 'field', this.name || null, oldValue, this.value_)); + if (this.sourceBlock_ && Events.isEnabled()) { + Events.fire(new (Events.get(Events.BLOCK_CHANGE))( + this.sourceBlock_, 'field', this.name || null, oldValue, + this.value_)); } } }; @@ -221,7 +226,7 @@ Blockly.FieldTextInput.prototype.doValueInvalid_ = function(_invalidValue) { * that this is a string. * @protected */ -Blockly.FieldTextInput.prototype.doValueUpdate_ = function(newValue) { +FieldTextInput.prototype.doValueUpdate_ = function(newValue) { this.isTextValid_ = true; this.value_ = newValue; if (!this.isBeingEdited_) { @@ -234,14 +239,14 @@ Blockly.FieldTextInput.prototype.doValueUpdate_ = function(newValue) { * Updates text field to match the colour/style of the block. * @package */ -Blockly.FieldTextInput.prototype.applyColour = function() { +FieldTextInput.prototype.applyColour = function() { if (this.sourceBlock_ && this.getConstants().FULL_BLOCK_FIELDS) { if (this.borderRect_) { - this.borderRect_.setAttribute('stroke', - this.sourceBlock_.style.colourTertiary); + this.borderRect_.setAttribute( + 'stroke', this.sourceBlock_.style.colourTertiary); } else { - this.sourceBlock_.pathObject.svgPath.setAttribute('fill', - this.getConstants().FIELD_BORDER_RECT_COLOUR); + this.sourceBlock_.pathObject.svgPath.setAttribute( + 'fill', this.getConstants().FIELD_BORDER_RECT_COLOUR); } } }; @@ -251,21 +256,19 @@ Blockly.FieldTextInput.prototype.applyColour = function() { * field's value. * @protected */ -Blockly.FieldTextInput.prototype.render_ = function() { - Blockly.FieldTextInput.superClass_.render_.call(this); +FieldTextInput.prototype.render_ = function() { + FieldTextInput.superClass_.render_.call(this); // This logic is done in render_ rather than doValueInvalid_ or // doValueUpdate_ so that the code is more centralized. if (this.isBeingEdited_) { this.resizeEditor_(); - var htmlInput = /** @type {!HTMLElement} */(this.htmlInput_); + const htmlInput = /** @type {!HTMLElement} */ (this.htmlInput_); if (!this.isTextValid_) { - Blockly.utils.dom.addClass(htmlInput, 'blocklyInvalidInput'); - Blockly.utils.aria.setState(htmlInput, - Blockly.utils.aria.State.INVALID, true); + dom.addClass(htmlInput, 'blocklyInvalidInput'); + aria.setState(htmlInput, aria.State.INVALID, true); } else { - Blockly.utils.dom.removeClass(htmlInput, 'blocklyInvalidInput'); - Blockly.utils.aria.setState(htmlInput, - Blockly.utils.aria.State.INVALID, false); + dom.removeClass(htmlInput, 'blocklyInvalidInput'); + aria.setState(htmlInput, aria.State.INVALID, false); } } }; @@ -274,7 +277,7 @@ Blockly.FieldTextInput.prototype.render_ = function() { * Set whether this field is spellchecked by the browser. * @param {boolean} check True if checked. */ -Blockly.FieldTextInput.prototype.setSpellcheck = function(check) { +FieldTextInput.prototype.setSpellcheck = function(check) { if (check == this.spellcheck_) { return; } @@ -292,14 +295,11 @@ Blockly.FieldTextInput.prototype.setSpellcheck = function(check) { * focus. Defaults to false. * @protected */ -Blockly.FieldTextInput.prototype.showEditor_ = function(_opt_e, - opt_quietInput) { - this.workspace_ = - (/** @type {!Blockly.BlockSvg} */ (this.sourceBlock_)).workspace; - var quietInput = opt_quietInput || false; - if (!quietInput && (Blockly.utils.userAgent.MOBILE || - Blockly.utils.userAgent.ANDROID || - Blockly.utils.userAgent.IPAD)) { +FieldTextInput.prototype.showEditor_ = function(_opt_e, opt_quietInput) { + this.workspace_ = (/** @type {!BlockSvg} */ (this.sourceBlock_)).workspace; + const quietInput = opt_quietInput || false; + if (!quietInput && + (userAgent.MOBILE || userAgent.ANDROID || userAgent.IPAD)) { this.showPromptEditor_(); } else { this.showInlineEditor_(quietInput); @@ -311,11 +311,10 @@ Blockly.FieldTextInput.prototype.showEditor_ = function(_opt_e, * Mobile browsers have issues with in-line textareas (focus and keyboards). * @private */ -Blockly.FieldTextInput.prototype.showPromptEditor_ = function() { - Blockly.prompt(Blockly.Msg['CHANGE_VALUE_TITLE'], this.getText(), - function(text) { - this.setValue(this.getValueFromEditorText_(text)); - }.bind(this)); +FieldTextInput.prototype.showPromptEditor_ = function() { + blocklyPrompt(Msg['CHANGE_VALUE_TITLE'], this.getText(), function(text) { + this.setValue(this.getValueFromEditorText_(text)); + }.bind(this)); }; /** @@ -324,14 +323,13 @@ Blockly.FieldTextInput.prototype.showPromptEditor_ = function() { * focus. * @private */ -Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) { - Blockly.WidgetDiv.show( - this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this)); +FieldTextInput.prototype.showInlineEditor_ = function(quietInput) { + WidgetDiv.show(this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this)); this.htmlInput_ = this.widgetCreate_(); this.isBeingEdited_ = true; if (!quietInput) { - this.htmlInput_.focus({preventScroll:true}); + this.htmlInput_.focus({preventScroll: true}); this.htmlInput_.select(); } }; @@ -341,38 +339,37 @@ Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) { * @return {!HTMLElement} The newly created text input editor. * @protected */ -Blockly.FieldTextInput.prototype.widgetCreate_ = function() { - Blockly.Events.setGroup(true); - var div = Blockly.WidgetDiv.DIV; +FieldTextInput.prototype.widgetCreate_ = function() { + Events.setGroup(true); + const div = WidgetDiv.DIV; - Blockly.utils.dom.addClass(this.getClickTarget_(), 'editing'); + dom.addClass(this.getClickTarget_(), 'editing'); - var htmlInput = /** @type {HTMLInputElement} */ (document.createElement('input')); + const htmlInput = + /** @type {HTMLInputElement} */ (document.createElement('input')); htmlInput.className = 'blocklyHtmlInput'; htmlInput.setAttribute('spellcheck', this.spellcheck_); - var scale = this.workspace_.getScale(); - var fontSize = - (this.getConstants().FIELD_TEXT_FONTSIZE * scale) + 'pt'; + const scale = this.workspace_.getScale(); + const fontSize = (this.getConstants().FIELD_TEXT_FONTSIZE * scale) + 'pt'; div.style.fontSize = fontSize; htmlInput.style.fontSize = fontSize; - var borderRadius = - (Blockly.FieldTextInput.BORDERRADIUS * scale) + 'px'; + let borderRadius = (FieldTextInput.BORDERRADIUS * scale) + 'px'; if (this.fullBlockClickTarget_) { - var bBox = this.getScaledBBox(); + const bBox = this.getScaledBBox(); // Override border radius. borderRadius = (bBox.bottom - bBox.top) / 2 + 'px'; // Pull stroke colour from the existing shadow block - var strokeColour = this.sourceBlock_.getParent() ? - this.sourceBlock_.getParent().style.colourTertiary : - this.sourceBlock_.style.colourTertiary; + const strokeColour = this.sourceBlock_.getParent() ? + this.sourceBlock_.getParent().style.colourTertiary : + this.sourceBlock_.style.colourTertiary; htmlInput.style.border = (1 * scale) + 'px solid ' + strokeColour; div.style.borderRadius = borderRadius; div.style.transition = 'box-shadow 0.25s ease 0s'; if (this.getConstants().FIELD_TEXTINPUT_BOX_SHADOW) { - div.style.boxShadow = 'rgba(255, 255, 255, 0.3) 0 0 0 ' + - (4 * scale) + 'px'; + div.style.boxShadow = + 'rgba(255, 255, 255, 0.3) 0 0 0 ' + (4 * scale) + 'px'; } } htmlInput.style.borderRadius = borderRadius; @@ -395,7 +392,7 @@ Blockly.FieldTextInput.prototype.widgetCreate_ = function() { * DOM-references belonging to the editor. * @protected */ -Blockly.FieldTextInput.prototype.widgetDispose_ = function() { +FieldTextInput.prototype.widgetDispose_ = function() { // Non-disposal related things that we do when the editor closes. this.isBeingEdited_ = false; this.isTextValid_ = true; @@ -405,11 +402,11 @@ Blockly.FieldTextInput.prototype.widgetDispose_ = function() { if (this.onFinishEditing_) { this.onFinishEditing_(this.value_); } - Blockly.Events.setGroup(false); + Events.setGroup(false); // Actual disposal. this.unbindInputEvents_(); - var style = Blockly.WidgetDiv.DIV.style; + const style = WidgetDiv.DIV.style; style.width = 'auto'; style.height = 'auto'; style.fontSize = ''; @@ -417,7 +414,7 @@ Blockly.FieldTextInput.prototype.widgetDispose_ = function() { style.boxShadow = ''; this.htmlInput_ = null; - Blockly.utils.dom.removeClass(this.getClickTarget_(), 'editing'); + dom.removeClass(this.getClickTarget_(), 'editing'); }; /** @@ -426,12 +423,12 @@ Blockly.FieldTextInput.prototype.widgetDispose_ = function() { * handlers will be bound. * @protected */ -Blockly.FieldTextInput.prototype.bindInputEvents_ = function(htmlInput) { +FieldTextInput.prototype.bindInputEvents_ = function(htmlInput) { // Trap Enter without IME and Esc to hide. - this.onKeyDownWrapper_ = Blockly.browserEvents.conditionalBind( + this.onKeyDownWrapper_ = browserEvents.conditionalBind( htmlInput, 'keydown', this, this.onHtmlInputKeyDown_); // Resize after every input change. - this.onKeyInputWrapper_ = Blockly.browserEvents.conditionalBind( + this.onKeyInputWrapper_ = browserEvents.conditionalBind( htmlInput, 'input', this, this.onHtmlInputChange_); }; @@ -439,13 +436,13 @@ Blockly.FieldTextInput.prototype.bindInputEvents_ = function(htmlInput) { * Unbind handlers for user input and workspace size changes. * @protected */ -Blockly.FieldTextInput.prototype.unbindInputEvents_ = function() { +FieldTextInput.prototype.unbindInputEvents_ = function() { if (this.onKeyDownWrapper_) { - Blockly.browserEvents.unbind(this.onKeyDownWrapper_); + browserEvents.unbind(this.onKeyDownWrapper_); this.onKeyDownWrapper_ = null; } if (this.onKeyInputWrapper_) { - Blockly.browserEvents.unbind(this.onKeyInputWrapper_); + browserEvents.unbind(this.onKeyInputWrapper_); this.onKeyInputWrapper_ = null; } }; @@ -455,17 +452,17 @@ Blockly.FieldTextInput.prototype.unbindInputEvents_ = function() { * @param {!Event} e Keyboard event. * @protected */ -Blockly.FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) { - if (e.keyCode == Blockly.utils.KeyCodes.ENTER) { - Blockly.WidgetDiv.hide(); - Blockly.DropDownDiv.hideWithoutAnimation(); - } else if (e.keyCode == Blockly.utils.KeyCodes.ESC) { +FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) { + if (e.keyCode == KeyCodes.ENTER) { + WidgetDiv.hide(); + DropDownDiv.hideWithoutAnimation(); + } else if (e.keyCode == KeyCodes.ESC) { this.setValue(this.htmlInput_.untypedDefaultValue_); - Blockly.WidgetDiv.hide(); - Blockly.DropDownDiv.hideWithoutAnimation(); - } else if (e.keyCode == Blockly.utils.KeyCodes.TAB) { - Blockly.WidgetDiv.hide(); - Blockly.DropDownDiv.hideWithoutAnimation(); + WidgetDiv.hide(); + DropDownDiv.hideWithoutAnimation(); + } else if (e.keyCode == KeyCodes.TAB) { + WidgetDiv.hide(); + DropDownDiv.hideWithoutAnimation(); this.sourceBlock_.tab(this, !e.shiftKey); e.preventDefault(); } @@ -476,12 +473,12 @@ Blockly.FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) { * @param {!Event} _e Keyboard event. * @private */ -Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(_e) { - var text = this.htmlInput_.value; +FieldTextInput.prototype.onHtmlInputChange_ = function(_e) { + const text = this.htmlInput_.value; if (text !== this.htmlInput_.oldValue_) { this.htmlInput_.oldValue_ = text; - var value = this.getValueFromEditorText_(text); + const value = this.getValueFromEditorText_(text); this.setValue(value); this.forceRerender(); this.resizeEditor_(); @@ -495,7 +492,7 @@ Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(_e) { * @param {*} newValue New value. * @protected */ -Blockly.FieldTextInput.prototype.setEditorValue_ = function(newValue) { +FieldTextInput.prototype.setEditorValue_ = function(newValue) { this.isDirty_ = true; if (this.isBeingEdited_) { // In the case this method is passed an invalid value, we still @@ -511,16 +508,16 @@ Blockly.FieldTextInput.prototype.setEditorValue_ = function(newValue) { * Resize the editor to fit the text. * @protected */ -Blockly.FieldTextInput.prototype.resizeEditor_ = function() { - var div = Blockly.WidgetDiv.DIV; - var bBox = this.getScaledBBox(); +FieldTextInput.prototype.resizeEditor_ = function() { + const div = WidgetDiv.DIV; + const bBox = this.getScaledBBox(); div.style.width = bBox.right - bBox.left + 'px'; div.style.height = bBox.bottom - bBox.top + 'px'; // In RTL mode block fields and LTR input fields the left edge moves, // whereas the right edge is fixed. Reposition the editor. - var x = this.sourceBlock_.RTL ? bBox.right - div.offsetWidth : bBox.left; - var xy = new Blockly.utils.Coordinate(x, bBox.top); + const x = this.sourceBlock_.RTL ? bBox.right - div.offsetWidth : bBox.left; + const xy = new Coordinate(x, bBox.top); div.style.left = xy.x + 'px'; div.style.top = xy.y + 'px'; @@ -531,20 +528,20 @@ Blockly.FieldTextInput.prototype.resizeEditor_ = function() { * @return {boolean} True if the field is tab navigable. * @override */ -Blockly.FieldTextInput.prototype.isTabNavigable = function() { +FieldTextInput.prototype.isTabNavigable = function() { return true; }; /** - * Use the `getText_` developer hook to override the field's text representation. - * When we're currently editing, return the current HTML value instead. - * Otherwise, return null which tells the field to use the default behaviour - * (which is a string cast of the field's value). + * Use the `getText_` developer hook to override the field's text + * representation. When we're currently editing, return the current HTML value + * instead. Otherwise, return null which tells the field to use the default + * behaviour (which is a string cast of the field's value). * @return {?string} The HTML value if we're editing, otherwise null. * @protected * @override */ -Blockly.FieldTextInput.prototype.getText_ = function() { +FieldTextInput.prototype.getText_ = function() { if (this.isBeingEdited_ && this.htmlInput_) { // We are currently editing, return the HTML input value instead. return this.htmlInput_.value; @@ -561,7 +558,7 @@ Blockly.FieldTextInput.prototype.getText_ = function() { * @return {string} The text to show on the HTML input. * @protected */ -Blockly.FieldTextInput.prototype.getEditorText_ = function(value) { +FieldTextInput.prototype.getEditorText_ = function(value) { return String(value); }; @@ -575,8 +572,10 @@ Blockly.FieldTextInput.prototype.getEditorText_ = function(value) { * @return {*} The value to store. * @protected */ -Blockly.FieldTextInput.prototype.getValueFromEditorText_ = function(text) { +FieldTextInput.prototype.getValueFromEditorText_ = function(text) { return text; }; -Blockly.fieldRegistry.register('field_input', Blockly.FieldTextInput); +fieldRegistry.register('field_input', FieldTextInput); + +exports = FieldTextInput; diff --git a/core/field_variable.js b/core/field_variable.js index f700d4a99..f4ae38a51 100644 --- a/core/field_variable.js +++ b/core/field_variable.js @@ -13,9 +13,12 @@ goog.module('Blockly.FieldVariable'); goog.module.declareLegacyNamespace(); +/* eslint-disable-next-line no-unused-vars */ const Block = goog.requireType('Blockly.Block'); const FieldDropdown = goog.require('Blockly.FieldDropdown'); +/* eslint-disable-next-line no-unused-vars */ const Menu = goog.requireType('Blockly.Menu'); +/* eslint-disable-next-line no-unused-vars */ const MenuItem = goog.requireType('Blockly.MenuItem'); const Msg = goog.require('Blockly.Msg'); const Size = goog.require('Blockly.utils.Size'); diff --git a/core/flyout_base.js b/core/flyout_base.js index 84d6d3870..594d83a9f 100644 --- a/core/flyout_base.js +++ b/core/flyout_base.js @@ -10,62 +10,67 @@ */ 'use strict'; -goog.provide('Blockly.Flyout'); +goog.module('Blockly.Flyout'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Block'); +/* eslint-disable-next-line no-unused-vars */ +const Block = goog.require('Blockly.Block'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +const ComponentManager = goog.require('Blockly.ComponentManager'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +const DeleteArea = goog.require('Blockly.DeleteArea'); +const Events = goog.require('Blockly.Events'); +const FlyoutButton = goog.require('Blockly.FlyoutButton'); +const FlyoutMetricsManager = goog.require('Blockly.FlyoutMetricsManager'); +/* eslint-disable-next-line no-unused-vars */ +const IFlyout = goog.require('Blockly.IFlyout'); +/* eslint-disable-next-line no-unused-vars */ +const Options = goog.requireType('Blockly.Options'); +const ScrollbarPair = goog.require('Blockly.ScrollbarPair'); +const Svg = goog.require('Blockly.utils.Svg'); +const Tooltip = goog.require('Blockly.Tooltip'); +const Variables = goog.require('Blockly.Variables'); +const WorkspaceSvg = goog.require('Blockly.WorkspaceSvg'); +const Xml = goog.require('Blockly.Xml'); +const browserEvents = goog.require('Blockly.browserEvents'); +const dom = goog.require('Blockly.utils.dom'); +const toolbox = goog.require('Blockly.utils.toolbox'); +const utils = goog.require('Blockly.utils'); +const utilsXml = goog.require('Blockly.utils.xml'); +const {hideChaff} = goog.require('Blockly'); /** @suppress {extraRequire} */ goog.require('Blockly.blockRendering'); -goog.require('Blockly.browserEvents'); -goog.require('Blockly.ComponentManager'); -goog.require('Blockly.DeleteArea'); -goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockCreate'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.VarCreate'); -goog.require('Blockly.FlyoutMetricsManager'); /** @suppress {extraRequire} */ goog.require('Blockly.Gesture'); -goog.require('Blockly.IFlyout'); -goog.require('Blockly.ScrollbarPair'); -goog.require('Blockly.Tooltip'); /** @suppress {extraRequire} */ goog.require('Blockly.Touch'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.Svg'); -goog.require('Blockly.utils.toolbox'); -goog.require('Blockly.utils.xml'); -goog.require('Blockly.WorkspaceSvg'); -goog.require('Blockly.Xml'); - -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.FlyoutButton'); -goog.requireType('Blockly.Options'); -goog.requireType('Blockly.utils.Rect'); /** * Class for a flyout. - * @param {!Blockly.Options} workspaceOptions Dictionary of options for the + * @param {!Options} workspaceOptions Dictionary of options for the * workspace. * @constructor * @abstract - * @implements {Blockly.IFlyout} - * @extends {Blockly.DeleteArea} + * @implements {IFlyout} + * @extends {DeleteArea} */ -Blockly.Flyout = function(workspaceOptions) { - Blockly.Flyout.superClass_.constructor.call(this); +const Flyout = function(workspaceOptions) { + Flyout.superClass_.constructor.call(this); workspaceOptions.setMetrics = this.setMetrics_.bind(this); /** - * @type {!Blockly.WorkspaceSvg} + * @type {!WorkspaceSvg} * @protected */ - this.workspace_ = new Blockly.WorkspaceSvg(workspaceOptions); + this.workspace_ = new WorkspaceSvg(workspaceOptions); this.workspace_.setMetricsManager( - new Blockly.FlyoutMetricsManager(this.workspace_, this)); + new FlyoutMetricsManager(this.workspace_, this)); this.workspace_.isFlyout = true; // Keep the workspace visibility consistent with the flyout's visibility. @@ -76,7 +81,7 @@ Blockly.Flyout = function(workspaceOptions) { * ComponentManager. * @type {string} */ - this.id = Blockly.utils.genUid(); + this.id = utils.genUid(); /** * Is RTL vs LTR. @@ -115,7 +120,7 @@ Blockly.Flyout = function(workspaceOptions) { /** * List of visible buttons. - * @type {!Array} + * @type {!Array} * @protected */ this.buttons_ = []; @@ -129,7 +134,7 @@ Blockly.Flyout = function(workspaceOptions) { /** * List of blocks that should always be disabled. - * @type {!Array} + * @type {!Array} * @private */ this.permanentlyDisabled_ = []; @@ -144,46 +149,46 @@ Blockly.Flyout = function(workspaceOptions) { /** * The target workspace - * @type {?Blockly.WorkspaceSvg} + * @type {?WorkspaceSvg} * @package */ this.targetWorkspace = null; }; -Blockly.utils.object.inherits(Blockly.Flyout, Blockly.DeleteArea); +utils.object.inherits(Flyout, DeleteArea); /** * Does the flyout automatically close when a block is created? * @type {boolean} */ -Blockly.Flyout.prototype.autoClose = true; +Flyout.prototype.autoClose = true; /** * Whether the flyout is visible. * @type {boolean} * @private */ -Blockly.Flyout.prototype.isVisible_ = false; +Flyout.prototype.isVisible_ = false; /** * Whether the workspace containing this flyout is visible. * @type {boolean} * @private */ -Blockly.Flyout.prototype.containerVisible_ = true; +Flyout.prototype.containerVisible_ = true; /** * Corner radius of the flyout background. * @type {number} * @const */ -Blockly.Flyout.prototype.CORNER_RADIUS = 8; +Flyout.prototype.CORNER_RADIUS = 8; /** * Margin around the edges of the blocks in the flyout. * @type {number} * @const */ -Blockly.Flyout.prototype.MARGIN = Blockly.Flyout.prototype.CORNER_RADIUS; +Flyout.prototype.MARGIN = Flyout.prototype.CORNER_RADIUS; // TODO: Move GAP_X and GAP_Y to their appropriate files. @@ -192,35 +197,35 @@ Blockly.Flyout.prototype.MARGIN = Blockly.Flyout.prototype.CORNER_RADIUS; * element. * @const {number} */ -Blockly.Flyout.prototype.GAP_X = Blockly.Flyout.prototype.MARGIN * 3; +Flyout.prototype.GAP_X = Flyout.prototype.MARGIN * 3; /** * Gap between items in vertical flyouts. Can be overridden with the "sep" * element. * @const {number} */ -Blockly.Flyout.prototype.GAP_Y = Blockly.Flyout.prototype.MARGIN * 3; +Flyout.prototype.GAP_Y = Flyout.prototype.MARGIN * 3; /** * Top/bottom padding between scrollbar and edge of flyout background. * @type {number} * @const */ -Blockly.Flyout.prototype.SCROLLBAR_MARGIN = 2.5; +Flyout.prototype.SCROLLBAR_MARGIN = 2.5; /** * Width of flyout. * @type {number} * @protected */ -Blockly.Flyout.prototype.width_ = 0; +Flyout.prototype.width_ = 0; /** * Height of flyout. * @type {number} * @protected */ -Blockly.Flyout.prototype.height_ = 0; +Flyout.prototype.height_ = 0; /** * Range of a drag angle from a flyout considered "dragging toward workspace". @@ -237,20 +242,20 @@ Blockly.Flyout.prototype.height_ = 0; * flyout. Setting it to 360 means that all drags create a new block. * @type {number} * @protected -*/ -Blockly.Flyout.prototype.dragAngleRange_ = 70; + */ +Flyout.prototype.dragAngleRange_ = 70; /** * Creates the flyout's DOM. Only needs to be called once. The flyout can * either exist as its own SVG element or be a g element nested inside a * separate SVG element. * @param {string| - * !Blockly.utils.Svg| - * !Blockly.utils.Svg} tagName The type of tag to + * !Svg| + * !Svg} tagName The type of tag to * put the flyout in. This should be or . * @return {!SVGElement} The flyout's SVG group. */ -Blockly.Flyout.prototype.createDom = function(tagName) { +Flyout.prototype.createDom = function(tagName) { /* @@ -259,11 +264,10 @@ Blockly.Flyout.prototype.createDom = function(tagName) { */ // Setting style to display:none to start. The toolbox and flyout // hide/show code will set up proper visibility and size later. - this.svgGroup_ = Blockly.utils.dom.createSvgElement(tagName, - {'class': 'blocklyFlyout', 'style': 'display: none'}, null); - this.svgBackground_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.PATH, - {'class': 'blocklyFlyoutBackground'}, this.svgGroup_); + this.svgGroup_ = dom.createSvgElement( + tagName, {'class': 'blocklyFlyout', 'style': 'display: none'}, null); + this.svgBackground_ = dom.createSvgElement( + Svg.PATH, {'class': 'blocklyFlyoutBackground'}, this.svgGroup_); this.svgGroup_.appendChild(this.workspace_.createDom()); this.workspace_.getThemeManager().subscribe( this.svgBackground_, 'flyoutBackgroundColour', 'fill'); @@ -274,14 +278,14 @@ Blockly.Flyout.prototype.createDom = function(tagName) { /** * Initializes the flyout. - * @param {!Blockly.WorkspaceSvg} targetWorkspace The workspace in which to + * @param {!WorkspaceSvg} targetWorkspace The workspace in which to * create new blocks. */ -Blockly.Flyout.prototype.init = function(targetWorkspace) { +Flyout.prototype.init = function(targetWorkspace) { this.targetWorkspace = targetWorkspace; this.workspace_.targetWorkspace = targetWorkspace; - this.workspace_.scrollbar = new Blockly.ScrollbarPair( + this.workspace_.scrollbar = new ScrollbarPair( this.workspace_, this.horizontalLayout, !this.horizontalLayout, 'blocklyFlyoutScrollbar', this.SCROLLBAR_MARGIN); @@ -289,7 +293,7 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) { Array.prototype.push.apply( this.eventWrappers_, - Blockly.browserEvents.conditionalBind( + browserEvents.conditionalBind( this.svgGroup_, 'wheel', this, this.wheel_)); if (!this.autoClose) { this.filterWrapper_ = this.filterForCapacity_.bind(this); @@ -299,7 +303,7 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) { // Dragging the flyout up and down. Array.prototype.push.apply( this.eventWrappers_, - Blockly.browserEvents.conditionalBind( + browserEvents.conditionalBind( this.svgBackground_, 'mousedown', this, this.onMouseDown_)); // A flyout connected to a workspace doesn't have its own current gesture. @@ -315,8 +319,8 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) { component: this, weight: 1, capabilities: [ - Blockly.ComponentManager.Capability.DELETE_AREA, - Blockly.ComponentManager.Capability.DRAG_TARGET + ComponentManager.Capability.DELETE_AREA, + ComponentManager.Capability.DRAG_TARGET ] }); }; @@ -326,10 +330,10 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) { * Unlink from all DOM elements to prevent memory leaks. * @suppress {checkTypes} */ -Blockly.Flyout.prototype.dispose = function() { +Flyout.prototype.dispose = function() { this.hide(); this.workspace_.getComponentManager().removeComponent(this.id); - Blockly.browserEvents.unbind(this.eventWrappers_); + browserEvents.unbind(this.eventWrappers_); if (this.filterWrapper_) { this.targetWorkspace.removeChangeListener(this.filterWrapper_); this.filterWrapper_ = null; @@ -341,7 +345,7 @@ Blockly.Flyout.prototype.dispose = function() { this.workspace_ = null; } if (this.svgGroup_) { - Blockly.utils.dom.removeNode(this.svgGroup_); + dom.removeNode(this.svgGroup_); this.svgGroup_ = null; } this.svgBackground_ = null; @@ -352,7 +356,7 @@ Blockly.Flyout.prototype.dispose = function() { * Get the width of the flyout. * @return {number} The width of the flyout. */ -Blockly.Flyout.prototype.getWidth = function() { +Flyout.prototype.getWidth = function() { return this.width_; }; @@ -360,7 +364,7 @@ Blockly.Flyout.prototype.getWidth = function() { * Get the height of the flyout. * @return {number} The width of the flyout. */ -Blockly.Flyout.prototype.getHeight = function() { +Flyout.prototype.getHeight = function() { return this.height_; }; @@ -369,16 +373,16 @@ Blockly.Flyout.prototype.getHeight = function() { * this matches the target workspace scale, but this can be overridden. * @return {number} Flyout workspace scale. */ -Blockly.Flyout.prototype.getFlyoutScale = function() { +Flyout.prototype.getFlyoutScale = function() { return this.targetWorkspace.scale; }; /** * Get the workspace inside the flyout. - * @return {!Blockly.WorkspaceSvg} The workspace inside the flyout. + * @return {!WorkspaceSvg} The workspace inside the flyout. * @package */ -Blockly.Flyout.prototype.getWorkspace = function() { +Flyout.prototype.getWorkspace = function() { return this.workspace_; }; @@ -386,7 +390,7 @@ Blockly.Flyout.prototype.getWorkspace = function() { * Is the flyout visible? * @return {boolean} True if visible. */ -Blockly.Flyout.prototype.isVisible = function() { +Flyout.prototype.isVisible = function() { return this.isVisible_; }; @@ -395,8 +399,8 @@ Blockly.Flyout.prototype.isVisible = function() { * that the flyout is shown. It could be hidden because its container is hidden. * @param {boolean} visible True if visible. */ -Blockly.Flyout.prototype.setVisible = function(visible) { - var visibilityChanged = (visible != this.isVisible()); +Flyout.prototype.setVisible = function(visible) { + const visibilityChanged = (visible != this.isVisible()); this.isVisible_ = visible; if (visibilityChanged) { @@ -413,8 +417,8 @@ Blockly.Flyout.prototype.setVisible = function(visible) { * Set whether this flyout's container is visible. * @param {boolean} visible Whether the container is visible. */ -Blockly.Flyout.prototype.setContainerVisible = function(visible) { - var visibilityChanged = (visible != this.containerVisible_); +Flyout.prototype.setContainerVisible = function(visible) { + const visibilityChanged = (visible != this.containerVisible_); this.containerVisible_ = visible; if (visibilityChanged) { this.updateDisplay_(); @@ -426,8 +430,8 @@ Blockly.Flyout.prototype.setContainerVisible = function(visible) { * be visible and whether its containing workspace is visible. * @private */ -Blockly.Flyout.prototype.updateDisplay_ = function() { - var show = true; +Flyout.prototype.updateDisplay_ = function() { + let show = true; if (!this.containerVisible_) { show = false; } else { @@ -447,23 +451,23 @@ Blockly.Flyout.prototype.updateDisplay_ = function() { * @param {number} y The computed y origin of the flyout's SVG group. * @protected */ -Blockly.Flyout.prototype.positionAt_ = function(width, height, x, y) { - this.svgGroup_.setAttribute("width", width); - this.svgGroup_.setAttribute("height", height); +Flyout.prototype.positionAt_ = function(width, height, x, y) { + this.svgGroup_.setAttribute('width', width); + this.svgGroup_.setAttribute('height', height); this.workspace_.setCachedParentSvgSize(width, height); if (this.svgGroup_.tagName == 'svg') { - var transform = 'translate(' + x + 'px,' + y + 'px)'; - Blockly.utils.dom.setCssTransform(this.svgGroup_, transform); + const transform = 'translate(' + x + 'px,' + y + 'px)'; + dom.setCssTransform(this.svgGroup_, transform); } else { // IE and Edge don't support CSS transforms on SVG elements so // it's important to set the transform on the SVG element itself - var transform = 'translate(' + x + ',' + y + ')'; - this.svgGroup_.setAttribute("transform", transform); + const transform = 'translate(' + x + ',' + y + ')'; + this.svgGroup_.setAttribute('transform', transform); } // Update the scrollbar (if one exists). - var scrollbar = this.workspace_.scrollbar; + const scrollbar = this.workspace_.scrollbar; if (scrollbar) { // Set the scrollbars origin to be the top left of the flyout. scrollbar.setOrigin(x, y); @@ -477,7 +481,6 @@ Blockly.Flyout.prototype.positionAt_ = function(width, height, x, y) { if (scrollbar.vScroll) { scrollbar.vScroll.setPosition( scrollbar.vScroll.position.x, scrollbar.vScroll.position.y); - } } }; @@ -485,14 +488,14 @@ Blockly.Flyout.prototype.positionAt_ = function(width, height, x, y) { /** * Hide and empty the flyout. */ -Blockly.Flyout.prototype.hide = function() { +Flyout.prototype.hide = function() { if (!this.isVisible()) { return; } this.setVisible(false); // Delete all the event listeners. - for (var i = 0, listen; (listen = this.listeners_[i]); i++) { - Blockly.browserEvents.unbind(listen); + for (let i = 0, listen; (listen = this.listeners_[i]); i++) { + browserEvents.unbind(listen); } this.listeners_.length = 0; if (this.reflowWrapper_) { @@ -505,11 +508,11 @@ Blockly.Flyout.prototype.hide = function() { /** * Show and populate the flyout. - * @param {!Blockly.utils.toolbox.FlyoutDefinition|string} flyoutDef Contents to display + * @param {!toolbox.FlyoutDefinition|string} flyoutDef Contents to display * in the flyout. This is either an array of Nodes, a NodeList, a * toolbox definition, or a string with the name of the dynamic category. */ -Blockly.Flyout.prototype.show = function(flyoutDef) { +Flyout.prototype.show = function(flyoutDef) { this.workspace_.setResizesEnabled(false); this.hide(); this.clearOldBlocks_(); @@ -521,23 +524,23 @@ Blockly.Flyout.prototype.show = function(flyoutDef) { this.setVisible(true); // Parse the Array, Node or NodeList into a a list of flyout items. - var parsedContent = Blockly.utils.toolbox.convertFlyoutDefToJsonArray(flyoutDef); - var flyoutInfo = - /** @type {{contents:!Array, gaps:!Array}} */ ( - this.createFlyoutInfo_(parsedContent)); + const parsedContent = toolbox.convertFlyoutDefToJsonArray(flyoutDef); + const flyoutInfo = + /** @type {{contents:!Array, gaps:!Array}} */ ( + this.createFlyoutInfo_(parsedContent)); this.layout_(flyoutInfo.contents, flyoutInfo.gaps); // IE 11 is an incompetent browser that fails to fire mouseout events. // When the mouse is over the background, deselect all blocks. - var deselectAll = function() { - var topBlocks = this.workspace_.getTopBlocks(false); - for (var i = 0, block; (block = topBlocks[i]); i++) { + const deselectAll = function() { + const topBlocks = this.workspace_.getTopBlocks(false); + for (let i = 0, block; (block = topBlocks[i]); i++) { block.removeSelect(); } }; - this.listeners_.push(Blockly.browserEvents.conditionalBind( + this.listeners_.push(browserEvents.conditionalBind( this.svgBackground_, 'mouseover', this, deselectAll)); if (this.horizontalLayout) { @@ -560,57 +563,63 @@ Blockly.Flyout.prototype.show = function(flyoutDef) { /** * Create the contents array and gaps array necessary to create the layout for * the flyout. - * @param {!Blockly.utils.toolbox.FlyoutItemInfoArray} parsedContent The array + * @param {!toolbox.FlyoutItemInfoArray} parsedContent The array * of objects to show in the flyout. * @return {{contents:Array, gaps:Array}} The list of contents * and gaps needed to lay out the flyout. * @private */ -Blockly.Flyout.prototype.createFlyoutInfo_ = function(parsedContent) { - var contents = []; - var gaps = []; +Flyout.prototype.createFlyoutInfo_ = function(parsedContent) { + const contents = []; + const gaps = []; this.permanentlyDisabled_.length = 0; - var defaultGap = this.horizontalLayout ? this.GAP_X : this.GAP_Y; - for (var i = 0, contentInfo; (contentInfo = parsedContent[i]); i++) { - + const defaultGap = this.horizontalLayout ? this.GAP_X : this.GAP_Y; + for (let i = 0, contentInfo; (contentInfo = parsedContent[i]); i++) { if (contentInfo['custom']) { - var customInfo = /** @type {!Blockly.utils.toolbox.DynamicCategoryInfo} */ (contentInfo); - var categoryName = customInfo['custom']; - var flyoutDef = this.getDynamicCategoryContents_(categoryName); - var parsedDynamicContent = /** @type {!Blockly.utils.toolbox.FlyoutItemInfoArray} */ - (Blockly.utils.toolbox.convertFlyoutDefToJsonArray(flyoutDef)); - parsedContent.splice.apply(parsedContent, [i, 1].concat(parsedDynamicContent)); + const customInfo = + /** @type {!toolbox.DynamicCategoryInfo} */ (contentInfo); + const categoryName = customInfo['custom']; + const flyoutDef = this.getDynamicCategoryContents_(categoryName); + const parsedDynamicContent = /** @type {!toolbox.FlyoutItemInfoArray} */ + (toolbox.convertFlyoutDefToJsonArray(flyoutDef)); + parsedContent.splice.apply( + parsedContent, [i, 1].concat(parsedDynamicContent)); contentInfo = parsedContent[i]; } switch (contentInfo['kind'].toUpperCase()) { - case 'BLOCK': - var blockInfo = /** @type {!Blockly.utils.toolbox.BlockInfo} */ (contentInfo); - var blockXml = this.getBlockXml_(blockInfo); - var block = this.createBlock_(blockXml); + case 'BLOCK': { + const blockInfo = /** @type {!toolbox.BlockInfo} */ (contentInfo); + const blockXml = this.getBlockXml_(blockInfo); + const block = this.createBlock_(blockXml); // This is a deprecated method for adding gap to a block. // - var gap = parseInt(blockInfo['gap'] || blockXml.getAttribute('gap'), 10); + const gap = + parseInt(blockInfo['gap'] || blockXml.getAttribute('gap'), 10); gaps.push(isNaN(gap) ? defaultGap : gap); contents.push({type: 'block', block: block}); break; - case 'SEP': - var sepInfo = /** @type {!Blockly.utils.toolbox.SeparatorInfo} */ (contentInfo); + } + case 'SEP': { + const sepInfo = /** @type {!toolbox.SeparatorInfo} */ (contentInfo); this.addSeparatorGap_(sepInfo, gaps, defaultGap); break; - case 'LABEL': - var labelInfo = /** @type {!Blockly.utils.toolbox.LabelInfo} */ (contentInfo); + } + case 'LABEL': { + const labelInfo = /** @type {!toolbox.LabelInfo} */ (contentInfo); // A label is a button with different styling. - var label = this.createButton_(labelInfo, /** isLabel */ true); + const label = this.createButton_(labelInfo, /** isLabel */ true); contents.push({type: 'button', button: label}); gaps.push(defaultGap); break; - case 'BUTTON': - var buttonInfo = /** @type {!Blockly.utils.toolbox.ButtonInfo} */ (contentInfo); - var button = this.createButton_(buttonInfo, /** isLabel */ false); + } + case 'BUTTON': { + const buttonInfo = /** @type {!toolbox.ButtonInfo} */ (contentInfo); + const button = this.createButton_(buttonInfo, /** isLabel */ false); contents.push({type: 'button', button: button}); gaps.push(defaultGap); break; + } } } return {contents: contents, gaps: gaps}; @@ -622,38 +631,40 @@ Blockly.Flyout.prototype.createFlyoutInfo_ = function(parsedContent) { * @return {!Array} The array of flyout items. * @private */ -Blockly.Flyout.prototype.getDynamicCategoryContents_ = function(categoryName) { +Flyout.prototype.getDynamicCategoryContents_ = function(categoryName) { // Look up the correct category generation function and call that to get a // valid XML list. - var fnToApply = this.workspace_.targetWorkspace.getToolboxCategoryCallback( - categoryName); + const fnToApply = + this.workspace_.targetWorkspace.getToolboxCategoryCallback(categoryName); if (typeof fnToApply != 'function') { - throw TypeError('Couldn\'t find a callback function when opening' + + throw TypeError( + 'Couldn\'t find a callback function when opening' + ' a toolbox category.'); } - var flyoutDef = fnToApply(this.workspace_.targetWorkspace); + const flyoutDef = fnToApply(this.workspace_.targetWorkspace); if (!Array.isArray(flyoutDef)) { - throw new TypeError('Result of toolbox category callback must be an array.'); + throw new TypeError( + 'Result of toolbox category callback must be an array.'); } return flyoutDef; }; /** * Creates a flyout button or a flyout label. - * @param {!Blockly.utils.toolbox.ButtonOrLabelInfo} btnInfo + * @param {!toolbox.ButtonOrLabelInfo} btnInfo * The object holding information about a button or a label. * @param {boolean} isLabel True if the button is a label, false otherwise. - * @return {!Blockly.FlyoutButton} The object used to display the button in the + * @return {!FlyoutButton} The object used to display the button in the * flyout. * @private */ -Blockly.Flyout.prototype.createButton_ = function(btnInfo, isLabel) { - if (!Blockly.FlyoutButton) { +Flyout.prototype.createButton_ = function(btnInfo, isLabel) { + if (!FlyoutButton) { throw Error('Missing require for Blockly.FlyoutButton'); } - var curButton = new Blockly.FlyoutButton(this.workspace_, - /** @type {!Blockly.WorkspaceSvg} */ (this.targetWorkspace), btnInfo, - isLabel); + const curButton = new FlyoutButton( + this.workspace_, + /** @type {!WorkspaceSvg} */ (this.targetWorkspace), btnInfo, isLabel); return curButton; }; @@ -661,12 +672,12 @@ Blockly.Flyout.prototype.createButton_ = function(btnInfo, isLabel) { * Create a block from the xml and permanently disable any blocks that were * defined as disabled. * @param {!Element} blockXml The xml of the block. - * @return {!Blockly.BlockSvg} The block created from the blockXml. + * @return {!BlockSvg} The block created from the blockXml. * @protected */ -Blockly.Flyout.prototype.createBlock_ = function(blockXml) { - var curBlock = /** @type {!Blockly.BlockSvg} */ ( - Blockly.Xml.domToBlock(blockXml, this.workspace_)); +Flyout.prototype.createBlock_ = function(blockXml) { + const curBlock = + /** @type {!BlockSvg} */ (Xml.domToBlock(blockXml, this.workspace_)); if (!curBlock.isEnabled()) { // Record blocks that were initially disabled. // Do not enable these blocks as a result of capacity filtering. @@ -677,48 +688,50 @@ Blockly.Flyout.prototype.createBlock_ = function(blockXml) { /** * Get the xml from the block info object. - * @param {!Blockly.utils.toolbox.BlockInfo} blockInfo The object holding + * @param {!toolbox.BlockInfo} blockInfo The object holding * information about a block. * @return {!Element} The xml for the block. * @throws {Error} if the xml is not a valid block definition. * @private */ -Blockly.Flyout.prototype.getBlockXml_ = function(blockInfo) { - var blockElement = null; - var blockXml = blockInfo['blockxml']; +Flyout.prototype.getBlockXml_ = function(blockInfo) { + let blockElement = null; + const blockXml = blockInfo['blockxml']; if (blockXml && typeof blockXml != 'string') { blockElement = blockXml; } else if (blockXml && typeof blockXml == 'string') { - blockElement = Blockly.Xml.textToDom(blockXml); + blockElement = Xml.textToDom(blockXml); blockInfo['blockxml'] = blockElement; } else if (blockInfo['type']) { - blockElement = Blockly.utils.xml.createElement('xml'); + blockElement = utilsXml.createElement('xml'); blockElement.setAttribute('type', blockInfo['type']); blockElement.setAttribute('disabled', blockInfo['disabled']); blockInfo['blockxml'] = blockElement; } if (!blockElement) { - throw Error('Error: Invalid block definition. Block definition must have blockxml or type.'); + throw Error( + 'Error: Invalid block definition. Block definition must have blockxml or type.'); } return blockElement; }; /** * Add the necessary gap in the flyout for a separator. - * @param {!Blockly.utils.toolbox.SeparatorInfo} sepInfo The object holding + * @param {!toolbox.SeparatorInfo} sepInfo The object holding * information about a separator. * @param {!Array} gaps The list gaps between items in the flyout. - * @param {number} defaultGap The default gap between the button and next element. + * @param {number} defaultGap The default gap between the button and next + * element. * @private */ -Blockly.Flyout.prototype.addSeparatorGap_ = function(sepInfo, gaps, defaultGap) { +Flyout.prototype.addSeparatorGap_ = function(sepInfo, gaps, defaultGap) { // Change the gap between two toolbox elements. // // The default gap is 24, can be set larger or smaller. // This overwrites the gap attribute on the previous element. - var newGap = parseInt(sepInfo['gap'], 10); + const newGap = parseInt(sepInfo['gap'], 10); // Ignore gaps before the first block. if (!isNaN(newGap) && gaps.length > 0) { gaps[gaps.length - 1] = newGap; @@ -731,25 +744,25 @@ Blockly.Flyout.prototype.addSeparatorGap_ = function(sepInfo, gaps, defaultGap) * Delete blocks, mats and buttons from a previous showing of the flyout. * @protected */ -Blockly.Flyout.prototype.clearOldBlocks_ = function() { +Flyout.prototype.clearOldBlocks_ = function() { // Delete any blocks from a previous showing. - var oldBlocks = this.workspace_.getTopBlocks(false); - for (var i = 0, block; (block = oldBlocks[i]); i++) { + const oldBlocks = this.workspace_.getTopBlocks(false); + for (let i = 0, block; (block = oldBlocks[i]); i++) { if (block.workspace == this.workspace_) { block.dispose(false, false); } } // Delete any mats from a previous showing. - for (var j = 0; j < this.mats_.length; j++) { - var rect = this.mats_[j]; + for (let j = 0; j < this.mats_.length; j++) { + const rect = this.mats_[j]; if (rect) { - Blockly.Tooltip.unbindMouseEvents(rect); - Blockly.utils.dom.removeNode(rect); + Tooltip.unbindMouseEvents(rect); + dom.removeNode(rect); } } this.mats_.length = 0; // Delete any buttons from a previous showing. - for (var i = 0, button; (button = this.buttons_[i]); i++) { + for (let i = 0, button; (button = this.buttons_[i]); i++) { button.dispose(); } this.buttons_.length = 0; @@ -761,36 +774,36 @@ Blockly.Flyout.prototype.clearOldBlocks_ = function() { /** * Add listeners to a block that has been added to the flyout. * @param {!SVGElement} root The root node of the SVG group the block is in. - * @param {!Blockly.BlockSvg} block The block to add listeners for. + * @param {!BlockSvg} block The block to add listeners for. * @param {!SVGElement} rect The invisible rectangle under the block that acts * as a mat for that block. * @protected */ -Blockly.Flyout.prototype.addBlockListeners_ = function(root, block, rect) { - this.listeners_.push(Blockly.browserEvents.conditionalBind( +Flyout.prototype.addBlockListeners_ = function(root, block, rect) { + this.listeners_.push(browserEvents.conditionalBind( root, 'mousedown', null, this.blockMouseDown_(block))); - this.listeners_.push(Blockly.browserEvents.conditionalBind( + this.listeners_.push(browserEvents.conditionalBind( rect, 'mousedown', null, this.blockMouseDown_(block))); this.listeners_.push( - Blockly.browserEvents.bind(root, 'mouseenter', block, block.addSelect)); - this.listeners_.push(Blockly.browserEvents.bind( - root, 'mouseleave', block, block.removeSelect)); + browserEvents.bind(root, 'mouseenter', block, block.addSelect)); this.listeners_.push( - Blockly.browserEvents.bind(rect, 'mouseenter', block, block.addSelect)); - this.listeners_.push(Blockly.browserEvents.bind( - rect, 'mouseleave', block, block.removeSelect)); + browserEvents.bind(root, 'mouseleave', block, block.removeSelect)); + this.listeners_.push( + browserEvents.bind(rect, 'mouseenter', block, block.addSelect)); + this.listeners_.push( + browserEvents.bind(rect, 'mouseleave', block, block.removeSelect)); }; /** * Handle a mouse-down on an SVG block in a non-closing flyout. - * @param {!Blockly.BlockSvg} block The flyout block to copy. + * @param {!BlockSvg} block The flyout block to copy. * @return {!Function} Function to call when block is clicked. * @private */ -Blockly.Flyout.prototype.blockMouseDown_ = function(block) { - var flyout = this; +Flyout.prototype.blockMouseDown_ = function(block) { + const flyout = this; return function(e) { - var gesture = flyout.targetWorkspace.getGesture(e); + const gesture = flyout.targetWorkspace.getGesture(e); if (gesture) { gesture.setStartBlock(block); gesture.handleFlyoutStart(e, flyout); @@ -803,8 +816,8 @@ Blockly.Flyout.prototype.blockMouseDown_ = function(block) { * @param {!Event} e Mouse down event. * @private */ -Blockly.Flyout.prototype.onMouseDown_ = function(e) { - var gesture = this.targetWorkspace.getGesture(e); +Flyout.prototype.onMouseDown_ = function(e) { + const gesture = this.targetWorkspace.getGesture(e); if (gesture) { gesture.handleFlyoutStart(e, this); } @@ -813,52 +826,50 @@ Blockly.Flyout.prototype.onMouseDown_ = function(e) { /** * Does this flyout allow you to create a new instance of the given block? * Used for deciding if a block can be "dragged out of" the flyout. - * @param {!Blockly.BlockSvg} block The block to copy from the flyout. + * @param {!BlockSvg} block The block to copy from the flyout. * @return {boolean} True if you can create a new instance of the block, false * otherwise. * @package */ -Blockly.Flyout.prototype.isBlockCreatable_ = function(block) { +Flyout.prototype.isBlockCreatable_ = function(block) { return block.isEnabled(); }; /** * Create a copy of this block on the workspace. - * @param {!Blockly.BlockSvg} originalBlock The block to copy from the flyout. - * @return {!Blockly.BlockSvg} The newly created block. + * @param {!BlockSvg} originalBlock The block to copy from the flyout. + * @return {!BlockSvg} The newly created block. * @throws {Error} if something went wrong with deserialization. * @package */ -Blockly.Flyout.prototype.createBlock = function(originalBlock) { - var newBlock = null; - Blockly.Events.disable(); - var variablesBeforeCreation = this.targetWorkspace.getAllVariables(); +Flyout.prototype.createBlock = function(originalBlock) { + let newBlock = null; + Events.disable(); + const variablesBeforeCreation = this.targetWorkspace.getAllVariables(); this.targetWorkspace.setResizesEnabled(false); try { newBlock = this.placeNewBlock_(originalBlock); } finally { - Blockly.Events.enable(); + Events.enable(); } // Close the flyout. - Blockly.hideChaff(); + hideChaff(); - var newVariables = Blockly.Variables.getAddedVariables(this.targetWorkspace, - variablesBeforeCreation); + const newVariables = Variables.getAddedVariables( + this.targetWorkspace, variablesBeforeCreation); - if (Blockly.Events.isEnabled()) { - Blockly.Events.setGroup(true); + if (Events.isEnabled()) { + Events.setGroup(true); // Fire a VarCreate event for each (if any) new variable created. - for (var i = 0; i < newVariables.length; i++) { - var thisVariable = newVariables[i]; - Blockly.Events.fire( - new (Blockly.Events.get(Blockly.Events.VAR_CREATE))(thisVariable)); + for (let i = 0; i < newVariables.length; i++) { + const thisVariable = newVariables[i]; + Events.fire(new (Events.get(Events.VAR_CREATE))(thisVariable)); } // Block events come after var events, in case they refer to newly created // variables. - Blockly.Events.fire( - new (Blockly.Events.get(Blockly.Events.BLOCK_CREATE))(newBlock)); + Events.fire(new (Events.get(Events.BLOCK_CREATE))(newBlock)); } if (this.autoClose) { this.hide(); @@ -871,18 +882,18 @@ Blockly.Flyout.prototype.createBlock = function(originalBlock) { /** * Initialize the given button: move it to the correct location, * add listeners, etc. - * @param {!Blockly.FlyoutButton} button The button to initialize and place. + * @param {!FlyoutButton} button The button to initialize and place. * @param {number} x The x position of the cursor during this layout pass. * @param {number} y The y position of the cursor during this layout pass. * @protected */ -Blockly.Flyout.prototype.initFlyoutButton_ = function(button, x, y) { - var buttonSvg = button.createDom(); +Flyout.prototype.initFlyoutButton_ = function(button, x, y) { + const buttonSvg = button.createDom(); button.moveTo(x, y); button.show(); // Clicking on a flyout button or label is a lot like clicking on the // flyout background. - this.listeners_.push(Blockly.browserEvents.conditionalBind( + this.listeners_.push(browserEvents.conditionalBind( buttonSvg, 'mousedown', this, this.onMouseDown_)); this.buttons_.push(button); @@ -890,7 +901,7 @@ Blockly.Flyout.prototype.initFlyoutButton_ = function(button, x, y) { /** * Create and place a rectangle corresponding to the given block. - * @param {!Blockly.BlockSvg} block The block to associate the rect to. + * @param {!BlockSvg} block The block to associate the rect to. * @param {number} x The x position of the cursor during this layout pass. * @param {number} y The y position of the cursor during this layout pass. * @param {!{height: number, width: number}} blockHW The height and width of the @@ -901,20 +912,20 @@ Blockly.Flyout.prototype.initFlyoutButton_ = function(button, x, y) { * block. * @protected */ -Blockly.Flyout.prototype.createRect_ = function(block, x, y, blockHW, index) { +Flyout.prototype.createRect_ = function(block, x, y, blockHW, index) { // Create an invisible rectangle under the block to act as a button. Just // using the block as a button is poor, since blocks have holes in them. - var rect = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { + const rect = dom.createSvgElement( + Svg.RECT, { 'fill-opacity': 0, 'x': x, 'y': y, 'height': blockHW.height, 'width': blockHW.width - }, null); + }, + null); rect.tooltip = block; - Blockly.Tooltip.bindMouseEvents(rect); + Tooltip.bindMouseEvents(rect); // Add the rectangles under the blocks, so that the blocks' tooltips work. this.workspace_.getCanvas().insertBefore(rect, block.getSvgRoot()); @@ -927,15 +938,15 @@ Blockly.Flyout.prototype.createRect_ = function(block, x, y, blockHW, index) { * Move a rectangle to sit exactly behind a block, taking into account tabs, * hats, and any other protrusions we invent. * @param {!SVGElement} rect The rectangle to move directly behind the block. - * @param {!Blockly.BlockSvg} block The block the rectangle should be behind. + * @param {!BlockSvg} block The block the rectangle should be behind. * @protected */ -Blockly.Flyout.prototype.moveRectToBlock_ = function(rect, block) { - var blockHW = block.getHeightWidth(); +Flyout.prototype.moveRectToBlock_ = function(rect, block) { + const blockHW = block.getHeightWidth(); rect.setAttribute('width', blockHW.width); rect.setAttribute('height', blockHW.height); - var blockXY = block.getRelativeToSurfaceXY(); + const blockXY = block.getRelativeToSurfaceXY(); rect.setAttribute('y', blockXY.y); rect.setAttribute('x', this.RTL ? blockXY.x - blockHW.width : blockXY.x); }; @@ -946,12 +957,12 @@ Blockly.Flyout.prototype.moveRectToBlock_ = function(rect, block) { * the workspace, an "a + b" block that has two shadow blocks would be disabled. * @private */ -Blockly.Flyout.prototype.filterForCapacity_ = function() { - var blocks = this.workspace_.getTopBlocks(false); - for (var i = 0, block; (block = blocks[i]); i++) { +Flyout.prototype.filterForCapacity_ = function() { + const blocks = this.workspace_.getTopBlocks(false); + for (let i = 0, block; (block = blocks[i]); i++) { if (this.permanentlyDisabled_.indexOf(block) == -1) { - var enable = this.targetWorkspace - .isCapacityAvailable(Blockly.utils.getBlockTypeCounts(block)); + const enable = this.targetWorkspace.isCapacityAvailable( + utils.getBlockTypeCounts(block)); while (block) { block.setEnabled(enable); block = block.getNextBlock(); @@ -963,7 +974,7 @@ Blockly.Flyout.prototype.filterForCapacity_ = function() { /** * Reflow blocks and their mats. */ -Blockly.Flyout.prototype.reflow = function() { +Flyout.prototype.reflow = function() { if (this.reflowWrapper_) { this.workspace_.removeChangeListener(this.reflowWrapper_); } @@ -978,63 +989,62 @@ Blockly.Flyout.prototype.reflow = function() { * dragging. * @package */ -Blockly.Flyout.prototype.isScrollable = function() { - return this.workspace_.scrollbar ? - this.workspace_.scrollbar.isVisible() : false; +Flyout.prototype.isScrollable = function() { + return this.workspace_.scrollbar ? this.workspace_.scrollbar.isVisible() : + false; }; /** * Copy a block from the flyout to the workspace and position it correctly. - * @param {!Blockly.BlockSvg} oldBlock The flyout block to copy. - * @return {!Blockly.BlockSvg} The new block in the main workspace. + * @param {!BlockSvg} oldBlock The flyout block to copy. + * @return {!BlockSvg} The new block in the main workspace. * @private */ -Blockly.Flyout.prototype.placeNewBlock_ = function(oldBlock) { - var targetWorkspace = this.targetWorkspace; - var svgRootOld = oldBlock.getSvgRoot(); +Flyout.prototype.placeNewBlock_ = function(oldBlock) { + const targetWorkspace = this.targetWorkspace; + const svgRootOld = oldBlock.getSvgRoot(); if (!svgRootOld) { throw Error('oldBlock is not rendered.'); } // Create the new block by cloning the block in the flyout (via XML). // This cast assumes that the oldBlock can not be an insertion marker. - var xml = /** @type {!Element} */ (Blockly.Xml.blockToDom(oldBlock, true)); + const xml = /** @type {!Element} */ (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); // Using domToBlock instead of domToWorkspace means that the new block will be // placed at position (0, 0) in main workspace units. - var block = /** @type {!Blockly.BlockSvg} */ - (Blockly.Xml.domToBlock(xml, targetWorkspace)); - var svgRootNew = block.getSvgRoot(); + const block = /** @type {!BlockSvg} */ + (Xml.domToBlock(xml, targetWorkspace)); + const svgRootNew = block.getSvgRoot(); if (!svgRootNew) { throw Error('block is not rendered.'); } // The offset in pixels between the main workspace's origin and the upper left // corner of the injection div. - var mainOffsetPixels = targetWorkspace.getOriginOffsetInPixels(); + const mainOffsetPixels = targetWorkspace.getOriginOffsetInPixels(); // The offset in pixels between the flyout workspace's origin and the upper // left corner of the injection div. - var flyoutOffsetPixels = this.workspace_.getOriginOffsetInPixels(); + const flyoutOffsetPixels = this.workspace_.getOriginOffsetInPixels(); // The position of the old block in flyout workspace coordinates. - var oldBlockPos = oldBlock.getRelativeToSurfaceXY(); + const oldBlockPos = oldBlock.getRelativeToSurfaceXY(); // The position of the old block in pixels relative to the flyout // workspace's origin. oldBlockPos.scale(this.workspace_.scale); // The position of the old block in pixels relative to the upper left corner // of the injection div. - var oldBlockOffsetPixels = Blockly.utils.Coordinate.sum(flyoutOffsetPixels, - oldBlockPos); + const oldBlockOffsetPixels = Coordinate.sum(flyoutOffsetPixels, oldBlockPos); // The position of the old block in pixels relative to the origin of the // main workspace. - var finalOffset = Blockly.utils.Coordinate.difference(oldBlockOffsetPixels, - mainOffsetPixels); + const finalOffset = + Coordinate.difference(oldBlockOffsetPixels, mainOffsetPixels); // The position of the old block in main workspace coordinates. finalOffset.scale(1 / targetWorkspace.scale); @@ -1045,26 +1055,26 @@ Blockly.Flyout.prototype.placeNewBlock_ = function(oldBlock) { /** * Returns the bounding rectangle of the drag target area in pixel units * relative to viewport. - * @return {Blockly.utils.Rect} The component's bounding box. + * @return {utils.Rect} The component's bounding box. */ -Blockly.Flyout.prototype.getClientRect; +Flyout.prototype.getClientRect; /** * Position the flyout. * @return {void} */ -Blockly.Flyout.prototype.position; +Flyout.prototype.position; /** * Determine if a drag delta is toward the workspace, based on the position * and orientation of the flyout. This is used in determineDragIntention_ to * determine if a new block should be created or if the flyout should scroll. - * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has + * @param {!Coordinate} currentDragDeltaXY How far the pointer has * moved from the position at mouse down, in pixel units. * @return {boolean} True if the drag is toward the workspace. * @package */ -Blockly.Flyout.prototype.isDragTowardWorkspace; +Flyout.prototype.isDragTowardWorkspace; /** * Sets the translation of the flyout to match the scrollbars. @@ -1073,7 +1083,7 @@ Blockly.Flyout.prototype.isDragTowardWorkspace; * similar x property. * @protected */ -Blockly.Flyout.prototype.setMetrics_; +Flyout.prototype.setMetrics_; /** * Lay out the blocks in the flyout. @@ -1081,14 +1091,14 @@ Blockly.Flyout.prototype.setMetrics_; * @param {!Array} gaps The visible gaps between blocks. * @protected */ -Blockly.Flyout.prototype.layout_; +Flyout.prototype.layout_; /** * Scroll the flyout. * @param {!Event} e Mouse wheel scroll event. * @protected */ -Blockly.Flyout.prototype.wheel_; +Flyout.prototype.wheel_; /** * Compute height of flyout. Position mat under each block. @@ -1096,16 +1106,18 @@ Blockly.Flyout.prototype.wheel_; * @return {void} * @protected */ -Blockly.Flyout.prototype.reflowInternal_; +Flyout.prototype.reflowInternal_; /** * Calculates the x coordinate for the flyout position. * @return {number} X coordinate. */ -Blockly.Flyout.prototype.getX; +Flyout.prototype.getX; /** * Calculates the y coordinate for the flyout position. * @return {number} Y coordinate. */ -Blockly.Flyout.prototype.getY; +Flyout.prototype.getY; + +exports = Flyout; diff --git a/core/flyout_button.js b/core/flyout_button.js index 643790d9f..db05ca4f4 100644 --- a/core/flyout_button.js +++ b/core/flyout_button.js @@ -10,42 +10,44 @@ */ 'use strict'; -goog.provide('Blockly.FlyoutButton'); +goog.module('Blockly.FlyoutButton'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.browserEvents'); -goog.require('Blockly.Css'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.style'); -goog.require('Blockly.utils.Svg'); - -goog.requireType('Blockly.utils.toolbox'); -goog.requireType('Blockly.WorkspaceSvg'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +const Css = goog.require('Blockly.Css'); +const Svg = goog.require('Blockly.utils.Svg'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +const browserEvents = goog.require('Blockly.browserEvents'); +const dom = goog.require('Blockly.utils.dom'); +const style = goog.require('Blockly.utils.style'); +/* eslint-disable-next-line no-unused-vars */ +const toolbox = goog.requireType('Blockly.utils.toolbox'); +const {replaceMessageReferences} = goog.require('Blockly.utils'); /** * Class for a button in the flyout. - * @param {!Blockly.WorkspaceSvg} workspace The workspace in which to place this + * @param {!WorkspaceSvg} workspace The workspace in which to place this * button. - * @param {!Blockly.WorkspaceSvg} targetWorkspace The flyout's target workspace. - * @param {!Blockly.utils.toolbox.ButtonOrLabelInfo} json + * @param {!WorkspaceSvg} targetWorkspace The flyout's target workspace. + * @param {!toolbox.ButtonOrLabelInfo} json * The JSON specifying the label/button. * @param {boolean} isLabel Whether this button should be styled as a label. * @constructor * @package */ -Blockly.FlyoutButton = function(workspace, targetWorkspace, json, isLabel) { +const FlyoutButton = function(workspace, targetWorkspace, json, isLabel) { // Labels behave the same as buttons, but are styled differently. /** - * @type {!Blockly.WorkspaceSvg} + * @type {!WorkspaceSvg} * @private */ this.workspace_ = workspace; /** - * @type {!Blockly.WorkspaceSvg} + * @type {!WorkspaceSvg} * @private */ this.targetWorkspace_ = targetWorkspace; @@ -57,10 +59,10 @@ Blockly.FlyoutButton = function(workspace, targetWorkspace, json, isLabel) { this.text_ = json['text']; /** - * @type {!Blockly.utils.Coordinate} + * @type {!Coordinate} * @private */ - this.position_ = new Blockly.utils.Coordinate(0, 0); + this.position_ = new Coordinate(0, 0); /** * Whether this button should be styled as a label. @@ -75,8 +77,8 @@ Blockly.FlyoutButton = function(workspace, targetWorkspace, json, isLabel) { * @private */ this.callbackKey_ = json['callbackKey'] || - /* Check the lower case version too to satisfy IE */ - json['callbackkey']; + /* Check the lower case version too to satisfy IE */ + json['callbackkey']; /** * If specified, a CSS class to add to this button. @@ -87,14 +89,14 @@ Blockly.FlyoutButton = function(workspace, targetWorkspace, json, isLabel) { /** * Mouse up event data. - * @type {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @private */ this.onMouseUpWrapper_ = null; /** * The JSON specifying the label / button. - * @type {!Blockly.utils.toolbox.ButtonOrLabelInfo} + * @type {!toolbox.ButtonOrLabelInfo} */ this.info = json; }; @@ -102,69 +104,70 @@ Blockly.FlyoutButton = function(workspace, targetWorkspace, json, isLabel) { /** * The horizontal margin around the text in the button. */ -Blockly.FlyoutButton.MARGIN_X = 5; +FlyoutButton.MARGIN_X = 5; /** * The vertical margin around the text in the button. */ -Blockly.FlyoutButton.MARGIN_Y = 2; +FlyoutButton.MARGIN_Y = 2; /** * The width of the button's rect. * @type {number} */ -Blockly.FlyoutButton.prototype.width = 0; +FlyoutButton.prototype.width = 0; /** * The height of the button's rect. * @type {number} */ -Blockly.FlyoutButton.prototype.height = 0; +FlyoutButton.prototype.height = 0; /** * Create the button elements. * @return {!SVGElement} The button's SVG group. */ -Blockly.FlyoutButton.prototype.createDom = function() { - var cssClass = this.isLabel_ ? 'blocklyFlyoutLabel' : 'blocklyFlyoutButton'; +FlyoutButton.prototype.createDom = function() { + let cssClass = this.isLabel_ ? 'blocklyFlyoutLabel' : 'blocklyFlyoutButton'; if (this.cssClass_) { cssClass += ' ' + this.cssClass_; } - this.svgGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, {'class': cssClass}, - this.workspace_.getCanvas()); + this.svgGroup_ = dom.createSvgElement( + Svg.G, {'class': cssClass}, this.workspace_.getCanvas()); + let shadow; if (!this.isLabel_) { // Shadow rectangle (light source does not mirror in RTL). - var shadow = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { + shadow = dom.createSvgElement( + Svg.RECT, { 'class': 'blocklyFlyoutButtonShadow', - 'rx': 4, 'ry': 4, 'x': 1, 'y': 1 + 'rx': 4, + 'ry': 4, + 'x': 1, + 'y': 1 }, this.svgGroup_); } // Background rectangle. - var rect = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { - 'class': this.isLabel_ ? - 'blocklyFlyoutLabelBackground' : 'blocklyFlyoutButtonBackground', - 'rx': 4, 'ry': 4 + const rect = dom.createSvgElement( + Svg.RECT, { + 'class': this.isLabel_ ? 'blocklyFlyoutLabelBackground' : + 'blocklyFlyoutButtonBackground', + 'rx': 4, + 'ry': 4 }, this.svgGroup_); - var svgText = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.TEXT, - { + const svgText = dom.createSvgElement( + Svg.TEXT, { 'class': this.isLabel_ ? 'blocklyFlyoutLabelText' : 'blocklyText', 'x': 0, 'y': 0, 'text-anchor': 'middle' }, this.svgGroup_); - var text = Blockly.utils.replaceMessageReferences(this.text_); + let text = replaceMessageReferences(this.text_); if (this.workspace_.RTL) { // Force text to be RTL by adding an RLM. text += '\u200F'; @@ -172,22 +175,22 @@ Blockly.FlyoutButton.prototype.createDom = function() { svgText.textContent = text; if (this.isLabel_) { this.svgText_ = svgText; - this.workspace_.getThemeManager().subscribe(this.svgText_, - 'flyoutForegroundColour', 'fill'); + this.workspace_.getThemeManager().subscribe( + this.svgText_, 'flyoutForegroundColour', 'fill'); } - var fontSize = Blockly.utils.style.getComputedStyle(svgText, 'fontSize'); - var fontWeight = Blockly.utils.style.getComputedStyle(svgText, 'fontWeight'); - var fontFamily = Blockly.utils.style.getComputedStyle(svgText, 'fontFamily'); - this.width = Blockly.utils.dom.getFastTextWidthWithSizeString(svgText, - fontSize, fontWeight, fontFamily); - var fontMetrics = Blockly.utils.dom.measureFontMetrics(text, fontSize, - fontWeight, fontFamily); + const fontSize = style.getComputedStyle(svgText, 'fontSize'); + const fontWeight = style.getComputedStyle(svgText, 'fontWeight'); + const fontFamily = style.getComputedStyle(svgText, 'fontFamily'); + this.width = dom.getFastTextWidthWithSizeString( + svgText, fontSize, fontWeight, fontFamily); + const fontMetrics = + dom.measureFontMetrics(text, fontSize, fontWeight, fontFamily); this.height = fontMetrics.height; if (!this.isLabel_) { - this.width += 2 * Blockly.FlyoutButton.MARGIN_X; - this.height += 2 * Blockly.FlyoutButton.MARGIN_Y; + this.width += 2 * FlyoutButton.MARGIN_X; + this.height += 2 * FlyoutButton.MARGIN_Y; shadow.setAttribute('width', this.width); shadow.setAttribute('height', this.height); } @@ -195,12 +198,12 @@ Blockly.FlyoutButton.prototype.createDom = function() { rect.setAttribute('height', this.height); svgText.setAttribute('x', this.width / 2); - svgText.setAttribute('y', this.height / 2 - fontMetrics.height / 2 + - fontMetrics.baseline); + svgText.setAttribute( + 'y', this.height / 2 - fontMetrics.height / 2 + fontMetrics.baseline); this.updateTransform_(); - this.onMouseUpWrapper_ = Blockly.browserEvents.conditionalBind( + this.onMouseUpWrapper_ = browserEvents.conditionalBind( this.svgGroup_, 'mouseup', this, this.onMouseUp_); return this.svgGroup_; }; @@ -208,7 +211,7 @@ Blockly.FlyoutButton.prototype.createDom = function() { /** * Correctly position the flyout button and make it visible. */ -Blockly.FlyoutButton.prototype.show = function() { +FlyoutButton.prototype.show = function() { this.updateTransform_(); this.svgGroup_.setAttribute('display', 'block'); }; @@ -217,8 +220,9 @@ Blockly.FlyoutButton.prototype.show = function() { * Update SVG attributes to match internal state. * @private */ -Blockly.FlyoutButton.prototype.updateTransform_ = function() { - this.svgGroup_.setAttribute('transform', +FlyoutButton.prototype.updateTransform_ = function() { + this.svgGroup_.setAttribute( + 'transform', 'translate(' + this.position_.x + ',' + this.position_.y + ')'); }; @@ -227,7 +231,7 @@ Blockly.FlyoutButton.prototype.updateTransform_ = function() { * @param {number} x The new x coordinate. * @param {number} y The new y coordinate. */ -Blockly.FlyoutButton.prototype.moveTo = function(x, y) { +FlyoutButton.prototype.moveTo = function(x, y) { this.position_.x = x; this.position_.y = y; this.updateTransform_(); @@ -236,44 +240,44 @@ Blockly.FlyoutButton.prototype.moveTo = function(x, y) { /** * @return {boolean} Whether or not the button is a label. */ -Blockly.FlyoutButton.prototype.isLabel = function() { +FlyoutButton.prototype.isLabel = function() { return this.isLabel_; }; /** * Location of the button. - * @return {!Blockly.utils.Coordinate} x, y coordinates. + * @return {!Coordinate} x, y coordinates. * @package */ -Blockly.FlyoutButton.prototype.getPosition = function() { +FlyoutButton.prototype.getPosition = function() { return this.position_; }; /** * @return {string} Text of the button. */ -Blockly.FlyoutButton.prototype.getButtonText = function() { +FlyoutButton.prototype.getButtonText = function() { return this.text_; }; /** * Get the button's target workspace. - * @return {!Blockly.WorkspaceSvg} The target workspace of the flyout where this + * @return {!WorkspaceSvg} The target workspace of the flyout where this * button resides. */ -Blockly.FlyoutButton.prototype.getTargetWorkspace = function() { +FlyoutButton.prototype.getTargetWorkspace = function() { return this.targetWorkspace_; }; /** * Dispose of this button. */ -Blockly.FlyoutButton.prototype.dispose = function() { +FlyoutButton.prototype.dispose = function() { if (this.onMouseUpWrapper_) { - Blockly.browserEvents.unbind(this.onMouseUpWrapper_); + browserEvents.unbind(this.onMouseUpWrapper_); } if (this.svgGroup_) { - Blockly.utils.dom.removeNode(this.svgGroup_); + dom.removeNode(this.svgGroup_); } if (this.svgText_) { this.workspace_.getThemeManager().unsubscribe(this.svgText_); @@ -285,16 +289,18 @@ Blockly.FlyoutButton.prototype.dispose = function() { * @param {!Event} e Mouse up event. * @private */ -Blockly.FlyoutButton.prototype.onMouseUp_ = function(e) { - var gesture = this.targetWorkspace_.getGesture(e); +FlyoutButton.prototype.onMouseUp_ = function(e) { + const gesture = this.targetWorkspace_.getGesture(e); if (gesture) { gesture.cancel(); } if (this.isLabel_ && this.callbackKey_) { console.warn('Labels should not have callbacks. Label text: ' + this.text_); - } else if (!this.isLabel_ && !(this.callbackKey_ && - this.targetWorkspace_.getButtonCallback(this.callbackKey_))) { + } else if ( + !this.isLabel_ && + !(this.callbackKey_ && + this.targetWorkspace_.getButtonCallback(this.callbackKey_))) { console.warn('Buttons should have callbacks. Button text: ' + this.text_); } else if (!this.isLabel_) { this.targetWorkspace_.getButtonCallback(this.callbackKey_)(this); @@ -304,7 +310,7 @@ Blockly.FlyoutButton.prototype.onMouseUp_ = function(e) { /** * CSS for buttons and labels. See css.js for use. */ -Blockly.Css.register([ +Css.register([ /* eslint-disable indent */ '.blocklyFlyoutButton {', 'fill: #888;', @@ -323,8 +329,8 @@ Blockly.Css.register([ 'cursor: default;', '}', - '.blocklyFlyoutLabelBackground {', - 'opacity: 0;', - '}', + '.blocklyFlyoutLabelBackground {', 'opacity: 0;', '}', /* eslint-enable indent */ ]); + +exports = FlyoutButton; diff --git a/core/flyout_vertical.js b/core/flyout_vertical.js index a09b3fb8e..2091d1321 100644 --- a/core/flyout_vertical.js +++ b/core/flyout_vertical.js @@ -10,43 +10,45 @@ */ 'use strict'; -goog.provide('Blockly.VerticalFlyout'); +goog.module('Blockly.VerticalFlyout'); +goog.module.declareLegacyNamespace(); +/* eslint-disable-next-line no-unused-vars */ +const Coordinate = goog.requireType('Blockly.utils.Coordinate'); +const DropDownDiv = goog.require('Blockly.DropDownDiv'); +const Flyout = goog.require('Blockly.Flyout'); +/* eslint-disable-next-line no-unused-vars */ +const Options = goog.requireType('Blockly.Options'); +const Rect = goog.require('Blockly.utils.Rect'); +const Scrollbar = goog.require('Blockly.Scrollbar'); +const WidgetDiv = goog.require('Blockly.WidgetDiv'); +const registry = goog.require('Blockly.registry'); +const {Position} = goog.require('Blockly.utils.toolbox'); +const {getScrollDeltaPixels} = goog.require('Blockly.utils'); +const {inherits} = goog.require('Blockly.utils.object'); /** @suppress {extraRequire} */ goog.require('Blockly.Block'); /** @suppress {extraRequire} */ goog.require('Blockly.constants'); -goog.require('Blockly.DropDownDiv'); -goog.require('Blockly.Flyout'); -goog.require('Blockly.registry'); -goog.require('Blockly.Scrollbar'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.object'); -goog.require('Blockly.utils.Rect'); -goog.require('Blockly.utils.toolbox'); -goog.require('Blockly.WidgetDiv'); - -goog.requireType('Blockly.Options'); -goog.requireType('Blockly.utils.Coordinate'); /** * Class for a flyout. - * @param {!Blockly.Options} workspaceOptions Dictionary of options for the + * @param {!Options} workspaceOptions Dictionary of options for the * workspace. - * @extends {Blockly.Flyout} + * @extends {Flyout} * @constructor */ -Blockly.VerticalFlyout = function(workspaceOptions) { - Blockly.VerticalFlyout.superClass_.constructor.call(this, workspaceOptions); +const VerticalFlyout = function(workspaceOptions) { + VerticalFlyout.superClass_.constructor.call(this, workspaceOptions); }; -Blockly.utils.object.inherits(Blockly.VerticalFlyout, Blockly.Flyout); +inherits(VerticalFlyout, Flyout); /** * The name of the vertical flyout in the registry. * @type {string} */ -Blockly.VerticalFlyout.registryName = 'verticalFlyout'; +VerticalFlyout.registryName = 'verticalFlyout'; /** * Sets the translation of the flyout to match the scrollbars. @@ -55,21 +57,22 @@ Blockly.VerticalFlyout.registryName = 'verticalFlyout'; * similar x property. * @protected */ -Blockly.VerticalFlyout.prototype.setMetrics_ = function(xyRatio) { +VerticalFlyout.prototype.setMetrics_ = function(xyRatio) { if (!this.isVisible()) { return; } - var metricsManager = this.workspace_.getMetricsManager(); - var scrollMetrics = metricsManager.getScrollMetrics(); - var viewMetrics = metricsManager.getViewMetrics(); - var absoluteMetrics = metricsManager.getAbsoluteMetrics(); + const metricsManager = this.workspace_.getMetricsManager(); + const scrollMetrics = metricsManager.getScrollMetrics(); + const viewMetrics = metricsManager.getViewMetrics(); + const absoluteMetrics = metricsManager.getAbsoluteMetrics(); if (typeof xyRatio.y == 'number') { this.workspace_.scrollY = -(scrollMetrics.top + - (scrollMetrics.height - viewMetrics.height) * xyRatio.y); + (scrollMetrics.height - viewMetrics.height) * xyRatio.y); } - this.workspace_.translate(this.workspace_.scrollX + absoluteMetrics.left, + this.workspace_.translate( + this.workspace_.scrollX + absoluteMetrics.left, this.workspace_.scrollY + absoluteMetrics.top); }; @@ -77,28 +80,28 @@ Blockly.VerticalFlyout.prototype.setMetrics_ = function(xyRatio) { * Calculates the x coordinate for the flyout position. * @return {number} X coordinate. */ -Blockly.VerticalFlyout.prototype.getX = function() { +VerticalFlyout.prototype.getX = function() { if (!this.isVisible()) { return 0; } - var metricsManager = this.targetWorkspace.getMetricsManager(); - var absoluteMetrics = metricsManager.getAbsoluteMetrics(); - var viewMetrics = metricsManager.getViewMetrics(); - var toolboxMetrics = metricsManager.getToolboxMetrics(); - var x = 0; + const metricsManager = this.targetWorkspace.getMetricsManager(); + const absoluteMetrics = metricsManager.getAbsoluteMetrics(); + const viewMetrics = metricsManager.getViewMetrics(); + const toolboxMetrics = metricsManager.getToolboxMetrics(); + let x = 0; // If this flyout is not the trashcan flyout (e.g. toolbox or mutator). if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_) { // If there is a category toolbox. if (this.targetWorkspace.getToolbox()) { - if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.LEFT) { + if (this.toolboxPosition_ == Position.LEFT) { x = toolboxMetrics.width; } else { x = viewMetrics.width - this.width_; } // Simple (flyout-only) toolbox. } else { - if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.LEFT) { + if (this.toolboxPosition_ == Position.LEFT) { x = 0; } else { // The simple flyout does not cover the workspace. @@ -107,7 +110,7 @@ Blockly.VerticalFlyout.prototype.getX = function() { } // Trashcan flyout is opposite the main flyout. } else { - if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.LEFT) { + if (this.toolboxPosition_ == Position.LEFT) { x = 0; } else { // Because the anchor point of the flyout is on the left, but we want @@ -125,7 +128,7 @@ Blockly.VerticalFlyout.prototype.getX = function() { * Calculates the y coordinate for the flyout position. * @return {number} Y coordinate. */ -Blockly.VerticalFlyout.prototype.getY = function() { +VerticalFlyout.prototype.getY = function() { // Y is always 0 since this is a vertical flyout. return 0; }; @@ -133,22 +136,22 @@ Blockly.VerticalFlyout.prototype.getY = function() { /** * Move the flyout to the edge of the workspace. */ -Blockly.VerticalFlyout.prototype.position = function() { +VerticalFlyout.prototype.position = function() { if (!this.isVisible() || !this.targetWorkspace.isVisible()) { return; } - var metricsManager = this.targetWorkspace.getMetricsManager(); - var targetWorkspaceViewMetrics = metricsManager.getViewMetrics(); + const metricsManager = this.targetWorkspace.getMetricsManager(); + const targetWorkspaceViewMetrics = metricsManager.getViewMetrics(); // Record the height for workspace metrics. this.height_ = targetWorkspaceViewMetrics.height; - var edgeWidth = this.width_ - this.CORNER_RADIUS; - var edgeHeight = targetWorkspaceViewMetrics.height - 2 * this.CORNER_RADIUS; + const edgeWidth = this.width_ - this.CORNER_RADIUS; + const edgeHeight = targetWorkspaceViewMetrics.height - 2 * this.CORNER_RADIUS; this.setBackgroundPath_(edgeWidth, edgeHeight); - var x = this.getX(); - var y = this.getY(); + const x = this.getX(); + const y = this.getY(); this.positionAt_(this.width_, this.height_, x, y); }; @@ -161,26 +164,24 @@ Blockly.VerticalFlyout.prototype.position = function() { * rounded corners. * @private */ -Blockly.VerticalFlyout.prototype.setBackgroundPath_ = function(width, height) { - var atRight = this.toolboxPosition_ == Blockly.utils.toolbox.Position.RIGHT; - var totalWidth = width + this.CORNER_RADIUS; +VerticalFlyout.prototype.setBackgroundPath_ = function(width, height) { + const atRight = this.toolboxPosition_ == Position.RIGHT; + const totalWidth = width + this.CORNER_RADIUS; // Decide whether to start on the left or right. - var path = ['M ' + (atRight ? totalWidth : 0) + ',0']; + const path = ['M ' + (atRight ? totalWidth : 0) + ',0']; // Top. path.push('h', atRight ? -width : width); // Rounded corner. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, - atRight ? 0 : 1, - atRight ? -this.CORNER_RADIUS : this.CORNER_RADIUS, - this.CORNER_RADIUS); + path.push( + 'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, atRight ? 0 : 1, + atRight ? -this.CORNER_RADIUS : this.CORNER_RADIUS, this.CORNER_RADIUS); // Side closest to workspace. path.push('v', Math.max(0, height)); // Rounded corner. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, - atRight ? 0 : 1, - atRight ? this.CORNER_RADIUS : -this.CORNER_RADIUS, - this.CORNER_RADIUS); + path.push( + 'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, atRight ? 0 : 1, + atRight ? this.CORNER_RADIUS : -this.CORNER_RADIUS, this.CORNER_RADIUS); // Bottom. path.push('h', atRight ? width : -width); path.push('z'); @@ -190,7 +191,7 @@ Blockly.VerticalFlyout.prototype.setBackgroundPath_ = function(width, height) { /** * Scroll the flyout to the top. */ -Blockly.VerticalFlyout.prototype.scrollToStart = function() { +VerticalFlyout.prototype.scrollToStart = function() { this.workspace_.scrollbar.setY(0); }; @@ -199,19 +200,19 @@ Blockly.VerticalFlyout.prototype.scrollToStart = function() { * @param {!Event} e Mouse wheel scroll event. * @protected */ -Blockly.VerticalFlyout.prototype.wheel_ = function(e) { - var scrollDelta = Blockly.utils.getScrollDeltaPixels(e); +VerticalFlyout.prototype.wheel_ = function(e) { + const scrollDelta = getScrollDeltaPixels(e); if (scrollDelta.y) { - var metricsManager = this.workspace_.getMetricsManager(); - var scrollMetrics = metricsManager.getScrollMetrics(); - var viewMetrics = metricsManager.getViewMetrics(); - var pos = (viewMetrics.top - scrollMetrics.top) + scrollDelta.y; + const metricsManager = this.workspace_.getMetricsManager(); + const scrollMetrics = metricsManager.getScrollMetrics(); + const viewMetrics = metricsManager.getViewMetrics(); + const pos = (viewMetrics.top - scrollMetrics.top) + scrollDelta.y; this.workspace_.scrollbar.setY(pos); // When the flyout moves from a wheel event, hide WidgetDiv and DropDownDiv. - Blockly.WidgetDiv.hide(); - Blockly.DropDownDiv.hideWithoutAnimation(); + WidgetDiv.hide(); + DropDownDiv.hideWithoutAnimation(); } // Don't scroll the page. @@ -226,30 +227,30 @@ Blockly.VerticalFlyout.prototype.wheel_ = function(e) { * @param {!Array} gaps The visible gaps between blocks. * @protected */ -Blockly.VerticalFlyout.prototype.layout_ = function(contents, gaps) { +VerticalFlyout.prototype.layout_ = function(contents, gaps) { this.workspace_.scale = this.targetWorkspace.scale; - var margin = this.MARGIN; - var cursorX = this.RTL ? margin : margin + this.tabWidth_; - var cursorY = margin; + const margin = this.MARGIN; + const cursorX = this.RTL ? margin : margin + this.tabWidth_; + let cursorY = margin; - for (var i = 0, item; (item = contents[i]); i++) { + for (let i = 0, item; (item = contents[i]); i++) { if (item.type == 'block') { - var block = item.block; - var allBlocks = block.getDescendants(false); - for (var j = 0, child; (child = allBlocks[j]); j++) { + const block = item.block; + const allBlocks = block.getDescendants(false); + for (let j = 0, child; (child = allBlocks[j]); j++) { // Mark blocks as being inside a flyout. This is used to detect and // prevent the closure of the flyout if the user right-clicks on such a // block. child.isInFlyout = true; } block.render(); - var root = block.getSvgRoot(); - var blockHW = block.getHeightWidth(); - var moveX = block.outputConnection ? cursorX - this.tabWidth_ : cursorX; + const root = block.getSvgRoot(); + const blockHW = block.getHeightWidth(); + const moveX = block.outputConnection ? cursorX - this.tabWidth_ : cursorX; block.moveBy(moveX, cursorY); - var rect = this.createRect_(block, - this.RTL ? moveX - blockHW.width : moveX, cursorY, blockHW, i); + const rect = this.createRect_( + block, this.RTL ? moveX - blockHW.width : moveX, cursorY, blockHW, i); this.addBlockListeners_(root, block, rect); @@ -265,19 +266,18 @@ Blockly.VerticalFlyout.prototype.layout_ = function(contents, gaps) { * Determine if a drag delta is toward the workspace, based on the position * and orientation of the flyout. This is used in determineDragIntention_ to * determine if a new block should be created or if the flyout should scroll. - * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has + * @param {!Coordinate} currentDragDeltaXY How far the pointer has * moved from the position at mouse down, in pixel units. * @return {boolean} True if the drag is toward the workspace. * @package */ -Blockly.VerticalFlyout.prototype.isDragTowardWorkspace = function( - currentDragDeltaXY) { - var dx = currentDragDeltaXY.x; - var dy = currentDragDeltaXY.y; +VerticalFlyout.prototype.isDragTowardWorkspace = function(currentDragDeltaXY) { + const dx = currentDragDeltaXY.x; + const dy = currentDragDeltaXY.y; // Direction goes from -180 to 180, with 0 toward the right and 90 on top. - var dragDirection = Math.atan2(dy, dx) / Math.PI * 180; + const dragDirection = Math.atan2(dy, dx) / Math.PI * 180; - var range = this.dragAngleRange_; + const range = this.dragAngleRange_; // Check for left or right dragging. if ((dragDirection < range && dragDirection > -range) || (dragDirection < -180 + range || dragDirection > 180 - range)) { @@ -289,28 +289,28 @@ Blockly.VerticalFlyout.prototype.isDragTowardWorkspace = function( /** * Returns the bounding rectangle of the drag target area in pixel units * relative to viewport. - * @return {?Blockly.utils.Rect} The component's bounding box. Null if drag + * @return {?Rect} The component's bounding box. Null if drag * target area should be ignored. */ -Blockly.VerticalFlyout.prototype.getClientRect = function() { +VerticalFlyout.prototype.getClientRect = function() { if (!this.svgGroup_ || this.autoClose || !this.isVisible()) { // The bounding rectangle won't compute correctly if the flyout is closed // and auto-close flyouts aren't valid drag targets (or delete areas). return null; } - var flyoutRect = this.svgGroup_.getBoundingClientRect(); + const flyoutRect = this.svgGroup_.getBoundingClientRect(); // BIG_NUM is offscreen padding so that blocks dragged beyond the shown flyout // area are still deleted. Must be larger than the largest screen size, // but be smaller than half Number.MAX_SAFE_INTEGER (not available on IE). - var BIG_NUM = 1000000000; - var left = flyoutRect.left; + const BIG_NUM = 1000000000; + const left = flyoutRect.left; - if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.LEFT) { - var width = flyoutRect.width; - return new Blockly.utils.Rect(-BIG_NUM, BIG_NUM, -BIG_NUM, left + width); + if (this.toolboxPosition_ == Position.LEFT) { + const width = flyoutRect.width; + return new Rect(-BIG_NUM, BIG_NUM, -BIG_NUM, left + width); } else { // Right - return new Blockly.utils.Rect(-BIG_NUM, BIG_NUM, left, BIG_NUM); + return new Rect(-BIG_NUM, BIG_NUM, left, BIG_NUM); } }; @@ -319,30 +319,30 @@ Blockly.VerticalFlyout.prototype.getClientRect = function() { * For RTL: Lay out the blocks and buttons to be right-aligned. * @protected */ -Blockly.VerticalFlyout.prototype.reflowInternal_ = function() { +VerticalFlyout.prototype.reflowInternal_ = function() { this.workspace_.scale = this.getFlyoutScale(); - var flyoutWidth = 0; - var blocks = this.workspace_.getTopBlocks(false); - for (var i = 0, block; (block = blocks[i]); i++) { - var width = block.getHeightWidth().width; + let flyoutWidth = 0; + const blocks = this.workspace_.getTopBlocks(false); + for (let i = 0, block; (block = blocks[i]); i++) { + let width = block.getHeightWidth().width; if (block.outputConnection) { width -= this.tabWidth_; } flyoutWidth = Math.max(flyoutWidth, width); } - for (var i = 0, button; (button = this.buttons_[i]); i++) { + for (let i = 0, button; (button = this.buttons_[i]); i++) { flyoutWidth = Math.max(flyoutWidth, button.width); } flyoutWidth += this.MARGIN * 1.5 + this.tabWidth_; flyoutWidth *= this.workspace_.scale; - flyoutWidth += Blockly.Scrollbar.scrollbarThickness; + flyoutWidth += Scrollbar.scrollbarThickness; if (this.width_ != flyoutWidth) { - for (var i = 0, block; (block = blocks[i]); i++) { + for (let i = 0, block; (block = blocks[i]); i++) { if (this.RTL) { // With the flyoutWidth known, right-align the blocks. - var oldX = block.getRelativeToSurfaceXY().x; - var newX = flyoutWidth / this.workspace_.scale - this.MARGIN; + const oldX = block.getRelativeToSurfaceXY().x; + let newX = flyoutWidth / this.workspace_.scale - this.MARGIN; if (!block.outputConnection) { newX -= this.tabWidth_; } @@ -354,22 +354,23 @@ Blockly.VerticalFlyout.prototype.reflowInternal_ = function() { } if (this.RTL) { // With the flyoutWidth known, right-align the buttons. - for (var i = 0, button; (button = this.buttons_[i]); i++) { - var y = button.getPosition().y; - var x = flyoutWidth / this.workspace_.scale - button.width - + for (let i = 0, button; (button = this.buttons_[i]); i++) { + const y = button.getPosition().y; + const x = flyoutWidth / this.workspace_.scale - button.width - this.MARGIN - this.tabWidth_; button.moveTo(x, y); } } if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_ && - this.toolboxPosition_ == Blockly.utils.toolbox.Position.LEFT && + this.toolboxPosition_ == Position.LEFT && !this.targetWorkspace.getToolbox()) { // This flyout is a simple toolbox. Reposition the workspace so that (0,0) // is in the correct position relative to the new absolute edge (ie // toolbox edge). this.targetWorkspace.translate( - this.targetWorkspace.scrollX + flyoutWidth, this.targetWorkspace.scrollY); + this.targetWorkspace.scrollX + flyoutWidth, + this.targetWorkspace.scrollY); } // Record the width for workspace metrics and .position. @@ -379,5 +380,7 @@ Blockly.VerticalFlyout.prototype.reflowInternal_ = function() { } }; -Blockly.registry.register(Blockly.registry.Type.FLYOUTS_VERTICAL_TOOLBOX, - Blockly.registry.DEFAULT, Blockly.VerticalFlyout); +registry.register( + registry.Type.FLYOUTS_VERTICAL_TOOLBOX, registry.DEFAULT, VerticalFlyout); + +exports = VerticalFlyout; diff --git a/core/gesture.js b/core/gesture.js index 483d73a25..a1ef6ca91 100644 --- a/core/gesture.js +++ b/core/gesture.js @@ -11,30 +11,41 @@ */ 'use strict'; -goog.provide('Blockly.Gesture'); +goog.module('Blockly.Gesture'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.blockAnimations'); +// TODO(#5073): Add Blockly require after fixing circular dependency. +// goog.require('Blockly'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +const BubbleDragger = goog.require('Blockly.BubbleDragger'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +/* eslint-disable-next-line no-unused-vars */ +const Events = goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const Field = goog.requireType('Blockly.Field'); +/* eslint-disable-next-line no-unused-vars */ +const IBlockDragger = goog.requireType('Blockly.IBlockDragger'); +/* eslint-disable-next-line no-unused-vars */ +const IBubble = goog.requireType('Blockly.IBubble'); +/* eslint-disable-next-line no-unused-vars */ +const IFlyout = goog.requireType('Blockly.IFlyout'); +const Tooltip = goog.require('Blockly.Tooltip'); +const Touch = goog.require('Blockly.Touch'); +/* eslint-disable-next-line no-unused-vars */ +const Workspace = goog.require('Blockly.Workspace'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +const WorkspaceDragger = goog.require('Blockly.WorkspaceDragger'); +const blockAnimations = goog.require('Blockly.blockAnimations'); +const browserEvents = goog.require('Blockly.browserEvents'); +const internalConstants = goog.require('Blockly.internalConstants'); +const registry = goog.require('Blockly.registry'); +const utils = goog.require('Blockly.utils'); /** @suppress {extraRequire} */ goog.require('Blockly.BlockDragger'); -goog.require('Blockly.browserEvents'); -goog.require('Blockly.BubbleDragger'); -goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.Click'); -goog.require('Blockly.internalConstants'); -goog.require('Blockly.Tooltip'); -goog.require('Blockly.Touch'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.Workspace'); -goog.require('Blockly.WorkspaceDragger'); - -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.Field'); -goog.requireType('Blockly.IBlockDragger'); -goog.requireType('Blockly.IBubble'); -goog.requireType('Blockly.IFlyout'); -goog.requireType('Blockly.WorkspaceSvg'); /** @@ -46,15 +57,15 @@ goog.requireType('Blockly.WorkspaceSvg'); /** * Class for one gesture. * @param {!Event} e The event that kicked off this gesture. - * @param {!Blockly.WorkspaceSvg} creatorWorkspace The workspace that created + * @param {!WorkspaceSvg} creatorWorkspace The workspace that created * this gesture and has a reference to it. * @constructor */ -Blockly.Gesture = function(e, creatorWorkspace) { +const Gesture = function(e, creatorWorkspace) { /** * The position of the mouse when the gesture started. Units are CSS pixels, * with (0, 0) at the top left of the browser window (mouseEvent clientX/Y). - * @type {Blockly.utils.Coordinate} + * @type {Coordinate} * @private */ this.mouseDownXY_ = null; @@ -62,15 +73,15 @@ Blockly.Gesture = function(e, creatorWorkspace) { /** * How far the mouse has moved during this drag, in pixel units. * (0, 0) is at this.mouseDownXY_. - * @type {!Blockly.utils.Coordinate} + * @type {!Coordinate} * @private */ - this.currentDragDeltaXY_ = new Blockly.utils.Coordinate(0, 0); + this.currentDragDeltaXY_ = new Coordinate(0, 0); /** * The bubble that the gesture started on, or null if it did not start on a * bubble. - * @type {Blockly.IBubble} + * @type {IBubble} * @private */ this.startBubble_ = null; @@ -78,7 +89,7 @@ Blockly.Gesture = function(e, creatorWorkspace) { /** * The field that the gesture started on, or null if it did not start on a * field. - * @type {Blockly.Field} + * @type {Field} * @private */ this.startField_ = null; @@ -86,7 +97,7 @@ Blockly.Gesture = function(e, creatorWorkspace) { /** * The block that the gesture started on, or null if it did not start on a * block. - * @type {Blockly.BlockSvg} + * @type {BlockSvg} * @private */ this.startBlock_ = null; @@ -96,7 +107,7 @@ Blockly.Gesture = function(e, creatorWorkspace) { * shadow block, this is the first non-shadow parent of the block. If the * gesture started in the flyout, this is the root block of the block group * that was clicked or dragged. - * @type {Blockly.BlockSvg} + * @type {BlockSvg} * @private */ this.targetBlock_ = null; @@ -105,7 +116,7 @@ Blockly.Gesture = function(e, creatorWorkspace) { * The workspace that the gesture started on. There may be multiple * workspaces on a page; this is more accurate than using * Blockly.getMainWorkspace(). - * @type {Blockly.WorkspaceSvg} + * @type {WorkspaceSvg} * @protected */ this.startWorkspace_ = null; @@ -115,7 +126,7 @@ Blockly.Gesture = function(e, creatorWorkspace) { * to the gesture, which will need to be cleared at deletion. * This may be different from the start workspace. For instance, a flyout is * a workspace, but its parent workspace manages gestures for it. - * @type {!Blockly.WorkspaceSvg} + * @type {!WorkspaceSvg} * @private */ this.creatorWorkspace_ = creatorWorkspace; @@ -160,7 +171,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 {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @protected */ this.onMoveWrapper_ = null; @@ -168,21 +179,21 @@ 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 {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @protected */ this.onUpWrapper_ = null; /** * The object tracking a bubble drag, or null if none is in progress. - * @type {Blockly.BubbleDragger} + * @type {BubbleDragger} * @private */ this.bubbleDragger_ = null; /** * The object tracking a block drag, or null if none is in progress. - * @type {?Blockly.IBlockDragger} + * @type {?IBlockDragger} * @private */ this.blockDragger_ = null; @@ -190,14 +201,14 @@ Blockly.Gesture = function(e, creatorWorkspace) { /** * The object tracking a workspace or flyout workspace drag, or null if none * is in progress. - * @type {Blockly.WorkspaceDragger} + * @type {WorkspaceDragger} * @private */ this.workspaceDragger_ = null; /** * The flyout a gesture started in, if any. - * @type {Blockly.IFlyout} + * @type {IFlyout} * @private */ this.flyout_ = null; @@ -229,24 +240,24 @@ Blockly.Gesture = function(e, creatorWorkspace) { * @type {boolean} * @private */ - this.healStack_ = !Blockly.internalConstants.DRAG_STACK; + this.healStack_ = !internalConstants.DRAG_STACK; }; /** * Sever all links from this object. * @package */ -Blockly.Gesture.prototype.dispose = function() { - Blockly.Touch.clearTouchIdentifier(); - Blockly.Tooltip.unblock(); +Gesture.prototype.dispose = function() { + Touch.clearTouchIdentifier(); + Tooltip.unblock(); // Clear the owner's reference to this gesture. this.creatorWorkspace_.clearGesture(); if (this.onMoveWrapper_) { - Blockly.browserEvents.unbind(this.onMoveWrapper_); + browserEvents.unbind(this.onMoveWrapper_); } if (this.onUpWrapper_) { - Blockly.browserEvents.unbind(this.onUpWrapper_); + browserEvents.unbind(this.onUpWrapper_); } if (this.blockDragger_) { @@ -265,9 +276,9 @@ Blockly.Gesture.prototype.dispose = function() { * @param {!Event} e The most recent mouse or touch event. * @private */ -Blockly.Gesture.prototype.updateFromEvent_ = function(e) { - var currentXY = new Blockly.utils.Coordinate(e.clientX, e.clientY); - var changed = this.updateDragDelta_(currentXY); +Gesture.prototype.updateFromEvent_ = function(e) { + const currentXY = new Coordinate(e.clientX, e.clientY); + const changed = this.updateDragDelta_(currentXY); // Exceeded the drag radius for the first time. if (changed) { this.updateIsDragging_(); @@ -278,25 +289,23 @@ Blockly.Gesture.prototype.updateFromEvent_ = function(e) { /** * DO MATH to set currentDragDeltaXY_ based on the most recent mouse position. - * @param {!Blockly.utils.Coordinate} currentXY The most recent mouse/pointer + * @param {!Coordinate} currentXY The most recent mouse/pointer * position, in pixel units, with (0, 0) at the window's top left corner. * @return {boolean} True if the drag just exceeded the drag radius for the * first time. * @private */ -Blockly.Gesture.prototype.updateDragDelta_ = function(currentXY) { - this.currentDragDeltaXY_ = Blockly.utils.Coordinate.difference( +Gesture.prototype.updateDragDelta_ = function(currentXY) { + this.currentDragDeltaXY_ = Coordinate.difference( currentXY, - /** @type {!Blockly.utils.Coordinate} */ (this.mouseDownXY_)); + /** @type {!Coordinate} */ (this.mouseDownXY_)); if (!this.hasExceededDragRadius_) { - var currentDragDelta = - Blockly.utils.Coordinate.magnitude(this.currentDragDeltaXY_); + const currentDragDelta = Coordinate.magnitude(this.currentDragDeltaXY_); // The flyout has a different drag radius from the rest of Blockly. - var limitRadius = this.flyout_ ? - Blockly.internalConstants.FLYOUT_DRAG_RADIUS : - Blockly.internalConstants.DRAG_RADIUS; + const limitRadius = this.flyout_ ? internalConstants.FLYOUT_DRAG_RADIUS : + internalConstants.DRAG_RADIUS; this.hasExceededDragRadius_ = currentDragDelta > limitRadius; return this.hasExceededDragRadius_; @@ -314,7 +323,7 @@ Blockly.Gesture.prototype.updateDragDelta_ = function(currentXY) { * @return {boolean} True if a block is being dragged from the flyout. * @private */ -Blockly.Gesture.prototype.updateIsDraggingFromFlyout_ = function() { +Gesture.prototype.updateIsDraggingFromFlyout_ = function() { if (!this.targetBlock_) { return false; } @@ -327,8 +336,8 @@ Blockly.Gesture.prototype.updateIsDraggingFromFlyout_ = function() { this.startWorkspace_.updateScreenCalculationsIfScrolled(); // Start the event group now, so that the same event group is used for block // creation and block dragging. - if (!Blockly.Events.getGroup()) { - Blockly.Events.setGroup(true); + if (!Events.getGroup()) { + Events.setGroup(true); } // The start block is no longer relevant, because this is a drag. this.startBlock_ = null; @@ -348,7 +357,7 @@ Blockly.Gesture.prototype.updateIsDraggingFromFlyout_ = function() { * @return {boolean} True if a bubble is being dragged. * @private */ -Blockly.Gesture.prototype.updateIsDraggingBubble_ = function() { +Gesture.prototype.updateIsDraggingBubble_ = function() { if (!this.startBubble_) { return false; } @@ -367,7 +376,7 @@ Blockly.Gesture.prototype.updateIsDraggingBubble_ = function() { * @return {boolean} True if a block is being dragged. * @private */ -Blockly.Gesture.prototype.updateIsDraggingBlock_ = function() { +Gesture.prototype.updateIsDraggingBlock_ = function() { if (!this.targetBlock_) { return false; } @@ -393,8 +402,8 @@ Blockly.Gesture.prototype.updateIsDraggingBlock_ = function() { * WorkspaceDragger and starts the drag. * @private */ -Blockly.Gesture.prototype.updateIsDraggingWorkspace_ = function() { - var wsMovable = this.flyout_ ? +Gesture.prototype.updateIsDraggingWorkspace_ = function() { + const wsMovable = this.flyout_ ? this.flyout_.isScrollable() : this.startWorkspace_ && this.startWorkspace_.isDraggable(); @@ -402,8 +411,8 @@ Blockly.Gesture.prototype.updateIsDraggingWorkspace_ = function() { return; } - this.workspaceDragger_ = new Blockly.WorkspaceDragger( - /** @type {!Blockly.WorkspaceSvg} */ (this.startWorkspace_)); + this.workspaceDragger_ = new WorkspaceDragger( + /** @type {!WorkspaceSvg} */ (this.startWorkspace_)); this.isDraggingWorkspace_ = true; this.workspaceDragger_.startDrag(); @@ -415,7 +424,7 @@ Blockly.Gesture.prototype.updateIsDraggingWorkspace_ = function() { * drag radius is exceeded. It should be called no more than once per gesture. * @private */ -Blockly.Gesture.prototype.updateIsDragging_ = function() { +Gesture.prototype.updateIsDragging_ = function() { // Sanity check. if (this.calledUpdateIsDragging_) { throw Error('updateIsDragging_ should only be called once per gesture.'); @@ -438,13 +447,13 @@ Blockly.Gesture.prototype.updateIsDragging_ = function() { * Create a block dragger and start dragging the selected block. * @private */ -Blockly.Gesture.prototype.startDraggingBlock_ = function() { - var BlockDraggerClass = Blockly.registry.getClassFromOptions( - Blockly.registry.Type.BLOCK_DRAGGER, this.creatorWorkspace_.options, true); +Gesture.prototype.startDraggingBlock_ = function() { + const BlockDraggerClass = registry.getClassFromOptions( + registry.Type.BLOCK_DRAGGER, this.creatorWorkspace_.options, true); this.blockDragger_ = new BlockDraggerClass( - /** @type {!Blockly.BlockSvg} */ (this.targetBlock_), - /** @type {!Blockly.WorkspaceSvg} */ (this.startWorkspace_)); + /** @type {!BlockSvg} */ (this.targetBlock_), + /** @type {!WorkspaceSvg} */ (this.startWorkspace_)); this.blockDragger_.startDrag(this.currentDragDeltaXY_, this.healStack_); this.blockDragger_.drag(this.mostRecentEvent_, this.currentDragDeltaXY_); }; @@ -454,10 +463,10 @@ Blockly.Gesture.prototype.startDraggingBlock_ = function() { * @private */ // TODO (fenichel): Possibly combine this and startDraggingBlock_. -Blockly.Gesture.prototype.startDraggingBubble_ = function() { - this.bubbleDragger_ = new Blockly.BubbleDragger( - /** @type {!Blockly.IBubble} */ (this.startBubble_), - /** @type {!Blockly.WorkspaceSvg} */ (this.startWorkspace_)); +Gesture.prototype.startDraggingBubble_ = function() { + this.bubbleDragger_ = new BubbleDragger( + /** @type {!IBubble} */ (this.startBubble_), + /** @type {!WorkspaceSvg} */ (this.startWorkspace_)); this.bubbleDragger_.startBubbleDrag(); this.bubbleDragger_.dragBubble( this.mostRecentEvent_, this.currentDragDeltaXY_); @@ -468,14 +477,14 @@ Blockly.Gesture.prototype.startDraggingBubble_ = function() { * @param {!Event} e A mouse down or touch start event. * @package */ -Blockly.Gesture.prototype.doStart = function(e) { - if (Blockly.utils.isTargetInput(e)) { +Gesture.prototype.doStart = function(e) { + if (utils.isTargetInput(e)) { this.cancel(); return; } this.hasStarted_ = true; - Blockly.blockAnimations.disconnectUiStop(); + blockAnimations.disconnectUiStop(); this.startWorkspace_.updateScreenCalculationsIfScrolled(); if (this.startWorkspace_.isMutator) { // Mutator's coordinate system could be out of date because the bubble was @@ -490,13 +499,13 @@ Blockly.Gesture.prototype.doStart = function(e) { this.startWorkspace_.markFocused(); this.mostRecentEvent_ = e; - Blockly.Tooltip.block(); + Tooltip.block(); if (this.targetBlock_) { this.targetBlock_.select(); } - if (Blockly.utils.isRightButton(e)) { + if (utils.isRightButton(e)) { this.handleRightClick(e); return; } @@ -507,7 +516,7 @@ Blockly.Gesture.prototype.doStart = function(e) { Blockly.longStart(e, this); } - this.mouseDownXY_ = new Blockly.utils.Coordinate(e.clientX, e.clientY); + this.mouseDownXY_ = new Coordinate(e.clientX, e.clientY); this.healStack_ = e.altKey || e.ctrlKey || e.metaKey; this.bindMouseEvents(e); @@ -518,10 +527,10 @@ Blockly.Gesture.prototype.doStart = function(e) { * @param {!Event} e A mouse down or touch start event. * @package */ -Blockly.Gesture.prototype.bindMouseEvents = function(e) { - this.onMoveWrapper_ = Blockly.browserEvents.conditionalBind( +Gesture.prototype.bindMouseEvents = function(e) { + this.onMoveWrapper_ = browserEvents.conditionalBind( document, 'mousemove', null, this.handleMove.bind(this)); - this.onUpWrapper_ = Blockly.browserEvents.conditionalBind( + this.onUpWrapper_ = browserEvents.conditionalBind( document, 'mouseup', null, this.handleUp.bind(this)); e.preventDefault(); @@ -533,13 +542,12 @@ Blockly.Gesture.prototype.bindMouseEvents = function(e) { * @param {!Event} e A mouse move or touch move event. * @package */ -Blockly.Gesture.prototype.handleMove = function(e) { +Gesture.prototype.handleMove = function(e) { this.updateFromEvent_(e); if (this.isDraggingWorkspace_) { this.workspaceDragger_.drag(this.currentDragDeltaXY_); } else if (this.isDraggingBlock_) { - this.blockDragger_.drag( - this.mostRecentEvent_, this.currentDragDeltaXY_); + this.blockDragger_.drag(this.mostRecentEvent_, this.currentDragDeltaXY_); } else if (this.isDraggingBubble_) { this.bubbleDragger_.dragBubble( this.mostRecentEvent_, this.currentDragDeltaXY_); @@ -553,7 +561,7 @@ Blockly.Gesture.prototype.handleMove = function(e) { * @param {!Event} e A mouse up or touch end event. * @package */ -Blockly.Gesture.prototype.handleUp = function(e) { +Gesture.prototype.handleUp = function(e) { this.updateFromEvent_(e); Blockly.longStop_(); @@ -595,7 +603,7 @@ Blockly.Gesture.prototype.handleUp = function(e) { * end the drag at the most recent location. * @package */ -Blockly.Gesture.prototype.cancel = function() { +Gesture.prototype.cancel = function() { // Disposing of a block cancels in-progress drags, but dragging to a delete // area disposes of a block and leads to recursive disposal. Break that cycle. if (this.isEnding_) { @@ -606,8 +614,7 @@ Blockly.Gesture.prototype.cancel = function() { this.bubbleDragger_.endBubbleDrag( this.mostRecentEvent_, this.currentDragDeltaXY_); } else if (this.isDraggingBlock_) { - this.blockDragger_.endDrag( - this.mostRecentEvent_, this.currentDragDeltaXY_); + this.blockDragger_.endDrag(this.mostRecentEvent_, this.currentDragDeltaXY_); } else if (this.isDraggingWorkspace_) { this.workspaceDragger_.endDrag(this.currentDragDeltaXY_); } @@ -619,7 +626,7 @@ Blockly.Gesture.prototype.cancel = function() { * @param {!Event} e A mouse move or touch move event. * @package */ -Blockly.Gesture.prototype.handleRightClick = function(e) { +Gesture.prototype.handleRightClick = function(e) { if (this.targetBlock_) { this.bringBlockToFront_(); Blockly.hideChaff(!!this.flyout_); @@ -641,10 +648,10 @@ Blockly.Gesture.prototype.handleRightClick = function(e) { /** * Handle a mousedown/touchstart event on a workspace. * @param {!Event} e A mouse down or touch start event. - * @param {!Blockly.WorkspaceSvg} ws The workspace the event hit. + * @param {!WorkspaceSvg} ws The workspace the event hit. * @package */ -Blockly.Gesture.prototype.handleWsStart = function(e, ws) { +Gesture.prototype.handleWsStart = function(e, ws) { if (this.hasStarted_) { throw Error( 'Tried to call gesture.handleWsStart, ' + @@ -657,21 +664,20 @@ Blockly.Gesture.prototype.handleWsStart = function(e, ws) { /** * Fires a workspace click event. - * @param {!Blockly.WorkspaceSvg} ws The workspace that a user clicks on. + * @param {!WorkspaceSvg} ws The workspace that a user clicks on. * @private */ -Blockly.Gesture.prototype.fireWorkspaceClick_ = function(ws) { - Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.CLICK))( - null, ws.id, 'workspace')); +Gesture.prototype.fireWorkspaceClick_ = function(ws) { + Events.fire(new (Events.get(Events.CLICK))(null, ws.id, 'workspace')); }; /** * Handle a mousedown/touchstart event on a flyout. * @param {!Event} e A mouse down or touch start event. - * @param {!Blockly.IFlyout} flyout The flyout the event hit. + * @param {!IFlyout} flyout The flyout the event hit. * @package */ -Blockly.Gesture.prototype.handleFlyoutStart = function(e, flyout) { +Gesture.prototype.handleFlyoutStart = function(e, flyout) { if (this.hasStarted_) { throw Error( 'Tried to call gesture.handleFlyoutStart, ' + @@ -684,10 +690,10 @@ Blockly.Gesture.prototype.handleFlyoutStart = function(e, flyout) { /** * Handle a mousedown/touchstart event on a block. * @param {!Event} e A mouse down or touch start event. - * @param {!Blockly.BlockSvg} block The block the event hit. + * @param {!BlockSvg} block The block the event hit. * @package */ -Blockly.Gesture.prototype.handleBlockStart = function(e, block) { +Gesture.prototype.handleBlockStart = function(e, block) { if (this.hasStarted_) { throw Error( 'Tried to call gesture.handleBlockStart, ' + @@ -700,10 +706,10 @@ Blockly.Gesture.prototype.handleBlockStart = function(e, block) { /** * Handle a mousedown/touchstart event on a bubble. * @param {!Event} e A mouse down or touch start event. - * @param {!Blockly.IBubble} bubble The bubble the event hit. + * @param {!IBubble} bubble The bubble the event hit. * @package */ -Blockly.Gesture.prototype.handleBubbleStart = function(e, bubble) { +Gesture.prototype.handleBubbleStart = function(e, bubble) { if (this.hasStarted_) { throw Error( 'Tried to call gesture.handleBubbleStart, ' + @@ -721,7 +727,7 @@ Blockly.Gesture.prototype.handleBubbleStart = function(e, bubble) { * Execute a bubble click. * @private */ -Blockly.Gesture.prototype.doBubbleClick_ = function() { +Gesture.prototype.doBubbleClick_ = function() { // TODO (#1673): Consistent handling of single clicks. this.startBubble_.setFocus && this.startBubble_.setFocus(); this.startBubble_.select && this.startBubble_.select(); @@ -731,7 +737,7 @@ Blockly.Gesture.prototype.doBubbleClick_ = function() { * Execute a field click. * @private */ -Blockly.Gesture.prototype.doFieldClick_ = function() { +Gesture.prototype.doFieldClick_ = function() { this.startField_.showEditor(this.mostRecentEvent_); this.bringBlockToFront_(); }; @@ -740,24 +746,24 @@ Blockly.Gesture.prototype.doFieldClick_ = function() { * Execute a block click. * @private */ -Blockly.Gesture.prototype.doBlockClick_ = function() { +Gesture.prototype.doBlockClick_ = function() { // Block click in an autoclosing flyout. if (this.flyout_ && this.flyout_.autoClose) { if (this.targetBlock_.isEnabled()) { - if (!Blockly.Events.getGroup()) { - Blockly.Events.setGroup(true); + if (!Events.getGroup()) { + Events.setGroup(true); } - var newBlock = this.flyout_.createBlock(this.targetBlock_); + const newBlock = this.flyout_.createBlock(this.targetBlock_); newBlock.scheduleSnapAndBump(); } } else { // Clicks events are on the start block, even if it was a shadow. - var event = new (Blockly.Events.get(Blockly.Events.CLICK))( + const event = new (Events.get(Events.CLICK))( this.startBlock_, this.startWorkspace_.id, 'block'); - Blockly.Events.fire(event); + Events.fire(event); } this.bringBlockToFront_(); - Blockly.Events.setGroup(false); + Events.setGroup(false); }; /** @@ -766,8 +772,8 @@ Blockly.Gesture.prototype.doBlockClick_ = function() { * @param {!Event} _e A mouse up or touch end event. * @private */ -Blockly.Gesture.prototype.doWorkspaceClick_ = function(_e) { - var ws = this.creatorWorkspace_; +Gesture.prototype.doWorkspaceClick_ = function(_e) { + const ws = this.creatorWorkspace_; if (Blockly.selected) { Blockly.selected.unselect(); } @@ -783,7 +789,7 @@ Blockly.Gesture.prototype.doWorkspaceClick_ = function(_e) { * not occluded by other blocks. * @private */ -Blockly.Gesture.prototype.bringBlockToFront_ = function() { +Gesture.prototype.bringBlockToFront_ = function() { // Blocks in the flyout don't overlap, so skip the work. if (this.targetBlock_ && !this.flyout_) { this.targetBlock_.bringToFront(); @@ -794,10 +800,10 @@ Blockly.Gesture.prototype.bringBlockToFront_ = function() { /** * Record the field that a gesture started on. - * @param {Blockly.Field} field The field the gesture started on. + * @param {Field} field The field the gesture started on. * @package */ -Blockly.Gesture.prototype.setStartField = function(field) { +Gesture.prototype.setStartField = function(field) { if (this.hasStarted_) { throw Error( 'Tried to call gesture.setStartField, ' + @@ -810,10 +816,10 @@ Blockly.Gesture.prototype.setStartField = function(field) { /** * Record the bubble that a gesture started on - * @param {Blockly.IBubble} bubble The bubble the gesture started on. + * @param {IBubble} bubble The bubble the gesture started on. * @package */ -Blockly.Gesture.prototype.setStartBubble = function(bubble) { +Gesture.prototype.setStartBubble = function(bubble) { if (!this.startBubble_) { this.startBubble_ = bubble; } @@ -822,10 +828,10 @@ Blockly.Gesture.prototype.setStartBubble = function(bubble) { /** * Record the block that a gesture started on, and set the target block * appropriately. - * @param {Blockly.BlockSvg} block The block the gesture started on. + * @param {BlockSvg} block The block the gesture started on. * @package */ -Blockly.Gesture.prototype.setStartBlock = function(block) { +Gesture.prototype.setStartBlock = function(block) { // If the gesture already went through a bubble, don't set the start block. if (!this.startBlock_ && !this.startBubble_) { this.startBlock_ = block; @@ -841,10 +847,10 @@ Blockly.Gesture.prototype.setStartBlock = function(block) { * Record the block that a gesture targets, meaning the block that will be * dragged if this turns into a drag. If this block is a shadow, that will be * its first non-shadow parent. - * @param {Blockly.BlockSvg} block The block the gesture targets. + * @param {BlockSvg} block The block the gesture targets. * @private */ -Blockly.Gesture.prototype.setTargetBlock_ = function(block) { +Gesture.prototype.setTargetBlock_ = function(block) { if (block.isShadow()) { this.setTargetBlock_(block.getParent()); } else { @@ -854,10 +860,10 @@ Blockly.Gesture.prototype.setTargetBlock_ = function(block) { /** * Record the workspace that a gesture started on. - * @param {Blockly.WorkspaceSvg} ws The workspace the gesture started on. + * @param {WorkspaceSvg} ws The workspace the gesture started on. * @private */ -Blockly.Gesture.prototype.setStartWorkspace_ = function(ws) { +Gesture.prototype.setStartWorkspace_ = function(ws) { if (!this.startWorkspace_) { this.startWorkspace_ = ws; } @@ -865,10 +871,10 @@ Blockly.Gesture.prototype.setStartWorkspace_ = function(ws) { /** * Record the flyout that a gesture started on. - * @param {Blockly.IFlyout} flyout The flyout the gesture started on. + * @param {IFlyout} flyout The flyout the gesture started on. * @private */ -Blockly.Gesture.prototype.setStartFlyout_ = function(flyout) { +Gesture.prototype.setStartFlyout_ = function(flyout) { if (!this.flyout_) { this.flyout_ = flyout; } @@ -886,9 +892,9 @@ Blockly.Gesture.prototype.setStartFlyout_ = function(flyout) { * @return {boolean} Whether this gesture was a click on a bubble. * @private */ -Blockly.Gesture.prototype.isBubbleClick_ = function() { +Gesture.prototype.isBubbleClick_ = function() { // A bubble click starts on a bubble and never escapes the drag radius. - var hasStartBubble = !!this.startBubble_; + const hasStartBubble = !!this.startBubble_; return hasStartBubble && !this.hasExceededDragRadius_; }; @@ -898,10 +904,10 @@ Blockly.Gesture.prototype.isBubbleClick_ = function() { * @return {boolean} Whether this gesture was a click on a block. * @private */ -Blockly.Gesture.prototype.isBlockClick_ = function() { +Gesture.prototype.isBlockClick_ = function() { // A block click starts on a block, never escapes the drag radius, and is not // a field click. - var hasStartBlock = !!this.startBlock_; + const hasStartBlock = !!this.startBlock_; return hasStartBlock && !this.hasExceededDragRadius_ && !this.isFieldClick_(); }; @@ -911,8 +917,8 @@ Blockly.Gesture.prototype.isBlockClick_ = function() { * @return {boolean} Whether this gesture was a click on a field. * @private */ -Blockly.Gesture.prototype.isFieldClick_ = function() { - var fieldClickable = +Gesture.prototype.isFieldClick_ = function() { + const fieldClickable = this.startField_ ? this.startField_.isClickable() : false; return fieldClickable && !this.hasExceededDragRadius_ && (!this.flyout_ || !this.flyout_.autoClose); @@ -924,8 +930,8 @@ Blockly.Gesture.prototype.isFieldClick_ = function() { * @return {boolean} Whether this gesture was a click on a workspace. * @private */ -Blockly.Gesture.prototype.isWorkspaceClick_ = function() { - var onlyTouchedWorkspace = +Gesture.prototype.isWorkspaceClick_ = function() { + const onlyTouchedWorkspace = !this.startBlock_ && !this.startBubble_ && !this.startField_; return onlyTouchedWorkspace && !this.hasExceededDragRadius_; }; @@ -939,7 +945,7 @@ Blockly.Gesture.prototype.isWorkspaceClick_ = function() { * @return {boolean} True if this gesture is a drag of a workspace or block. * @package */ -Blockly.Gesture.prototype.isDragging = function() { +Gesture.prototype.isDragging = function() { return this.isDraggingWorkspace_ || this.isDraggingBlock_ || this.isDraggingBubble_; }; @@ -951,18 +957,18 @@ Blockly.Gesture.prototype.isDragging = function() { * @return {boolean} Whether this gesture was a click on a workspace. * @package */ -Blockly.Gesture.prototype.hasStarted = function() { +Gesture.prototype.hasStarted = function() { return this.hasStarted_; }; /** * Get a list of the insertion markers that currently exist. Block drags have * 0, 1, or 2 insertion markers. - * @return {!Array} A possibly empty list of insertion + * @return {!Array} A possibly empty list of insertion * marker blocks. * @package */ -Blockly.Gesture.prototype.getInsertionMarkers = function() { +Gesture.prototype.getInsertionMarkers = function() { if (this.blockDragger_) { return this.blockDragger_.getInsertionMarkers(); } @@ -972,10 +978,10 @@ Blockly.Gesture.prototype.getInsertionMarkers = function() { /** * Gets the current dragger if an item is being dragged. Null if nothing is * being dragged. - * @return {!Blockly.WorkspaceDragger|!Blockly.BubbleDragger|!Blockly.IBlockDragger|null} + * @return {!WorkspaceDragger|!BubbleDragger|!IBlockDragger|null} * The dragger that is currently in use or null if no drag is in progress. */ -Blockly.Gesture.prototype.getCurrentDragger = function() { +Gesture.prototype.getCurrentDragger = function() { if (this.isDraggingBlock_) { return this.blockDragger_; } else if (this.isDraggingWorkspace_) { @@ -990,12 +996,14 @@ Blockly.Gesture.prototype.getCurrentDragger = function() { * Is a drag or other gesture currently in progress on any workspace? * @return {boolean} True if gesture is occurring. */ -Blockly.Gesture.inProgress = function() { - var workspaces = Blockly.Workspace.getAll(); - for (var i = 0, workspace; (workspace = workspaces[i]); i++) { +Gesture.inProgress = function() { + const workspaces = Workspace.getAll(); + for (let i = 0, workspace; (workspace = workspaces[i]); i++) { if (workspace.currentGesture_) { return true; } } return false; }; + +exports = Gesture; diff --git a/core/input.js b/core/input.js index 443bfc83f..afa7a3358 100644 --- a/core/input.js +++ b/core/input.js @@ -10,31 +10,36 @@ */ 'use strict'; -goog.provide('Blockly.Input'); +goog.module('Blockly.Input'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Connection'); -goog.require('Blockly.fieldRegistry'); +/* eslint-disable-next-line no-unused-vars */ +const Block = goog.requireType('Blockly.Block'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +/* eslint-disable-next-line no-unused-vars */ +const Connection = goog.require('Blockly.Connection'); +/* eslint-disable-next-line no-unused-vars */ +const Field = goog.requireType('Blockly.Field'); +/* eslint-disable-next-line no-unused-vars */ +const RenderedConnection = goog.requireType('Blockly.RenderedConnection'); +const constants = goog.require('Blockly.constants'); +const fieldRegistry = goog.require('Blockly.fieldRegistry'); +const inputTypes = goog.require('Blockly.inputTypes'); /** @suppress {extraRequire} */ goog.require('Blockly.FieldLabel'); -goog.require('Blockly.inputTypes'); - -goog.requireType('Blockly.Block'); -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.Field'); -goog.requireType('Blockly.RenderedConnection'); - /** * Class for an input with an optional field. * @param {number} type The type of the input. * @param {string} name Language-neutral identifier which may used to find this * input again. - * @param {!Blockly.Block} block The block containing this input. - * @param {Blockly.Connection} connection Optional connection for this input. + * @param {!Block} block The block containing this input. + * @param {Connection} connection Optional connection for this input. * @constructor */ -Blockly.Input = function(type, name, block, connection) { - if (type != Blockly.inputTypes.DUMMY && !name) { +const Input = function(type, name, block, connection) { + if (type != inputTypes.DUMMY && !name) { throw Error('Value inputs and statement inputs must have non-empty name.'); } /** @type {number} */ @@ -42,13 +47,13 @@ Blockly.Input = function(type, name, block, connection) { /** @type {string} */ this.name = name; /** - * @type {!Blockly.Block} + * @type {!Block} * @private */ this.sourceBlock_ = block; - /** @type {Blockly.Connection} */ + /** @type {Connection} */ this.connection = connection; - /** @type {!Array} */ + /** @type {!Array} */ this.fieldRow = []; }; @@ -56,32 +61,32 @@ Blockly.Input = function(type, name, block, connection) { * Alignment of input's fields (left, right or centre). * @type {number} */ -Blockly.Input.prototype.align = Blockly.constants.ALIGN.LEFT; +Input.prototype.align = constants.ALIGN.LEFT; /** * Is the input visible? * @type {boolean} * @private */ -Blockly.Input.prototype.visible_ = true; +Input.prototype.visible_ = true; /** * Get the source block for this input. - * @return {?Blockly.Block} The source block, or null if there is none. + * @return {?Block} The source block, or null if there is none. */ -Blockly.Input.prototype.getSourceBlock = function() { +Input.prototype.getSourceBlock = function() { return this.sourceBlock_; }; /** * Add a field (or label from string), and all prefix and suffix fields, to the * end of the input's field row. - * @param {string|!Blockly.Field} field Something to add as a field. + * @param {string|!Field} field Something to add as a field. * @param {string=} opt_name Language-neutral identifier which may used to find * this field again. Should be unique to the host block. - * @return {!Blockly.Input} The input being append to (to allow chaining). + * @return {!Input} The input being append to (to allow chaining). */ -Blockly.Input.prototype.appendField = function(field, opt_name) { +Input.prototype.appendField = function(field, opt_name) { this.insertFieldAt(this.fieldRow.length, field, opt_name); return this; }; @@ -90,12 +95,12 @@ Blockly.Input.prototype.appendField = function(field, opt_name) { * Inserts a field (or label from string), and all prefix and suffix fields, at * the location of the input's field row. * @param {number} index The index at which to insert field. - * @param {string|!Blockly.Field} field Something to add as a field. + * @param {string|!Field} field Something to add as a field. * @param {string=} opt_name Language-neutral identifier which may used to find * this field again. Should be unique to the host block. * @return {number} The index following the last inserted field. */ -Blockly.Input.prototype.insertFieldAt = function(index, field, opt_name) { +Input.prototype.insertFieldAt = function(index, field, opt_name) { if (index < 0 || index > this.fieldRow.length) { throw Error('index ' + index + ' out of bounds.'); } @@ -107,7 +112,7 @@ Blockly.Input.prototype.insertFieldAt = function(index, field, opt_name) { // Generate a FieldLabel when given a plain text field. if (typeof field == 'string') { - field = /** @type {!Blockly.Field} **/ (Blockly.fieldRegistry.fromJson({ + field = /** @type {!Field} **/ (fieldRegistry.fromJson({ 'type': 'field_label', 'text': field, })); @@ -134,7 +139,7 @@ Blockly.Input.prototype.insertFieldAt = function(index, field, opt_name) { } if (this.sourceBlock_.rendered) { - this.sourceBlock_ = /** @type {!Blockly.BlockSvg} */ (this.sourceBlock_); + this.sourceBlock_ = /** @type {!BlockSvg} */ (this.sourceBlock_); this.sourceBlock_.render(); // Adding a field will cause the block to change shape. this.sourceBlock_.bumpNeighbours(); @@ -150,13 +155,13 @@ Blockly.Input.prototype.insertFieldAt = function(index, field, opt_name) { * and opt_quiet is true. * @throws {Error} if the field is not present and opt_quiet is false. */ -Blockly.Input.prototype.removeField = function(name, opt_quiet) { - for (var i = 0, field; (field = this.fieldRow[i]); i++) { +Input.prototype.removeField = function(name, opt_quiet) { + for (let i = 0, field; (field = this.fieldRow[i]); i++) { if (field.name === name) { field.dispose(); this.fieldRow.splice(i, 1); if (this.sourceBlock_.rendered) { - this.sourceBlock_ = /** @type {!Blockly.BlockSvg} */ (this.sourceBlock_); + this.sourceBlock_ = /** @type {!BlockSvg} */ (this.sourceBlock_); this.sourceBlock_.render(); // Removing a field will cause the block to change shape. this.sourceBlock_.bumpNeighbours(); @@ -174,7 +179,7 @@ Blockly.Input.prototype.removeField = function(name, opt_quiet) { * Gets whether this input is visible or not. * @return {boolean} True if visible. */ -Blockly.Input.prototype.isVisible = function() { +Input.prototype.isVisible = function() { return this.visible_; }; @@ -182,32 +187,32 @@ Blockly.Input.prototype.isVisible = function() { * Sets whether this input is visible or not. * Should only be used to collapse/uncollapse a block. * @param {boolean} visible True if visible. - * @return {!Array} List of blocks to render. + * @return {!Array} List of blocks to render. * @package */ -Blockly.Input.prototype.setVisible = function(visible) { +Input.prototype.setVisible = function(visible) { // Note: Currently there are only unit tests for block.setCollapsed() // because this function is package. If this function goes back to being a // public API tests (lots of tests) should be added. - var renderList = []; + let renderList = []; if (this.visible_ == visible) { return renderList; } this.visible_ = visible; - for (var y = 0, field; (field = this.fieldRow[y]); y++) { + for (let y = 0, field; (field = this.fieldRow[y]); y++) { field.setVisible(visible); } if (this.connection) { this.connection = - /** @type {!Blockly.RenderedConnection} */ (this.connection); + /** @type {!RenderedConnection} */ (this.connection); // Has a connection. if (visible) { renderList = this.connection.startTrackingAll(); } else { this.connection.stopTrackingAll(); } - var child = this.connection.targetBlock(); + const child = this.connection.targetBlock(); if (child) { child.getSvgRoot().style.display = visible ? 'block' : 'none'; } @@ -219,8 +224,8 @@ Blockly.Input.prototype.setVisible = function(visible) { * Mark all fields on this input as dirty. * @package */ -Blockly.Input.prototype.markDirty = function() { - for (var y = 0, field; (field = this.fieldRow[y]); y++) { +Input.prototype.markDirty = function() { + for (let y = 0, field; (field = this.fieldRow[y]); y++) { field.markDirty(); } }; @@ -229,9 +234,9 @@ Blockly.Input.prototype.markDirty = function() { * Change a connection's compatibility. * @param {string|Array|null} check Compatible value type or * list of value types. Null if all types are compatible. - * @return {!Blockly.Input} The input being modified (to allow chaining). + * @return {!Input} The input being modified (to allow chaining). */ -Blockly.Input.prototype.setCheck = function(check) { +Input.prototype.setCheck = function(check) { if (!this.connection) { throw Error('This input does not have a connection.'); } @@ -241,14 +246,14 @@ Blockly.Input.prototype.setCheck = function(check) { /** * Change the alignment of the connection's field(s). - * @param {number} align One of the values of Blockly.constants.ALIGN. + * @param {number} align One of the values of constants.ALIGN. * In RTL mode directions are reversed, and ALIGN.RIGHT aligns to the left. - * @return {!Blockly.Input} The input being modified (to allow chaining). + * @return {!Input} The input being modified (to allow chaining). */ -Blockly.Input.prototype.setAlign = function(align) { +Input.prototype.setAlign = function(align) { this.align = align; if (this.sourceBlock_.rendered) { - this.sourceBlock_ = /** @type {!Blockly.BlockSvg} */ (this.sourceBlock_); + this.sourceBlock_ = /** @type {!BlockSvg} */ (this.sourceBlock_); this.sourceBlock_.render(); } return this; @@ -257,9 +262,9 @@ Blockly.Input.prototype.setAlign = function(align) { /** * Changes the connection's shadow block. * @param {?Element} shadow DOM representation of a block or null. - * @return {!Blockly.Input} The input being modified (to allow chaining). + * @return {!Input} The input being modified (to allow chaining). */ -Blockly.Input.prototype.setShadowDom = function(shadow) { +Input.prototype.setShadowDom = function(shadow) { if (!this.connection) { throw Error('This input does not have a connection.'); } @@ -271,7 +276,7 @@ Blockly.Input.prototype.setShadowDom = function(shadow) { * Returns the XML representation of the connection's shadow block. * @return {?Element} Shadow DOM representation of a block or null. */ -Blockly.Input.prototype.getShadowDom = function() { +Input.prototype.getShadowDom = function() { if (!this.connection) { throw Error('This input does not have a connection.'); } @@ -281,11 +286,11 @@ Blockly.Input.prototype.getShadowDom = function() { /** * Initialize the fields on this input. */ -Blockly.Input.prototype.init = function() { +Input.prototype.init = function() { if (!this.sourceBlock_.workspace.rendered) { return; // Headless blocks don't need fields initialized. } - for (var i = 0; i < this.fieldRow.length; i++) { + for (let i = 0; i < this.fieldRow.length; i++) { this.fieldRow[i].init(); } }; @@ -294,8 +299,8 @@ Blockly.Input.prototype.init = function() { * Sever all links to this input. * @suppress {checkTypes} */ -Blockly.Input.prototype.dispose = function() { - for (var i = 0, field; (field = this.fieldRow[i]); i++) { +Input.prototype.dispose = function() { + for (let i = 0, field; (field = this.fieldRow[i]); i++) { field.dispose(); } if (this.connection) { @@ -303,3 +308,5 @@ Blockly.Input.prototype.dispose = function() { } this.sourceBlock_ = null; }; + +exports = Input; diff --git a/core/interfaces/i_keyboard_accessible.js b/core/interfaces/i_keyboard_accessible.js index 8243e67d1..04704a2fe 100644 --- a/core/interfaces/i_keyboard_accessible.js +++ b/core/interfaces/i_keyboard_accessible.js @@ -15,7 +15,7 @@ goog.module('Blockly.IKeyboardAccessible'); goog.module.declareLegacyNamespace(); /* eslint-disable-next-line no-unused-vars */ -const {KeyboardShortcut} = goog.requireType('Blockly.ShortcutRegistry'); +const ShortcutRegistry = goog.requireType('Blockly.ShortcutRegistry'); /** @@ -26,7 +26,8 @@ const IKeyboardAccessible = function() {}; /** * Handles the given keyboard shortcut. - * @param {!KeyboardShortcut} shortcut The shortcut to be handled. + * @param {!ShortcutRegistry.KeyboardShortcut} shortcut The shortcut to be + * handled. * @return {boolean} True if the shortcut has been handled, false otherwise. */ IKeyboardAccessible.prototype.onShortcut; diff --git a/core/keyboard_nav/ast_node.js b/core/keyboard_nav/ast_node.js index d86a22a4c..b52ca1b18 100644 --- a/core/keyboard_nav/ast_node.js +++ b/core/keyboard_nav/ast_node.js @@ -10,18 +10,25 @@ */ 'use strict'; -goog.provide('Blockly.ASTNode'); +goog.module('Blockly.ASTNode'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.connectionTypes'); -goog.require('Blockly.utils.Coordinate'); - -goog.requireType('Blockly.Block'); -goog.requireType('Blockly.Connection'); -goog.requireType('Blockly.Field'); -goog.requireType('Blockly.IASTNodeLocation'); -goog.requireType('Blockly.IASTNodeLocationWithBlock'); -goog.requireType('Blockly.Input'); -goog.requireType('Blockly.Workspace'); +/* eslint-disable-next-line no-unused-vars */ +const Block = goog.requireType('Blockly.Block'); +/* eslint-disable-next-line no-unused-vars */ +const Connection = goog.requireType('Blockly.Connection'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +/* eslint-disable-next-line no-unused-vars */ +const Field = goog.requireType('Blockly.Field'); +/* eslint-disable-next-line no-unused-vars */ +const IASTNodeLocation = goog.requireType('Blockly.IASTNodeLocation'); +/* eslint-disable-next-line no-unused-vars */ +const IASTNodeLocationWithBlock = goog.requireType('Blockly.IASTNodeLocationWithBlock'); +/* eslint-disable-next-line no-unused-vars */ +const Input = goog.requireType('Blockly.Input'); +/* eslint-disable-next-line no-unused-vars */ +const Workspace = goog.requireType('Blockly.Workspace'); +const connectionTypes = goog.require('Blockly.connectionTypes'); /** @@ -29,19 +36,19 @@ goog.requireType('Blockly.Workspace'); * It is recommended that you use one of the createNode methods instead of * creating a node directly. * @param {string} type The type of the location. - * Must be in Blockly.ASTNode.types. - * @param {!Blockly.IASTNodeLocation} location The position in the AST. - * @param {!Blockly.ASTNode.Params=} opt_params Optional dictionary of options. + * Must be in ASTNode.types. + * @param {!IASTNodeLocation} location The position in the AST. + * @param {!ASTNode.Params=} opt_params Optional dictionary of options. * @constructor */ -Blockly.ASTNode = function(type, location, opt_params) { +const ASTNode = function(type, location, opt_params) { if (!location) { throw Error('Cannot create a node without a location.'); } /** * The type of the location. - * One of Blockly.ASTNode.types + * One of ASTNode.types * @type {string} * @private */ @@ -52,18 +59,18 @@ Blockly.ASTNode = function(type, location, opt_params) { * @type {boolean} * @private */ - this.isConnection_ = Blockly.ASTNode.isConnectionType_(type); + this.isConnection_ = ASTNode.isConnectionType_(type); /** * The location of the AST node. - * @type {!Blockly.IASTNodeLocation} + * @type {!IASTNodeLocation} * @private */ this.location_ = location; /** * The coordinate on the workspace. - * @type {Blockly.utils.Coordinate} + * @type {Coordinate} * @private */ this.wsCoordinate_ = null; @@ -73,16 +80,16 @@ Blockly.ASTNode = function(type, location, opt_params) { /** * @typedef {{ - * wsCoordinate: Blockly.utils.Coordinate + * wsCoordinate: Coordinate * }} */ -Blockly.ASTNode.Params; +ASTNode.Params; /** * Object holding different types for an AST node. * @enum {string} */ -Blockly.ASTNode.types = { +ASTNode.types = { FIELD: 'field', BLOCK: 'block', INPUT: 'input', @@ -97,7 +104,7 @@ Blockly.ASTNode.types = { * True to navigate to all fields. False to only navigate to clickable fields. * @type {boolean} */ -Blockly.ASTNode.NAVIGATE_ALL_FIELDS = false; +ASTNode.NAVIGATE_ALL_FIELDS = false; /** * The default y offset to use when moving the cursor from a stack to the @@ -105,20 +112,20 @@ Blockly.ASTNode.NAVIGATE_ALL_FIELDS = false; * @type {number} * @private */ -Blockly.ASTNode.DEFAULT_OFFSET_Y = -20; +ASTNode.DEFAULT_OFFSET_Y = -20; /** * Whether an AST node of the given type points to a connection. - * @param {string} type The type to check. One of Blockly.ASTNode.types. + * @param {string} type The type to check. One of ASTNode.types. * @return {boolean} True if a node of the given type points to a connection. * @private */ -Blockly.ASTNode.isConnectionType_ = function(type) { +ASTNode.isConnectionType_ = function(type) { switch (type) { - case Blockly.ASTNode.types.PREVIOUS: - case Blockly.ASTNode.types.NEXT: - case Blockly.ASTNode.types.INPUT: - case Blockly.ASTNode.types.OUTPUT: + case ASTNode.types.PREVIOUS: + case ASTNode.types.NEXT: + case ASTNode.types.INPUT: + case ASTNode.types.OUTPUT: return true; } return false; @@ -126,39 +133,39 @@ Blockly.ASTNode.isConnectionType_ = function(type) { /** * Create an AST node pointing to a field. - * @param {Blockly.Field} field The location of the AST node. - * @return {Blockly.ASTNode} An AST node pointing to a field. + * @param {Field} field The location of the AST node. + * @return {ASTNode} An AST node pointing to a field. */ -Blockly.ASTNode.createFieldNode = function(field) { +ASTNode.createFieldNode = function(field) { if (!field) { return null; } - return new Blockly.ASTNode(Blockly.ASTNode.types.FIELD, field); + return new ASTNode(ASTNode.types.FIELD, field); }; /** * Creates an AST node pointing to a connection. If the connection has a parent * input then create an AST node of type input that will hold the connection. - * @param {Blockly.Connection} connection This is the connection the node will + * @param {Connection} connection This is the connection the node will * point to. - * @return {Blockly.ASTNode} An AST node pointing to a connection. + * @return {ASTNode} An AST node pointing to a connection. */ -Blockly.ASTNode.createConnectionNode = function(connection) { +ASTNode.createConnectionNode = function(connection) { if (!connection) { return null; } - var type = connection.type; - if (type == Blockly.connectionTypes.INPUT_VALUE) { - return Blockly.ASTNode.createInputNode(connection.getParentInput()); - } else if (type == Blockly.connectionTypes.NEXT_STATEMENT && - connection.getParentInput()) { - return Blockly.ASTNode.createInputNode(connection.getParentInput()); - } else if (type == Blockly.connectionTypes.NEXT_STATEMENT) { - return new Blockly.ASTNode(Blockly.ASTNode.types.NEXT, connection); - } else if (type == Blockly.connectionTypes.OUTPUT_VALUE) { - return new Blockly.ASTNode(Blockly.ASTNode.types.OUTPUT, connection); - } else if (type == Blockly.connectionTypes.PREVIOUS_STATEMENT) { - return new Blockly.ASTNode(Blockly.ASTNode.types.PREVIOUS, connection); + const type = connection.type; + if (type == connectionTypes.INPUT_VALUE) { + return ASTNode.createInputNode(connection.getParentInput()); + } else if ( + type == connectionTypes.NEXT_STATEMENT && connection.getParentInput()) { + return ASTNode.createInputNode(connection.getParentInput()); + } else if (type == connectionTypes.NEXT_STATEMENT) { + return new ASTNode(ASTNode.types.NEXT, connection); + } else if (type == connectionTypes.OUTPUT_VALUE) { + return new ASTNode(ASTNode.types.OUTPUT, connection); + } else if (type == connectionTypes.PREVIOUS_STATEMENT) { + return new ASTNode(ASTNode.types.PREVIOUS, connection); } return null; }; @@ -166,86 +173,83 @@ Blockly.ASTNode.createConnectionNode = function(connection) { /** * Creates an AST node pointing to an input. Stores the input connection as the * location. - * @param {Blockly.Input} input The input used to create an AST node. - * @return {Blockly.ASTNode} An AST node pointing to a input. + * @param {Input} input The input used to create an AST node. + * @return {ASTNode} An AST node pointing to a input. */ -Blockly.ASTNode.createInputNode = function(input) { +ASTNode.createInputNode = function(input) { if (!input || !input.connection) { return null; } - return new Blockly.ASTNode(Blockly.ASTNode.types.INPUT, input.connection); + return new ASTNode(ASTNode.types.INPUT, input.connection); }; /** * Creates an AST node pointing to a block. - * @param {Blockly.Block} block The block used to create an AST node. - * @return {Blockly.ASTNode} An AST node pointing to a block. + * @param {Block} block The block used to create an AST node. + * @return {ASTNode} An AST node pointing to a block. */ -Blockly.ASTNode.createBlockNode = function(block) { +ASTNode.createBlockNode = function(block) { if (!block) { return null; } - return new Blockly.ASTNode(Blockly.ASTNode.types.BLOCK, block); + return new ASTNode(ASTNode.types.BLOCK, block); }; /** * Create an AST node of type stack. A stack, represented by its top block, is * the set of all blocks connected to a top block, including the top block. - * @param {Blockly.Block} topBlock A top block has no parent and can be found + * @param {Block} topBlock A top block has no parent and can be found * in the list returned by workspace.getTopBlocks(). - * @return {Blockly.ASTNode} An AST node of type stack that points to the top + * @return {ASTNode} An AST node of type stack that points to the top * block on the stack. */ -Blockly.ASTNode.createStackNode = function(topBlock) { +ASTNode.createStackNode = function(topBlock) { if (!topBlock) { return null; } - return new Blockly.ASTNode(Blockly.ASTNode.types.STACK, topBlock); + return new ASTNode(ASTNode.types.STACK, topBlock); }; /** * Creates an AST node pointing to a workspace. - * @param {!Blockly.Workspace} workspace The workspace that we are on. - * @param {Blockly.utils.Coordinate} wsCoordinate The position on the workspace + * @param {!Workspace} workspace The workspace that we are on. + * @param {Coordinate} wsCoordinate The position on the workspace * for this node. - * @return {Blockly.ASTNode} An AST node pointing to a workspace and a position + * @return {ASTNode} An AST node pointing to a workspace and a position * on the workspace. */ -Blockly.ASTNode.createWorkspaceNode = function(workspace, wsCoordinate) { +ASTNode.createWorkspaceNode = function(workspace, wsCoordinate) { if (!wsCoordinate || !workspace) { return null; } - var params = { - wsCoordinate: wsCoordinate - }; - return new Blockly.ASTNode( - Blockly.ASTNode.types.WORKSPACE, workspace, params); + const params = {wsCoordinate: wsCoordinate}; + return new ASTNode(ASTNode.types.WORKSPACE, workspace, params); }; /** * Creates an AST node for the top position on a block. * This is either an output connection, previous connection, or block. - * @param {!Blockly.Block} block The block to find the top most AST node on. - * @return {Blockly.ASTNode} The AST node holding the top most position on the + * @param {!Block} block The block to find the top most AST node on. + * @return {ASTNode} The AST node holding the top most position on the * block. */ -Blockly.ASTNode.createTopNode = function(block) { - var astNode; - var topConnection = block.previousConnection || block.outputConnection; +ASTNode.createTopNode = function(block) { + let astNode; + const topConnection = block.previousConnection || block.outputConnection; if (topConnection) { - astNode = Blockly.ASTNode.createConnectionNode(topConnection); + astNode = ASTNode.createConnectionNode(topConnection); } else { - astNode = Blockly.ASTNode.createBlockNode(block); + astNode = ASTNode.createBlockNode(block); } return astNode; }; /** * Parse the optional parameters. - * @param {?Blockly.ASTNode.Params} params The user specified parameters. + * @param {?ASTNode.Params} params The user specified parameters. * @private */ -Blockly.ASTNode.prototype.processParams_ = function(params) { +ASTNode.prototype.processParams_ = function(params) { if (!params) { return; } @@ -258,28 +262,28 @@ Blockly.ASTNode.prototype.processParams_ = function(params) { * Gets the value pointed to by this node. * It is the callers responsibility to check the node type to figure out what * type of object they get back from this. - * @return {!Blockly.IASTNodeLocation} The current field, connection, workspace, or + * @return {!IASTNodeLocation} The current field, connection, workspace, or * block the cursor is on. */ -Blockly.ASTNode.prototype.getLocation = function() { +ASTNode.prototype.getLocation = function() { return this.location_; }; /** * The type of the current location. - * One of Blockly.ASTNode.types + * One of ASTNode.types * @return {string} The type of the location. */ -Blockly.ASTNode.prototype.getType = function() { +ASTNode.prototype.getType = function() { return this.type_; }; /** * The coordinate on the workspace. - * @return {Blockly.utils.Coordinate} The workspace coordinate or null if the + * @return {Coordinate} The workspace coordinate or null if the * location is not a workspace. */ -Blockly.ASTNode.prototype.getWsCoordinate = function() { +ASTNode.prototype.getWsCoordinate = function() { return this.wsCoordinate_; }; @@ -288,7 +292,7 @@ Blockly.ASTNode.prototype.getWsCoordinate = function() { * @return {boolean} [description] * @package */ -Blockly.ASTNode.prototype.isConnection = function() { +ASTNode.prototype.isConnection = function() { return this.isConnection_; }; @@ -296,25 +300,27 @@ Blockly.ASTNode.prototype.isConnection = function() { * Given an input find the next editable field or an input with a non null * connection in the same block. The current location must be an input * connection. - * @return {Blockly.ASTNode} The AST node holding the next field or connection + * @return {ASTNode} The AST node holding the next field or connection * or null if there is no editable field or input connection after the given * input. * @private */ -Blockly.ASTNode.prototype.findNextForInput_ = function() { - var location = /** @type {!Blockly.Connection} */ (this.location_); - var parentInput = location.getParentInput(); - var block = parentInput.getSourceBlock(); - var curIdx = block.inputList.indexOf(parentInput); - for (var i = curIdx + 1, input; (input = block.inputList[i]); i++) { - var fieldRow = input.fieldRow; - for (var j = 0, field; (field = fieldRow[j]); j++) { - if (field.isClickable() || Blockly.ASTNode.NAVIGATE_ALL_FIELDS) { - return Blockly.ASTNode.createFieldNode(field); +ASTNode.prototype.findNextForInput_ = function() { + const location = /** @type {!Connection} */ (this.location_); + const parentInput = location.getParentInput(); + const block = parentInput.getSourceBlock(); + const curIdx = block.inputList.indexOf(parentInput); + for (let i = curIdx + 1; i < block.inputList.length; i++) { + const input = block.inputList[i]; + const fieldRow = input.fieldRow; + for (let j = 0; j < fieldRow.length; j++) { + const field = fieldRow[j]; + if (field.isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) { + return ASTNode.createFieldNode(field); } } if (input.connection) { - return Blockly.ASTNode.createInputNode(input); + return ASTNode.createInputNode(input); } } return null; @@ -323,28 +329,29 @@ Blockly.ASTNode.prototype.findNextForInput_ = function() { /** * Given a field find the next editable field or an input with a non null * connection in the same block. The current location must be a field. - * @return {Blockly.ASTNode} The AST node pointing to the next field or + * @return {ASTNode} The AST node pointing to the next field or * connection or null if there is no editable field or input connection * after the given input. * @private */ -Blockly.ASTNode.prototype.findNextForField_ = function() { - var location = /** @type {!Blockly.Field} */ (this.location_); - var input = location.getParentInput(); - var block = location.getSourceBlock(); - var curIdx = block.inputList.indexOf(/** @type {!Blockly.Input} */ (input)); - var fieldIdx = input.fieldRow.indexOf(location) + 1; - for (var i = curIdx, newInput; (newInput = block.inputList[i]); i++) { - var fieldRow = newInput.fieldRow; +ASTNode.prototype.findNextForField_ = function() { + const location = /** @type {!Field} */ (this.location_); + const input = location.getParentInput(); + const block = location.getSourceBlock(); + const curIdx = block.inputList.indexOf(/** @type {!Input} */ (input)); + let fieldIdx = input.fieldRow.indexOf(location) + 1; + for (let i = curIdx; i < block.inputList.length; i++) { + const newInput = block.inputList[i]; + const fieldRow = newInput.fieldRow; while (fieldIdx < fieldRow.length) { - if (fieldRow[fieldIdx].isClickable() || Blockly.ASTNode.NAVIGATE_ALL_FIELDS) { - return Blockly.ASTNode.createFieldNode(fieldRow[fieldIdx]); + if (fieldRow[fieldIdx].isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) { + return ASTNode.createFieldNode(fieldRow[fieldIdx]); } fieldIdx++; } fieldIdx = 0; if (newInput.connection) { - return Blockly.ASTNode.createInputNode(newInput); + return ASTNode.createInputNode(newInput); } } return null; @@ -354,23 +361,25 @@ Blockly.ASTNode.prototype.findNextForField_ = function() { * Given an input find the previous editable field or an input with a non null * connection in the same block. The current location must be an input * connection. - * @return {Blockly.ASTNode} The AST node holding the previous field or + * @return {ASTNode} The AST node holding the previous field or * connection. * @private */ -Blockly.ASTNode.prototype.findPrevForInput_ = function() { - var location = /** @type {!Blockly.Connection} */ (this.location_); - var parentInput = location.getParentInput(); - var block = parentInput.getSourceBlock(); - var curIdx = block.inputList.indexOf(parentInput); - for (var i = curIdx, input; (input = block.inputList[i]); i--) { +ASTNode.prototype.findPrevForInput_ = function() { + const location = /** @type {!Connection} */ (this.location_); + const parentInput = location.getParentInput(); + const block = parentInput.getSourceBlock(); + const curIdx = block.inputList.indexOf(parentInput); + for (let i = curIdx; i >= 0; i--) { + const input = block.inputList[i]; if (input.connection && input !== parentInput) { - return Blockly.ASTNode.createInputNode(input); + return ASTNode.createInputNode(input); } - var fieldRow = input.fieldRow; - for (var j = fieldRow.length - 1, field; (field = fieldRow[j]); j--) { - if (field.isClickable() || Blockly.ASTNode.NAVIGATE_ALL_FIELDS) { - return Blockly.ASTNode.createFieldNode(field); + const fieldRow = input.fieldRow; + for (let j = fieldRow.length - 1; j >= 0; j--) { + const field = fieldRow[j]; + if (field.isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) { + return ASTNode.createFieldNode(field); } } } @@ -380,24 +389,25 @@ Blockly.ASTNode.prototype.findPrevForInput_ = function() { /** * Given a field find the previous editable field or an input with a non null * connection in the same block. The current location must be a field. - * @return {Blockly.ASTNode} The AST node holding the previous input or field. + * @return {ASTNode} The AST node holding the previous input or field. * @private */ -Blockly.ASTNode.prototype.findPrevForField_ = function() { - var location = /** @type {!Blockly.Field} */ (this.location_); - var parentInput = location.getParentInput(); - var block = location.getSourceBlock(); - var curIdx = block.inputList.indexOf( - /** @type {!Blockly.Input} */ (parentInput)); - var fieldIdx = parentInput.fieldRow.indexOf(location) - 1; - for (var i = curIdx, input; (input = block.inputList[i]); i--) { +ASTNode.prototype.findPrevForField_ = function() { + const location = /** @type {!Field} */ (this.location_); + const parentInput = location.getParentInput(); + const block = location.getSourceBlock(); + const curIdx = block.inputList.indexOf( + /** @type {!Input} */ (parentInput)); + let fieldIdx = parentInput.fieldRow.indexOf(location) - 1; + for (let i = curIdx; i >= 0; i--) { + const input = block.inputList[i]; if (input.connection && input !== parentInput) { - return Blockly.ASTNode.createInputNode(input); + return ASTNode.createInputNode(input); } - var fieldRow = input.fieldRow; + const fieldRow = input.fieldRow; while (fieldIdx > -1) { - if (fieldRow[fieldIdx].isClickable() || Blockly.ASTNode.NAVIGATE_ALL_FIELDS) { - return Blockly.ASTNode.createFieldNode(fieldRow[fieldIdx]); + if (fieldRow[fieldIdx].isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) { + return ASTNode.createFieldNode(fieldRow[fieldIdx]); } fieldIdx--; } @@ -412,29 +422,30 @@ Blockly.ASTNode.prototype.findPrevForField_ = function() { /** * Navigate between stacks of blocks on the workspace. * @param {boolean} forward True to go forward. False to go backwards. - * @return {Blockly.ASTNode} The first block of the next stack or null if there + * @return {ASTNode} The first block of the next stack or null if there * are no blocks on the workspace. * @private */ -Blockly.ASTNode.prototype.navigateBetweenStacks_ = function(forward) { +ASTNode.prototype.navigateBetweenStacks_ = function(forward) { var curLocation = this.getLocation(); if (curLocation.getSourceBlock) { - curLocation = /** @type {!Blockly.IASTNodeLocationWithBlock} */ ( - curLocation).getSourceBlock(); + curLocation = /** @type {!IASTNodeLocationWithBlock} */ (curLocation) + .getSourceBlock(); } if (!curLocation || !curLocation.workspace) { return null; } - var curRoot = curLocation.getRootBlock(); - var topBlocks = curRoot.workspace.getTopBlocks(true); - for (var i = 0, topBlock; (topBlock = topBlocks[i]); i++) { + const curRoot = curLocation.getRootBlock(); + const topBlocks = curRoot.workspace.getTopBlocks(true); + for (let i = 0; i < topBlocks.length; i++) { + const topBlock = topBlocks[i]; if (curRoot.id == topBlock.id) { - var offset = forward ? 1 : -1; - var resultIndex = i + offset; + const offset = forward ? 1 : -1; + const resultIndex = i + offset; if (resultIndex == -1 || resultIndex == topBlocks.length) { return null; } - return Blockly.ASTNode.createStackNode(topBlocks[resultIndex]); + return ASTNode.createStackNode(topBlocks[resultIndex]); } } throw Error('Couldn\'t find ' + (forward ? 'next' : 'previous') + ' stack?!'); @@ -444,69 +455,71 @@ Blockly.ASTNode.prototype.navigateBetweenStacks_ = function(forward) { * Finds the top most AST node for a given block. * This is either the previous connection, output connection or block depending * on what kind of connections the block has. - * @param {!Blockly.Block} block The block that we want to find the top + * @param {!Block} block The block that we want to find the top * connection on. - * @return {!Blockly.ASTNode} The AST node containing the top connection. + * @return {!ASTNode} The AST node containing the top connection. * @private */ -Blockly.ASTNode.prototype.findTopASTNodeForBlock_ = function(block) { - var topConnection = block.previousConnection || block.outputConnection; +ASTNode.prototype.findTopASTNodeForBlock_ = function(block) { + const topConnection = block.previousConnection || block.outputConnection; if (topConnection) { - return /** @type {!Blockly.ASTNode} */ (Blockly.ASTNode.createConnectionNode( - topConnection)); + return /** @type {!ASTNode} */ ( + ASTNode.createConnectionNode(topConnection)); } else { - return /** @type {!Blockly.ASTNode} */ (Blockly.ASTNode.createBlockNode( - block)); + return /** @type {!ASTNode} */ (ASTNode.createBlockNode(block)); } }; /** * Get the AST node pointing to the input that the block is nested under or if * the block is not nested then get the stack AST node. - * @param {Blockly.Block} block The source block of the current location. - * @return {Blockly.ASTNode} The AST node pointing to the input connection or + * @param {Block} block The source block of the current location. + * @return {ASTNode} The AST node pointing to the input connection or * the top block of the stack this block is in. * @private */ -Blockly.ASTNode.prototype.getOutAstNodeForBlock_ = function(block) { +ASTNode.prototype.getOutAstNodeForBlock_ = function(block) { if (!block) { return null; } - var topBlock; + let topBlock; // If the block doesn't have a previous connection then it is the top of the // substack. topBlock = block.getTopStackBlock(); - var topConnection = topBlock.previousConnection || topBlock.outputConnection; + const topConnection = + topBlock.previousConnection || topBlock.outputConnection; // If the top connection has a parentInput, create an AST node pointing to // that input. if (topConnection && topConnection.targetConnection && topConnection.targetConnection.getParentInput()) { - return Blockly.ASTNode.createInputNode( + return ASTNode.createInputNode( topConnection.targetConnection.getParentInput()); } else { // Go to stack level if you are not underneath an input. - return Blockly.ASTNode.createStackNode(topBlock); + return ASTNode.createStackNode(topBlock); } }; /** * Find the first editable field or input with a connection on a given block. - * @param {!Blockly.Block} block The source block of the current location. - * @return {Blockly.ASTNode} An AST node pointing to the first field or input. + * @param {!Block} block The source block of the current location. + * @return {ASTNode} An AST node pointing to the first field or input. * Null if there are no editable fields or inputs with connections on the block. * @private */ -Blockly.ASTNode.prototype.findFirstFieldOrInput_ = function(block) { - var inputs = block.inputList; - for (var i = 0, input; (input = inputs[i]); i++) { - var fieldRow = input.fieldRow; - for (var j = 0, field; (field = fieldRow[j]); j++) { - if (field.isClickable() || Blockly.ASTNode.NAVIGATE_ALL_FIELDS) { - return Blockly.ASTNode.createFieldNode(field); +ASTNode.prototype.findFirstFieldOrInput_ = function(block) { + const inputs = block.inputList; + for (let i = 0; i < inputs.length; i++) { + const input = inputs[i]; + const fieldRow = input.fieldRow; + for (let j = 0; j < fieldRow.length; j++) { + const field = fieldRow[j]; + if (field.isClickable() || ASTNode.NAVIGATE_ALL_FIELDS) { + return ASTNode.createFieldNode(field); } } if (input.connection) { - return Blockly.ASTNode.createInputNode(input); + return ASTNode.createInputNode(input); } } return null; @@ -514,55 +527,56 @@ Blockly.ASTNode.prototype.findFirstFieldOrInput_ = function(block) { /** * Finds the source block of the location of this node. - * @return {Blockly.Block} The source block of the location, or null if the node + * @return {Block} The source block of the location, or null if the node * is of type workspace. */ -Blockly.ASTNode.prototype.getSourceBlock = function() { - if (this.getType() === Blockly.ASTNode.types.BLOCK) { - return /** @type {Blockly.Block} */ (this.getLocation()); - } else if (this.getType() === Blockly.ASTNode.types.STACK) { - return /** @type {Blockly.Block} */ (this.getLocation()); - } else if (this.getType() === Blockly.ASTNode.types.WORKSPACE) { +ASTNode.prototype.getSourceBlock = function() { + if (this.getType() === ASTNode.types.BLOCK) { + return /** @type {Block} */ (this.getLocation()); + } else if (this.getType() === ASTNode.types.STACK) { + return /** @type {Block} */ (this.getLocation()); + } else if (this.getType() === ASTNode.types.WORKSPACE) { return null; } else { - return /** @type {Blockly.IASTNodeLocationWithBlock} */ ( - this.getLocation()).getSourceBlock(); + return /** @type {IASTNodeLocationWithBlock} */ (this.getLocation()) + .getSourceBlock(); } }; /** * Find the element to the right of the current element in the AST. - * @return {Blockly.ASTNode} An AST node that wraps the next field, connection, + * @return {ASTNode} An AST node that wraps the next field, connection, * block, or workspace. Or null if there is no node to the right. */ -Blockly.ASTNode.prototype.next = function() { +ASTNode.prototype.next = function() { switch (this.type_) { - case Blockly.ASTNode.types.STACK: + case ASTNode.types.STACK: return this.navigateBetweenStacks_(true); - case Blockly.ASTNode.types.OUTPUT: - var connection = /** @type {!Blockly.Connection} */ (this.location_); - return Blockly.ASTNode.createBlockNode(connection.getSourceBlock()); - - case Blockly.ASTNode.types.FIELD: + case ASTNode.types.OUTPUT: { + const connection = /** @type {!Connection} */ (this.location_); + return ASTNode.createBlockNode(connection.getSourceBlock()); + } + case ASTNode.types.FIELD: return this.findNextForField_(); - case Blockly.ASTNode.types.INPUT: + case ASTNode.types.INPUT: return this.findNextForInput_(); - case Blockly.ASTNode.types.BLOCK: - var block = /** @type {!Blockly.Block} */ (this.location_); - var nextConnection = block.nextConnection; - return Blockly.ASTNode.createConnectionNode(nextConnection); - - case Blockly.ASTNode.types.PREVIOUS: - var connection = /** @type {!Blockly.Connection} */ (this.location_); - return Blockly.ASTNode.createBlockNode(connection.getSourceBlock()); - - case Blockly.ASTNode.types.NEXT: - var connection = /** @type {!Blockly.Connection} */ (this.location_); - var targetConnection = connection.targetConnection; - return Blockly.ASTNode.createConnectionNode(targetConnection); + case ASTNode.types.BLOCK: { + const block = /** @type {!Block} */ (this.location_); + const nextConnection = block.nextConnection; + return ASTNode.createConnectionNode(nextConnection); + } + case ASTNode.types.PREVIOUS: { + const connection = /** @type {!Connection} */ (this.location_); + return ASTNode.createBlockNode(connection.getSourceBlock()); + } + case ASTNode.types.NEXT: { + const connection = /** @type {!Connection} */ (this.location_); + const targetConnection = connection.targetConnection; + return ASTNode.createConnectionNode(targetConnection); + } } return null; @@ -571,31 +585,32 @@ Blockly.ASTNode.prototype.next = function() { /** * Find the element one level below and all the way to the left of the current * location. - * @return {Blockly.ASTNode} An AST node that wraps the next field, connection, + * @return {ASTNode} An AST node that wraps the next field, connection, * workspace, or block. Or null if there is nothing below this node. */ -Blockly.ASTNode.prototype.in = function() { +ASTNode.prototype.in = function() { switch (this.type_) { - case Blockly.ASTNode.types.WORKSPACE: - var workspace = /** @type {!Blockly.Workspace} */ (this.location_); - var topBlocks = workspace.getTopBlocks(true); + case ASTNode.types.WORKSPACE: { + const workspace = /** @type {!Workspace} */ (this.location_); + const topBlocks = workspace.getTopBlocks(true); if (topBlocks.length > 0) { - return Blockly.ASTNode.createStackNode(topBlocks[0]); + return ASTNode.createStackNode(topBlocks[0]); } break; - - case Blockly.ASTNode.types.STACK: - var block = /** @type {!Blockly.Block} */ (this.location_); + } + case ASTNode.types.STACK: { + const block = /** @type {!Block} */ (this.location_); return this.findTopASTNodeForBlock_(block); - - case Blockly.ASTNode.types.BLOCK: - var block = /** @type {!Blockly.Block} */ (this.location_); + } + case ASTNode.types.BLOCK: { + const block = /** @type {!Block} */ (this.location_); return this.findFirstFieldOrInput_(block); - - case Blockly.ASTNode.types.INPUT: - var connection = /** @type {!Blockly.Connection} */ (this.location_); - var targetConnection = connection.targetConnection; - return Blockly.ASTNode.createConnectionNode(targetConnection); + } + case ASTNode.types.INPUT: { + const connection = /** @type {!Connection} */ (this.location_); + const targetConnection = connection.targetConnection; + return ASTNode.createConnectionNode(targetConnection); + } } return null; @@ -603,40 +618,41 @@ Blockly.ASTNode.prototype.in = function() { /** * Find the element to the left of the current element in the AST. - * @return {Blockly.ASTNode} An AST node that wraps the previous field, + * @return {ASTNode} An AST node that wraps the previous field, * connection, workspace or block. Or null if no node exists to the left. * null. */ -Blockly.ASTNode.prototype.prev = function() { +ASTNode.prototype.prev = function() { switch (this.type_) { - case Blockly.ASTNode.types.STACK: + case ASTNode.types.STACK: return this.navigateBetweenStacks_(false); - case Blockly.ASTNode.types.OUTPUT: + case ASTNode.types.OUTPUT: return null; - case Blockly.ASTNode.types.FIELD: + case ASTNode.types.FIELD: return this.findPrevForField_(); - case Blockly.ASTNode.types.INPUT: + case ASTNode.types.INPUT: return this.findPrevForInput_(); - case Blockly.ASTNode.types.BLOCK: - var block = /** @type {!Blockly.Block} */ (this.location_); - var topConnection = block.previousConnection || block.outputConnection; - return Blockly.ASTNode.createConnectionNode(topConnection); - - case Blockly.ASTNode.types.PREVIOUS: - var connection = /** @type {!Blockly.Connection} */ (this.location_); - var targetConnection = connection.targetConnection; + case ASTNode.types.BLOCK: { + const block = /** @type {!Block} */ (this.location_); + const topConnection = block.previousConnection || block.outputConnection; + return ASTNode.createConnectionNode(topConnection); + } + case ASTNode.types.PREVIOUS: { + const connection = /** @type {!Connection} */ (this.location_); + const targetConnection = connection.targetConnection; if (targetConnection && !targetConnection.getParentInput()) { - return Blockly.ASTNode.createConnectionNode(targetConnection); + return ASTNode.createConnectionNode(targetConnection); } break; - - case Blockly.ASTNode.types.NEXT: - var connection = /** @type {!Blockly.Connection} */ (this.location_); - return Blockly.ASTNode.createBlockNode(connection.getSourceBlock()); + } + case ASTNode.types.NEXT: { + const connection = /** @type {!Connection} */ (this.location_); + return ASTNode.createBlockNode(connection.getSourceBlock()); + } } return null; @@ -645,47 +661,50 @@ Blockly.ASTNode.prototype.prev = function() { /** * Find the next element that is one position above and all the way to the left * of the current location. - * @return {Blockly.ASTNode} An AST node that wraps the next field, connection, + * @return {ASTNode} An AST node that wraps the next field, connection, * workspace or block. Or null if we are at the workspace level. */ -Blockly.ASTNode.prototype.out = function() { +ASTNode.prototype.out = function() { switch (this.type_) { - case Blockly.ASTNode.types.STACK: - var block = /** @type {!Blockly.Block} */ (this.location_); - var blockPos = block.getRelativeToSurfaceXY(); + case ASTNode.types.STACK: { + const block = /** @type {!Block} */ (this.location_); + const blockPos = block.getRelativeToSurfaceXY(); // TODO: Make sure this is in the bounds of the workspace. - var wsCoordinate = new Blockly.utils.Coordinate( - blockPos.x, blockPos.y + Blockly.ASTNode.DEFAULT_OFFSET_Y); - return Blockly.ASTNode.createWorkspaceNode(block.workspace, wsCoordinate); - - case Blockly.ASTNode.types.OUTPUT: - var connection = /** @type {!Blockly.Connection} */ (this.location_); - var target = connection.targetConnection; + const wsCoordinate = + new Coordinate(blockPos.x, blockPos.y + ASTNode.DEFAULT_OFFSET_Y); + return ASTNode.createWorkspaceNode(block.workspace, wsCoordinate); + } + case ASTNode.types.OUTPUT: { + const connection = /** @type {!Connection} */ (this.location_); + const target = connection.targetConnection; if (target) { - return Blockly.ASTNode.createConnectionNode(target); + return ASTNode.createConnectionNode(target); } - return Blockly.ASTNode.createStackNode(connection.getSourceBlock()); - - case Blockly.ASTNode.types.FIELD: - var field = /** @type {!Blockly.Field} */ (this.location_); - return Blockly.ASTNode.createBlockNode(field.getSourceBlock()); - - case Blockly.ASTNode.types.INPUT: - var connection = /** @type {!Blockly.Connection} */ (this.location_); - return Blockly.ASTNode.createBlockNode(connection.getSourceBlock()); - - case Blockly.ASTNode.types.BLOCK: - var block = /** @type {!Blockly.Block} */ (this.location_); + return ASTNode.createStackNode(connection.getSourceBlock()); + } + case ASTNode.types.FIELD: { + const field = /** @type {!Field} */ (this.location_); + return ASTNode.createBlockNode(field.getSourceBlock()); + } + case ASTNode.types.INPUT: { + const connection = /** @type {!Connection} */ (this.location_); + return ASTNode.createBlockNode(connection.getSourceBlock()); + } + case ASTNode.types.BLOCK: { + const block = /** @type {!Block} */ (this.location_); return this.getOutAstNodeForBlock_(block); - - case Blockly.ASTNode.types.PREVIOUS: - var connection = /** @type {!Blockly.Connection} */ (this.location_); + } + case ASTNode.types.PREVIOUS: { + const connection = /** @type {!Connection} */ (this.location_); return this.getOutAstNodeForBlock_(connection.getSourceBlock()); - - case Blockly.ASTNode.types.NEXT: - var connection = /** @type {!Blockly.Connection} */ (this.location_); + } + case ASTNode.types.NEXT: { + const connection = /** @type {!Connection} */ (this.location_); return this.getOutAstNodeForBlock_(connection.getSourceBlock()); + } } return null; }; + +exports = ASTNode; diff --git a/core/keyboard_nav/marker.js b/core/keyboard_nav/marker.js index de31d6084..4b6f341bb 100644 --- a/core/keyboard_nav/marker.js +++ b/core/keyboard_nav/marker.js @@ -11,11 +11,13 @@ */ 'use strict'; -goog.provide('Blockly.Marker'); +goog.module('Blockly.Marker'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.ASTNode'); - -goog.requireType('Blockly.blockRendering.MarkerSvg'); +/* eslint-disable-next-line no-unused-vars */ +const ASTNode = goog.requireType('Blockly.ASTNode'); +/* eslint-disable-next-line no-unused-vars */ +const MarkerSvg = goog.requireType('Blockly.blockRendering.MarkerSvg'); /** @@ -23,7 +25,7 @@ goog.requireType('Blockly.blockRendering.MarkerSvg'); * This is used in keyboard navigation to save a location in the Blockly AST. * @constructor */ -Blockly.Marker = function() { +const Marker = function() { /** * The colour of the marker. * @type {?string} @@ -32,14 +34,15 @@ Blockly.Marker = function() { /** * The current location of the marker. - * @type {Blockly.ASTNode} + * @type {ASTNode} * @private */ this.curNode_ = null; /** - * The object in charge of drawing the visual representation of the current node. - * @type {Blockly.blockRendering.MarkerSvg} + * The object in charge of drawing the visual representation of the current + * node. + * @type {MarkerSvg} * @private */ this.drawer_ = null; @@ -53,28 +56,28 @@ Blockly.Marker = function() { /** * Sets the object in charge of drawing the marker. - * @param {Blockly.blockRendering.MarkerSvg} drawer The object in charge of + * @param {MarkerSvg} drawer The object in charge of * drawing the marker. */ -Blockly.Marker.prototype.setDrawer = function(drawer) { +Marker.prototype.setDrawer = function(drawer) { this.drawer_ = drawer; }; /** * Get the current drawer for the marker. - * @return {Blockly.blockRendering.MarkerSvg} The object in charge of drawing + * @return {MarkerSvg} The object in charge of drawing * the marker. */ -Blockly.Marker.prototype.getDrawer = function() { +Marker.prototype.getDrawer = function() { return this.drawer_; }; /** * Gets the current location of the marker. - * @return {Blockly.ASTNode} The current field, connection, or block the marker + * @return {ASTNode} The current field, connection, or block the marker * is on. */ -Blockly.Marker.prototype.getCurNode = function() { +Marker.prototype.getCurNode = function() { return this.curNode_; }; @@ -82,10 +85,10 @@ Blockly.Marker.prototype.getCurNode = function() { * Set the location of the marker and call the update method. * Setting isStack to true will only work if the newLocation is the top most * output or previous connection on a stack. - * @param {Blockly.ASTNode} newNode The new location of the marker. + * @param {ASTNode} newNode The new location of the marker. */ -Blockly.Marker.prototype.setCurNode = function(newNode) { - var oldNode = this.curNode_; +Marker.prototype.setCurNode = function(newNode) { + const oldNode = this.curNode_; this.curNode_ = newNode; if (this.drawer_) { this.drawer_.draw(oldNode, this.curNode_); @@ -96,7 +99,7 @@ Blockly.Marker.prototype.setCurNode = function(newNode) { * Redraw the current marker. * @package */ -Blockly.Marker.prototype.draw = function() { +Marker.prototype.draw = function() { if (this.drawer_) { this.drawer_.draw(this.curNode_, this.curNode_); } @@ -105,7 +108,7 @@ Blockly.Marker.prototype.draw = function() { /** * Hide the marker SVG. */ -Blockly.Marker.prototype.hide = function() { +Marker.prototype.hide = function() { if (this.drawer_) { this.drawer_.hide(); } @@ -114,8 +117,10 @@ Blockly.Marker.prototype.hide = function() { /** * Dispose of this marker. */ -Blockly.Marker.prototype.dispose = function() { +Marker.prototype.dispose = function() { if (this.getDrawer()) { this.getDrawer().dispose(); } }; + +exports = Marker; diff --git a/core/marker_manager.js b/core/marker_manager.js index 82c149052..60cb3b870 100644 --- a/core/marker_manager.js +++ b/core/marker_manager.js @@ -10,24 +10,26 @@ */ 'use strict'; -goog.provide('Blockly.MarkerManager'); +goog.module('Blockly.MarkerManager'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Cursor'); -goog.require('Blockly.Marker'); - -goog.requireType('Blockly.WorkspaceSvg'); +/* eslint-disable-next-line no-unused-vars */ +const Cursor = goog.requireType('Blockly.Cursor'); +/* eslint-disable-next-line no-unused-vars */ +const Marker = goog.requireType('Blockly.Marker'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); /** * Class to manage the multiple markers and the cursor on a workspace. - * @param {!Blockly.WorkspaceSvg} workspace The workspace for the marker manager. + * @param {!WorkspaceSvg} workspace The workspace for the marker manager. * @constructor - * @package */ -Blockly.MarkerManager = function(workspace){ +const MarkerManager = function(workspace) { /** * The cursor. - * @type {?Blockly.Cursor} + * @type {?Cursor} * @private */ this.cursor_ = null; @@ -41,14 +43,14 @@ Blockly.MarkerManager = function(workspace){ /** * The map of markers for the workspace. - * @type {!Object} + * @type {!Object} * @private */ this.markers_ = Object.create(null); /** * The workspace this marker manager is associated with. - * @type {!Blockly.WorkspaceSvg} + * @type {!WorkspaceSvg} * @private */ this.workspace_ = workspace; @@ -59,19 +61,19 @@ Blockly.MarkerManager = function(workspace){ * @type {string} * @const */ -Blockly.MarkerManager.LOCAL_MARKER = 'local_marker_1'; +MarkerManager.LOCAL_MARKER = 'local_marker_1'; /** * Register the marker by adding it to the map of markers. * @param {string} id A unique identifier for the marker. - * @param {!Blockly.Marker} marker The marker to register. + * @param {!Marker} marker The marker to register. */ -Blockly.MarkerManager.prototype.registerMarker = function(id, marker) { +MarkerManager.prototype.registerMarker = function(id, marker) { if (this.markers_[id]) { this.unregisterMarker(id); } - marker.setDrawer(this.workspace_.getRenderer() - .makeMarkerDrawer(this.workspace_, marker)); + marker.setDrawer( + this.workspace_.getRenderer().makeMarkerDrawer(this.workspace_, marker)); this.setMarkerSvg(marker.getDrawer().createDom()); this.markers_[id] = marker; }; @@ -80,47 +82,48 @@ Blockly.MarkerManager.prototype.registerMarker = function(id, marker) { * Unregister the marker by removing it from the map of markers. * @param {string} id The ID of the marker to unregister. */ -Blockly.MarkerManager.prototype.unregisterMarker = function(id) { - var marker = this.markers_[id]; +MarkerManager.prototype.unregisterMarker = function(id) { + const marker = this.markers_[id]; if (marker) { marker.dispose(); delete this.markers_[id]; } else { - throw Error('Marker with ID ' + id + ' does not exist. ' + + throw Error( + 'Marker with ID ' + id + ' does not exist. ' + 'Can only unregister markers that exist.'); } }; /** * Get the cursor for the workspace. - * @return {?Blockly.Cursor} The cursor for this workspace. + * @return {?Cursor} The cursor for this workspace. */ -Blockly.MarkerManager.prototype.getCursor = function() { +MarkerManager.prototype.getCursor = function() { return this.cursor_; }; /** * Get a single marker that corresponds to the given ID. * @param {string} id A unique identifier for the marker. - * @return {?Blockly.Marker} The marker that corresponds to the given ID, + * @return {?Marker} The marker that corresponds to the given ID, * or null if none exists. */ -Blockly.MarkerManager.prototype.getMarker = function(id) { +MarkerManager.prototype.getMarker = function(id) { return this.markers_[id] || null; }; /** * Sets the cursor and initializes the drawer for use with keyboard navigation. - * @param {Blockly.Cursor} cursor The cursor used to move around this workspace. + * @param {Cursor} cursor The cursor used to move around this workspace. */ -Blockly.MarkerManager.prototype.setCursor = function(cursor) { +MarkerManager.prototype.setCursor = function(cursor) { if (this.cursor_ && this.cursor_.getDrawer()) { this.cursor_.getDrawer().dispose(); } this.cursor_ = cursor; if (this.cursor_) { - var drawer = this.workspace_.getRenderer() - .makeMarkerDrawer(this.workspace_, this.cursor_); + const drawer = this.workspace_.getRenderer().makeMarkerDrawer( + this.workspace_, this.cursor_); this.cursor_.setDrawer(drawer); this.setCursorSvg(this.cursor_.getDrawer().createDom()); } @@ -132,7 +135,7 @@ Blockly.MarkerManager.prototype.setCursor = function(cursor) { * workspace SVG group. * @package */ -Blockly.MarkerManager.prototype.setCursorSvg = function(cursorSvg) { +MarkerManager.prototype.setCursorSvg = function(cursorSvg) { if (!cursorSvg) { this.cursorSvg_ = null; return; @@ -148,7 +151,7 @@ Blockly.MarkerManager.prototype.setCursorSvg = function(cursorSvg) { * workspace SVG group. * @package */ -Blockly.MarkerManager.prototype.setMarkerSvg = function(markerSvg) { +MarkerManager.prototype.setMarkerSvg = function(markerSvg) { if (!markerSvg) { this.markerSvg_ = null; return; @@ -167,7 +170,7 @@ Blockly.MarkerManager.prototype.setMarkerSvg = function(markerSvg) { * Redraw the attached cursor SVG if needed. * @package */ -Blockly.MarkerManager.prototype.updateMarkers = function() { +MarkerManager.prototype.updateMarkers = function() { if (this.workspace_.keyboardAccessibilityMode && this.cursorSvg_) { this.workspace_.getCursor().draw(); } @@ -179,9 +182,9 @@ Blockly.MarkerManager.prototype.updateMarkers = function() { * @suppress {checkTypes} * @package */ -Blockly.MarkerManager.prototype.dispose = function() { - var markerIds = Object.keys(this.markers_); - for (var i = 0, markerId; (markerId = markerIds[i]); i++) { +MarkerManager.prototype.dispose = function() { + const markerIds = Object.keys(this.markers_); + for (let i = 0, markerId; (markerId = markerIds[i]); i++) { this.unregisterMarker(markerId); } this.markers_ = null; @@ -190,3 +193,6 @@ Blockly.MarkerManager.prototype.dispose = function() { this.cursor_ = null; } }; + +/** @package */ +exports = MarkerManager; diff --git a/core/mutator.js b/core/mutator.js index 2733964c7..8f9bab118 100644 --- a/core/mutator.js +++ b/core/mutator.js @@ -11,81 +11,88 @@ */ 'use strict'; -goog.provide('Blockly.Mutator'); +goog.module('Blockly.Mutator'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Bubble'); -goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const Abstract = goog.requireType('Blockly.Events.Abstract'); +/* eslint-disable-next-line no-unused-vars */ +const Block = goog.requireType('Blockly.Block'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +/* eslint-disable-next-line no-unused-vars */ +const Blockly = goog.requireType('Blockly'); +const Bubble = goog.require('Blockly.Bubble'); +/* eslint-disable-next-line no-unused-vars */ +const Connection = goog.requireType('Blockly.Connection'); +/* eslint-disable-next-line no-unused-vars */ +const Coordinate = goog.requireType('Blockly.utils.Coordinate'); +const Events = goog.require('Blockly.Events'); +const Icon = goog.require('Blockly.Icon'); +const Options = goog.require('Blockly.Options'); +const Svg = goog.require('Blockly.utils.Svg'); +/* eslint-disable-next-line no-unused-vars */ +const Workspace = goog.requireType('Blockly.Workspace'); +const WorkspaceSvg = goog.require('Blockly.WorkspaceSvg'); +const Xml = goog.require('Blockly.Xml'); +const dom = goog.require('Blockly.utils.dom'); +const internalConstants = goog.require('Blockly.internalConstants'); +const object = goog.require('Blockly.utils.object'); +const toolbox = goog.require('Blockly.utils.toolbox'); +const xml = goog.require('Blockly.utils.xml'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockChange'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BubbleOpen'); -goog.require('Blockly.Icon'); -goog.require('Blockly.internalConstants'); -goog.require('Blockly.Options'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.object'); -goog.require('Blockly.utils.Svg'); -goog.require('Blockly.utils.toolbox'); -goog.require('Blockly.utils.xml'); -goog.require('Blockly.WorkspaceSvg'); -goog.require('Blockly.Xml'); - -goog.requireType('Blockly.Block'); -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.Connection'); -goog.requireType('Blockly.Events.Abstract'); -goog.requireType('Blockly.utils.Coordinate'); -goog.requireType('Blockly.Workspace'); /** * Class for a mutator dialog. * @param {!Array} quarkNames List of names of sub-blocks for flyout. - * @extends {Blockly.Icon} + * @extends {Icon} * @constructor */ -Blockly.Mutator = function(quarkNames) { - Blockly.Mutator.superClass_.constructor.call(this, null); +const Mutator = function(quarkNames) { + Mutator.superClass_.constructor.call(this, null); this.quarkNames_ = quarkNames; }; -Blockly.utils.object.inherits(Blockly.Mutator, Blockly.Icon); +object.inherits(Mutator, Icon); /** * Workspace in the mutator's bubble. - * @type {?Blockly.WorkspaceSvg} + * @type {?WorkspaceSvg} * @private */ -Blockly.Mutator.prototype.workspace_ = null; +Mutator.prototype.workspace_ = null; /** * Width of workspace. * @private */ -Blockly.Mutator.prototype.workspaceWidth_ = 0; +Mutator.prototype.workspaceWidth_ = 0; /** * Height of workspace. * @private */ -Blockly.Mutator.prototype.workspaceHeight_ = 0; +Mutator.prototype.workspaceHeight_ = 0; /** * Set the block this mutator is associated with. - * @param {!Blockly.BlockSvg} block The block associated with this mutator. + * @param {!BlockSvg} block The block associated with this mutator. * @package */ -Blockly.Mutator.prototype.setBlock = function(block) { +Mutator.prototype.setBlock = function(block) { this.block_ = block; }; /** * Returns the workspace inside this mutator icon's bubble. - * @return {?Blockly.WorkspaceSvg} The workspace inside this mutator icon's + * @return {?WorkspaceSvg} The workspace inside this mutator icon's * bubble or null if the mutator isn't open. * @package */ -Blockly.Mutator.prototype.getWorkspace = function() { +Mutator.prototype.getWorkspace = function() { return this.workspace_; }; @@ -94,11 +101,10 @@ Blockly.Mutator.prototype.getWorkspace = function() { * @param {!Element} group The icon group. * @protected */ -Blockly.Mutator.prototype.drawIcon_ = function(group) { +Mutator.prototype.drawIcon_ = function(group) { // Square with rounded corners. - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { + dom.createSvgElement( + Svg.RECT, { 'class': 'blocklyIconShape', 'rx': '4', 'ry': '4', @@ -107,29 +113,22 @@ Blockly.Mutator.prototype.drawIcon_ = function(group) { }, group); // Gear teeth. - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.PATH, - { + dom.createSvgElement( + Svg.PATH, { 'class': 'blocklyIconSymbol', 'd': 'm4.203,7.296 0,1.368 -0.92,0.677 -0.11,0.41 0.9,1.559 0.41,' + - '0.11 1.043,-0.457 1.187,0.683 0.127,1.134 0.3,0.3 1.8,0 0.3,' + - '-0.299 0.127,-1.138 1.185,-0.682 1.046,0.458 0.409,-0.11 0.9,' + - '-1.559 -0.11,-0.41 -0.92,-0.677 0,-1.366 0.92,-0.677 0.11,' + - '-0.41 -0.9,-1.559 -0.409,-0.109 -1.046,0.458 -1.185,-0.682 ' + - '-0.127,-1.138 -0.3,-0.299 -1.8,0 -0.3,0.3 -0.126,1.135 -1.187,' + - '0.682 -1.043,-0.457 -0.41,0.11 -0.899,1.559 0.108,0.409z' + '0.11 1.043,-0.457 1.187,0.683 0.127,1.134 0.3,0.3 1.8,0 0.3,' + + '-0.299 0.127,-1.138 1.185,-0.682 1.046,0.458 0.409,-0.11 0.9,' + + '-1.559 -0.11,-0.41 -0.92,-0.677 0,-1.366 0.92,-0.677 0.11,' + + '-0.41 -0.9,-1.559 -0.409,-0.109 -1.046,0.458 -1.185,-0.682 ' + + '-0.127,-1.138 -0.3,-0.299 -1.8,0 -0.3,0.3 -0.126,1.135 -1.187,' + + '0.682 -1.043,-0.457 -0.41,0.11 -0.899,1.559 0.108,0.409z' }, group); // Axle hole. - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.CIRCLE, - { - 'class': 'blocklyIconShape', - 'r': '2.7', - 'cx': '8', - 'cy': '8' - }, - group); + dom.createSvgElement( + Svg.CIRCLE, + {'class': 'blocklyIconShape', 'r': '2.7', 'cx': '8', 'cy': '8'}, group); }; /** @@ -139,9 +138,9 @@ Blockly.Mutator.prototype.drawIcon_ = function(group) { * @protected * @override */ -Blockly.Mutator.prototype.iconClick_ = function(e) { +Mutator.prototype.iconClick_ = function(e) { if (this.block_.isEditable()) { - Blockly.Icon.prototype.iconClick_.call(this, e); + Icon.prototype.iconClick_.call(this, e); } }; @@ -150,28 +149,27 @@ Blockly.Mutator.prototype.iconClick_ = function(e) { * @return {!SVGElement} The top-level node of the editor. * @private */ -Blockly.Mutator.prototype.createEditor_ = function() { +Mutator.prototype.createEditor_ = function() { /* Create the editor. Here's the markup that will be generated: [Workspace] */ - this.svgDialog_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.SVG, - {'x': Blockly.Bubble.BORDER_WIDTH, 'y': Blockly.Bubble.BORDER_WIDTH}, - null); + this.svgDialog_ = dom.createSvgElement( + Svg.SVG, {'x': Bubble.BORDER_WIDTH, 'y': Bubble.BORDER_WIDTH}, null); // Convert the list of names into a list of XML objects for the flyout. + let quarkXml; if (this.quarkNames_.length) { - var quarkXml = Blockly.utils.xml.createElement('xml'); - for (var i = 0, quarkName; (quarkName = this.quarkNames_[i]); i++) { - var element = Blockly.utils.xml.createElement('block'); + quarkXml = xml.createElement('xml'); + for (let i = 0, quarkName; (quarkName = this.quarkNames_[i]); i++) { + const element = xml.createElement('block'); element.setAttribute('type', quarkName); quarkXml.appendChild(element); } } else { - var quarkXml = null; + quarkXml = null; } - var workspaceOptions = new Blockly.Options( + const workspaceOptions = new Options( /** @type {!Blockly.BlocklyOptions} */ ({ // If you want to enable disabling, also remove the @@ -184,25 +182,22 @@ Blockly.Mutator.prototype.createEditor_ = function() { 'renderer': this.block_.workspace.options.renderer, 'rendererOverrides': this.block_.workspace.options.rendererOverrides })); - workspaceOptions.toolboxPosition = this.block_.RTL ? - Blockly.utils.toolbox.Position.RIGHT : - Blockly.utils.toolbox.Position.LEFT; - var hasFlyout = !!quarkXml; + workspaceOptions.toolboxPosition = + this.block_.RTL ? toolbox.Position.RIGHT : toolbox.Position.LEFT; + const hasFlyout = !!quarkXml; if (hasFlyout) { - workspaceOptions.languageTree = - Blockly.utils.toolbox.convertToolboxDefToJson(quarkXml); + workspaceOptions.languageTree = toolbox.convertToolboxDefToJson(quarkXml); } - this.workspace_ = new Blockly.WorkspaceSvg(workspaceOptions); + this.workspace_ = new WorkspaceSvg(workspaceOptions); this.workspace_.isMutator = true; - this.workspace_.addChangeListener(Blockly.Events.disableOrphans); + this.workspace_.addChangeListener(Events.disableOrphans); // Mutator flyouts go inside the mutator workspace's rather than in // a top level SVG. Instead of handling scale themselves, mutators // inherit scale from the parent workspace. // To fix this, scale needs to be applied at a different level in the DOM. - var flyoutSvg = hasFlyout ? - this.workspace_.addFlyout(Blockly.utils.Svg.G) : null; - var background = this.workspace_.createDom('blocklyMutatorBackground'); + const flyoutSvg = hasFlyout ? this.workspace_.addFlyout(Svg.G) : null; + const background = this.workspace_.createDom('blocklyMutatorBackground'); if (flyoutSvg) { // Insert the flyout after the but before the block canvas so that @@ -218,12 +213,12 @@ Blockly.Mutator.prototype.createEditor_ = function() { /** * Add or remove the UI indicating if this icon may be clicked or not. */ -Blockly.Mutator.prototype.updateEditable = function() { - Blockly.Mutator.superClass_.updateEditable.call(this); +Mutator.prototype.updateEditable = function() { + Mutator.superClass_.updateEditable.call(this); if (!this.block_.isInFlyout) { if (this.block_.isEditable()) { if (this.iconGroup_) { - Blockly.utils.dom.removeClass( + dom.removeClass( /** @type {!Element} */ (this.iconGroup_), 'blocklyIconGroupReadonly'); } @@ -231,7 +226,7 @@ Blockly.Mutator.prototype.updateEditable = function() { // Close any mutator bubble. Icon is not clickable. this.setVisible(false); if (this.iconGroup_) { - Blockly.utils.dom.addClass( + dom.addClass( /** @type {!Element} */ (this.iconGroup_), 'blocklyIconGroupReadonly'); } @@ -243,15 +238,15 @@ Blockly.Mutator.prototype.updateEditable = function() { * Resize the bubble to match the size of the workspace. * @private */ -Blockly.Mutator.prototype.resizeBubble_ = function() { - var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH; - var workspaceSize = this.workspace_.getCanvas().getBBox(); - var width = workspaceSize.width + workspaceSize.x; - var height = workspaceSize.height + doubleBorderWidth * 3; - var flyout = this.workspace_.getFlyout(); +Mutator.prototype.resizeBubble_ = function() { + const doubleBorderWidth = 2 * Bubble.BORDER_WIDTH; + const workspaceSize = this.workspace_.getCanvas().getBBox(); + let width = workspaceSize.width + workspaceSize.x; + let height = workspaceSize.height + doubleBorderWidth * 3; + const flyout = this.workspace_.getFlyout(); if (flyout) { - var flyoutScrollMetrics = flyout.getWorkspace().getMetricsManager() - .getScrollMetrics(); + const flyoutScrollMetrics = + flyout.getWorkspace().getMetricsManager().getScrollMetrics(); height = Math.max(height, flyoutScrollMetrics.height + 20); width += flyout.getWidth(); } @@ -276,7 +271,7 @@ Blockly.Mutator.prototype.resizeBubble_ = function() { if (this.block_.RTL) { // Scroll the workspace to always left-align. - var translation = 'translate(' + this.workspaceWidth_ + ',0)'; + const translation = 'translate(' + this.workspaceWidth_ + ',0)'; this.workspace_.getCanvas().setAttribute('transform', translation); } this.workspace_.resize(); @@ -286,7 +281,7 @@ Blockly.Mutator.prototype.resizeBubble_ = function() { * A method handler for when the bubble is moved. * @private */ -Blockly.Mutator.prototype.onBubbleMove_ = function() { +Mutator.prototype.onBubbleMove_ = function() { if (this.workspace_) { this.workspace_.recordDragTargets(); } @@ -296,43 +291,44 @@ Blockly.Mutator.prototype.onBubbleMove_ = function() { * Show or hide the mutator bubble. * @param {boolean} visible True if the bubble should be visible. */ -Blockly.Mutator.prototype.setVisible = function(visible) { +Mutator.prototype.setVisible = function(visible) { if (visible == this.isVisible()) { // No change. return; } - Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.BUBBLE_OPEN))( - this.block_, visible, 'mutator')); + Events.fire( + new (Events.get(Events.BUBBLE_OPEN))(this.block_, visible, 'mutator')); if (visible) { // Create the bubble. - this.bubble_ = new Blockly.Bubble( - /** @type {!Blockly.WorkspaceSvg} */ (this.block_.workspace), + this.bubble_ = new Bubble( + /** @type {!WorkspaceSvg} */ (this.block_.workspace), this.createEditor_(), this.block_.pathObject.svgPath, - /** @type {!Blockly.utils.Coordinate} */ (this.iconXY_), null, null); + /** @type {!Coordinate} */ (this.iconXY_), null, null); // Expose this mutator's block's ID on its top-level SVG group. this.bubble_.setSvgId(this.block_.id); this.bubble_.registerMoveEvent(this.onBubbleMove_.bind(this)); - var tree = this.workspace_.options.languageTree; - var flyout = this.workspace_.getFlyout(); + const tree = this.workspace_.options.languageTree; + const flyout = this.workspace_.getFlyout(); if (tree) { flyout.init(this.workspace_); flyout.show(tree); } this.rootBlock_ = this.block_.decompose(this.workspace_); - var blocks = this.rootBlock_.getDescendants(false); - for (var i = 0, child; (child = blocks[i]); i++) { + const blocks = this.rootBlock_.getDescendants(false); + for (let i = 0, child; (child = blocks[i]); i++) { child.render(); } // The root block should not be draggable or deletable. this.rootBlock_.setMovable(false); this.rootBlock_.setDeletable(false); + let margin, x; if (flyout) { - var margin = flyout.CORNER_RADIUS * 2; - var x = this.rootBlock_.RTL ? flyout.getWidth() + margin : margin; + margin = flyout.CORNER_RADIUS * 2; + x = this.rootBlock_.RTL ? flyout.getWidth() + margin : margin; } else { - var margin = 16; - var x = margin; + margin = 16; + x = margin; } if (this.block_.RTL) { x = -x; @@ -340,10 +336,9 @@ Blockly.Mutator.prototype.setVisible = function(visible) { this.rootBlock_.moveBy(x, margin); // Save the initial connections, then listen for further changes. if (this.block_.saveConnections) { - var thisMutator = this; - var mutatorBlock = - /** @type {{saveConnections: function(!Blockly.Block)}} */ ( - this.block_); + const thisMutator = this; + const mutatorBlock = + /** @type {{saveConnections: function(!Block)}} */ (this.block_); mutatorBlock.saveConnections(this.rootBlock_); this.sourceListener_ = function() { mutatorBlock.saveConnections(thisMutator.rootBlock_); @@ -375,21 +370,20 @@ Blockly.Mutator.prototype.setVisible = function(visible) { * Update the source block when the mutator's blocks are changed. * Bump down any block that's too high. * Fired whenever a change is made to the mutator's workspace. - * @param {!Blockly.Events.Abstract} e Custom data for event. + * @param {!Abstract} e Custom data for event. * @private */ -Blockly.Mutator.prototype.workspaceChanged_ = function(e) { - if (e.isUiEvent || - (e.type == Blockly.Events.CHANGE && e.element == 'disabled')) { +Mutator.prototype.workspaceChanged_ = function(e) { + if (e.isUiEvent || (e.type == Events.CHANGE && e.element == 'disabled')) { return; } if (!this.workspace_.isDragging()) { - var blocks = this.workspace_.getTopBlocks(false); - var MARGIN = 20; + const blocks = this.workspace_.getTopBlocks(false); + const MARGIN = 20; - for (var b = 0, block; (block = blocks[b]); b++) { - var blockXY = block.getRelativeToSurfaceXY(); + for (let b = 0, block; (block = blocks[b]); b++) { + const blockXY = block.getRelativeToSurfaceXY(); // Bump any block that's above the top back inside. if (blockXY.y < MARGIN) { @@ -397,8 +391,8 @@ Blockly.Mutator.prototype.workspaceChanged_ = function(e) { } // Bump any block overlapping the flyout back inside. if (block.RTL) { - var right = -MARGIN; - var flyout = this.workspace_.getFlyout(); + let right = -MARGIN; + const flyout = this.workspace_.getFlyout(); if (flyout) { right -= flyout.getWidth(); } @@ -413,13 +407,13 @@ Blockly.Mutator.prototype.workspaceChanged_ = function(e) { // When the mutator's workspace changes, update the source block. if (this.rootBlock_.workspace == this.workspace_) { - Blockly.Events.setGroup(true); - var block = this.block_; - var oldMutationDom = block.mutationToDom(); - var oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom); + Events.setGroup(true); + const block = this.block_; + const oldMutationDom = block.mutationToDom(); + const oldMutation = oldMutationDom && Xml.domToText(oldMutationDom); // Switch off rendering while the source block is rebuilt. - var savedRendered = block.rendered; + const savedRendered = block.rendered; // TODO(#4288): We should not be setting the rendered property to false. block.rendered = false; @@ -434,18 +428,18 @@ Blockly.Mutator.prototype.workspaceChanged_ = function(e) { block.render(); } - var newMutationDom = block.mutationToDom(); - var newMutation = newMutationDom && Blockly.Xml.domToText(newMutationDom); + const newMutationDom = block.mutationToDom(); + const newMutation = newMutationDom && Xml.domToText(newMutationDom); if (oldMutation != newMutation) { - Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.BLOCK_CHANGE))( + Events.fire(new (Events.get(Events.BLOCK_CHANGE))( block, 'mutation', null, oldMutation, newMutation)); // Ensure that any bump is part of this mutation's event group. - var group = Blockly.Events.getGroup(); + const group = Events.getGroup(); setTimeout(function() { - Blockly.Events.setGroup(group); + Events.setGroup(group); block.bumpNeighbours(); - Blockly.Events.setGroup(false); - }, Blockly.internalConstants.BUMP_DELAY); + Events.setGroup(false); + }, internalConstants.BUMP_DELAY); } // Don't update the bubble until the drag has ended, to avoid moving blocks @@ -453,35 +447,35 @@ Blockly.Mutator.prototype.workspaceChanged_ = function(e) { if (!this.workspace_.isDragging()) { this.resizeBubble_(); } - Blockly.Events.setGroup(false); + Events.setGroup(false); } }; /** * Dispose of this mutator. */ -Blockly.Mutator.prototype.dispose = function() { +Mutator.prototype.dispose = function() { this.block_.mutator = null; - Blockly.Icon.prototype.dispose.call(this); + Icon.prototype.dispose.call(this); }; /** * Update the styles on all blocks in the mutator. * @public */ -Blockly.Mutator.prototype.updateBlockStyle = function() { - var ws = this.workspace_; +Mutator.prototype.updateBlockStyle = function() { + const ws = this.workspace_; if (ws && ws.getAllBlocks(false)) { - var workspaceBlocks = ws.getAllBlocks(false); - for (var i = 0, block; (block = workspaceBlocks[i]); i++) { + const workspaceBlocks = ws.getAllBlocks(false); + for (let i = 0, block; (block = workspaceBlocks[i]); i++) { block.setStyle(block.getStyleName()); } - var flyout = ws.getFlyout(); + const flyout = ws.getFlyout(); if (flyout) { - var flyoutBlocks = flyout.workspace_.getAllBlocks(false); - for (var i = 0, block; (block = flyoutBlocks[i]); i++) { + const flyoutBlocks = flyout.workspace_.getAllBlocks(false); + for (let i = 0, block; (block = flyoutBlocks[i]); i++) { block.setStyle(block.getStyleName()); } } @@ -490,17 +484,17 @@ Blockly.Mutator.prototype.updateBlockStyle = function() { /** * Reconnect an block to a mutated input. - * @param {Blockly.Connection} connectionChild Connection on child block. - * @param {!Blockly.Block} block Parent block. + * @param {Connection} connectionChild Connection on child block. + * @param {!Block} block Parent block. * @param {string} inputName Name of input on parent block. * @return {boolean} True iff a reconnection was made, false otherwise. */ -Blockly.Mutator.reconnect = function(connectionChild, block, inputName) { +Mutator.reconnect = function(connectionChild, block, inputName) { if (!connectionChild || !connectionChild.getSourceBlock().workspace) { return false; // No connection or block has been deleted. } - var connectionParent = block.getInput(inputName).connection; - var currentParent = connectionChild.targetBlock(); + const connectionParent = block.getInput(inputName).connection; + const currentParent = connectionChild.targetBlock(); if ((!currentParent || currentParent == block) && connectionParent.targetConnection != connectionChild) { if (connectionParent.isConnected()) { @@ -516,14 +510,14 @@ Blockly.Mutator.reconnect = function(connectionChild, block, inputName) { /** * Get the parent workspace of a workspace that is inside a mutator, taking into * account whether it is a flyout. - * @param {Blockly.Workspace} workspace The workspace that is inside a mutator. - * @return {?Blockly.Workspace} The mutator's parent workspace or null. + * @param {Workspace} workspace The workspace that is inside a mutator. + * @return {?Workspace} The mutator's parent workspace or null. * @public */ -Blockly.Mutator.findParentWs = function(workspace) { - var outerWs = null; +Mutator.findParentWs = function(workspace) { + let outerWs = null; if (workspace && workspace.options) { - var parent = workspace.options.parentWorkspace; + const parent = workspace.options.parentWorkspace; // If we were in a flyout in a mutator, need to go up two levels to find // the actual parent. if (workspace.isFlyout) { @@ -536,3 +530,5 @@ Blockly.Mutator.findParentWs = function(workspace) { } return outerWs; }; + +exports = Mutator; diff --git a/core/registry.js b/core/registry.js index 2959cf73e..5752702ae 100644 --- a/core/registry.js +++ b/core/registry.js @@ -11,20 +11,33 @@ */ 'use strict'; -goog.provide('Blockly.registry'); +goog.module('Blockly.registry'); +goog.module.declareLegacyNamespace(); -goog.requireType('Blockly.blockRendering.Renderer'); -goog.requireType('Blockly.Cursor'); -goog.requireType('Blockly.Events.Abstract'); -goog.requireType('Blockly.Field'); -goog.requireType('Blockly.IBlockDragger'); -goog.requireType('Blockly.IConnectionChecker'); -goog.requireType('Blockly.IFlyout'); -goog.requireType('Blockly.IMetricsManager'); -goog.requireType('Blockly.IToolbox'); -goog.requireType('Blockly.Options'); -goog.requireType('Blockly.Theme'); -goog.requireType('Blockly.ToolboxItem'); +/* eslint-disable-next-line no-unused-vars */ +const Abstract = goog.requireType('Blockly.Events.Abstract'); +/* eslint-disable-next-line no-unused-vars */ +const Cursor = goog.requireType('Blockly.Cursor'); +/* eslint-disable-next-line no-unused-vars */ +const Field = goog.requireType('Blockly.Field'); +/* eslint-disable-next-line no-unused-vars */ +const IBlockDragger = goog.requireType('Blockly.IBlockDragger'); +/* eslint-disable-next-line no-unused-vars */ +const IConnectionChecker = goog.requireType('Blockly.IConnectionChecker'); +/* eslint-disable-next-line no-unused-vars */ +const IFlyout = goog.requireType('Blockly.IFlyout'); +/* eslint-disable-next-line no-unused-vars */ +const IMetricsManager = goog.requireType('Blockly.IMetricsManager'); +/* eslint-disable-next-line no-unused-vars */ +const IToolbox = goog.requireType('Blockly.IToolbox'); +/* eslint-disable-next-line no-unused-vars */ +const Options = goog.requireType('Blockly.Options'); +/* eslint-disable-next-line no-unused-vars */ +const Renderer = goog.requireType('Blockly.blockRendering.Renderer'); +/* eslint-disable-next-line no-unused-vars */ +const Theme = goog.requireType('Blockly.Theme'); +/* eslint-disable-next-line no-unused-vars */ +const ToolboxItem = goog.requireType('Blockly.ToolboxItem'); /** @@ -34,13 +47,16 @@ goog.requireType('Blockly.ToolboxItem'); * * @type {Object>} */ -Blockly.registry.typeMap_ = Object.create(null); +const typeMap = Object.create(null); +/** @private */ +exports.typeMap_ = typeMap; /** * The string used to register the default class for a type of plugin. * @type {string} */ -Blockly.registry.DEFAULT = 'default'; +const DEFAULT = 'default'; +exports.DEFAULT = DEFAULT; /** * A name with the type of the element stored in the generic. @@ -48,67 +64,63 @@ Blockly.registry.DEFAULT = 'default'; * @constructor * @template T */ -Blockly.registry.Type = function(name) { +const Type = function(name) { /** * @type {string} * @private */ this.name_ = name; }; +exports.Type = Type; /** * Returns the name of the type. * @return {string} The name. * @override */ -Blockly.registry.Type.prototype.toString = function() { +Type.prototype.toString = function() { return this.name_; }; -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.CONNECTION_CHECKER = - new Blockly.registry.Type('connectionChecker'); +/** @type {!Type} */ +Type.CONNECTION_CHECKER = new Type('connectionChecker'); -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.CURSOR = new Blockly.registry.Type('cursor'); +/** @type {!Type} */ +Type.CURSOR = new Type('cursor'); -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.EVENT = new Blockly.registry.Type('event'); +/** @type {!Type} */ +Type.EVENT = new Type('event'); -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.FIELD = new Blockly.registry.Type('field'); +/** @type {!Type} */ +Type.FIELD = new Type('field'); -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.RENDERER = new Blockly.registry.Type('renderer'); +/** @type {!Type} */ +Type.RENDERER = new Type('renderer'); -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.TOOLBOX = new Blockly.registry.Type('toolbox'); +/** @type {!Type} */ +Type.TOOLBOX = new Type('toolbox'); -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.THEME = new Blockly.registry.Type('theme'); +/** @type {!Type} */ +Type.THEME = new Type('theme'); -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.TOOLBOX_ITEM = new Blockly.registry.Type('toolboxItem'); +/** @type {!Type} */ +Type.TOOLBOX_ITEM = new Type('toolboxItem'); -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.FLYOUTS_VERTICAL_TOOLBOX = - new Blockly.registry.Type('flyoutsVerticalToolbox'); +/** @type {!Type} */ +Type.FLYOUTS_VERTICAL_TOOLBOX = new Type('flyoutsVerticalToolbox'); -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX = - new Blockly.registry.Type('flyoutsHorizontalToolbox'); +/** @type {!Type} */ +Type.FLYOUTS_HORIZONTAL_TOOLBOX = new Type('flyoutsHorizontalToolbox'); -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.METRICS_MANAGER = - new Blockly.registry.Type('metricsManager'); +/** @type {!Type} */ +Type.METRICS_MANAGER = new Type('metricsManager'); -/** @type {!Blockly.registry.Type} */ -Blockly.registry.Type.BLOCK_DRAGGER = - new Blockly.registry.Type('blockDragger'); +/** @type {!Type} */ +Type.BLOCK_DRAGGER = new Type('blockDragger'); /** * Registers a class based on a type and name. - * @param {string|!Blockly.registry.Type} type The type of the plugin. + * @param {string|!Type} type The type of the plugin. * (e.g. Field, Renderer) * @param {string} name The plugin's name. (Ex. field_angle, geras) * @param {?function(new:T, ...?)|Object} registryItem The class or object to @@ -120,9 +132,8 @@ Blockly.registry.Type.BLOCK_DRAGGER = * it's type. * @template T */ -Blockly.registry.register = function( - type, name, registryItem, opt_allowOverrides) { - if ((!(type instanceof Blockly.registry.Type) && typeof type != 'string') || +const register = function(type, name, registryItem, opt_allowOverrides) { + if ((!(type instanceof Type) && typeof type != 'string') || String(type).trim() == '') { throw Error( 'Invalid type "' + type + '". The type must be a' + @@ -139,14 +150,14 @@ Blockly.registry.register = function( if (!registryItem) { throw Error('Can not register a null value'); } - var typeRegistry = Blockly.registry.typeMap_[type]; + let typeRegistry = typeMap[type]; // If the type registry has not been created, create it. if (!typeRegistry) { - typeRegistry = Blockly.registry.typeMap_[type] = Object.create(null); + typeRegistry = typeMap[type] = Object.create(null); } // Validate that the given class has all the required properties. - Blockly.registry.validate_(type, registryItem); + validate(type, registryItem); // Don't throw an error if opt_allowOverrides is true. if (!opt_allowOverrides && typeRegistry[name]) { @@ -155,6 +166,7 @@ Blockly.registry.register = function( } typeRegistry[name] = registryItem; }; +exports.register = register; /** * Checks the given registry item for properties that are required based on the @@ -162,11 +174,10 @@ Blockly.registry.register = function( * @param {string} type The type of the plugin. (e.g. Field, Renderer) * @param {Function|Object} registryItem A class or object that we are checking * for the required properties. - * @private */ -Blockly.registry.validate_ = function(type, registryItem) { +const validate = function(type, registryItem) { switch (type) { - case String(Blockly.registry.Type.FIELD): + case String(Type.FIELD): if (typeof registryItem.fromJson != 'function') { throw Error('Type "' + type + '" must have a fromJson function'); } @@ -176,27 +187,29 @@ Blockly.registry.validate_ = function(type, registryItem) { /** * Unregisters the registry item with the given type and name. - * @param {string|!Blockly.registry.Type} type The type of the plugin. + * @param {string|!Type} type The type of the plugin. * (e.g. Field, Renderer) * @param {string} name The plugin's name. (Ex. field_angle, geras) * @template T */ -Blockly.registry.unregister = function(type, name) { +const unregister = function(type, name) { type = String(type).toLowerCase(); name = name.toLowerCase(); - var typeRegistry = Blockly.registry.typeMap_[type]; + const typeRegistry = typeMap[type]; if (!typeRegistry || !typeRegistry[name]) { - console.warn('Unable to unregister [' + name + '][' + type + '] from the ' + - 'registry.'); + console.warn( + 'Unable to unregister [' + name + '][' + type + '] from the ' + + 'registry.'); return; } - delete Blockly.registry.typeMap_[type][name]; + delete typeMap[type][name]; }; +exports.unregister = unregister; /** * Gets the registry item for the given name and type. This can be either a * class or an object. - * @param {string|!Blockly.registry.Type} type The type of the plugin. + * @param {string|!Type} type The type of the plugin. * (e.g. Field, Renderer) * @param {string} name The plugin's name. (Ex. field_angle, geras) * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we @@ -205,15 +218,15 @@ Blockly.registry.unregister = function(type, name) { * name and type or null if none exists. * @template T */ -Blockly.registry.getItem_ = function(type, name, opt_throwIfMissing) { +const getItem = function(type, name, opt_throwIfMissing) { type = String(type).toLowerCase(); name = name.toLowerCase(); - var typeRegistry = Blockly.registry.typeMap_[type]; + const typeRegistry = typeMap[type]; if (!typeRegistry || !typeRegistry[name]) { - var msg = 'Unable to find [' + name + '][' + type + '] in the registry.'; + const msg = 'Unable to find [' + name + '][' + type + '] in the registry.'; if (opt_throwIfMissing) { - throw new Error(msg + ' You must require or register a ' + type + - ' plugin.'); + throw new Error( + msg + ' You must require or register a ' + type + ' plugin.'); } else { console.warn(msg); } @@ -225,26 +238,27 @@ Blockly.registry.getItem_ = function(type, name, opt_throwIfMissing) { /** * Returns whether or not the registry contains an item with the given type and * name. - * @param {string|!Blockly.registry.Type} type The type of the plugin. + * @param {string|!Type} type The type of the plugin. * (e.g. Field, Renderer) * @param {string} name The plugin's name. (Ex. field_angle, geras) * @return {boolean} True if the registry has an item with the given type and * name, false otherwise. * @template T */ -Blockly.registry.hasItem = function(type, name) { +const hasItem = function(type, name) { type = String(type).toLowerCase(); name = name.toLowerCase(); - var typeRegistry = Blockly.registry.typeMap_[type]; + const typeRegistry = typeMap[type]; if (!typeRegistry) { return false; } return !!(typeRegistry[name]); }; +exports.hasItem = hasItem; /** * Gets the class for the given name and type. - * @param {string|!Blockly.registry.Type} type The type of the plugin. + * @param {string|!Type} type The type of the plugin. * (e.g. Field, Renderer) * @param {string} name The plugin's name. (Ex. field_angle, geras) * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we @@ -253,14 +267,15 @@ Blockly.registry.hasItem = function(type, name) { * null if none exists. * @template T */ -Blockly.registry.getClass = function(type, name, opt_throwIfMissing) { +const getClass = function(type, name, opt_throwIfMissing) { return /** @type {?function(new:T, ...?)} */ ( - Blockly.registry.getItem_(type, name, opt_throwIfMissing)); + getItem(type, name, opt_throwIfMissing)); }; +exports.getClass = getClass; /** * Gets the object for the given name and type. - * @param {string|!Blockly.registry.Type} type The type of the plugin. + * @param {string|!Type} type The type of the plugin. * (e.g. Category) * @param {string} name The plugin's name. (Ex. logic_category) * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we @@ -268,30 +283,30 @@ Blockly.registry.getClass = function(type, name, opt_throwIfMissing) { * @return {?T} The object with the given name and type or null if none exists. * @template T */ -Blockly.registry.getObject = function(type, name, opt_throwIfMissing) { - return /** @type {T} */ ( - Blockly.registry.getItem_(type, name, opt_throwIfMissing)); +const getObject = function(type, name, opt_throwIfMissing) { + return /** @type {T} */ (getItem(type, name, opt_throwIfMissing)); }; +exports.getObject = getObject; /** * Gets the class from Blockly options for the given type. * This is used for plugins that override a built in feature. (e.g. Toolbox) - * @param {!Blockly.registry.Type} type The type of the plugin. - * @param {!Blockly.Options} options The option object to check for the given + * @param {!Type} type The type of the plugin. + * @param {!Options} options The option object to check for the given * plugin. * @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we * are unable to find the plugin. * @return {?function(new:T, ...?)} The class for the plugin. * @template T */ -Blockly.registry.getClassFromOptions = function(type, options, - opt_throwIfMissing) { - var typeName = type.toString(); - var plugin = options.plugins[typeName] || Blockly.registry.DEFAULT; +const getClassFromOptions = function(type, options, opt_throwIfMissing) { + const typeName = type.toString(); + const plugin = options.plugins[typeName] || DEFAULT; // If the user passed in a plugin class instead of a registered plugin name. if (typeof plugin == 'function') { return plugin; } - return Blockly.registry.getClass(type, plugin, opt_throwIfMissing); + return getClass(type, plugin, opt_throwIfMissing); }; +exports.getClassFromOptions = getClassFromOptions; diff --git a/core/rendered_connection.js b/core/rendered_connection.js index cddda9200..0abc123e5 100644 --- a/core/rendered_connection.js +++ b/core/rendered_connection.js @@ -10,36 +10,40 @@ */ 'use strict'; -goog.provide('Blockly.RenderedConnection'); +goog.module('Blockly.RenderedConnection'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Connection'); -goog.require('Blockly.connectionTypes'); -goog.require('Blockly.internalConstants'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.deprecation'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.object'); -goog.require('Blockly.utils.Svg'); - -goog.requireType('Blockly.Block'); -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.ConnectionDB'); +/* eslint-disable-next-line no-unused-vars */ +const Block = goog.requireType('Blockly.Block'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +const Connection = goog.require('Blockly.Connection'); +/* eslint-disable-next-line no-unused-vars */ +const ConnectionDB = goog.requireType('Blockly.ConnectionDB'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +const Events = goog.require('Blockly.Events'); +const Svg = goog.require('Blockly.utils.Svg'); +const connectionTypes = goog.require('Blockly.connectionTypes'); +const deprecation = goog.require('Blockly.utils.deprecation'); +const dom = goog.require('Blockly.utils.dom'); +const internalConstants = goog.require('Blockly.internalConstants'); +const object = goog.require('Blockly.utils.object'); +const utils = goog.require('Blockly.utils'); /** * Class for a connection between blocks that may be rendered on screen. - * @param {!Blockly.BlockSvg} source The block establishing this connection. + * @param {!BlockSvg} source The block establishing this connection. * @param {number} type The type of the connection. - * @extends {Blockly.Connection} + * @extends {Connection} * @constructor */ -Blockly.RenderedConnection = function(source, type) { - Blockly.RenderedConnection.superClass_.constructor.call(this, source, type); +const RenderedConnection = function(source, type) { + RenderedConnection.superClass_.constructor.call(this, source, type); /** * Connection database for connections of this type on the current workspace. - * @const {!Blockly.ConnectionDB} + * @const {!ConnectionDB} * @private */ this.db_ = source.workspace.connectionDBList[type]; @@ -47,34 +51,33 @@ Blockly.RenderedConnection = function(source, type) { /** * Connection database for connections compatible with this type on the * current workspace. - * @const {!Blockly.ConnectionDB} + * @const {!ConnectionDB} * @private */ this.dbOpposite_ = - source.workspace - .connectionDBList[Blockly.internalConstants.OPPOSITE_TYPE[type]]; + source.workspace.connectionDBList[internalConstants.OPPOSITE_TYPE[type]]; /** * Workspace units, (0, 0) is top left of block. - * @type {!Blockly.utils.Coordinate} + * @type {!Coordinate} * @private */ - this.offsetInBlock_ = new Blockly.utils.Coordinate(0, 0); + this.offsetInBlock_ = new Coordinate(0, 0); /** * Describes the state of this connection's tracked-ness. - * @type {Blockly.RenderedConnection.TrackedState} + * @type {RenderedConnection.TrackedState} * @private */ - this.trackedState_ = Blockly.RenderedConnection.TrackedState.WILL_TRACK; + this.trackedState_ = RenderedConnection.TrackedState.WILL_TRACK; /** * Connection this connection connects to. Null if not connected. - * @type {Blockly.RenderedConnection} + * @type {RenderedConnection} */ this.targetConnection = null; }; -Blockly.utils.object.inherits(Blockly.RenderedConnection, Blockly.Connection); +object.inherits(RenderedConnection, Connection); /** * Enum for different kinds of tracked states. @@ -88,7 +91,7 @@ Blockly.utils.object.inherits(Blockly.RenderedConnection, Blockly.Connection); * TRACKED means that this connection is currently being tracked. * @enum {number} */ -Blockly.RenderedConnection.TrackedState = { +RenderedConnection.TrackedState = { WILL_TRACK: -1, UNTRACKED: 0, TRACKED: 1 @@ -100,65 +103,65 @@ Blockly.RenderedConnection.TrackedState = { * @override * @package */ -Blockly.RenderedConnection.prototype.dispose = function() { - Blockly.RenderedConnection.superClass_.dispose.call(this); - if (this.trackedState_ == Blockly.RenderedConnection.TrackedState.TRACKED) { +RenderedConnection.prototype.dispose = function() { + RenderedConnection.superClass_.dispose.call(this); + if (this.trackedState_ == RenderedConnection.TrackedState.TRACKED) { this.db_.removeConnection(this, this.y); } }; /** * Get the source block for this connection. - * @return {!Blockly.BlockSvg} The source block. + * @return {!BlockSvg} The source block. * @override */ -Blockly.RenderedConnection.prototype.getSourceBlock = function() { - return /** @type {!Blockly.BlockSvg} */ ( - Blockly.RenderedConnection.superClass_.getSourceBlock.call(this)); +RenderedConnection.prototype.getSourceBlock = function() { + return /** @type {!BlockSvg} */ ( + RenderedConnection.superClass_.getSourceBlock.call(this)); }; /** * Returns the block that this connection connects to. - * @return {?Blockly.BlockSvg} The connected block or null if none is connected. + * @return {?BlockSvg} The connected block or null if none is connected. * @override */ -Blockly.RenderedConnection.prototype.targetBlock = function() { - return /** @type {Blockly.BlockSvg} */ ( - Blockly.RenderedConnection.superClass_.targetBlock.call(this)); +RenderedConnection.prototype.targetBlock = function() { + return /** @type {BlockSvg} */ ( + RenderedConnection.superClass_.targetBlock.call(this)); }; /** * Returns the distance between this connection and another connection in * workspace units. - * @param {!Blockly.Connection} otherConnection The other connection to measure + * @param {!Connection} otherConnection The other connection to measure * the distance to. * @return {number} The distance between connections, in workspace units. */ -Blockly.RenderedConnection.prototype.distanceFrom = function(otherConnection) { - var xDiff = this.x - otherConnection.x; - var yDiff = this.y - otherConnection.y; +RenderedConnection.prototype.distanceFrom = function(otherConnection) { + const xDiff = this.x - otherConnection.x; + const yDiff = this.y - otherConnection.y; return Math.sqrt(xDiff * xDiff + yDiff * yDiff); }; /** * Move the block(s) belonging to the connection to a point where they don't * visually interfere with the specified connection. - * @param {!Blockly.Connection} staticConnection The connection to move away + * @param {!Connection} staticConnection The connection to move away * from. * @package */ -Blockly.RenderedConnection.prototype.bumpAwayFrom = function(staticConnection) { +RenderedConnection.prototype.bumpAwayFrom = function(staticConnection) { if (this.sourceBlock_.workspace.isDragging()) { // Don't move blocks around while the user is doing the same. return; } // Move the root block. - var rootBlock = this.sourceBlock_.getRootBlock(); + let rootBlock = this.sourceBlock_.getRootBlock(); if (rootBlock.isInFlyout) { // Don't move blocks around in a flyout. return; } - var reverse = false; + let reverse = false; if (!rootBlock.isMovable()) { // Can't bump an uneditable block away. // Check to see if the other block is movable. @@ -171,24 +174,21 @@ Blockly.RenderedConnection.prototype.bumpAwayFrom = function(staticConnection) { reverse = true; } // Raise it to the top for extra visibility. - var selected = Blockly.selected == rootBlock; + const selected = Blockly.selected == rootBlock; selected || rootBlock.addSelect(); - var dx = - (staticConnection.x + Blockly.internalConstants.SNAP_RADIUS + - Math.floor(Math.random() * Blockly.internalConstants.BUMP_RANDOMNESS)) - + let dx = (staticConnection.x + internalConstants.SNAP_RADIUS + + Math.floor(Math.random() * internalConstants.BUMP_RANDOMNESS)) - this.x; - var dy = - (staticConnection.y + Blockly.internalConstants.SNAP_RADIUS + - Math.floor(Math.random() * Blockly.internalConstants.BUMP_RANDOMNESS)) - + let dy = (staticConnection.y + internalConstants.SNAP_RADIUS + + Math.floor(Math.random() * internalConstants.BUMP_RANDOMNESS)) - this.y; if (reverse) { // When reversing a bump due to an uneditable block, bump up. dy = -dy; } if (rootBlock.RTL) { - dx = (staticConnection.x - Blockly.internalConstants.SNAP_RADIUS - - Math.floor( - Math.random() * Blockly.internalConstants.BUMP_RANDOMNESS)) - + dx = (staticConnection.x - internalConstants.SNAP_RADIUS - + Math.floor(Math.random() * internalConstants.BUMP_RANDOMNESS)) - this.x; } rootBlock.moveBy(dx, dy); @@ -200,12 +200,11 @@ Blockly.RenderedConnection.prototype.bumpAwayFrom = function(staticConnection) { * @param {number} x New absolute x coordinate, in workspace coordinates. * @param {number} y New absolute y coordinate, in workspace coordinates. */ -Blockly.RenderedConnection.prototype.moveTo = function(x, y) { - if (this.trackedState_ == Blockly.RenderedConnection.TrackedState.WILL_TRACK) { +RenderedConnection.prototype.moveTo = function(x, y) { + if (this.trackedState_ == RenderedConnection.TrackedState.WILL_TRACK) { this.db_.addConnection(this, y); - this.trackedState_ = Blockly.RenderedConnection.TrackedState.TRACKED; - } else if (this.trackedState_ == Blockly.RenderedConnection - .TrackedState.TRACKED) { + this.trackedState_ = RenderedConnection.TrackedState.TRACKED; + } else if (this.trackedState_ == RenderedConnection.TrackedState.TRACKED) { this.db_.removeConnection(this, this.y); this.db_.addConnection(this, y); } @@ -218,19 +217,19 @@ Blockly.RenderedConnection.prototype.moveTo = function(x, y) { * @param {number} dx Change to x coordinate, in workspace units. * @param {number} dy Change to y coordinate, in workspace units. */ -Blockly.RenderedConnection.prototype.moveBy = function(dx, dy) { +RenderedConnection.prototype.moveBy = function(dx, dy) { this.moveTo(this.x + dx, this.y + dy); }; /** * Move this connection to the location given by its offset within the block and * the location of the block's top left corner. - * @param {!Blockly.utils.Coordinate} blockTL The location of the top left + * @param {!Coordinate} blockTL The location of the top left * corner of the block, in workspace coordinates. */ -Blockly.RenderedConnection.prototype.moveToOffset = function(blockTL) { - this.moveTo(blockTL.x + this.offsetInBlock_.x, - blockTL.y + this.offsetInBlock_.y); +RenderedConnection.prototype.moveToOffset = function(blockTL) { + this.moveTo( + blockTL.x + this.offsetInBlock_.x, blockTL.y + this.offsetInBlock_.y); }; /** @@ -238,17 +237,17 @@ Blockly.RenderedConnection.prototype.moveToOffset = function(blockTL) { * @param {number} x The new relative x, in workspace units. * @param {number} y The new relative y, in workspace units. */ -Blockly.RenderedConnection.prototype.setOffsetInBlock = function(x, y) { +RenderedConnection.prototype.setOffsetInBlock = function(x, y) { this.offsetInBlock_.x = x; this.offsetInBlock_.y = y; }; /** * Get the offset of this connection relative to the top left of its block. - * @return {!Blockly.utils.Coordinate} The offset of the connection. + * @return {!Coordinate} The offset of the connection. * @package */ -Blockly.RenderedConnection.prototype.getOffsetInBlock = function() { +RenderedConnection.prototype.getOffsetInBlock = function() { return this.offsetInBlock_; }; @@ -256,19 +255,19 @@ Blockly.RenderedConnection.prototype.getOffsetInBlock = function() { * Move the blocks on either side of this connection right next to each other. * @package */ -Blockly.RenderedConnection.prototype.tighten = function() { - var dx = this.targetConnection.x - this.x; - var dy = this.targetConnection.y - this.y; +RenderedConnection.prototype.tighten = function() { + const dx = this.targetConnection.x - this.x; + const dy = this.targetConnection.y - this.y; if (dx != 0 || dy != 0) { - var block = this.targetBlock(); - var svgRoot = block.getSvgRoot(); + const block = this.targetBlock(); + const svgRoot = block.getSvgRoot(); if (!svgRoot) { throw Error('block is not rendered.'); } // Workspace coordinates. - var xy = Blockly.utils.getRelativeXY(svgRoot); - block.getSvgRoot().setAttribute('transform', - 'translate(' + (xy.x - dx) + ',' + (xy.y - dy) + ')'); + const xy = utils.getRelativeXY(svgRoot); + block.getSvgRoot().setAttribute( + 'transform', 'translate(' + (xy.x - dx) + ',' + (xy.y - dy) + ')'); block.moveConnections(-dx, -dy); } }; @@ -277,47 +276,44 @@ Blockly.RenderedConnection.prototype.tighten = function() { * Find the closest compatible connection to this connection. * All parameters are in workspace units. * @param {number} maxLimit The maximum radius to another connection. - * @param {!Blockly.utils.Coordinate} dxy Offset between this connection's location + * @param {!Coordinate} dxy Offset between this connection's location * in the database and the current location (as a result of dragging). - * @return {!{connection: ?Blockly.Connection, radius: number}} Contains two + * @return {!{connection: ?Connection, radius: number}} Contains two * properties: 'connection' which is either another connection or null, * and 'radius' which is the distance. */ -Blockly.RenderedConnection.prototype.closest = function(maxLimit, dxy) { +RenderedConnection.prototype.closest = function(maxLimit, dxy) { return this.dbOpposite_.searchForClosest(this, maxLimit, dxy); }; /** * Add highlighting around this connection. */ -Blockly.RenderedConnection.prototype.highlight = function() { - var steps; - var sourceBlockSvg = /** @type {!Blockly.BlockSvg} */ (this.sourceBlock_); - var renderConstants = sourceBlockSvg.workspace.getRenderer().getConstants(); - var shape = renderConstants.shapeFor(this); - if (this.type == Blockly.connectionTypes.INPUT_VALUE || - this.type == Blockly.connectionTypes.OUTPUT_VALUE) { +RenderedConnection.prototype.highlight = function() { + let steps; + const sourceBlockSvg = /** @type {!BlockSvg} */ (this.sourceBlock_); + const renderConstants = sourceBlockSvg.workspace.getRenderer().getConstants(); + const shape = renderConstants.shapeFor(this); + if (this.type == connectionTypes.INPUT_VALUE || + this.type == connectionTypes.OUTPUT_VALUE) { // Vertical line, puzzle tab, vertical line. - var yLen = renderConstants.TAB_OFFSET_FROM_TOP; - steps = Blockly.utils.svgPaths.moveBy(0, -yLen) + - Blockly.utils.svgPaths.lineOnAxis('v', yLen) + - shape.pathDown + - Blockly.utils.svgPaths.lineOnAxis('v', yLen); + const yLen = renderConstants.TAB_OFFSET_FROM_TOP; + steps = utils.svgPaths.moveBy(0, -yLen) + + utils.svgPaths.lineOnAxis('v', yLen) + shape.pathDown + + utils.svgPaths.lineOnAxis('v', yLen); } else { - var xLen = + const xLen = renderConstants.NOTCH_OFFSET_LEFT - renderConstants.CORNER_RADIUS; // Horizontal line, notch, horizontal line. - steps = Blockly.utils.svgPaths.moveBy(-xLen, 0) + - Blockly.utils.svgPaths.lineOnAxis('h', xLen) + - shape.pathLeft + - Blockly.utils.svgPaths.lineOnAxis('h', xLen); + steps = utils.svgPaths.moveBy(-xLen, 0) + + utils.svgPaths.lineOnAxis('h', xLen) + shape.pathLeft + + utils.svgPaths.lineOnAxis('h', xLen); } - var xy = this.sourceBlock_.getRelativeToSurfaceXY(); - var x = this.x - xy.x; - var y = this.y - xy.y; - Blockly.Connection.highlightedPath_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.PATH, - { + const xy = this.sourceBlock_.getRelativeToSurfaceXY(); + const x = this.x - xy.x; + const y = this.y - xy.y; + Connection.highlightedPath_ = dom.createSvgElement( + Svg.PATH, { 'class': 'blocklyHighlightedConnectionPath', 'd': steps, transform: 'translate(' + x + ',' + y + ')' + @@ -329,9 +325,9 @@ Blockly.RenderedConnection.prototype.highlight = function() { /** * Remove the highlighting around this connection. */ -Blockly.RenderedConnection.prototype.unhighlight = function() { - Blockly.utils.dom.removeNode(Blockly.Connection.highlightedPath_); - delete Blockly.Connection.highlightedPath_; +RenderedConnection.prototype.unhighlight = function() { + dom.removeNode(Connection.highlightedPath_); + delete Connection.highlightedPath_; }; /** @@ -339,11 +335,11 @@ Blockly.RenderedConnection.prototype.unhighlight = function() { * @param {boolean} doTracking If true, start tracking. If false, stop tracking. * @package */ -Blockly.RenderedConnection.prototype.setTracking = function(doTracking) { - if ((doTracking && this.trackedState_ == - Blockly.RenderedConnection.TrackedState.TRACKED) || - (!doTracking && this.trackedState_ == - Blockly.RenderedConnection.TrackedState.UNTRACKED)) { +RenderedConnection.prototype.setTracking = function(doTracking) { + if ((doTracking && + this.trackedState_ == RenderedConnection.TrackedState.TRACKED) || + (!doTracking && + this.trackedState_ == RenderedConnection.TrackedState.UNTRACKED)) { return; } if (this.sourceBlock_.isInFlyout) { @@ -352,13 +348,13 @@ Blockly.RenderedConnection.prototype.setTracking = function(doTracking) { } if (doTracking) { this.db_.addConnection(this, this.y); - this.trackedState_ = Blockly.RenderedConnection.TrackedState.TRACKED; + this.trackedState_ = RenderedConnection.TrackedState.TRACKED; return; } - if (this.trackedState_ == Blockly.RenderedConnection.TrackedState.TRACKED) { + if (this.trackedState_ == RenderedConnection.TrackedState.TRACKED) { this.db_.removeConnection(this, this.y); } - this.trackedState_ = Blockly.RenderedConnection.TrackedState.UNTRACKED; + this.trackedState_ = RenderedConnection.TrackedState.UNTRACKED; }; /** @@ -369,20 +365,20 @@ Blockly.RenderedConnection.prototype.setTracking = function(doTracking) { * Also closes down-stream icons/bubbles. * @package */ -Blockly.RenderedConnection.prototype.stopTrackingAll = function() { +RenderedConnection.prototype.stopTrackingAll = function() { this.setTracking(false); if (this.targetConnection) { - var blocks = this.targetBlock().getDescendants(false); - for (var i = 0; i < blocks.length; i++) { - var block = blocks[i]; + const blocks = this.targetBlock().getDescendants(false); + for (let i = 0; i < blocks.length; i++) { + const block = blocks[i]; // Stop tracking connections of all children. - var connections = block.getConnections_(true); - for (var j = 0; j < connections.length; j++) { + const connections = block.getConnections_(true); + for (let j = 0; j < connections.length; j++) { connections[j].setTracking(false); } // Close all bubbles of all children. - var icons = block.getIcons(); - for (var j = 0; j < icons.length; j++) { + const icons = block.getIcons(); + for (let j = 0; j < icons.length; j++) { icons[j].setVisible(false); } } @@ -392,23 +388,23 @@ Blockly.RenderedConnection.prototype.stopTrackingAll = function() { /** * Start tracking this connection, as well as all down-stream connections on * any block attached to this connection. This happens when a block is expanded. - * @return {!Array} List of blocks to render. + * @return {!Array} List of blocks to render. */ -Blockly.RenderedConnection.prototype.startTrackingAll = function() { +RenderedConnection.prototype.startTrackingAll = function() { this.setTracking(true); // All blocks that are not tracked must start tracking before any // rendering takes place, since rendering requires knowing the dimensions // of lower blocks. Also, since rendering a block renders all its parents, // we only need to render the leaf nodes. - var renderList = []; - if (this.type != Blockly.connectionTypes.INPUT_VALUE && - this.type != Blockly.connectionTypes.NEXT_STATEMENT) { + const renderList = []; + if (this.type != connectionTypes.INPUT_VALUE && + this.type != connectionTypes.NEXT_STATEMENT) { // Only spider down. return renderList; } - var block = this.targetBlock(); + const block = this.targetBlock(); if (block) { - var connections; + let connections; if (block.isCollapsed()) { // This block should only be partially revealed since it is collapsed. connections = []; @@ -419,7 +415,7 @@ Blockly.RenderedConnection.prototype.startTrackingAll = function() { // Show all connections of this block. connections = block.getConnections_(true); } - for (var i = 0; i < connections.length; i++) { + for (let i = 0; i < connections.length; i++) { renderList.push.apply(renderList, connections[i].startTrackingAll()); } if (!renderList.length) { @@ -432,62 +428,60 @@ Blockly.RenderedConnection.prototype.startTrackingAll = function() { /** * Check if the two connections can be dragged to connect to each other. - * @param {!Blockly.Connection} candidate A nearby connection to check. + * @param {!Connection} candidate A nearby connection to check. * @param {number=} maxRadius The maximum radius allowed for connections, in * workspace units. * @return {boolean} True if the connection is allowed, false otherwise. * @deprecated July 2020 */ -Blockly.RenderedConnection.prototype.isConnectionAllowed = function(candidate, - maxRadius) { - Blockly.utils.deprecation.warn( - 'RenderedConnection.prototype.isConnectionAllowed', - 'July 2020', +RenderedConnection.prototype.isConnectionAllowed = function( + candidate, maxRadius) { + deprecation.warn( + 'RenderedConnection.prototype.isConnectionAllowed', 'July 2020', 'July 2021', 'Blockly.Workspace.prototype.getConnectionChecker().canConnect'); if (this.distanceFrom(candidate) > maxRadius) { return false; } - return Blockly.RenderedConnection.superClass_.isConnectionAllowed.call(this, - candidate); + return RenderedConnection.superClass_.isConnectionAllowed.call( + this, candidate); }; /** * Behavior after a connection attempt fails. * Bumps this connection away from the other connection. Called when an * attempted connection fails. - * @param {!Blockly.Connection} otherConnection Connection that this connection + * @param {!Connection} otherConnection Connection that this connection * failed to connect to. * @package */ -Blockly.RenderedConnection.prototype.onFailedConnect = - function(otherConnection) { - var block = this.getSourceBlock(); - if (Blockly.Events.recordUndo) { - var group = Blockly.Events.getGroup(); - setTimeout(function() { - if (!block.isDisposed() && !block.getParent()) { - Blockly.Events.setGroup(group); - this.bumpAwayFrom(otherConnection); - Blockly.Events.setGroup(false); - } - }.bind(this), Blockly.internalConstants.BUMP_DELAY); +RenderedConnection.prototype.onFailedConnect = function(otherConnection) { + const block = this.getSourceBlock(); + if (Events.recordUndo) { + const group = Events.getGroup(); + setTimeout(function() { + if (!block.isDisposed() && !block.getParent()) { + Events.setGroup(group); + this.bumpAwayFrom(otherConnection); + Events.setGroup(false); } - }; + }.bind(this), internalConstants.BUMP_DELAY); + } +}; /** * Disconnect two blocks that are connected by this connection. - * @param {!Blockly.Block} parentBlock The superior block. - * @param {!Blockly.Block} childBlock The inferior block. + * @param {!Block} parentBlock The superior block. + * @param {!Block} childBlock The inferior block. * @protected * @override */ -Blockly.RenderedConnection.prototype.disconnectInternal_ = function(parentBlock, - childBlock) { - Blockly.RenderedConnection.superClass_.disconnectInternal_.call(this, - parentBlock, childBlock); +RenderedConnection.prototype.disconnectInternal_ = function( + parentBlock, childBlock) { + RenderedConnection.superClass_.disconnectInternal_.call( + this, parentBlock, childBlock); // Rerender the parent so that it may reflow. if (parentBlock.rendered) { parentBlock.render(); @@ -506,9 +500,9 @@ Blockly.RenderedConnection.prototype.disconnectInternal_ = function(parentBlock, * @protected * @override */ -Blockly.RenderedConnection.prototype.respawnShadow_ = function() { - Blockly.RenderedConnection.superClass_.respawnShadow_.call(this); - var blockShadow = this.targetBlock(); +RenderedConnection.prototype.respawnShadow_ = function() { + RenderedConnection.superClass_.respawnShadow_.call(this); + const blockShadow = this.targetBlock(); if (!blockShadow) { // This connection must not have a shadowDom_. return; @@ -516,7 +510,7 @@ Blockly.RenderedConnection.prototype.respawnShadow_ = function() { blockShadow.initSvg(); blockShadow.render(false); - var parentBlock = this.getSourceBlock(); + const parentBlock = this.getSourceBlock(); if (parentBlock.rendered) { parentBlock.render(); } @@ -527,27 +521,27 @@ Blockly.RenderedConnection.prototype.respawnShadow_ = function() { * Type checking does not apply, since this function is used for bumping. * @param {number} maxLimit The maximum radius to another connection, in * workspace units. - * @return {!Array} List of connections. + * @return {!Array} List of connections. * @package */ -Blockly.RenderedConnection.prototype.neighbours = function(maxLimit) { +RenderedConnection.prototype.neighbours = function(maxLimit) { return this.dbOpposite_.getNeighbours(this, maxLimit); }; /** * Connect two connections together. This is the connection on the superior * block. Rerender blocks as needed. - * @param {!Blockly.Connection} childConnection Connection on inferior block. + * @param {!Connection} childConnection Connection on inferior block. * @protected */ -Blockly.RenderedConnection.prototype.connect_ = function(childConnection) { - Blockly.RenderedConnection.superClass_.connect_.call(this, childConnection); +RenderedConnection.prototype.connect_ = function(childConnection) { + RenderedConnection.superClass_.connect_.call(this, childConnection); - var parentConnection = this; - var parentBlock = parentConnection.getSourceBlock(); - var childBlock = childConnection.getSourceBlock(); - var parentRendered = parentBlock.rendered; - var childRendered = childBlock.rendered; + const parentConnection = this; + const parentBlock = parentConnection.getSourceBlock(); + const childBlock = childConnection.getSourceBlock(); + const parentRendered = parentBlock.rendered; + const childRendered = childBlock.rendered; if (parentRendered) { parentBlock.updateDisabled(); @@ -556,8 +550,8 @@ Blockly.RenderedConnection.prototype.connect_ = function(childConnection) { childBlock.updateDisabled(); } if (parentRendered && childRendered) { - if (parentConnection.type == Blockly.connectionTypes.NEXT_STATEMENT || - parentConnection.type == Blockly.connectionTypes.PREVIOUS_STATEMENT) { + if (parentConnection.type == connectionTypes.NEXT_STATEMENT || + parentConnection.type == connectionTypes.PREVIOUS_STATEMENT) { // Child block may need to square off its corners if it is in a stack. // Rendering a child will render its parent. childBlock.render(); @@ -569,9 +563,9 @@ Blockly.RenderedConnection.prototype.connect_ = function(childConnection) { } // The input the child block is connected to (if any). - var parentInput = parentBlock.getInputWithBlock(childBlock); + const parentInput = parentBlock.getInputWithBlock(childBlock); if (parentInput) { - var visible = parentInput.isVisible(); + const visible = parentInput.isVisible(); childBlock.getSvgRoot().style.display = visible ? 'block' : 'none'; } }; @@ -580,14 +574,17 @@ Blockly.RenderedConnection.prototype.connect_ = function(childConnection) { * Function to be called when this connection's compatible types have changed. * @protected */ -Blockly.RenderedConnection.prototype.onCheckChanged_ = function() { +RenderedConnection.prototype.onCheckChanged_ = function() { // The new value type may not be compatible with the existing connection. - if (this.isConnected() && (!this.targetConnection || - !this.getConnectionChecker().canConnect( - this, this.targetConnection, false))) { - var child = this.isSuperior() ? this.targetBlock() : this.sourceBlock_; + if (this.isConnected() && + (!this.targetConnection || + !this.getConnectionChecker().canConnect( + this, this.targetConnection, false))) { + const child = this.isSuperior() ? this.targetBlock() : this.sourceBlock_; child.unplug(); // Bump away. this.sourceBlock_.bumpNeighbours(); } }; + +exports = RenderedConnection; diff --git a/core/renderers/common/constants.js b/core/renderers/common/constants.js index 5c73d0510..5e5ecb747 100644 --- a/core/renderers/common/constants.js +++ b/core/renderers/common/constants.js @@ -10,19 +10,20 @@ */ 'use strict'; -goog.provide('Blockly.blockRendering.ConstantProvider'); +goog.module('Blockly.blockRendering.ConstantProvider'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.connectionTypes'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.colour'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.Svg'); -goog.require('Blockly.utils.svgPaths'); -goog.require('Blockly.utils.userAgent'); - -goog.requireType('Blockly.blockRendering.Debug'); -goog.requireType('Blockly.RenderedConnection'); -goog.requireType('Blockly.Theme'); +/* eslint-disable-next-line no-unused-vars */ +const RenderedConnection = goog.requireType('Blockly.RenderedConnection'); +const Svg = goog.require('Blockly.utils.Svg'); +/* eslint-disable-next-line no-unused-vars */ +const Theme = goog.requireType('Blockly.Theme'); +const colour = goog.require('Blockly.utils.colour'); +const connectionTypes = goog.require('Blockly.connectionTypes'); +const dom = goog.require('Blockly.utils.dom'); +const svgPaths = goog.require('Blockly.utils.svgPaths'); +const userAgent = goog.require('Blockly.utils.userAgent'); +const utils = goog.require('Blockly.utils'); /** @@ -30,8 +31,7 @@ goog.requireType('Blockly.Theme'); * @constructor * @package */ -Blockly.blockRendering.ConstantProvider = function() { - +const ConstantProvider = function() { /** * The size of an empty spacer. * @type {number} @@ -214,15 +214,15 @@ Blockly.blockRendering.ConstantProvider = function() { this.EXTERNAL_VALUE_INPUT_PADDING = 2; /** - * The height of an empty statement input. Note that in the old rendering this - * varies slightly depending on whether the block has external or inline inputs. - * In the new rendering this is consistent. It seems unlikely that the old - * behaviour was intentional. + * The height of an empty statement input. Note that in the old rendering + * this varies slightly depending on whether the block has external or inline + * inputs. In the new rendering this is consistent. It seems unlikely that + * the old behaviour was intentional. * @type {number} */ this.EMPTY_STATEMENT_INPUT_HEIGHT = this.MIN_BLOCK_HEIGHT; - this.START_POINT = Blockly.utils.svgPaths.moveBy(0, 0); + this.START_POINT = svgPaths.moveBy(0, 0); /** * Height of SVG path for jagged teeth at the end of collapsed blocks. @@ -303,8 +303,7 @@ Blockly.blockRendering.ConstantProvider = function() { * A field's text element's dominant baseline. * @type {boolean} */ - this.FIELD_TEXT_BASELINE_CENTER = - !Blockly.utils.userAgent.IE && !Blockly.utils.userAgent.EDGE; + this.FIELD_TEXT_BASELINE_CENTER = !userAgent.IE && !userAgent.EDGE; /** * A dropdown field's border rect height. @@ -349,17 +348,17 @@ Blockly.blockRendering.ConstantProvider = function() { * @type {string} */ this.FIELD_DROPDOWN_SVG_ARROW_DATAURI = - 'data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllci' + - 'AxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMi43MSIgaG' + - 'VpZ2h0PSI4Ljc5IiB2aWV3Qm94PSIwIDAgMTIuNzEgOC43OSI+PHRpdGxlPmRyb3Bkb3duLW' + - 'Fycm93PC90aXRsZT48ZyBvcGFjaXR5PSIwLjEiPjxwYXRoIGQ9Ik0xMi43MSwyLjQ0QTIuND' + - 'EsMi40MSwwLDAsMSwxMiw0LjE2TDguMDgsOC4wOGEyLjQ1LDIuNDUsMCwwLDEtMy40NSwwTD' + - 'AuNzIsNC4xNkEyLjQyLDIuNDIsMCwwLDEsMCwyLjQ0LDIuNDgsMi40OCwwLDAsMSwuNzEuNz' + - 'FDMSwwLjQ3LDEuNDMsMCw2LjM2LDBTMTEuNzUsMC40NiwxMiwuNzFBMi40NCwyLjQ0LDAsMC' + - 'wxLDEyLjcxLDIuNDRaIiBmaWxsPSIjMjMxZjIwIi8+PC9nPjxwYXRoIGQ9Ik02LjM2LDcuNz' + - 'lhMS40MywxLjQzLDAsMCwxLTEtLjQyTDEuNDIsMy40NWExLjQ0LDEuNDQsMCwwLDEsMC0yYz' + - 'AuNTYtLjU2LDkuMzEtMC41Niw5Ljg3LDBhMS40NCwxLjQ0LDAsMCwxLDAsMkw3LjM3LDcuMz' + - 'dBMS40MywxLjQzLDAsMCwxLDYuMzYsNy43OVoiIGZpbGw9IiNmZmYiLz48L3N2Zz4='; + 'data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllci' + + 'AxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMi43MSIgaG' + + 'VpZ2h0PSI4Ljc5IiB2aWV3Qm94PSIwIDAgMTIuNzEgOC43OSI+PHRpdGxlPmRyb3Bkb3duLW' + + 'Fycm93PC90aXRsZT48ZyBvcGFjaXR5PSIwLjEiPjxwYXRoIGQ9Ik0xMi43MSwyLjQ0QTIuND' + + 'EsMi40MSwwLDAsMSwxMiw0LjE2TDguMDgsOC4wOGEyLjQ1LDIuNDUsMCwwLDEtMy40NSwwTD' + + 'AuNzIsNC4xNkEyLjQyLDIuNDIsMCwwLDEsMCwyLjQ0LDIuNDgsMi40OCwwLDAsMSwuNzEuNz' + + 'FDMSwwLjQ3LDEuNDMsMCw2LjM2LDBTMTEuNzUsMC40NiwxMiwuNzFBMi40NCwyLjQ0LDAsMC' + + 'wxLDEyLjcxLDIuNDRaIiBmaWxsPSIjMjMxZjIwIi8+PC9nPjxwYXRoIGQ9Ik02LjM2LDcuNz' + + 'lhMS40MywxLjQzLDAsMCwxLTEtLjQyTDEuNDIsMy40NWExLjQ0LDEuNDQsMCwwLDEsMC0yYz' + + 'AuNTYtLjU2LDkuMzEtMC41Niw5Ljg3LDBhMS40NCwxLjQ0LDAsMCwxLDAsMkw3LjM3LDcuMz' + + 'dBMS40MywxLjQzLDAsMCwxLDYuMzYsNy43OVoiIGZpbGw9IiNmZmYiLz48L3N2Zz4='; /** * Whether or not to show a box shadow around the widget div. This is only a @@ -401,6 +400,14 @@ Blockly.blockRendering.ConstantProvider = function() { */ this.randomIdentifier = String(Math.random()).substring(2); + /** + * The defs tag that contains all filters and patterns for this Blockly + * instance. + * @type {?SVGElement} + * @private + */ + this.defs_ = null; + /** * The ID of the emboss filter, or the empty string if no filter is set. * @type {string} @@ -525,18 +532,14 @@ Blockly.blockRendering.ConstantProvider = function() { * Enum for connection shapes. * @enum {number} */ - this.SHAPES = { - PUZZLE: 1, - NOTCH: 2 - }; + this.SHAPES = {PUZZLE: 1, NOTCH: 2}; }; /** * Initialize shape objects based on the constants set in the constructor. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.init = function() { - +ConstantProvider.prototype.init = function() { /** * An object containing sizing and path information about collapsed block * indicators. @@ -577,21 +580,19 @@ Blockly.blockRendering.ConstantProvider.prototype.init = function() { /** * Refresh constants properties that depend on the theme. - * @param {!Blockly.Theme} theme The current workspace theme. + * @param {!Theme} theme The current workspace theme. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.setTheme = function( - theme) { - +ConstantProvider.prototype.setTheme = function(theme) { /** * The block styles map. - * @type {Object} + * @type {Object} * @package */ this.blockStyles = Object.create(null); - var blockStyles = theme.blockStyles; - for (var key in blockStyles) { + const blockStyles = theme.blockStyles; + for (const key in blockStyles) { this.blockStyles[key] = this.validatedBlockStyle_(blockStyles[key]); } @@ -600,39 +601,38 @@ Blockly.blockRendering.ConstantProvider.prototype.setTheme = function( /** * Sets dynamic properties that depend on other values or theme properties. - * @param {!Blockly.Theme} theme The current workspace theme. + * @param {!Theme} theme The current workspace theme. * @protected */ -Blockly.blockRendering.ConstantProvider.prototype.setDynamicProperties_ = - function(theme) { - /* eslint-disable indent */ +ConstantProvider.prototype.setDynamicProperties_ = function(theme) { this.setFontConstants_(theme); this.setComponentConstants_(theme); - this.ADD_START_HATS = theme.startHats != null ? theme.startHats : - this.ADD_START_HATS; -}; /* eslint-enable indent */ + this.ADD_START_HATS = + theme.startHats != null ? theme.startHats : this.ADD_START_HATS; +}; /** * Set constants related to fonts. - * @param {!Blockly.Theme} theme The current workspace theme. + * @param {!Theme} theme The current workspace theme. * @protected */ -Blockly.blockRendering.ConstantProvider.prototype.setFontConstants_ = function( - theme) { +ConstantProvider.prototype.setFontConstants_ = function(theme) { this.FIELD_TEXT_FONTFAMILY = theme.fontStyle && theme.fontStyle['family'] != undefined ? - theme.fontStyle['family'] : this.FIELD_TEXT_FONTFAMILY; + theme.fontStyle['family'] : + this.FIELD_TEXT_FONTFAMILY; this.FIELD_TEXT_FONTWEIGHT = theme.fontStyle && theme.fontStyle['weight'] != undefined ? - theme.fontStyle['weight'] : this.FIELD_TEXT_FONTWEIGHT; + theme.fontStyle['weight'] : + this.FIELD_TEXT_FONTWEIGHT; this.FIELD_TEXT_FONTSIZE = theme.fontStyle && theme.fontStyle['size'] != undefined ? - theme.fontStyle['size'] : this.FIELD_TEXT_FONTSIZE; + theme.fontStyle['size'] : + this.FIELD_TEXT_FONTSIZE; - var fontMetrics = Blockly.utils.dom.measureFontMetrics('Hg', - this.FIELD_TEXT_FONTSIZE + 'pt', - this.FIELD_TEXT_FONTWEIGHT, + const fontMetrics = dom.measureFontMetrics( + 'Hg', this.FIELD_TEXT_FONTSIZE + 'pt', this.FIELD_TEXT_FONTWEIGHT, this.FIELD_TEXT_FONTFAMILY); this.FIELD_TEXT_HEIGHT = fontMetrics.height; @@ -641,68 +641,60 @@ Blockly.blockRendering.ConstantProvider.prototype.setFontConstants_ = function( /** * Set constants from a theme's component styles. - * @param {!Blockly.Theme} theme The current workspace theme. + * @param {!Theme} theme The current workspace theme. * @protected */ -Blockly.blockRendering.ConstantProvider.prototype.setComponentConstants_ = - function(theme) { - /* eslint-disable indent */ - this.CURSOR_COLOUR = theme.getComponentStyle('cursorColour') || - this.CURSOR_COLOUR; - this.MARKER_COLOUR = theme.getComponentStyle('markerColour') || - this.MARKER_COLOUR; +ConstantProvider.prototype.setComponentConstants_ = function(theme) { + this.CURSOR_COLOUR = + theme.getComponentStyle('cursorColour') || this.CURSOR_COLOUR; + this.MARKER_COLOUR = + theme.getComponentStyle('markerColour') || this.MARKER_COLOUR; this.INSERTION_MARKER_COLOUR = - theme.getComponentStyle('insertionMarkerColour') || - this.INSERTION_MARKER_COLOUR; + theme.getComponentStyle('insertionMarkerColour') || + this.INSERTION_MARKER_COLOUR; this.INSERTION_MARKER_OPACITY = - Number(theme.getComponentStyle('insertionMarkerOpacity')) || - this.INSERTION_MARKER_OPACITY; -}; /* eslint-enable indent */ + Number(theme.getComponentStyle('insertionMarkerOpacity')) || + this.INSERTION_MARKER_OPACITY; +}; /** * Get or create a block style based on a single colour value. Generate a name * for the style based on the colour. * @param {string} colour #RRGGBB colour string. - * @return {{style: !Blockly.Theme.BlockStyle, name: string}} An object + * @return {{style: !Theme.BlockStyle, name: string}} An object * containing the style and an autogenerated name for that style. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.getBlockStyleForColour = - function(colour) { - /* eslint-disable indent */ - var name = 'auto_' + colour; +ConstantProvider.prototype.getBlockStyleForColour = function(colour) { + const name = 'auto_' + colour; if (!this.blockStyles[name]) { this.blockStyles[name] = this.createBlockStyle_(colour); } return {style: this.blockStyles[name], name: name}; -}; /* eslint-enable indent */ +}; /** * Gets the BlockStyle for the given block style name. * @param {?string} blockStyleName The name of the block style. - * @return {!Blockly.Theme.BlockStyle} The named block style, or a default style + * @return {!Theme.BlockStyle} The named block style, or a default style * if no style with the given name was found. */ -Blockly.blockRendering.ConstantProvider.prototype.getBlockStyle = function( - blockStyleName) { +ConstantProvider.prototype.getBlockStyle = function(blockStyleName) { return this.blockStyles[blockStyleName || ''] || (blockStyleName && blockStyleName.indexOf('auto_') == 0 ? - this.getBlockStyleForColour(blockStyleName.substring(5)).style : - this.createBlockStyle_('#000000')); + this.getBlockStyleForColour(blockStyleName.substring(5)).style : + this.createBlockStyle_('#000000')); }; /** * Create a block style object based on the given colour. * @param {string} colour #RRGGBB colour string. - * @return {!Blockly.Theme.BlockStyle} A populated block style based on the + * @return {!Theme.BlockStyle} A populated block style based on the * given colour. * @protected */ -Blockly.blockRendering.ConstantProvider.prototype.createBlockStyle_ = function( - colour) { - return this.validatedBlockStyle_({ - 'colourPrimary': colour - }); +ConstantProvider.prototype.createBlockStyle_ = function(colour) { + return this.validatedBlockStyle_({'colourPrimary': colour}); }; /** @@ -715,56 +707,49 @@ Blockly.blockRendering.ConstantProvider.prototype.createBlockStyle_ = function( * hat:(string|undefined) * }} blockStyle A full or partial block style object. - * @return {!Blockly.Theme.BlockStyle} A full block style object, with all + * @return {!Theme.BlockStyle} A full block style object, with all * required properties populated. * @protected */ -Blockly.blockRendering.ConstantProvider.prototype.validatedBlockStyle_ = - function(blockStyle) { - /* eslint-disable indent */ +ConstantProvider.prototype.validatedBlockStyle_ = function(blockStyle) { // Make a new object with all of the same properties. - var valid = /** @type {!Blockly.Theme.BlockStyle} */ ({}); + const valid = /** @type {!Theme.BlockStyle} */ ({}); if (blockStyle) { - Blockly.utils.object.mixin(valid, blockStyle); + utils.object.mixin(valid, blockStyle); } // Validate required properties. - var parsedColour = Blockly.utils.parseBlockColour( - valid['colourPrimary'] || '#000'); + const parsedColour = utils.parseBlockColour(valid['colourPrimary'] || '#000'); valid.colourPrimary = parsedColour.hex; valid.colourSecondary = valid['colourSecondary'] ? - Blockly.utils.parseBlockColour(valid['colourSecondary']).hex : + utils.parseBlockColour(valid['colourSecondary']).hex : this.generateSecondaryColour_(valid.colourPrimary); valid.colourTertiary = valid['colourTertiary'] ? - Blockly.utils.parseBlockColour(valid['colourTertiary']).hex : + utils.parseBlockColour(valid['colourTertiary']).hex : this.generateTertiaryColour_(valid.colourPrimary); valid.hat = valid['hat'] || ''; return valid; -}; /* eslint-enable indent */ +}; /** * Generate a secondary colour from the passed in primary colour. - * @param {string} colour Primary colour. + * @param {string} inputColour Primary colour. * @return {string} The generated secondary colour. * @protected */ -Blockly.blockRendering.ConstantProvider.prototype.generateSecondaryColour_ = - function(colour) { - /* eslint-disable indent */ - return Blockly.utils.colour.blend('#fff', colour, 0.6) || colour; -}; /* eslint-enable indent */ +ConstantProvider.prototype.generateSecondaryColour_ = function(inputColour) { + return colour.blend('#fff', inputColour, 0.6) || inputColour; +}; /** * Generate a tertiary colour from the passed in primary colour. - * @param {string} colour Primary colour. + * @param {string} inputColour Primary colour. * @return {string} The generated tertiary colour. * @protected */ -Blockly.blockRendering.ConstantProvider.prototype.generateTertiaryColour_ = - function(colour) { - /* eslint-disable indent */ - return Blockly.utils.colour.blend('#fff', colour, 0.3) || colour; -}; /* eslint-enable indent */ +ConstantProvider.prototype.generateTertiaryColour_ = function(inputColour) { + return colour.blend('#fff', inputColour, 0.3) || inputColour; +}; /** @@ -772,15 +757,15 @@ Blockly.blockRendering.ConstantProvider.prototype.generateTertiaryColour_ = * Delete all DOM elements that this provider created. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.dispose = function() { +ConstantProvider.prototype.dispose = function() { if (this.embossFilter_) { - Blockly.utils.dom.removeNode(this.embossFilter_); + dom.removeNode(this.embossFilter_); } if (this.disabledPattern_) { - Blockly.utils.dom.removeNode(this.disabledPattern_); + dom.removeNode(this.disabledPattern_); } if (this.debugFilter_) { - Blockly.utils.dom.removeNode(this.debugFilter_); + dom.removeNode(this.debugFilter_); } this.cssNode_ = null; }; @@ -790,22 +775,15 @@ Blockly.blockRendering.ConstantProvider.prototype.dispose = function() { * collapsed block indicators. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.makeJaggedTeeth = function() { - var height = this.JAGGED_TEETH_HEIGHT; - var width = this.JAGGED_TEETH_WIDTH; +ConstantProvider.prototype.makeJaggedTeeth = function() { + const height = this.JAGGED_TEETH_HEIGHT; + const width = this.JAGGED_TEETH_WIDTH; - var mainPath = - Blockly.utils.svgPaths.line( - [ - Blockly.utils.svgPaths.point(width, height / 4), - Blockly.utils.svgPaths.point(-width * 2, height / 2), - Blockly.utils.svgPaths.point(width, height / 4) - ]); - return { - height: height, - width: width, - path: mainPath - }; + const mainPath = svgPaths.line([ + svgPaths.point(width, height / 4), svgPaths.point(-width * 2, height / 2), + svgPaths.point(width, height / 4) + ]); + return {height: height, width: width, path: mainPath}; }; /** @@ -813,22 +791,15 @@ Blockly.blockRendering.ConstantProvider.prototype.makeJaggedTeeth = function() { * start hats. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.makeStartHat = function() { - var height = this.START_HAT_HEIGHT; - var width = this.START_HAT_WIDTH; +ConstantProvider.prototype.makeStartHat = function() { + const height = this.START_HAT_HEIGHT; + const width = this.START_HAT_WIDTH; - var mainPath = - Blockly.utils.svgPaths.curve('c', - [ - Blockly.utils.svgPaths.point(30, -height), - Blockly.utils.svgPaths.point(70, -height), - Blockly.utils.svgPaths.point(width, 0) - ]); - return { - height: height, - width: width, - path: mainPath - }; + const mainPath = svgPaths.curve('c', [ + svgPaths.point(30, -height), svgPaths.point(70, -height), + svgPaths.point(width, 0) + ]); + return {height: height, width: width, path: mainPath}; }; /** @@ -836,9 +807,9 @@ Blockly.blockRendering.ConstantProvider.prototype.makeStartHat = function() { * puzzle tabs. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.makePuzzleTab = function() { - var width = this.TAB_WIDTH; - var height = this.TAB_HEIGHT; +ConstantProvider.prototype.makePuzzleTab = function() { + const width = this.TAB_WIDTH; + const height = this.TAB_HEIGHT; // The main path for the puzzle tab is made out of a few curves (c and s). // Those curves are defined with relative positions. The 'up' and 'down' @@ -846,35 +817,32 @@ Blockly.blockRendering.ConstantProvider.prototype.makePuzzleTab = function() { // are the signs to use to move the cursor in the direction that the path is // being drawn. function makeMainPath(up) { - var forward = up ? -1 : 1; - var back = -forward; + const forward = up ? -1 : 1; + const back = -forward; - var overlap = 2.5; - var halfHeight = height / 2; - var control1Y = halfHeight + overlap; - var control2Y = halfHeight + 0.5; - var control3Y = overlap; // 2.5 + const overlap = 2.5; + const halfHeight = height / 2; + const control1Y = halfHeight + overlap; + const control2Y = halfHeight + 0.5; + const control3Y = overlap; // 2.5 - var endPoint1 = Blockly.utils.svgPaths.point(-width, forward * halfHeight); - var endPoint2 = Blockly.utils.svgPaths.point(width, forward * halfHeight); + const endPoint1 = svgPaths.point(-width, forward * halfHeight); + const endPoint2 = svgPaths.point(width, forward * halfHeight); - return Blockly.utils.svgPaths.curve('c', - [ - Blockly.utils.svgPaths.point(0, forward * control1Y), - Blockly.utils.svgPaths.point(-width, back * control2Y), - endPoint1 - ]) + - Blockly.utils.svgPaths.curve('s', - [ - Blockly.utils.svgPaths.point(width, back * control3Y), - endPoint2 - ]); + return svgPaths.curve( + 'c', + [ + svgPaths.point(0, forward * control1Y), + svgPaths.point(-width, back * control2Y), endPoint1 + ]) + + svgPaths.curve( + 's', [svgPaths.point(width, back * control3Y), endPoint2]); } // c 0,-10 -8,8 -8,-7.5 s 8,2.5 8,-7.5 - var pathUp = makeMainPath(true); + const pathUp = makeMainPath(true); // c 0,10 -8,-8 -8,7.5 s 8,-2.5 8,7.5 - var pathDown = makeMainPath(false); + const pathDown = makeMainPath(false); return { type: this.SHAPES.PUZZLE, @@ -890,21 +858,20 @@ Blockly.blockRendering.ConstantProvider.prototype.makePuzzleTab = function() { * notches. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.makeNotch = function() { - var width = this.NOTCH_WIDTH; - var height = this.NOTCH_HEIGHT; - var innerWidth = 3; - var outerWidth = (width - innerWidth) / 2; +ConstantProvider.prototype.makeNotch = function() { + const width = this.NOTCH_WIDTH; + const height = this.NOTCH_HEIGHT; + const innerWidth = 3; + const outerWidth = (width - innerWidth) / 2; function makeMainPath(dir) { - return Blockly.utils.svgPaths.line( - [ - Blockly.utils.svgPaths.point(dir * outerWidth, height), - Blockly.utils.svgPaths.point(dir * innerWidth, 0), - Blockly.utils.svgPaths.point(dir * outerWidth, -height) - ]); + return svgPaths.line([ + svgPaths.point(dir * outerWidth, height), + svgPaths.point(dir * innerWidth, 0), + svgPaths.point(dir * outerWidth, -height) + ]); } - var pathLeft = makeMainPath(1); - var pathRight = makeMainPath(-1); + const pathLeft = makeMainPath(1); + const pathRight = makeMainPath(-1); return { type: this.SHAPES.NOTCH, @@ -920,14 +887,14 @@ Blockly.blockRendering.ConstantProvider.prototype.makeNotch = function() { * inside corners. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.makeInsideCorners = function() { - var radius = this.CORNER_RADIUS; +ConstantProvider.prototype.makeInsideCorners = function() { + const radius = this.CORNER_RADIUS; - var innerTopLeftCorner = Blockly.utils.svgPaths.arc('a', '0 0,0', radius, - Blockly.utils.svgPaths.point(-radius, radius)); + const innerTopLeftCorner = + svgPaths.arc('a', '0 0,0', radius, svgPaths.point(-radius, radius)); - var innerBottomLeftCorner = Blockly.utils.svgPaths.arc('a', '0 0,0', radius, - Blockly.utils.svgPaths.point(radius, radius)); + const innerBottomLeftCorner = + svgPaths.arc('a', '0 0,0', radius, svgPaths.point(radius, radius)); return { width: radius, @@ -942,38 +909,35 @@ Blockly.blockRendering.ConstantProvider.prototype.makeInsideCorners = function() * outside corners. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.makeOutsideCorners = function() { - var radius = this.CORNER_RADIUS; +ConstantProvider.prototype.makeOutsideCorners = function() { + const radius = this.CORNER_RADIUS; /** * SVG path for drawing the rounded top-left corner. * @const */ - var topLeft = - Blockly.utils.svgPaths.moveBy(0, radius) + - Blockly.utils.svgPaths.arc('a', '0 0,1', radius, - Blockly.utils.svgPaths.point(radius, -radius)); + const topLeft = svgPaths.moveBy(0, radius) + + svgPaths.arc('a', '0 0,1', radius, svgPaths.point(radius, -radius)); /** * SVG path for drawing the rounded top-right corner. * @const */ - var topRight = - Blockly.utils.svgPaths.arc('a', '0 0,1', radius, - Blockly.utils.svgPaths.point(radius, radius)); + const topRight = + svgPaths.arc('a', '0 0,1', radius, svgPaths.point(radius, radius)); /** * SVG path for drawing the rounded bottom-left corner. * @const */ - var bottomLeft = Blockly.utils.svgPaths.arc('a', '0 0,1', radius, - Blockly.utils.svgPaths.point(-radius, -radius)); + const bottomLeft = + svgPaths.arc('a', '0 0,1', radius, svgPaths.point(-radius, -radius)); /** * SVG path for drawing the rounded bottom-right corner. * @const */ - var bottomRight = Blockly.utils.svgPaths.arc('a', '0 0,1', radius, - Blockly.utils.svgPaths.point(-radius, radius)); + const bottomRight = + svgPaths.arc('a', '0 0,1', radius, svgPaths.point(-radius, radius)); return { topLeft: topLeft, @@ -987,19 +951,18 @@ Blockly.blockRendering.ConstantProvider.prototype.makeOutsideCorners = function( /** * Get an object with connection shape and sizing information based on the type * of the connection. - * @param {!Blockly.RenderedConnection} connection The connection to find a + * @param {!RenderedConnection} connection The connection to find a * shape object for * @return {!Object} The shape object for the connection. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.shapeFor = function( - connection) { +ConstantProvider.prototype.shapeFor = function(connection) { switch (connection.type) { - case Blockly.connectionTypes.INPUT_VALUE: - case Blockly.connectionTypes.OUTPUT_VALUE: + case connectionTypes.INPUT_VALUE: + case connectionTypes.OUTPUT_VALUE: return this.PUZZLE_TAB; - case Blockly.connectionTypes.PREVIOUS_STATEMENT: - case Blockly.connectionTypes.NEXT_STATEMENT: + case connectionTypes.PREVIOUS_STATEMENT: + case connectionTypes.NEXT_STATEMENT: return this.NOTCH; default: throw Error('Unknown connection type'); @@ -1014,8 +977,7 @@ Blockly.blockRendering.ConstantProvider.prototype.shapeFor = function( * @suppress {strictModuleDepCheck} Debug renderer only included in playground. * @package */ -Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg, - tagName, selector) { +ConstantProvider.prototype.createDom = function(svg, tagName, selector) { this.injectCSS_(tagName, selector); /* @@ -1023,8 +985,7 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg, ... filters go here ... */ - var defs = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.DEFS, {}, svg); + this.defs_ = dom.createSvgElement(Svg.DEFS, {}, svg); /* @@ -1039,15 +1000,14 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg, k1="0" k2="1" k3="1" k4="0" /> */ - var embossFilter = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FILTER, - {'id': 'blocklyEmbossFilter' + this.randomIdentifier}, defs); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FEGAUSSIANBLUR, + const embossFilter = dom.createSvgElement( + Svg.FILTER, {'id': 'blocklyEmbossFilter' + this.randomIdentifier}, + this.defs_); + dom.createSvgElement( + Svg.FEGAUSSIANBLUR, {'in': 'SourceAlpha', 'stdDeviation': 1, 'result': 'blur'}, embossFilter); - var feSpecularLighting = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FESPECULARLIGHTING, - { + const feSpecularLighting = dom.createSvgElement( + Svg.FESPECULARLIGHTING, { 'in': 'blur', 'surfaceScale': 1, 'specularConstant': 0.5, @@ -1056,20 +1016,19 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg, 'result': 'specOut' }, embossFilter); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FEPOINTLIGHT, - {'x': -5000, 'y': -10000, 'z': 20000}, feSpecularLighting); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FECOMPOSITE, - { + dom.createSvgElement( + Svg.FEPOINTLIGHT, {'x': -5000, 'y': -10000, 'z': 20000}, + feSpecularLighting); + dom.createSvgElement( + Svg.FECOMPOSITE, { 'in': 'specOut', 'in2': 'SourceAlpha', 'operator': 'in', 'result': 'specOut' - }, embossFilter); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FECOMPOSITE, - { + }, + embossFilter); + dom.createSvgElement( + Svg.FECOMPOSITE, { 'in': 'SourceGraphic', 'in2': 'specOut', 'operator': 'arithmetic', @@ -1077,7 +1036,8 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg, 'k2': 1, 'k3': 1, 'k4': 0 - }, embossFilter); + }, + embossFilter); this.embossFilterId = embossFilter.id; this.embossFilter_ = embossFilter; @@ -1088,59 +1048,60 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg, */ - var disabledPattern = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.PATTERN, - { + const disabledPattern = dom.createSvgElement( + Svg.PATTERN, { 'id': 'blocklyDisabledPattern' + this.randomIdentifier, 'patternUnits': 'userSpaceOnUse', 'width': 10, 'height': 10 - }, defs); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - {'width': 10, 'height': 10, 'fill': '#aaa'}, disabledPattern); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.PATH, - {'d': 'M 0 0 L 10 10 M 10 0 L 0 10', 'stroke': '#cc0'}, disabledPattern); + }, + this.defs_); + dom.createSvgElement( + Svg.RECT, {'width': 10, 'height': 10, 'fill': '#aaa'}, disabledPattern); + dom.createSvgElement( + Svg.PATH, {'d': 'M 0 0 L 10 10 M 10 0 L 0 10', 'stroke': '#cc0'}, + disabledPattern); this.disabledPatternId = disabledPattern.id; this.disabledPattern_ = disabledPattern; - if (Blockly.blockRendering.Debug) { - var debugFilter = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FILTER, - { + this.createDebugFilter(); +}; + +/** + * Create a filter for highlighting the currently rendering block during + * render debugging. + * @private + */ +ConstantProvider.prototype.createDebugFilter = function() { + // Only create the debug filter once. + if (!this.debugFilter_) { + const debugFilter = dom.createSvgElement( + Svg.FILTER, { 'id': 'blocklyDebugFilter' + this.randomIdentifier, 'height': '160%', 'width': '180%', y: '-30%', x: '-40%' }, - defs); + this.defs_); // Set all gaussian blur pixels to 1 opacity before applying flood - var debugComponentTransfer = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FECOMPONENTTRANSFER, { - 'result': 'outBlur' - }, debugFilter); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FEFUNCA, - { - 'type': 'table', 'tableValues': '0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1' - }, + const debugComponentTransfer = dom.createSvgElement( + Svg.FECOMPONENTTRANSFER, {'result': 'outBlur'}, debugFilter); + dom.createSvgElement( + Svg.FEFUNCA, + {'type': 'table', 'tableValues': '0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1'}, debugComponentTransfer); // Color the highlight - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FEFLOOD, - { - 'flood-color': '#ff0000', - 'flood-opacity': 0.5, - 'result': 'outColor' - }, + dom.createSvgElement( + Svg.FEFLOOD, + {'flood-color': '#ff0000', 'flood-opacity': 0.5, 'result': 'outColor'}, debugFilter); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FECOMPOSITE, - { - 'in': 'outColor', 'in2': 'outBlur', - 'operator': 'in', 'result': 'outGlow' + dom.createSvgElement( + Svg.FECOMPOSITE, { + 'in': 'outColor', + 'in2': 'outBlur', + 'operator': 'in', + 'result': 'outGlow' }, debugFilter); this.debugFilterId = debugFilter.id; @@ -1154,23 +1115,22 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg, * @param {string} selector The CSS selector to use. * @protected */ -Blockly.blockRendering.ConstantProvider.prototype.injectCSS_ = function( - tagName, selector) { - var cssArray = this.getCSS_(selector); - var cssNodeId = 'blockly-renderer-style-' + tagName; +ConstantProvider.prototype.injectCSS_ = function(tagName, selector) { + const cssArray = this.getCSS_(selector); + const cssNodeId = 'blockly-renderer-style-' + tagName; this.cssNode_ = - /** @type {!HTMLStyleElement} */ (document.getElementById(cssNodeId)); - var text = cssArray.join('\n'); + /** @type {!HTMLStyleElement} */ (document.getElementById(cssNodeId)); + const text = cssArray.join('\n'); if (this.cssNode_) { // Already injected, update if the theme changed. this.cssNode_.firstChild.textContent = text; return; } // Inject CSS tag at start of head. - var cssNode = - /** @type {!HTMLStyleElement} */ (document.createElement('style')); + const cssNode = + /** @type {!HTMLStyleElement} */ (document.createElement('style')); cssNode.id = cssNodeId; - var cssTextNode = document.createTextNode(text); + const cssTextNode = document.createTextNode(text); cssNode.appendChild(cssTextNode); document.head.insertBefore(cssNode, document.head.firstChild); this.cssNode_ = cssNode; @@ -1182,9 +1142,10 @@ Blockly.blockRendering.ConstantProvider.prototype.injectCSS_ = function( * @return {!Array} Array of CSS strings. * @protected */ -Blockly.blockRendering.ConstantProvider.prototype.getCSS_ = function(selector) { +ConstantProvider.prototype.getCSS_ = function(selector) { return [ /* eslint-disable indent */ + /* clang-format off */ // Text. selector + ' .blocklyText, ', selector + ' .blocklyFlyoutLabelText {', @@ -1254,6 +1215,9 @@ Blockly.blockRendering.ConstantProvider.prototype.getCSS_ = function(selector) { 'fill-opacity: ' + this.INSERTION_MARKER_OPACITY + ';', 'stroke: none;', '}', + /* clang-format on */ /* eslint-enable indent */ ]; }; + +exports = ConstantProvider; diff --git a/core/renderers/common/path_object.js b/core/renderers/common/path_object.js index e81b8e0e2..7b1f6af9d 100644 --- a/core/renderers/common/path_object.js +++ b/core/renderers/common/path_object.js @@ -11,34 +11,39 @@ 'use strict'; -goog.provide('Blockly.blockRendering.PathObject'); +goog.module('Blockly.blockRendering.PathObject'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.blockRendering.ConstantProvider'); -goog.require('Blockly.blockRendering.IPathObject'); -goog.require('Blockly.Theme'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.Svg'); - -goog.requireType('Blockly.Block'); -goog.requireType('Blockly.Connection'); +/* eslint-disable-next-line no-unused-vars */ +const Block = goog.requireType('Blockly.Block'); +/* eslint-disable-next-line no-unused-vars */ +const Connection = goog.requireType('Blockly.Connection'); +/* eslint-disable-next-line no-unused-vars */ +const ConstantProvider = goog.requireType('Blockly.blockRendering.ConstantProvider'); +/* eslint-disable-next-line no-unused-vars */ +const IPathObject = goog.require('Blockly.blockRendering.IPathObject'); +const Svg = goog.require('Blockly.utils.Svg'); +/* eslint-disable-next-line no-unused-vars */ +const Theme = goog.requireType('Blockly.Theme'); +const dom = goog.require('Blockly.utils.dom'); /** * An object that handles creating and setting each of the SVG elements * used by the renderer. * @param {!SVGElement} root The root SVG element. - * @param {!Blockly.Theme.BlockStyle} style The style object to use for + * @param {!Theme.BlockStyle} style The style object to use for * colouring. - * @param {!Blockly.blockRendering.ConstantProvider} constants The renderer's + * @param {!ConstantProvider} constants The renderer's * constants. * @constructor - * @implements {Blockly.blockRendering.IPathObject} + * @implements {IPathObject} * @package */ -Blockly.blockRendering.PathObject = function(root, style, constants) { +const PathObject = function(root, style, constants) { /** * The renderer's constant provider. - * @type {!Blockly.blockRendering.ConstantProvider} + * @type {!ConstantProvider} * @package */ this.constants = constants; @@ -50,13 +55,12 @@ Blockly.blockRendering.PathObject = function(root, style, constants) { * @type {!SVGElement} * @package */ - this.svgPath = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.PATH, - {'class': 'blocklyPath'}, this.svgRoot); + this.svgPath = + dom.createSvgElement(Svg.PATH, {'class': 'blocklyPath'}, this.svgRoot); /** * The style object to use when colouring block paths. - * @type {!Blockly.Theme.BlockStyle} + * @type {!Theme.BlockStyle} * @package */ this.style = style; @@ -83,7 +87,7 @@ Blockly.blockRendering.PathObject = function(root, style, constants) { * @param {string} pathString The path. * @package */ -Blockly.blockRendering.PathObject.prototype.setPath = function(pathString) { +PathObject.prototype.setPath = function(pathString) { this.svgPath.setAttribute('d', pathString); }; @@ -91,7 +95,7 @@ Blockly.blockRendering.PathObject.prototype.setPath = function(pathString) { * Flip the SVG paths in RTL. * @package */ -Blockly.blockRendering.PathObject.prototype.flipRTL = function() { +PathObject.prototype.flipRTL = function() { // Mirror the block's path. this.svgPath.setAttribute('transform', 'scale(-1 1)'); }; @@ -102,7 +106,7 @@ Blockly.blockRendering.PathObject.prototype.flipRTL = function() { * block SVG group. * @package */ -Blockly.blockRendering.PathObject.prototype.setCursorSvg = function(cursorSvg) { +PathObject.prototype.setCursorSvg = function(cursorSvg) { if (!cursorSvg) { this.cursorSvg = null; return; @@ -118,7 +122,7 @@ Blockly.blockRendering.PathObject.prototype.setCursorSvg = function(cursorSvg) { * block SVG group. * @package */ -Blockly.blockRendering.PathObject.prototype.setMarkerSvg = function(markerSvg) { +PathObject.prototype.setMarkerSvg = function(markerSvg) { if (!markerSvg) { this.markerSvg = null; return; @@ -135,10 +139,10 @@ Blockly.blockRendering.PathObject.prototype.setMarkerSvg = function(markerSvg) { /** * Apply the stored colours to the block's path, taking into account whether * the paths belong to a shadow block. - * @param {!Blockly.Block} block The source block. + * @param {!Block} block The source block. * @package */ -Blockly.blockRendering.PathObject.prototype.applyColour = function(block) { +PathObject.prototype.applyColour = function(block) { this.svgPath.setAttribute('stroke', this.style.colourTertiary); this.svgPath.setAttribute('fill', this.style.colourPrimary); @@ -148,10 +152,10 @@ Blockly.blockRendering.PathObject.prototype.applyColour = function(block) { /** * Set the style. - * @param {!Blockly.Theme.BlockStyle} blockStyle The block style to use. + * @param {!Theme.BlockStyle} blockStyle The block style to use. * @package */ -Blockly.blockRendering.PathObject.prototype.setStyle = function(blockStyle) { +PathObject.prototype.setStyle = function(blockStyle) { this.style = blockStyle; }; @@ -162,14 +166,11 @@ Blockly.blockRendering.PathObject.prototype.setStyle = function(blockStyle) { * be removed. * @protected */ -Blockly.blockRendering.PathObject.prototype.setClass_ = function( - className, add) { +PathObject.prototype.setClass_ = function(className, add) { if (add) { - Blockly.utils.dom.addClass(/** @type {!Element} */ (this.svgRoot), - className); + dom.addClass(/** @type {!Element} */ (this.svgRoot), className); } else { - Blockly.utils.dom.removeClass(/** @type {!Element} */ (this.svgRoot), - className); + dom.removeClass(/** @type {!Element} */ (this.svgRoot), className); } }; @@ -179,11 +180,10 @@ Blockly.blockRendering.PathObject.prototype.setClass_ = function( * @param {boolean} enable True if highlighted. * @package */ -Blockly.blockRendering.PathObject.prototype.updateHighlighted = function( - enable) { +PathObject.prototype.updateHighlighted = function(enable) { if (enable) { - this.svgPath.setAttribute('filter', - 'url(#' + this.constants.embossFilterId + ')'); + this.svgPath.setAttribute( + 'filter', 'url(#' + this.constants.embossFilterId + ')'); } else { this.svgPath.setAttribute('filter', 'none'); } @@ -194,7 +194,7 @@ Blockly.blockRendering.PathObject.prototype.updateHighlighted = function( * @param {boolean} shadow True if the block is a shadow block. * @protected */ -Blockly.blockRendering.PathObject.prototype.updateShadow_ = function(shadow) { +PathObject.prototype.updateShadow_ = function(shadow) { if (shadow) { this.svgPath.setAttribute('stroke', 'none'); this.svgPath.setAttribute('fill', this.style.colourSecondary); @@ -206,12 +206,11 @@ Blockly.blockRendering.PathObject.prototype.updateShadow_ = function(shadow) { * @param {boolean} disabled True if disabled. * @protected */ -Blockly.blockRendering.PathObject.prototype.updateDisabled_ = function( - disabled) { +PathObject.prototype.updateDisabled_ = function(disabled) { this.setClass_('blocklyDisabled', disabled); if (disabled) { - this.svgPath.setAttribute('fill', - 'url(#' + this.constants.disabledPatternId + ')'); + this.svgPath.setAttribute( + 'fill', 'url(#' + this.constants.disabledPatternId + ')'); } }; @@ -220,7 +219,7 @@ Blockly.blockRendering.PathObject.prototype.updateDisabled_ = function( * @param {boolean} enable True if selection is enabled, false otherwise. * @package */ -Blockly.blockRendering.PathObject.prototype.updateSelected = function(enable) { +PathObject.prototype.updateSelected = function(enable) { this.setClass_('blocklySelected', enable); }; @@ -230,8 +229,7 @@ Blockly.blockRendering.PathObject.prototype.updateSelected = function(enable) { * area, false otherwise. * @package */ -Blockly.blockRendering.PathObject.prototype.updateDraggingDelete = function( - enable) { +PathObject.prototype.updateDraggingDelete = function(enable) { this.setClass_('blocklyDraggingDelete', enable); }; @@ -241,8 +239,7 @@ Blockly.blockRendering.PathObject.prototype.updateDraggingDelete = function( * otherwise. * @package */ -Blockly.blockRendering.PathObject.prototype.updateInsertionMarker = function( - enable) { +PathObject.prototype.updateInsertionMarker = function(enable) { this.setClass_('blocklyInsertionMarker', enable); }; @@ -251,7 +248,7 @@ Blockly.blockRendering.PathObject.prototype.updateInsertionMarker = function( * @param {boolean} enable True if the block is movable, false otherwise. * @package */ -Blockly.blockRendering.PathObject.prototype.updateMovable = function(enable) { +PathObject.prototype.updateMovable = function(enable) { this.setClass_('blocklyDraggable', enable); }; @@ -262,21 +259,19 @@ Blockly.blockRendering.PathObject.prototype.updateMovable = function(enable) { * @param {boolean} enable True if styling should be added. * @package */ -Blockly.blockRendering.PathObject.prototype.updateReplacementFade = - function(enable) { - /* eslint-disable indent */ +PathObject.prototype.updateReplacementFade = function(enable) { this.setClass_('blocklyReplaceable', enable); -}; /* eslint-enable indent */ +}; /** * Add or remove styling that shows that if the dragging block is dropped, this * block will be connected to the input. - * @param {Blockly.Connection} _conn The connection on the input to highlight. + * @param {Connection} _conn The connection on the input to highlight. * @param {boolean} _enable True if styling should be added. * @package */ -Blockly.blockRendering.PathObject.prototype.updateShapeForInputHighlight = - function(_conn, _enable) { - /* eslint-disable indent */ +PathObject.prototype.updateShapeForInputHighlight = function(_conn, _enable) { // NOP -}; /* eslint-enable indent */ +}; + +exports = PathObject; diff --git a/core/requires.js b/core/requires.js index 2ca295441..cc67f564a 100644 --- a/core/requires.js +++ b/core/requires.js @@ -42,7 +42,6 @@ goog.require('Blockly.Trashcan'); goog.require('Blockly.VariablesDynamic'); // Only need to require these two if you're using workspace comments. // goog.require('Blockly.WorkspaceCommentSvg'); -// goog.require('Blockly.WorkspaceCommentSvg.render'); // If zoom controls aren't required, then Blockly.inject's // "zoom"/"controls" configuration must be false. goog.require('Blockly.ZoomControls'); diff --git a/core/shortcut_registry.js b/core/shortcut_registry.js index 14684e1b8..3da777eae 100644 --- a/core/shortcut_registry.js +++ b/core/shortcut_registry.js @@ -11,27 +11,28 @@ */ 'use strict'; -goog.provide('Blockly.ShortcutRegistry'); +goog.module('Blockly.ShortcutRegistry'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.utils.KeyCodes'); -goog.require('Blockly.utils.object'); - -goog.requireType('Blockly.Workspace'); +const KeyCodes = goog.require('Blockly.utils.KeyCodes'); +/* eslint-disable-next-line no-unused-vars */ +const Workspace = goog.requireType('Blockly.Workspace'); +const object = goog.require('Blockly.utils.object'); /** * Class for the registry of keyboard shortcuts. This is intended to be a * singleton. You should not create a new instance, and only access this class - * from Blockly.ShortcutRegistry.registry. + * from ShortcutRegistry.registry. * @constructor */ -Blockly.ShortcutRegistry = function() { +const ShortcutRegistry = function() { // Singleton instance should be registered once. - Blockly.ShortcutRegistry.registry = this; + ShortcutRegistry.registry = this; /** * Registry of all keyboard shortcuts, keyed by name of shortcut. - * @type {!Object} + * @type {!Object} * @private */ this.registry_ = Object.create(null); @@ -46,39 +47,38 @@ Blockly.ShortcutRegistry = function() { /** * Enum of valid modifiers. - * @enum {!Blockly.utils.KeyCodes} + * @enum {!KeyCodes} */ -Blockly.ShortcutRegistry.modifierKeys = { - 'Shift': Blockly.utils.KeyCodes.SHIFT, - 'Control': Blockly.utils.KeyCodes.CTRL, - 'Alt': Blockly.utils.KeyCodes.ALT, - 'Meta': Blockly.utils.KeyCodes.META +ShortcutRegistry.modifierKeys = { + 'Shift': KeyCodes.SHIFT, + 'Control': KeyCodes.CTRL, + 'Alt': KeyCodes.ALT, + 'Meta': KeyCodes.META }; /** * A keyboard shortcut. * @typedef {{ - * callback: ((function(!Blockly.Workspace, Event, - * !Blockly.ShortcutRegistry.KeyboardShortcut):boolean)|undefined), + * callback: ((function(!Workspace, Event, + * !ShortcutRegistry.KeyboardShortcut):boolean)|undefined), * name: string, - * preconditionFn: ((function(!Blockly.Workspace):boolean)|undefined), + * preconditionFn: ((function(!Workspace):boolean)|undefined), * metadata: (Object|undefined) * }} */ -Blockly.ShortcutRegistry.KeyboardShortcut; +ShortcutRegistry.KeyboardShortcut; /** * Registers a keyboard shortcut. - * @param {!Blockly.ShortcutRegistry.KeyboardShortcut} shortcut The + * @param {!ShortcutRegistry.KeyboardShortcut} shortcut The * shortcut for this key code. * @param {boolean=} opt_allowOverrides True to prevent a warning when * overriding an already registered item. * @throws {Error} if a shortcut with the same name already exists. * @public */ -Blockly.ShortcutRegistry.prototype.register = function( - shortcut, opt_allowOverrides) { - var registeredShortcut = this.registry_[shortcut.name]; +ShortcutRegistry.prototype.register = function(shortcut, opt_allowOverrides) { + const registeredShortcut = this.registry_[shortcut.name]; if (registeredShortcut && !opt_allowOverrides) { throw new Error( 'Shortcut with name "' + shortcut.name + '" already exists.'); @@ -93,8 +93,8 @@ Blockly.ShortcutRegistry.prototype.register = function( * @return {boolean} True if an item was unregistered, false otherwise. * @public */ -Blockly.ShortcutRegistry.prototype.unregister = function(shortcutName) { - var shortcut = this.registry_[shortcutName]; +ShortcutRegistry.prototype.unregister = function(shortcutName) { + const shortcut = this.registry_[shortcutName]; if (!shortcut) { console.warn( @@ -110,9 +110,9 @@ Blockly.ShortcutRegistry.prototype.unregister = function(shortcutName) { /** * Adds a mapping between a keycode and a keyboard shortcut. - * @param {string|Blockly.utils.KeyCodes} keyCode The key code for the keyboard + * @param {string|KeyCodes} keyCode The key code for the keyboard * shortcut. If registering a key code with a modifier (ex: ctrl+c) use - * Blockly.ShortcutRegistry.registry.createSerializedKey; + * ShortcutRegistry.registry.createSerializedKey; * @param {string} shortcutName The name of the shortcut to execute when the * given keycode is pressed. * @param {boolean=} opt_allowCollision True to prevent an error when adding a @@ -120,10 +120,10 @@ Blockly.ShortcutRegistry.prototype.unregister = function(shortcutName) { * @throws {Error} if the given key code is already mapped to a shortcut. * @public */ -Blockly.ShortcutRegistry.prototype.addKeyMapping = function( +ShortcutRegistry.prototype.addKeyMapping = function( keyCode, shortcutName, opt_allowCollision) { keyCode = String(keyCode); - var shortcutNames = this.keyMap_[keyCode]; + const shortcutNames = this.keyMap_[keyCode]; if (shortcutNames && !opt_allowCollision) { throw new Error( 'Shortcut with name "' + shortcutName + '" collides with shortcuts ' + @@ -139,7 +139,7 @@ Blockly.ShortcutRegistry.prototype.addKeyMapping = function( * Removes a mapping between a keycode and a keyboard shortcut. * @param {string} keyCode The key code for the keyboard shortcut. If * registering a key code with a modifier (ex: ctrl+c) use - * Blockly.ShortcutRegistry.registry.createSerializedKey; + * ShortcutRegistry.registry.createSerializedKey; * @param {string} shortcutName The name of the shortcut to execute when the * given keycode is pressed. * @param {boolean=} opt_quiet True to not console warn when there is no @@ -147,9 +147,9 @@ Blockly.ShortcutRegistry.prototype.addKeyMapping = function( * @return {boolean} True if a key mapping was removed, false otherwise. * @public */ -Blockly.ShortcutRegistry.prototype.removeKeyMapping = function( +ShortcutRegistry.prototype.removeKeyMapping = function( keyCode, shortcutName, opt_quiet) { - var shortcutNames = this.keyMap_[keyCode]; + const shortcutNames = this.keyMap_[keyCode]; if (!shortcutNames && !opt_quiet) { console.warn( @@ -158,7 +158,7 @@ Blockly.ShortcutRegistry.prototype.removeKeyMapping = function( return false; } - var shortcutIdx = shortcutNames.indexOf(shortcutName); + const shortcutIdx = shortcutNames.indexOf(shortcutName); if (shortcutIdx > -1) { shortcutNames.splice(shortcutIdx, 1); if (shortcutNames.length == 0) { @@ -167,7 +167,8 @@ Blockly.ShortcutRegistry.prototype.removeKeyMapping = function( return true; } if (!opt_quiet) { - console.warn('No keyboard shortcut with name "' + shortcutName + + console.warn( + 'No keyboard shortcut with name "' + shortcutName + '" registered with key code "' + keyCode + '"'); } return false; @@ -175,13 +176,14 @@ Blockly.ShortcutRegistry.prototype.removeKeyMapping = function( /** * Removes all the key mappings for a shortcut with the given name. - * Useful when changing the default key mappings and the key codes registered to the shortcut are - * unknown. - * @param {string} shortcutName The name of the shortcut to remove from the key map. + * Useful when changing the default key mappings and the key codes registered to + * the shortcut are unknown. + * @param {string} shortcutName The name of the shortcut to remove from the key + * map. * @public */ -Blockly.ShortcutRegistry.prototype.removeAllKeyMappings = function(shortcutName) { - for (var keyCode in this.keyMap_) { +ShortcutRegistry.prototype.removeAllKeyMappings = function(shortcutName) { + for (const keyCode in this.keyMap_) { this.removeKeyMapping(keyCode, shortcutName, true); } }; @@ -192,46 +194,46 @@ Blockly.ShortcutRegistry.prototype.removeAllKeyMappings = function(shortcutName) * shortcut names. * @public */ -Blockly.ShortcutRegistry.prototype.setKeyMap = function(keyMap) { +ShortcutRegistry.prototype.setKeyMap = function(keyMap) { this.keyMap_ = keyMap; }; /** * Gets the current key map. - * @return {!Object>} - * The object holding key codes to Blockly.ShortcutRegistry.KeyboardShortcut. + * @return {!Object>} + * The object holding key codes to ShortcutRegistry.KeyboardShortcut. * @public */ -Blockly.ShortcutRegistry.prototype.getKeyMap = function() { - return Blockly.utils.object.deepMerge(Object.create(null), this.keyMap_); +ShortcutRegistry.prototype.getKeyMap = function() { + return object.deepMerge(Object.create(null), this.keyMap_); }; /** * Gets the registry of keyboard shortcuts. - * @return {!Object} + * @return {!Object} * The registry of keyboard shortcuts. * @public */ -Blockly.ShortcutRegistry.prototype.getRegistry = function() { - return Blockly.utils.object.deepMerge(Object.create(null), this.registry_); +ShortcutRegistry.prototype.getRegistry = function() { + return object.deepMerge(Object.create(null), this.registry_); }; /** * Handles key down events. - * @param {!Blockly.Workspace} workspace The main workspace where the event was + * @param {!Workspace} workspace The main workspace where the event was * captured. * @param {!Event} e The key down event. * @return {boolean} True if the event was handled, false otherwise. * @public */ -Blockly.ShortcutRegistry.prototype.onKeyDown = function(workspace, e) { - var key = this.serializeKeyEvent_(e); - var shortcutNames = this.getShortcutNamesByKeyCode(key); +ShortcutRegistry.prototype.onKeyDown = function(workspace, e) { + const key = this.serializeKeyEvent_(e); + const shortcutNames = this.getShortcutNamesByKeyCode(key); if (!shortcutNames) { return false; } - for (var i = 0, shortcutName; (shortcutName = shortcutNames[i]); i++) { - var shortcut = this.registry_[shortcutName]; + for (let i = 0, shortcutName; (shortcutName = shortcutNames[i]); i++) { + const shortcut = this.registry_[shortcutName]; if (!shortcut.preconditionFn || shortcut.preconditionFn(workspace)) { // If the key has been handled, stop processing shortcuts. if (shortcut.callback && shortcut.callback(workspace, e, shortcut)) { @@ -249,8 +251,7 @@ Blockly.ShortcutRegistry.prototype.onKeyDown = function(workspace, e) { * given keyCode is used. Undefined if no shortcuts exist. * @public */ -Blockly.ShortcutRegistry.prototype.getShortcutNamesByKeyCode = function( - keyCode) { +ShortcutRegistry.prototype.getShortcutNamesByKeyCode = function(keyCode) { return this.keyMap_[keyCode] || []; }; @@ -262,12 +263,11 @@ Blockly.ShortcutRegistry.prototype.getShortcutNamesByKeyCode = function( * registered under. * @public */ -Blockly.ShortcutRegistry.prototype.getKeyCodesByShortcutName = function( - shortcutName) { - var keys = []; - for (var keyCode in this.keyMap_) { - var shortcuts = this.keyMap_[keyCode]; - var shortcutIdx = shortcuts.indexOf(shortcutName); +ShortcutRegistry.prototype.getKeyCodesByShortcutName = function(shortcutName) { + const keys = []; + for (const keyCode in this.keyMap_) { + const shortcuts = this.keyMap_[keyCode]; + const shortcutIdx = shortcuts.indexOf(shortcutName); if (shortcutIdx > -1) { keys.push(keyCode); } @@ -281,9 +281,9 @@ Blockly.ShortcutRegistry.prototype.getKeyCodesByShortcutName = function( * @return {string} The serialized key code for the given event. * @private */ -Blockly.ShortcutRegistry.prototype.serializeKeyEvent_ = function(e) { - var serializedKey = ''; - for (var modifier in Blockly.ShortcutRegistry.modifierKeys) { +ShortcutRegistry.prototype.serializeKeyEvent_ = function(e) { + let serializedKey = ''; + for (const modifier in ShortcutRegistry.modifierKeys) { if (e.getModifierState(modifier)) { if (serializedKey != '') { serializedKey += '+'; @@ -305,11 +305,9 @@ Blockly.ShortcutRegistry.prototype.serializeKeyEvent_ = function(e) { * @throws {Error} if the modifier is not in the valid modifiers list. * @private */ -Blockly.ShortcutRegistry.prototype.checkModifiers_ = function( - modifiers) { - var validModifiers = Blockly.utils.object.values( - Blockly.ShortcutRegistry.modifierKeys); - for (var i = 0, modifier; (modifier = modifiers[i]); i++) { +ShortcutRegistry.prototype.checkModifiers_ = function(modifiers) { + const validModifiers = object.values(ShortcutRegistry.modifierKeys); + for (let i = 0, modifier; (modifier = modifiers[i]); i++) { if (validModifiers.indexOf(modifier) < 0) { throw new Error(modifier + ' is not a valid modifier key.'); } @@ -321,19 +319,17 @@ Blockly.ShortcutRegistry.prototype.checkModifiers_ = function( * @param {number} keyCode Number code representing the key. * @param {?Array} modifiers List of modifier key codes to be used with * the key. All valid modifiers can be found in the - * Blockly.ShortcutRegistry.modifierKeys. + * ShortcutRegistry.modifierKeys. * @return {string} The serialized key code for the given modifiers and key. * @public */ -Blockly.ShortcutRegistry.prototype.createSerializedKey = function( - keyCode, modifiers) { - var serializedKey = ''; +ShortcutRegistry.prototype.createSerializedKey = function(keyCode, modifiers) { + let serializedKey = ''; if (modifiers) { this.checkModifiers_(modifiers); - for (var modifier in Blockly.ShortcutRegistry.modifierKeys) { - var modifierKeyCode = - Blockly.ShortcutRegistry.modifierKeys[modifier]; + for (const modifier in ShortcutRegistry.modifierKeys) { + const modifierKeyCode = ShortcutRegistry.modifierKeys[modifier]; if (modifiers.indexOf(modifierKeyCode) > -1) { if (serializedKey != '') { serializedKey += '+'; @@ -352,4 +348,6 @@ Blockly.ShortcutRegistry.prototype.createSerializedKey = function( }; // Creates and assigns the singleton instance. -new Blockly.ShortcutRegistry(); +new ShortcutRegistry(); + +exports = ShortcutRegistry; diff --git a/core/theme_manager.js b/core/theme_manager.js index 6c461a2e7..859a33658 100644 --- a/core/theme_manager.js +++ b/core/theme_manager.js @@ -12,47 +12,50 @@ */ 'use strict'; -goog.provide('Blockly.ThemeManager'); +goog.module('Blockly.ThemeManager'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Theme'); - -goog.requireType('Blockly.Workspace'); -goog.requireType('Blockly.WorkspaceSvg'); +/* eslint-disable-next-line no-unused-vars */ +const Theme = goog.requireType('Blockly.Theme'); +/* eslint-disable-next-line no-unused-vars */ +const Workspace = goog.requireType('Blockly.Workspace'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +const dom = goog.require('Blockly.utils.dom'); /** * Class for storing and updating a workspace's theme and UI components. - * @param {!Blockly.WorkspaceSvg} workspace The main workspace. - * @param {!Blockly.Theme} theme The workspace theme. + * @param {!WorkspaceSvg} workspace The main workspace. + * @param {!Theme} theme The workspace theme. * @constructor * @package */ -Blockly.ThemeManager = function(workspace, theme) { - +const ThemeManager = function(workspace, theme) { /** * The main workspace. - * @type {!Blockly.WorkspaceSvg} + * @type {!WorkspaceSvg} * @private */ this.workspace_ = workspace; /** * The Blockly theme to use. - * @type {!Blockly.Theme} + * @type {!Theme} * @private */ this.theme_ = theme; /** * A list of workspaces that are subscribed to this theme. - * @type {!Array} + * @type {!Array} * @private */ this.subscribedWorkspaces_ = []; /** * A map of subscribed UI components, keyed by component name. - * @type {!Object>} + * @type {!Object>} * @private */ this.componentDB_ = Object.create(null); @@ -61,51 +64,51 @@ Blockly.ThemeManager = function(workspace, theme) { /** * A Blockly UI component type. * @typedef {{ - * element:!Element, - * propertyName:string - * }} - */ -Blockly.ThemeManager.Component; + * element:!Element, + * propertyName:string + * }} + */ +ThemeManager.Component; /** * Get the workspace theme. - * @return {!Blockly.Theme} The workspace theme. + * @return {!Theme} The workspace theme. * @package */ -Blockly.ThemeManager.prototype.getTheme = function() { +ThemeManager.prototype.getTheme = function() { return this.theme_; }; /** * Set the workspace theme, and refresh the workspace and all components. - * @param {!Blockly.Theme} theme The workspace theme. + * @param {!Theme} theme The workspace theme. * @package */ -Blockly.ThemeManager.prototype.setTheme = function(theme) { - var prevTheme = this.theme_; +ThemeManager.prototype.setTheme = function(theme) { + const prevTheme = this.theme_; this.theme_ = theme; // Set the theme name onto the injection div. - var injectionDiv = this.workspace_.getInjectionDiv(); + const injectionDiv = this.workspace_.getInjectionDiv(); if (injectionDiv) { if (prevTheme) { - Blockly.utils.dom.removeClass(injectionDiv, prevTheme.getClassName()); + dom.removeClass(injectionDiv, prevTheme.getClassName()); } - Blockly.utils.dom.addClass(injectionDiv, this.theme_.getClassName()); + dom.addClass(injectionDiv, this.theme_.getClassName()); } // Refresh all subscribed workspaces. - for (var i = 0, workspace; (workspace = this.subscribedWorkspaces_[i]); i++) { + for (let i = 0, workspace; (workspace = this.subscribedWorkspaces_[i]); i++) { workspace.refreshTheme(); } // Refresh all registered Blockly UI components. - for (var i = 0, keys = Object.keys(this.componentDB_), - key; (key = keys[i]); i++) { - for (var j = 0, component; (component = this.componentDB_[key][j]); j++) { - var element = component.element; - var propertyName = component.propertyName; - var style = this.theme_ && this.theme_.getComponentStyle(key); + for (let i = 0, keys = Object.keys(this.componentDB_), key; (key = keys[i]); + i++) { + for (let j = 0, component; (component = this.componentDB_[key][j]); j++) { + const element = component.element; + const propertyName = component.propertyName; + const style = this.theme_ && this.theme_.getComponentStyle(key); element.style[propertyName] = style || ''; } } @@ -116,20 +119,20 @@ Blockly.ThemeManager.prototype.setTheme = function(theme) { /** * Subscribe a workspace to changes to the selected theme. If a new theme is * set, the workspace is called to refresh its blocks. - * @param {!Blockly.Workspace} workspace The workspace to subscribe. + * @param {!Workspace} workspace The workspace to subscribe. * @package */ -Blockly.ThemeManager.prototype.subscribeWorkspace = function(workspace) { +ThemeManager.prototype.subscribeWorkspace = function(workspace) { this.subscribedWorkspaces_.push(workspace); }; /** * Unsubscribe a workspace to changes to the selected theme. - * @param {!Blockly.Workspace} workspace The workspace to unsubscribe. + * @param {!Workspace} workspace The workspace to unsubscribe. * @package */ -Blockly.ThemeManager.prototype.unsubscribeWorkspace = function(workspace) { - var index = this.subscribedWorkspaces_.indexOf(workspace); +ThemeManager.prototype.unsubscribeWorkspace = function(workspace) { + const index = this.subscribedWorkspaces_.indexOf(workspace); if (index < 0) { throw Error('Cannot unsubscribe a workspace that hasn\'t been subscribed.'); } @@ -145,20 +148,18 @@ Blockly.ThemeManager.prototype.unsubscribeWorkspace = function(workspace) { * @param {string} propertyName The inline style property name to update. * @package */ -Blockly.ThemeManager.prototype.subscribe = function(element, componentName, - propertyName) { +ThemeManager.prototype.subscribe = function( + element, componentName, propertyName) { if (!this.componentDB_[componentName]) { this.componentDB_[componentName] = []; } // Add the element to our component map. - this.componentDB_[componentName].push({ - element: element, - propertyName: propertyName - }); + this.componentDB_[componentName].push( + {element: element, propertyName: propertyName}); // Initialize the element with its corresponding theme style. - var style = this.theme_ && this.theme_.getComponentStyle(componentName); + const style = this.theme_ && this.theme_.getComponentStyle(componentName); element.style[propertyName] = style || ''; }; @@ -167,15 +168,15 @@ Blockly.ThemeManager.prototype.subscribe = function(element, componentName, * @param {Element} element The element to unsubscribe. * @package */ -Blockly.ThemeManager.prototype.unsubscribe = function(element) { +ThemeManager.prototype.unsubscribe = function(element) { if (!element) { return; } // Go through all component, and remove any references to this element. - var componentNames = Object.keys(this.componentDB_); - for (var c = 0, componentName; (componentName = componentNames[c]); c++) { - var elements = this.componentDB_[componentName]; - for (var i = elements.length - 1; i >= 0; i--) { + const componentNames = Object.keys(this.componentDB_); + for (let c = 0, componentName; (componentName = componentNames[c]); c++) { + const elements = this.componentDB_[componentName]; + for (let i = elements.length - 1; i >= 0; i--) { if (elements[i].element === element) { elements.splice(i, 1); } @@ -192,9 +193,11 @@ Blockly.ThemeManager.prototype.unsubscribe = function(element) { * @package * @suppress {checkTypes} */ -Blockly.ThemeManager.prototype.dispose = function() { +ThemeManager.prototype.dispose = function() { this.owner_ = null; this.theme_ = null; this.subscribedWorkspaces_ = null; this.componentDB_ = null; }; + +exports = ThemeManager; diff --git a/core/toolbox/collapsible_category.js b/core/toolbox/collapsible_category.js index 979931848..ae243f1e6 100644 --- a/core/toolbox/collapsible_category.js +++ b/core/toolbox/collapsible_category.js @@ -10,34 +10,36 @@ */ 'use strict'; -goog.provide('Blockly.CollapsibleToolboxCategory'); +goog.module('Blockly.CollapsibleToolboxCategory'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.ICollapsibleToolboxItem'); -goog.require('Blockly.registry'); -goog.require('Blockly.ToolboxCategory'); -goog.require('Blockly.ToolboxItem'); -goog.require('Blockly.ToolboxSeparator'); -goog.require('Blockly.utils.aria'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.object'); -goog.require('Blockly.utils.toolbox'); - -goog.requireType('Blockly.IToolbox'); -goog.requireType('Blockly.IToolboxItem'); +/* eslint-disable-next-line no-unused-vars */ +const ICollapsibleToolboxItem = goog.require('Blockly.ICollapsibleToolboxItem'); +/* eslint-disable-next-line no-unused-vars */ +const IToolbox = goog.requireType('Blockly.IToolbox'); +/* eslint-disable-next-line no-unused-vars */ +const IToolboxItem = goog.requireType('Blockly.IToolboxItem'); +const ToolboxCategory = goog.require('Blockly.ToolboxCategory'); +const ToolboxSeparator = goog.require('Blockly.ToolboxSeparator'); +const aria = goog.require('Blockly.utils.aria'); +const dom = goog.require('Blockly.utils.dom'); +const object = goog.require('Blockly.utils.object'); +const registry = goog.require('Blockly.registry'); +const toolbox = goog.require('Blockly.utils.toolbox'); /** * Class for a category in a toolbox that can be collapsed. - * @param {!Blockly.utils.toolbox.CategoryInfo} categoryDef The information needed + * @param {!toolbox.CategoryInfo} categoryDef The information needed * to create a category in the toolbox. - * @param {!Blockly.IToolbox} toolbox The parent toolbox for the category. - * @param {Blockly.ICollapsibleToolboxItem=} opt_parent The parent category or null if + * @param {!IToolbox} toolbox The parent toolbox for the category. + * @param {ICollapsibleToolboxItem=} opt_parent The parent category or null if * the category does not have a parent. * @constructor - * @extends {Blockly.ToolboxCategory} - * @implements {Blockly.ICollapsibleToolboxItem} + * @extends {ToolboxCategory} + * @implements {ICollapsibleToolboxItem} */ -Blockly.CollapsibleToolboxCategory = function(categoryDef, toolbox, opt_parent) { +const CollapsibleToolboxCategory = function(categoryDef, toolbox, opt_parent) { /** * Container for any child categories. * @type {?Element} @@ -54,16 +56,16 @@ Blockly.CollapsibleToolboxCategory = function(categoryDef, toolbox, opt_parent) /** * The child toolbox items for this category. - * @type {!Array} + * @type {!Array} * @protected */ this.toolboxItems_ = []; - Blockly.CollapsibleToolboxCategory.superClass_.constructor.call( + CollapsibleToolboxCategory.superClass_.constructor.call( this, categoryDef, toolbox, opt_parent); }; -Blockly.utils.object.inherits(Blockly.CollapsibleToolboxCategory, Blockly.ToolboxCategory); +object.inherits(CollapsibleToolboxCategory, ToolboxCategory); /** * All the CSS class names that are used to create a collapsible @@ -80,19 +82,20 @@ Blockly.utils.object.inherits(Blockly.CollapsibleToolboxCategory, Blockly.Toolbo * contents:?string * }} */ -Blockly.CollapsibleToolboxCategory.CssConfig; +CollapsibleToolboxCategory.CssConfig; /** * Name used for registering a collapsible toolbox category. * @const {string} */ -Blockly.CollapsibleToolboxCategory.registrationName = 'collapsibleCategory'; +CollapsibleToolboxCategory.registrationName = 'collapsibleCategory'; /** * @override */ -Blockly.CollapsibleToolboxCategory.prototype.makeDefaultCssConfig_ = function() { - var cssConfig = Blockly.CollapsibleToolboxCategory.superClass_.makeDefaultCssConfig_.call(this); +CollapsibleToolboxCategory.prototype.makeDefaultCssConfig_ = function() { + const cssConfig = + CollapsibleToolboxCategory.superClass_.makeDefaultCssConfig_.call(this); cssConfig['contents'] = 'blocklyToolboxContents'; return cssConfig; }; @@ -100,20 +103,21 @@ Blockly.CollapsibleToolboxCategory.prototype.makeDefaultCssConfig_ = function() /** * @override */ -Blockly.CollapsibleToolboxCategory.prototype.parseContents_ = function(categoryDef) { - var contents = categoryDef['contents']; - var prevIsFlyoutItem = true; +CollapsibleToolboxCategory.prototype.parseContents_ = function(categoryDef) { + const contents = categoryDef['contents']; + let prevIsFlyoutItem = true; if (categoryDef['custom']) { this.flyoutItems_ = categoryDef['custom']; } else if (contents) { - for (var i = 0, itemDef; (itemDef = contents[i]); i++) { + for (let i = 0; i < contents.length; i++) { + const itemDef = contents[i]; // Separators can exist as either a flyout item or a toolbox item so // decide where it goes based on the type of the previous item. - if (!Blockly.registry.hasItem(Blockly.registry.Type.TOOLBOX_ITEM, itemDef['kind']) || - (itemDef['kind'].toLowerCase() == Blockly.ToolboxSeparator.registrationName && - prevIsFlyoutItem)) { - var flyoutItem = /** @type {Blockly.utils.toolbox.FlyoutItemInfo} */ (itemDef); + if (!registry.hasItem(registry.Type.TOOLBOX_ITEM, itemDef['kind']) || + (itemDef['kind'].toLowerCase() == ToolboxSeparator.registrationName && + prevIsFlyoutItem)) { + const flyoutItem = /** @type {toolbox.FlyoutItemInfo} */ (itemDef); this.flyoutItems_.push(flyoutItem); prevIsFlyoutItem = true; } else { @@ -126,46 +130,46 @@ Blockly.CollapsibleToolboxCategory.prototype.parseContents_ = function(categoryD /** * Creates a toolbox item and adds it to the list of toolbox items. - * @param {!Blockly.utils.toolbox.ToolboxItemInfo} itemDef The information needed + * @param {!toolbox.ToolboxItemInfo} itemDef The information needed * to create a toolbox item. * @private */ -Blockly.CollapsibleToolboxCategory.prototype.createToolboxItem_ = function(itemDef) { - var registryName = itemDef['kind']; - var categoryDef = /** @type {!Blockly.utils.toolbox.CategoryInfo} */ (itemDef); +CollapsibleToolboxCategory.prototype.createToolboxItem_ = function(itemDef) { + let registryName = itemDef['kind']; + const categoryDef = /** @type {!toolbox.CategoryInfo} */ (itemDef); // Categories that are collapsible are created using a class registered under // a diffferent name. if (registryName.toUpperCase() == 'CATEGORY' && - Blockly.utils.toolbox.isCategoryCollapsible(categoryDef)) { - registryName = Blockly.CollapsibleToolboxCategory.registrationName; + toolbox.isCategoryCollapsible(categoryDef)) { + registryName = CollapsibleToolboxCategory.registrationName; } - var ToolboxItemClass = Blockly.registry.getClass( - Blockly.registry.Type.TOOLBOX_ITEM, registryName); - var toolboxItem = new ToolboxItemClass(itemDef, this.parentToolbox_, this); + const ToolboxItemClass = + registry.getClass(registry.Type.TOOLBOX_ITEM, registryName); + const toolboxItem = new ToolboxItemClass(itemDef, this.parentToolbox_, this); this.toolboxItems_.push(toolboxItem); }; /** * @override */ -Blockly.CollapsibleToolboxCategory.prototype.init = function() { - Blockly.CollapsibleToolboxCategory.superClass_.init.call(this); +CollapsibleToolboxCategory.prototype.init = function() { + CollapsibleToolboxCategory.superClass_.init.call(this); - this.setExpanded(this.toolboxItemDef_['expanded'] == 'true' || + this.setExpanded( + this.toolboxItemDef_['expanded'] == 'true' || this.toolboxItemDef_['expanded']); }; /** * @override */ -Blockly.CollapsibleToolboxCategory.prototype.createDom_ = function() { - Blockly.CollapsibleToolboxCategory.superClass_.createDom_.call(this); +CollapsibleToolboxCategory.prototype.createDom_ = function() { + CollapsibleToolboxCategory.superClass_.createDom_.call(this); - var subCategories = this.getChildToolboxItems(); + const subCategories = this.getChildToolboxItems(); this.subcategoriesDiv_ = this.createSubCategoriesDom_(subCategories); - Blockly.utils.aria.setRole(this.subcategoriesDiv_, - Blockly.utils.aria.Role.GROUP); + aria.setRole(this.subcategoriesDiv_, aria.Role.GROUP); this.htmlDiv_.appendChild(this.subcategoriesDiv_); return this.htmlDiv_; @@ -174,10 +178,10 @@ Blockly.CollapsibleToolboxCategory.prototype.createDom_ = function() { /** * @override */ -Blockly.CollapsibleToolboxCategory.prototype.createIconDom_ = function() { - var toolboxIcon = document.createElement('span'); +CollapsibleToolboxCategory.prototype.createIconDom_ = function() { + const toolboxIcon = document.createElement('span'); if (!this.parentToolbox_.isHorizontal()) { - Blockly.utils.dom.addClass(toolboxIcon, this.cssConfig_['icon']); + dom.addClass(toolboxIcon, this.cssConfig_['icon']); toolboxIcon.style.visibility = 'visible'; } @@ -187,18 +191,19 @@ Blockly.CollapsibleToolboxCategory.prototype.createIconDom_ = function() { /** * Create the DOM for all subcategories. - * @param {!Array} subcategories The subcategories. + * @param {!Array} subcategories The subcategories. * @return {!Element} The div holding all the subcategories. * @protected */ -Blockly.CollapsibleToolboxCategory.prototype.createSubCategoriesDom_ = function(subcategories) { - var contentsContainer = document.createElement('div'); - Blockly.utils.dom.addClass(contentsContainer, this.cssConfig_['contents']); +CollapsibleToolboxCategory.prototype.createSubCategoriesDom_ = function( + subcategories) { + const contentsContainer = document.createElement('div'); + dom.addClass(contentsContainer, this.cssConfig_['contents']); - for (var i = 0; i < subcategories.length; i++) { - var newCategory = subcategories[i]; + for (let i = 0; i < subcategories.length; i++) { + const newCategory = subcategories[i]; newCategory.init(); - var newCategoryDiv = newCategory.getDiv(); + const newCategoryDiv = newCategory.getDiv(); contentsContainer.appendChild(newCategoryDiv); if (newCategory.getClickTarget) { newCategory.getClickTarget().setAttribute('id', newCategory.getId()); @@ -213,7 +218,7 @@ Blockly.CollapsibleToolboxCategory.prototype.createSubCategoriesDom_ = function( * @param {boolean} isExpanded True to expand the category, false to close. * @public */ -Blockly.CollapsibleToolboxCategory.prototype.setExpanded = function(isExpanded) { +CollapsibleToolboxCategory.prototype.setExpanded = function(isExpanded) { if (this.expanded_ == isExpanded) { return; } @@ -225,8 +230,8 @@ Blockly.CollapsibleToolboxCategory.prototype.setExpanded = function(isExpanded) this.subcategoriesDiv_.style.display = 'none'; this.closeIcon_(this.iconDom_); } - Blockly.utils.aria.setState(/** @type {!Element} */ (this.htmlDiv_), - Blockly.utils.aria.State.EXPANDED, isExpanded); + aria.setState( + /** @type {!Element} */ (this.htmlDiv_), aria.State.EXPANDED, isExpanded); this.parentToolbox_.handleToolboxItemResize(); }; @@ -234,9 +239,11 @@ Blockly.CollapsibleToolboxCategory.prototype.setExpanded = function(isExpanded) /** * @override */ -Blockly.CollapsibleToolboxCategory.prototype.setVisible_ = function(isVisible) { +CollapsibleToolboxCategory.prototype.setVisible_ = function(isVisible) { this.htmlDiv_.style.display = isVisible ? 'block' : 'none'; - for (var i = 0, child; (child = this.getChildToolboxItems()[i]); i++) { + const childToolboxItems = this.getChildToolboxItems(); + for (let i = 0; i < childToolboxItems.length; i++) { + const child = childToolboxItems[i]; child.setVisible_(isVisible); } this.isHidden_ = !isVisible; @@ -252,21 +259,21 @@ Blockly.CollapsibleToolboxCategory.prototype.setVisible_ = function(isVisible) { * is collapsed. * @public */ -Blockly.CollapsibleToolboxCategory.prototype.isExpanded = function() { +CollapsibleToolboxCategory.prototype.isExpanded = function() { return this.expanded_; }; /** * @override */ -Blockly.CollapsibleToolboxCategory.prototype.isCollapsible = function() { +CollapsibleToolboxCategory.prototype.isCollapsible = function() { return true; }; /** * @override */ -Blockly.CollapsibleToolboxCategory.prototype.onClick = function(_e) { +CollapsibleToolboxCategory.prototype.onClick = function(_e) { this.toggleExpanded(); }; @@ -274,25 +281,28 @@ Blockly.CollapsibleToolboxCategory.prototype.onClick = function(_e) { * Toggles whether or not the category is expanded. * @public */ -Blockly.CollapsibleToolboxCategory.prototype.toggleExpanded = function() { +CollapsibleToolboxCategory.prototype.toggleExpanded = function() { this.setExpanded(!this.expanded_); }; /** * @override */ -Blockly.CollapsibleToolboxCategory.prototype.getDiv = function() { +CollapsibleToolboxCategory.prototype.getDiv = function() { return this.htmlDiv_; }; /** * Gets any children toolbox items. (ex. Gets the subcategories) - * @return {!Array} The child toolbox items. + * @return {!Array} The child toolbox items. */ -Blockly.CollapsibleToolboxCategory.prototype.getChildToolboxItems = function() { +CollapsibleToolboxCategory.prototype.getChildToolboxItems = function() { return this.toolboxItems_; }; -Blockly.registry.register(Blockly.registry.Type.TOOLBOX_ITEM, - Blockly.CollapsibleToolboxCategory.registrationName, Blockly.CollapsibleToolboxCategory); +registry.register( + registry.Type.TOOLBOX_ITEM, CollapsibleToolboxCategory.registrationName, + CollapsibleToolboxCategory); + +exports = CollapsibleToolboxCategory; diff --git a/core/utils/dom.js b/core/utils/dom.js index 57843c8b9..5ec684acf 100644 --- a/core/utils/dom.js +++ b/core/utils/dom.js @@ -16,36 +16,37 @@ * @name Blockly.utils.dom * @namespace */ -goog.provide('Blockly.utils.dom'); +goog.module('Blockly.utils.dom'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.utils.Svg'); -goog.require('Blockly.utils.userAgent'); +const Svg = goog.require('Blockly.utils.Svg'); +const userAgent = goog.require('Blockly.utils.userAgent'); /** * Required name space for SVG elements. * @const */ -Blockly.utils.dom.SVG_NS = 'http://www.w3.org/2000/svg'; +const SVG_NS = 'http://www.w3.org/2000/svg'; /** * Required name space for HTML elements. * @const */ -Blockly.utils.dom.HTML_NS = 'http://www.w3.org/1999/xhtml'; +const HTML_NS = 'http://www.w3.org/1999/xhtml'; /** * Required name space for XLINK elements. * @const */ -Blockly.utils.dom.XLINK_NS = 'http://www.w3.org/1999/xlink'; +const XLINK_NS = 'http://www.w3.org/1999/xlink'; /** * Node type constants. * https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType * @enum {number} */ -Blockly.utils.dom.NodeType = { +const NodeType = { ELEMENT_NODE: 1, TEXT_NODE: 3, COMMENT_NODE: 8, @@ -57,36 +58,35 @@ Blockly.utils.dom.NodeType = { * @type {Object} * @private */ -Blockly.utils.dom.cacheWidths_ = null; +let cacheWidths = null; /** * Number of current references to cache. * @type {number} * @private */ -Blockly.utils.dom.cacheReference_ = 0; +let cacheReference = 0; /** * A HTML canvas context used for computing text width. * @type {CanvasRenderingContext2D} * @private */ -Blockly.utils.dom.canvasContext_ = null; +let canvasContext = null; /** * Helper method for creating SVG elements. - * @param {string|Blockly.utils.Svg} name Element's tag name. + * @param {string|Svg} name Element's tag name. * @param {!Object} attrs Dictionary of attribute names and values. * @param {Element=} opt_parent Optional parent on which to append the element. * @return {T} Newly created SVG element. The return type is {!SVGElement} if - * name is a string or a more specific type if it a member of - * Blockly.utils.Svg + * name is a string or a more specific type if it a member of Svg. * @template T */ -Blockly.utils.dom.createSvgElement = function(name, attrs, opt_parent) { - var e = /** @type {T} */ - (document.createElementNS(Blockly.utils.dom.SVG_NS, String(name))); - for (var key in attrs) { +const createSvgElement = function(name, attrs, opt_parent) { + const e = /** @type {T} */ + (document.createElementNS(SVG_NS, String(name))); + for (const key in attrs) { e.setAttribute(key, attrs[key]); } // IE defines a unique attribute "runtimeStyle", it is NOT applied to @@ -108,8 +108,8 @@ Blockly.utils.dom.createSvgElement = function(name, attrs, opt_parent) { * @param {string} className Name of class to add. * @return {boolean} True if class was added, false if already present. */ -Blockly.utils.dom.addClass = function(element, className) { - var classes = element.getAttribute('class') || ''; +const addClass = function(element, className) { + let classes = element.getAttribute('class') || ''; if ((' ' + classes + ' ').indexOf(' ' + className + ' ') != -1) { return false; } @@ -126,11 +126,10 @@ Blockly.utils.dom.addClass = function(element, className) { * @param {string} classNames A string of one or multiple class names for an * element. */ -Blockly.utils.dom.removeClasses = function(element, classNames) { - var classList = classNames.split(' '); - for (var i = 0; i < classList.length; i++) { - var cssName = classList[i]; - Blockly.utils.dom.removeClass(element, cssName); +const removeClasses = function(element, classNames) { + const classList = classNames.split(' '); + for (let i = 0; i < classList.length; i++) { + removeClass(element, classList[i]); } }; @@ -141,13 +140,13 @@ Blockly.utils.dom.removeClasses = function(element, classNames) { * @param {string} className Name of class to remove. * @return {boolean} True if class was removed, false if never present. */ -Blockly.utils.dom.removeClass = function(element, className) { - var classes = element.getAttribute('class'); +const removeClass = function(element, className) { + const classes = element.getAttribute('class'); if ((' ' + classes + ' ').indexOf(' ' + className + ' ') == -1) { return false; } - var classList = classes.split(/\s+/); - for (var i = 0; i < classList.length; i++) { + const classList = classes.split(/\s+/); + for (let i = 0; i < classList.length; i++) { if (!classList[i] || classList[i] == className) { classList.splice(i, 1); i--; @@ -168,8 +167,8 @@ Blockly.utils.dom.removeClass = function(element, className) { * @param {string} className Name of class to check. * @return {boolean} True if class exists, false otherwise. */ -Blockly.utils.dom.hasClass = function(element, className) { - var classes = element.getAttribute('class'); +const hasClass = function(element, className) { + const classes = element.getAttribute('class'); return (' ' + classes + ' ').indexOf(' ' + className + ' ') != -1; }; @@ -179,7 +178,7 @@ Blockly.utils.dom.hasClass = function(element, className) { * @return {?Node} The node removed if removed; else, null. */ // Copied from Closure goog.dom.removeNode -Blockly.utils.dom.removeNode = function(node) { +const removeNode = function(node) { return node && node.parentNode ? node.parentNode.removeChild(node) : null; }; @@ -189,9 +188,9 @@ Blockly.utils.dom.removeNode = function(node) { * @param {!Element} newNode New element to insert. * @param {!Element} refNode Existing element to precede new node. */ -Blockly.utils.dom.insertAfter = function(newNode, refNode) { - var siblingNode = refNode.nextSibling; - var parentNode = refNode.parentNode; +const insertAfter = function(newNode, refNode) { + const siblingNode = refNode.nextSibling; + const parentNode = refNode.parentNode; if (!parentNode) { throw Error('Reference node has no parent.'); } @@ -208,9 +207,10 @@ Blockly.utils.dom.insertAfter = function(newNode, refNode) { * @param {!Node} descendant The node to test presence of. * @return {boolean} Whether the parent node contains the descendant node. */ -Blockly.utils.dom.containsNode = function(parent, descendant) { - return !!(parent.compareDocumentPosition(descendant) & - Blockly.utils.dom.NodeType.DOCUMENT_POSITION_CONTAINED_BY); +const containsNode = function(parent, descendant) { + return !!( + parent.compareDocumentPosition(descendant) & + NodeType.DOCUMENT_POSITION_CONTAINED_BY); }; /** @@ -220,7 +220,7 @@ Blockly.utils.dom.containsNode = function(parent, descendant) { * @param {!Element} element Element to which the CSS transform will be applied. * @param {string} transform The value of the CSS `transform` property. */ -Blockly.utils.dom.setCssTransform = function(element, transform) { +const setCssTransform = function(element, transform) { element.style['transform'] = transform; element.style['-webkit-transform'] = transform; }; @@ -229,10 +229,10 @@ Blockly.utils.dom.setCssTransform = function(element, transform) { * Start caching text widths. Every call to this function MUST also call * stopTextWidthCache. Caches must not survive between execution threads. */ -Blockly.utils.dom.startTextWidthCache = function() { - Blockly.utils.dom.cacheReference_++; - if (!Blockly.utils.dom.cacheWidths_) { - Blockly.utils.dom.cacheWidths_ = Object.create(null); +const startTextWidthCache = function() { + cacheReference++; + if (!cacheWidths) { + cacheWidths = Object.create(null); } }; @@ -240,10 +240,10 @@ Blockly.utils.dom.startTextWidthCache = function() { * Stop caching field widths. Unless caching was already on when the * corresponding call to startTextWidthCache was made. */ -Blockly.utils.dom.stopTextWidthCache = function() { - Blockly.utils.dom.cacheReference_--; - if (!Blockly.utils.dom.cacheReference_) { - Blockly.utils.dom.cacheWidths_ = null; +const stopTextWidthCache = function() { + cacheReference--; + if (!cacheReference) { + cacheWidths = null; } }; @@ -252,13 +252,13 @@ Blockly.utils.dom.stopTextWidthCache = function() { * @param {!Element} textElement An SVG 'text' element. * @return {number} Width of element. */ -Blockly.utils.dom.getTextWidth = function(textElement) { - var key = textElement.textContent + '\n' + textElement.className.baseVal; - var width; +const getTextWidth = function(textElement) { + const key = textElement.textContent + '\n' + textElement.className.baseVal; + let width; // Return the cached width if it exists. - if (Blockly.utils.dom.cacheWidths_) { - width = Blockly.utils.dom.cacheWidths_[key]; + if (cacheWidths) { + width = cacheWidths[key]; if (width) { return width; } @@ -266,7 +266,7 @@ Blockly.utils.dom.getTextWidth = function(textElement) { // Attempt to compute fetch the width of the SVG text element. try { - if (Blockly.utils.userAgent.IE || Blockly.utils.userAgent.EDGE) { + if (userAgent.IE || userAgent.EDGE) { width = textElement.getBBox().width; } else { width = textElement.getComputedTextLength(); @@ -280,8 +280,8 @@ Blockly.utils.dom.getTextWidth = function(textElement) { } // Cache the computed width and return. - if (Blockly.utils.dom.cacheWidths_) { - Blockly.utils.dom.cacheWidths_[key] = width; + if (cacheWidths) { + cacheWidths[key] = width; } return width; }; @@ -296,10 +296,10 @@ Blockly.utils.dom.getTextWidth = function(textElement) { * @param {string} fontFamily The font family to use. * @return {number} Width of element. */ -Blockly.utils.dom.getFastTextWidth = function(textElement, - fontSize, fontWeight, fontFamily) { - return Blockly.utils.dom.getFastTextWidthWithSizeString(textElement, - fontSize + 'pt', fontWeight, fontFamily); +const getFastTextWidth = function( + textElement, fontSize, fontWeight, fontFamily) { + return getFastTextWidthWithSizeString( + textElement, fontSize + 'pt', fontWeight, fontFamily); }; /** @@ -314,41 +314,40 @@ Blockly.utils.dom.getFastTextWidth = function(textElement, * @param {string} fontFamily The font family to use. * @return {number} Width of element. */ -Blockly.utils.dom.getFastTextWidthWithSizeString = function(textElement, - fontSize, fontWeight, fontFamily) { - var text = textElement.textContent; - var key = text + '\n' + textElement.className.baseVal; - var width; +const getFastTextWidthWithSizeString = function( + textElement, fontSize, fontWeight, fontFamily) { + const text = textElement.textContent; + const key = text + '\n' + textElement.className.baseVal; + let width; // Return the cached width if it exists. - if (Blockly.utils.dom.cacheWidths_) { - width = Blockly.utils.dom.cacheWidths_[key]; + if (cacheWidths) { + width = cacheWidths[key]; if (width) { return width; } } - if (!Blockly.utils.dom.canvasContext_) { + if (!canvasContext) { // Inject the canvas element used for computing text widths. - var computeCanvas = document.createElement('canvas'); + const computeCanvas = document.createElement('canvas'); computeCanvas.className = 'blocklyComputeCanvas'; document.body.appendChild(computeCanvas); // Initialize the HTML canvas context and set the font. // The context font must match blocklyText's fontsize and font-family // set in CSS. - Blockly.utils.dom.canvasContext_ = computeCanvas.getContext('2d'); + canvasContext = computeCanvas.getContext('2d'); } // Set the desired font size and family. - Blockly.utils.dom.canvasContext_.font = - fontWeight + ' ' + fontSize + ' ' + fontFamily; + canvasContext.font = fontWeight + ' ' + fontSize + ' ' + fontFamily; // Measure the text width using the helper canvas context. - width = Blockly.utils.dom.canvasContext_.measureText(text).width; + width = canvasContext.measureText(text).width; // Cache the computed width and return. - if (Blockly.utils.dom.cacheWidths_) { - Blockly.utils.dom.cacheWidths_[key] = width; + if (cacheWidths) { + cacheWidths[key] = width; } return width; }; @@ -361,18 +360,16 @@ Blockly.utils.dom.getFastTextWidthWithSizeString = function(textElement, * @param {string} fontFamily The font family to use. * @return {{height: number, baseline: number}} Font measurements. */ -Blockly.utils.dom.measureFontMetrics = function(text, fontSize, fontWeight, - fontFamily) { - - var span = document.createElement('span'); +const measureFontMetrics = function(text, fontSize, fontWeight, fontFamily) { + const span = document.createElement('span'); span.style.font = fontWeight + ' ' + fontSize + ' ' + fontFamily; span.textContent = text; - var block = document.createElement('div'); + const block = document.createElement('div'); block.style.width = '1px'; block.style.height = 0; - var div = document.createElement('div'); + const div = document.createElement('div'); div.setAttribute('style', 'position: fixed; top: 0; left: 0; display: flex;'); div.appendChild(span); div.appendChild(block); @@ -389,3 +386,25 @@ Blockly.utils.dom.measureFontMetrics = function(text, fontSize, fontWeight, } return result; }; + +exports = { + SVG_NS, + HTML_NS, + XLINK_NS, + NodeType, + createSvgElement, + addClass, + removeClasses, + removeClass, + hasClass, + removeNode, + insertAfter, + containsNode, + setCssTransform, + startTextWidthCache, + stopTextWidthCache, + getTextWidth, + getFastTextWidth, + getFastTextWidthWithSizeString, + measureFontMetrics, +}; diff --git a/core/utils/size.js b/core/utils/size.js index 2ffa91ac1..56ec2eb91 100644 --- a/core/utils/size.js +++ b/core/utils/size.js @@ -13,10 +13,11 @@ 'use strict'; /** - * @name Blockly.utils.Size + * @name Size * @namespace */ -goog.provide('Blockly.utils.Size'); +goog.module('Blockly.utils.Size'); +goog.module.declareLegacyNamespace(); /** @@ -26,7 +27,7 @@ goog.provide('Blockly.utils.Size'); * @struct * @constructor */ -Blockly.utils.Size = function(width, height) { +const Size = function(width, height) { /** * Width * @type {number} @@ -42,12 +43,12 @@ Blockly.utils.Size = function(width, height) { /** * Compares sizes for equality. - * @param {?Blockly.utils.Size} a A Size. - * @param {?Blockly.utils.Size} b A Size. + * @param {?Size} a A Size. + * @param {?Size} b A Size. * @return {boolean} True iff the sizes have equal widths and equal * heights, or if both are null. */ -Blockly.utils.Size.equals = function(a, b) { +Size.equals = function(a, b) { if (a == b) { return true; } @@ -56,3 +57,5 @@ Blockly.utils.Size.equals = function(a, b) { } return a.width == b.width && a.height == b.height; }; + +exports = Size; diff --git a/core/variable_model.js b/core/variable_model.js index bc097da8a..2f5936f4e 100644 --- a/core/variable_model.js +++ b/core/variable_model.js @@ -10,20 +10,21 @@ */ 'use strict'; -goog.provide('Blockly.VariableModel'); +goog.module('Blockly.VariableModel'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Events'); +const Events = goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const Workspace = goog.requireType('Blockly.Workspace'); +const utils = goog.require('Blockly.utils'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.VarCreate'); -goog.require('Blockly.utils'); - -goog.requireType('Blockly.Workspace'); /** * Class for a variable model. * Holds information for the variable including name, ID, and type. - * @param {!Blockly.Workspace} workspace The variable's workspace. + * @param {!Workspace} workspace The variable's workspace. * @param {string} name The name of the variable. This is the user-visible name * (e.g. 'my var' or '私の変数'), not the generated name. * @param {string=} opt_type The type of the variable like 'int' or 'string'. @@ -34,10 +35,10 @@ goog.requireType('Blockly.Workspace'); * @see {Blockly.FieldVariable} * @constructor */ -Blockly.VariableModel = function(workspace, name, opt_type, opt_id) { +const VariableModel = function(workspace, name, opt_type, opt_id) { /** * The workspace the variable is in. - * @type {!Blockly.Workspace} + * @type {!Workspace} */ this.workspace = workspace; @@ -64,27 +65,28 @@ Blockly.VariableModel = function(workspace, name, opt_type, opt_id) { * @type {string} * @private */ - this.id_ = opt_id || Blockly.utils.genUid(); + this.id_ = opt_id || utils.genUid(); - Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.VAR_CREATE))( - this)); + Events.fire(new (Events.get(Events.VAR_CREATE))(this)); }; /** * @return {string} The ID for the variable. */ -Blockly.VariableModel.prototype.getId = function() { +VariableModel.prototype.getId = function() { return this.id_; }; /** * A custom compare function for the VariableModel objects. - * @param {Blockly.VariableModel} var1 First variable to compare. - * @param {Blockly.VariableModel} var2 Second variable to compare. + * @param {VariableModel} var1 First variable to compare. + * @param {VariableModel} var2 Second variable to compare. * @return {number} -1 if name of var1 is less than name of var2, 0 if equal, * and 1 if greater. * @package */ -Blockly.VariableModel.compareByName = function(var1, var2) { +VariableModel.compareByName = function(var1, var2) { return var1.name.localeCompare(var2.name, undefined, {sensitivity: 'base'}); }; + +exports = VariableModel; diff --git a/core/warning.js b/core/warning.js index 9bbd9c91b..6ed5d0c02 100644 --- a/core/warning.js +++ b/core/warning.js @@ -10,51 +10,53 @@ */ 'use strict'; -goog.provide('Blockly.Warning'); +goog.module('Blockly.Warning'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Bubble'); -goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const Block = goog.requireType('Blockly.Block'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +const Bubble = goog.require('Blockly.Bubble'); +/* eslint-disable-next-line no-unused-vars */ +const Coordinate = goog.requireType('Blockly.utils.Coordinate'); +const Events = goog.require('Blockly.Events'); +const Icon = goog.require('Blockly.Icon'); +const Svg = goog.require('Blockly.utils.Svg'); +const dom = goog.require('Blockly.utils.dom'); +const object = goog.require('Blockly.utils.object'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BubbleOpen'); -goog.require('Blockly.Icon'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.object'); -goog.require('Blockly.utils.Svg'); - -goog.requireType('Blockly.Block'); -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.utils.Coordinate'); /** * Class for a warning. - * @param {!Blockly.Block} block The block associated with this warning. - * @extends {Blockly.Icon} + * @param {!Block} block The block associated with this warning. + * @extends {Icon} * @constructor */ -Blockly.Warning = function(block) { - Blockly.Warning.superClass_.constructor.call(this, block); +const Warning = function(block) { + Warning.superClass_.constructor.call(this, block); this.createIcon(); // The text_ object can contain multiple warnings. this.text_ = Object.create(null); }; -Blockly.utils.object.inherits(Blockly.Warning, Blockly.Icon); +object.inherits(Warning, Icon); /** * Does this icon get hidden when the block is collapsed. */ -Blockly.Warning.prototype.collapseHidden = false; +Warning.prototype.collapseHidden = false; /** * Draw the warning icon. * @param {!Element} group The icon group. * @protected */ -Blockly.Warning.prototype.drawIcon_ = function(group) { +Warning.prototype.drawIcon_ = function(group) { // Triangle with rounded corners. - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.PATH, - { + dom.createSvgElement( + Svg.PATH, { 'class': 'blocklyIconShape', 'd': 'M2,15Q-1,15 0.5,12L6.5,1.7Q8,-1 9.5,1.7L15.5,12Q17,15 14,15z' }, @@ -62,19 +64,20 @@ Blockly.Warning.prototype.drawIcon_ = function(group) { // Can't use a real '!' text character since different browsers and operating // systems render it differently. // Body of exclamation point. - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.PATH, - { + dom.createSvgElement( + Svg.PATH, { 'class': 'blocklyIconSymbol', 'd': 'm7,4.8v3.16l0.27,2.27h1.46l0.27,-2.27v-3.16z' }, group); // Dot of exclamation point. - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { + dom.createSvgElement( + Svg.RECT, { 'class': 'blocklyIconSymbol', - 'x': '7', 'y': '11', 'height': '2', 'width': '2' + 'x': '7', + 'y': '11', + 'height': '2', + 'width': '2' }, group); }; @@ -83,12 +86,12 @@ Blockly.Warning.prototype.drawIcon_ = function(group) { * Show or hide the warning bubble. * @param {boolean} visible True if the bubble should be visible. */ -Blockly.Warning.prototype.setVisible = function(visible) { +Warning.prototype.setVisible = function(visible) { if (visible == this.isVisible()) { return; } - Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.BUBBLE_OPEN))( - this.block_, visible, 'warning')); + Events.fire( + new (Events.get(Events.BUBBLE_OPEN))(this.block_, visible, 'warning')); if (visible) { this.createBubble_(); } else { @@ -100,11 +103,11 @@ Blockly.Warning.prototype.setVisible = function(visible) { * Show the bubble. * @private */ -Blockly.Warning.prototype.createBubble_ = function() { - this.paragraphElement_ = Blockly.Bubble.textToDom(this.getText()); - this.bubble_ = Blockly.Bubble.createNonEditableBubble( - this.paragraphElement_, /** @type {!Blockly.BlockSvg} */ (this.block_), - /** @type {!Blockly.utils.Coordinate} */ (this.iconXY_)); +Warning.prototype.createBubble_ = function() { + this.paragraphElement_ = Bubble.textToDom(this.getText()); + this.bubble_ = Bubble.createNonEditableBubble( + this.paragraphElement_, /** @type {!BlockSvg} */ (this.block_), + /** @type {!Coordinate} */ (this.iconXY_)); this.applyColour(); }; @@ -112,7 +115,7 @@ Blockly.Warning.prototype.createBubble_ = function() { * Dispose of the bubble and references to it. * @private */ -Blockly.Warning.prototype.disposeBubble_ = function() { +Warning.prototype.disposeBubble_ = function() { this.bubble_.dispose(); this.bubble_ = null; this.paragraphElement_ = null; @@ -125,7 +128,7 @@ Blockly.Warning.prototype.disposeBubble_ = function() { * @param {string} id An ID for this text entry to be able to maintain * multiple warnings. */ -Blockly.Warning.prototype.setText = function(text, id) { +Warning.prototype.setText = function(text, id) { if (this.text_[id] == text) { return; } @@ -144,9 +147,9 @@ Blockly.Warning.prototype.setText = function(text, id) { * Get this warning's texts. * @return {string} All texts concatenated into one string. */ -Blockly.Warning.prototype.getText = function() { - var allWarnings = []; - for (var id in this.text_) { +Warning.prototype.getText = function() { + const allWarnings = []; + for (const id in this.text_) { allWarnings.push(this.text_[id]); } return allWarnings.join('\n'); @@ -155,7 +158,9 @@ Blockly.Warning.prototype.getText = function() { /** * Dispose of this warning. */ -Blockly.Warning.prototype.dispose = function() { +Warning.prototype.dispose = function() { this.block_.warning = null; - Blockly.Icon.prototype.dispose.call(this); + Icon.prototype.dispose.call(this); }; + +exports = Warning; diff --git a/core/workspace_audio.js b/core/workspace_audio.js index 378c19287..ba1da0c95 100644 --- a/core/workspace_audio.js +++ b/core/workspace_audio.js @@ -11,28 +11,27 @@ */ 'use strict'; -goog.provide('Blockly.WorkspaceAudio'); +goog.module('Blockly.WorkspaceAudio'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.internalConstants'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.global'); -goog.require('Blockly.utils.userAgent'); - -goog.requireType('Blockly.WorkspaceSvg'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +const global = goog.require('Blockly.utils.global'); +const internalConstants = goog.require('Blockly.internalConstants'); +const userAgent = goog.require('Blockly.utils.userAgent'); /** * Class for loading, storing, and playing audio for a workspace. - * @param {Blockly.WorkspaceSvg} parentWorkspace The parent of the workspace + * @param {WorkspaceSvg} parentWorkspace The parent of the workspace * this audio object belongs to, or null. * @constructor */ -Blockly.WorkspaceAudio = function(parentWorkspace) { - +const WorkspaceAudio = function(parentWorkspace) { /** * The parent of the workspace this object belongs to, or null. May be * checked for sounds that this object can't find. - * @type {Blockly.WorkspaceSvg} + * @type {WorkspaceSvg} * @private */ this.parentWorkspace_ = parentWorkspace; @@ -49,13 +48,13 @@ Blockly.WorkspaceAudio = function(parentWorkspace) { * @type {Date} * @private */ -Blockly.WorkspaceAudio.prototype.lastSound_ = null; +WorkspaceAudio.prototype.lastSound_ = null; /** * Dispose of this audio manager. * @package */ -Blockly.WorkspaceAudio.prototype.dispose = function() { +WorkspaceAudio.prototype.dispose = function() { this.parentWorkspace_ = null; this.SOUNDS_ = null; }; @@ -67,24 +66,25 @@ Blockly.WorkspaceAudio.prototype.dispose = function() { * Filenames include path from Blockly's root. File extensions matter. * @param {string} name Name of sound. */ -Blockly.WorkspaceAudio.prototype.load = function(filenames, name) { +WorkspaceAudio.prototype.load = function(filenames, name) { if (!filenames.length) { return; } + let audioTest; try { - var audioTest = new Blockly.utils.global['Audio'](); + audioTest = new global['Audio'](); } catch (e) { // No browser support for Audio. // IE can throw an error even if the Audio object exists. return; } - var sound; - for (var i = 0; i < filenames.length; i++) { - var filename = filenames[i]; - var ext = filename.match(/\.(\w+)$/); + let sound; + for (let i = 0; i < filenames.length; i++) { + const filename = filenames[i]; + const ext = filename.match(/\.(\w+)$/); if (ext && audioTest.canPlayType('audio/' + ext[1])) { // Found an audio format we can play. - sound = new Blockly.utils.global['Audio'](filename); + sound = new global['Audio'](filename); break; } } @@ -97,16 +97,17 @@ Blockly.WorkspaceAudio.prototype.load = function(filenames, name) { * Preload all the audio files so that they play quickly when asked for. * @package */ -Blockly.WorkspaceAudio.prototype.preload = function() { - for (var name in this.SOUNDS_) { - var sound = this.SOUNDS_[name]; +WorkspaceAudio.prototype.preload = function() { + for (const name in this.SOUNDS_) { + const sound = this.SOUNDS_[name]; sound.volume = 0.01; - var playPromise = sound.play(); + const playPromise = sound.play(); // Edge does not return a promise, so we need to check. if (playPromise !== undefined) { - // If we don't wait for the play request to complete before calling pause() - // we will get an exception: (DOMException: The play() request was interrupted) - // See more: https://developers.google.com/web/updates/2017/06/play-request-was-interrupted + // If we don't wait for the play request to complete before calling + // pause() we will get an exception: (DOMException: The play() request was + // interrupted) See more: + // https://developers.google.com/web/updates/2017/06/play-request-was-interrupted playPromise.then(sound.pause).catch(function() { // Play without user interaction was prevented. }); @@ -116,7 +117,7 @@ Blockly.WorkspaceAudio.prototype.preload = function() { // iOS can only process one sound at a time. Trying to load more than one // corrupts the earlier ones. Just load one and leave the others uncached. - if (Blockly.utils.userAgent.IPAD || Blockly.utils.userAgent.IPHONE) { + if (userAgent.IPAD || userAgent.IPHONE) { break; } } @@ -128,18 +129,18 @@ Blockly.WorkspaceAudio.prototype.preload = function() { * @param {string} name Name of sound. * @param {number=} opt_volume Volume of sound (0-1). */ -Blockly.WorkspaceAudio.prototype.play = function(name, opt_volume) { - var sound = this.SOUNDS_[name]; +WorkspaceAudio.prototype.play = function(name, opt_volume) { + const sound = this.SOUNDS_[name]; if (sound) { // Don't play one sound on top of another. - var now = new Date; + const now = new Date; if (this.lastSound_ != null && - now - this.lastSound_ < Blockly.internalConstants.SOUND_LIMIT) { + now - this.lastSound_ < internalConstants.SOUND_LIMIT) { return; } this.lastSound_ = now; - var mySound; - if (Blockly.utils.userAgent.IPAD || Blockly.utils.userAgent.ANDROID) { + let mySound; + if (userAgent.IPAD || userAgent.ANDROID) { // Creating a new audio node causes lag in Android and iPad. Android // refetches the file from the server, iPad uses a singleton audio // node which must be deleted and recreated for each new audio tag. @@ -154,3 +155,5 @@ Blockly.WorkspaceAudio.prototype.play = function(name, opt_volume) { this.parentWorkspace_.getAudioManager().play(name, opt_volume); } }; + +exports = WorkspaceAudio; diff --git a/core/workspace_comment.js b/core/workspace_comment.js index 5399dbe39..8d9009f94 100644 --- a/core/workspace_comment.js +++ b/core/workspace_comment.js @@ -10,9 +10,15 @@ */ 'use strict'; -goog.provide('Blockly.WorkspaceComment'); +goog.module('Blockly.WorkspaceComment'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Events'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +const Events = goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const Workspace = goog.requireType('Blockly.Workspace'); +const utils = goog.require('Blockly.utils'); +const xml = goog.require('Blockly.utils.xml'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.CommentChange'); /** @suppress {extraRequire} */ @@ -21,14 +27,11 @@ goog.require('Blockly.Events.CommentCreate'); goog.require('Blockly.Events.CommentDelete'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.CommentMove'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.xml'); /** * Class for a workspace comment. - * @param {!Blockly.Workspace} workspace The block's workspace. + * @param {!Workspace} workspace The block's workspace. * @param {string} content The content of this workspace comment. * @param {number} height Height of the comment. * @param {number} width Width of the comment. @@ -36,20 +39,20 @@ goog.require('Blockly.utils.xml'); * create a new ID. * @constructor */ -Blockly.WorkspaceComment = function(workspace, content, height, width, opt_id) { +const WorkspaceComment = function(workspace, content, height, width, opt_id) { /** @type {string} */ - this.id = (opt_id && !workspace.getCommentById(opt_id)) ? - opt_id : Blockly.utils.genUid(); + this.id = + (opt_id && !workspace.getCommentById(opt_id)) ? opt_id : utils.genUid(); workspace.addTopComment(this); /** * The comment's position in workspace units. (0, 0) is at the workspace's * origin; scale does not change this value. - * @type {!Blockly.utils.Coordinate} + * @type {!Coordinate} * @protected */ - this.xy_ = new Blockly.utils.Coordinate(0, 0); + this.xy_ = new Coordinate(0, 0); /** * The comment's height in workspace units. Scale does not change this value. @@ -66,7 +69,7 @@ Blockly.WorkspaceComment = function(workspace, content, height, width, opt_id) { this.width_ = width; /** - * @type {!Blockly.Workspace} + * @type {!Workspace} */ this.workspace = workspace; @@ -106,22 +109,21 @@ Blockly.WorkspaceComment = function(workspace, content, height, width, opt_id) { */ this.isComment = true; - Blockly.WorkspaceComment.fireCreateEvent(this); + WorkspaceComment.fireCreateEvent(this); }; /** * Dispose of this comment. * @package */ -Blockly.WorkspaceComment.prototype.dispose = function() { +WorkspaceComment.prototype.dispose = function() { if (!this.workspace) { // The comment has already been deleted. return; } - if (Blockly.Events.isEnabled()) { - Blockly.Events.fire( - new (Blockly.Events.get(Blockly.Events.COMMENT_DELETE))(this)); + if (Events.isEnabled()) { + Events.fire(new (Events.get(Events.COMMENT_DELETE))(this)); } // Remove from the list of top comments and the comment database. @@ -137,7 +139,7 @@ Blockly.WorkspaceComment.prototype.dispose = function() { * @return {number} Comment height. * @package */ -Blockly.WorkspaceComment.prototype.getHeight = function() { +WorkspaceComment.prototype.getHeight = function() { return this.height_; }; @@ -146,7 +148,7 @@ Blockly.WorkspaceComment.prototype.getHeight = function() { * @param {number} height Comment height. * @package */ -Blockly.WorkspaceComment.prototype.setHeight = function(height) { +WorkspaceComment.prototype.setHeight = function(height) { this.height_ = height; }; @@ -155,7 +157,7 @@ Blockly.WorkspaceComment.prototype.setHeight = function(height) { * @return {number} Comment width. * @package */ -Blockly.WorkspaceComment.prototype.getWidth = function() { +WorkspaceComment.prototype.getWidth = function() { return this.width_; }; @@ -164,18 +166,18 @@ Blockly.WorkspaceComment.prototype.getWidth = function() { * @param {number} width comment width. * @package */ -Blockly.WorkspaceComment.prototype.setWidth = function(width) { +WorkspaceComment.prototype.setWidth = function(width) { this.width_ = width; }; /** * Get stored location. - * @return {!Blockly.utils.Coordinate} The comment's stored location. + * @return {!Coordinate} The comment's stored location. * This is not valid if the comment is currently being dragged. * @package */ -Blockly.WorkspaceComment.prototype.getXY = function() { - return new Blockly.utils.Coordinate(this.xy_.x, this.xy_.y); +WorkspaceComment.prototype.getXY = function() { + return new Coordinate(this.xy_.x, this.xy_.y); }; /** @@ -184,11 +186,11 @@ Blockly.WorkspaceComment.prototype.getXY = function() { * @param {number} dy Vertical offset, in workspace units. * @package */ -Blockly.WorkspaceComment.prototype.moveBy = function(dx, dy) { - var event = new (Blockly.Events.get(Blockly.Events.COMMENT_MOVE))(this); +WorkspaceComment.prototype.moveBy = function(dx, dy) { + const event = new (Events.get(Events.COMMENT_MOVE))(this); this.xy_.translate(dx, dy); event.recordNew(); - Blockly.Events.fire(event); + Events.fire(event); }; /** @@ -196,7 +198,7 @@ Blockly.WorkspaceComment.prototype.moveBy = function(dx, dy) { * @return {boolean} True if deletable. * @package */ -Blockly.WorkspaceComment.prototype.isDeletable = function() { +WorkspaceComment.prototype.isDeletable = function() { return this.deletable_ && !(this.workspace && this.workspace.options.readOnly); }; @@ -206,7 +208,7 @@ Blockly.WorkspaceComment.prototype.isDeletable = function() { * @param {boolean} deletable True if deletable. * @package */ -Blockly.WorkspaceComment.prototype.setDeletable = function(deletable) { +WorkspaceComment.prototype.setDeletable = function(deletable) { this.deletable_ = deletable; }; @@ -215,9 +217,8 @@ Blockly.WorkspaceComment.prototype.setDeletable = function(deletable) { * @return {boolean} True if movable. * @package */ -Blockly.WorkspaceComment.prototype.isMovable = function() { - return this.movable_ && - !(this.workspace && this.workspace.options.readOnly); +WorkspaceComment.prototype.isMovable = function() { + return this.movable_ && !(this.workspace && this.workspace.options.readOnly); }; /** @@ -225,7 +226,7 @@ Blockly.WorkspaceComment.prototype.isMovable = function() { * @param {boolean} movable True if movable. * @package */ -Blockly.WorkspaceComment.prototype.setMovable = function(movable) { +WorkspaceComment.prototype.setMovable = function(movable) { this.movable_ = movable; }; @@ -233,16 +234,15 @@ Blockly.WorkspaceComment.prototype.setMovable = function(movable) { * Get whether this comment is editable or not. * @return {boolean} True if editable. */ -Blockly.WorkspaceComment.prototype.isEditable = function() { - return this.editable_ && - !(this.workspace && this.workspace.options.readOnly); +WorkspaceComment.prototype.isEditable = function() { + return this.editable_ && !(this.workspace && this.workspace.options.readOnly); }; /** * Set whether this comment is editable or not. * @param {boolean} editable True if editable. */ -Blockly.WorkspaceComment.prototype.setEditable = function(editable) { +WorkspaceComment.prototype.setEditable = function(editable) { this.editable_ = editable; }; @@ -251,7 +251,7 @@ Blockly.WorkspaceComment.prototype.setEditable = function(editable) { * @return {string} Comment text. * @package */ -Blockly.WorkspaceComment.prototype.getContent = function() { +WorkspaceComment.prototype.getContent = function() { return this.content_; }; @@ -260,10 +260,10 @@ Blockly.WorkspaceComment.prototype.getContent = function() { * @param {string} content Comment content. * @package */ -Blockly.WorkspaceComment.prototype.setContent = function(content) { +WorkspaceComment.prototype.setContent = function(content) { if (this.content_ != content) { - Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.COMMENT_CHANGE))( - this, this.content_, content)); + Events.fire( + new (Events.get(Events.COMMENT_CHANGE))(this, this.content_, content)); this.content_ = content; } }; @@ -274,8 +274,8 @@ Blockly.WorkspaceComment.prototype.setContent = function(content) { * @return {!Element} Tree of XML elements. * @package */ -Blockly.WorkspaceComment.prototype.toXmlWithXY = function(opt_noId) { - var element = this.toXml(opt_noId); +WorkspaceComment.prototype.toXmlWithXY = function(opt_noId) { + const element = this.toXml(opt_noId); element.setAttribute('x', Math.round(this.xy_.x)); element.setAttribute('y', Math.round(this.xy_.y)); element.setAttribute('h', this.height_); @@ -291,8 +291,8 @@ Blockly.WorkspaceComment.prototype.toXmlWithXY = function(opt_noId) { * @return {!Element} Tree of XML elements. * @package */ -Blockly.WorkspaceComment.prototype.toXml = function(opt_noId) { - var commentElement = Blockly.utils.xml.createElement('comment'); +WorkspaceComment.prototype.toXml = function(opt_noId) { + const commentElement = xml.createElement('comment'); if (!opt_noId) { commentElement.id = this.id; } @@ -302,21 +302,20 @@ Blockly.WorkspaceComment.prototype.toXml = function(opt_noId) { /** * Fire a create event for the given workspace comment, if comments are enabled. - * @param {!Blockly.WorkspaceComment} comment The comment that was just created. + * @param {!WorkspaceComment} comment The comment that was just created. * @package */ -Blockly.WorkspaceComment.fireCreateEvent = function(comment) { - if (Blockly.Events.isEnabled()) { - var existingGroup = Blockly.Events.getGroup(); +WorkspaceComment.fireCreateEvent = function(comment) { + if (Events.isEnabled()) { + const existingGroup = Events.getGroup(); if (!existingGroup) { - Blockly.Events.setGroup(true); + Events.setGroup(true); } try { - Blockly.Events.fire( - new (Blockly.Events.get(Blockly.Events.COMMENT_CREATE))(comment)); + Events.fire(new (Events.get(Events.COMMENT_CREATE))(comment)); } finally { if (!existingGroup) { - Blockly.Events.setGroup(false); + Events.setGroup(false); } } } @@ -325,23 +324,23 @@ Blockly.WorkspaceComment.fireCreateEvent = function(comment) { /** * Decode an XML comment tag and create a comment on the workspace. * @param {!Element} xmlComment XML comment element. - * @param {!Blockly.Workspace} workspace The workspace. - * @return {!Blockly.WorkspaceComment} The created workspace comment. + * @param {!Workspace} workspace The workspace. + * @return {!WorkspaceComment} The created workspace comment. * @package */ -Blockly.WorkspaceComment.fromXml = function(xmlComment, workspace) { - var info = Blockly.WorkspaceComment.parseAttributes(xmlComment); +WorkspaceComment.fromXml = function(xmlComment, workspace) { + const info = WorkspaceComment.parseAttributes(xmlComment); - var comment = new Blockly.WorkspaceComment( - workspace, info.content, info.h, info.w, info.id); + const comment = + new WorkspaceComment(workspace, info.content, info.h, info.w, info.id); - var commentX = parseInt(xmlComment.getAttribute('x'), 10); - var commentY = parseInt(xmlComment.getAttribute('y'), 10); + const commentX = parseInt(xmlComment.getAttribute('x'), 10); + const commentY = parseInt(xmlComment.getAttribute('y'), 10); if (!isNaN(commentX) && !isNaN(commentY)) { comment.moveBy(commentX, commentY); } - Blockly.WorkspaceComment.fireCreateEvent(comment); + WorkspaceComment.fireCreateEvent(comment); return comment; }; @@ -352,9 +351,9 @@ Blockly.WorkspaceComment.fromXml = function(xmlComment, workspace) { * object containing the id, size, position, and comment string. * @package */ -Blockly.WorkspaceComment.parseAttributes = function(xml) { - var xmlH = xml.getAttribute('h'); - var xmlW = xml.getAttribute('w'); +WorkspaceComment.parseAttributes = function(xml) { + const xmlH = xml.getAttribute('h'); + const xmlW = xml.getAttribute('w'); return { // @type {string} @@ -377,3 +376,5 @@ Blockly.WorkspaceComment.parseAttributes = function(xml) { content: xml.textContent }; }; + +exports = WorkspaceComment; diff --git a/core/workspace_comment_render_svg.js b/core/workspace_comment_render_svg.js deleted file mode 100644 index 5097f0c92..000000000 --- a/core/workspace_comment_render_svg.js +++ /dev/null @@ -1,463 +0,0 @@ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview Methods for rendering a workspace comment as SVG - * @author fenichel@google.com (Rachel Fenichel) - */ -'use strict'; - -goog.provide('Blockly.WorkspaceCommentSvg.render'); - -goog.require('Blockly.utils'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.Svg'); - - -/** - * Size of the resize icon. - * @type {number} - * @const - * @private - */ -Blockly.WorkspaceCommentSvg.RESIZE_SIZE = 8; - -/** - * Radius of the border around the comment. - * @type {number} - * @const - * @private - */ -Blockly.WorkspaceCommentSvg.BORDER_RADIUS = 3; - -/** - * Offset from the foreignobject edge to the textarea edge. - * @type {number} - * @const - * @private - */ -Blockly.WorkspaceCommentSvg.TEXTAREA_OFFSET = 2; - -/** - * Offset from the top to make room for a top bar. - * @type {number} - * @const - * @private - */ -Blockly.WorkspaceCommentSvg.TOP_OFFSET = 10; - -/** - * Returns a bounding box describing the dimensions of this comment. - * @return {!{height: number, width: number}} Object with height and width - * properties in workspace units. - * @package - */ -Blockly.WorkspaceCommentSvg.prototype.getHeightWidth = function() { - return { width: this.getWidth(), height: this.getHeight() }; -}; - -/** - * Renders the workspace comment. - * @package - */ -Blockly.WorkspaceCommentSvg.prototype.render = function() { - if (this.rendered_) { - return; - } - - var size = this.getHeightWidth(); - - // Add text area - this.createEditor_(); - this.svgGroup_.appendChild(this.foreignObject_); - - this.svgHandleTarget_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { - 'class': 'blocklyCommentHandleTarget', - 'x': 0, - 'y': 0 - }); - this.svgGroup_.appendChild(this.svgHandleTarget_); - this.svgRectTarget_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { - 'class': 'blocklyCommentTarget', - 'x': 0, - 'y': 0, - 'rx': Blockly.WorkspaceCommentSvg.BORDER_RADIUS, - 'ry': Blockly.WorkspaceCommentSvg.BORDER_RADIUS - }); - this.svgGroup_.appendChild(this.svgRectTarget_); - - // Add the resize icon - this.addResizeDom_(); - if (this.isDeletable()) { - // Add the delete icon - this.addDeleteDom_(); - } - - this.setSize_(size.width, size.height); - - // Set the content - this.textarea_.value = this.content_; - - this.rendered_ = true; - - if (this.resizeGroup_) { - Blockly.browserEvents.conditionalBind( - this.resizeGroup_, 'mousedown', this, this.resizeMouseDown_); - } - - if (this.isDeletable()) { - Blockly.browserEvents.conditionalBind( - this.deleteGroup_, 'mousedown', this, this.deleteMouseDown_); - Blockly.browserEvents.conditionalBind( - this.deleteGroup_, 'mouseout', this, this.deleteMouseOut_); - Blockly.browserEvents.conditionalBind( - this.deleteGroup_, 'mouseup', this, this.deleteMouseUp_); - } -}; - -/** - * Create the text area for the comment. - * @return {!Element} The top-level node of the editor. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.createEditor_ = function() { - /* Create the editor. Here's the markup that will be generated: - - - - - - */ - this.foreignObject_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FOREIGNOBJECT, - { - 'x': 0, - 'y': Blockly.WorkspaceCommentSvg.TOP_OFFSET, - 'class': 'blocklyCommentForeignObject' - }, - null); - var body = document.createElementNS(Blockly.utils.dom.HTML_NS, 'body'); - body.setAttribute('xmlns', Blockly.utils.dom.HTML_NS); - body.className = 'blocklyMinimalBody'; - var textarea = document.createElementNS(Blockly.utils.dom.HTML_NS, 'textarea'); - textarea.className = 'blocklyCommentTextarea'; - textarea.setAttribute('dir', this.RTL ? 'RTL' : 'LTR'); - textarea.readOnly = !this.isEditable(); - body.appendChild(textarea); - this.textarea_ = textarea; - this.foreignObject_.appendChild(body); - // Don't zoom with mousewheel. - Blockly.browserEvents.conditionalBind(textarea, 'wheel', this, function(e) { - e.stopPropagation(); - }); - Blockly.browserEvents.conditionalBind( - textarea, 'change', this, - function( - /* eslint-disable no-unused-vars */ e - /* eslint-enable no-unused-vars */) { - this.setContent(textarea.value); - }); - return this.foreignObject_; -}; - -/** - * Add the resize icon to the DOM - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.addResizeDom_ = function() { - this.resizeGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, - { - 'class': this.RTL ? 'blocklyResizeSW' : 'blocklyResizeSE' - }, - this.svgGroup_); - var resizeSize = Blockly.WorkspaceCommentSvg.RESIZE_SIZE; - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.POLYGON, - {'points': '0,x x,x x,0'.replace(/x/g, resizeSize.toString())}, - this.resizeGroup_); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.LINE, - { - 'class': 'blocklyResizeLine', - 'x1': resizeSize / 3, 'y1': resizeSize - 1, - 'x2': resizeSize - 1, 'y2': resizeSize / 3 - }, this.resizeGroup_); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.LINE, - { - 'class': 'blocklyResizeLine', - 'x1': resizeSize * 2 / 3, 'y1': resizeSize - 1, - 'x2': resizeSize - 1, 'y2': resizeSize * 2 / 3 - }, this.resizeGroup_); -}; - -/** - * Add the delete icon to the DOM - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.addDeleteDom_ = function() { - this.deleteGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, - { - 'class': 'blocklyCommentDeleteIcon' - }, - this.svgGroup_); - this.deleteIconBorder_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.CIRCLE, - { - 'class': 'blocklyDeleteIconShape', - 'r': '7', - 'cx': '7.5', - 'cy': '7.5' - }, - this.deleteGroup_); - // x icon. - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.LINE, - { - 'x1': '5', 'y1': '10', - 'x2': '10', 'y2': '5', - 'stroke': '#fff', - 'stroke-width': '2' - }, - this.deleteGroup_); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.LINE, - { - 'x1': '5', 'y1': '5', - 'x2': '10', 'y2': '10', - 'stroke': '#fff', - 'stroke-width': '2' - }, - this.deleteGroup_); -}; - -/** - * Handle a mouse-down on comment's resize corner. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.resizeMouseDown_ = function(e) { - this.unbindDragEvents_(); - if (Blockly.utils.isRightButton(e)) { - // No right-click. - e.stopPropagation(); - return; - } - // Left-click (or middle click) - this.workspace.startDrag(e, new Blockly.utils.Coordinate( - this.workspace.RTL ? -this.width_ : this.width_, this.height_)); - - this.onMouseUpWrapper_ = Blockly.browserEvents.conditionalBind( - document, 'mouseup', this, this.resizeMouseUp_); - this.onMouseMoveWrapper_ = Blockly.browserEvents.conditionalBind( - document, 'mousemove', this, this.resizeMouseMove_); - Blockly.hideChaff(); - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); -}; - -/** - * Handle a mouse-down on comment's delete icon. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.deleteMouseDown_ = function(e) { - // Highlight the delete icon. - Blockly.utils.dom.addClass( - /** @type {!Element} */ (this.deleteIconBorder_), - 'blocklyDeleteIconHighlighted'); - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); -}; - -/** - * Handle a mouse-out on comment's delete icon. - * @param {!Event} _e Mouse out event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.deleteMouseOut_ = function(_e) { - // Restore highlight on the delete icon. - Blockly.utils.dom.removeClass( - /** @type {!Element} */ (this.deleteIconBorder_), - 'blocklyDeleteIconHighlighted'); -}; - -/** - * Handle a mouse-up on comment's delete icon. - * @param {!Event} e Mouse up event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.deleteMouseUp_ = function(e) { - // Delete this comment. - this.dispose(true, true); - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); -}; - -/** - * Stop binding to the global mouseup and mousemove events. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.unbindDragEvents_ = function() { - if (this.onMouseUpWrapper_) { - Blockly.browserEvents.unbind(this.onMouseUpWrapper_); - this.onMouseUpWrapper_ = null; - } - if (this.onMouseMoveWrapper_) { - Blockly.browserEvents.unbind(this.onMouseMoveWrapper_); - this.onMouseMoveWrapper_ = null; - } -}; - -/** - * Handle a mouse-up event while dragging a comment's border or resize handle. - * @param {!Event} e Mouse up event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.resizeMouseUp_ = function(/* e */) { - Blockly.Touch.clearTouchIdentifier(); - this.unbindDragEvents_(); -}; - -/** - * Resize this comment to follow the mouse. - * @param {!Event} e Mouse move event. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.resizeMouseMove_ = function(e) { - this.autoLayout_ = false; - var newXY = this.workspace.moveDrag(e); - this.setSize_(this.RTL ? -newXY.x : newXY.x, newXY.y); -}; - -/** - * Callback function triggered when the comment has resized. - * Resize the text area accordingly. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.resizeComment_ = function() { - var size = this.getHeightWidth(); - var topOffset = Blockly.WorkspaceCommentSvg.TOP_OFFSET; - var textOffset = Blockly.WorkspaceCommentSvg.TEXTAREA_OFFSET * 2; - - this.foreignObject_.setAttribute('width', size.width); - this.foreignObject_.setAttribute('height', size.height - topOffset); - if (this.RTL) { - this.foreignObject_.setAttribute('x', -size.width); - } - this.textarea_.style.width = (size.width - textOffset) + 'px'; - this.textarea_.style.height = (size.height - textOffset - topOffset) + 'px'; -}; - -/** - * Set size - * @param {number} width width of the container - * @param {number} height height of the container - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.setSize_ = function(width, height) { - // Minimum size of a comment. - width = Math.max(width, 45); - height = Math.max(height, 20 + Blockly.WorkspaceCommentSvg.TOP_OFFSET); - this.width_ = width; - this.height_ = height; - this.svgRect_.setAttribute('width', width); - this.svgRect_.setAttribute('height', height); - this.svgRectTarget_.setAttribute('width', width); - this.svgRectTarget_.setAttribute('height', height); - this.svgHandleTarget_.setAttribute('width', width); - this.svgHandleTarget_.setAttribute('height', - Blockly.WorkspaceCommentSvg.TOP_OFFSET); - if (this.RTL) { - this.svgRect_.setAttribute('transform', 'scale(-1 1)'); - this.svgRectTarget_.setAttribute('transform', 'scale(-1 1)'); - } - - var resizeSize = Blockly.WorkspaceCommentSvg.RESIZE_SIZE; - if (this.resizeGroup_) { - if (this.RTL) { - // Mirror the resize group. - this.resizeGroup_.setAttribute('transform', 'translate(' + - (-width + resizeSize) + ',' + (height - resizeSize) + ') scale(-1 1)'); - this.deleteGroup_.setAttribute('transform', 'translate(' + - (-width + resizeSize) + ',' + (-resizeSize) + ') scale(-1 1)'); - } else { - this.resizeGroup_.setAttribute('transform', 'translate(' + - (width - resizeSize) + ',' + - (height - resizeSize) + ')'); - this.deleteGroup_.setAttribute('transform', 'translate(' + - (width - resizeSize) + ',' + - (-resizeSize) + ')'); - } - } - - // Allow the contents to resize. - this.resizeComment_(); -}; - -/** - * Dispose of any rendered comment components. - * @private - */ -Blockly.WorkspaceCommentSvg.prototype.disposeInternal_ = function() { - this.textarea_ = null; - this.foreignObject_ = null; - this.svgRectTarget_ = null; - this.svgHandleTarget_ = null; - this.disposed_ = true; -}; - -/** - * Set the focus on the text area. - * @package - */ -Blockly.WorkspaceCommentSvg.prototype.setFocus = function() { - var comment = this; - this.focused_ = true; - // Defer CSS changes. - setTimeout(function() { - if (comment.disposed_) { - return; - } - comment.textarea_.focus(); - comment.addFocus(); - Blockly.utils.dom.addClass( - comment.svgRectTarget_, 'blocklyCommentTargetFocused'); - Blockly.utils.dom.addClass( - comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused'); - }, 0); -}; - -/** - * Remove focus from the text area. - * @package - */ -Blockly.WorkspaceCommentSvg.prototype.blurFocus = function() { - var comment = this; - this.focused_ = false; - // Defer CSS changes. - setTimeout(function() { - if (comment.disposed_) { - return; - } - - comment.textarea_.blur(); - comment.removeFocus(); - Blockly.utils.dom.removeClass( - comment.svgRectTarget_, 'blocklyCommentTargetFocused'); - Blockly.utils.dom.removeClass( - comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused'); - }, 0); -}; diff --git a/core/workspace_comment_svg.js b/core/workspace_comment_svg.js index 401b840e1..77e8c713d 100644 --- a/core/workspace_comment_svg.js +++ b/core/workspace_comment_svg.js @@ -10,10 +10,32 @@ */ 'use strict'; -goog.provide('Blockly.WorkspaceCommentSvg'); +goog.module('Blockly.WorkspaceCommentSvg'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Css'); -goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const BlockDragSurfaceSvg = goog.requireType('Blockly.BlockDragSurfaceSvg'); +const Blockly = goog.require('Blockly'); +const ContextMenu = goog.require('Blockly.ContextMenu'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +const Css = goog.require('Blockly.Css'); +const Events = goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const IBoundedElement = goog.require('Blockly.IBoundedElement'); +/* eslint-disable-next-line no-unused-vars */ +const IBubble = goog.require('Blockly.IBubble'); +/* eslint-disable-next-line no-unused-vars */ +const ICopyable = goog.require('Blockly.ICopyable'); +const Rect = goog.require('Blockly.utils.Rect'); +const Svg = goog.require('Blockly.utils.Svg'); +const Touch = goog.require('Blockly.Touch'); +/* eslint-disable-next-line no-unused-vars */ +const Workspace = goog.requireType('Blockly.Workspace'); +const WorkspaceComment = goog.require('Blockly.WorkspaceComment'); +const browserEvents = goog.require('Blockly.browserEvents'); +const dom = goog.require('Blockly.utils.dom'); +const object = goog.require('Blockly.utils.object'); +const utils = goog.require('Blockly.utils'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.CommentCreate'); /** @suppress {extraRequire} */ @@ -22,45 +44,55 @@ goog.require('Blockly.Events.CommentDelete'); goog.require('Blockly.Events.CommentMove'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.Selected'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.object'); -goog.require('Blockly.utils.Rect'); -goog.require('Blockly.utils.Svg'); -goog.require('Blockly.WorkspaceComment'); - -goog.requireType('Blockly.IBoundedElement'); -goog.requireType('Blockly.IBubble'); -goog.requireType('Blockly.ICopyable'); +/** + * Size of the resize icon. + * @type {number} + * @const + */ +const RESIZE_SIZE = 8; + +/** + * Radius of the border around the comment. + * @type {number} + * @const + */ +const BORDER_RADIUS = 3; + +/** + * Offset from the foreignobject edge to the textarea edge. + * @type {number} + * @const + */ +const TEXTAREA_OFFSET = 2; + /** * Class for a workspace comment's SVG representation. - * @param {!Blockly.Workspace} workspace The block's workspace. + * @param {!Workspace} workspace The block's workspace. * @param {string} content The content of this workspace comment. * @param {number} height Height of the comment. * @param {number} width Width of the comment. * @param {string=} opt_id Optional ID. Use this ID if provided, otherwise * create a new ID. - * @extends {Blockly.WorkspaceComment} - * @implements {Blockly.IBoundedElement} - * @implements {Blockly.IBubble} - * @implements {Blockly.ICopyable} + * @extends {WorkspaceComment} + * @implements {IBoundedElement} + * @implements {IBubble} + * @implements {ICopyable} * @constructor */ -Blockly.WorkspaceCommentSvg = function( +const WorkspaceCommentSvg = function( workspace, content, height, width, opt_id) { /** * Mouse up event data. - * @type {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @private */ this.onMouseUpWrapper_ = null; /** * Mouse move event data. - * @type {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @private */ this.onMouseMoveWrapper_ = null; @@ -70,18 +102,17 @@ Blockly.WorkspaceCommentSvg = function( * @type {!SVGElement} * @private */ - this.svgGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, {'class': 'blocklyComment'}, null); + this.svgGroup_ = + dom.createSvgElement(Svg.G, {'class': 'blocklyComment'}, null); this.svgGroup_.translate_ = ''; - this.svgRect_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, { - 'class': 'blocklyCommentRect', - 'x': 0, - 'y': 0, - 'rx': Blockly.WorkspaceCommentSvg.BORDER_RADIUS, - 'ry': Blockly.WorkspaceCommentSvg.BORDER_RADIUS - }); + this.svgRect_ = dom.createSvgElement(Svg.RECT, { + 'class': 'blocklyCommentRect', + 'x': 0, + 'y': 0, + 'rx': BORDER_RADIUS, + 'ry': BORDER_RADIUS + }); this.svgGroup_.appendChild(this.svgRect_); /** @@ -97,16 +128,14 @@ Blockly.WorkspaceCommentSvg = function( * @type {boolean} * @private */ - this.useDragSurface_ = - Blockly.utils.is3dSupported() && !!workspace.blockDragSurface_; + this.useDragSurface_ = utils.is3dSupported() && !!workspace.blockDragSurface_; - Blockly.WorkspaceCommentSvg.superClass_.constructor.call( + WorkspaceCommentSvg.superClass_.constructor.call( this, workspace, content, height, width, opt_id); this.render(); }; -Blockly.utils.object.inherits( - Blockly.WorkspaceCommentSvg, Blockly.WorkspaceComment); +object.inherits(WorkspaceCommentSvg, WorkspaceComment); /** * The width and height to use to size a workspace comment when it is first @@ -114,13 +143,21 @@ Blockly.utils.object.inherits( * @type {number} * @package */ -Blockly.WorkspaceCommentSvg.DEFAULT_SIZE = 100; +WorkspaceCommentSvg.DEFAULT_SIZE = 100; + +/** + * Offset from the top to make room for a top bar. + * @type {number} + * @const + * @private + */ +WorkspaceCommentSvg.TOP_OFFSET = 10; /** * Dispose of this comment. * @package */ -Blockly.WorkspaceCommentSvg.prototype.dispose = function() { +WorkspaceCommentSvg.prototype.dispose = function() { if (!this.workspace) { // The comment has already been deleted. return; @@ -131,39 +168,39 @@ Blockly.WorkspaceCommentSvg.prototype.dispose = function() { this.workspace.cancelCurrentGesture(); } - if (Blockly.Events.isEnabled()) { - Blockly.Events.fire( - new (Blockly.Events.get(Blockly.Events.COMMENT_DELETE))(this)); + if (Events.isEnabled()) { + Events.fire(new (Events.get(Events.COMMENT_DELETE))(this)); } - Blockly.utils.dom.removeNode(this.svgGroup_); + dom.removeNode(this.svgGroup_); // Sever JavaScript to DOM connections. this.svgGroup_ = null; this.svgRect_ = null; // Dispose of any rendered components this.disposeInternal_(); - Blockly.Events.disable(); - Blockly.WorkspaceCommentSvg.superClass_.dispose.call(this); - Blockly.Events.enable(); + Events.disable(); + WorkspaceCommentSvg.superClass_.dispose.call(this); + Events.enable(); }; /** * Create and initialize the SVG representation of a workspace comment. * May be called more than once. * - * @param {boolean=} opt_noSelect Text inside text area will be selected if false + * @param {boolean=} opt_noSelect Text inside text area will be selected if + * false * * @package */ -Blockly.WorkspaceCommentSvg.prototype.initSvg = function(opt_noSelect) { +WorkspaceCommentSvg.prototype.initSvg = function(opt_noSelect) { if (!this.workspace.rendered) { throw TypeError('Workspace is headless.'); } if (!this.workspace.options.readOnly && !this.eventsInit_) { - Blockly.browserEvents.conditionalBind( + browserEvents.conditionalBind( this.svgRectTarget_, 'mousedown', this, this.pathMouseDown_); - Blockly.browserEvents.conditionalBind( + browserEvents.conditionalBind( this.svgHandleTarget_, 'mousedown', this, this.pathMouseDown_); } this.eventsInit_ = true; @@ -183,8 +220,8 @@ Blockly.WorkspaceCommentSvg.prototype.initSvg = function(opt_noSelect) { * @param {!Event} e Mouse down event or touch start event. * @private */ -Blockly.WorkspaceCommentSvg.prototype.pathMouseDown_ = function(e) { - var gesture = this.workspace.getGesture(e); +WorkspaceCommentSvg.prototype.pathMouseDown_ = function(e) { + const gesture = this.workspace.getGesture(e); if (gesture) { gesture.handleBubbleStart(e, this); } @@ -195,44 +232,44 @@ Blockly.WorkspaceCommentSvg.prototype.pathMouseDown_ = function(e) { * @param {!Event} e Mouse event. * @package */ -Blockly.WorkspaceCommentSvg.prototype.showContextMenu = function(e) { +WorkspaceCommentSvg.prototype.showContextMenu = function(e) { if (this.workspace.options.readOnly) { return; } // Save the current workspace comment in a variable for use in closures. - var comment = this; - var menuOptions = []; + const comment = this; + const menuOptions = []; if (this.isDeletable() && this.isMovable()) { - menuOptions.push(Blockly.ContextMenu.commentDuplicateOption(comment)); - menuOptions.push(Blockly.ContextMenu.commentDeleteOption(comment)); + menuOptions.push(ContextMenu.commentDuplicateOption(comment)); + menuOptions.push(ContextMenu.commentDeleteOption(comment)); } - Blockly.ContextMenu.show(e, menuOptions, this.RTL); + ContextMenu.show(e, menuOptions, this.RTL); }; /** * Select this comment. Highlight it visually. * @package */ -Blockly.WorkspaceCommentSvg.prototype.select = function() { +WorkspaceCommentSvg.prototype.select = function() { if (Blockly.selected == this) { return; } - var oldId = null; + let oldId = null; if (Blockly.selected) { oldId = Blockly.selected.id; // Unselect any previously selected block. - Blockly.Events.disable(); + Events.disable(); try { Blockly.selected.unselect(); } finally { - Blockly.Events.enable(); + Events.enable(); } } - var event = new (Blockly.Events.get(Blockly.Events.SELECTED))(oldId, this.id, - this.workspace.id); - Blockly.Events.fire(event); + const event = + new (Events.get(Events.SELECTED))(oldId, this.id, this.workspace.id); + Events.fire(event); Blockly.selected = this; this.addSelect(); }; @@ -241,13 +278,13 @@ Blockly.WorkspaceCommentSvg.prototype.select = function() { * Unselect this comment. Remove its highlighting. * @package */ -Blockly.WorkspaceCommentSvg.prototype.unselect = function() { +WorkspaceCommentSvg.prototype.unselect = function() { if (Blockly.selected != this) { return; } - var event = new (Blockly.Events.get(Blockly.Events.SELECTED))(this.id, null, - this.workspace.id); - Blockly.Events.fire(event); + const event = + new (Events.get(Events.SELECTED))(this.id, null, this.workspace.id); + Events.fire(event); Blockly.selected = null; this.removeSelect(); this.blurFocus(); @@ -257,8 +294,8 @@ Blockly.WorkspaceCommentSvg.prototype.unselect = function() { * Select this comment. Highlight it visually. * @package */ -Blockly.WorkspaceCommentSvg.prototype.addSelect = function() { - Blockly.utils.dom.addClass( +WorkspaceCommentSvg.prototype.addSelect = function() { + dom.addClass( /** @type {!Element} */ (this.svgGroup_), 'blocklySelected'); this.setFocus(); }; @@ -267,8 +304,8 @@ Blockly.WorkspaceCommentSvg.prototype.addSelect = function() { * Unselect this comment. Remove its highlighting. * @package */ -Blockly.WorkspaceCommentSvg.prototype.removeSelect = function() { - Blockly.utils.dom.removeClass( +WorkspaceCommentSvg.prototype.removeSelect = function() { + dom.removeClass( /** @type {!Element} */ (this.svgGroup_), 'blocklySelected'); this.blurFocus(); }; @@ -277,8 +314,8 @@ Blockly.WorkspaceCommentSvg.prototype.removeSelect = function() { * Focus this comment. Highlight it visually. * @package */ -Blockly.WorkspaceCommentSvg.prototype.addFocus = function() { - Blockly.utils.dom.addClass( +WorkspaceCommentSvg.prototype.addFocus = function() { + dom.addClass( /** @type {!Element} */ (this.svgGroup_), 'blocklyFocused'); }; @@ -286,8 +323,8 @@ Blockly.WorkspaceCommentSvg.prototype.addFocus = function() { * Unfocus this comment. Remove its highlighting. * @package */ -Blockly.WorkspaceCommentSvg.prototype.removeFocus = function() { - Blockly.utils.dom.removeClass( +WorkspaceCommentSvg.prototype.removeFocus = function() { + dom.removeClass( /** @type {!Element} */ (this.svgGroup_), 'blocklyFocused'); }; @@ -297,29 +334,29 @@ Blockly.WorkspaceCommentSvg.prototype.removeFocus = function() { * If the comment is on the workspace, (0, 0) is the origin of the workspace * coordinate system. * This does not change with workspace scale. - * @return {!Blockly.utils.Coordinate} Object with .x and .y properties in + * @return {!Coordinate} Object with .x and .y properties in * workspace coordinates. * @package */ -Blockly.WorkspaceCommentSvg.prototype.getRelativeToSurfaceXY = function() { - var x = 0; - var y = 0; +WorkspaceCommentSvg.prototype.getRelativeToSurfaceXY = function() { + let x = 0; + let y = 0; - var dragSurfaceGroup = + const dragSurfaceGroup = this.useDragSurface_ ? this.workspace.blockDragSurface_.getGroup() : null; - var element = this.getSvgRoot(); + let element = this.getSvgRoot(); if (element) { do { // Loop through this comment and every parent. - var xy = Blockly.utils.getRelativeXY(element); + const xy = utils.getRelativeXY(element); x += xy.x; y += xy.y; // If this element is the current element on the drag surface, include // the translation of the drag surface itself. if (this.useDragSurface_ && this.workspace.blockDragSurface_.getCurrentBlock() == element) { - var surfaceTranslation = + const surfaceTranslation = this.workspace.blockDragSurface_.getSurfaceTranslation(); x += surfaceTranslation.x; y += surfaceTranslation.y; @@ -328,7 +365,7 @@ Blockly.WorkspaceCommentSvg.prototype.getRelativeToSurfaceXY = function() { } while (element && element != this.workspace.getBubbleCanvas() && element != dragSurfaceGroup); } - this.xy_ = new Blockly.utils.Coordinate(x, y); + this.xy_ = new Coordinate(x, y); return this.xy_; }; @@ -338,14 +375,14 @@ Blockly.WorkspaceCommentSvg.prototype.getRelativeToSurfaceXY = function() { * @param {number} dy Vertical offset, in workspace units. * @package */ -Blockly.WorkspaceCommentSvg.prototype.moveBy = function(dx, dy) { - var event = new (Blockly.Events.get(Blockly.Events.COMMENT_MOVE))(this); +WorkspaceCommentSvg.prototype.moveBy = function(dx, dy) { + const event = new (Events.get(Events.COMMENT_MOVE))(this); // TODO: Do I need to look up the relative to surface XY position here? - var xy = this.getRelativeToSurfaceXY(); + const xy = this.getRelativeToSurfaceXY(); this.translate(xy.x + dx, xy.y + dy); - this.xy_ = new Blockly.utils.Coordinate(xy.x + dx, xy.y + dy); + this.xy_ = new Coordinate(xy.x + dx, xy.y + dy); event.recordNew(); - Blockly.Events.fire(event); + Events.fire(event); this.workspace.resizeContents(); }; @@ -356,8 +393,8 @@ Blockly.WorkspaceCommentSvg.prototype.moveBy = function(dx, dy) { * @param {number} y The y coordinate of the translation in workspace units. * @package */ -Blockly.WorkspaceCommentSvg.prototype.translate = function(x, y) { - this.xy_ = new Blockly.utils.Coordinate(x, y); +WorkspaceCommentSvg.prototype.translate = function(x, y) { + this.xy_ = new Coordinate(x, y); this.getSvgRoot().setAttribute('transform', 'translate(' + x + ',' + y + ')'); }; @@ -367,7 +404,7 @@ Blockly.WorkspaceCommentSvg.prototype.translate = function(x, y) { * setDragging(true). Does nothing if useDragSurface_ is false. * @package */ -Blockly.WorkspaceCommentSvg.prototype.moveToDragSurface = function() { +WorkspaceCommentSvg.prototype.moveToDragSurface = function() { if (!this.useDragSurface_) { return; } @@ -375,7 +412,7 @@ Blockly.WorkspaceCommentSvg.prototype.moveToDragSurface = function() { // is equal to the current relative-to-surface position, // to keep the position in sync as it move on/off the surface. // This is in workspace coordinates. - var xy = this.getRelativeToSurfaceXY(); + const xy = this.getRelativeToSurfaceXY(); this.clearTransformAttributes_(); this.workspace.blockDragSurface_.translateSurface(xy.x, xy.y); // Execute the move on the top-level SVG component @@ -386,11 +423,11 @@ Blockly.WorkspaceCommentSvg.prototype.moveToDragSurface = function() { * Move this comment back to the workspace block canvas. * Generally should be called at the same time as setDragging(false). * Does nothing if useDragSurface_ is false. - * @param {!Blockly.utils.Coordinate} newXY The position the comment should take + * @param {!Coordinate} newXY The position the comment should take * on on the workspace canvas, in workspace coordinates. * @private */ -Blockly.WorkspaceCommentSvg.prototype.moveOffDragSurface = function(newXY) { +WorkspaceCommentSvg.prototype.moveOffDragSurface = function(newXY) { if (!this.useDragSurface_) { return; } @@ -402,14 +439,13 @@ Blockly.WorkspaceCommentSvg.prototype.moveOffDragSurface = function(newXY) { /** * Move this comment during a drag, taking into account whether we are using a * drag surface to translate blocks. - * @param {Blockly.BlockDragSurfaceSvg} dragSurface The surface that carries + * @param {BlockDragSurfaceSvg} dragSurface The surface that carries * rendered items during a drag, or null if no drag surface is in use. - * @param {!Blockly.utils.Coordinate} newLoc The location to translate to, in + * @param {!Coordinate} newLoc The location to translate to, in * workspace coordinates. * @package */ -Blockly.WorkspaceCommentSvg.prototype.moveDuringDrag = function( - dragSurface, newLoc) { +WorkspaceCommentSvg.prototype.moveDuringDrag = function(dragSurface, newLoc) { if (dragSurface) { dragSurface.translateSurface(newLoc.x, newLoc.y); } else { @@ -425,7 +461,7 @@ Blockly.WorkspaceCommentSvg.prototype.moveDuringDrag = function( * @param {number} y The y position to move to. * @package */ -Blockly.WorkspaceCommentSvg.prototype.moveTo = function(x, y) { +WorkspaceCommentSvg.prototype.moveTo = function(x, y) { this.translate(x, y); }; @@ -434,7 +470,7 @@ Blockly.WorkspaceCommentSvg.prototype.moveTo = function(x, y) { * Used when the comment is switching from 3d to 2d transform or vice versa. * @private */ -Blockly.WorkspaceCommentSvg.prototype.clearTransformAttributes_ = function() { +WorkspaceCommentSvg.prototype.clearTransformAttributes_ = function() { this.getSvgRoot().removeAttribute('transform'); }; @@ -442,15 +478,16 @@ Blockly.WorkspaceCommentSvg.prototype.clearTransformAttributes_ = function() { * Returns the coordinates of a bounding box describing the dimensions of this * comment. * Coordinate system: workspace coordinates. - * @return {!Blockly.utils.Rect} Object with coordinates of the bounding box. + * @return {!Rect} Object with coordinates of the bounding box. * @package */ -Blockly.WorkspaceCommentSvg.prototype.getBoundingRectangle = function() { - var blockXY = this.getRelativeToSurfaceXY(); - var commentBounds = this.getHeightWidth(); - var top = blockXY.y; - var bottom = blockXY.y + commentBounds.height; - var left, right; +WorkspaceCommentSvg.prototype.getBoundingRectangle = function() { + const blockXY = this.getRelativeToSurfaceXY(); + const commentBounds = this.getHeightWidth(); + const top = blockXY.y; + const bottom = blockXY.y + commentBounds.height; + let left; + let right; if (this.RTL) { left = blockXY.x - commentBounds.width; // Add the width of the tab/puzzle piece knob to the x coordinate @@ -462,19 +499,19 @@ Blockly.WorkspaceCommentSvg.prototype.getBoundingRectangle = function() { left = blockXY.x; right = blockXY.x + commentBounds.width; } - return new Blockly.utils.Rect(top, bottom, left, right); + return new Rect(top, bottom, left, right); }; /** * Add or remove the UI indicating if this comment is movable or not. * @package */ -Blockly.WorkspaceCommentSvg.prototype.updateMovable = function() { +WorkspaceCommentSvg.prototype.updateMovable = function() { if (this.isMovable()) { - Blockly.utils.dom.addClass( + dom.addClass( /** @type {!Element} */ (this.svgGroup_), 'blocklyDraggable'); } else { - Blockly.utils.dom.removeClass( + dom.removeClass( /** @type {!Element} */ (this.svgGroup_), 'blocklyDraggable'); } }; @@ -484,8 +521,8 @@ Blockly.WorkspaceCommentSvg.prototype.updateMovable = function() { * @param {boolean} movable True if movable. * @package */ -Blockly.WorkspaceCommentSvg.prototype.setMovable = function(movable) { - Blockly.WorkspaceCommentSvg.superClass_.setMovable.call(this, movable); +WorkspaceCommentSvg.prototype.setMovable = function(movable) { + WorkspaceCommentSvg.superClass_.setMovable.call(this, movable); this.updateMovable(); }; @@ -493,8 +530,8 @@ Blockly.WorkspaceCommentSvg.prototype.setMovable = function(movable) { * Set whether this comment is editable or not. * @param {boolean} editable True if editable. */ -Blockly.WorkspaceCommentSvg.prototype.setEditable = function(editable) { - Blockly.WorkspaceCommentSvg.superClass_.setEditable.call(this, editable); +WorkspaceCommentSvg.prototype.setEditable = function(editable) { + WorkspaceCommentSvg.superClass_.setEditable.call(this, editable); if (this.textarea_) { this.textarea_.readOnly = !editable; } @@ -505,15 +542,15 @@ Blockly.WorkspaceCommentSvg.prototype.setEditable = function(editable) { * @param {boolean} adding True if adding, false if removing. * @package */ -Blockly.WorkspaceCommentSvg.prototype.setDragging = function(adding) { +WorkspaceCommentSvg.prototype.setDragging = function(adding) { if (adding) { - var group = this.getSvgRoot(); + const group = this.getSvgRoot(); group.translate_ = ''; group.skew_ = ''; - Blockly.utils.dom.addClass( + dom.addClass( /** @type {!Element} */ (this.svgGroup_), 'blocklyDragging'); } else { - Blockly.utils.dom.removeClass( + dom.removeClass( /** @type {!Element} */ (this.svgGroup_), 'blocklyDragging'); } }; @@ -523,7 +560,7 @@ Blockly.WorkspaceCommentSvg.prototype.setDragging = function(adding) { * @return {!SVGElement} The root SVG node (probably a group). * @package */ -Blockly.WorkspaceCommentSvg.prototype.getSvgRoot = function() { +WorkspaceCommentSvg.prototype.getSvgRoot = function() { return this.svgGroup_; }; @@ -532,7 +569,7 @@ Blockly.WorkspaceCommentSvg.prototype.getSvgRoot = function() { * @return {string} Comment text. * @package */ -Blockly.WorkspaceCommentSvg.prototype.getContent = function() { +WorkspaceCommentSvg.prototype.getContent = function() { return this.textarea_ ? this.textarea_.value : this.content_; }; @@ -541,8 +578,8 @@ Blockly.WorkspaceCommentSvg.prototype.getContent = function() { * @param {string} content Comment content. * @package */ -Blockly.WorkspaceCommentSvg.prototype.setContent = function(content) { - Blockly.WorkspaceCommentSvg.superClass_.setContent.call(this, content); +WorkspaceCommentSvg.prototype.setContent = function(content) { + WorkspaceCommentSvg.superClass_.setContent.call(this, content); if (this.textarea_) { this.textarea_.value = content; } @@ -554,12 +591,12 @@ Blockly.WorkspaceCommentSvg.prototype.setContent = function(content) { * otherwise. * @package */ -Blockly.WorkspaceCommentSvg.prototype.setDeleteStyle = function(enable) { +WorkspaceCommentSvg.prototype.setDeleteStyle = function(enable) { if (enable) { - Blockly.utils.dom.addClass( + dom.addClass( /** @type {!Element} */ (this.svgGroup_), 'blocklyDraggingDelete'); } else { - Blockly.utils.dom.removeClass( + dom.removeClass( /** @type {!Element} */ (this.svgGroup_), 'blocklyDraggingDelete'); } }; @@ -572,26 +609,26 @@ Blockly.WorkspaceCommentSvg.prototype.setDeleteStyle = function(enable) { * otherwise. * @package */ -Blockly.WorkspaceCommentSvg.prototype.setAutoLayout = function(_enable) { +WorkspaceCommentSvg.prototype.setAutoLayout = function(_enable) { // NOP for compatibility with the bubble dragger. }; /** * Decode an XML comment tag and create a rendered comment on the workspace. * @param {!Element} xmlComment XML comment element. - * @param {!Blockly.Workspace} workspace The workspace. + * @param {!Workspace} workspace The workspace. * @param {number=} opt_wsWidth The width of the workspace, which is used to * position comments correctly in RTL. - * @return {!Blockly.WorkspaceCommentSvg} The created workspace comment. + * @return {!WorkspaceCommentSvg} The created workspace comment. * @package */ -Blockly.WorkspaceCommentSvg.fromXml = function( - xmlComment, workspace, opt_wsWidth) { - Blockly.Events.disable(); +WorkspaceCommentSvg.fromXml = function(xmlComment, workspace, opt_wsWidth) { + Events.disable(); + let comment; try { - var info = Blockly.WorkspaceComment.parseAttributes(xmlComment); + const info = WorkspaceComment.parseAttributes(xmlComment); - var comment = new Blockly.WorkspaceCommentSvg( + comment = new WorkspaceCommentSvg( workspace, info.content, info.h, info.w, info.id); if (workspace.rendered) { comment.initSvg(true); @@ -601,16 +638,16 @@ Blockly.WorkspaceCommentSvg.fromXml = function( // rendered RTL workspace. if (!isNaN(info.x) && !isNaN(info.y)) { if (workspace.RTL) { - var wsWidth = opt_wsWidth || workspace.getWidth(); + const wsWidth = opt_wsWidth || workspace.getWidth(); comment.moveBy(wsWidth - info.x, info.y); } else { comment.moveBy(info.x, info.y); } } } finally { - Blockly.Events.enable(); + Events.enable(); } - Blockly.WorkspaceComment.fireCreateEvent(comment); + WorkspaceComment.fireCreateEvent(comment); return comment; }; @@ -621,14 +658,14 @@ Blockly.WorkspaceCommentSvg.fromXml = function( * @return {!Element} Tree of XML elements. * @package */ -Blockly.WorkspaceCommentSvg.prototype.toXmlWithXY = function(opt_noId) { - var width; // Not used in LTR. +WorkspaceCommentSvg.prototype.toXmlWithXY = function(opt_noId) { + let width; // Not used in LTR. if (this.workspace.RTL) { // Here be performance dragons: This calls getMetrics(). width = this.workspace.getWidth(); } - var element = this.toXml(opt_noId); - var xy = this.getRelativeToSurfaceXY(); + const element = this.toXml(opt_noId); + const xy = this.getRelativeToSurfaceXY(); element.setAttribute( 'x', Math.round(this.workspace.RTL ? width - xy.x : xy.x)); element.setAttribute('y', Math.round(xy.y)); @@ -639,17 +676,416 @@ Blockly.WorkspaceCommentSvg.prototype.toXmlWithXY = function(opt_noId) { /** * Encode a comment for copying. - * @return {!Blockly.ICopyable.CopyData} Copy metadata. + * @return {!ICopyable.CopyData} Copy metadata. * @package */ -Blockly.WorkspaceCommentSvg.prototype.toCopyData = function() { +WorkspaceCommentSvg.prototype.toCopyData = function() { return {xml: this.toXmlWithXY(), source: this.workspace, typeCounts: null}; }; +/** + * Returns a bounding box describing the dimensions of this comment. + * @return {!{height: number, width: number}} Object with height and width + * properties in workspace units. + * @package + */ +WorkspaceCommentSvg.prototype.getHeightWidth = function() { + return {width: this.getWidth(), height: this.getHeight()}; +}; + +/** + * Renders the workspace comment. + * @package + */ +WorkspaceCommentSvg.prototype.render = function() { + if (this.rendered_) { + return; + } + + const size = this.getHeightWidth(); + + // Add text area + this.createEditor_(); + this.svgGroup_.appendChild(this.foreignObject_); + + this.svgHandleTarget_ = dom.createSvgElement( + Svg.RECT, {'class': 'blocklyCommentHandleTarget', 'x': 0, 'y': 0}); + this.svgGroup_.appendChild(this.svgHandleTarget_); + this.svgRectTarget_ = dom.createSvgElement(Svg.RECT, { + 'class': 'blocklyCommentTarget', + 'x': 0, + 'y': 0, + 'rx': BORDER_RADIUS, + 'ry': BORDER_RADIUS + }); + this.svgGroup_.appendChild(this.svgRectTarget_); + + // Add the resize icon + this.addResizeDom_(); + if (this.isDeletable()) { + // Add the delete icon + this.addDeleteDom_(); + } + + this.setSize_(size.width, size.height); + + // Set the content + this.textarea_.value = this.content_; + + this.rendered_ = true; + + if (this.resizeGroup_) { + browserEvents.conditionalBind( + this.resizeGroup_, 'mousedown', this, this.resizeMouseDown_); + } + + if (this.isDeletable()) { + browserEvents.conditionalBind( + this.deleteGroup_, 'mousedown', this, this.deleteMouseDown_); + browserEvents.conditionalBind( + this.deleteGroup_, 'mouseout', this, this.deleteMouseOut_); + browserEvents.conditionalBind( + this.deleteGroup_, 'mouseup', this, this.deleteMouseUp_); + } +}; + +/** + * Create the text area for the comment. + * @return {!Element} The top-level node of the editor. + * @private + */ +WorkspaceCommentSvg.prototype.createEditor_ = function() { + /* Create the editor. Here's the markup that will be generated: + + + + */ + this.foreignObject_ = dom.createSvgElement( + Svg.FOREIGNOBJECT, { + 'x': 0, + 'y': WorkspaceCommentSvg.TOP_OFFSET, + 'class': 'blocklyCommentForeignObject' + }, + null); + const body = document.createElementNS(dom.HTML_NS, 'body'); + body.setAttribute('xmlns', dom.HTML_NS); + body.className = 'blocklyMinimalBody'; + const textarea = document.createElementNS(dom.HTML_NS, 'textarea'); + textarea.className = 'blocklyCommentTextarea'; + textarea.setAttribute('dir', this.RTL ? 'RTL' : 'LTR'); + textarea.readOnly = !this.isEditable(); + body.appendChild(textarea); + this.textarea_ = textarea; + this.foreignObject_.appendChild(body); + // Don't zoom with mousewheel. + browserEvents.conditionalBind(textarea, 'wheel', this, function(e) { + e.stopPropagation(); + }); + browserEvents.conditionalBind( + textarea, 'change', this, + function( + /* eslint-disable no-unused-vars */ e + /* eslint-enable no-unused-vars */) { + this.setContent(textarea.value); + }); + return this.foreignObject_; +}; + +/** + * Add the resize icon to the DOM + * @private + */ +WorkspaceCommentSvg.prototype.addResizeDom_ = function() { + this.resizeGroup_ = dom.createSvgElement( + Svg.G, {'class': this.RTL ? 'blocklyResizeSW' : 'blocklyResizeSE'}, + this.svgGroup_); + dom.createSvgElement( + Svg.POLYGON, + {'points': '0,x x,x x,0'.replace(/x/g, RESIZE_SIZE.toString())}, + this.resizeGroup_); + dom.createSvgElement( + Svg.LINE, { + 'class': 'blocklyResizeLine', + 'x1': RESIZE_SIZE / 3, + 'y1': RESIZE_SIZE - 1, + 'x2': RESIZE_SIZE - 1, + 'y2': RESIZE_SIZE / 3 + }, + this.resizeGroup_); + dom.createSvgElement( + Svg.LINE, { + 'class': 'blocklyResizeLine', + 'x1': RESIZE_SIZE * 2 / 3, + 'y1': RESIZE_SIZE - 1, + 'x2': RESIZE_SIZE - 1, + 'y2': RESIZE_SIZE * 2 / 3 + }, + this.resizeGroup_); +}; + +/** + * Add the delete icon to the DOM + * @private + */ +WorkspaceCommentSvg.prototype.addDeleteDom_ = function() { + this.deleteGroup_ = dom.createSvgElement( + Svg.G, {'class': 'blocklyCommentDeleteIcon'}, this.svgGroup_); + this.deleteIconBorder_ = dom.createSvgElement( + Svg.CIRCLE, + {'class': 'blocklyDeleteIconShape', 'r': '7', 'cx': '7.5', 'cy': '7.5'}, + this.deleteGroup_); + // x icon. + dom.createSvgElement( + Svg.LINE, { + 'x1': '5', + 'y1': '10', + 'x2': '10', + 'y2': '5', + 'stroke': '#fff', + 'stroke-width': '2' + }, + this.deleteGroup_); + dom.createSvgElement( + Svg.LINE, { + 'x1': '5', + 'y1': '5', + 'x2': '10', + 'y2': '10', + 'stroke': '#fff', + 'stroke-width': '2' + }, + this.deleteGroup_); +}; + +/** + * Handle a mouse-down on comment's resize corner. + * @param {!Event} e Mouse down event. + * @private + */ +WorkspaceCommentSvg.prototype.resizeMouseDown_ = function(e) { + this.unbindDragEvents_(); + if (utils.isRightButton(e)) { + // No right-click. + e.stopPropagation(); + return; + } + // Left-click (or middle click) + this.workspace.startDrag( + e, + new Coordinate( + this.workspace.RTL ? -this.width_ : this.width_, this.height_)); + + this.onMouseUpWrapper_ = browserEvents.conditionalBind( + document, 'mouseup', this, this.resizeMouseUp_); + this.onMouseMoveWrapper_ = browserEvents.conditionalBind( + document, 'mousemove', this, this.resizeMouseMove_); + Blockly.hideChaff(); + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); +}; + +/** + * Handle a mouse-down on comment's delete icon. + * @param {!Event} e Mouse down event. + * @private + */ +WorkspaceCommentSvg.prototype.deleteMouseDown_ = function(e) { + // Highlight the delete icon. + dom.addClass( + /** @type {!Element} */ (this.deleteIconBorder_), + 'blocklyDeleteIconHighlighted'); + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); +}; + +/** + * Handle a mouse-out on comment's delete icon. + * @param {!Event} _e Mouse out event. + * @private + */ +WorkspaceCommentSvg.prototype.deleteMouseOut_ = function(_e) { + // Restore highlight on the delete icon. + dom.removeClass( + /** @type {!Element} */ (this.deleteIconBorder_), + 'blocklyDeleteIconHighlighted'); +}; + +/** + * Handle a mouse-up on comment's delete icon. + * @param {!Event} e Mouse up event. + * @private + */ +WorkspaceCommentSvg.prototype.deleteMouseUp_ = function(e) { + // Delete this comment. + this.dispose(true, true); + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); +}; + +/** + * Stop binding to the global mouseup and mousemove events. + * @private + */ +WorkspaceCommentSvg.prototype.unbindDragEvents_ = function() { + if (this.onMouseUpWrapper_) { + browserEvents.unbind(this.onMouseUpWrapper_); + this.onMouseUpWrapper_ = null; + } + if (this.onMouseMoveWrapper_) { + browserEvents.unbind(this.onMouseMoveWrapper_); + this.onMouseMoveWrapper_ = null; + } +}; + +/** + * Handle a mouse-up event while dragging a comment's border or resize handle. + * @param {!Event} e Mouse up event. + * @private + */ +WorkspaceCommentSvg.prototype.resizeMouseUp_ = function(/* e */) { + Touch.clearTouchIdentifier(); + this.unbindDragEvents_(); +}; + +/** + * Resize this comment to follow the mouse. + * @param {!Event} e Mouse move event. + * @private + */ +WorkspaceCommentSvg.prototype.resizeMouseMove_ = function(e) { + this.autoLayout_ = false; + const newXY = this.workspace.moveDrag(e); + this.setSize_(this.RTL ? -newXY.x : newXY.x, newXY.y); +}; + +/** + * Callback function triggered when the comment has resized. + * Resize the text area accordingly. + * @private + */ +WorkspaceCommentSvg.prototype.resizeComment_ = function() { + const size = this.getHeightWidth(); + const topOffset = WorkspaceCommentSvg.TOP_OFFSET; + const textOffset = TEXTAREA_OFFSET * 2; + + this.foreignObject_.setAttribute('width', size.width); + this.foreignObject_.setAttribute('height', size.height - topOffset); + if (this.RTL) { + this.foreignObject_.setAttribute('x', -size.width); + } + this.textarea_.style.width = (size.width - textOffset) + 'px'; + this.textarea_.style.height = (size.height - textOffset - topOffset) + 'px'; +}; + +/** + * Set size + * @param {number} width width of the container + * @param {number} height height of the container + * @private + */ +WorkspaceCommentSvg.prototype.setSize_ = function(width, height) { + // Minimum size of a comment. + width = Math.max(width, 45); + height = Math.max(height, 20 + WorkspaceCommentSvg.TOP_OFFSET); + this.width_ = width; + this.height_ = height; + this.svgRect_.setAttribute('width', width); + this.svgRect_.setAttribute('height', height); + this.svgRectTarget_.setAttribute('width', width); + this.svgRectTarget_.setAttribute('height', height); + this.svgHandleTarget_.setAttribute('width', width); + this.svgHandleTarget_.setAttribute('height', WorkspaceCommentSvg.TOP_OFFSET); + if (this.RTL) { + this.svgRect_.setAttribute('transform', 'scale(-1 1)'); + this.svgRectTarget_.setAttribute('transform', 'scale(-1 1)'); + } + + if (this.resizeGroup_) { + if (this.RTL) { + // Mirror the resize group. + this.resizeGroup_.setAttribute( + 'transform', + 'translate(' + (-width + RESIZE_SIZE) + ',' + (height - RESIZE_SIZE) + + ') scale(-1 1)'); + this.deleteGroup_.setAttribute( + 'transform', + 'translate(' + (-width + RESIZE_SIZE) + ',' + (-RESIZE_SIZE) + + ') scale(-1 1)'); + } else { + this.resizeGroup_.setAttribute( + 'transform', + 'translate(' + (width - RESIZE_SIZE) + ',' + (height - RESIZE_SIZE) + + ')'); + this.deleteGroup_.setAttribute( + 'transform', + 'translate(' + (width - RESIZE_SIZE) + ',' + (-RESIZE_SIZE) + ')'); + } + } + + // Allow the contents to resize. + this.resizeComment_(); +}; + +/** + * Dispose of any rendered comment components. + * @private + */ +WorkspaceCommentSvg.prototype.disposeInternal_ = function() { + this.textarea_ = null; + this.foreignObject_ = null; + this.svgRectTarget_ = null; + this.svgHandleTarget_ = null; + this.disposed_ = true; +}; + +/** + * Set the focus on the text area. + * @package + */ +WorkspaceCommentSvg.prototype.setFocus = function() { + const comment = this; + this.focused_ = true; + // Defer CSS changes. + setTimeout(function() { + if (comment.disposed_) { + return; + } + comment.textarea_.focus(); + comment.addFocus(); + dom.addClass(comment.svgRectTarget_, 'blocklyCommentTargetFocused'); + dom.addClass(comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused'); + }, 0); +}; + +/** + * Remove focus from the text area. + * @package + */ +WorkspaceCommentSvg.prototype.blurFocus = function() { + const comment = this; + this.focused_ = false; + // Defer CSS changes. + setTimeout(function() { + if (comment.disposed_) { + return; + } + + comment.textarea_.blur(); + comment.removeFocus(); + dom.removeClass(comment.svgRectTarget_, 'blocklyCommentTargetFocused'); + dom.removeClass( + comment.svgHandleTarget_, 'blocklyCommentHandleTargetFocused'); + }, 0); +}; + /** * CSS for workspace comment. See css.js for use. */ -Blockly.Css.register([ +Css.register([ // clang-format off /* eslint-disable indent */ '.blocklyCommentForeignObject {', @@ -712,3 +1148,5 @@ Blockly.Css.register([ /* eslint-enable indent */ // clang-format on ]); + +exports = WorkspaceCommentSvg; diff --git a/core/zoom_controls.js b/core/zoom_controls.js index 7d0d7e6ce..1b7a568cc 100644 --- a/core/zoom_controls.js +++ b/core/zoom_controls.js @@ -10,35 +10,37 @@ */ 'use strict'; -goog.provide('Blockly.ZoomControls'); +goog.module('Blockly.ZoomControls'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.browserEvents'); -goog.require('Blockly.ComponentManager'); -goog.require('Blockly.Css'); -goog.require('Blockly.Events'); +const ComponentManager = goog.require('Blockly.ComponentManager'); +const Css = goog.require('Blockly.Css'); +const Events = goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const IPositionable = goog.require('Blockly.IPositionable'); +const Rect = goog.require('Blockly.utils.Rect'); +const Svg = goog.require('Blockly.utils.Svg'); +const Touch = goog.require('Blockly.Touch'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +const browserEvents = goog.require('Blockly.browserEvents'); +const dom = goog.require('Blockly.utils.dom'); +const internalConstants = goog.require('Blockly.internalConstants'); +const uiPosition = goog.require('Blockly.uiPosition'); +const utils = goog.require('Blockly.utils'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.Click'); -goog.require('Blockly.IPositionable'); -goog.require('Blockly.internalConstants'); -goog.require('Blockly.Touch'); -goog.require('Blockly.uiPosition'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.Rect'); -goog.require('Blockly.utils.Svg'); - -goog.requireType('Blockly.WorkspaceSvg'); /** * Class for a zoom controls. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to sit in. + * @param {!WorkspaceSvg} workspace The workspace to sit in. * @constructor - * @implements {Blockly.IPositionable} + * @implements {IPositionable} */ -Blockly.ZoomControls = function(workspace) { +const ZoomControls = function(workspace) { /** - * @type {!Blockly.WorkspaceSvg} + * @type {!WorkspaceSvg} * @private */ this.workspace_ = workspace; @@ -52,24 +54,24 @@ Blockly.ZoomControls = function(workspace) { /** * A handle to use to unbind the mouse down event handler for zoom reset - * button. Opaque data returned from Blockly.bindEventWithChecks_. - * @type {?Blockly.browserEvents.Data} + * button. Opaque data returned from browserEvents.conditionalBind. + * @type {?browserEvents.Data} * @private */ this.onZoomResetWrapper_ = null; /** * A handle to use to unbind the mouse down event handler for zoom in button. - * Opaque data returned from Blockly.bindEventWithChecks_. - * @type {?Blockly.browserEvents.Data} + * Opaque data returned from browserEvents.conditionalBind. + * @type {?browserEvents.Data} * @private */ this.onZoomInWrapper_ = null; /** * A handle to use to unbind the mouse down event handler for zoom out button. - * Opaque data returned from Blockly.bindEventWithChecks_. - * @type {?Blockly.browserEvents.Data} + * Opaque data returned from browserEvents.conditionalBind. + * @type {?browserEvents.Data} * @private */ this.onZoomOutWrapper_ = null; @@ -102,7 +104,7 @@ Blockly.ZoomControls = function(workspace) { * @const * @private */ -Blockly.ZoomControls.prototype.WIDTH_ = 32; +ZoomControls.prototype.WIDTH_ = 32; /** * Height of each zoom control. @@ -110,7 +112,7 @@ Blockly.ZoomControls.prototype.WIDTH_ = 32; * @const * @private */ -Blockly.ZoomControls.prototype.HEIGHT_ = 32; +ZoomControls.prototype.HEIGHT_ = 32; /** * Small spacing used between the zoom in and out control, in pixels. @@ -118,7 +120,7 @@ Blockly.ZoomControls.prototype.HEIGHT_ = 32; * @const * @private */ -Blockly.ZoomControls.prototype.SMALL_SPACING_ = 2; +ZoomControls.prototype.SMALL_SPACING_ = 2; /** * Large spacing used between the zoom in and reset control, in pixels. @@ -126,7 +128,7 @@ Blockly.ZoomControls.prototype.SMALL_SPACING_ = 2; * @const * @private */ -Blockly.ZoomControls.prototype.LARGE_SPACING_ = 11; +ZoomControls.prototype.LARGE_SPACING_ = 11; /** * Distance between zoom controls and bottom or top edge of workspace. @@ -134,55 +136,54 @@ Blockly.ZoomControls.prototype.LARGE_SPACING_ = 11; * @const * @private */ -Blockly.ZoomControls.prototype.MARGIN_VERTICAL_ = 20; +ZoomControls.prototype.MARGIN_VERTICAL_ = 20; /** * Distance between zoom controls and right or left edge of workspace. * @type {number} * @private */ -Blockly.ZoomControls.prototype.MARGIN_HORIZONTAL_ = 20; +ZoomControls.prototype.MARGIN_HORIZONTAL_ = 20; /** * The SVG group containing the zoom controls. * @type {SVGElement} * @private */ -Blockly.ZoomControls.prototype.svgGroup_ = null; +ZoomControls.prototype.svgGroup_ = null; /** * Left coordinate of the zoom controls. * @type {number} * @private */ -Blockly.ZoomControls.prototype.left_ = 0; +ZoomControls.prototype.left_ = 0; /** * Top coordinate of the zoom controls. * @type {number} * @private */ -Blockly.ZoomControls.prototype.top_ = 0; +ZoomControls.prototype.top_ = 0; /** * Whether this has been initialized. * @type {boolean} * @private */ -Blockly.ZoomControls.prototype.initialized_ = false; +ZoomControls.prototype.initialized_ = false; /** * Create the zoom controls. * @return {!SVGElement} The zoom controls SVG group. */ -Blockly.ZoomControls.prototype.createDom = function() { - this.svgGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, {}, null); +ZoomControls.prototype.createDom = function() { + this.svgGroup_ = dom.createSvgElement(Svg.G, {}, null); // Each filter/pattern needs a unique ID for the case of multiple Blockly // instances on a page. Browser behaviour becomes undefined otherwise. // https://neil.fraser.name/news/2015/11/01/ - var rnd = String(Math.random()).substring(2); + const rnd = String(Math.random()).substring(2); this.createZoomOutSvg_(rnd); this.createZoomInSvg_(rnd); if (this.workspace_.isMovable()) { @@ -196,11 +197,11 @@ Blockly.ZoomControls.prototype.createDom = function() { /** * Initializes the zoom controls. */ -Blockly.ZoomControls.prototype.init = function() { +ZoomControls.prototype.init = function() { this.workspace_.getComponentManager().addComponent({ component: this, weight: 2, - capabilities: [Blockly.ComponentManager.Capability.POSITIONABLE] + capabilities: [ComponentManager.Capability.POSITIONABLE] }); this.initialized_ = true; }; @@ -209,36 +210,36 @@ Blockly.ZoomControls.prototype.init = function() { * Disposes of this zoom controls. * Unlink from all DOM elements to prevent memory leaks. */ -Blockly.ZoomControls.prototype.dispose = function() { +ZoomControls.prototype.dispose = function() { this.workspace_.getComponentManager().removeComponent('zoomControls'); if (this.svgGroup_) { - Blockly.utils.dom.removeNode(this.svgGroup_); + dom.removeNode(this.svgGroup_); } if (this.onZoomResetWrapper_) { - Blockly.browserEvents.unbind(this.onZoomResetWrapper_); + browserEvents.unbind(this.onZoomResetWrapper_); } if (this.onZoomInWrapper_) { - Blockly.browserEvents.unbind(this.onZoomInWrapper_); + browserEvents.unbind(this.onZoomInWrapper_); } if (this.onZoomOutWrapper_) { - Blockly.browserEvents.unbind(this.onZoomOutWrapper_); + browserEvents.unbind(this.onZoomOutWrapper_); } }; /** * Returns the bounding rectangle of the UI element in pixel units relative to * the Blockly injection div. - * @return {?Blockly.utils.Rect} The UI elements’s bounding box. Null if + * @return {?Rect} The UI elements’s bounding box. Null if * bounding box should be ignored by other UI elements. */ -Blockly.ZoomControls.prototype.getBoundingRectangle = function() { - var height = this.SMALL_SPACING_ + 2 * this.HEIGHT_; +ZoomControls.prototype.getBoundingRectangle = function() { + let height = this.SMALL_SPACING_ + 2 * this.HEIGHT_; if (this.zoomResetGroup_) { height += this.LARGE_SPACING_ + this.HEIGHT_; } - var bottom = this.top_ + height; - var right = this.left_ + this.WIDTH_; - return new Blockly.utils.Rect(this.top_, bottom, this.left_, right); + const bottom = this.top_ + height; + const right = this.left_ + this.WIDTH_; + return new Rect(this.top_, bottom, this.left_, right); }; @@ -247,59 +248,57 @@ Blockly.ZoomControls.prototype.getBoundingRectangle = function() { * It is positioned in the opposite corner to the corner the * categories/toolbox starts at. * @param {!Blockly.MetricsManager.UiMetrics} metrics The workspace metrics. - * @param {!Array} savedPositions List of rectangles that + * @param {!Array} savedPositions List of rectangles that * are already on the workspace. */ -Blockly.ZoomControls.prototype.position = function(metrics, savedPositions) { +ZoomControls.prototype.position = function(metrics, savedPositions) { // Not yet initialized. if (!this.initialized_) { return; } - var cornerPosition = - Blockly.uiPosition.getCornerOppositeToolbox(this.workspace_, metrics); - var height = this.SMALL_SPACING_ + 2 * this.HEIGHT_; + const cornerPosition = + uiPosition.getCornerOppositeToolbox(this.workspace_, metrics); + let height = this.SMALL_SPACING_ + 2 * this.HEIGHT_; if (this.zoomResetGroup_) { height += this.LARGE_SPACING_ + this.HEIGHT_; } - var startRect = Blockly.uiPosition.getStartPositionRect( - cornerPosition, new Blockly.utils.Size(this.WIDTH_, height), - this.MARGIN_HORIZONTAL_, this.MARGIN_VERTICAL_, metrics, - this.workspace_); + const startRect = uiPosition.getStartPositionRect( + cornerPosition, new utils.Size(this.WIDTH_, height), + this.MARGIN_HORIZONTAL_, this.MARGIN_VERTICAL_, metrics, this.workspace_); - var verticalPosition = cornerPosition.vertical; - var bumpDirection = - verticalPosition === Blockly.uiPosition.verticalPosition.TOP ? - Blockly.uiPosition.bumpDirection.DOWN : - Blockly.uiPosition.bumpDirection.UP; - var positionRect = Blockly.uiPosition.bumpPositionRect( + const verticalPosition = cornerPosition.vertical; + const bumpDirection = verticalPosition === uiPosition.verticalPosition.TOP ? + uiPosition.bumpDirection.DOWN : + uiPosition.bumpDirection.UP; + const positionRect = uiPosition.bumpPositionRect( startRect, this.MARGIN_VERTICAL_, bumpDirection, savedPositions); - if (verticalPosition === Blockly.uiPosition.verticalPosition.TOP) { - var zoomInTranslateY = this.SMALL_SPACING_ + this.HEIGHT_; - this.zoomInGroup_.setAttribute('transform', - 'translate(0, ' + zoomInTranslateY + ')'); + if (verticalPosition === uiPosition.verticalPosition.TOP) { + const zoomInTranslateY = this.SMALL_SPACING_ + this.HEIGHT_; + this.zoomInGroup_.setAttribute( + 'transform', 'translate(0, ' + zoomInTranslateY + ')'); if (this.zoomResetGroup_) { - var zoomResetTranslateY = + const zoomResetTranslateY = zoomInTranslateY + this.LARGE_SPACING_ + this.HEIGHT_; - this.zoomResetGroup_.setAttribute('transform', - 'translate(0, ' + zoomResetTranslateY + ')'); + this.zoomResetGroup_.setAttribute( + 'transform', 'translate(0, ' + zoomResetTranslateY + ')'); } } else { - var zoomInTranslateY = this.zoomResetGroup_ ? - this.LARGE_SPACING_ + this.HEIGHT_ : 0; - this.zoomInGroup_.setAttribute('transform', - 'translate(0, ' + zoomInTranslateY + ')'); - var zoomOutTranslateY = + const zoomInTranslateY = + this.zoomResetGroup_ ? this.LARGE_SPACING_ + this.HEIGHT_ : 0; + this.zoomInGroup_.setAttribute( + 'transform', 'translate(0, ' + zoomInTranslateY + ')'); + const zoomOutTranslateY = zoomInTranslateY + this.SMALL_SPACING_ + this.HEIGHT_; - this.zoomOutGroup_.setAttribute('transform', - 'translate(0, ' + zoomOutTranslateY + ')'); + this.zoomOutGroup_.setAttribute( + 'transform', 'translate(0, ' + zoomOutTranslateY + ')'); } this.top_ = positionRect.top; this.left_ = positionRect.left; - this.svgGroup_.setAttribute('transform', - 'translate(' + this.left_ + ',' + this.top_ + ')'); + this.svgGroup_.setAttribute( + 'transform', 'translate(' + this.left_ + ',' + this.top_ + ')'); }; /** @@ -309,48 +308,42 @@ Blockly.ZoomControls.prototype.position = function(metrics, savedPositions) { * instances on the same page. * @private */ -Blockly.ZoomControls.prototype.createZoomOutSvg_ = function(rnd) { +ZoomControls.prototype.createZoomOutSvg_ = function(rnd) { /* This markup will be generated and added to the .svgGroup_: */ - this.zoomOutGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, - {'class': 'blocklyZoom'}, this.svgGroup_); - var clip = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.CLIPPATH, - { - 'id': 'blocklyZoomoutClipPath' + rnd - }, - this.zoomOutGroup_); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { + this.zoomOutGroup_ = + dom.createSvgElement(Svg.G, {'class': 'blocklyZoom'}, this.svgGroup_); + const clip = dom.createSvgElement( + Svg.CLIPPATH, {'id': 'blocklyZoomoutClipPath' + rnd}, this.zoomOutGroup_); + dom.createSvgElement( + Svg.RECT, { 'width': 32, 'height': 32, }, clip); - var zoomoutSvg = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.IMAGE, { - 'width': Blockly.internalConstants.SPRITE.width, - 'height': Blockly.internalConstants.SPRITE.height, + const zoomoutSvg = dom.createSvgElement( + Svg.IMAGE, { + 'width': internalConstants.SPRITE.width, + 'height': internalConstants.SPRITE.height, 'x': -64, 'y': -92, 'clip-path': 'url(#blocklyZoomoutClipPath' + rnd + ')' }, this.zoomOutGroup_); zoomoutSvg.setAttributeNS( - Blockly.utils.dom.XLINK_NS, 'xlink:href', - this.workspace_.options.pathToMedia + - Blockly.internalConstants.SPRITE.url); + dom.XLINK_NS, 'xlink:href', + this.workspace_.options.pathToMedia + internalConstants.SPRITE.url); // Attach listener. - this.onZoomOutWrapper_ = Blockly.browserEvents.conditionalBind( + this.onZoomOutWrapper_ = browserEvents.conditionalBind( this.zoomOutGroup_, 'mousedown', null, this.zoom_.bind(this, -1)); }; @@ -361,48 +354,42 @@ Blockly.ZoomControls.prototype.createZoomOutSvg_ = function(rnd) { * instances on the same page. * @private */ -Blockly.ZoomControls.prototype.createZoomInSvg_ = function(rnd) { +ZoomControls.prototype.createZoomInSvg_ = function(rnd) { /* This markup will be generated and added to the .svgGroup_: - */ - this.zoomInGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, - {'class': 'blocklyZoom'}, this.svgGroup_); - var clip = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.CLIPPATH, - { - 'id': 'blocklyZoominClipPath' + rnd - }, - this.zoomInGroup_); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { + this.zoomInGroup_ = + dom.createSvgElement(Svg.G, {'class': 'blocklyZoom'}, this.svgGroup_); + const clip = dom.createSvgElement( + Svg.CLIPPATH, {'id': 'blocklyZoominClipPath' + rnd}, this.zoomInGroup_); + dom.createSvgElement( + Svg.RECT, { 'width': 32, 'height': 32, }, clip); - var zoominSvg = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.IMAGE, { - 'width': Blockly.internalConstants.SPRITE.width, - 'height': Blockly.internalConstants.SPRITE.height, + const zoominSvg = dom.createSvgElement( + Svg.IMAGE, { + 'width': internalConstants.SPRITE.width, + 'height': internalConstants.SPRITE.height, 'x': -32, 'y': -92, 'clip-path': 'url(#blocklyZoominClipPath' + rnd + ')' }, this.zoomInGroup_); zoominSvg.setAttributeNS( - Blockly.utils.dom.XLINK_NS, 'xlink:href', - this.workspace_.options.pathToMedia + - Blockly.internalConstants.SPRITE.url); + dom.XLINK_NS, 'xlink:href', + this.workspace_.options.pathToMedia + internalConstants.SPRITE.url); // Attach listener. - this.onZoomInWrapper_ = Blockly.browserEvents.conditionalBind( + this.onZoomInWrapper_ = browserEvents.conditionalBind( this.zoomInGroup_, 'mousedown', null, this.zoom_.bind(this, 1)); }; @@ -414,13 +401,13 @@ Blockly.ZoomControls.prototype.createZoomInSvg_ = function(rnd) { * @param {!Event} e A mouse down event. * @private */ -Blockly.ZoomControls.prototype.zoom_ = function(amount, e) { +ZoomControls.prototype.zoom_ = function(amount, e) { this.workspace_.markFocused(); this.workspace_.zoomCenter(amount); this.fireZoomEvent_(); - Blockly.Touch.clearTouchIdentifier(); // Don't block future drags. - e.stopPropagation(); // Don't start a workspace scroll. - e.preventDefault(); // Stop double-clicking from selecting text. + Touch.clearTouchIdentifier(); // Don't block future drags. + e.stopPropagation(); // Don't start a workspace scroll. + e.preventDefault(); // Stop double-clicking from selecting text. }; /** @@ -430,47 +417,37 @@ Blockly.ZoomControls.prototype.zoom_ = function(amount, e) { * instances on the same page. * @private */ -Blockly.ZoomControls.prototype.createZoomResetSvg_ = function(rnd) { +ZoomControls.prototype.createZoomResetSvg_ = function(rnd) { /* This markup will be generated and added to the .svgGroup_: - */ - this.zoomResetGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, - {'class': 'blocklyZoom'}, this.svgGroup_); - var clip = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.CLIPPATH, - { - 'id': 'blocklyZoomresetClipPath' + rnd - }, + this.zoomResetGroup_ = + dom.createSvgElement(Svg.G, {'class': 'blocklyZoom'}, this.svgGroup_); + const clip = dom.createSvgElement( + Svg.CLIPPATH, {'id': 'blocklyZoomresetClipPath' + rnd}, this.zoomResetGroup_); - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { - 'width': 32, - 'height': 32 - }, - clip); - var zoomresetSvg = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.IMAGE, { - 'width': Blockly.internalConstants.SPRITE.width, - 'height': Blockly.internalConstants.SPRITE.height, + dom.createSvgElement(Svg.RECT, {'width': 32, 'height': 32}, clip); + const zoomresetSvg = dom.createSvgElement( + Svg.IMAGE, { + 'width': internalConstants.SPRITE.width, + 'height': internalConstants.SPRITE.height, 'y': -92, 'clip-path': 'url(#blocklyZoomresetClipPath' + rnd + ')' }, this.zoomResetGroup_); zoomresetSvg.setAttributeNS( - Blockly.utils.dom.XLINK_NS, 'xlink:href', - this.workspace_.options.pathToMedia + - Blockly.internalConstants.SPRITE.url); + dom.XLINK_NS, 'xlink:href', + this.workspace_.options.pathToMedia + internalConstants.SPRITE.url); // Attach event listeners. - this.onZoomResetWrapper_ = Blockly.browserEvents.conditionalBind( + this.onZoomResetWrapper_ = browserEvents.conditionalBind( this.zoomResetGroup_, 'mousedown', null, this.resetZoom_.bind(this)); }; @@ -479,55 +456,55 @@ Blockly.ZoomControls.prototype.createZoomResetSvg_ = function(rnd) { * @param {!Event} e A mouse down event. * @private */ -Blockly.ZoomControls.prototype.resetZoom_ = function(e) { +ZoomControls.prototype.resetZoom_ = function(e) { this.workspace_.markFocused(); // zoom is passed amount and computes the new scale using the formula: // targetScale = currentScale * Math.pow(speed, amount) - var targetScale = this.workspace_.options.zoomOptions.startScale; - var currentScale = this.workspace_.scale; - var speed = this.workspace_.options.zoomOptions.scaleSpeed; + const targetScale = this.workspace_.options.zoomOptions.startScale; + const currentScale = this.workspace_.scale; + const speed = this.workspace_.options.zoomOptions.scaleSpeed; // To compute amount: // amount = log(speed, (targetScale / currentScale)) // Math.log computes natural logarithm (ln), to change the base, use formula: // log(base, value) = ln(value) / ln(base) - var amount = Math.log(targetScale / currentScale) / Math.log(speed); + const amount = Math.log(targetScale / currentScale) / Math.log(speed); this.workspace_.beginCanvasTransition(); this.workspace_.zoomCenter(amount); this.workspace_.scrollCenter(); setTimeout(this.workspace_.endCanvasTransition.bind(this.workspace_), 500); this.fireZoomEvent_(); - Blockly.Touch.clearTouchIdentifier(); // Don't block future drags. - e.stopPropagation(); // Don't start a workspace scroll. - e.preventDefault(); // Stop double-clicking from selecting text. + Touch.clearTouchIdentifier(); // Don't block future drags. + e.stopPropagation(); // Don't start a workspace scroll. + e.preventDefault(); // Stop double-clicking from selecting text. }; /** * Fires a zoom control UI event. * @private */ -Blockly.ZoomControls.prototype.fireZoomEvent_ = function() { - var uiEvent = new (Blockly.Events.get(Blockly.Events.CLICK))( - null, this.workspace_.id, 'zoom_controls'); - Blockly.Events.fire(uiEvent); +ZoomControls.prototype.fireZoomEvent_ = function() { + const uiEvent = + new (Events.get(Events.CLICK))(null, this.workspace_.id, 'zoom_controls'); + Events.fire(uiEvent); }; /** * CSS for zoom controls. See css.js for use. */ -Blockly.Css.register([ - /* eslint-disable indent */ - '.blocklyZoom>image, .blocklyZoom>svg>image {', - 'opacity: .4;', - '}', +Css.register([ + `.blocklyZoom>image, .blocklyZoom>svg>image { + opacity: .4; +}`, - '.blocklyZoom>image:hover, .blocklyZoom>svg>image:hover {', - 'opacity: .6;', - '}', + `.blocklyZoom>image:hover, .blocklyZoom>svg>image:hover { + opacity: .6; +}`, - '.blocklyZoom>image:active, .blocklyZoom>svg>image:active {', - 'opacity: .8;', - '}' - /* eslint-enable indent */ + `.blocklyZoom>image:active, .blocklyZoom>svg>image:active { + 'opacity: .8; +}` ]); + +exports = ZoomControls; diff --git a/scripts/goog_module/convert-file.sh b/scripts/goog_module/convert-file.sh index 8b6bdfc6f..4d6c13345 100755 --- a/scripts/goog_module/convert-file.sh +++ b/scripts/goog_module/convert-file.sh @@ -1,5 +1,41 @@ #!/bin/bash +# This file makes extensive use of perl for the purpose of extracting and +# replacing string (regex) patterns in a way that is both GNU and macOS +# compatible. +# +# Common perl flags used (also described at https://perldoc.perl.org/perlrun): +# -e : Used to execute perl programs on the command line +# -p : Assumes an input loop around script. Prints every processed line. +# -n : Assumes an input loop around script. Does not print every line. +# -i : Used for in-place editing. Used in commands for find/replace. +# -l[octnum] : Assigns the output record separator "$/" as an octal number. If +# octnum is not present, sets output record separator to the current +# value of the input record separator "$\". +# +# Common perl commands found: +# 1. perl -pi -e 's/regex/replacement/modifiers' +# This command does an in-place search-and-replace. The global ("/g") modifier +# causes it to replace all occurrences, rather than only the first match. +# 2. perl -ne 'print m/regex/modifiers' +# This command returns a string containing the regex match (designated by the +# capture group "()" in the regex). This will return the first match, unless +# the global modifier is specified, in which case, it will return all matches. +# If this command is used without a capture group it returns true or false (in +# the form a truthy or falsy value). +# 3. perl -nle 'print $& while m{regex}modifiers' +# Similar to (2), but returns regex matches separated by newlines. +# The "m{regex}modifiers" is equivalent to "m/regex/modifiers" syntax. +# +# Additional information on regex: +# This script makes use of some advanced regex syntax such as "capture groups" +# and "lookaround assertions". +# Additionally, characters are escaped from regex with a backslash "\". +# Single quotes need to be escaped in both regex and the string, resulting in +# '\'' being used to represent a single quote character. +# For a reference to syntax of regular expressions in Perl, see: +# https://perldoc.perl.org/perlre + ####################################### # Logging functions. ####################################### @@ -89,6 +125,64 @@ commit-step() { success "created commit with message: \"${message}\"" } +####################################### +# Extracts a list of properties that are accessed on the specified module name. +# Excludes any matches +# Arguments: +# The module name to find properties accessed for. +# The modules required by the specified module as a single string. +# The filepath to extract requires from. +# Optional: The top-level module. +# Outputs: +# Writes list of properties to stdout as items separated by spaces. +####################################### +getPropertiesAccessed() { + local module_name="$1" + local requires="$2" + local filepath="$3" + local top_module_name="$4" + # Get any strings that follow "$module_name.", excluding matches for + # "$module_name.prototype" and remove list item duplicates (sort -u). + local properties_accessed=$(perl -nle 'print $& while m{(?<='"${module_name}"'\.)(?!prototype)\w+}g' "${filepath}" | sort -u) + + # Get a list of any requires that are a child of $module_name. + # Ex: Blockly.utils.dom is a child of Blockly.utils, this would return "dom" + local requires_overlap=$(echo "${requires}" | perl -nle 'print $& while m{(?<='"${module_name}"'\.)\w+}g') + # Detect if there was any overlap. + if [[ -n "${requires_overlap}" ]]; then + while read -r requires_overlap_prop; do + # Removes any instances of $requires_overlap_prop. Includes regex + # lookarounds so that it does not simply match string contains. + # Ex: if $requires_overlap is "Svg", then it would update the list + # "isTargetInput mouseToSvg noEvent Svg" to + # "isTargetInput mouseToSvg noEvent " (note that mouseToSvg is unchanged). + properties_accessed=$(echo "${properties_accessed}" | perl -pe 's/(? |-s ]" echo " -h Display help and exit" - echo " -c Create a commit for the specified step [2-4]" - echo " -s Run the specified step [1-4]" + echo " -c Create a commit for the specified step [1-4]" + echo " -s Run the specified step [2-4]" } ####################################### diff --git a/tests/deps.js b/tests/deps.js index d27093d4d..1bb9bf742 100644 --- a/tests/deps.js +++ b/tests/deps.js @@ -54,23 +54,23 @@ goog.addDependency('../../core/field_checkbox.js', ['Blockly.FieldCheckbox'], [' goog.addDependency('../../core/field_colour.js', ['Blockly.FieldColour'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.IdGenerator', 'Blockly.utils.KeyCodes', 'Blockly.utils.Size', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/field_dropdown.js', ['Blockly.FieldDropdown'], ['Blockly.DropDownDiv', 'Blockly.Field', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/field_image.js', ['Blockly.FieldImage'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/field_label.js', ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/field_label.js', ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/field_label_serializable.js', ['Blockly.FieldLabelSerializable'], ['Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/field_multilineinput.js', ['Blockly.FieldMultilineInput'], ['Blockly.Css', 'Blockly.Field', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/field_number.js', ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'Blockly.fieldRegistry', 'Blockly.utils.aria', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/field_registry.js', ['Blockly.fieldRegistry'], ['Blockly.registry'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/field_textinput.js', ['Blockly.FieldTextInput'], ['Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/field_textinput.js', ['Blockly.FieldTextInput'], ['Blockly', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/field_variable.js', ['Blockly.FieldVariable'], ['Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml', 'Blockly.fieldRegistry', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.IFlyout', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox', 'Blockly.utils.xml']); -goog.addDependency('../../core/flyout_button.js', ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es5'}); +goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly', 'Blockly.Block', 'Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutButton', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.IFlyout', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/flyout_button.js', ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/flyout_vertical.js', ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox']); +goog.addDependency('../../core/flyout_vertical.js', ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly', 'Blockly.internalConstants', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate']); +goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Grid', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceSvg', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/input.js', ['Blockly.Input'], ['Blockly.Connection', 'Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.inputTypes'], {'lang': 'es5'}); +goog.addDependency('../../core/input.js', ['Blockly.Input'], ['Blockly.Connection', 'Blockly.FieldLabel', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/input_types.js', ['Blockly.inputTypes'], ['Blockly.connectionTypes']); goog.addDependency('../../core/insertion_marker_manager.js', ['Blockly.InsertionMarkerManager'], ['Blockly.ComponentManager', 'Blockly.Events', 'Blockly.blockAnimations', 'Blockly.connectionTypes', 'Blockly.internalConstants'], {'lang': 'es5'}); goog.addDependency('../../core/interfaces/i_ast_node_location.js', ['Blockly.IASTNodeLocation'], [], {'lang': 'es6', 'module': 'goog'}); @@ -102,31 +102,31 @@ goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable' goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], ['Blockly.IRegistrable'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/interfaces/i_toolbox_item.js', ['Blockly.IToolboxItem'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/internal_constants.js', ['Blockly.internalConstants'], ['Blockly.connectionTypes'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/keyboard_nav/ast_node.js', ['Blockly.ASTNode'], ['Blockly.connectionTypes', 'Blockly.utils.Coordinate'], {'lang': 'es5'}); +goog.addDependency('../../core/keyboard_nav/ast_node.js', ['Blockly.ASTNode'], ['Blockly.connectionTypes', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/keyboard_nav/basic_cursor.js', ['Blockly.BasicCursor'], ['Blockly.ASTNode', 'Blockly.Cursor', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/keyboard_nav/cursor.js', ['Blockly.Cursor'], ['Blockly.ASTNode', 'Blockly.Marker', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], ['Blockly.ASTNode']); +goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/keyboard_nav/tab_navigate_cursor.js', ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], ['Blockly.Cursor', 'Blockly.Marker']); +goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/menu.js', ['Blockly.Menu'], ['Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/menuitem.js', ['Blockly.MenuItem'], ['Blockly.utils.IdGenerator', 'Blockly.utils.aria', 'Blockly.utils.dom']); goog.addDependency('../../core/metrics_manager.js', ['Blockly.FlyoutMetricsManager', 'Blockly.MetricsManager'], ['Blockly.IMetricsManager', 'Blockly.registry', 'Blockly.utils.Size', 'Blockly.utils.toolbox'], {'lang': 'es5'}); goog.addDependency('../../core/msg.js', ['Blockly.Msg'], ['Blockly.utils.global']); -goog.addDependency('../../core/mutator.js', ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Options', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml']); +goog.addDependency('../../core/mutator.js', ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Options', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.internalConstants', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/names.js', ['Blockly.Names'], ['Blockly.Msg', 'Blockly.internalConstants']); goog.addDependency('../../core/options.js', ['Blockly.Options'], ['Blockly.Theme', 'Blockly.Themes.Classic', 'Blockly.registry', 'Blockly.utils.IdGenerator', 'Blockly.utils.Metrics', 'Blockly.utils.toolbox']); goog.addDependency('../../core/positionable_helpers.js', ['Blockly.uiPosition'], ['Blockly.Scrollbar', 'Blockly.utils.Rect', 'Blockly.utils.toolbox']); goog.addDependency('../../core/procedures.js', ['Blockly.Procedures'], ['Blockly.Blocks', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.Names', 'Blockly.Workspace', 'Blockly.Xml', 'Blockly.internalConstants', 'Blockly.utils.xml']); -goog.addDependency('../../core/registry.js', ['Blockly.registry'], []); -goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.connectionTypes', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/registry.js', ['Blockly.registry'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.Events', 'Blockly.connectionTypes', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/renderers/common/block_rendering.js', ['Blockly.blockRendering'], ['Blockly.registry']); -goog.addDependency('../../core/renderers/common/constants.js', ['Blockly.blockRendering.ConstantProvider'], ['Blockly.connectionTypes', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent'], {'lang': 'es5'}); +goog.addDependency('../../core/renderers/common/constants.js', ['Blockly.blockRendering.ConstantProvider'], ['Blockly.connectionTypes', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/renderers/common/debugger.js', ['Blockly.blockRendering.Debug'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.connectionTypes', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'}); goog.addDependency('../../core/renderers/common/drawer.js', ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.svgPaths'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/renderers/common/i_path_object.js', ['Blockly.blockRendering.IPathObject'], []); goog.addDependency('../../core/renderers/common/info.js', ['Blockly.blockRendering.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.Icon', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/renderers/common/marker_svg.js', ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode', 'Blockly.Events', 'Blockly.Events.MarkerMove', 'Blockly.connectionTypes', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/renderers/common/path_object.js', ['Blockly.blockRendering.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.IPathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom']); +goog.addDependency('../../core/renderers/common/path_object.js', ['Blockly.blockRendering.PathObject'], ['Blockly.blockRendering.IPathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/renderers/common/renderer.js', ['Blockly.blockRendering.Renderer'], ['Blockly.IRegistrable', 'Blockly.InsertionMarkerManager', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Debug', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.IPathObject', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.RenderInfo', 'Blockly.connectionTypes']); goog.addDependency('../../core/renderers/geras/constants.js', ['Blockly.geras.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object'], {'lang': 'es5'}); goog.addDependency('../../core/renderers/geras/drawer.js', ['Blockly.geras.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.geras.Highlighter', 'Blockly.geras.RenderInfo', 'Blockly.utils.object', 'Blockly.utils.svgPaths']); @@ -160,13 +160,13 @@ goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Ren goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']); goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar', 'Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Svg', 'Blockly.utils.dom']); goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.utils.KeyCodes']); -goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object']); +goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/theme/classic.js', ['Blockly.Themes.Classic'], ['Blockly.Theme']); goog.addDependency('../../core/theme/zelos.js', ['Blockly.Themes.Zelos'], ['Blockly.Theme']); -goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Blockly.Theme']); +goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/toolbox/category.js', ['Blockly.ToolboxCategory'], ['Blockly.ISelectableToolboxItem', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/toolbox/collapsible_category.js', ['Blockly.CollapsibleToolboxCategory'], ['Blockly.ICollapsibleToolboxItem', 'Blockly.ToolboxCategory', 'Blockly.ToolboxItem', 'Blockly.ToolboxSeparator', 'Blockly.registry', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox']); +goog.addDependency('../../core/toolbox/collapsible_category.js', ['Blockly.CollapsibleToolboxCategory'], ['Blockly.ICollapsibleToolboxItem', 'Blockly.ToolboxCategory', 'Blockly.ToolboxSeparator', 'Blockly.registry', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/toolbox/separator.js', ['Blockly.ToolboxSeparator'], ['Blockly.IToolboxItem', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils.dom'], {'lang': 'es5'}); goog.addDependency('../../core/toolbox/toolbox.js', ['Blockly.Toolbox'], ['Blockly.BlockSvg', 'Blockly.CollapsibleToolboxCategory', 'Blockly.ComponentManager', 'Blockly.Css', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.ToolboxItemSelect', 'Blockly.IAutoHideable', 'Blockly.IKeyboardAccessible', 'Blockly.IStyleable', 'Blockly.IToolbox', 'Blockly.Options', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'}); goog.addDependency('../../core/toolbox/toolbox_item.js', ['Blockly.ToolboxItem'], ['Blockly.IToolboxItem']); @@ -179,7 +179,7 @@ goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], []); goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/coordinate.js', ['Blockly.utils.Coordinate'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/deprecation.js', ['Blockly.utils.deprecation'], [], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/utils/dom.js', ['Blockly.utils.dom'], ['Blockly.utils.Svg', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/utils/dom.js', ['Blockly.utils.dom'], ['Blockly.utils.Svg', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/global.js', ['Blockly.utils.global'], []); goog.addDependency('../../core/utils/idgenerator.js', ['Blockly.utils.IdGenerator'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/keycodes.js', ['Blockly.utils.KeyCodes'], [], {'lang': 'es6', 'module': 'goog'}); @@ -187,7 +187,7 @@ goog.addDependency('../../core/utils/math.js', ['Blockly.utils.math'], [], {'lan goog.addDependency('../../core/utils/metrics.js', ['Blockly.utils.Metrics'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/object.js', ['Blockly.utils.object'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/rect.js', ['Blockly.utils.Rect'], [], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/utils/size.js', ['Blockly.utils.Size'], []); +goog.addDependency('../../core/utils/size.js', ['Blockly.utils.Size'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/string.js', ['Blockly.utils.string'], []); goog.addDependency('../../core/utils/style.js', ['Blockly.utils.style'], ['Blockly.utils.Coordinate', 'Blockly.utils.Size'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/utils/svg.js', ['Blockly.utils.Svg'], []); @@ -196,20 +196,19 @@ goog.addDependency('../../core/utils/toolbox.js', ['Blockly.utils.toolbox'], ['B goog.addDependency('../../core/utils/useragent.js', ['Blockly.utils.userAgent'], ['Blockly.utils.global']); goog.addDependency('../../core/utils/xml.js', ['Blockly.utils.xml'], []); goog.addDependency('../../core/variable_map.js', ['Blockly.VariableMap'], ['Blockly.Events', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename', 'Blockly.Msg', 'Blockly.utils', 'Blockly.utils.object']); -goog.addDependency('../../core/variable_model.js', ['Blockly.VariableModel'], ['Blockly.Events', 'Blockly.Events.VarCreate', 'Blockly.utils']); +goog.addDependency('../../core/variable_model.js', ['Blockly.VariableModel'], ['Blockly.Events', 'Blockly.Events.VarCreate', 'Blockly.utils'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/variables.js', ['Blockly.Variables'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Xml', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.xml']); goog.addDependency('../../core/variables_dynamic.js', ['Blockly.VariablesDynamic'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.utils.xml']); -goog.addDependency('../../core/warning.js', ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/warning.js', ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/widgetdiv.js', ['Blockly.WidgetDiv'], ['Blockly.utils.dom']); goog.addDependency('../../core/workspace.js', ['Blockly.Workspace'], ['Blockly.ConnectionChecker', 'Blockly.Events', 'Blockly.IASTNodeLocation', 'Blockly.Options', 'Blockly.VariableMap', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.math']); -goog.addDependency('../../core/workspace_audio.js', ['Blockly.WorkspaceAudio'], ['Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es5'}); -goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.xml']); -goog.addDependency('../../core/workspace_comment_render_svg.js', ['Blockly.WorkspaceCommentSvg.render'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly.Css', 'Blockly.Events', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.WorkspaceComment', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']); +goog.addDependency('../../core/workspace_audio.js', ['Blockly.WorkspaceAudio'], ['Blockly.internalConstants', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.xml'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly', 'Blockly.ContextMenu', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.IBoundedElement', 'Blockly.IBubble', 'Blockly.ICopyable', 'Blockly.Touch', 'Blockly.WorkspaceComment', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/workspace_drag_surface_svg.js', ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom']); goog.addDependency('../../core/workspace_dragger.js', ['Blockly.WorkspaceDragger'], ['Blockly.utils.Coordinate']); goog.addDependency('../../core/workspace_svg.js', ['Blockly.WorkspaceSvg'], ['Blockly.BlockSvg', 'Blockly.ComponentManager', 'Blockly.ConnectionDB', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.ThemeChange', 'Blockly.Events.ViewportChange', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.IASTNodeLocationSvg', 'Blockly.MarkerManager', 'Blockly.MetricsManager', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ThemeManager', 'Blockly.Themes.Classic', 'Blockly.TouchGesture', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'}); goog.addDependency('../../core/xml.js', ['Blockly.Xml'], ['Blockly.Events', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.dom', 'Blockly.utils.xml']); -goog.addDependency('../../core/zoom_controls.js', ['Blockly.ZoomControls'], ['Blockly.ComponentManager', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.IPositionable', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'}); +goog.addDependency('../../core/zoom_controls.js', ['Blockly.ZoomControls'], ['Blockly.ComponentManager', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.IPositionable', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('base.js', [], []); diff --git a/tests/playground.html b/tests/playground.html index 11179a0db..b53e76ea8 100644 --- a/tests/playground.html +++ b/tests/playground.html @@ -71,7 +71,6 @@