diff --git a/.eslintrc.json b/.eslintrc.json index 9d74291da..28766db11 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,29 +2,6 @@ "rules": { "curly": ["error"], "eol-last": ["error"], - // Blockly/Google use 2-space indents. - // Blockly/Google uses +4 space indents for line continuations. - // Ignore default rules for ternary expressions. - "indent": [ - "error", 2, - { - "SwitchCase": 1, - "MemberExpression": 2, - "ObjectExpression": 1, - "FunctionDeclaration": { - "body": 1, - "parameters": 2 - }, - "FunctionExpression": { - "body": 1, - "parameters": 2 - }, - "CallExpression": { - "arguments": 2 - }, - "ignoredNodes": ["ConditionalExpression"] - } - ], "keyword-spacing": ["error"], "linebreak-style": ["error", "unix"], "max-len": [ @@ -39,7 +16,7 @@ ], "no-trailing-spaces": ["error", { "skipBlankLines": true }], "no-unused-vars": [ - "error", + "warn", { "args": "after-used", // Ignore vars starting with an underscore. @@ -48,7 +25,6 @@ "argsIgnorePattern": "^_" } ], - "no-use-before-define": ["error"], // Blockly uses for exporting symbols. no-self-assign added in eslint 5. "no-self-assign": ["off"], // Blockly uses single quotes except for JSON blobs, which must use double quotes. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f00730990..9a7d2b859 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,3 +41,19 @@ jobs: env: CI: true + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js 16.x + uses: actions/setup-node@v1 + with: + node-version: 16.x + + - name: Npm Install + run: npm install + + - name: Lint + run: npm run lint diff --git a/.github/workflows/tag_module_cleanup.yml b/.github/workflows/tag_module_cleanup.yml new file mode 100644 index 000000000..94e7ec692 --- /dev/null +++ b/.github/workflows/tag_module_cleanup.yml @@ -0,0 +1,35 @@ +# For new pull requests against the goog_module branch, adds the 'type: cleanup' +# label and sets the milestone to q3 2021 release. + +name: Tag module cleanup + +# Trigger on pull requests against goog_module branch only +# Uses pull_request_target to get write permissions so that it can write labels. +on: + pull_request_target: + branches: + - goog_module + +jobs: + tag-module-cleanup: + + # Add the type: cleanup label + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@a3e7071a34d7e1f219a8a4de9a5e0a34d1ee1293 + with: + script: | + // 2021 q3 release milestone. + // https://github.com/google/blockly/milestone/18 + const milestoneNumber = 18; + // Note that pull requests are accessed through the issues API. + const issuesUpdateParams = { + owner: context.repo.owner, + repo: context.repo.repo, + // Adds the milestone + milestone: milestoneNumber, + issue_number: context.issue.number, + // Sets the labels + labels: ['type: cleanup'] + } + await github.issues.update(issuesUpdateParams) diff --git a/.github/workflows/update_metadata.yml b/.github/workflows/update_metadata.yml new file mode 100644 index 000000000..82a36230f --- /dev/null +++ b/.github/workflows/update_metadata.yml @@ -0,0 +1,40 @@ +# This workflow updates the check_metadata.sh script, which compares the current +# size of build artifacts against their size in the previous version of Blockly. + +name: Update Metadata + +on: [workflow_dispatch] + +jobs: + update-metadata: + runs-on: ubuntu-latest + + steps: + - name: Check Out Blockly + uses: actions/checkout@v2 + with: + ref: 'develop' + + - name: Use Node.js 16.x + uses: actions/setup-node@v1 + with: + node-version: 16.x + + - name: Build Blockly + run: npm run build:compressed + + - name: Build Blockly blocks + run: npm run build:blocks + + - name: Update Metadata + run: source ./tests/scripts/update_metadata.sh + + - name: Create Pull Request + uses: peter-evans/create-pull-request@9825ae65b1cb54b543b938503728b432a0176d29 + with: + commit-message: Update build artifact sizes in check_metadata.sh + delete-branch: true + title: Update build artifact sizes in check_metadata.sh + + - name: View Pull Request + run: echo "View Pull Request - ${{ steps.cpr.outputs.pull-request-url }}" \ No newline at end of file diff --git a/core/block_animations.js b/core/block_animations.js index 82e2516b1..27926002e 100644 --- a/core/block_animations.js +++ b/core/block_animations.js @@ -10,50 +10,49 @@ */ 'use strict'; -goog.provide('Blockly.blockAnimations'); +goog.module('Blockly.blockAnimations'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.Svg'); - -goog.requireType('Blockly.BlockSvg'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +const Svg = goog.require('Blockly.utils.Svg'); +const dom = goog.require('Blockly.utils.dom'); /** * PID of disconnect UI animation. There can only be one at a time. * @type {number} - * @private */ -Blockly.blockAnimations.disconnectPid_ = 0; +let disconnectPid = 0; /** * SVG group of wobbling block. There can only be one at a time. * @type {Element} - * @private */ -Blockly.blockAnimations.disconnectGroup_ = null; +let disconnectGroup = null; /** * Play some UI effects (sound, animation) when disposing of a block. - * @param {!Blockly.BlockSvg} block The block being disposed of. - * @package + * @param {!BlockSvg} block The block being disposed of. */ -Blockly.blockAnimations.disposeUiEffect = function(block) { - var workspace = block.workspace; - var svgGroup = block.getSvgRoot(); +const disposeUiEffect = function(block) { + const workspace = block.workspace; + const svgGroup = block.getSvgRoot(); workspace.getAudioManager().play('delete'); - var xy = workspace.getSvgXY(svgGroup); + const xy = workspace.getSvgXY(svgGroup); // Deeply clone the current block. - var clone = svgGroup.cloneNode(true); + const clone = svgGroup.cloneNode(true); clone.translateX_ = xy.x; clone.translateY_ = xy.y; clone.setAttribute('transform', 'translate(' + xy.x + ',' + xy.y + ')'); workspace.getParentSvg().appendChild(clone); clone.bBox_ = clone.getBBox(); // Start the animation. - Blockly.blockAnimations.disposeUiStep_(clone, workspace.RTL, new Date, - workspace.scale); + disposeUiStep(clone, workspace.RTL, new Date, workspace.scale); }; +/** @package */ +exports.disposeUiEffect = disposeUiEffect; /** * Animate a cloned block and eventually dispose of it. @@ -63,40 +62,38 @@ Blockly.blockAnimations.disposeUiEffect = function(block) { * @param {boolean} rtl True if RTL, false if LTR. * @param {!Date} start Date of animation's start. * @param {number} workspaceScale Scale of workspace. - * @private */ -Blockly.blockAnimations.disposeUiStep_ = function(clone, rtl, start, - workspaceScale) { - var ms = new Date - start; - var percent = ms / 150; +const disposeUiStep = function(clone, rtl, start, workspaceScale) { + const ms = new Date - start; + const percent = ms / 150; if (percent > 1) { - Blockly.utils.dom.removeNode(clone); + dom.removeNode(clone); } else { - var x = clone.translateX_ + + const x = clone.translateX_ + (rtl ? -1 : 1) * clone.bBox_.width * workspaceScale / 2 * percent; - var y = clone.translateY_ + clone.bBox_.height * workspaceScale * percent; - var scale = (1 - percent) * workspaceScale; - clone.setAttribute('transform', 'translate(' + x + ',' + y + ')' + - ' scale(' + scale + ')'); - setTimeout(Blockly.blockAnimations.disposeUiStep_, 10, clone, rtl, start, - workspaceScale); + const y = clone.translateY_ + clone.bBox_.height * workspaceScale * percent; + const scale = (1 - percent) * workspaceScale; + clone.setAttribute( + 'transform', + 'translate(' + x + ',' + y + ')' + + ' scale(' + scale + ')'); + setTimeout(disposeUiStep, 10, clone, rtl, start, workspaceScale); } }; /** * Play some UI effects (sound, ripple) after a connection has been established. - * @param {!Blockly.BlockSvg} block The block being connected. - * @package + * @param {!BlockSvg} block The block being connected. */ -Blockly.blockAnimations.connectionUiEffect = function(block) { - var workspace = block.workspace; - var scale = workspace.scale; +const connectionUiEffect = function(block) { + const workspace = block.workspace; + const scale = workspace.scale; workspace.getAudioManager().play('click'); if (scale < 1) { return; // Too small to care about visual effects. } // Determine the absolute coordinates of the inferior block. - var xy = workspace.getSvgXY(block.getSvgRoot()); + const xy = workspace.getSvgXY(block.getSvgRoot()); // Offset the coordinates based on the two connection types, fix scale. if (block.outputConnection) { xy.x += (block.RTL ? 3 : -3) * scale; @@ -105,9 +102,8 @@ Blockly.blockAnimations.connectionUiEffect = function(block) { xy.x += (block.RTL ? -23 : 23) * scale; xy.y += 3 * scale; } - var ripple = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.CIRCLE, - { + const ripple = dom.createSvgElement( + Svg.CIRCLE, { 'cx': xy.x, 'cy': xy.y, 'r': 0, @@ -117,89 +113,88 @@ Blockly.blockAnimations.connectionUiEffect = function(block) { }, workspace.getParentSvg()); // Start the animation. - Blockly.blockAnimations.connectionUiStep_(ripple, new Date, scale); + connectionUiStep(ripple, new Date, scale); }; +/** @package */ +exports.connectionUiEffect = connectionUiEffect; /** * Expand a ripple around a connection. * @param {!SVGElement} ripple Element to animate. * @param {!Date} start Date of animation's start. * @param {number} scale Scale of workspace. - * @private */ -Blockly.blockAnimations.connectionUiStep_ = function(ripple, start, scale) { - var ms = new Date - start; - var percent = ms / 150; +const connectionUiStep = function(ripple, start, scale) { + const ms = new Date - start; + const percent = ms / 150; if (percent > 1) { - Blockly.utils.dom.removeNode(ripple); + dom.removeNode(ripple); } else { ripple.setAttribute('r', percent * 25 * scale); ripple.style.opacity = 1 - percent; - Blockly.blockAnimations.disconnectPid_ = setTimeout( - Blockly.blockAnimations.connectionUiStep_, 10, ripple, start, scale); + disconnectPid = setTimeout(connectionUiStep, 10, ripple, start, scale); } }; /** * Play some UI effects (sound, animation) when disconnecting a block. - * @param {!Blockly.BlockSvg} block The block being disconnected. - * @package + * @param {!BlockSvg} block The block being disconnected. */ -Blockly.blockAnimations.disconnectUiEffect = function(block) { +const disconnectUiEffect = function(block) { block.workspace.getAudioManager().play('disconnect'); if (block.workspace.scale < 1) { return; // Too small to care about visual effects. } // Horizontal distance for bottom of block to wiggle. - var DISPLACEMENT = 10; + const DISPLACEMENT = 10; // Scale magnitude of skew to height of block. - var height = block.getHeightWidth().height; - var magnitude = Math.atan(DISPLACEMENT / height) / Math.PI * 180; + const height = block.getHeightWidth().height; + let magnitude = Math.atan(DISPLACEMENT / height) / Math.PI * 180; if (!block.RTL) { magnitude *= -1; } // Start the animation. - Blockly.blockAnimations.disconnectUiStep_( - block.getSvgRoot(), magnitude, new Date); + disconnectUiStep(block.getSvgRoot(), magnitude, new Date); }; +/** @package */ +exports.disconnectUiEffect = disconnectUiEffect; + /** * Animate a brief wiggle of a disconnected block. * @param {!SVGElement} group SVG element to animate. * @param {number} magnitude Maximum degrees skew (reversed for RTL). * @param {!Date} start Date of animation's start. - * @private */ -Blockly.blockAnimations.disconnectUiStep_ = function(group, magnitude, start) { - var DURATION = 200; // Milliseconds. - var WIGGLES = 3; // Half oscillations. +const disconnectUiStep = function(group, magnitude, start) { + const DURATION = 200; // Milliseconds. + const WIGGLES = 3; // Half oscillations. - var ms = new Date - start; - var percent = ms / DURATION; + const ms = new Date - start; + const percent = ms / DURATION; if (percent > 1) { group.skew_ = ''; } else { - var skew = Math.round( + const skew = Math.round( Math.sin(percent * Math.PI * WIGGLES) * (1 - percent) * magnitude); group.skew_ = 'skewX(' + skew + ')'; - Blockly.blockAnimations.disconnectGroup_ = group; - Blockly.blockAnimations.disconnectPid_ = - setTimeout(Blockly.blockAnimations.disconnectUiStep_, 10, group, - magnitude, start); + disconnectGroup = group; + disconnectPid = setTimeout(disconnectUiStep, 10, group, magnitude, start); } group.setAttribute('transform', group.translate_ + group.skew_); }; /** * Stop the disconnect UI animation immediately. - * @package */ -Blockly.blockAnimations.disconnectUiStop = function() { - if (Blockly.blockAnimations.disconnectGroup_) { - clearTimeout(Blockly.blockAnimations.disconnectPid_); - var group = Blockly.blockAnimations.disconnectGroup_; +const disconnectUiStop = function() { + if (disconnectGroup) { + clearTimeout(disconnectPid); + const group = disconnectGroup; group.skew_ = ''; group.setAttribute('transform', group.translate_); - Blockly.blockAnimations.disconnectGroup_ = null; + disconnectGroup = null; } }; +/** @package */ +exports.disconnectUiStop = disconnectUiStop; diff --git a/core/block_drag_surface.js b/core/block_drag_surface.js index b2a2cda0f..2b911ef09 100644 --- a/core/block_drag_surface.js +++ b/core/block_drag_surface.js @@ -15,11 +15,13 @@ 'use strict'; -goog.provide('Blockly.BlockDragSurfaceSvg'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.Svg'); +goog.module('Blockly.BlockDragSurfaceSvg'); +goog.module.declareLegacyNamespace(); + +const Coordinate = goog.require('Blockly.utils.Coordinate'); +const {G, SVG} = goog.require('Blockly.utils.Svg'); +const {createSvgElement, HTML_NS, setCssTransform, SVG_NS, XLINK_NS} = goog.require('Blockly.utils.dom'); +const {getRelativeXY} = goog.require('Blockly.utils'); /** @@ -28,7 +30,7 @@ goog.require('Blockly.utils.Svg'); * @param {!Element} container Containing element. * @constructor */ -Blockly.BlockDragSurfaceSvg = function(container) { +const BlockDragSurfaceSvg = function(container) { /** * @type {!Element} * @private @@ -38,11 +40,11 @@ Blockly.BlockDragSurfaceSvg = function(container) { }; /** - * The SVG drag surface. Set once by Blockly.BlockDragSurfaceSvg.createDom. + * The SVG drag surface. Set once by BlockDragSurfaceSvg.createDom. * @type {?SVGElement} * @private */ -Blockly.BlockDragSurfaceSvg.prototype.SVG_ = null; +BlockDragSurfaceSvg.prototype.SVG_ = null; /** * This is where blocks live while they are being dragged if the drag surface @@ -50,14 +52,14 @@ Blockly.BlockDragSurfaceSvg.prototype.SVG_ = null; * @type {?SVGElement} * @private */ -Blockly.BlockDragSurfaceSvg.prototype.dragGroup_ = null; +BlockDragSurfaceSvg.prototype.dragGroup_ = null; /** * Containing HTML element; parent of the workspace and the drag surface. * @type {?Element} * @private */ -Blockly.BlockDragSurfaceSvg.prototype.container_ = null; +BlockDragSurfaceSvg.prototype.container_ = null; /** * Cached value for the scale of the drag surface. @@ -65,45 +67,43 @@ Blockly.BlockDragSurfaceSvg.prototype.container_ = null; * @type {number} * @private */ -Blockly.BlockDragSurfaceSvg.prototype.scale_ = 1; +BlockDragSurfaceSvg.prototype.scale_ = 1; /** * Cached value for the translation of the drag surface. * This translation is in pixel units, because the scale is applied to the * drag group rather than the top-level SVG. - * @type {?Blockly.utils.Coordinate} + * @type {?Coordinate} * @private */ -Blockly.BlockDragSurfaceSvg.prototype.surfaceXY_ = null; +BlockDragSurfaceSvg.prototype.surfaceXY_ = null; /** * Cached value for the translation of the child drag surface in pixel units. * Since the child drag surface tracks the translation of the workspace this is * ultimately the translation of the workspace. - * @type {!Blockly.utils.Coordinate} + * @type {!Coordinate} * @private */ -Blockly.BlockDragSurfaceSvg.prototype.childSurfaceXY_ = - new Blockly.utils.Coordinate(0, 0); +BlockDragSurfaceSvg.prototype.childSurfaceXY_ = new Coordinate(0, 0); /** * Create the drag surface and inject it into the container. */ -Blockly.BlockDragSurfaceSvg.prototype.createDom = function() { +BlockDragSurfaceSvg.prototype.createDom = function() { if (this.SVG_) { return; // Already created. } - this.SVG_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.SVG, { - 'xmlns': Blockly.utils.dom.SVG_NS, - 'xmlns:html': Blockly.utils.dom.HTML_NS, - 'xmlns:xlink': Blockly.utils.dom.XLINK_NS, + this.SVG_ = createSvgElement( + SVG, { + 'xmlns': SVG_NS, + 'xmlns:html': HTML_NS, + 'xmlns:xlink': XLINK_NS, 'version': '1.1', 'class': 'blocklyBlockDragSurface' }, this.container_); - this.dragGroup_ = - Blockly.utils.dom.createSvgElement(Blockly.utils.Svg.G, {}, this.SVG_); + this.dragGroup_ = createSvgElement(G, {}, this.SVG_); }; /** @@ -112,14 +112,14 @@ Blockly.BlockDragSurfaceSvg.prototype.createDom = function() { * @param {!SVGElement} blocks Block or group of blocks to place on the drag * surface. */ -Blockly.BlockDragSurfaceSvg.prototype.setBlocksAndShow = function(blocks) { +BlockDragSurfaceSvg.prototype.setBlocksAndShow = function(blocks) { if (this.dragGroup_.childNodes.length) { throw Error('Already dragging a block.'); } // appendChild removes the blocks from the previous parent this.dragGroup_.appendChild(blocks); this.SVG_.style.display = 'block'; - this.surfaceXY_ = new Blockly.utils.Coordinate(0, 0); + this.surfaceXY_ = new Coordinate(0, 0); }; /** @@ -129,13 +129,12 @@ Blockly.BlockDragSurfaceSvg.prototype.setBlocksAndShow = function(blocks) { * @param {number} y Y translation in pixel coordinates. * @param {number} scale Scale of the group. */ -Blockly.BlockDragSurfaceSvg.prototype.translateAndScaleGroup = function( - x, y, scale) { +BlockDragSurfaceSvg.prototype.translateAndScaleGroup = function(x, y, scale) { this.scale_ = scale; // This is a work-around to prevent a the blocks from rendering // fuzzy while they are being dragged on the drag surface. - var fixedX = x.toFixed(0); - var fixedY = y.toFixed(0); + const fixedX = x.toFixed(0); + const fixedY = y.toFixed(0); this.childSurfaceXY_.x = parseInt(fixedX, 10); this.childSurfaceXY_.y = parseInt(fixedY, 10); @@ -149,17 +148,16 @@ Blockly.BlockDragSurfaceSvg.prototype.translateAndScaleGroup = function( * Translate the drag surface's SVG based on its internal state. * @private */ -Blockly.BlockDragSurfaceSvg.prototype.translateSurfaceInternal_ = function() { - var x = this.surfaceXY_.x; - var y = this.surfaceXY_.y; +BlockDragSurfaceSvg.prototype.translateSurfaceInternal_ = function() { + let x = this.surfaceXY_.x; + let y = this.surfaceXY_.y; // This is a work-around to prevent a the blocks from rendering // fuzzy while they are being dragged on the drag surface. x = x.toFixed(0); y = y.toFixed(0); this.SVG_.style.display = 'block'; - Blockly.utils.dom.setCssTransform( - this.SVG_, 'translate3d(' + x + 'px, ' + y + 'px, 0)'); + setCssTransform(this.SVG_, 'translate3d(' + x + 'px, ' + y + 'px, 0)'); }; /** @@ -167,10 +165,10 @@ Blockly.BlockDragSurfaceSvg.prototype.translateSurfaceInternal_ = function() { * @param {number} deltaX Horizontal offset in pixel units. * @param {number} deltaY Vertical offset in pixel units. */ -Blockly.BlockDragSurfaceSvg.prototype.translateBy = function(deltaX, deltaY) { - var x = this.surfaceXY_.x + deltaX; - var y = this.surfaceXY_.y + deltaY; - this.surfaceXY_ = new Blockly.utils.Coordinate(x, y); +BlockDragSurfaceSvg.prototype.translateBy = function(deltaX, deltaY) { + const x = this.surfaceXY_.x + deltaX; + const y = this.surfaceXY_.y + deltaY; + this.surfaceXY_ = new Coordinate(x, y); this.translateSurfaceInternal_(); }; @@ -182,20 +180,19 @@ Blockly.BlockDragSurfaceSvg.prototype.translateBy = function(deltaX, deltaY) { * @param {number} x X translation for the entire surface. * @param {number} y Y translation for the entire surface. */ -Blockly.BlockDragSurfaceSvg.prototype.translateSurface = function(x, y) { - this.surfaceXY_ = - new Blockly.utils.Coordinate(x * this.scale_, y * this.scale_); +BlockDragSurfaceSvg.prototype.translateSurface = function(x, y) { + this.surfaceXY_ = new Coordinate(x * this.scale_, y * this.scale_); this.translateSurfaceInternal_(); }; /** * Reports the surface translation in scaled workspace coordinates. * Use this when finishing a drag to return blocks to the correct position. - * @return {!Blockly.utils.Coordinate} Current translation of the surface. + * @return {!Coordinate} Current translation of the surface. */ -Blockly.BlockDragSurfaceSvg.prototype.getSurfaceTranslation = function() { - var xy = Blockly.utils.getRelativeXY(/** @type {!SVGElement} */ (this.SVG_)); - return new Blockly.utils.Coordinate(xy.x / this.scale_, xy.y / this.scale_); +BlockDragSurfaceSvg.prototype.getSurfaceTranslation = function() { + const xy = getRelativeXY(/** @type {!SVGElement} */ (this.SVG_)); + return new Coordinate(xy.x / this.scale_, xy.y / this.scale_); }; /** @@ -203,7 +200,7 @@ Blockly.BlockDragSurfaceSvg.prototype.getSurfaceTranslation = function() { * BlockSvg.getRelativeToSurfaceXY). * @return {?SVGElement} Drag surface group element. */ -Blockly.BlockDragSurfaceSvg.prototype.getGroup = function() { +BlockDragSurfaceSvg.prototype.getGroup = function() { return this.dragGroup_; }; @@ -211,16 +208,17 @@ Blockly.BlockDragSurfaceSvg.prototype.getGroup = function() { * Returns the SVG drag surface. * @returns {?SVGElement} The SVG drag surface. */ -Blockly.BlockDragSurfaceSvg.prototype.getSvgRoot = function() { +BlockDragSurfaceSvg.prototype.getSvgRoot = function() { return this.SVG_; }; /** * Get the current blocks on the drag surface, if any (primarily * for BlockSvg.getRelativeToSurfaceXY). - * @return {?Element} Drag surface block DOM element, or null if no blocks exist. + * @return {?Element} Drag surface block DOM element, or null if no blocks + * exist. */ -Blockly.BlockDragSurfaceSvg.prototype.getCurrentBlock = function() { +BlockDragSurfaceSvg.prototype.getCurrentBlock = function() { return /** @type {Element} */ (this.dragGroup_.firstChild); }; @@ -228,9 +226,9 @@ Blockly.BlockDragSurfaceSvg.prototype.getCurrentBlock = function() { * Gets the translation of the child block surface * This surface is in charge of keeping track of how much the workspace has * moved. - * @return {!Blockly.utils.Coordinate} The amount the workspace has been moved. + * @return {!Coordinate} The amount the workspace has been moved. */ -Blockly.BlockDragSurfaceSvg.prototype.getWsTranslation = function() { +BlockDragSurfaceSvg.prototype.getWsTranslation = function() { // Returning a copy so the coordinate can not be changed outside this class. return this.childSurfaceXY_.clone(); }; @@ -244,7 +242,7 @@ Blockly.BlockDragSurfaceSvg.prototype.getWsTranslation = function() { * to, or null if the blocks should be removed from this surface without * being moved to a different surface. */ -Blockly.BlockDragSurfaceSvg.prototype.clearAndHide = function(opt_newSurface) { +BlockDragSurfaceSvg.prototype.clearAndHide = function(opt_newSurface) { if (opt_newSurface) { // appendChild removes the node from this.dragGroup_ opt_newSurface.appendChild(this.getCurrentBlock()); @@ -257,3 +255,5 @@ Blockly.BlockDragSurfaceSvg.prototype.clearAndHide = function(opt_newSurface) { } this.surfaceXY_ = null; }; + +exports = BlockDragSurfaceSvg; diff --git a/core/block_dragger.js b/core/block_dragger.js index a1d4b6f2d..b7c11e8a3 100644 --- a/core/block_dragger.js +++ b/core/block_dragger.js @@ -10,61 +10,63 @@ */ 'use strict'; -goog.provide('Blockly.BlockDragger'); +goog.module('Blockly.BlockDragger'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.blockAnimations'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); -goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +/* eslint-disable-next-line no-unused-vars */ +const IBlockDragger = goog.require('Blockly.IBlockDragger'); +/* eslint-disable-next-line no-unused-vars */ +const IDragTarget = goog.requireType('Blockly.IDragTarget'); +const InsertionMarkerManager = goog.require('Blockly.InsertionMarkerManager'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +const blockAnimation = goog.require('Blockly.blockAnimations'); +const dom = goog.require('Blockly.utils.dom'); +const events = goog.require('Blockly.Events'); +const registry = goog.require('Blockly.registry'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockDrag'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockMove'); -goog.require('Blockly.IBlockDragger'); -goog.require('Blockly.InsertionMarkerManager'); -goog.require('Blockly.registry'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.dom'); - -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.IDragTarget'); -goog.requireType('Blockly.WorkspaceSvg'); /** * Class for a block dragger. It moves blocks around the workspace when they * are being dragged by a mouse or touch. - * @param {!Blockly.BlockSvg} block The block to drag. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to drag on. + * @param {!BlockSvg} block The block to drag. + * @param {!WorkspaceSvg} workspace The workspace to drag on. * @constructor - * @implements {Blockly.IBlockDragger} + * @implements {IBlockDragger} */ -Blockly.BlockDragger = function(block, workspace) { +const BlockDragger = function(block, workspace) { /** * The top block in the stack that is being dragged. - * @type {!Blockly.BlockSvg} + * @type {!BlockSvg} * @protected */ this.draggingBlock_ = block; /** * The workspace on which the block is being dragged. - * @type {!Blockly.WorkspaceSvg} + * @type {!WorkspaceSvg} * @protected */ this.workspace_ = workspace; /** * Object that keeps track of connections on dragged blocks. - * @type {!Blockly.InsertionMarkerManager} + * @type {!InsertionMarkerManager} * @protected */ this.draggedConnectionManager_ = - new Blockly.InsertionMarkerManager(this.draggingBlock_); + new InsertionMarkerManager(this.draggingBlock_); /** * Which drag area the mouse pointer is over, if any. - * @type {?Blockly.IDragTarget} + * @type {?IDragTarget} * @private */ this.dragTarget_ = null; @@ -79,7 +81,7 @@ Blockly.BlockDragger = function(block, workspace) { /** * The location of the top left corner of the dragging block at the beginning * of the drag in workspace coordinates. - * @type {!Blockly.utils.Coordinate} + * @type {!Coordinate} * @protected */ this.startXY_ = this.draggingBlock_.getRelativeToSurfaceXY(); @@ -91,14 +93,14 @@ Blockly.BlockDragger = function(block, workspace) { * @type {Array} * @protected */ - this.dragIconData_ = Blockly.BlockDragger.initIconData_(block); + this.dragIconData_ = initIconData(block); }; /** * Sever all links from this object. * @package */ -Blockly.BlockDragger.prototype.dispose = function() { +BlockDragger.prototype.dispose = function() { this.dragIconData_.length = 0; if (this.draggedConnectionManager_) { @@ -110,19 +112,19 @@ Blockly.BlockDragger.prototype.dispose = function() { * Make a list of all of the icons (comment, warning, and mutator) that are * on this block and its descendants. Moving an icon moves the bubble that * extends from it if that bubble is open. - * @param {!Blockly.BlockSvg} block The root block that is being dragged. + * @param {!BlockSvg} block The root block that is being dragged. * @return {!Array} The list of all icons and their locations. - * @private */ -Blockly.BlockDragger.initIconData_ = function(block) { +const initIconData = function(block) { // Build a list of icons that need to be moved and where they started. - var dragIconData = []; - var descendants = block.getDescendants(false); - for (var i = 0, descendant; (descendant = descendants[i]); i++) { - var icons = descendant.getIcons(); - for (var j = 0; j < icons.length; j++) { - var data = { - // Blockly.utils.Coordinate with x and y properties (workspace + const dragIconData = []; + const descendants = block.getDescendants(false); + + for (let i = 0, descendant; (descendant = descendants[i]); i++) { + const icons = descendant.getIcons(); + for (let j = 0; j < icons.length; j++) { + const data = { + // Coordinate with x and y properties (workspace // coordinates). location: icons[j].getIconLocation(), // Blockly.Icon @@ -136,16 +138,15 @@ Blockly.BlockDragger.initIconData_ = function(block) { /** * Start dragging a block. This includes moving it to the drag surface. - * @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. * @param {boolean} healStack Whether or not to heal the stack after * disconnecting. * @public */ -Blockly.BlockDragger.prototype.startDrag = function( - currentDragDeltaXY, healStack) { - if (!Blockly.Events.getGroup()) { - Blockly.Events.setGroup(true); +BlockDragger.prototype.startDrag = function(currentDragDeltaXY, healStack) { + if (!events.getGroup()) { + events.setGroup(true); } this.fireDragStartEvent_(); @@ -159,9 +160,9 @@ Blockly.BlockDragger.prototype.startDrag = function( // During a drag there may be a lot of rerenders, but not field changes. // Turn the cache on so we don't do spurious remeasures during the drag. - Blockly.utils.dom.startTextWidthCache(); + dom.startTextWidthCache(); this.workspace_.setResizesEnabled(false); - Blockly.blockAnimations.disconnectUiStop(); + blockAnimation.disconnectUiStop(); if (this.shouldDisconnect_(healStack)) { this.disconnectBlock_(healStack, currentDragDeltaXY); @@ -180,9 +181,9 @@ Blockly.BlockDragger.prototype.startDrag = function( * @return {boolean} True to disconnect the block, false otherwise. * @protected */ -Blockly.BlockDragger.prototype.shouldDisconnect_ = function(healStack) { +BlockDragger.prototype.shouldDisconnect_ = function(healStack) { return !!( - this.draggingBlock_.getParent() || + this.draggingBlock_.getParent() || (healStack && this.draggingBlock_.nextConnection && this.draggingBlock_.nextConnection.targetBlock())); }; @@ -191,18 +192,18 @@ Blockly.BlockDragger.prototype.shouldDisconnect_ = function(healStack) { * Disconnects the block and moves it to a new location. * @param {boolean} healStack Whether or not to heal the stack after * disconnecting. - * @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. * @protected */ -Blockly.BlockDragger.prototype.disconnectBlock_ = function( +BlockDragger.prototype.disconnectBlock_ = function( healStack, currentDragDeltaXY) { this.draggingBlock_.unplug(healStack); - var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); - var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta); + const delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); + const newLoc = Coordinate.sum(this.startXY_, delta); this.draggingBlock_.translate(newLoc.x, newLoc.y); - Blockly.blockAnimations.disconnectUiEffect(this.draggingBlock_); + blockAnimation.disconnectUiEffect(this.draggingBlock_); this.draggedConnectionManager_.updateAvailableConnections(); }; @@ -210,31 +211,31 @@ Blockly.BlockDragger.prototype.disconnectBlock_ = function( * Fire a UI event at the start of a block drag. * @protected */ -Blockly.BlockDragger.prototype.fireDragStartEvent_ = function() { - var event = new (Blockly.Events.get(Blockly.Events.BLOCK_DRAG))( +BlockDragger.prototype.fireDragStartEvent_ = function() { + const event = new (events.get(events.BLOCK_DRAG))( this.draggingBlock_, true, this.draggingBlock_.getDescendants(false)); - Blockly.Events.fire(event); + events.fire(event); }; /** * Execute a step of block dragging, based on the given event. Update the * display accordingly. * @param {!Event} e The most recent move event. - * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has + * @param {!Coordinate} currentDragDeltaXY How far the pointer has * moved from the position at the start of the drag, in pixel units. * @public */ -Blockly.BlockDragger.prototype.drag = function(e, currentDragDeltaXY) { - var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); - var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta); +BlockDragger.prototype.drag = function(e, currentDragDeltaXY) { + const delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); + const newLoc = Coordinate.sum(this.startXY_, delta); this.draggingBlock_.moveDuringDrag(newLoc); this.dragIcons_(delta); - var oldDragTarget = this.dragTarget_; + const oldDragTarget = this.dragTarget_; this.dragTarget_ = this.workspace_.getDragTarget(e); this.draggedConnectionManager_.update(delta, this.dragTarget_); - var oldWouldDeleteBlock = this.wouldDeleteBlock_; + const oldWouldDeleteBlock = this.wouldDeleteBlock_; this.wouldDeleteBlock_ = this.draggedConnectionManager_.wouldDeleteBlock(); if (oldWouldDeleteBlock != this.wouldDeleteBlock_) { // Prevent unnecessary add/remove class calls. @@ -253,26 +254,26 @@ Blockly.BlockDragger.prototype.drag = function(e, currentDragDeltaXY) { /** * Finish a block drag and put the block back on the workspace. * @param {!Event} e The mouseup/touchend event. - * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has + * @param {!Coordinate} currentDragDeltaXY How far the pointer has * moved from the position at the start of the drag, in pixel units. * @public */ -Blockly.BlockDragger.prototype.endDrag = function(e, currentDragDeltaXY) { +BlockDragger.prototype.endDrag = function(e, currentDragDeltaXY) { // Make sure internal state is fresh. this.drag(e, currentDragDeltaXY); this.dragIconData_ = []; this.fireDragEndEvent_(); - Blockly.utils.dom.stopTextWidthCache(); + dom.stopTextWidthCache(); - Blockly.blockAnimations.disconnectUiStop(); + blockAnimation.disconnectUiStop(); - var preventMove = !!this.dragTarget_ && + const preventMove = !!this.dragTarget_ && this.dragTarget_.shouldPreventMove(this.draggingBlock_); if (preventMove) { var newLoc = this.startXY_; } else { - var newValues = this.getNewLocationAfterDrag_(currentDragDeltaXY); + const newValues = this.getNewLocationAfterDrag_(currentDragDeltaXY); var delta = newValues.delta; var newLoc = newValues.newLocation; } @@ -282,7 +283,7 @@ Blockly.BlockDragger.prototype.endDrag = function(e, currentDragDeltaXY) { this.dragTarget_.onDrop(this.draggingBlock_); } - var deleted = this.maybeDeleteBlock_(); + const deleted = this.maybeDeleteBlock_(); if (!deleted) { // These are expensive and don't need to be done if we're deleting. this.draggingBlock_.setDragging(false); @@ -299,25 +300,23 @@ Blockly.BlockDragger.prototype.endDrag = function(e, currentDragDeltaXY) { } this.workspace_.setResizesEnabled(true); - Blockly.Events.setGroup(false); + events.setGroup(false); }; /** * Calculates the drag delta and new location values after a block is dragged. - * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has + * @param {!Coordinate} currentDragDeltaXY How far the pointer has * moved from the start of the drag, in pixel units. - * @return {{delta: !Blockly.utils.Coordinate, newLocation: - * !Blockly.utils.Coordinate}} New location after drag. delta is in + * @return {{delta: !Coordinate, newLocation: + * !Coordinate}} New location after drag. delta is in * workspace units. newLocation is the new coordinate where the block should * end up. * @protected */ -Blockly.BlockDragger.prototype.getNewLocationAfterDrag_ = function( - currentDragDeltaXY) { - var newValues = {}; +BlockDragger.prototype.getNewLocationAfterDrag_ = function(currentDragDeltaXY) { + const newValues = {}; newValues.delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); - newValues.newLocation = - Blockly.utils.Coordinate.sum(this.startXY_, newValues.delta); + newValues.newLocation = Coordinate.sum(this.startXY_, newValues.delta); return newValues; }; @@ -328,7 +327,7 @@ Blockly.BlockDragger.prototype.getNewLocationAfterDrag_ = function( * @return {boolean} True if the block was deleted. * @protected */ -Blockly.BlockDragger.prototype.maybeDeleteBlock_ = function() { +BlockDragger.prototype.maybeDeleteBlock_ = function() { if (this.wouldDeleteBlock_) { // Fire a move event, so we know where to go back to for an undo. this.fireMoveEvent_(); @@ -341,11 +340,11 @@ Blockly.BlockDragger.prototype.maybeDeleteBlock_ = function() { /** * Updates the necessary information to place a block at a certain location. - * @param {!Blockly.utils.Coordinate} delta The change in location from where + * @param {!Coordinate} delta The change in location from where * the block started the drag to where it ended the drag. * @protected */ -Blockly.BlockDragger.prototype.updateBlockAfterMove_ = function(delta) { +BlockDragger.prototype.updateBlockAfterMove_ = function(delta) { this.draggingBlock_.moveConnections(delta.x, delta.y); this.fireMoveEvent_(); if (this.draggedConnectionManager_.wouldConnectBlock()) { @@ -361,10 +360,10 @@ Blockly.BlockDragger.prototype.updateBlockAfterMove_ = function(delta) { * Fire a UI event at the end of a block drag. * @protected */ -Blockly.BlockDragger.prototype.fireDragEndEvent_ = function() { - var event = new (Blockly.Events.get(Blockly.Events.BLOCK_DRAG))( +BlockDragger.prototype.fireDragEndEvent_ = function() { + const event = new (events.get(events.BLOCK_DRAG))( this.draggingBlock_, false, this.draggingBlock_.getDescendants(false)); - Blockly.Events.fire(event); + events.fire(event); }; /** @@ -374,12 +373,12 @@ Blockly.BlockDragger.prototype.fireDragEndEvent_ = function() { * @param {boolean} isEnd True if we are at the end of a drag, false otherwise. * @protected */ -Blockly.BlockDragger.prototype.updateToolboxStyle_ = function(isEnd) { - var toolbox = this.workspace_.getToolbox(); +BlockDragger.prototype.updateToolboxStyle_ = function(isEnd) { + const toolbox = this.workspace_.getToolbox(); if (toolbox) { - var style = this.draggingBlock_.isDeletable() ? 'blocklyToolboxDelete' : - 'blocklyToolboxGrab'; + const style = this.draggingBlock_.isDeletable() ? 'blocklyToolboxDelete' : + 'blocklyToolboxGrab'; if (isEnd && typeof toolbox.removeStyle == 'function') { toolbox.removeStyle(style); @@ -394,12 +393,11 @@ Blockly.BlockDragger.prototype.updateToolboxStyle_ = function(isEnd) { * Fire a move event at the end of a block drag. * @protected */ -Blockly.BlockDragger.prototype.fireMoveEvent_ = function() { - var event = - new (Blockly.Events.get(Blockly.Events.BLOCK_MOVE))(this.draggingBlock_); +BlockDragger.prototype.fireMoveEvent_ = function() { + const event = new (events.get(events.BLOCK_MOVE))(this.draggingBlock_); event.oldCoordinate = this.startXY_; event.recordNew(); - Blockly.Events.fire(event); + events.fire(event); }; /** @@ -407,7 +405,7 @@ Blockly.BlockDragger.prototype.fireMoveEvent_ = function() { * dragging block would be deleted if released immediately. * @protected */ -Blockly.BlockDragger.prototype.updateCursorDuringBlockDrag_ = function() { +BlockDragger.prototype.updateCursorDuringBlockDrag_ = function() { this.draggingBlock_.setDeleteStyle(this.wouldDeleteBlock_); }; @@ -416,14 +414,14 @@ Blockly.BlockDragger.prototype.updateCursorDuringBlockDrag_ = function() { * correction for mutator workspaces. * This function does not consider differing origins. It simply scales the * input's x and y values. - * @param {!Blockly.utils.Coordinate} pixelCoord A coordinate with x and y + * @param {!Coordinate} pixelCoord A coordinate with x and y * values in CSS pixel units. - * @return {!Blockly.utils.Coordinate} The input coordinate divided by the + * @return {!Coordinate} The input coordinate divided by the * workspace scale. * @protected */ -Blockly.BlockDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) { - var result = new Blockly.utils.Coordinate( +BlockDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) { + const result = new Coordinate( pixelCoord.x / this.workspace_.scale, pixelCoord.y / this.workspace_.scale); if (this.workspace_.isMutator) { @@ -431,7 +429,7 @@ Blockly.BlockDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) { // oddities in our rendering optimizations. The actual scale is the same as // the scale on the parent workspace. // Fix that for dragging. - var mainScale = this.workspace_.options.parentWorkspace.scale; + const mainScale = this.workspace_.options.parentWorkspace.scale; result.scale(1 / mainScale); } return result; @@ -439,26 +437,26 @@ Blockly.BlockDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) { /** * Move all of the icons connected to this drag. - * @param {!Blockly.utils.Coordinate} dxy How far to move the icons from their + * @param {!Coordinate} dxy How far to move the icons from their * original positions, in workspace units. * @protected */ -Blockly.BlockDragger.prototype.dragIcons_ = function(dxy) { +BlockDragger.prototype.dragIcons_ = function(dxy) { // Moving icons moves their associated bubbles. - for (var i = 0; i < this.dragIconData_.length; i++) { - var data = this.dragIconData_[i]; - data.icon.setIconLocation(Blockly.utils.Coordinate.sum(data.location, dxy)); + for (let i = 0; i < this.dragIconData_.length; i++) { + const data = this.dragIconData_[i]; + data.icon.setIconLocation(Coordinate.sum(data.location, dxy)); } }; /** * Get a list of the insertion markers that currently exist. 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. * @public */ -Blockly.BlockDragger.prototype.getInsertionMarkers = function() { +BlockDragger.prototype.getInsertionMarkers = function() { // No insertion markers with the old style of dragged connection managers. if (this.draggedConnectionManager_ && this.draggedConnectionManager_.getInsertionMarkers) { @@ -467,6 +465,6 @@ Blockly.BlockDragger.prototype.getInsertionMarkers = function() { return []; }; -Blockly.registry.register( - Blockly.registry.Type.BLOCK_DRAGGER, Blockly.registry.DEFAULT, - Blockly.BlockDragger); +registry.register(registry.Type.BLOCK_DRAGGER, registry.DEFAULT, BlockDragger); + +exports = BlockDragger; diff --git a/core/block_svg.js b/core/block_svg.js index 08e5addcb..fd5be3212 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -18,7 +18,6 @@ goog.require('Blockly.blockAnimations'); goog.require('Blockly.blockRendering.IPathObject'); goog.require('Blockly.browserEvents'); goog.require('Blockly.connectionTypes'); -/** @suppress {extraRequire} */ goog.require('Blockly.constants'); goog.require('Blockly.ContextMenu'); goog.require('Blockly.ContextMenuRegistry'); @@ -31,6 +30,7 @@ goog.require('Blockly.IASTNodeLocationSvg'); goog.require('Blockly.IBoundedElement'); goog.require('Blockly.ICopyable'); goog.require('Blockly.IDraggable'); +goog.require('Blockly.internalConstants'); goog.require('Blockly.Msg'); goog.require('Blockly.RenderedConnection'); goog.require('Blockly.TabNavigateCursor'); @@ -688,7 +688,7 @@ Blockly.BlockSvg.prototype.updateCollapsed_ = function() { icon.setVisible(false); } - var text = this.toString(Blockly.COLLAPSE_CHARS); + var text = this.toString(Blockly.internalConstants.COLLAPSE_CHARS); var field = this.getField(collapsedFieldName); if (field) { field.setValue(text); @@ -1550,7 +1550,8 @@ Blockly.BlockSvg.prototype.bumpNeighbours = function() { connection.targetBlock().bumpNeighbours(); } - var neighbours = connection.neighbours(Blockly.SNAP_RADIUS); + var neighbours = + connection.neighbours(Blockly.internalConstants.SNAP_RADIUS); for (var j = 0, otherConnection; (otherConnection = neighbours[j]); j++) { // If both connections are connected, that's probably fine. But if @@ -1585,13 +1586,13 @@ Blockly.BlockSvg.prototype.scheduleSnapAndBump = function() { Blockly.Events.setGroup(group); block.snapToGrid(); Blockly.Events.setGroup(false); - }, Blockly.BUMP_DELAY / 2); + }, Blockly.internalConstants.BUMP_DELAY / 2); setTimeout(function() { Blockly.Events.setGroup(group); block.bumpNeighbours(); Blockly.Events.setGroup(false); - }, Blockly.BUMP_DELAY); + }, Blockly.internalConstants.BUMP_DELAY); }; /** diff --git a/core/blockly.js b/core/blockly.js index 92716e4d1..94f485c99 100644 --- a/core/blockly.js +++ b/core/blockly.js @@ -35,6 +35,7 @@ goog.require('Blockly.Events.VarCreate'); /** @suppress {extraRequire} */ goog.require('Blockly.inject'); goog.require('Blockly.inputTypes'); +goog.require('Blockly.internalConstants'); /** @suppress {extraRequire} */ goog.require('Blockly.Procedures'); goog.require('Blockly.ShortcutRegistry'); @@ -424,8 +425,9 @@ Blockly.isNumber = function(str) { * @return {string} RGB code, e.g. '#5ba65b'. */ Blockly.hueToHex = function(hue) { - return Blockly.utils.colour.hsvToHex(hue, Blockly.HSV_SATURATION, - Blockly.HSV_VALUE * 255); + return Blockly.utils.colour.hsvToHex( + hue, Blockly.internalConstants.HSV_SATURATION, + Blockly.internalConstants.HSV_VALUE * 255); }; /** @@ -596,3 +598,38 @@ Blockly.TOOLBOX_AT_LEFT = Blockly.utils.toolbox.Position.LEFT; * @see Blockly.utils.toolbox.Position.RIGHT */ Blockly.TOOLBOX_AT_RIGHT = Blockly.utils.toolbox.Position.RIGHT; + +// Aliases to allow external code to access these values for legacy reasons. +Blockly.LINE_MODE_MULTIPLIER = Blockly.internalConstants.LINE_MODE_MULTIPLIER; +Blockly.PAGE_MODE_MULTIPLIER = Blockly.internalConstants.PAGE_MODE_MULTIPLIER; +Blockly.DRAG_RADIUS = Blockly.internalConstants.DRAG_RADIUS; +Blockly.FLYOUT_DRAG_RADIUS = Blockly.internalConstants.FLYOUT_DRAG_RADIUS; +Blockly.SNAP_RADIUS = Blockly.internalConstants.SNAP_RADIUS; +Blockly.CONNECTING_SNAP_RADIUS = + Blockly.internalConstants.CONNECTING_SNAP_RADIUS; +Blockly.CURRENT_CONNECTION_PREFERENCE = + Blockly.internalConstants.CURRENT_CONNECTION_PREFERENCE; +Blockly.BUMP_DELAY = Blockly.internalConstants.BUMP_DELAY; +Blockly.BUMP_RANDOMNESS = Blockly.internalConstants.BUMP_RANDOMNESS; +Blockly.COLLAPSE_CHARS = Blockly.internalConstants.COLLAPSE_CHARS; +Blockly.LONGPRESS = Blockly.internalConstants.LONGPRESS; +Blockly.SOUND_LIMIT = Blockly.internalConstants.SOUND_LIMIT; +Blockly.DRAG_STACK = Blockly.internalConstants.DRAG_STACK; +Blockly.HSV_SATURATION = Blockly.internalConstants.HSV_SATURATION; +Blockly.HSV_VALUE = Blockly.internalConstants.HSV_VALUE; +Blockly.SPRITE = Blockly.internalConstants.SPRITE; +Blockly.DRAG_NONE = Blockly.internalConstants.DRAG_NONE; +Blockly.DRAG_STICKY = Blockly.internalConstants.DRAG_STICKY; +Blockly.DRAG_BEGIN = Blockly.internalConstants.DRAG_BEGIN; +Blockly.DRAG_FREE = Blockly.internalConstants.DRAG_FREE; +Blockly.OPPOSITE_TYPE = Blockly.internalConstants.OPPOSITE_TYPE; +Blockly.VARIABLE_CATEGORY_NAME = + Blockly.internalConstants.VARIABLE_CATEGORY_NAME; +Blockly.VARIABLE_DYNAMIC_CATEGORY_NAME = + Blockly.internalConstants.VARIABLE_DYNAMIC_CATEGORY_NAME; +Blockly.PROCEDURE_CATEGORY_NAME = + Blockly.internalConstants.PROCEDURE_CATEGORY_NAME; +Blockly.RENAME_VARIABLE_ID = Blockly.internalConstants.RENAME_VARIABLE_ID; +Blockly.DELETE_VARIABLE_ID = Blockly.internalConstants.DELETE_VARIABLE_ID; +Blockly.COLLAPSED_INPUT_NAME = Blockly.constants.COLLAPSED_INPUT_NAME; +Blockly.COLLAPSED_FIELD_NAME = Blockly.constants.COLLAPSED_FIELD_NAME; diff --git a/core/blocks.js b/core/blocks.js index 5f0d96b21..37c2105ce 100644 --- a/core/blocks.js +++ b/core/blocks.js @@ -14,10 +14,13 @@ * A mapping of block type names to block prototype objects. * @name Blockly.Blocks */ -goog.provide('Blockly.Blocks'); +goog.module('Blockly.Blocks'); +goog.module.declareLegacyNamespace(); /** * A mapping of block type names to block prototype objects. - * @type {!Object} + * @type {!Object} */ -Blockly.Blocks = Object.create(null); +const Blocks = Object.create(null); + +exports = Blocks; diff --git a/core/bubble_dragger.js b/core/bubble_dragger.js index e014b8738..d06c2fdc0 100644 --- a/core/bubble_dragger.js +++ b/core/bubble_dragger.js @@ -10,50 +10,57 @@ */ 'use strict'; -goog.provide('Blockly.BubbleDragger'); +goog.module('Blockly.BubbleDragger'); +goog.module.declareLegacyNamespace(); +/* eslint-disable-next-line no-unused-vars */ +const BlockDragSurfaceSvg = goog.requireType('Blockly.BlockDragSurfaceSvg'); +const ComponentManager = goog.require('Blockly.ComponentManager'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +const Events = goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const IBubble = goog.requireType('Blockly.IBubble'); +/* eslint-disable-next-line no-unused-vars */ +const IDeleteArea = goog.requireType('Blockly.IDeleteArea'); +/* eslint-disable-next-line no-unused-vars */ +const IDragTarget = goog.requireType('Blockly.IDragTarget'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +const utils = goog.require('Blockly.utils'); /** @suppress {extraRequire} */ goog.require('Blockly.Bubble'); -goog.require('Blockly.ComponentManager'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); -goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.CommentMove'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.Coordinate'); - -goog.requireType('Blockly.BlockDragSurfaceSvg'); -goog.requireType('Blockly.IBubble'); -goog.requireType('Blockly.WorkspaceSvg'); +/** @suppress {extraRequire} */ +goog.require('Blockly.constants'); /** * Class for a bubble dragger. It moves things on the bubble canvas around the * workspace when they are being dragged by a mouse or touch. These can be * block comments, mutators, warnings, or workspace comments. - * @param {!Blockly.IBubble} bubble The item on the bubble canvas to drag. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to drag on. + * @param {!IBubble} bubble The item on the bubble canvas to drag. + * @param {!WorkspaceSvg} workspace The workspace to drag on. * @constructor */ -Blockly.BubbleDragger = function(bubble, workspace) { +const BubbleDragger = function(bubble, workspace) { /** * The item on the bubble canvas that is being dragged. - * @type {!Blockly.IBubble} + * @type {!IBubble} * @private */ this.draggingBubble_ = bubble; /** * The workspace on which the bubble is being dragged. - * @type {!Blockly.WorkspaceSvg} + * @type {!WorkspaceSvg} * @private */ this.workspace_ = workspace; /** * Which drag target the mouse pointer is over, if any. - * @type {?Blockly.IDragTarget} + * @type {?IDragTarget} * @private */ this.dragTarget_ = null; @@ -68,7 +75,7 @@ Blockly.BubbleDragger = function(bubble, workspace) { /** * The location of the top left corner of the dragging bubble's body at the * beginning of the drag, in workspace coordinates. - * @type {!Blockly.utils.Coordinate} + * @type {!Coordinate} * @private */ this.startXY_ = this.draggingBubble_.getRelativeToSurfaceXY(); @@ -76,11 +83,11 @@ Blockly.BubbleDragger = function(bubble, workspace) { /** * The drag surface to move bubbles to during a drag, or null if none should * be used. Block dragging and bubble dragging use the same surface. - * @type {Blockly.BlockDragSurfaceSvg} + * @type {BlockDragSurfaceSvg} * @private */ this.dragSurface_ = - Blockly.utils.is3dSupported() && !!workspace.getBlockDragSurface() ? + utils.is3dSupported() && !!workspace.getBlockDragSurface() ? workspace.getBlockDragSurface() : null; }; @@ -90,7 +97,7 @@ Blockly.BubbleDragger = function(bubble, workspace) { * @package * @suppress {checkTypes} */ -Blockly.BubbleDragger.prototype.dispose = function() { +BubbleDragger.prototype.dispose = function() { this.draggingBubble_ = null; this.workspace_ = null; this.dragSurface_ = null; @@ -100,9 +107,9 @@ Blockly.BubbleDragger.prototype.dispose = function() { * Start dragging a bubble. This includes moving it to the drag surface. * @package */ -Blockly.BubbleDragger.prototype.startBubbleDrag = function() { - if (!Blockly.Events.getGroup()) { - Blockly.Events.setGroup(true); +BubbleDragger.prototype.startBubbleDrag = function() { + if (!Events.getGroup()) { + Events.setGroup(true); } this.workspace_.setResizesEnabled(false); @@ -118,19 +125,19 @@ Blockly.BubbleDragger.prototype.startBubbleDrag = function() { * Execute a step of bubble dragging, based on the given event. Update the * display accordingly. * @param {!Event} e The most recent move event. - * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has + * @param {!Coordinate} currentDragDeltaXY How far the pointer has * moved from the position at the start of the drag, in pixel units. * @package */ -Blockly.BubbleDragger.prototype.dragBubble = function(e, currentDragDeltaXY) { - var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); - var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta); +BubbleDragger.prototype.dragBubble = function(e, currentDragDeltaXY) { + const delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); + const newLoc = Coordinate.sum(this.startXY_, delta); this.draggingBubble_.moveDuringDrag(this.dragSurface_, newLoc); - var oldDragTarget = this.dragTarget_; + const oldDragTarget = this.dragTarget_; this.dragTarget_ = this.workspace_.getDragTarget(e); - var oldWouldDeleteBubble = this.wouldDeleteBubble_; + const oldWouldDeleteBubble = this.wouldDeleteBubble_; this.wouldDeleteBubble_ = this.shouldDelete_(this.dragTarget_); if (oldWouldDeleteBubble != this.wouldDeleteBubble_) { // Prevent unnecessary add/remove class calls. @@ -147,19 +154,19 @@ Blockly.BubbleDragger.prototype.dragBubble = function(e, currentDragDeltaXY) { /** * Whether ending the drag would delete the bubble. - * @param {?Blockly.IDragTarget} dragTarget The drag target that the bubblee is + * @param {?IDragTarget} dragTarget The drag target that the bubblee is * currently over. * @return {boolean} Whether dropping the bubble immediately would delete the * block. * @private */ -Blockly.BubbleDragger.prototype.shouldDelete_ = function(dragTarget) { +BubbleDragger.prototype.shouldDelete_ = function(dragTarget) { if (dragTarget) { - var componentManager = this.workspace_.getComponentManager(); - var isDeleteArea = componentManager.hasCapability(dragTarget.id, - Blockly.ComponentManager.Capability.DELETE_AREA); + const componentManager = this.workspace_.getComponentManager(); + const isDeleteArea = componentManager.hasCapability( + dragTarget.id, ComponentManager.Capability.DELETE_AREA); if (isDeleteArea) { - return (/** @type {!Blockly.IDeleteArea} */ (dragTarget)) + return (/** @type {!IDeleteArea} */ (dragTarget)) .wouldDelete(this.draggingBubble_, false); } } @@ -171,29 +178,29 @@ Blockly.BubbleDragger.prototype.shouldDelete_ = function(dragTarget) { * dragging bubble would be deleted if released immediately. * @private */ -Blockly.BubbleDragger.prototype.updateCursorDuringBubbleDrag_ = function() { +BubbleDragger.prototype.updateCursorDuringBubbleDrag_ = function() { this.draggingBubble_.setDeleteStyle(this.wouldDeleteBubble_); }; /** * Finish a bubble drag and put the bubble back on the workspace. * @param {!Event} e The mouseup/touchend event. - * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has + * @param {!Coordinate} currentDragDeltaXY How far the pointer has * moved from the position at the start of the drag, in pixel units. * @package */ -Blockly.BubbleDragger.prototype.endBubbleDrag = function( - e, currentDragDeltaXY) { +BubbleDragger.prototype.endBubbleDrag = function(e, currentDragDeltaXY) { // Make sure internal state is fresh. this.dragBubble(e, currentDragDeltaXY); - var preventMove = this.dragTarget_ && + const preventMove = this.dragTarget_ && this.dragTarget_.shouldPreventMove(this.draggingBubble_); + let newLoc; if (preventMove) { - var newLoc = this.startXY_; + newLoc = this.startXY_; } else { - var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); - var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta); + const delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); + newLoc = Coordinate.sum(this.startXY_, delta); } // Move the bubble to its final location. this.draggingBubble_.moveTo(newLoc.x, newLoc.y); @@ -218,20 +225,21 @@ Blockly.BubbleDragger.prototype.endBubbleDrag = function( } this.workspace_.setResizesEnabled(true); - Blockly.Events.setGroup(false); + Events.setGroup(false); }; /** * Fire a move event at the end of a bubble drag. * @private */ -Blockly.BubbleDragger.prototype.fireMoveEvent_ = function() { +BubbleDragger.prototype.fireMoveEvent_ = function() { if (this.draggingBubble_.isComment) { - var event = new (Blockly.Events.get(Blockly.Events.COMMENT_MOVE))( + // TODO (adodson): Resolve build errors when requiring WorkspaceCommentSvg. + const event = new (Events.get(Events.COMMENT_MOVE))( /** @type {!Blockly.WorkspaceCommentSvg} */ (this.draggingBubble_)); event.setOldCoordinate(this.startXY_); event.recordNew(); - Blockly.Events.fire(event); + Events.fire(event); } // TODO (fenichel): move events for comments. return; @@ -242,14 +250,14 @@ Blockly.BubbleDragger.prototype.fireMoveEvent_ = function() { * correction for mutator workspaces. * This function does not consider differing origins. It simply scales the * input's x and y values. - * @param {!Blockly.utils.Coordinate} pixelCoord A coordinate with x and y + * @param {!Coordinate} pixelCoord A coordinate with x and y * values in CSS pixel units. - * @return {!Blockly.utils.Coordinate} The input coordinate divided by the + * @return {!Coordinate} The input coordinate divided by the * workspace scale. * @private */ -Blockly.BubbleDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) { - var result = new Blockly.utils.Coordinate( +BubbleDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) { + const result = new Coordinate( pixelCoord.x / this.workspace_.scale, pixelCoord.y / this.workspace_.scale); if (this.workspace_.isMutator) { @@ -257,7 +265,7 @@ Blockly.BubbleDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) { // oddities in our rendering optimizations. The actual scale is the same as // the scale on the parent workspace. // Fix that for dragging. - var mainScale = this.workspace_.options.parentWorkspace.scale; + const mainScale = this.workspace_.options.parentWorkspace.scale; result.scale(1 / mainScale); } return result; @@ -268,9 +276,11 @@ Blockly.BubbleDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) { * drag surface to preserve the apparent location of the bubble. * @private */ -Blockly.BubbleDragger.prototype.moveToDragSurface_ = function() { +BubbleDragger.prototype.moveToDragSurface_ = function() { this.draggingBubble_.moveTo(0, 0); this.dragSurface_.translateSurface(this.startXY_.x, this.startXY_.y); // Execute the move on the top-level SVG component. this.dragSurface_.setBlocksAndShow(this.draggingBubble_.getSvgRoot()); }; + +exports = BubbleDragger; diff --git a/core/comment.js b/core/comment.js index 7917b2ec5..99d81e89c 100644 --- a/core/comment.js +++ b/core/comment.js @@ -10,43 +10,49 @@ */ 'use strict'; -goog.provide('Blockly.Comment'); +goog.module('Blockly.Comment'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.browserEvents'); -goog.require('Blockly.Bubble'); -goog.require('Blockly.Css'); -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'); +/* eslint-disable-next-line no-unused-vars */ +const Size = goog.requireType('Blockly.utils.Size'); +const Svg = goog.require('Blockly.utils.Svg'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +const userAgent = goog.require('Blockly.utils.userAgent'); +/* eslint-disable-next-line no-unused-vars */ +const {conditionalBind, Data, unbind} = goog.require('Blockly.browserEvents'); +const {createSvgElement, HTML_NS} = goog.require('Blockly.utils.dom'); +const {inherits} = goog.require('Blockly.utils.object'); +const {register} = goog.require('Blockly.Css'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockChange'); /** @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.require('Blockly.utils.userAgent'); /** @suppress {extraRequire} */ goog.require('Blockly.Warning'); -goog.requireType('Blockly.Block'); -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.utils.Coordinate'); -goog.requireType('Blockly.utils.Size'); -goog.requireType('Blockly.WorkspaceSvg'); - /** * Class for a comment. - * @param {!Blockly.Block} block The block associated with this comment. - * @extends {Blockly.Icon} + * @param {!Block} block The block associated with this comment. + * @extends {Icon} * @constructor */ -Blockly.Comment = function(block) { - Blockly.Comment.superClass_.constructor.call(this, block); +const Comment = function(block) { + Comment.superClass_.constructor.call(this, block); /** * The model for this comment. - * @type {!Blockly.Block.CommentModel} + * @type {!Block.CommentModel} * @private */ this.model_ = block.commentModel; @@ -64,62 +70,60 @@ Blockly.Comment = function(block) { /** * Mouse up event data. - * @type {?Blockly.browserEvents.Data} + * @type {?Data} * @private */ this.onMouseUpWrapper_ = null; /** * Wheel event data. - * @type {?Blockly.browserEvents.Data} + * @type {?Data} * @private */ this.onWheelWrapper_ = null; /** * Change event data. - * @type {?Blockly.browserEvents.Data} + * @type {?Data} * @private */ this.onChangeWrapper_ = null; /** * Input event data. - * @type {?Blockly.browserEvents.Data} + * @type {?Data} * @private */ this.onInputWrapper_ = null; this.createIcon(); }; -Blockly.utils.object.inherits(Blockly.Comment, Blockly.Icon); +inherits(Comment, Icon); /** * Draw the comment icon. * @param {!Element} group The icon group. * @protected */ -Blockly.Comment.prototype.drawIcon_ = function(group) { +Comment.prototype.drawIcon_ = function(group) { // Circle. - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.CIRCLE, - {'class': 'blocklyIconShape', 'r': '8', 'cx': '8', 'cy': '8'}, + createSvgElement( + Svg.CIRCLE, {'class': 'blocklyIconShape', 'r': '8', 'cx': '8', 'cy': '8'}, group); // Can't use a real '?' text character since different browsers and operating // systems render it differently. // Body of question mark. - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.PATH, - { + createSvgElement( + Svg.PATH, { 'class': 'blocklyIconSymbol', 'd': 'm6.8,10h2c0.003,-0.617 0.271,-0.962 0.633,-1.266 2.875,-2.405' + - '0.607,-5.534 -3.765,-3.874v1.7c3.12,-1.657 3.698,0.118 2.336,1.25' + - '-1.201,0.998 -1.201,1.528 -1.204,2.19z'}, + '0.607,-5.534 -3.765,-3.874v1.7c3.12,-1.657 3.698,0.118 2.336,1.25' + + '-1.201,0.998 -1.201,1.528 -1.204,2.19z' + }, group); // Dot of question mark. - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, - { + createSvgElement( + Svg.RECT, { 'class': 'blocklyIconSymbol', 'x': '6.8', 'y': '10.78', @@ -134,7 +138,7 @@ Blockly.Comment.prototype.drawIcon_ = function(group) { * @return {!SVGElement} The top-level node of the editor. * @private */ -Blockly.Comment.prototype.createEditor_ = function() { +Comment.prototype.createEditor_ = function() { /* Create the editor. Here's the markup that will be generated in * editable mode: @@ -147,18 +151,16 @@ Blockly.Comment.prototype.createEditor_ = function() { * For non-editable mode see Warning.textToDom_. */ - this.foreignObject_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.FOREIGNOBJECT, - {'x': Blockly.Bubble.BORDER_WIDTH, 'y': Blockly.Bubble.BORDER_WIDTH}, + this.foreignObject_ = createSvgElement( + Svg.FOREIGNOBJECT, {'x': Bubble.BORDER_WIDTH, 'y': Bubble.BORDER_WIDTH}, null); - var body = document.createElementNS(Blockly.utils.dom.HTML_NS, 'body'); - body.setAttribute('xmlns', Blockly.utils.dom.HTML_NS); + const body = document.createElementNS(HTML_NS, 'body'); + body.setAttribute('xmlns', HTML_NS); body.className = 'blocklyMinimalBody'; - this.textarea_ = document.createElementNS( - Blockly.utils.dom.HTML_NS, 'textarea'); - var textarea = this.textarea_; + this.textarea_ = document.createElementNS(HTML_NS, 'textarea'); + const textarea = this.textarea_; textarea.className = 'blocklyCommentTextarea'; textarea.setAttribute('dir', this.block_.RTL ? 'RTL' : 'LTR'); textarea.value = this.model_.text; @@ -170,26 +172,23 @@ Blockly.Comment.prototype.createEditor_ = function() { // Ideally this would be hooked to the focus event for the comment. // However doing so in Firefox swallows the cursor for unknown reasons. // So this is hooked to mouseup instead. No big deal. - this.onMouseUpWrapper_ = Blockly.browserEvents.conditionalBind( - textarea, 'mouseup', this, this.startEdit_, true, true); + this.onMouseUpWrapper_ = + conditionalBind(textarea, 'mouseup', this, this.startEdit_, true, true); // Don't zoom with mousewheel. - this.onWheelWrapper_ = Blockly.browserEvents.conditionalBind( - textarea, 'wheel', this, function(e) { - e.stopPropagation(); - }); - this.onChangeWrapper_ = Blockly.browserEvents.conditionalBind( - textarea, 'change', this, function(_e) { + this.onWheelWrapper_ = conditionalBind(textarea, 'wheel', this, function(e) { + e.stopPropagation(); + }); + this.onChangeWrapper_ = + conditionalBind(textarea, 'change', this, function(_e) { if (this.cachedText_ != this.model_.text) { - Blockly.Events.fire( - new (Blockly.Events.get(Blockly.Events.BLOCK_CHANGE))( - this.block_, 'comment', null, this.cachedText_, - this.model_.text)); + Events.fire(new (Events.get(Events.BLOCK_CHANGE))( + this.block_, 'comment', null, this.cachedText_, + this.model_.text)); } }); - this.onInputWrapper_ = Blockly.browserEvents.conditionalBind( - textarea, 'input', this, function(_e) { - this.model_.text = textarea.value; - }); + this.onInputWrapper_ = conditionalBind(textarea, 'input', this, function(_e) { + this.model_.text = textarea.value; + }); setTimeout(textarea.focus.bind(textarea), 0); @@ -200,8 +199,8 @@ Blockly.Comment.prototype.createEditor_ = function() { * Add or remove editability of the comment. * @override */ -Blockly.Comment.prototype.updateEditable = function() { - Blockly.Comment.superClass_.updateEditable.call(this); +Comment.prototype.updateEditable = function() { + Comment.superClass_.updateEditable.call(this); if (this.isVisible()) { // Recreate the bubble with the correct UI. this.disposeBubble_(); @@ -214,7 +213,7 @@ Blockly.Comment.prototype.updateEditable = function() { * Resize the text area accordingly. * @private */ -Blockly.Comment.prototype.onBubbleResize_ = function() { +Comment.prototype.onBubbleResize_ = function() { if (!this.isVisible()) { return; } @@ -227,11 +226,11 @@ Blockly.Comment.prototype.onBubbleResize_ = function() { * the size of the bubble). * @private */ -Blockly.Comment.prototype.resizeTextarea_ = function() { - var size = this.model_.size; - var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH; - var widthMinusBorder = size.width - doubleBorderWidth; - var heightMinusBorder = size.height - doubleBorderWidth; +Comment.prototype.resizeTextarea_ = function() { + const size = this.model_.size; + const doubleBorderWidth = 2 * Bubble.BORDER_WIDTH; + const widthMinusBorder = size.width - doubleBorderWidth; + const heightMinusBorder = size.height - doubleBorderWidth; this.foreignObject_.setAttribute('width', widthMinusBorder); this.foreignObject_.setAttribute('height', heightMinusBorder); this.textarea_.style.width = (widthMinusBorder - 4) + 'px'; @@ -242,12 +241,12 @@ Blockly.Comment.prototype.resizeTextarea_ = function() { * Show or hide the comment bubble. * @param {boolean} visible True if the bubble should be visible. */ -Blockly.Comment.prototype.setVisible = function(visible) { +Comment.prototype.setVisible = function(visible) { if (visible == this.isVisible()) { return; } - Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.BUBBLE_OPEN))( - this.block_, visible, 'comment')); + Events.fire( + new (Events.get(Events.BUBBLE_OPEN))(this.block_, visible, 'comment')); this.model_.pinned = visible; if (visible) { this.createBubble_(); @@ -260,8 +259,8 @@ Blockly.Comment.prototype.setVisible = function(visible) { * Show the bubble. Handles deciding if it should be editable or not. * @private */ -Blockly.Comment.prototype.createBubble_ = function() { - if (!this.block_.isEditable() || Blockly.utils.userAgent.IE) { +Comment.prototype.createBubble_ = function() { + if (!this.block_.isEditable() || userAgent.IE) { // MSIE does not support foreignobject; textareas are impossible. // https://docs.microsoft.com/en-us/openspecs/ie_standards/ms-svg/56e6e04c-7c8c-44dd-8100-bd745ee42034 // Always treat comments in IE as uneditable. @@ -275,12 +274,12 @@ Blockly.Comment.prototype.createBubble_ = function() { * Show an editable bubble. * @private */ -Blockly.Comment.prototype.createEditableBubble_ = function() { - this.bubble_ = new Blockly.Bubble( - /** @type {!Blockly.WorkspaceSvg} */ (this.block_.workspace), +Comment.prototype.createEditableBubble_ = function() { + this.bubble_ = new Bubble( + /** @type {!WorkspaceSvg} */ (this.block_.workspace), this.createEditor_(), this.block_.pathObject.svgPath, - /** @type {!Blockly.utils.Coordinate} */ (this.iconXY_), - this.model_.size.width, this.model_.size.height); + /** @type {!Coordinate} */ (this.iconXY_), this.model_.size.width, + this.model_.size.height); // Expose this comment's block's ID on its top-level SVG group. this.bubble_.setSvgId(this.block_.id); this.bubble_.registerResizeEvent(this.onBubbleResize_.bind(this)); @@ -292,12 +291,12 @@ Blockly.Comment.prototype.createEditableBubble_ = function() { * @private * @suppress {checkTypes} Suppress `this` type mismatch. */ -Blockly.Comment.prototype.createNonEditableBubble_ = function() { +Comment.prototype.createNonEditableBubble_ = function() { // TODO (#2917): It would be great if the comment could support line breaks. - this.paragraphElement_ = Blockly.Bubble.textToDom(this.block_.getCommentText()); - this.bubble_ = Blockly.Bubble.createNonEditableBubble( - this.paragraphElement_, /** @type {!Blockly.BlockSvg} */ (this.block_), - /** @type {!Blockly.utils.Coordinate} */ (this.iconXY_)); + this.paragraphElement_ = Bubble.textToDom(this.block_.getCommentText()); + this.bubble_ = Bubble.createNonEditableBubble( + this.paragraphElement_, /** @type {!BlockSvg} */ (this.block_), + /** @type {!Coordinate} */ (this.iconXY_)); this.applyColour(); }; @@ -306,21 +305,21 @@ Blockly.Comment.prototype.createNonEditableBubble_ = function() { * @private * @suppress {checkTypes} Suppress `this` type mismatch. */ -Blockly.Comment.prototype.disposeBubble_ = function() { +Comment.prototype.disposeBubble_ = function() { if (this.onMouseUpWrapper_) { - Blockly.browserEvents.unbind(this.onMouseUpWrapper_); + unbind(this.onMouseUpWrapper_); this.onMouseUpWrapper_ = null; } if (this.onWheelWrapper_) { - Blockly.browserEvents.unbind(this.onWheelWrapper_); + unbind(this.onWheelWrapper_); this.onWheelWrapper_ = null; } if (this.onChangeWrapper_) { - Blockly.browserEvents.unbind(this.onChangeWrapper_); + unbind(this.onChangeWrapper_); this.onChangeWrapper_ = null; } if (this.onInputWrapper_) { - Blockly.browserEvents.unbind(this.onInputWrapper_); + unbind(this.onInputWrapper_); this.onInputWrapper_ = null; } this.bubble_.dispose(); @@ -338,7 +337,7 @@ Blockly.Comment.prototype.disposeBubble_ = function() { * @param {!Event} _e Mouse up event. * @private */ -Blockly.Comment.prototype.startEdit_ = function(_e) { +Comment.prototype.startEdit_ = function(_e) { if (this.bubble_.promote()) { // Since the act of moving this node within the DOM causes a loss of focus, // we need to reapply the focus. @@ -350,9 +349,9 @@ Blockly.Comment.prototype.startEdit_ = function(_e) { /** * Get the dimensions of this comment's bubble. - * @return {Blockly.utils.Size} Object with width and height properties. + * @return {Size} Object with width and height properties. */ -Blockly.Comment.prototype.getBubbleSize = function() { +Comment.prototype.getBubbleSize = function() { return this.model_.size; }; @@ -361,7 +360,7 @@ Blockly.Comment.prototype.getBubbleSize = function() { * @param {number} width Width of the bubble. * @param {number} height Height of the bubble. */ -Blockly.Comment.prototype.setBubbleSize = function(width, height) { +Comment.prototype.setBubbleSize = function(width, height) { if (this.bubble_) { this.bubble_.setBubbleSize(width, height); } else { @@ -374,7 +373,7 @@ Blockly.Comment.prototype.setBubbleSize = function(width, height) { * Update the comment's view to match the model. * @package */ -Blockly.Comment.prototype.updateText = function() { +Comment.prototype.updateText = function() { if (this.textarea_) { this.textarea_.value = this.model_.text; } else if (this.paragraphElement_) { @@ -390,25 +389,20 @@ Blockly.Comment.prototype.updateText = function() { * If you want to receive a comment "delete" event (newValue: null), then this * should not be called directly. Instead call block.setCommentText(null); */ -Blockly.Comment.prototype.dispose = function() { +Comment.prototype.dispose = function() { this.block_.comment = null; - Blockly.Icon.prototype.dispose.call(this); + Icon.prototype.dispose.call(this); }; /** * CSS for block comment. See css.js for use. */ -Blockly.Css.register([ +register([ /* eslint-disable indent */ - '.blocklyCommentTextarea {', - 'background-color: #fef49c;', - 'border: 0;', - 'outline: 0;', - 'margin: 0;', - 'padding: 3px;', - 'resize: none;', - 'display: block;', - 'text-overflow: hidden;', - '}' + '.blocklyCommentTextarea {', 'background-color: #fef49c;', 'border: 0;', + 'outline: 0;', 'margin: 0;', 'padding: 3px;', 'resize: none;', + 'display: block;', 'text-overflow: hidden;', '}' /* eslint-enable indent */ ]); + +exports = Comment; diff --git a/core/component_manager.js b/core/component_manager.js index d8b215504..ad2370bd6 100644 --- a/core/component_manager.js +++ b/core/component_manager.js @@ -11,23 +11,29 @@ 'use strict'; -goog.provide('Blockly.ComponentManager'); +goog.module('Blockly.ComponentManager'); +goog.module.declareLegacyNamespace(); -goog.requireType('Blockly.IAutoHideable'); -goog.requireType('Blockly.IComponent'); -goog.requireType('Blockly.IDeleteArea'); -goog.requireType('Blockly.IDragTarget'); -goog.requireType('Blockly.IPositionable'); +/* eslint-disable-next-line no-unused-vars */ +const IAutoHideable = goog.requireType('Blockly.IAutoHideable'); +/* eslint-disable-next-line no-unused-vars */ +const IComponent = goog.requireType('Blockly.IComponent'); +/* eslint-disable-next-line no-unused-vars */ +const IDeleteArea = goog.requireType('Blockly.IDeleteArea'); +/* eslint-disable-next-line no-unused-vars */ +const IDragTarget = goog.requireType('Blockly.IDragTarget'); +/* eslint-disable-next-line no-unused-vars */ +const IPositionable = goog.requireType('Blockly.IPositionable'); /** * Manager for all items registered with the workspace. * @constructor */ -Blockly.ComponentManager = function() { +const ComponentManager = function() { /** * A map of the components registered with the workspace, mapped to id. - * @type {!Object} + * @type {!Object} * @private */ this.componentData_ = Object.create(null); @@ -43,35 +49,35 @@ Blockly.ComponentManager = function() { /** * An object storing component information. * @typedef {{ - * component: !Blockly.IComponent, + * component: !IComponent, * capabilities: ( - * !Array> + * !Array> * ), * weight: number * }} */ -Blockly.ComponentManager.ComponentDatum; +ComponentManager.ComponentDatum; /** * Adds a component. - * @param {!Blockly.ComponentManager.ComponentDatum} componentInfo The data for + * @param {!ComponentManager.ComponentDatum} componentInfo The data for * the component to register. * @param {boolean=} opt_allowOverrides True to prevent an error when overriding * an already registered item. */ -Blockly.ComponentManager.prototype.addComponent = function( +ComponentManager.prototype.addComponent = function( componentInfo, opt_allowOverrides) { // Don't throw an error if opt_allowOverrides is true. - var id = componentInfo.component.id; + const id = componentInfo.component.id; if (!opt_allowOverrides && this.componentData_[id]) { throw Error( 'Plugin "' + id + '" with capabilities "' + this.componentData_[id].capabilities + '" already added.'); } this.componentData_[id] = componentInfo; - var stringCapabilities = []; - for (var i = 0; i < componentInfo.capabilities.length; i++) { - var capability = String(componentInfo.capabilities[i]).toLowerCase(); + const stringCapabilities = []; + for (let i = 0; i < componentInfo.capabilities.length; i++) { + const capability = String(componentInfo.capabilities[i]).toLowerCase(); stringCapabilities.push(capability); if (this.capabilityToComponentIds_[capability] === undefined) { this.capabilityToComponentIds_[capability] = [id]; @@ -86,13 +92,13 @@ Blockly.ComponentManager.prototype.addComponent = function( * Removes a component. * @param {string} id The ID of the component to remove. */ -Blockly.ComponentManager.prototype.removeComponent = function(id) { - var componentInfo = this.componentData_[id]; +ComponentManager.prototype.removeComponent = function(id) { + const componentInfo = this.componentData_[id]; if (!componentInfo) { return; } - for (var i = 0; i < componentInfo.capabilities.length; i++) { - var capability = String(componentInfo.capabilities[i]).toLowerCase(); + for (let i = 0; i < componentInfo.capabilities.length; i++) { + const capability = String(componentInfo.capabilities[i]).toLowerCase(); this.capabilityToComponentIds_[capability].splice( this.capabilityToComponentIds_[capability].indexOf(id), 1); } @@ -102,18 +108,19 @@ Blockly.ComponentManager.prototype.removeComponent = function(id) { /** * Adds a capability to a existing registered component. * @param {string} id The ID of the component to add the capability to. - * @param {string|!Blockly.ComponentManager.Capability} capability The + * @param {string|!ComponentManager.Capability} capability The * capability to add. * @template T */ -Blockly.ComponentManager.prototype.addCapability = function(id, capability) { +ComponentManager.prototype.addCapability = function(id, capability) { if (!this.getComponent(id)) { - throw Error('Cannot add capability, "' + capability + '". Plugin "' + - id + '" has not been added to the ComponentManager'); + throw Error( + 'Cannot add capability, "' + capability + '". Plugin "' + id + + '" has not been added to the ComponentManager'); } if (this.hasCapability(id, capability)) { - console.warn('Plugin "' + id + 'already has capability "' + - capability + '"'); + console.warn( + 'Plugin "' + id + 'already has capability "' + capability + '"'); return; } capability = String(capability).toLowerCase(); @@ -124,18 +131,20 @@ Blockly.ComponentManager.prototype.addCapability = function(id, capability) { /** * Removes a capability from an existing registered component. * @param {string} id The ID of the component to remove the capability from. - * @param {string|!Blockly.ComponentManager.Capability} capability The + * @param {string|!ComponentManager.Capability} capability The * capability to remove. * @template T */ -Blockly.ComponentManager.prototype.removeCapability = function(id, capability) { +ComponentManager.prototype.removeCapability = function(id, capability) { if (!this.getComponent(id)) { - throw Error('Cannot remove capability, "' + capability + '". Plugin "' + - id + '" has not been added to the ComponentManager'); + throw Error( + 'Cannot remove capability, "' + capability + '". Plugin "' + id + + '" has not been added to the ComponentManager'); } if (!this.hasCapability(id, capability)) { - console.warn('Plugin "' + id + 'doesn\'t have capability "' + - capability + '" to remove'); + console.warn( + 'Plugin "' + id + 'doesn\'t have capability "' + capability + + '" to remove'); return; } capability = String(capability).toLowerCase(); @@ -148,12 +157,12 @@ Blockly.ComponentManager.prototype.removeCapability = function(id, capability) { /** * Returns whether the component with this id has the specified capability. * @param {string} id The ID of the component to check. - * @param {string|!Blockly.ComponentManager.Capability} capability The + * @param {string|!ComponentManager.Capability} capability The * capability to check for. * @return {boolean} Whether the component has the capability. * @template T */ -Blockly.ComponentManager.prototype.hasCapability = function(id, capability) { +ComponentManager.prototype.hasCapability = function(id, capability) { capability = String(capability).toLowerCase(); return this.componentData_[id].capabilities.indexOf(capability) !== -1; }; @@ -161,31 +170,31 @@ Blockly.ComponentManager.prototype.hasCapability = function(id, capability) { /** * Gets the component with the given ID. * @param {string} id The ID of the component to get. - * @return {!Blockly.IComponent|undefined} The component with the given name + * @return {!IComponent|undefined} The component with the given name * or undefined if not found. */ -Blockly.ComponentManager.prototype.getComponent = function(id) { +ComponentManager.prototype.getComponent = function(id) { return this.componentData_[id] && this.componentData_[id].component; }; /** * Gets all the components with the specified capability. - * @param {string|!Blockly.ComponentManager.Capability + * @param {string|!ComponentManager.Capability * } capability The capability of the component. * @param {boolean} sorted Whether to return list ordered by weights. * @return {!Array} The components that match the specified capability. * @template T */ -Blockly.ComponentManager.prototype.getComponents = function(capability, sorted) { +ComponentManager.prototype.getComponents = function(capability, sorted) { capability = String(capability).toLowerCase(); - var componentIds = this.capabilityToComponentIds_[capability]; + const componentIds = this.capabilityToComponentIds_[capability]; if (!componentIds) { return []; } - var components = []; + const components = []; if (sorted) { - var componentDataList = []; - var componentData = this.componentData_; + const componentDataList = []; + const componentData = this.componentData_; componentIds.forEach(function(id) { componentDataList.push(componentData[id]); }); @@ -196,7 +205,7 @@ Blockly.ComponentManager.prototype.getComponents = function(capability, sorted) components.push(ComponentDatum.component); }); } else { - var componentData = this.componentData_; + const componentData = this.componentData_; componentIds.forEach(function(id) { components.push(componentData[id].component); }); @@ -210,7 +219,7 @@ Blockly.ComponentManager.prototype.getComponents = function(capability, sorted) * @constructor * @template T */ -Blockly.ComponentManager.Capability = function(name) { +ComponentManager.Capability = function(name) { /** * @type {string} * @private @@ -223,22 +232,24 @@ Blockly.ComponentManager.Capability = function(name) { * @return {string} The name. * @override */ -Blockly.ComponentManager.Capability.prototype.toString = function() { +ComponentManager.Capability.prototype.toString = function() { return this.name_; }; -/** @type {!Blockly.ComponentManager.Capability} */ -Blockly.ComponentManager.Capability.POSITIONABLE = - new Blockly.ComponentManager.Capability('positionable'); +/** @type {!ComponentManager.Capability} */ +ComponentManager.Capability.POSITIONABLE = + new ComponentManager.Capability('positionable'); -/** @type {!Blockly.ComponentManager.Capability} */ -Blockly.ComponentManager.Capability.DRAG_TARGET = - new Blockly.ComponentManager.Capability('drag_target'); +/** @type {!ComponentManager.Capability} */ +ComponentManager.Capability.DRAG_TARGET = + new ComponentManager.Capability('drag_target'); -/** @type {!Blockly.ComponentManager.Capability} */ -Blockly.ComponentManager.Capability.DELETE_AREA = - new Blockly.ComponentManager.Capability('delete_area'); +/** @type {!ComponentManager.Capability} */ +ComponentManager.Capability.DELETE_AREA = + new ComponentManager.Capability('delete_area'); -/** @type {!Blockly.ComponentManager.Capability} */ -Blockly.ComponentManager.Capability.AUTOHIDEABLE = - new Blockly.ComponentManager.Capability('autohideable'); +/** @type {!ComponentManager.Capability} */ +ComponentManager.Capability.AUTOHIDEABLE = + new ComponentManager.Capability('autohideable'); + +exports = ComponentManager; diff --git a/core/connection.js b/core/connection.js index 27526c711..f272b59e0 100644 --- a/core/connection.js +++ b/core/connection.js @@ -10,33 +10,37 @@ */ 'use strict'; -goog.provide('Blockly.Connection'); +goog.module('Blockly.Connection'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.connectionTypes'); +/* eslint-disable-next-line no-unused-vars */ +const Block = goog.requireType('Blockly.Block'); +const Events = goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const IASTNodeLocationWithBlock = goog.require('Blockly.IASTNodeLocationWithBlock'); +/* eslint-disable-next-line no-unused-vars */ +const IConnectionChecker = goog.requireType('Blockly.IConnectionChecker'); +/* eslint-disable-next-line no-unused-vars */ +const Input = goog.requireType('Blockly.Input'); +const Xml = goog.require('Blockly.Xml'); +const connectionTypes = goog.require('Blockly.connectionTypes'); +const deprecation = goog.require('Blockly.utils.deprecation'); /** @suppress {extraRequire} */ goog.require('Blockly.constants'); -goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockMove'); -goog.require('Blockly.IASTNodeLocationWithBlock'); -goog.require('Blockly.utils.deprecation'); -goog.require('Blockly.Xml'); - -goog.requireType('Blockly.Block'); -goog.requireType('Blockly.IConnectionChecker'); -goog.requireType('Blockly.Input'); /** * Class for a connection between blocks. - * @param {!Blockly.Block} source The block establishing this connection. + * @param {!Block} source The block establishing this connection. * @param {number} type The type of the connection. * @constructor - * @implements {Blockly.IASTNodeLocationWithBlock} + * @implements {IASTNodeLocationWithBlock} */ -Blockly.Connection = function(source, type) { +const Connection = function(source, type) { /** - * @type {!Blockly.Block} + * @type {!Block} * @protected */ this.sourceBlock_ = source; @@ -47,67 +51,67 @@ Blockly.Connection = function(source, type) { /** * Constants for checking whether two connections are compatible. */ -Blockly.Connection.CAN_CONNECT = 0; -Blockly.Connection.REASON_SELF_CONNECTION = 1; -Blockly.Connection.REASON_WRONG_TYPE = 2; -Blockly.Connection.REASON_TARGET_NULL = 3; -Blockly.Connection.REASON_CHECKS_FAILED = 4; -Blockly.Connection.REASON_DIFFERENT_WORKSPACES = 5; -Blockly.Connection.REASON_SHADOW_PARENT = 6; -Blockly.Connection.REASON_DRAG_CHECKS_FAILED = 7; +Connection.CAN_CONNECT = 0; +Connection.REASON_SELF_CONNECTION = 1; +Connection.REASON_WRONG_TYPE = 2; +Connection.REASON_TARGET_NULL = 3; +Connection.REASON_CHECKS_FAILED = 4; +Connection.REASON_DIFFERENT_WORKSPACES = 5; +Connection.REASON_SHADOW_PARENT = 6; +Connection.REASON_DRAG_CHECKS_FAILED = 7; /** * Connection this connection connects to. Null if not connected. - * @type {Blockly.Connection} + * @type {Connection} */ -Blockly.Connection.prototype.targetConnection = null; +Connection.prototype.targetConnection = null; /** * Has this connection been disposed of? * @type {boolean} * @package */ -Blockly.Connection.prototype.disposed = false; +Connection.prototype.disposed = false; /** * List of compatible value types. Null if all types are compatible. * @type {Array} * @private */ -Blockly.Connection.prototype.check_ = null; +Connection.prototype.check_ = null; /** * DOM representation of a shadow block, or null if none. * @type {Element} * @private */ -Blockly.Connection.prototype.shadowDom_ = null; +Connection.prototype.shadowDom_ = null; /** * Horizontal location of this connection. * @type {number} * @package */ -Blockly.Connection.prototype.x = 0; +Connection.prototype.x = 0; /** * Vertical location of this connection. * @type {number} * @package */ -Blockly.Connection.prototype.y = 0; +Connection.prototype.y = 0; /** * Connect two connections together. This is the connection on the superior * block. - * @param {!Blockly.Connection} childConnection Connection on inferior block. + * @param {!Connection} childConnection Connection on inferior block. * @protected */ -Blockly.Connection.prototype.connect_ = function(childConnection) { - var INPUT = Blockly.connectionTypes.INPUT_VALUE; - var parentConnection = this; - var parentBlock = parentConnection.getSourceBlock(); - var childBlock = childConnection.getSourceBlock(); +Connection.prototype.connect_ = function(childConnection) { + const INPUT = connectionTypes.INPUT_VALUE; + const parentConnection = this; + const parentBlock = parentConnection.getSourceBlock(); + const childBlock = childConnection.getSourceBlock(); // Make sure the childConnection is available. if (childConnection.isConnected()) { @@ -115,11 +119,11 @@ Blockly.Connection.prototype.connect_ = function(childConnection) { } // Make sure the parentConnection is available. - var orphan; + let orphan; if (parentConnection.isConnected()) { - var shadowDom = parentConnection.getShadowDom(true); + const shadowDom = parentConnection.getShadowDom(true); parentConnection.shadowDom_ = null; // Set to null so it doesn't respawn. - var target = parentConnection.targetBlock(); + const target = parentConnection.targetBlock(); if (target.isShadow()) { target.dispose(false); } else { @@ -130,23 +134,24 @@ Blockly.Connection.prototype.connect_ = function(childConnection) { } // Connect the new connection to the parent. - var event; - if (Blockly.Events.isEnabled()) { - event = new (Blockly.Events.get(Blockly.Events.BLOCK_MOVE))(childBlock); + let event; + if (Events.isEnabled()) { + event = new (Events.get(Events.BLOCK_MOVE))(childBlock); } - Blockly.Connection.connectReciprocally_(parentConnection, childConnection); + connectReciprocally(parentConnection, childConnection); childBlock.setParent(parentBlock); if (event) { event.recordNew(); - Blockly.Events.fire(event); + Events.fire(event); } // Deal with the orphan if it exists. if (orphan) { - var orphanConnection = parentConnection.type === INPUT ? - orphan.outputConnection : orphan.previousConnection; - var connection = Blockly.Connection.getConnectionForOrphanedConnection( - childBlock, /** @type {!Blockly.Connection} */ (orphanConnection)); + const orphanConnection = parentConnection.type === INPUT ? + orphan.outputConnection : + orphan.previousConnection; + const connection = Connection.getConnectionForOrphanedConnection( + childBlock, /** @type {!Connection} */ (orphanConnection)); if (connection) { orphanConnection.connect(connection); } else { @@ -160,14 +165,13 @@ Blockly.Connection.prototype.connect_ = function(childConnection) { * Dispose of this connection and deal with connected blocks. * @package */ -Blockly.Connection.prototype.dispose = function() { - +Connection.prototype.dispose = function() { // isConnected returns true for shadows and non-shadows. if (this.isConnected()) { // Destroy the attached shadow block & its children (if it exists). this.setShadowDom(null); - var targetBlock = this.targetBlock(); + const targetBlock = this.targetBlock(); if (targetBlock) { // Disconnect the attached normal block. targetBlock.unplug(); @@ -179,9 +183,9 @@ Blockly.Connection.prototype.dispose = function() { /** * Get the source block for this connection. - * @return {!Blockly.Block} The source block. + * @return {!Block} The source block. */ -Blockly.Connection.prototype.getSourceBlock = function() { +Connection.prototype.getSourceBlock = function() { return this.sourceBlock_; }; @@ -189,82 +193,75 @@ Blockly.Connection.prototype.getSourceBlock = function() { * Does the connection belong to a superior block (higher in the source stack)? * @return {boolean} True if connection faces down or right. */ -Blockly.Connection.prototype.isSuperior = function() { - return this.type == Blockly.connectionTypes.INPUT_VALUE || - this.type == Blockly.connectionTypes.NEXT_STATEMENT; +Connection.prototype.isSuperior = function() { + return this.type == connectionTypes.INPUT_VALUE || + this.type == connectionTypes.NEXT_STATEMENT; }; /** * Is the connection connected? * @return {boolean} True if connection is connected to another connection. */ -Blockly.Connection.prototype.isConnected = function() { +Connection.prototype.isConnected = function() { return !!this.targetConnection; }; /** * Checks whether the current connection can connect with the target * connection. - * @param {Blockly.Connection} target Connection to check compatibility with. - * @return {number} Blockly.Connection.CAN_CONNECT if the connection is legal, + * @param {Connection} target Connection to check compatibility with. + * @return {number} Connection.CAN_CONNECT if the connection is legal, * an error code otherwise. * @deprecated July 2020. Will be deleted July 2021. Use the workspace's * connectionChecker instead. */ -Blockly.Connection.prototype.canConnectWithReason = function(target) { - Blockly.utils.deprecation.warn( - 'Connection.prototype.canConnectWithReason', - 'July 2020', - 'July 2021', +Connection.prototype.canConnectWithReason = function(target) { + deprecation.warn( + 'Connection.prototype.canConnectWithReason', 'July 2020', 'July 2021', 'the workspace\'s connection checker'); - return this.getConnectionChecker().canConnectWithReason( - this, target, false); + return this.getConnectionChecker().canConnectWithReason(this, target, false); }; /** * Checks whether the current connection and target connection are compatible * and throws an exception if they are not. - * @param {Blockly.Connection} target The connection to check compatibility + * @param {Connection} target The connection to check compatibility * with. * @package * @deprecated July 2020. Will be deleted July 2021. Use the workspace's * connectionChecker instead. */ -Blockly.Connection.prototype.checkConnection = function(target) { - Blockly.utils.deprecation.warn( - 'Connection.prototype.checkConnection', - 'July 2020', - 'July 2021', +Connection.prototype.checkConnection = function(target) { + deprecation.warn( + 'Connection.prototype.checkConnection', 'July 2020', 'July 2021', 'the workspace\'s connection checker'); - var checker = this.getConnectionChecker(); - var reason = checker.canConnectWithReason(this, target, false); - if (reason != Blockly.Connection.CAN_CONNECT) { + const checker = this.getConnectionChecker(); + const reason = checker.canConnectWithReason(this, target, false); + if (reason != Connection.CAN_CONNECT) { throw new Error(checker.getErrorMessage(reason, this, target)); } }; /** * Get the workspace's connection type checker object. - * @return {!Blockly.IConnectionChecker} The connection type checker for the + * @return {!IConnectionChecker} The connection type checker for the * source block's workspace. * @package */ -Blockly.Connection.prototype.getConnectionChecker = function() { +Connection.prototype.getConnectionChecker = function() { return this.sourceBlock_.workspace.connectionChecker; }; /** * 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. * @return {boolean} True if the connection is allowed, false otherwise. * @deprecated July 2020. Will be deleted July 2021. Use the workspace's * connectionChecker instead. */ -Blockly.Connection.prototype.isConnectionAllowed = function(candidate) { - Blockly.utils.deprecation.warn( - 'Connection.prototype.isConnectionAllowed', - 'July 2020', - 'July 2021', +Connection.prototype.isConnectionAllowed = function(candidate) { + deprecation.warn( + 'Connection.prototype.isConnectionAllowed', 'July 2020', 'July 2021', 'the workspace\'s connection checker'); return this.getConnectionChecker().canConnect(this, candidate, true); }; @@ -272,29 +269,29 @@ Blockly.Connection.prototype.isConnectionAllowed = function(candidate) { /** * Called when an attempted connection fails. NOP by default (i.e. for headless * workspaces). - * @param {!Blockly.Connection} _otherConnection Connection that this connection + * @param {!Connection} _otherConnection Connection that this connection * failed to connect to. * @package */ -Blockly.Connection.prototype.onFailedConnect = function(_otherConnection) { +Connection.prototype.onFailedConnect = function(_otherConnection) { // NOP }; /** * Connect this connection to another connection. - * @param {!Blockly.Connection} otherConnection Connection to connect to. + * @param {!Connection} otherConnection Connection to connect to. */ -Blockly.Connection.prototype.connect = function(otherConnection) { +Connection.prototype.connect = function(otherConnection) { if (this.targetConnection == otherConnection) { // Already connected together. NOP. return; } - var checker = this.getConnectionChecker(); + const checker = this.getConnectionChecker(); if (checker.canConnect(this, otherConnection, false)) { - var eventGroup = Blockly.Events.getGroup(); + const eventGroup = Events.getGroup(); if (!eventGroup) { - Blockly.Events.setGroup(true); + Events.setGroup(true); } // Determine which block is superior (higher in the source stack). if (this.isSuperior()) { @@ -305,18 +302,17 @@ Blockly.Connection.prototype.connect = function(otherConnection) { otherConnection.connect_(this); } if (!eventGroup) { - Blockly.Events.setGroup(false); + Events.setGroup(false); } } }; /** * Update two connections to target each other. - * @param {Blockly.Connection} first The first connection to update. - * @param {Blockly.Connection} second The second connection to update. - * @private + * @param {Connection} first The first connection to update. + * @param {Connection} second The second connection to update. */ -Blockly.Connection.connectReciprocally_ = function(first, second) { +const connectReciprocally = function(first, second) { if (!first || !second) { throw Error('Cannot connect null connections.'); } @@ -329,19 +325,18 @@ Blockly.Connection.connectReciprocally_ = function(first, second) { * block, if one can be found. If the block has multiple compatible connections * (even if they are filled) this returns null. If the block has no compatible * connections, this returns null. - * @param {!Blockly.Block} block The superior block. - * @param {!Blockly.Block} orphanBlock The inferior block. - * @return {?Blockly.Connection} The suitable connection point on 'block', + * @param {!Block} block The superior block. + * @param {!Block} orphanBlock The inferior block. + * @return {?Connection} The suitable connection point on 'block', * or null. - * @private */ -Blockly.Connection.getSingleConnection_ = function(block, orphanBlock) { - var foundConnection = null; - var output = orphanBlock.outputConnection; - var typeChecker = output.getConnectionChecker(); +const getSingleConnection = function(block, orphanBlock) { + let foundConnection = null; + const output = orphanBlock.outputConnection; + const typeChecker = output.getConnectionChecker(); - for (var i = 0, input; (input = block.inputList[i]); i++) { - var connection = input.connection; + for (let i = 0, input; (input = block.inputList[i]); i++) { + const connection = input.connection; if (connection && typeChecker.canConnect(output, connection, false)) { if (foundConnection) { return null; // More than one connection. @@ -358,64 +353,62 @@ Blockly.Connection.getSingleConnection_ = function(block, orphanBlock) { * are zero or multiple eligible connections, returns null. Otherwise * returns the only input on the last block in the chain. * Terminates early for shadow blocks. - * @param {!Blockly.Block} startBlock The block on which to start the search. - * @param {!Blockly.Block} orphanBlock The block that is looking for a home. - * @return {?Blockly.Connection} The suitable connection point on the chain + * @param {!Block} startBlock The block on which to start the search. + * @param {!Block} orphanBlock The block that is looking for a home. + * @return {?Connection} The suitable connection point on the chain * of blocks, or null. - * @private */ -Blockly.Connection.getConnectionForOrphanedOutput_ = - function(startBlock, orphanBlock) { - var newBlock = startBlock; - var connection; - while ((connection = Blockly.Connection.getSingleConnection_( - /** @type {!Blockly.Block} */ (newBlock), orphanBlock))) { - newBlock = connection.targetBlock(); - if (!newBlock || newBlock.isShadow()) { - return connection; - } - } - return null; - }; +const getConnectionForOrphanedOutput = function(startBlock, orphanBlock) { + let newBlock = startBlock; + let connection; + while ( + (connection = getSingleConnection( + /** @type {!Block} */ (newBlock), orphanBlock))) { + newBlock = connection.targetBlock(); + if (!newBlock || newBlock.isShadow()) { + return connection; + } + } + return null; +}; /** * Returns the connection (starting at the startBlock) which will accept * the given connection. This includes compatible connection types and * connection checks. - * @param {!Blockly.Block} startBlock The block on which to start the search. - * @param {!Blockly.Connection} orphanConnection The connection that is looking + * @param {!Block} startBlock The block on which to start the search. + * @param {!Connection} orphanConnection The connection that is looking * for a home. - * @return {?Blockly.Connection} The suitable connection point on the chain of + * @return {?Connection} The suitable connection point on the chain of * blocks, or null. */ -Blockly.Connection.getConnectionForOrphanedConnection = - function(startBlock, orphanConnection) { - if (orphanConnection.type === Blockly.connectionTypes.OUTPUT_VALUE) { - return Blockly.Connection.getConnectionForOrphanedOutput_( - startBlock, orphanConnection.getSourceBlock()); - } - // Otherwise we're dealing with a stack. - var connection = startBlock.lastConnectionInStack(true); - var checker = orphanConnection.getConnectionChecker(); - if (connection && - checker.canConnect(orphanConnection, connection, false)) { - return connection; - } - return null; - }; +Connection.getConnectionForOrphanedConnection = function( + startBlock, orphanConnection) { + if (orphanConnection.type === connectionTypes.OUTPUT_VALUE) { + return getConnectionForOrphanedOutput( + startBlock, orphanConnection.getSourceBlock()); + } + // Otherwise we're dealing with a stack. + const connection = startBlock.lastConnectionInStack(true); + const checker = orphanConnection.getConnectionChecker(); + if (connection && checker.canConnect(orphanConnection, connection, false)) { + return connection; + } + return null; +}; /** * Disconnect this connection. */ -Blockly.Connection.prototype.disconnect = function() { - var otherConnection = this.targetConnection; +Connection.prototype.disconnect = function() { + const otherConnection = this.targetConnection; if (!otherConnection) { throw Error('Source connection not connected.'); } if (otherConnection.targetConnection != this) { throw Error('Target connection not connected to source connection.'); } - var parentBlock, childBlock, parentConnection; + let parentBlock, childBlock, parentConnection; if (this.isSuperior()) { // Superior block. parentBlock = this.sourceBlock_; @@ -428,9 +421,9 @@ Blockly.Connection.prototype.disconnect = function() { parentConnection = otherConnection; } - var eventGroup = Blockly.Events.getGroup(); + const eventGroup = Events.getGroup(); if (!eventGroup) { - Blockly.Events.setGroup(true); + Events.setGroup(true); } this.disconnectInternal_(parentBlock, childBlock); if (!childBlock.isShadow()) { @@ -438,29 +431,28 @@ Blockly.Connection.prototype.disconnect = function() { parentConnection.respawnShadow_(); } if (!eventGroup) { - Blockly.Events.setGroup(false); + Events.setGroup(false); } }; /** * 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 */ -Blockly.Connection.prototype.disconnectInternal_ = function(parentBlock, - childBlock) { - var event; - if (Blockly.Events.isEnabled()) { - event = new (Blockly.Events.get(Blockly.Events.BLOCK_MOVE))(childBlock); +Connection.prototype.disconnectInternal_ = function(parentBlock, childBlock) { + let event; + if (Events.isEnabled()) { + event = new (Events.get(Events.BLOCK_MOVE))(childBlock); } - var otherConnection = this.targetConnection; + const otherConnection = this.targetConnection; otherConnection.targetConnection = null; this.targetConnection = null; childBlock.setParent(null); if (event) { event.recordNew(); - Blockly.Events.fire(event); + Events.fire(event); } }; @@ -468,11 +460,11 @@ Blockly.Connection.prototype.disconnectInternal_ = function(parentBlock, * Respawn the shadow block if there was one connected to the this connection. * @protected */ -Blockly.Connection.prototype.respawnShadow_ = function() { - var parentBlock = this.getSourceBlock(); - var shadow = this.getShadowDom(); +Connection.prototype.respawnShadow_ = function() { + const parentBlock = this.getSourceBlock(); + const shadow = this.getShadowDom(); if (parentBlock.workspace && shadow) { - var blockShadow = Blockly.Xml.domToBlock(shadow, parentBlock.workspace); + const blockShadow = Xml.domToBlock(shadow, parentBlock.workspace); if (blockShadow.outputConnection) { this.connect(blockShadow.outputConnection); } else if (blockShadow.previousConnection) { @@ -485,9 +477,9 @@ Blockly.Connection.prototype.respawnShadow_ = function() { /** * Returns the block that this connection connects to. - * @return {?Blockly.Block} The connected block or null if none is connected. + * @return {?Block} The connected block or null if none is connected. */ -Blockly.Connection.prototype.targetBlock = function() { +Connection.prototype.targetBlock = function() { if (this.isConnected()) { return this.targetConnection.getSourceBlock(); } @@ -497,36 +489,31 @@ Blockly.Connection.prototype.targetBlock = function() { /** * Is this connection compatible with another connection with respect to the * value type system. E.g. square_root("Hello") is not compatible. - * @param {!Blockly.Connection} otherConnection Connection to compare against. + * @param {!Connection} otherConnection Connection to compare against. * @return {boolean} True if the connections share a type. * @deprecated July 2020. Will be deleted July 2021. Use the workspace's * connectionChecker instead. */ -Blockly.Connection.prototype.checkType = function(otherConnection) { - Blockly.utils.deprecation.warn( - 'Connection.prototype.checkType', - 'October 2019', - 'January 2021', +Connection.prototype.checkType = function(otherConnection) { + deprecation.warn( + 'Connection.prototype.checkType', 'October 2019', 'January 2021', 'the workspace\'s connection checker'); - return this.getConnectionChecker().canConnect(this, otherConnection, - false); + return this.getConnectionChecker().canConnect(this, otherConnection, false); }; /** * Is this connection compatible with another connection with respect to the * value type system. E.g. square_root("Hello") is not compatible. - * @param {!Blockly.Connection} otherConnection Connection to compare against. + * @param {!Connection} otherConnection Connection to compare against. * @return {boolean} True if the connections share a type. * @private * @deprecated October 2019. Will be deleted January 2021. Use the workspace's * connectionChecker instead. * @suppress {unusedPrivateMembers} */ -Blockly.Connection.prototype.checkType_ = function(otherConnection) { - Blockly.utils.deprecation.warn( - 'Connection.prototype.checkType_', - 'October 2019', - 'January 2021', +Connection.prototype.checkType_ = function(otherConnection) { + deprecation.warn( + 'Connection.prototype.checkType_', 'October 2019', 'January 2021', 'the workspace\'s connection checker'); return this.checkType(otherConnection); }; @@ -535,12 +522,13 @@ Blockly.Connection.prototype.checkType_ = function(otherConnection) { * Function to be called when this connection's compatible types have changed. * @protected */ -Blockly.Connection.prototype.onCheckChanged_ = function() { +Connection.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(); } }; @@ -549,10 +537,10 @@ Blockly.Connection.prototype.onCheckChanged_ = function() { * Change a connection's compatibility. * @param {?(string|!Array)} check Compatible value type or list of * value types. Null if all types are compatible. - * @return {!Blockly.Connection} The connection being modified + * @return {!Connection} The connection being modified * (to allow chaining). */ -Blockly.Connection.prototype.setCheck = function(check) { +Connection.prototype.setCheck = function(check) { if (check) { // Ensure that check is in an array. if (!Array.isArray(check)) { @@ -572,7 +560,7 @@ Blockly.Connection.prototype.setCheck = function(check) { * Null if all types are compatible. * @public */ -Blockly.Connection.prototype.getCheck = function() { +Connection.prototype.getCheck = function() { return this.check_; }; @@ -580,9 +568,9 @@ Blockly.Connection.prototype.getCheck = function() { * Changes the connection's shadow block. * @param {?Element} shadow DOM representation of a block or null. */ -Blockly.Connection.prototype.setShadowDom = function(shadow) { +Connection.prototype.setShadowDom = function(shadow) { this.shadowDom_ = shadow; - var target = this.targetBlock(); + const target = this.targetBlock(); if (!target) { this.respawnShadow_(); } else if (target.isShadow()) { @@ -600,10 +588,10 @@ Blockly.Connection.prototype.setShadowDom = function(shadow) { * shadowDom is just returned. * @return {?Element} Shadow DOM representation of a block or null. */ -Blockly.Connection.prototype.getShadowDom = function(returnCurrent) { +Connection.prototype.getShadowDom = function(returnCurrent) { return (returnCurrent && this.targetBlock().isShadow()) ? - /** @type {!Element} */ (Blockly.Xml.blockToDom( - /** @type {!Blockly.Block} */ (this.targetBlock()))) : + /** @type {!Element} */ (Xml.blockToDom( + /** @type {!Block} */ (this.targetBlock()))) : this.shadowDom_; }; @@ -616,23 +604,23 @@ Blockly.Connection.prototype.getShadowDom = function(returnCurrent) { * {@link Blockly.RenderedConnection} overrides this behavior with a list * computed from the rendered positioning. * @param {number} _maxLimit The maximum radius to another connection. - * @return {!Array} List of connections. + * @return {!Array} List of connections. * @package */ -Blockly.Connection.prototype.neighbours = function(_maxLimit) { +Connection.prototype.neighbours = function(_maxLimit) { return []; }; /** * Get the parent input of a connection. - * @return {?Blockly.Input} The input that the connection belongs to or null if + * @return {?Input} The input that the connection belongs to or null if * no parent exists. * @package */ -Blockly.Connection.prototype.getParentInput = function() { - var parentInput = null; - var inputs = this.sourceBlock_.inputList; - for (var i = 0; i < inputs.length; i++) { +Connection.prototype.getParentInput = function() { + let parentInput = null; + const inputs = this.sourceBlock_.inputList; + for (let i = 0; i < inputs.length; i++) { if (inputs[i].connection === this) { parentInput = inputs[i]; break; @@ -646,12 +634,12 @@ Blockly.Connection.prototype.getParentInput = function() { * (English only). Intended to on be used in console logs and errors. * @return {string} The description. */ -Blockly.Connection.prototype.toString = function() { - var block = this.sourceBlock_; +Connection.prototype.toString = function() { + const block = this.sourceBlock_; if (!block) { return 'Orphan Connection'; } - var msg; + let msg; if (block.outputConnection == this) { msg = 'Output Connection of '; } else if (block.previousConnection == this) { @@ -659,8 +647,8 @@ Blockly.Connection.prototype.toString = function() { } else if (block.nextConnection == this) { msg = 'Next Connection of '; } else { - var parentInput = null; - for (var i = 0, input; (input = block.inputList[i]); i++) { + let parentInput = null; + for (let i = 0, input; (input = block.inputList[i]); i++) { if (input.connection == this) { parentInput = input; break; @@ -675,3 +663,5 @@ Blockly.Connection.prototype.toString = function() { } return msg + block.toDevString(); }; + +exports = Connection; diff --git a/core/connection_checker.js b/core/connection_checker.js index 004d5e3f3..2ea27aa19 100644 --- a/core/connection_checker.js +++ b/core/connection_checker.js @@ -5,37 +5,37 @@ */ /** - * @fileoverview An object that encapsulates logic for checking whether a potential - * connection is safe and valid. + * @fileoverview An object that encapsulates logic for checking whether a + * potential connection is safe and valid. * @author fenichel@google.com (Rachel Fenichel) */ 'use strict'; -goog.provide('Blockly.ConnectionChecker'); +goog.module('Blockly.ConnectionChecker'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Connection'); -goog.require('Blockly.connectionTypes'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); -goog.require('Blockly.IConnectionChecker'); -goog.require('Blockly.registry'); - -goog.requireType('Blockly.RenderedConnection'); +const Connection = goog.require('Blockly.Connection'); +/* eslint-disable-next-line no-unused-vars */ +const IConnectionChecker = goog.require('Blockly.IConnectionChecker'); +/* eslint-disable-next-line no-unused-vars */ +const RenderedConnection = goog.requireType('Blockly.RenderedConnection'); +const connectionTypes = goog.require('Blockly.connectionTypes'); +const registry = goog.require('Blockly.registry'); +const {OPPOSITE_TYPE} = goog.require('Blockly.internalConstants'); /** * Class for connection type checking logic. - * @implements {Blockly.IConnectionChecker} + * @implements {IConnectionChecker} * @constructor */ -Blockly.ConnectionChecker = function() { -}; +const ConnectionChecker = function() {}; /** * Check whether the current connection can connect with the target * connection. - * @param {Blockly.Connection} a Connection to check compatibility with. - * @param {Blockly.Connection} b Connection to check compatibility with. + * @param {Connection} a Connection to check compatibility with. + * @param {Connection} b Connection to check compatibility with. * @param {boolean} isDragging True if the connection is being made by dragging * a block. * @param {number=} opt_distance The max allowable distance between the @@ -43,80 +43,80 @@ Blockly.ConnectionChecker = function() { * @return {boolean} Whether the connection is legal. * @public */ -Blockly.ConnectionChecker.prototype.canConnect = function(a, b, - isDragging, opt_distance) { +ConnectionChecker.prototype.canConnect = function( + a, b, isDragging, opt_distance) { return this.canConnectWithReason(a, b, isDragging, opt_distance) == - Blockly.Connection.CAN_CONNECT; + Connection.CAN_CONNECT; }; /** * Checks whether the current connection can connect with the target * connection, and return an error code if there are problems. - * @param {Blockly.Connection} a Connection to check compatibility with. - * @param {Blockly.Connection} b Connection to check compatibility with. + * @param {Connection} a Connection to check compatibility with. + * @param {Connection} b Connection to check compatibility with. * @param {boolean} isDragging True if the connection is being made by dragging * a block. * @param {number=} opt_distance The max allowable distance between the * connections for drag checks. - * @return {number} Blockly.Connection.CAN_CONNECT if the connection is legal, + * @return {number} Connection.CAN_CONNECT if the connection is legal, * an error code otherwise. * @public */ -Blockly.ConnectionChecker.prototype.canConnectWithReason = function( +ConnectionChecker.prototype.canConnectWithReason = function( a, b, isDragging, opt_distance) { - var safety = this.doSafetyChecks(a, b); - if (safety != Blockly.Connection.CAN_CONNECT) { + const safety = this.doSafetyChecks(a, b); + if (safety != Connection.CAN_CONNECT) { return safety; } // If the safety checks passed, both connections are non-null. - var connOne = /** @type {!Blockly.Connection} **/ (a); - var connTwo = /** @type {!Blockly.Connection} **/ (b); + const connOne = /** @type {!Connection} **/ (a); + const connTwo = /** @type {!Connection} **/ (b); if (!this.doTypeChecks(connOne, connTwo)) { - return Blockly.Connection.REASON_CHECKS_FAILED; + return Connection.REASON_CHECKS_FAILED; } if (isDragging && !this.doDragChecks( - /** @type {!Blockly.RenderedConnection} **/ (a), - /** @type {!Blockly.RenderedConnection} **/ (b), - opt_distance || 0)) { - return Blockly.Connection.REASON_DRAG_CHECKS_FAILED; + /** @type {!RenderedConnection} **/ (a), + /** @type {!RenderedConnection} **/ (b), opt_distance || 0)) { + return Connection.REASON_DRAG_CHECKS_FAILED; } - return Blockly.Connection.CAN_CONNECT; + return Connection.CAN_CONNECT; }; /** * Helper method that translates a connection error code into a string. * @param {number} errorCode The error code. - * @param {Blockly.Connection} a One of the two connections being checked. - * @param {Blockly.Connection} b The second of the two connections being + * @param {Connection} a One of the two connections being checked. + * @param {Connection} b The second of the two connections being * checked. * @return {string} A developer-readable error string. * @public */ -Blockly.ConnectionChecker.prototype.getErrorMessage = function(errorCode, - a, b) { +ConnectionChecker.prototype.getErrorMessage = function(errorCode, a, b) { switch (errorCode) { - case Blockly.Connection.REASON_SELF_CONNECTION: + case Connection.REASON_SELF_CONNECTION: return 'Attempted to connect a block to itself.'; - case Blockly.Connection.REASON_DIFFERENT_WORKSPACES: + case Connection.REASON_DIFFERENT_WORKSPACES: // Usually this means one block has been deleted. return 'Blocks not on same workspace.'; - case Blockly.Connection.REASON_WRONG_TYPE: + case Connection.REASON_WRONG_TYPE: return 'Attempt to connect incompatible types.'; - case Blockly.Connection.REASON_TARGET_NULL: + case Connection.REASON_TARGET_NULL: return 'Target connection is null.'; - case Blockly.Connection.REASON_CHECKS_FAILED: - var connOne = /** @type {!Blockly.Connection} **/ (a); - var connTwo = /** @type {!Blockly.Connection} **/ (b); - var msg = 'Connection checks failed. '; - msg += connOne + ' expected ' + connOne.getCheck() + ', found ' + connTwo.getCheck(); + case Connection.REASON_CHECKS_FAILED: { + const connOne = /** @type {!Connection} **/ (a); + const connTwo = /** @type {!Connection} **/ (b); + let msg = 'Connection checks failed. '; + msg += connOne + ' expected ' + connOne.getCheck() + ', found ' + + connTwo.getCheck(); return msg; - case Blockly.Connection.REASON_SHADOW_PARENT: + } + case Connection.REASON_SHADOW_PARENT: return 'Connecting non-shadow to shadow block.'; - case Blockly.Connection.REASON_DRAG_CHECKS_FAILED: + case Connection.REASON_DRAG_CHECKS_FAILED: return 'Drag checks failed.'; default: return 'Unknown connection failure: this should never happen!'; @@ -126,53 +126,54 @@ Blockly.ConnectionChecker.prototype.getErrorMessage = function(errorCode, /** * Check that connecting the given connections is safe, meaning that it would * not break any of Blockly's basic assumptions (e.g. no self connections). - * @param {Blockly.Connection} a The first of the connections to check. - * @param {Blockly.Connection} b The second of the connections to check. + * @param {Connection} a The first of the connections to check. + * @param {Connection} b The second of the connections to check. * @return {number} An enum with the reason this connection is safe or unsafe. * @public */ -Blockly.ConnectionChecker.prototype.doSafetyChecks = function(a, b) { +ConnectionChecker.prototype.doSafetyChecks = function(a, b) { if (!a || !b) { - return Blockly.Connection.REASON_TARGET_NULL; + return Connection.REASON_TARGET_NULL; } + let blockA, blockB; if (a.isSuperior()) { - var blockA = a.getSourceBlock(); - var blockB = b.getSourceBlock(); + blockA = a.getSourceBlock(); + blockB = b.getSourceBlock(); } else { - var blockB = a.getSourceBlock(); - var blockA = b.getSourceBlock(); + blockB = a.getSourceBlock(); + blockA = b.getSourceBlock(); } if (blockA == blockB) { - return Blockly.Connection.REASON_SELF_CONNECTION; - } else if (b.type != Blockly.OPPOSITE_TYPE[a.type]) { - return Blockly.Connection.REASON_WRONG_TYPE; + return Connection.REASON_SELF_CONNECTION; + } else if (b.type != OPPOSITE_TYPE[a.type]) { + return Connection.REASON_WRONG_TYPE; } else if (blockA.workspace !== blockB.workspace) { - return Blockly.Connection.REASON_DIFFERENT_WORKSPACES; + return Connection.REASON_DIFFERENT_WORKSPACES; } else if (blockA.isShadow() && !blockB.isShadow()) { - return Blockly.Connection.REASON_SHADOW_PARENT; + return Connection.REASON_SHADOW_PARENT; } - return Blockly.Connection.CAN_CONNECT; + return Connection.CAN_CONNECT; }; /** * Check whether this connection is compatible with another connection with * respect to the value type system. E.g. square_root("Hello") is not * compatible. - * @param {!Blockly.Connection} a Connection to compare. - * @param {!Blockly.Connection} b Connection to compare against. + * @param {!Connection} a Connection to compare. + * @param {!Connection} b Connection to compare against. * @return {boolean} True if the connections share a type. * @public */ -Blockly.ConnectionChecker.prototype.doTypeChecks = function(a, b) { - var checkArrayOne = a.getCheck(); - var checkArrayTwo = b.getCheck(); +ConnectionChecker.prototype.doTypeChecks = function(a, b) { + const checkArrayOne = a.getCheck(); + const checkArrayTwo = b.getCheck(); if (!checkArrayOne || !checkArrayTwo) { // One or both sides are promiscuous enough that anything will fit. return true; } // Find any intersection in the check lists. - for (var i = 0; i < checkArrayOne.length; i++) { + for (let i = 0; i < checkArrayOne.length; i++) { if (checkArrayTwo.indexOf(checkArrayOne[i]) != -1) { return true; } @@ -183,13 +184,13 @@ Blockly.ConnectionChecker.prototype.doTypeChecks = function(a, b) { /** * Check whether this connection can be made by dragging. - * @param {!Blockly.RenderedConnection} a Connection to compare. - * @param {!Blockly.RenderedConnection} b Connection to compare against. + * @param {!RenderedConnection} a Connection to compare. + * @param {!RenderedConnection} b Connection to compare against. * @param {number} distance The maximum allowable distance between connections. * @return {boolean} True if the connection is allowed during a drag. * @public */ -Blockly.ConnectionChecker.prototype.doDragChecks = function(a, b, distance) { +ConnectionChecker.prototype.doDragChecks = function(a, b, distance) { if (a.distanceFrom(b) > distance) { return false; } @@ -200,38 +201,34 @@ Blockly.ConnectionChecker.prototype.doDragChecks = function(a, b, distance) { } switch (b.type) { - case Blockly.connectionTypes.PREVIOUS_STATEMENT: + case connectionTypes.PREVIOUS_STATEMENT: return this.canConnectToPrevious_(a, b); - case Blockly.connectionTypes.OUTPUT_VALUE: { + case connectionTypes.OUTPUT_VALUE: { // Don't offer to connect an already connected left (male) value plug to // an available right (female) value plug. - if ((b.isConnected() && - !b.targetBlock().isInsertionMarker()) || + if ((b.isConnected() && !b.targetBlock().isInsertionMarker()) || a.isConnected()) { return false; } break; } - case Blockly.connectionTypes.INPUT_VALUE: { + case connectionTypes.INPUT_VALUE: { // Offering to connect the left (male) of a value block to an already // connected value pair is ok, we'll splice it in. // However, don't offer to splice into an immovable block. - if (b.isConnected() && - !b.targetBlock().isMovable() && + if (b.isConnected() && !b.targetBlock().isMovable() && !b.targetBlock().isShadow()) { return false; } break; } - case Blockly.connectionTypes.NEXT_STATEMENT: { + case connectionTypes.NEXT_STATEMENT: { // Don't let a block with no next connection bump other blocks out of the // stack. But covering up a shadow block or stack of shadow blocks is // fine. Similarly, replacing a terminal statement with another terminal // statement is allowed. - if (b.isConnected() && - !a.getSourceBlock().nextConnection && - !b.targetBlock().isShadow() && - b.targetBlock().nextConnection) { + if (b.isConnected() && !a.getSourceBlock().nextConnection && + !b.targetBlock().isShadow() && b.targetBlock().nextConnection) { return false; } break; @@ -251,14 +248,14 @@ Blockly.ConnectionChecker.prototype.doDragChecks = function(a, b, distance) { /** * Helper function for drag checking. - * @param {!Blockly.Connection} a The connection to check, which must be a + * @param {!Connection} a The connection to check, which must be a * statement input or next connection. - * @param {!Blockly.Connection} b A nearby connection to check, which + * @param {!Connection} b A nearby connection to check, which * must be a previous connection. * @return {boolean} True if the connection is allowed, false otherwise. * @protected */ -Blockly.ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) { +ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) { if (a.targetConnection) { // This connection is already occupied. // A next connection will never disconnect itself mid-drag. @@ -274,7 +271,7 @@ Blockly.ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) { return true; } - var targetBlock = b.targetBlock(); + const targetBlock = b.targetBlock(); // If it is connected to a real block, game over. if (!targetBlock.isInsertionMarker()) { return false; @@ -285,5 +282,7 @@ Blockly.ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) { return !targetBlock.getPreviousBlock(); }; -Blockly.registry.register(Blockly.registry.Type.CONNECTION_CHECKER, - Blockly.registry.DEFAULT, Blockly.ConnectionChecker); +registry.register( + registry.Type.CONNECTION_CHECKER, registry.DEFAULT, ConnectionChecker); + +exports = ConnectionChecker; diff --git a/core/connection_db.js b/core/connection_db.js index 4b2615725..d3bc0507d 100644 --- a/core/connection_db.js +++ b/core/connection_db.js @@ -12,37 +12,40 @@ */ 'use strict'; -goog.provide('Blockly.ConnectionDB'); +goog.module('Blockly.ConnectionDB'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.connectionTypes'); +/* eslint-disable-next-line no-unused-vars */ +const Coordinate = goog.requireType('Blockly.utils.Coordinate'); +/* eslint-disable-next-line no-unused-vars */ +const IConnectionChecker = goog.requireType('Blockly.IConnectionChecker'); +/* eslint-disable-next-line no-unused-vars */ +const RenderedConnection = goog.require('Blockly.RenderedConnection'); +const connectionTypes = goog.require('Blockly.connectionTypes'); /** @suppress {extraRequire} */ goog.require('Blockly.constants'); -goog.require('Blockly.RenderedConnection'); - -goog.requireType('Blockly.IConnectionChecker'); -goog.requireType('Blockly.utils.Coordinate'); /** * Database of connections. * Connections are stored in order of their vertical component. This way * connections in an area may be looked up quickly using a binary search. - * @param {!Blockly.IConnectionChecker} checker The workspace's + * @param {!IConnectionChecker} checker The workspace's * connection type checker, used to decide if connections are valid during a * drag. * @constructor */ -Blockly.ConnectionDB = function(checker) { +const ConnectionDB = function(checker) { /** * Array of connections sorted by y position in workspace units. - * @type {!Array} + * @type {!Array} * @private */ this.connections_ = []; /** * The workspace's connection type checker, used to decide if connections are * valid during a drag. - * @type {!Blockly.IConnectionChecker} + * @type {!IConnectionChecker} * @private */ this.connectionChecker_ = checker; @@ -50,13 +53,13 @@ Blockly.ConnectionDB = function(checker) { /** * Add a connection to the database. Should not already exist in the database. - * @param {!Blockly.RenderedConnection} connection The connection to be added. + * @param {!RenderedConnection} connection The connection to be added. * @param {number} yPos The y position used to decide where to insert the * connection. * @package */ -Blockly.ConnectionDB.prototype.addConnection = function(connection, yPos) { - var index = this.calculateIndexForYPos_(yPos); +ConnectionDB.prototype.addConnection = function(connection, yPos) { + const index = this.calculateIndexForYPos_(yPos); this.connections_.splice(index, 0, connection); }; @@ -65,18 +68,18 @@ Blockly.ConnectionDB.prototype.addConnection = function(connection, yPos) { * * Starts by doing a binary search to find the approximate location, then * linearly searches nearby for the exact connection. - * @param {!Blockly.RenderedConnection} conn The connection to find. + * @param {!RenderedConnection} conn The connection to find. * @param {number} yPos The y position used to find the index of the connection. * @return {number} The index of the connection, or -1 if the connection was * not found. * @private */ -Blockly.ConnectionDB.prototype.findIndexOfConnection_ = function(conn, yPos) { +ConnectionDB.prototype.findIndexOfConnection_ = function(conn, yPos) { if (!this.connections_.length) { return -1; } - var bestGuess = this.calculateIndexForYPos_(yPos); + const bestGuess = this.calculateIndexForYPos_(yPos); if (bestGuess >= this.connections_.length) { // Not in list return -1; @@ -84,7 +87,7 @@ Blockly.ConnectionDB.prototype.findIndexOfConnection_ = function(conn, yPos) { yPos = conn.y; // Walk forward and back on the y axis looking for the connection. - var pointer = bestGuess; + let pointer = bestGuess; while (pointer >= 0 && this.connections_[pointer].y == yPos) { if (this.connections_[pointer] == conn) { return pointer; @@ -110,14 +113,14 @@ Blockly.ConnectionDB.prototype.findIndexOfConnection_ = function(conn, yPos) { * @return {number} The candidate index. * @private */ -Blockly.ConnectionDB.prototype.calculateIndexForYPos_ = function(yPos) { +ConnectionDB.prototype.calculateIndexForYPos_ = function(yPos) { if (!this.connections_.length) { return 0; } - var pointerMin = 0; - var pointerMax = this.connections_.length; + let pointerMin = 0; + let pointerMax = this.connections_.length; while (pointerMin < pointerMax) { - var pointerMid = Math.floor((pointerMin + pointerMax) / 2); + const pointerMid = Math.floor((pointerMin + pointerMax) / 2); if (this.connections_[pointerMid].y < yPos) { pointerMin = pointerMid + 1; } else if (this.connections_[pointerMid].y > yPos) { @@ -132,12 +135,12 @@ Blockly.ConnectionDB.prototype.calculateIndexForYPos_ = function(yPos) { /** * Remove a connection from the database. Must already exist in DB. - * @param {!Blockly.RenderedConnection} connection The connection to be removed. + * @param {!RenderedConnection} connection The connection to be removed. * @param {number} yPos The y position used to find the index of the connection. * @throws {Error} If the connection cannot be found in the database. */ -Blockly.ConnectionDB.prototype.removeConnection = function(connection, yPos) { - var index = this.findIndexOfConnection_(connection, yPos); +ConnectionDB.prototype.removeConnection = function(connection, yPos) { + const index = this.findIndexOfConnection_(connection, yPos); if (index == -1) { throw Error('Unable to find connection in connectionDB.'); } @@ -147,20 +150,20 @@ Blockly.ConnectionDB.prototype.removeConnection = function(connection, yPos) { /** * Find all nearby connections to the given connection. * Type checking does not apply, since this function is used for bumping. - * @param {!Blockly.RenderedConnection} connection The connection whose + * @param {!RenderedConnection} connection The connection whose * neighbours should be returned. * @param {number} maxRadius The maximum radius to another connection. - * @return {!Array} List of connections. + * @return {!Array} List of connections. */ -Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) { - var db = this.connections_; - var currentX = connection.x; - var currentY = connection.y; +ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) { + const db = this.connections_; + const currentX = connection.x; + const currentY = connection.y; // Binary search to find the closest y location. - var pointerMin = 0; - var pointerMax = db.length - 2; - var pointerMid = pointerMax; + let pointerMin = 0; + let pointerMax = db.length - 2; + let pointerMid = pointerMax; while (pointerMin < pointerMid) { if (db[pointerMid].y < currentY) { pointerMin = pointerMid; @@ -170,7 +173,7 @@ Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) { pointerMid = Math.floor((pointerMin + pointerMax) / 2); } - var neighbours = []; + const neighbours = []; /** * Computes if the current connection is within the allowed radius of another * connection. @@ -180,9 +183,9 @@ Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) { * the other connection is less than the allowed radius. */ function checkConnection_(yIndex) { - var dx = currentX - db[yIndex].x; - var dy = currentY - db[yIndex].y; - var r = Math.sqrt(dx * dx + dy * dy); + const dx = currentX - db[yIndex].x; + const dy = currentY - db[yIndex].y; + const r = Math.sqrt(dx * dx + dy * dy); if (r <= maxRadius) { neighbours.push(db[yIndex]); } @@ -213,32 +216,31 @@ Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) { * @return {boolean} True if connection is in range. * @private */ -Blockly.ConnectionDB.prototype.isInYRange_ = function(index, baseY, maxRadius) { +ConnectionDB.prototype.isInYRange_ = function(index, baseY, maxRadius) { return (Math.abs(this.connections_[index].y - baseY) <= maxRadius); }; /** * Find the closest compatible connection to this connection. - * @param {!Blockly.RenderedConnection} conn The connection searching for a compatible + * @param {!RenderedConnection} conn The connection searching for a compatible * mate. * @param {number} maxRadius The maximum radius to another connection. - * @param {!Blockly.utils.Coordinate} dxy Offset between this connection's + * @param {!Coordinate} dxy Offset between this connection's * location in the database and the current location (as a result of * dragging). - * @return {!{connection: Blockly.RenderedConnection, radius: number}} + * @return {!{connection: RenderedConnection, radius: number}} * Contains two properties: 'connection' which is either another * connection or null, and 'radius' which is the distance. */ -Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius, - dxy) { +ConnectionDB.prototype.searchForClosest = function(conn, maxRadius, dxy) { if (!this.connections_.length) { // Don't bother. return {connection: null, radius: maxRadius}; } // Stash the values of x and y from before the drag. - var baseY = conn.y; - var baseX = conn.x; + const baseY = conn.y; + const baseX = conn.x; conn.x = baseX + dxy.x; conn.y = baseY + dxy.y; @@ -246,14 +248,14 @@ Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius, // calculateIndexForYPos_ finds an index for insertion, which is always // after any block with the same y index. We want to search both forward // and back, so search on both sides of the index. - var closestIndex = this.calculateIndexForYPos_(conn.y); + const closestIndex = this.calculateIndexForYPos_(conn.y); - var bestConnection = null; - var bestRadius = maxRadius; - var temp; + let bestConnection = null; + let bestRadius = maxRadius; + let temp; // Walk forward and back on the y axis looking for the closest x,y point. - var pointerMin = closestIndex - 1; + let pointerMin = closestIndex - 1; while (pointerMin >= 0 && this.isInYRange_(pointerMin, conn.y, maxRadius)) { temp = this.connections_[pointerMin]; if (this.connectionChecker_.canConnect(conn, temp, true, bestRadius)) { @@ -263,9 +265,9 @@ Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius, pointerMin--; } - var pointerMax = closestIndex; + let pointerMax = closestIndex; while (pointerMax < this.connections_.length && - this.isInYRange_(pointerMax, conn.y, maxRadius)) { + this.isInYRange_(pointerMax, conn.y, maxRadius)) { temp = this.connections_[pointerMax]; if (this.connectionChecker_.canConnect(conn, temp, true, bestRadius)) { bestConnection = temp; @@ -284,20 +286,19 @@ Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius, /** * Initialize a set of connection DBs for a workspace. - * @param {!Blockly.IConnectionChecker} checker The workspace's - * connection checker, used to decide if connections are valid during a drag. - * @return {!Array} Array of databases. + * @param {!IConnectionChecker} checker The workspace's + * connection checker, used to decide if connections are valid during a + * drag. + * @return {!Array} Array of databases. */ -Blockly.ConnectionDB.init = function(checker) { +ConnectionDB.init = function(checker) { // Create four databases, one for each connection type. - var dbList = []; - dbList[Blockly.connectionTypes.INPUT_VALUE] = - new Blockly.ConnectionDB(checker); - dbList[Blockly.connectionTypes.OUTPUT_VALUE] = - new Blockly.ConnectionDB(checker); - dbList[Blockly.connectionTypes.NEXT_STATEMENT] = - new Blockly.ConnectionDB(checker); - dbList[Blockly.connectionTypes.PREVIOUS_STATEMENT] = - new Blockly.ConnectionDB(checker); + const dbList = []; + dbList[connectionTypes.INPUT_VALUE] = new ConnectionDB(checker); + dbList[connectionTypes.OUTPUT_VALUE] = new ConnectionDB(checker); + dbList[connectionTypes.NEXT_STATEMENT] = new ConnectionDB(checker); + dbList[connectionTypes.PREVIOUS_STATEMENT] = new ConnectionDB(checker); return dbList; }; + +exports = ConnectionDB; diff --git a/core/connection_types.js b/core/connection_types.js index b2116812b..569ffc442 100644 --- a/core/connection_types.js +++ b/core/connection_types.js @@ -11,13 +11,14 @@ 'use strict'; -goog.provide('Blockly.connectionTypes'); +goog.module('Blockly.connectionTypes'); +goog.module.declareLegacyNamespace(); /** * Enum for the type of a connection or input. * @enum {number} */ -Blockly.connectionTypes = { +const connectionTypes = { // A right-facing value input. E.g. 'set item to' or 'return'. INPUT_VALUE: 1, // A left-facing value output. E.g. 'random fraction'. @@ -27,3 +28,5 @@ Blockly.connectionTypes = { // An up-facing block stack. E.g. 'break out of loop'. PREVIOUS_STATEMENT: 4 }; + +exports = connectionTypes; diff --git a/core/constants.js b/core/constants.js index 1d19fb8d5..727e42a1f 100644 --- a/core/constants.js +++ b/core/constants.js @@ -10,204 +10,31 @@ */ 'use strict'; -goog.provide('Blockly.constants'); +goog.module('Blockly.constants'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.connectionTypes'); - - -/** - * The multiplier for scroll wheel deltas using the line delta mode. - * @type {number} - */ -Blockly.LINE_MODE_MULTIPLIER = 40; - -/** - * The multiplier for scroll wheel deltas using the page delta mode. - * @type {number} - */ -Blockly.PAGE_MODE_MULTIPLIER = 125; - -/** - * Number of pixels the mouse must move before a drag starts. - */ -Blockly.DRAG_RADIUS = 5; - -/** - * Number of pixels the mouse must move before a drag/scroll starts from the - * flyout. Because the drag-intention is determined when this is reached, it is - * larger than Blockly.DRAG_RADIUS so that the drag-direction is clearer. - */ -Blockly.FLYOUT_DRAG_RADIUS = 10; - -/** - * Maximum misalignment between connections for them to snap together. - */ -Blockly.SNAP_RADIUS = 28; - -/** - * Maximum misalignment between connections for them to snap together, - * when a connection is already highlighted. - */ -Blockly.CONNECTING_SNAP_RADIUS = Blockly.SNAP_RADIUS; - -/** - * How much to prefer staying connected to the current connection over moving to - * a new connection. The current previewed connection is considered to be this - * much closer to the matching connection on the block than it actually is. - */ -Blockly.CURRENT_CONNECTION_PREFERENCE = 8; - -/** - * Delay in ms between trigger and bumping unconnected block out of alignment. - */ -Blockly.BUMP_DELAY = 250; - -/** - * Maximum randomness in workspace units for bumping a block. - */ -Blockly.BUMP_RANDOMNESS = 10; - -/** - * Number of characters to truncate a collapsed block to. - */ -Blockly.COLLAPSE_CHARS = 30; - -/** - * Length in ms for a touch to become a long press. - */ -Blockly.LONGPRESS = 750; - -/** - * Prevent a sound from playing if another sound preceded it within this many - * milliseconds. - */ -Blockly.SOUND_LIMIT = 100; - -/** - * When dragging a block out of a stack, split the stack in two (true), or drag - * out the block healing the stack (false). - */ -Blockly.DRAG_STACK = true; - -/** - * The richness of block colours, regardless of the hue. - * Must be in the range of 0 (inclusive) to 1 (exclusive). - */ -Blockly.HSV_SATURATION = 0.45; - -/** - * The intensity of block colours, regardless of the hue. - * Must be in the range of 0 (inclusive) to 1 (exclusive). - */ -Blockly.HSV_VALUE = 0.65; - -/** - * Sprited icons and images. - */ -Blockly.SPRITE = { - width: 96, - height: 124, - url: 'sprites.png' -}; - -// Constants below this point are not intended to be changed. /** * Enum for alignment of inputs. * @enum {number} */ -Blockly.constants.ALIGN = { +const ALIGN = { LEFT: -1, CENTRE: 0, RIGHT: 1 }; - -/** - * ENUM for no drag operation. - * @const - */ -Blockly.DRAG_NONE = 0; - -/** - * ENUM for inside the sticky DRAG_RADIUS. - * @const - */ -Blockly.DRAG_STICKY = 1; - -/** - * ENUM for inside the non-sticky DRAG_RADIUS, for differentiating between - * clicks and drags. - * @const - */ -Blockly.DRAG_BEGIN = 1; - -/** - * ENUM for freely draggable (outside the DRAG_RADIUS, if one applies). - * @const - */ -Blockly.DRAG_FREE = 2; - -/** - * Lookup table for determining the opposite type of a connection. - * @const - */ -Blockly.OPPOSITE_TYPE = []; -Blockly.OPPOSITE_TYPE[Blockly.connectionTypes.INPUT_VALUE] = - Blockly.connectionTypes.OUTPUT_VALUE; -Blockly.OPPOSITE_TYPE[Blockly.connectionTypes.OUTPUT_VALUE] = - Blockly.connectionTypes.INPUT_VALUE; -Blockly.OPPOSITE_TYPE[Blockly.connectionTypes.NEXT_STATEMENT] = - Blockly.connectionTypes.PREVIOUS_STATEMENT; -Blockly.OPPOSITE_TYPE[Blockly.connectionTypes.PREVIOUS_STATEMENT] = - Blockly.connectionTypes.NEXT_STATEMENT; - -/** - * String for use in the "custom" attribute of a category in toolbox XML. - * This string indicates that the category should be dynamically populated with - * variable blocks. - * @const {string} - */ -Blockly.VARIABLE_CATEGORY_NAME = 'VARIABLE'; -/** - * String for use in the "custom" attribute of a category in toolbox XML. - * This string indicates that the category should be dynamically populated with - * variable blocks. - * @const {string} - */ -Blockly.VARIABLE_DYNAMIC_CATEGORY_NAME = 'VARIABLE_DYNAMIC'; - -/** - * String for use in the "custom" attribute of a category in toolbox XML. - * This string indicates that the category should be dynamically populated with - * procedure blocks. - * @const {string} - */ -Blockly.PROCEDURE_CATEGORY_NAME = 'PROCEDURE'; - -/** - * String for use in the dropdown created in field_variable. - * This string indicates that this option in the dropdown is 'Rename - * variable...' and if selected, should trigger the prompt to rename a variable. - * @const {string} - */ -Blockly.RENAME_VARIABLE_ID = 'RENAME_VARIABLE_ID'; - -/** - * String for use in the dropdown created in field_variable. - * This string indicates that this option in the dropdown is 'Delete the "%1" - * variable' and if selected, should trigger the prompt to delete a variable. - * @const {string} - */ -Blockly.DELETE_VARIABLE_ID = 'DELETE_VARIABLE_ID'; +exports.ALIGN = ALIGN; /** * The language-neutral ID given to the collapsed input. * @const {string} */ -Blockly.constants.COLLAPSED_INPUT_NAME = '_TEMP_COLLAPSED_INPUT'; +const COLLAPSED_INPUT_NAME = '_TEMP_COLLAPSED_INPUT'; +exports.COLLAPSED_INPUT_NAME = COLLAPSED_INPUT_NAME; /** * The language-neutral ID given to the collapsed field. * @const {string} */ -Blockly.constants.COLLAPSED_FIELD_NAME = '_TEMP_COLLAPSED_FIELD'; +const COLLAPSED_FIELD_NAME = '_TEMP_COLLAPSED_FIELD'; +exports.COLLAPSED_FIELD_NAME = COLLAPSED_FIELD_NAME; diff --git a/core/contextmenu.js b/core/contextmenu.js index e070207b7..3bfcda167 100644 --- a/core/contextmenu.js +++ b/core/contextmenu.js @@ -17,11 +17,10 @@ goog.provide('Blockly.ContextMenu'); goog.require('Blockly.browserEvents'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockCreate'); +goog.require('Blockly.internalConstants'); goog.require('Blockly.Menu'); goog.require('Blockly.MenuItem'); goog.require('Blockly.Msg'); @@ -195,11 +194,11 @@ Blockly.ContextMenu.callbackFactory = function(block, xml) { // Move the new block next to the old block. var xy = block.getRelativeToSurfaceXY(); if (block.RTL) { - xy.x -= Blockly.SNAP_RADIUS; + xy.x -= Blockly.internalConstants.SNAP_RADIUS; } else { - xy.x += Blockly.SNAP_RADIUS; + xy.x += Blockly.internalConstants.SNAP_RADIUS; } - xy.y += Blockly.SNAP_RADIUS * 2; + xy.y += Blockly.internalConstants.SNAP_RADIUS * 2; newBlock.moveBy(xy.x, xy.y); } finally { Blockly.Events.enable(); diff --git a/core/css.js b/core/css.js index 9f6037d7b..6f34e6c0d 100644 --- a/core/css.js +++ b/core/css.js @@ -14,7 +14,8 @@ * @name Blockly.Css * @namespace */ -goog.provide('Blockly.Css'); +goog.module('Blockly.Css'); +goog.module.declareLegacyNamespace(); /** @@ -22,7 +23,7 @@ goog.provide('Blockly.Css'); * @type {boolean} * @private */ -Blockly.Css.injected_ = false; +let injected = false; /** * Add some CSS to the blob that will be injected later. Allows optional @@ -30,14 +31,15 @@ Blockly.Css.injected_ = false; * The provided array of CSS will be destroyed by this function. * @param {!Array} cssArray Array of CSS strings. */ -Blockly.Css.register = function(cssArray) { - if (Blockly.Css.injected_) { +const register = function(cssArray) { + if (injected) { throw Error('CSS already injected'); } - // Concatenate cssArray onto Blockly.Css.CONTENT. - Array.prototype.push.apply(Blockly.Css.CONTENT, cssArray); + // Concatenate cssArray onto CONTENT. + Array.prototype.push.apply(CONTENT, cssArray); cssArray.length = 0; // Garbage collect provided CSS content. }; +exports.register = register; /** * Inject the CSS into the DOM. This is preferable over using a regular CSS @@ -49,504 +51,508 @@ Blockly.Css.register = function(cssArray) { * (providing CSS becomes the document's responsibility). * @param {string} pathToMedia Path from page to the Blockly media directory. */ -Blockly.Css.inject = function(hasCss, pathToMedia) { +const inject = function(hasCss, pathToMedia) { // Only inject the CSS once. - if (Blockly.Css.injected_) { + if (injected) { return; } - Blockly.Css.injected_ = true; - var text = Blockly.Css.CONTENT.join('\n'); - Blockly.Css.CONTENT.length = 0; // Garbage collect CSS content. + injected = true; + let text = CONTENT.join('\n'); + CONTENT.length = 0; // Garbage collect CSS content. if (!hasCss) { return; } // Strip off any trailing slash (either Unix or Windows). - var mediaPath = pathToMedia.replace(/[\\/]$/, ''); + const mediaPath = pathToMedia.replace(/[\\/]$/, ''); text = text.replace(/<<>>/g, mediaPath); // Inject CSS tag at start of head. - var cssNode = document.createElement('style'); + const cssNode = document.createElement('style'); cssNode.id = 'blockly-common-style'; - var cssTextNode = document.createTextNode(text); + const cssTextNode = document.createTextNode(text); cssNode.appendChild(cssTextNode); document.head.insertBefore(cssNode, document.head.firstChild); }; +exports.inject = inject; /** * Array making up the CSS content for Blockly. */ -Blockly.Css.CONTENT = [ - /* eslint-disable indent */ - '.blocklySvg {', - 'background-color: #fff;', - 'outline: none;', - 'overflow: hidden;', /* IE overflows by default. */ - 'position: absolute;', - 'display: block;', - '}', +const CONTENT = [ + `.blocklySvg { + background-color: #fff; + outline: none; + overflow: hidden; /* IE overflows by default. */ + position: absolute; + display: block; +}`, - '.blocklyWidgetDiv {', - 'display: none;', - 'position: absolute;', - 'z-index: 99999;', /* big value for bootstrap3 compatibility */ - '}', + `.blocklyWidgetDiv { + display: none; + position: absolute; + z-index: 99999; /* big value for bootstrap3 compatibility */ +}`, - '.injectionDiv {', - 'height: 100%;', - 'position: relative;', - 'overflow: hidden;', /* So blocks in drag surface disappear at edges */ - 'touch-action: none;', - '}', + `.injectionDiv { + height: 100%; + position: relative; + overflow: hidden; /* So blocks in drag surface disappear at edges */ + touch-action: none; +}`, - '.blocklyNonSelectable {', - 'user-select: none;', - '-ms-user-select: none;', - '-webkit-user-select: none;', - '}', + `.blocklyNonSelectable { + user-select: none; + -ms-user-select: none; + -webkit-user-select: none; +}`, + + `.blocklyWsDragSurface { + display: none; + position: absolute; + top: 0; + left: 0; +}`, - '.blocklyWsDragSurface {', - 'display: none;', - 'position: absolute;', - 'top: 0;', - 'left: 0;', - '}', /* Added as a separate rule with multiple classes to make it more specific than a bootstrap rule that selects svg:root. See issue #1275 for context. */ - '.blocklyWsDragSurface.blocklyOverflowVisible {', - 'overflow: visible;', - '}', + `.blocklyWsDragSurface.blocklyOverflowVisible { + overflow: visible; +}`, - '.blocklyBlockDragSurface {', - 'display: none;', - 'position: absolute;', - 'top: 0;', - 'left: 0;', - 'right: 0;', - 'bottom: 0;', - 'overflow: visible !important;', - 'z-index: 50;', /* Display below toolbox, but above everything else. */ - '}', + `.blocklyBlockDragSurface { + display: none; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + overflow: visible !important; + z-index: 50;', /* Display below toolbox, but above everything else. */ +}`, - '.blocklyBlockCanvas.blocklyCanvasTransitioning,', - '.blocklyBubbleCanvas.blocklyCanvasTransitioning {', - 'transition: transform .5s;', - '}', + `.blocklyBlockCanvas.blocklyCanvasTransitioning, +.blocklyBubbleCanvas.blocklyCanvasTransitioning { + transition: transform .5s; +}`, - '.blocklyTooltipDiv {', - 'background-color: #ffffc7;', - 'border: 1px solid #ddc;', - 'box-shadow: 4px 4px 20px 1px rgba(0,0,0,.15);', - 'color: #000;', - 'display: none;', - 'font: 9pt sans-serif;', - 'opacity: .9;', - 'padding: 2px;', - 'position: absolute;', - 'z-index: 100000;', /* big value for bootstrap3 compatibility */ - '}', + `.blocklyTooltipDiv { + background-color: #ffffc7; + border: 1px solid #ddc; + box-shadow: 4px 4px 20px 1px rgba(0,0,0,.15); + color: #000; + display: none; + font: 9pt sans-serif; + opacity: .9; + padding: 2px; + position: absolute; + z-index: 100000;', /* big value for bootstrap3 compatibility */ +}`, - '.blocklyDropDownDiv {', - 'position: absolute;', - 'left: 0;', - 'top: 0;', - 'z-index: 1000;', - 'display: none;', - 'border: 1px solid;', - 'border-color: #dadce0;', - 'background-color: #fff;', - 'border-radius: 2px;', - 'padding: 4px;', - 'box-shadow: 0 0 3px 1px rgba(0,0,0,.3);', - '}', + `.blocklyDropDownDiv { + position: absolute; + left: 0; + top: 0; + z-index: 1000; + display: none; + border: 1px solid; + border-color: #dadce0; + background-color: #fff; + border-radius: 2px; + padding: 4px; + box-shadow: 0 0 3px 1px rgba(0,0,0,.3); +}`, - '.blocklyDropDownDiv.blocklyFocused {', - 'box-shadow: 0 0 6px 1px rgba(0,0,0,.3);', - '}', + `.blocklyDropDownDiv.blocklyFocused { + box-shadow: 0 0 6px 1px rgba(0,0,0,.3); +}`, - '.blocklyDropDownContent {', - 'max-height: 300px;', // @todo: spec for maximum height. - 'overflow: auto;', - 'overflow-x: hidden;', - 'position: relative;', - '}', + `.blocklyDropDownContent { + max-height: 300px;', // @todo: spec for maximum height. + overflow: auto; + overflow-x: hidden; + position: relative; +}`, - '.blocklyDropDownArrow {', - 'position: absolute;', - 'left: 0;', - 'top: 0;', - 'width: 16px;', - 'height: 16px;', - 'z-index: -1;', - 'background-color: inherit;', - 'border-color: inherit;', - '}', + `.blocklyDropDownArrow { + position: absolute; + left: 0; + top: 0; + width: 16px; + height: 16px; + z-index: -1; + background-color: inherit; + border-color: inherit; +}`, - '.blocklyDropDownButton {', - 'display: inline-block;', - 'float: left;', - 'padding: 0;', - 'margin: 4px;', - 'border-radius: 4px;', - 'outline: none;', - 'border: 1px solid;', - 'transition: box-shadow .1s;', - 'cursor: pointer;', - '}', + `.blocklyDropDownButton { + display: inline-block; + float: left; + padding: 0; + margin: 4px; + border-radius: 4px; + outline: none; + border: 1px solid; + transition: box-shadow .1s; + cursor: pointer; +}`, - '.blocklyArrowTop {', - 'border-top: 1px solid;', - 'border-left: 1px solid;', - 'border-top-left-radius: 4px;', - 'border-color: inherit;', - '}', + `.blocklyArrowTop { + border-top: 1px solid; + border-left: 1px solid; + border-top-left-radius: 4px; + border-color: inherit; +}`, - '.blocklyArrowBottom {', - 'border-bottom: 1px solid;', - 'border-right: 1px solid;', - 'border-bottom-right-radius: 4px;', - 'border-color: inherit;', - '}', + `.blocklyArrowBottom { + border-bottom: 1px solid; + border-right: 1px solid; + border-bottom-right-radius: 4px; + border-color: inherit; +}`, - '.blocklyResizeSE {', - 'cursor: se-resize;', - 'fill: #aaa;', - '}', + `.blocklyResizeSE { + cursor: se-resize; + fill: #aaa; +}`, - '.blocklyResizeSW {', - 'cursor: sw-resize;', - 'fill: #aaa;', - '}', + `.blocklyResizeSW { + cursor: sw-resize; + fill: #aaa; +}`, - '.blocklyResizeLine {', - 'stroke: #515A5A;', - 'stroke-width: 1;', - '}', + `.blocklyResizeLine { + stroke: #515A5A; + stroke-width: 1; +}`, - '.blocklyHighlightedConnectionPath {', - 'fill: none;', - 'stroke: #fc3;', - 'stroke-width: 4px;', - '}', + `.blocklyHighlightedConnectionPath { + fill: none; + stroke: #fc3; + stroke-width: 4px; +}`, - '.blocklyPathLight {', - 'fill: none;', - 'stroke-linecap: round;', - 'stroke-width: 1;', - '}', + `.blocklyPathLight { + fill: none; + stroke-linecap: round; + stroke-width: 1; +}`, - '.blocklySelected>.blocklyPathLight {', - 'display: none;', - '}', + `.blocklySelected>.blocklyPathLight { + display: none; +}`, - '.blocklyDraggable {', - /* backup for browsers (e.g. IE11) that don't support grab */ - 'cursor: url("<<>>/handopen.cur"), auto;', - 'cursor: grab;', - 'cursor: -webkit-grab;', - '}', + `.blocklyDraggable { + /* backup for browsers (e.g. IE11) that don't support grab */ + cursor: url("<<>>/handopen.cur"), auto; + cursor: grab; + cursor: -webkit-grab; +}`, + + /* backup for browsers (e.g. IE11) that don't support grabbing */ + `.blocklyDragging { + /* backup for browsers (e.g. IE11) that don't support grabbing */ + cursor: url("<<>>/handclosed.cur"), auto; + cursor: grabbing; + cursor: -webkit-grabbing; +}`, - '.blocklyDragging {', - /* backup for browsers (e.g. IE11) that don't support grabbing */ - 'cursor: url("<<>>/handclosed.cur"), auto;', - 'cursor: grabbing;', - 'cursor: -webkit-grabbing;', - '}', /* Changes cursor on mouse down. Not effective in Firefox because of - https://bugzilla.mozilla.org/show_bug.cgi?id=771241 */ - '.blocklyDraggable:active {', - /* backup for browsers (e.g. IE11) that don't support grabbing */ - 'cursor: url("<<>>/handclosed.cur"), auto;', - 'cursor: grabbing;', - 'cursor: -webkit-grabbing;', - '}', + https://bugzilla.mozilla.org/show_bug.cgi?id=771241 */ + `.blocklyDraggable:active { + /* backup for browsers (e.g. IE11) that don't support grabbing */ + cursor: url("<<>>/handclosed.cur"), auto; + cursor: grabbing; + cursor: -webkit-grabbing; +}`, + /* Change the cursor on the whole drag surface in case the mouse gets ahead of block during a drag. This way the cursor is still a closed hand. */ - '.blocklyBlockDragSurface .blocklyDraggable {', - /* backup for browsers (e.g. IE11) that don't support grabbing */ - 'cursor: url("<<>>/handclosed.cur"), auto;', - 'cursor: grabbing;', - 'cursor: -webkit-grabbing;', - '}', + `.blocklyBlockDragSurface .blocklyDraggable { + /* backup for browsers (e.g. IE11) that don't support grabbing */ + cursor: url("<<>>/handclosed.cur"), auto; + cursor: grabbing; + cursor: -webkit-grabbing; +}`, - '.blocklyDragging.blocklyDraggingDelete {', - 'cursor: url("<<>>/handdelete.cur"), auto;', - '}', + `.blocklyDragging.blocklyDraggingDelete { + cursor: url("<<>>/handdelete.cur"), auto; +}`, - '.blocklyDragging>.blocklyPath,', - '.blocklyDragging>.blocklyPathLight {', - 'fill-opacity: .8;', - 'stroke-opacity: .8;', - '}', + `.blocklyDragging>.blocklyPath, +.blocklyDragging>.blocklyPathLight { + fill-opacity: .8; + stroke-opacity: .8; +}`, - '.blocklyDragging>.blocklyPathDark {', - 'display: none;', - '}', + `.blocklyDragging>.blocklyPathDark { + display: none; +}`, - '.blocklyDisabled>.blocklyPath {', - 'fill-opacity: .5;', - 'stroke-opacity: .5;', - '}', + `.blocklyDisabled>.blocklyPath { + fill-opacity: .5; + stroke-opacity: .5; +}`, - '.blocklyDisabled>.blocklyPathLight,', - '.blocklyDisabled>.blocklyPathDark {', - 'display: none;', - '}', + `.blocklyDisabled>.blocklyPathLight, +.blocklyDisabled>.blocklyPathDark { + display: none; +}`, - '.blocklyInsertionMarker>.blocklyPath,', - '.blocklyInsertionMarker>.blocklyPathLight,', - '.blocklyInsertionMarker>.blocklyPathDark {', - 'fill-opacity: .2;', - 'stroke: none;', - '}', + `.blocklyInsertionMarker>.blocklyPath, +.blocklyInsertionMarker>.blocklyPathLight, +.blocklyInsertionMarker>.blocklyPathDark { + fill-opacity: .2; + stroke: none; +}`, - '.blocklyMultilineText {', - 'font-family: monospace;', - '}', + `.blocklyMultilineText { + font-family: monospace; +}`, - '.blocklyNonEditableText>text {', - 'pointer-events: none;', - '}', + `.blocklyNonEditableText>text { + pointer-events: none; +}`, - '.blocklyFlyout {', - 'position: absolute;', - 'z-index: 20;', - '}', + `.blocklyFlyout { + position: absolute; + z-index: 20; +}`, - '.blocklyText text {', - 'cursor: default;', - '}', + `.blocklyText text { + cursor: default; +}`, /* Don't allow users to select text. It gets annoying when trying to drag a block and selected text moves instead. */ - '.blocklySvg text,', - '.blocklyBlockDragSurface text {', - 'user-select: none;', - '-ms-user-select: none;', - '-webkit-user-select: none;', - 'cursor: inherit;', - '}', + `.blocklySvg text, +.blocklyBlockDragSurface text { + user-select: none; + -ms-user-select: none; + -webkit-user-select: none; + cursor: inherit; +}`, - '.blocklyHidden {', - 'display: none;', - '}', + `.blocklyHidden { + display: none; +}`, - '.blocklyFieldDropdown:not(.blocklyHidden) {', - 'display: block;', - '}', + `.blocklyFieldDropdown:not(.blocklyHidden) { + display: block; +}`, - '.blocklyIconGroup {', - 'cursor: default;', - '}', + `.blocklyIconGroup { + cursor: default; +}`, - '.blocklyIconGroup:not(:hover),', - '.blocklyIconGroupReadonly {', - 'opacity: .6;', - '}', + `.blocklyIconGroup:not(:hover), +.blocklyIconGroupReadonly { + opacity: .6; +}`, - '.blocklyIconShape {', - 'fill: #00f;', - 'stroke: #fff;', - 'stroke-width: 1px;', - '}', + `.blocklyIconShape { + fill: #00f; + stroke: #fff; + stroke-width: 1px; +}`, - '.blocklyIconSymbol {', - 'fill: #fff;', - '}', + `.blocklyIconSymbol { + fill: #fff; +}`, - '.blocklyMinimalBody {', - 'margin: 0;', - 'padding: 0;', - '}', + `.blocklyMinimalBody { + margin: 0; + padding: 0; +}`, - '.blocklyHtmlInput {', - 'border: none;', - 'border-radius: 4px;', - 'height: 100%;', - 'margin: 0;', - 'outline: none;', - 'padding: 0;', - 'width: 100%;', - 'text-align: center;', - 'display: block;', - 'box-sizing: border-box;', - '}', + `.blocklyHtmlInput { + border: none; + border-radius: 4px; + height: 100%; + margin: 0; + outline: none; + padding: 0; + width: 100%; + text-align: center; + display: block; + box-sizing: border-box; +}`, /* Edge and IE introduce a close icon when the input value is longer than a certain length. This affects our sizing calculations of the text input. Hiding the close icon to avoid that. */ - '.blocklyHtmlInput::-ms-clear {', - 'display: none;', - '}', + `.blocklyHtmlInput::-ms-clear { + display: none; +}`, - '.blocklyMainBackground {', - 'stroke-width: 1;', - 'stroke: #c6c6c6;', /* Equates to #ddd due to border being off-pixel. */ - '}', + `.blocklyMainBackground { + stroke-width: 1; + stroke: #c6c6c6;', /* Equates to #ddd due to border being off-pixel. */ +}`, - '.blocklyMutatorBackground {', - 'fill: #fff;', - 'stroke: #ddd;', - 'stroke-width: 1;', - '}', + `.blocklyMutatorBackground { + fill: #fff; + stroke: #ddd; + stroke-width: 1; +}`, - '.blocklyFlyoutBackground {', - 'fill: #ddd;', - 'fill-opacity: .8;', - '}', + `.blocklyFlyoutBackground { + fill: #ddd; + fill-opacity: .8; +}`, - '.blocklyMainWorkspaceScrollbar {', - 'z-index: 20;', - '}', + `.blocklyMainWorkspaceScrollbar { + z-index: 20; +}`, - '.blocklyFlyoutScrollbar {', - 'z-index: 30;', - '}', + `.blocklyFlyoutScrollbar { + z-index: 30; +}`, - '.blocklyScrollbarHorizontal,', - '.blocklyScrollbarVertical {', - 'position: absolute;', - 'outline: none;', - '}', + `.blocklyScrollbarHorizontal, +.blocklyScrollbarVertical { + position: absolute; + outline: none; +}`, - '.blocklyScrollbarBackground {', - 'opacity: 0;', - '}', + `.blocklyScrollbarBackground { + opacity: 0; +}`, - '.blocklyScrollbarHandle {', - 'fill: #ccc;', - '}', + `.blocklyScrollbarHandle { + fill: #ccc; +}`, - '.blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,', - '.blocklyScrollbarHandle:hover {', - 'fill: #bbb;', - '}', + `.blocklyScrollbarBackground:hover+.blocklyScrollbarHandle, +.blocklyScrollbarHandle:hover { + fill: #bbb; +}`, /* Darken flyout scrollbars due to being on a grey background. */ /* By contrast, workspace scrollbars are on a white background. */ - '.blocklyFlyout .blocklyScrollbarHandle {', - 'fill: #bbb;', - '}', + `.blocklyFlyout .blocklyScrollbarHandle { + fill: #bbb; +}`, - '.blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,', - '.blocklyFlyout .blocklyScrollbarHandle:hover {', - 'fill: #aaa;', - '}', + `.blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle, +.blocklyFlyout .blocklyScrollbarHandle:hover { + fill: #aaa; +}`, - '.blocklyInvalidInput {', - 'background: #faa;', - '}', + `.blocklyInvalidInput { + background: #faa; +}`, - '.blocklyVerticalMarker {', - 'stroke-width: 3px;', - 'fill: rgba(255,255,255,.5);', - 'pointer-events: none;', - '}', + `.blocklyVerticalMarker { + stroke-width: 3px; + fill: rgba(255,255,255,.5); + pointer-events: none; +}`, - '.blocklyComputeCanvas {', - 'position: absolute;', - 'width: 0;', - 'height: 0;', - '}', + `.blocklyComputeCanvas { + position: absolute; + width: 0; + height: 0; +}`, - '.blocklyNoPointerEvents {', - 'pointer-events: none;', - '}', + `.blocklyNoPointerEvents { + pointer-events: none; +}`, - '.blocklyContextMenu {', - 'border-radius: 4px;', - 'max-height: 100%;', - '}', + `.blocklyContextMenu { + border-radius: 4px; + max-height: 100%; +}`, - '.blocklyDropdownMenu {', - 'border-radius: 2px;', - 'padding: 0 !important;', - '}', + `.blocklyDropdownMenu { + border-radius: 2px; + padding: 0 !important; +}`, - '.blocklyDropdownMenu .blocklyMenuItem {', - /* 28px on the left for icon or checkbox. */ - 'padding-left: 28px;', - '}', + `.blocklyDropdownMenu .blocklyMenuItem { + /* 28px on the left for icon or checkbox. */ + padding-left: 28px; +}`, /* BiDi override for the resting state. */ - '.blocklyDropdownMenu .blocklyMenuItemRtl {', - /* Flip left/right padding for BiDi. */ - 'padding-left: 5px;', - 'padding-right: 28px;', - '}', + `.blocklyDropdownMenu .blocklyMenuItemRtl { + /* Flip left/right padding for BiDi. */ + padding-left: 5px; + padding-right: 28px; +}`, - '.blocklyWidgetDiv .blocklyMenu {', - 'background: #fff;', - 'border: 1px solid transparent;', - 'box-shadow: 0 0 3px 1px rgba(0,0,0,.3);', - 'font: normal 13px Arial, sans-serif;', - 'margin: 0;', - 'outline: none;', - 'padding: 4px 0;', - 'position: absolute;', - 'overflow-y: auto;', - 'overflow-x: hidden;', - 'max-height: 100%;', - 'z-index: 20000;', /* Arbitrary, but some apps depend on it... */ - '}', + `.blocklyWidgetDiv .blocklyMenu { + background: #fff; + border: 1px solid transparent; + box-shadow: 0 0 3px 1px rgba(0,0,0,.3); + font: normal 13px Arial, sans-serif; + margin: 0; + outline: none; + padding: 4px 0; + position: absolute; + overflow-y: auto; + overflow-x: hidden; + max-height: 100%; + z-index: 20000;', /* Arbitrary, but some apps depend on it... */ +}`, - '.blocklyWidgetDiv .blocklyMenu.blocklyFocused {', - 'box-shadow: 0 0 6px 1px rgba(0,0,0,.3);', - '}', + `.blocklyWidgetDiv .blocklyMenu.blocklyFocused { + box-shadow: 0 0 6px 1px rgba(0,0,0,.3); +}`, - '.blocklyDropDownDiv .blocklyMenu {', - 'background: inherit;', /* Compatibility with gapi, reset from goog-menu */ - 'border: inherit;', /* Compatibility with gapi, reset from goog-menu */ - 'font: normal 13px "Helvetica Neue", Helvetica, sans-serif;', - 'outline: none;', - 'position: relative;', /* Compatibility with gapi, reset from goog-menu */ - 'z-index: 20000;', /* Arbitrary, but some apps depend on it... */ - '}', + `.blocklyDropDownDiv .blocklyMenu { + background: inherit;', /* Compatibility with gapi, reset from goog-menu */ + border: inherit;', /* Compatibility with gapi, reset from goog-menu */ + font: normal 13px "Helvetica Neue", Helvetica, sans-serif; + outline: none; + position: relative;', /* Compatibility with gapi, reset from goog-menu */ + z-index: 20000;', /* Arbitrary, but some apps depend on it... */ +}`, /* State: resting. */ - '.blocklyMenuItem {', - 'border: none;', - 'color: #000;', - 'cursor: pointer;', - 'list-style: none;', - 'margin: 0;', - /* 7em on the right for shortcut. */ - 'min-width: 7em;', - 'padding: 6px 15px;', - 'white-space: nowrap;', - '}', + `.blocklyMenuItem { + border: none; + color: #000; + cursor: pointer; + list-style: none; + margin: 0; + /* 7em on the right for shortcut. */ + min-width: 7em; + padding: 6px 15px; + white-space: nowrap; +}`, /* State: disabled. */ - '.blocklyMenuItemDisabled {', - 'color: #ccc;', - 'cursor: inherit;', - '}', + `.blocklyMenuItemDisabled { + color: #ccc; + cursor: inherit; +}`, /* State: hover. */ - '.blocklyMenuItemHighlight {', - 'background-color: rgba(0,0,0,.1);', - '}', + `.blocklyMenuItemHighlight { + background-color: rgba(0,0,0,.1); +}`, /* State: selected/checked. */ - '.blocklyMenuItemCheckbox {', - 'height: 16px;', - 'position: absolute;', - 'width: 16px;', - '}', + `.blocklyMenuItemCheckbox { + height: 16px; + position: absolute; + width: 16px; +}`, - '.blocklyMenuItemSelected .blocklyMenuItemCheckbox {', - 'background: url(<<>>/sprites.png) no-repeat -48px -16px;', - 'float: left;', - 'margin-left: -24px;', - 'position: static;', /* Scroll with the menu. */ - '}', + `.blocklyMenuItemSelected .blocklyMenuItemCheckbox { + background: url(<<>>/sprites.png) no-repeat -48px -16px; + float: left; + margin-left: -24px; + position: static;', /* Scroll with the menu. */ +}`, - '.blocklyMenuItemRtl .blocklyMenuItemCheckbox {', - 'float: right;', - 'margin-right: -24px;', - '}', - /* eslint-enable indent */ + `.blocklyMenuItemRtl .blocklyMenuItemCheckbox { + float: right; + margin-right: -24px; +}`, ]; +exports.CONTENT = CONTENT; diff --git a/core/delete_area.js b/core/delete_area.js index 384136a05..55eb61a34 100644 --- a/core/delete_area.js +++ b/core/delete_area.js @@ -12,23 +12,26 @@ 'use strict'; -goog.provide('Blockly.DeleteArea'); +goog.module('Blockly.DeleteArea'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.BlockSvg'); -goog.require('Blockly.DragTarget'); -goog.require('Blockly.IDeleteArea'); - -goog.requireType('Blockly.IDraggable'); +const BlockSvg = goog.require('Blockly.BlockSvg'); +const DragTarget = goog.require('Blockly.DragTarget'); +/* eslint-disable-next-line no-unused-vars */ +const IDeleteArea = goog.require('Blockly.IDeleteArea'); +/* eslint-disable-next-line no-unused-vars */ +const IDraggable = goog.requireType('Blockly.IDraggable'); +const {inherits} = goog.require('Blockly.utils.object'); /** * Abstract class for a component that can delete a block or bubble that is * dropped on top of it. - * @extends {Blockly.DragTarget} - * @implements {Blockly.IDeleteArea} + * @extends {DragTarget} + * @implements {IDeleteArea} * @constructor */ -Blockly.DeleteArea = function() { - Blockly.DeleteArea.superClass_.constructor.call(this); +const DeleteArea = function() { + DeleteArea.superClass_.constructor.call(this); /** * Whether the last block or bubble dragged over this delete area would be @@ -39,24 +42,24 @@ Blockly.DeleteArea = function() { */ this.wouldDelete_ = false; }; -Blockly.utils.object.inherits(Blockly.DeleteArea, Blockly.DragTarget); +inherits(DeleteArea, DragTarget); /** * Returns whether the provided block or bubble would be deleted if dropped on * this area. * This method should check if the element is deletable and is always called * before onDragEnter/onDragOver/onDragExit. - * @param {!Blockly.IDraggable} element The block or bubble currently being + * @param {!IDraggable} element The block or bubble currently being * dragged. * @param {boolean} couldConnect Whether the element could could connect to * another. * @return {boolean} Whether the element provided would be deleted if dropped on * this area. */ -Blockly.DeleteArea.prototype.wouldDelete = function(element, couldConnect) { - if (element instanceof Blockly.BlockSvg) { - var block = /** @type {Blockly.BlockSvg} */ (element); - var couldDeleteBlock = !block.getParent() && block.isDeletable(); +DeleteArea.prototype.wouldDelete = function(element, couldConnect) { + if (element instanceof BlockSvg) { + const block = /** @type {BlockSvg} */ (element); + const couldDeleteBlock = !block.getParent() && block.isDeletable(); this.updateWouldDelete_(couldDeleteBlock && !couldConnect); } else { this.updateWouldDelete_(element.isDeletable()); @@ -69,6 +72,8 @@ Blockly.DeleteArea.prototype.wouldDelete = function(element, couldConnect) { * @param {boolean} wouldDelete The new value for the wouldDelete state. * @protected */ -Blockly.DeleteArea.prototype.updateWouldDelete_ = function(wouldDelete) { +DeleteArea.prototype.updateWouldDelete_ = function(wouldDelete) { this.wouldDelete_ = wouldDelete; }; + +exports = DeleteArea; diff --git a/core/drag_target.js b/core/drag_target.js index 438bf6a31..18e29b40a 100644 --- a/core/drag_target.js +++ b/core/drag_target.js @@ -12,65 +12,68 @@ 'use strict'; -goog.provide('Blockly.DragTarget'); +goog.module('Blockly.DragTarget'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.IDragTarget'); - -goog.requireType('Blockly.IDraggable'); -goog.requireType('Blockly.utils.Rect'); +/* eslint-disable-next-line no-unused-vars */ +const IDragTarget = goog.require('Blockly.IDragTarget'); +/* eslint-disable-next-line no-unused-vars */ +const IDraggable = goog.requireType('Blockly.IDraggable'); +/* eslint-disable-next-line no-unused-vars */ +const Rect = goog.requireType('Blockly.utils.Rect'); /** * Abstract class for a component with custom behaviour when a block or bubble * is dragged over or dropped on top of it. - * @implements {Blockly.IDragTarget} + * @implements {IDragTarget} * @constructor */ -Blockly.DragTarget = function() {}; +const DragTarget = function() {}; /** * Returns the bounding rectangle of the drag target area in pixel units * relative to the Blockly injection div. - * @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.DragTarget.prototype.getClientRect; +DragTarget.prototype.getClientRect; /** * Handles when a cursor with a block or bubble enters this drag target. - * @param {!Blockly.IDraggable} _dragElement The block or bubble currently being + * @param {!IDraggable} _dragElement The block or bubble currently being * dragged. */ -Blockly.DragTarget.prototype.onDragEnter = function(_dragElement) { +DragTarget.prototype.onDragEnter = function(_dragElement) { // no-op }; /** * Handles when a cursor with a block or bubble is dragged over this drag * target. - * @param {!Blockly.IDraggable} _dragElement The block or bubble currently being + * @param {!IDraggable} _dragElement The block or bubble currently being * dragged. */ -Blockly.DragTarget.prototype.onDragOver = function(_dragElement) { +DragTarget.prototype.onDragOver = function(_dragElement) { // no-op }; /** * Handles when a cursor with a block or bubble exits this drag target. - * @param {!Blockly.IDraggable} _dragElement The block or bubble currently being + * @param {!IDraggable} _dragElement The block or bubble currently being * dragged. */ -Blockly.DragTarget.prototype.onDragExit = function(_dragElement) { +DragTarget.prototype.onDragExit = function(_dragElement) { // no-op }; /** * Handles when a block or bubble is dropped on this component. * Should not handle delete here. - * @param {!Blockly.IDraggable} _dragElement The block or bubble currently being + * @param {!IDraggable} _dragElement The block or bubble currently being * dragged. */ -Blockly.DragTarget.prototype.onDrop = function(_dragElement) { +DragTarget.prototype.onDrop = function(_dragElement) { // no-op }; @@ -78,11 +81,13 @@ Blockly.DragTarget.prototype.onDrop = function(_dragElement) { * Returns whether the provided block or bubble should not be moved after being * dropped on this component. If true, the element will return to where it was * when the drag started. - * @param {!Blockly.IDraggable} _dragElement The block or bubble currently being + * @param {!IDraggable} _dragElement The block or bubble currently being * dragged. * @return {boolean} Whether the block or bubble provided should be returned to * drag start. */ -Blockly.DragTarget.prototype.shouldPreventMove = function(_dragElement) { +DragTarget.prototype.shouldPreventMove = function(_dragElement) { return false; }; + +exports = DragTarget; diff --git a/core/extensions.js b/core/extensions.js index 0a2c146ad..3f20777aa 100644 --- a/core/extensions.js +++ b/core/extensions.js @@ -17,18 +17,20 @@ * @name Blockly.Extensions * @namespace */ -goog.provide('Blockly.Extensions'); +goog.module('Blockly.Extensions'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.utils'); - -goog.requireType('Blockly.Block'); +/* eslint-disable-next-line no-unused-vars */ +const Block = goog.requireType('Blockly.Block'); +const {checkMessageReferences, replaceMessageReferences, runAfterPageLoad} = goog.require('Blockly.utils'); /** * The set of all registered extensions, keyed by extension name/id. * @private */ -Blockly.Extensions.ALL_ = Object.create(null); +const allExtensions = Object.create(null); +exports.ALL_ = allExtensions; /** * Registers a new extension function. Extensions are functions that help @@ -40,18 +42,19 @@ Blockly.Extensions.ALL_ = Object.create(null); * @throws {Error} if the extension name is empty, the extension is already * registered, or extensionFn is not a function. */ -Blockly.Extensions.register = function(name, initFn) { +const register = function(name, initFn) { if ((typeof name != 'string') || (name.trim() == '')) { throw Error('Error: Invalid extension name "' + name + '"'); } - if (Blockly.Extensions.ALL_[name]) { + if (allExtensions[name]) { throw Error('Error: Extension "' + name + '" is already registered.'); } if (typeof initFn != 'function') { throw Error('Error: Extension "' + name + '" must be a function'); } - Blockly.Extensions.ALL_[name] = initFn; + allExtensions[name] = initFn; }; +exports.register = register; /** * Registers a new extension function that adds all key/value of mixinObj. @@ -60,14 +63,15 @@ Blockly.Extensions.register = function(name, initFn) { * @throws {Error} if the extension name is empty or the extension is already * registered. */ -Blockly.Extensions.registerMixin = function(name, mixinObj) { +const registerMixin = function(name, mixinObj) { if (!mixinObj || typeof mixinObj != 'object') { throw Error('Error: Mixin "' + name + '" must be a object'); } - Blockly.Extensions.register(name, function() { + register(name, function() { this.mixin(mixinObj); }); }; +exports.registerMixin = registerMixin; /** * Registers a new extension function that adds a mutator to the block. @@ -82,25 +86,21 @@ Blockly.Extensions.registerMixin = function(name, mixinObj) { * flyout of the mutator dialog. * @throws {Error} if the mutation is invalid or can't be applied to the block. */ -Blockly.Extensions.registerMutator = function(name, mixinObj, opt_helperFn, - opt_blockList) { - var errorPrefix = 'Error when registering mutator "' + name + '": '; +const registerMutator = function(name, mixinObj, opt_helperFn, opt_blockList) { + const errorPrefix = 'Error when registering mutator "' + name + '": '; // Sanity check the mixin object before registering it. - Blockly.Extensions.checkHasFunction_( - errorPrefix, mixinObj.domToMutation, 'domToMutation'); - Blockly.Extensions.checkHasFunction_( - errorPrefix, mixinObj.mutationToDom, 'mutationToDom'); + checkHasFunction(errorPrefix, mixinObj.domToMutation, 'domToMutation'); + checkHasFunction(errorPrefix, mixinObj.mutationToDom, 'mutationToDom'); - var hasMutatorDialog = - Blockly.Extensions.checkMutatorDialog_(mixinObj, errorPrefix); + const hasMutatorDialog = checkMutatorDialog(mixinObj, errorPrefix); if (opt_helperFn && (typeof opt_helperFn != 'function')) { throw Error('Extension "' + name + '" is not a function'); } // Sanity checks passed. - Blockly.Extensions.register(name, function() { + register(name, function() { if (hasMutatorDialog) { if (!Blockly.Mutator) { throw Error(errorPrefix + 'Missing require for Blockly.Mutator'); @@ -115,54 +115,59 @@ Blockly.Extensions.registerMutator = function(name, mixinObj, opt_helperFn, } }); }; +exports.registerMutator = registerMutator; /** * Unregisters the extension registered with the given name. * @param {string} name The name of the extension to unregister. */ -Blockly.Extensions.unregister = function(name) { - if (Blockly.Extensions.ALL_[name]) { - delete Blockly.Extensions.ALL_[name]; +const unregister = function(name) { + if (allExtensions[name]) { + delete allExtensions[name]; } else { - console.warn('No extension mapping for name "' + name + - '" found to unregister'); + console.warn( + 'No extension mapping for name "' + name + '" found to unregister'); } }; +exports.unregister = unregister; /** * Applies an extension method to a block. This should only be called during * block construction. * @param {string} name The name of the extension. - * @param {!Blockly.Block} block The block to apply the named extension to. + * @param {!Block} block The block to apply the named extension to. * @param {boolean} isMutator True if this extension defines a mutator. * @throws {Error} if the extension is not found. */ -Blockly.Extensions.apply = function(name, block, isMutator) { - var extensionFn = Blockly.Extensions.ALL_[name]; +const apply = function(name, block, isMutator) { + const extensionFn = allExtensions[name]; if (typeof extensionFn != 'function') { throw Error('Error: Extension "' + name + '" not found.'); } + let mutatorProperties; if (isMutator) { // Fail early if the block already has mutation properties. - Blockly.Extensions.checkNoMutatorProperties_(name, block); + checkNoMutatorProperties(name, block); } else { // Record the old properties so we can make sure they don't change after // applying the extension. - var mutatorProperties = Blockly.Extensions.getMutatorProperties_(block); + mutatorProperties = getMutatorProperties(block); } extensionFn.apply(block); if (isMutator) { - var errorPrefix = 'Error after applying mutator "' + name + '": '; - Blockly.Extensions.checkBlockHasMutatorProperties_(errorPrefix, block); + const errorPrefix = 'Error after applying mutator "' + name + '": '; + checkBlockHasMutatorProperties(errorPrefix, block); } else { - if (!Blockly.Extensions.mutatorPropertiesMatch_( - /** @type {!Array} */ (mutatorProperties), block)) { - throw Error('Error when applying extension "' + name + '": ' + + if (!mutatorPropertiesMatch( + /** @type {!Array} */ (mutatorProperties), block)) { + throw Error( + 'Error when applying extension "' + name + '": ' + 'mutation properties changed when applying a non-mutator extension.'); } } }; +exports.apply = apply; /** * Check that the given value is a function. @@ -172,14 +177,14 @@ Blockly.Extensions.apply = function(name, block, isMutator) { * @throws {Error} if the property does not exist or is not a function. * @private */ -Blockly.Extensions.checkHasFunction_ = function(errorPrefix, func, - propertyName) { +const checkHasFunction = function(errorPrefix, func, propertyName) { if (!func) { - throw Error(errorPrefix + - 'missing required property "' + propertyName + '"'); + throw Error( + errorPrefix + 'missing required property "' + propertyName + '"'); } else if (typeof func != 'function') { - throw Error(errorPrefix + - '" required property "' + propertyName + '" must be a function'); + throw Error( + errorPrefix + '" required property "' + propertyName + + '" must be a function'); } }; @@ -189,14 +194,15 @@ Blockly.Extensions.checkHasFunction_ = function(errorPrefix, func, * extension to a block, to make sure we are not overwriting properties. * @param {string} mutationName The name of the mutation to reference in error * messages. - * @param {!Blockly.Block} block The block to check. + * @param {!Block} block The block to check. * @throws {Error} if any of the properties already exist on the block. * @private */ -Blockly.Extensions.checkNoMutatorProperties_ = function(mutationName, block) { - var properties = Blockly.Extensions.getMutatorProperties_(block); +const checkNoMutatorProperties = function(mutationName, block) { + const properties = getMutatorProperties(block); if (properties.length) { - throw Error('Error: tried to apply mutation "' + mutationName + + throw Error( + 'Error: tried to apply mutation "' + mutationName + '" to a block that already has mutator functions.' + ' Block id: ' + block.id); } @@ -214,9 +220,9 @@ Blockly.Extensions.checkNoMutatorProperties_ = function(mutationName, block) { * @throws {Error} if the object has only one of the functions. * @private */ -Blockly.Extensions.checkMutatorDialog_ = function(object, errorPrefix) { - var hasCompose = object.compose !== undefined; - var hasDecompose = object.decompose !== undefined; +const checkMutatorDialog = function(object, errorPrefix) { + const hasCompose = object.compose !== undefined; + const hasDecompose = object.decompose !== undefined; if (hasCompose && hasDecompose) { if (typeof object.compose != 'function') { @@ -228,19 +234,18 @@ Blockly.Extensions.checkMutatorDialog_ = function(object, errorPrefix) { } else if (!hasCompose && !hasDecompose) { return false; } - throw Error(errorPrefix + - 'Must have both or neither of "compose" and "decompose"'); + throw Error( + errorPrefix + 'Must have both or neither of "compose" and "decompose"'); }; /** * Check that a block has required mutator properties. This should be called * after applying a mutation extension. * @param {string} errorPrefix The string to prepend to any error message. - * @param {!Blockly.Block} block The block to inspect. + * @param {!Block} block The block to inspect. * @private */ -Blockly.Extensions.checkBlockHasMutatorProperties_ = function(errorPrefix, - block) { +const checkBlockHasMutatorProperties = function(errorPrefix, block) { if (typeof block.domToMutation != 'function') { throw Error(errorPrefix + 'Applying a mutator didn\'t add "domToMutation"'); } @@ -250,18 +255,18 @@ Blockly.Extensions.checkBlockHasMutatorProperties_ = function(errorPrefix, // A block with a mutator isn't required to have a mutation dialog, but // it should still have both or neither of compose and decompose. - Blockly.Extensions.checkMutatorDialog_(block, errorPrefix); + checkMutatorDialog(block, errorPrefix); }; /** * Get a list of values of mutator properties on the given block. - * @param {!Blockly.Block} block The block to inspect. + * @param {!Block} block The block to inspect. * @return {!Array} A list with all of the defined properties, which * should be functions, but may be anything other than undefined. * @private */ -Blockly.Extensions.getMutatorProperties_ = function(block) { - var result = []; +const getMutatorProperties = function(block) { + const result = []; // List each function explicitly by reference to allow for renaming // during compilation. if (block.domToMutation !== undefined) { @@ -284,16 +289,16 @@ Blockly.Extensions.getMutatorProperties_ = function(block) { * properties. This should be called after applying a non-mutator extension, * to verify that the extension didn't change properties it shouldn't. * @param {!Array} oldProperties The old values to compare to. - * @param {!Blockly.Block} block The block to inspect for new values. + * @param {!Block} block The block to inspect for new values. * @return {boolean} True if the property lists match. * @private */ -Blockly.Extensions.mutatorPropertiesMatch_ = function(oldProperties, block) { - var newProperties = Blockly.Extensions.getMutatorProperties_(block); +const mutatorPropertiesMatch = function(oldProperties, block) { + const newProperties = getMutatorProperties(block); if (newProperties.length != oldProperties.length) { return false; } - for (var i = 0; i < newProperties.length; i++) { + for (let i = 0; i < newProperties.length; i++) { if (oldProperties[i] != newProperties[i]) { return false; } @@ -320,76 +325,75 @@ Blockly.Extensions.mutatorPropertiesMatch_ = function(oldProperties, block) { * tooltip text. * @return {!Function} The extension function. */ -Blockly.Extensions.buildTooltipForDropdown = function(dropdownName, - lookupTable) { +const buildTooltipForDropdown = function(dropdownName, lookupTable) { // List of block types already validated, to minimize duplicate warnings. - var blockTypesChecked = []; + const blockTypesChecked = []; // Check the tooltip string messages for invalid references. // Wait for load, in case Blockly.Msg is not yet populated. // runAfterPageLoad() does not run in a Node.js environment due to lack of // document object, in which case skip the validation. if (typeof document == 'object') { // Relies on document.readyState - Blockly.utils.runAfterPageLoad(function() { - for (var key in lookupTable) { + runAfterPageLoad(function() { + for (let key in lookupTable) { // Will print warnings if reference is missing. - Blockly.utils.checkMessageReferences(lookupTable[key]); + checkMessageReferences(lookupTable[key]); } }); } /** * The actual extension. - * @this {Blockly.Block} + * @this {Block} */ - var extensionFn = function() { + const extensionFn = function() { if (this.type && blockTypesChecked.indexOf(this.type) == -1) { - Blockly.Extensions.checkDropdownOptionsInTable_( - this, dropdownName, lookupTable); + checkDropdownOptionsInTable(this, dropdownName, lookupTable); blockTypesChecked.push(this.type); } this.setTooltip(function() { - var value = String(this.getFieldValue(dropdownName)); - var tooltip = lookupTable[value]; + const value = String(this.getFieldValue(dropdownName)); + let tooltip = lookupTable[value]; if (tooltip == null) { if (blockTypesChecked.indexOf(this.type) == -1) { // Warn for missing values on generated tooltips. - var warning = 'No tooltip mapping for value ' + value + - ' of field ' + dropdownName; + let warning = 'No tooltip mapping for value ' + value + ' of field ' + + dropdownName; if (this.type != null) { warning += (' of block type ' + this.type); } console.warn(warning + '.'); } } else { - tooltip = Blockly.utils.replaceMessageReferences(tooltip); + tooltip = replaceMessageReferences(tooltip); } return tooltip; }.bind(this)); }; return extensionFn; }; +exports.buildTooltipForDropdown = buildTooltipForDropdown; /** * Checks all options keys are present in the provided string lookup table. * Emits console warnings when they are not. - * @param {!Blockly.Block} block The block containing the dropdown + * @param {!Block} block The block containing the dropdown * @param {string} dropdownName The name of the dropdown * @param {!Object} lookupTable The string lookup table * @private */ -Blockly.Extensions.checkDropdownOptionsInTable_ = function(block, dropdownName, - lookupTable) { +const checkDropdownOptionsInTable = function(block, dropdownName, lookupTable) { // Validate all dropdown options have values. - var dropdown = block.getField(dropdownName); + const dropdown = block.getField(dropdownName); if (!dropdown.isOptionListDynamic()) { - var options = dropdown.getOptions(); - for (var i = 0; i < options.length; ++i) { - var optionKey = options[i][1]; // label, then value + const options = dropdown.getOptions(); + for (let i = 0; i < options.length; ++i) { + const optionKey = options[i][1]; // label, then value if (lookupTable[optionKey] == null) { - console.warn('No tooltip mapping for value ' + optionKey + - ' of field ' + dropdownName + ' of block type ' + block.type); + console.warn( + 'No tooltip mapping for value ' + optionKey + ' of field ' + + dropdownName + ' of block type ' + block.type); } } } @@ -404,48 +408,47 @@ Blockly.Extensions.checkDropdownOptionsInTable_ = function(block, dropdownName, * @param {string} fieldName The field with the replacement text. * @return {!Function} The extension function. */ -Blockly.Extensions.buildTooltipWithFieldText = function(msgTemplate, - fieldName) { +const buildTooltipWithFieldText = function(msgTemplate, fieldName) { // Check the tooltip string messages for invalid references. // Wait for load, in case Blockly.Msg is not yet populated. // runAfterPageLoad() does not run in a Node.js environment due to lack of // document object, in which case skip the validation. if (typeof document == 'object') { // Relies on document.readyState - Blockly.utils.runAfterPageLoad(function() { + runAfterPageLoad(function() { // Will print warnings if reference is missing. - Blockly.utils.checkMessageReferences(msgTemplate); + checkMessageReferences(msgTemplate); }); } /** * The actual extension. - * @this {Blockly.Block} + * @this {Block} */ - var extensionFn = function() { + const extensionFn = function() { this.setTooltip(function() { - var field = this.getField(fieldName); - return Blockly.utils.replaceMessageReferences(msgTemplate) + const field = this.getField(fieldName); + return replaceMessageReferences(msgTemplate) .replace('%1', field ? field.getText() : ''); }.bind(this)); }; return extensionFn; }; +exports.buildTooltipWithFieldText = buildTooltipWithFieldText; /** * Configures the tooltip to mimic the parent block when connected. Otherwise, * uses the tooltip text at the time this extension is initialized. This takes * advantage of the fact that all other values from JSON are initialized before * extensions. - * @this {Blockly.Block} + * @this {Block} * @private */ -Blockly.Extensions.extensionParentTooltip_ = function() { - this.tooltipWhenNotConnected_ = this.tooltip; +const extensionParentTooltip = function() { + this.tooltipWhenNotConnected = this.tooltip; this.setTooltip(function() { - var parent = this.getParent(); + const parent = this.getParent(); return (parent && parent.getInputsInline() && parent.tooltip) || - this.tooltipWhenNotConnected_; + this.tooltipWhenNotConnected; }.bind(this)); }; -Blockly.Extensions.register('parent_tooltip_when_inline', - Blockly.Extensions.extensionParentTooltip_); +register('parent_tooltip_when_inline', extensionParentTooltip); diff --git a/core/field.js b/core/field.js index c343359da..926e62008 100644 --- a/core/field.js +++ b/core/field.js @@ -7,42 +7,54 @@ /** * @fileoverview Field. Used for editable titles, variables, etc. * This is an abstract class that defines the UI on the block. Actual - * instances would be Blockly.FieldTextInput, Blockly.FieldDropdown, etc. + * instances would be FieldTextInput, FieldDropdown, etc. * @author fraser@google.com (Neil Fraser) */ 'use strict'; -goog.provide('Blockly.Field'); +goog.module('Blockly.Field'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.browserEvents'); -goog.require('Blockly.DropDownDiv'); -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'); +/* eslint-disable-next-line no-unused-vars */ +const ConstantProvider = goog.requireType('Blockly.blockRendering.ConstantProvider'); +/* eslint-disable-next-line no-unused-vars */ +const Coordinate = goog.requireType('Blockly.utils.Coordinate'); +const DropDownDiv = goog.require('Blockly.DropDownDiv'); +const Events = goog.require('Blockly.Events'); +/* eslint-disable-next-line no-unused-vars */ +const IASTNodeLocationSvg = goog.require('Blockly.IASTNodeLocationSvg'); +/* eslint-disable-next-line no-unused-vars */ +const IASTNodeLocationWithBlock = goog.require('Blockly.IASTNodeLocationWithBlock'); +/* eslint-disable-next-line no-unused-vars */ +const IKeyboardAccessible = goog.require('Blockly.IKeyboardAccessible'); +/* eslint-disable-next-line no-unused-vars */ +const IRegistrable = goog.require('Blockly.IRegistrable'); +/* eslint-disable-next-line no-unused-vars */ +const Input = goog.requireType('Blockly.Input'); +const MarkerManager = goog.require('Blockly.MarkerManager'); +const Rect = goog.require('Blockly.utils.Rect'); +/* eslint-disable-next-line no-unused-vars */ +const ShortcutRegistry = goog.requireType('Blockly.ShortcutRegistry'); +const Size = goog.require('Blockly.utils.Size'); +const Svg = goog.require('Blockly.utils.Svg'); +const Tooltip = goog.require('Blockly.Tooltip'); +const WidgetDiv = goog.require('Blockly.WidgetDiv'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +const userAgent = goog.require('Blockly.utils.userAgent'); +const {addClass, createSvgElement, getFastTextWidth, removeClass, removeNode} = goog.require('Blockly.utils.dom'); +/* eslint-disable-next-line no-unused-vars */ +const {conditionalBind, unbind, Data} = goog.require('Blockly.browserEvents'); +const {getPageOffset} = goog.require('Blockly.utils.style'); +const {replaceMessageReferences} = goog.require('Blockly.utils'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockChange'); /** @suppress {extraRequire} */ goog.require('Blockly.Gesture'); -goog.require('Blockly.IASTNodeLocationSvg'); -goog.require('Blockly.IASTNodeLocationWithBlock'); -goog.require('Blockly.IKeyboardAccessible'); -goog.require('Blockly.IRegistrable'); -goog.require('Blockly.MarkerManager'); -goog.require('Blockly.Tooltip'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.Rect'); -goog.require('Blockly.utils.Size'); -goog.require('Blockly.utils.style'); -goog.require('Blockly.utils.Svg'); -goog.require('Blockly.utils.userAgent'); -goog.require('Blockly.WidgetDiv'); - -goog.requireType('Blockly.Block'); -goog.requireType('Blockly.blockRendering.ConstantProvider'); -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.Input'); -goog.requireType('Blockly.ShortcutRegistry'); -goog.requireType('Blockly.utils.Coordinate'); -goog.requireType('Blockly.WorkspaceSvg'); /** @@ -56,12 +68,12 @@ goog.requireType('Blockly.WorkspaceSvg'); * parameter supports. * @constructor * @abstract - * @implements {Blockly.IASTNodeLocationSvg} - * @implements {Blockly.IASTNodeLocationWithBlock} - * @implements {Blockly.IKeyboardAccessible} - * @implements {Blockly.IRegistrable} + * @implements {IASTNodeLocationSvg} + * @implements {IASTNodeLocationWithBlock} + * @implements {IKeyboardAccessible} + * @implements {IRegistrable} */ -Blockly.Field = function(value, opt_validator, opt_config) { +const Field = function(value, opt_validator, opt_config) { /** * A generic value possessed by the field. * Should generally be non-null, only null when the field is created. @@ -80,17 +92,17 @@ Blockly.Field = function(value, opt_validator, opt_config) { /** * Used to cache the field's tooltip value if setTooltip is called when the * field is not yet initialized. Is *not* guaranteed to be accurate. - * @type {?Blockly.Tooltip.TipInfo} + * @type {?Tooltip.TipInfo} * @private */ this.tooltip_ = null; /** * The size of the area rendered by the field. - * @type {!Blockly.utils.Size} + * @type {!Size} * @protected */ - this.size_ = new Blockly.utils.Size(0, 0); + this.size_ = new Size(0, 0); /** * Holds the cursors svg element when the cursor is attached to the field. @@ -138,14 +150,14 @@ Blockly.Field = function(value, opt_validator, opt_config) { /** * Mouse down event listener data. - * @type {?Blockly.browserEvents.Data} + * @type {?Data} * @private */ this.mouseDownWrapper_ = null; /** * Constants associated with the source block's renderer. - * @type {Blockly.blockRendering.ConstantProvider} + * @type {ConstantProvider} * @protected */ this.constants_ = null; @@ -160,55 +172,62 @@ Blockly.Field = function(value, opt_validator, opt_config) { * @type {*} * @protected */ -Blockly.Field.prototype.DEFAULT_VALUE = null; +Field.prototype.DEFAULT_VALUE = null; /** * Name of field. Unique within each block. * Static labels are usually unnamed. * @type {string|undefined} */ -Blockly.Field.prototype.name = undefined; +Field.prototype.name = undefined; /** * Has this field been disposed of? * @type {boolean} * @package */ -Blockly.Field.prototype.disposed = false; +Field.prototype.disposed = false; /** * Maximum characters of text to display before adding an ellipsis. * @type {number} */ -Blockly.Field.prototype.maxDisplayLength = 50; +Field.prototype.maxDisplayLength = 50; /** * Block this field is attached to. Starts as null, then set in init. - * @type {Blockly.Block} + * @type {Block} * @protected */ -Blockly.Field.prototype.sourceBlock_ = null; +Field.prototype.sourceBlock_ = null; /** * Does this block need to be re-rendered? * @type {boolean} * @protected */ -Blockly.Field.prototype.isDirty_ = true; +Field.prototype.isDirty_ = true; /** * Is the field visible, or hidden due to the block being collapsed? * @type {boolean} * @protected */ -Blockly.Field.prototype.visible_ = true; +Field.prototype.visible_ = true; + +/** + * Can the field value be changed using the editor on an editable block? + * @type {boolean} + * @protected + */ +Field.prototype.enabled_ = true; /** * The element the click handler is bound to. * @type {Element} * @protected */ -Blockly.Field.prototype.clickTarget_ = null; +Field.prototype.clickTarget_ = null; /** * A developer hook to override the returned text of this field. @@ -218,7 +237,7 @@ Blockly.Field.prototype.clickTarget_ = null; * @return {?string} Current text. Return null to resort to a string cast. * @protected */ -Blockly.Field.prototype.getText_; +Field.prototype.getText_; /** * An optional method that can be defined to show an editor when the field is @@ -229,20 +248,20 @@ Blockly.Field.prototype.getText_; * @return {void} * @protected */ -Blockly.Field.prototype.showEditor_; +Field.prototype.showEditor_; /** * Non-breaking space. * @const */ -Blockly.Field.NBSP = '\u00A0'; +Field.NBSP = '\u00A0'; /** * Editable fields usually show some sort of UI indicating they are editable. * They will also be saved by the XML renderer. * @type {boolean} */ -Blockly.Field.prototype.EDITABLE = true; +Field.prototype.EDITABLE = true; /** * Serializable fields are saved by the XML renderer, non-serializable fields @@ -250,7 +269,7 @@ Blockly.Field.prototype.EDITABLE = true; * case by default so that SERIALIZABLE is backwards compatible. * @type {boolean} */ -Blockly.Field.prototype.SERIALIZABLE = false; +Field.prototype.SERIALIZABLE = false; /** * Process the configuration map passed to the field. @@ -259,11 +278,10 @@ Blockly.Field.prototype.SERIALIZABLE = false; * parameter supports. * @protected */ -Blockly.Field.prototype.configure_ = function(config) { - var tooltip = config['tooltip']; +Field.prototype.configure_ = function(config) { + let tooltip = config['tooltip']; if (typeof tooltip == 'string') { - tooltip = Blockly.utils.replaceMessageReferences( - config['tooltip']); + tooltip = replaceMessageReferences(config['tooltip']); } tooltip && this.setTooltip(tooltip); @@ -273,9 +291,9 @@ Blockly.Field.prototype.configure_ = function(config) { /** * Attach this field to a block. - * @param {!Blockly.Block} block The block containing this field. + * @param {!Block} block The block containing this field. */ -Blockly.Field.prototype.setSourceBlock = function(block) { +Field.prototype.setSourceBlock = function(block) { if (this.sourceBlock_) { throw Error('Field already bound to a block'); } @@ -284,10 +302,10 @@ Blockly.Field.prototype.setSourceBlock = function(block) { /** * Get the renderer constant provider. - * @return {?Blockly.blockRendering.ConstantProvider} The renderer constant + * @return {?ConstantProvider} The renderer constant * provider. */ -Blockly.Field.prototype.getConstants = function() { +Field.prototype.getConstants = function() { if (!this.constants_ && this.sourceBlock_ && this.sourceBlock_.workspace && this.sourceBlock_.workspace.rendered) { this.constants_ = this.sourceBlock_.workspace.getRenderer().getConstants(); @@ -297,9 +315,9 @@ Blockly.Field.prototype.getConstants = function() { /** * Get the block this field is attached to. - * @return {Blockly.Block} The block containing this field. + * @return {Block} The block containing this field. */ -Blockly.Field.prototype.getSourceBlock = function() { +Field.prototype.getSourceBlock = function() { return this.sourceBlock_; }; @@ -308,17 +326,16 @@ Blockly.Field.prototype.getSourceBlock = function() { * methods initModel and initView rather than this method. * @package */ -Blockly.Field.prototype.init = function() { +Field.prototype.init = function() { if (this.fieldGroup_) { // Field has already been initialized once. return; } - this.fieldGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, {}, null); + this.fieldGroup_ = createSvgElement(Svg.G, {}, null); if (!this.isVisible()) { this.fieldGroup_.style.display = 'none'; } - var sourceBlockSvg = /** @type {!Blockly.BlockSvg} **/ (this.sourceBlock_); + const sourceBlockSvg = /** @type {!BlockSvg} **/ (this.sourceBlock_); sourceBlockSvg.getSvgRoot().appendChild(this.fieldGroup_); this.initView(); this.updateEditable(); @@ -331,7 +348,7 @@ Blockly.Field.prototype.init = function() { * Create the block UI for this field. * @package */ -Blockly.Field.prototype.initView = function() { +Field.prototype.initView = function() { this.createBorderRect_(); this.createTextElement_(); }; @@ -341,8 +358,7 @@ Blockly.Field.prototype.initView = function() { * No-op by default. * @package */ -Blockly.Field.prototype.initModel = function() { -}; +Field.prototype.initModel = function() {}; /** * Create a field border rect element. Not to be overridden by subclasses. @@ -350,9 +366,9 @@ Blockly.Field.prototype.initModel = function() { * separate function to call. * @protected */ -Blockly.Field.prototype.createBorderRect_ = function() { - this.borderRect_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.RECT, { +Field.prototype.createBorderRect_ = function() { + this.borderRect_ = createSvgElement( + Svg.RECT, { 'rx': this.getConstants().FIELD_BORDER_RECT_RADIUS, 'ry': this.getConstants().FIELD_BORDER_RECT_RADIUS, 'x': 0, @@ -360,7 +376,8 @@ Blockly.Field.prototype.createBorderRect_ = function() { 'height': this.size_.height, 'width': this.size_.width, 'class': 'blocklyFieldRect' - }, this.fieldGroup_); + }, + this.fieldGroup_); }; /** @@ -369,11 +386,12 @@ Blockly.Field.prototype.createBorderRect_ = function() { * function to call. * @protected */ -Blockly.Field.prototype.createTextElement_ = function() { - this.textElement_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.TEXT, { +Field.prototype.createTextElement_ = function() { + this.textElement_ = createSvgElement( + Svg.TEXT, { 'class': 'blocklyText', - }, this.fieldGroup_); + }, + this.fieldGroup_); if (this.getConstants().FIELD_TEXT_BASELINE_CENTER) { this.textElement_.setAttribute('dominant-baseline', 'central'); } @@ -386,20 +404,20 @@ Blockly.Field.prototype.createTextElement_ = function() { * custom input handling. * @protected */ -Blockly.Field.prototype.bindEvents_ = function() { - Blockly.Tooltip.bindMouseEvents(this.getClickTarget_()); - this.mouseDownWrapper_ = Blockly.browserEvents.conditionalBind( +Field.prototype.bindEvents_ = function() { + Tooltip.bindMouseEvents(this.getClickTarget_()); + this.mouseDownWrapper_ = conditionalBind( this.getClickTarget_(), 'mousedown', this, this.onMouseDown_); }; /** - * Sets the field's value based on the given XML element. Should only be - * called by Blockly.Xml. + * Sets the field's value based on the given XML element. Should only be called + * by Blockly.Xml. * @param {!Element} fieldElement The element containing info about the * field's state. * @package */ -Blockly.Field.prototype.fromXml = function(fieldElement) { +Field.prototype.fromXml = function(fieldElement) { this.setValue(fieldElement.textContent); }; @@ -410,7 +428,7 @@ Blockly.Field.prototype.fromXml = function(fieldElement) { * @return {!Element} The element containing info about the field's state. * @package */ -Blockly.Field.prototype.toXml = function(fieldElement) { +Field.prototype.toXml = function(fieldElement) { fieldElement.textContent = this.getValue(); return fieldElement; }; @@ -419,16 +437,16 @@ Blockly.Field.prototype.toXml = function(fieldElement) { * Dispose of all DOM objects and events belonging to this editable field. * @package */ -Blockly.Field.prototype.dispose = function() { - Blockly.DropDownDiv.hideIfOwner(this); - Blockly.WidgetDiv.hideIfOwner(this); - Blockly.Tooltip.unbindMouseEvents(this.getClickTarget_()); +Field.prototype.dispose = function() { + DropDownDiv.hideIfOwner(this); + WidgetDiv.hideIfOwner(this); + Tooltip.unbindMouseEvents(this.getClickTarget_()); if (this.mouseDownWrapper_) { - Blockly.browserEvents.unbind(this.mouseDownWrapper_); + unbind(this.mouseDownWrapper_); } - Blockly.utils.dom.removeNode(this.fieldGroup_); + removeNode(this.fieldGroup_); this.disposed = true; }; @@ -436,39 +454,61 @@ Blockly.Field.prototype.dispose = function() { /** * Add or remove the UI indicating if this field is editable or not. */ -Blockly.Field.prototype.updateEditable = function() { - var group = this.fieldGroup_; +Field.prototype.updateEditable = function() { + const group = this.fieldGroup_; if (!this.EDITABLE || !group) { return; } - if (this.sourceBlock_.isEditable()) { - Blockly.utils.dom.addClass(group, 'blocklyEditableText'); - Blockly.utils.dom.removeClass(group, 'blocklyNonEditableText'); + if (this.enabled_ && this.sourceBlock_.isEditable()) { + addClass(group, 'blocklyEditableText'); + removeClass(group, 'blocklyNonEditableText'); group.style.cursor = this.CURSOR; } else { - Blockly.utils.dom.addClass(group, 'blocklyNonEditableText'); - Blockly.utils.dom.removeClass(group, 'blocklyEditableText'); + addClass(group, 'blocklyNonEditableText'); + removeClass(group, 'blocklyEditableText'); group.style.cursor = ''; } }; +/** + * Set whether this field's value can be changed using the editor when the + * source block is editable. + * @param {boolean} enabled True if enabled. + */ +Field.prototype.setEnabled = function(enabled) { + this.enabled_ = enabled; + this.updateEditable(); +}; + +/** + * Check whether this field's value can be changed using the editor when the + * source block is editable. + * @return {boolean} Whether this field is enabled. + */ +Field.prototype.isEnabled = function() { + return this.enabled_; +}; + /** * Check whether this field defines the showEditor_ function. * @return {boolean} Whether this field is clickable. */ -Blockly.Field.prototype.isClickable = function() { - return !!this.sourceBlock_ && this.sourceBlock_.isEditable() && - !!this.showEditor_ && (typeof this.showEditor_ === 'function'); +Field.prototype.isClickable = function() { + return this.enabled_ && !!this.sourceBlock_ && + this.sourceBlock_.isEditable() && !!this.showEditor_ && + (typeof this.showEditor_ === 'function'); }; /** * Check whether this field is currently editable. Some fields are never * EDITABLE (e.g. text labels). Other fields may be EDITABLE but may exist on - * non-editable blocks. - * @return {boolean} Whether this field is editable and on an editable block + * non-editable blocks or be currently disabled. + * @return {boolean} Whether this field is currently enabled, editable and on + * an editable block. */ -Blockly.Field.prototype.isCurrentlyEditable = function() { - return this.EDITABLE && !!this.sourceBlock_ && this.sourceBlock_.isEditable(); +Field.prototype.isCurrentlyEditable = function() { + return this.enabled_ && this.EDITABLE && !!this.sourceBlock_ && + this.sourceBlock_.isEditable(); }; /** @@ -476,15 +516,16 @@ Blockly.Field.prototype.isCurrentlyEditable = function() { * Handles the logic for backwards compatibility and incongruous states. * @return {boolean} Whether this field should be serialized or not. */ -Blockly.Field.prototype.isSerializable = function() { - var isSerializable = false; +Field.prototype.isSerializable = function() { + let isSerializable = false; if (this.name) { if (this.SERIALIZABLE) { isSerializable = true; } else if (this.EDITABLE) { - console.warn('Detected an editable field that was not serializable.' + - ' Please define SERIALIZABLE property as true on all editable custom' + - ' fields. Proceeding with serialization.'); + console.warn( + 'Detected an editable field that was not serializable.' + + ' Please define SERIALIZABLE property as true on all editable custom' + + ' fields. Proceeding with serialization.'); isSerializable = true; } } @@ -495,7 +536,7 @@ Blockly.Field.prototype.isSerializable = function() { * Gets whether this editable field is visible or not. * @return {boolean} True if visible. */ -Blockly.Field.prototype.isVisible = function() { +Field.prototype.isVisible = function() { return this.visible_; }; @@ -505,12 +546,12 @@ Blockly.Field.prototype.isVisible = function() { * @param {boolean} visible True if visible. * @package */ -Blockly.Field.prototype.setVisible = function(visible) { +Field.prototype.setVisible = function(visible) { if (this.visible_ == visible) { return; } this.visible_ = visible; - var root = this.getSvgRoot(); + const root = this.getSvgRoot(); if (root) { root.style.display = visible ? 'block' : 'none'; } @@ -531,7 +572,7 @@ Blockly.Field.prototype.setVisible = function(visible) { * @param {Function} handler The validator function * or null to clear a previous validator. */ -Blockly.Field.prototype.setValidator = function(handler) { +Field.prototype.setValidator = function(handler) { this.validator_ = handler; }; @@ -539,7 +580,7 @@ Blockly.Field.prototype.setValidator = function(handler) { * Gets the validation function for editable fields, or null if not set. * @return {?Function} Validation function, or null. */ -Blockly.Field.prototype.getValidator = function() { +Field.prototype.getValidator = function() { return this.validator_; }; @@ -548,7 +589,7 @@ Blockly.Field.prototype.getValidator = function() { * Used for measuring the size and for positioning. * @return {!SVGGElement} The group element. */ -Blockly.Field.prototype.getSvgRoot = function() { +Field.prototype.getSvgRoot = function() { return /** @type {!SVGGElement} */ (this.fieldGroup_); }; @@ -557,7 +598,7 @@ Blockly.Field.prototype.getSvgRoot = function() { * called by BlockSvg.applyColour(). * @package */ -Blockly.Field.prototype.applyColour = function() { +Field.prototype.applyColour = function() { // Non-abstract sub-classes may wish to implement this. See FieldDropdown. }; @@ -568,7 +609,7 @@ Blockly.Field.prototype.applyColour = function() { * done here, and should be triggered by getSize(). * @protected */ -Blockly.Field.prototype.render_ = function() { +Field.prototype.render_ = function() { if (this.textContent_) { this.textContent_.nodeValue = this.getDisplayText_(); } @@ -581,7 +622,7 @@ Blockly.Field.prototype.render_ = function() { * or undefined if triggered programmatically. * @package */ -Blockly.Field.prototype.showEditor = function(opt_e) { +Field.prototype.showEditor = function(opt_e) { if (this.isClickable()) { this.showEditor_(opt_e); } @@ -592,19 +633,19 @@ Blockly.Field.prototype.showEditor = function(opt_e) { * @param {number=} opt_margin margin to use when positioning the text element. * @protected */ -Blockly.Field.prototype.updateSize_ = function(opt_margin) { - var constants = this.getConstants(); - var xOffset = opt_margin != undefined ? opt_margin : +Field.prototype.updateSize_ = function(opt_margin) { + const constants = this.getConstants(); + const xOffset = opt_margin != undefined ? + opt_margin : (this.borderRect_ ? this.getConstants().FIELD_BORDER_RECT_X_PADDING : 0); - var totalWidth = xOffset * 2; - var totalHeight = constants.FIELD_TEXT_HEIGHT; + let totalWidth = xOffset * 2; + let totalHeight = constants.FIELD_TEXT_HEIGHT; - var contentWidth = 0; + let contentWidth = 0; if (this.textElement_) { - contentWidth = Blockly.utils.dom.getFastTextWidth(this.textElement_, - constants.FIELD_TEXT_FONTSIZE, - constants.FIELD_TEXT_FONTWEIGHT, - constants.FIELD_TEXT_FONTFAMILY); + contentWidth = getFastTextWidth( + this.textElement_, constants.FIELD_TEXT_FONTSIZE, + constants.FIELD_TEXT_FONTWEIGHT, constants.FIELD_TEXT_FONTFAMILY); totalWidth += contentWidth; } if (this.borderRect_) { @@ -625,34 +666,38 @@ Blockly.Field.prototype.updateSize_ = function(opt_margin) { * @param {number} contentWidth The content width. * @protected */ -Blockly.Field.prototype.positionTextElement_ = function(xOffset, contentWidth) { +Field.prototype.positionTextElement_ = function(xOffset, contentWidth) { if (!this.textElement_) { return; } - var constants = this.getConstants(); - var halfHeight = this.size_.height / 2; + const constants = this.getConstants(); + const halfHeight = this.size_.height / 2; - this.textElement_.setAttribute('x', this.sourceBlock_.RTL ? - this.size_.width - contentWidth - xOffset : xOffset); - this.textElement_.setAttribute('y', constants.FIELD_TEXT_BASELINE_CENTER ? - halfHeight : halfHeight - constants.FIELD_TEXT_HEIGHT / 2 + - constants.FIELD_TEXT_BASELINE); + this.textElement_.setAttribute( + 'x', + this.sourceBlock_.RTL ? this.size_.width - contentWidth - xOffset : + xOffset); + this.textElement_.setAttribute( + 'y', + constants.FIELD_TEXT_BASELINE_CENTER ? halfHeight : + halfHeight - + constants.FIELD_TEXT_HEIGHT / 2 + constants.FIELD_TEXT_BASELINE); }; /** * Position a field's border rect after a size change. * @protected */ -Blockly.Field.prototype.positionBorderRect_ = function() { +Field.prototype.positionBorderRect_ = function() { if (!this.borderRect_) { return; } this.borderRect_.setAttribute('width', this.size_.width); this.borderRect_.setAttribute('height', this.size_.height); - this.borderRect_.setAttribute('rx', - this.getConstants().FIELD_BORDER_RECT_RADIUS); - this.borderRect_.setAttribute('ry', - this.getConstants().FIELD_BORDER_RECT_RADIUS); + this.borderRect_.setAttribute( + 'rx', this.getConstants().FIELD_BORDER_RECT_RADIUS); + this.borderRect_.setAttribute( + 'ry', this.getConstants().FIELD_BORDER_RECT_RADIUS); }; @@ -660,11 +705,11 @@ Blockly.Field.prototype.positionBorderRect_ = function() { * Returns the height and width of the field. * * This should *in general* be the only place render_ gets called from. - * @return {!Blockly.utils.Size} Height and width. + * @return {!Size} Height and width. */ -Blockly.Field.prototype.getSize = function() { +Field.prototype.getSize = function() { if (!this.isVisible()) { - return new Blockly.utils.Size(0, 0); + return new Size(0, 0); } if (this.isDirty_) { @@ -673,8 +718,9 @@ Blockly.Field.prototype.getSize = function() { } else if (this.visible_ && this.size_.width == 0) { // If the field is not visible the width will be 0 as well, one of the // problems with the old system. - console.warn('Deprecated use of setting size_.width to 0 to rerender a' + - ' field. Set field.isDirty_ to true instead.'); + console.warn( + 'Deprecated use of setting size_.width to 0 to rerender a' + + ' field. Set field.isDirty_ to true instead.'); this.render_(); } return this.size_; @@ -683,28 +729,29 @@ Blockly.Field.prototype.getSize = function() { /** * Returns the bounding box of the rendered field, accounting for workspace * scaling. - * @return {!Blockly.utils.Rect} An object with top, bottom, left, and right in + * @return {!Rect} An object with top, bottom, left, and right in * pixels relative to the top left corner of the page (window coordinates). * @package */ -Blockly.Field.prototype.getScaledBBox = function() { +Field.prototype.getScaledBBox = function() { + let scaledWidth, scaledHeight, xy; if (!this.borderRect_) { // Browsers are inconsistent in what they return for a bounding box. // - Webkit / Blink: fill-box / object bounding box // - Gecko / Triden / EdgeHTML: stroke-box - var bBox = this.sourceBlock_.getHeightWidth(); - var scale = this.sourceBlock_.workspace.scale; - var xy = this.getAbsoluteXY_(); - var scaledWidth = bBox.width * scale; - var scaledHeight = bBox.height * scale; + const bBox = this.sourceBlock_.getHeightWidth(); + const scale = this.sourceBlock_.workspace.scale; + xy = this.getAbsoluteXY_(); + scaledWidth = bBox.width * scale; + scaledHeight = bBox.height * scale; - if (Blockly.utils.userAgent.GECKO) { + if (userAgent.GECKO) { xy.x += 1.5 * scale; xy.y += 1.5 * scale; scaledWidth += 1 * scale; scaledHeight += 1 * scale; } else { - if (!Blockly.utils.userAgent.EDGE && !Blockly.utils.userAgent.IE) { + if (!userAgent.EDGE && !userAgent.IE) { xy.x -= 0.5 * scale; xy.y -= 0.5 * scale; } @@ -712,17 +759,12 @@ Blockly.Field.prototype.getScaledBBox = function() { scaledHeight += 1 * scale; } } else { - var bBox = this.borderRect_.getBoundingClientRect(); - var xy = Blockly.utils.style.getPageOffset(this.borderRect_); - var scaledWidth = bBox.width; - var scaledHeight = bBox.height; + const bBox = this.borderRect_.getBoundingClientRect(); + xy = getPageOffset(this.borderRect_); + scaledWidth = bBox.width; + scaledHeight = bBox.height; } - return new Blockly.utils.Rect( - xy.y, - xy.y + scaledHeight, - xy.x, - xy.x + scaledWidth - ); + return new Rect(xy.y, xy.y + scaledHeight, xy.x, xy.x + scaledWidth); }; /** @@ -731,18 +773,18 @@ Blockly.Field.prototype.getScaledBBox = function() { * @return {string} Text to display. * @protected */ -Blockly.Field.prototype.getDisplayText_ = function() { - var text = this.getText(); +Field.prototype.getDisplayText_ = function() { + let text = this.getText(); if (!text) { // Prevent the field from disappearing if empty. - return Blockly.Field.NBSP; + return Field.NBSP; } if (text.length > this.maxDisplayLength) { // Truncate displayed string and add an ellipsis ('...'). text = text.substring(0, this.maxDisplayLength - 2) + '\u2026'; } // Replace whitespace with non-breaking spaces so the text doesn't collapse. - text = text.replace(/\s/g, Blockly.Field.NBSP); + text = text.replace(/\s/g, Field.NBSP); if (this.sourceBlock_ && this.sourceBlock_.RTL) { // The SVG is LTR, force text to be RTL. text += '\u200F'; @@ -754,9 +796,9 @@ Blockly.Field.prototype.getDisplayText_ = function() { * Get the text from this field. * @return {string} Current text. */ -Blockly.Field.prototype.getText = function() { +Field.prototype.getText = function() { if (this.getText_) { - var text = this.getText_.call(this); + const text = this.getText_.call(this); if (text !== null) { return String(text); } @@ -771,7 +813,7 @@ Blockly.Field.prototype.getText = function() { * already been recorded. * @package */ -Blockly.Field.prototype.markDirty = function() { +Field.prototype.markDirty = function() { this.isDirty_ = true; this.constants_ = null; }; @@ -783,7 +825,7 @@ Blockly.Field.prototype.markDirty = function() { * already been recorded. * @package */ -Blockly.Field.prototype.forceRerender = function() { +Field.prototype.forceRerender = function() { this.isDirty_ = true; if (this.sourceBlock_ && this.sourceBlock_.rendered) { this.sourceBlock_.render(); @@ -798,15 +840,15 @@ Blockly.Field.prototype.forceRerender = function() { * than this method. * @param {*} newValue New value. */ -Blockly.Field.prototype.setValue = function(newValue) { - var doLogging = false; +Field.prototype.setValue = function(newValue) { + const doLogging = false; if (newValue === null) { doLogging && console.log('null, return'); // Not a valid value to check. return; } - var validatedValue = this.doClassValidation_(newValue); + let validatedValue = this.doClassValidation_(newValue); // Class validators might accidentally forget to return, we'll ignore that. newValue = this.processValidation_(newValue, validatedValue); if (newValue instanceof Error) { @@ -814,7 +856,7 @@ Blockly.Field.prototype.setValue = function(newValue) { return; } - var localValidator = this.getValidator(); + const localValidator = this.getValidator(); if (localValidator) { validatedValue = localValidator.call(this, newValue); // Local validators might accidentally forget to return, we'll ignore that. @@ -824,20 +866,20 @@ Blockly.Field.prototype.setValue = function(newValue) { return; } } - var source = this.sourceBlock_; + const source = this.sourceBlock_; if (source && source.disposed) { doLogging && console.log('source disposed, return'); return; } - var oldValue = this.getValue(); + const oldValue = this.getValue(); if (oldValue === newValue) { doLogging && console.log('same, doValueUpdate_, return'); this.doValueUpdate_(newValue); return; } - if (source && Blockly.Events.isEnabled()) { - Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.BLOCK_CHANGE))( + if (source && Events.isEnabled()) { + Events.fire(new (Events.get(Events.BLOCK_CHANGE))( source, 'field', this.name || null, oldValue, newValue)); } this.doValueUpdate_(newValue); @@ -854,8 +896,7 @@ Blockly.Field.prototype.setValue = function(newValue) { * @return {*} New value, or an Error object. * @private */ -Blockly.Field.prototype.processValidation_ = function(newValue, - validatedValue) { +Field.prototype.processValidation_ = function(newValue, validatedValue) { if (validatedValue === null) { this.doValueInvalid_(newValue); if (this.isDirty_) { @@ -873,7 +914,7 @@ Blockly.Field.prototype.processValidation_ = function(newValue, * Get the current value of the field. * @return {*} Current value. */ -Blockly.Field.prototype.getValue = function() { +Field.prototype.getValue = function() { return this.value_; }; @@ -884,7 +925,7 @@ Blockly.Field.prototype.getValue = function() { * @return {*} The validated value, same as input by default. * @protected */ -Blockly.Field.prototype.doClassValidation_ = function(opt_newValue) { +Field.prototype.doClassValidation_ = function(opt_newValue) { if (opt_newValue === null || opt_newValue === undefined) { return null; } @@ -897,7 +938,7 @@ Blockly.Field.prototype.doClassValidation_ = function(opt_newValue) { * @param {*} newValue The value to be saved. * @protected */ -Blockly.Field.prototype.doValueUpdate_ = function(newValue) { +Field.prototype.doValueUpdate_ = function(newValue) { this.value_ = newValue; this.isDirty_ = true; }; @@ -909,7 +950,7 @@ Blockly.Field.prototype.doValueUpdate_ = function(newValue) { * @param {*} _invalidValue The input value that was determined to be invalid. * @protected */ -Blockly.Field.prototype.doValueInvalid_ = function(_invalidValue) { +Field.prototype.doValueInvalid_ = function(_invalidValue) { // NOP }; @@ -918,11 +959,11 @@ Blockly.Field.prototype.doValueInvalid_ = function(_invalidValue) { * @param {!Event} e Mouse down event. * @protected */ -Blockly.Field.prototype.onMouseDown_ = function(e) { +Field.prototype.onMouseDown_ = function(e) { if (!this.sourceBlock_ || !this.sourceBlock_.workspace) { return; } - var gesture = this.sourceBlock_.workspace.getGesture(e); + const gesture = this.sourceBlock_.workspace.getGesture(e); if (gesture) { gesture.setStartField(this); } @@ -930,16 +971,16 @@ Blockly.Field.prototype.onMouseDown_ = function(e) { /** * Sets the tooltip for this field. - * @param {?Blockly.Tooltip.TipInfo} newTip The + * @param {?Tooltip.TipInfo} newTip The * text for the tooltip, a function that returns the text for the tooltip, a * parent object whose tooltip will be used, or null to display the tooltip * of the parent block. To not display a tooltip pass the empty string. */ -Blockly.Field.prototype.setTooltip = function(newTip) { +Field.prototype.setTooltip = function(newTip) { if (!newTip && newTip !== '') { // If null or undefined. newTip = this.sourceBlock_; } - var clickTarget = this.getClickTarget_(); + const clickTarget = this.getClickTarget_(); if (clickTarget) { clickTarget.tooltip = newTip; } else { @@ -952,13 +993,13 @@ Blockly.Field.prototype.setTooltip = function(newTip) { * Returns the tooltip text for this field. * @return {string} The tooltip text for this field. */ -Blockly.Field.prototype.getTooltip = function() { - var clickTarget = this.getClickTarget_(); +Field.prototype.getTooltip = function() { + const clickTarget = this.getClickTarget_(); if (clickTarget) { - return Blockly.Tooltip.getTooltipOfObject(clickTarget); + return Tooltip.getTooltipOfObject(clickTarget); } // Field has not been initialized yet. Return stashed this.tooltip_ value. - return Blockly.Tooltip.getTooltipOfObject({tooltip: this.tooltip_}); + return Tooltip.getTooltipOfObject({tooltip: this.tooltip_}); }; /** @@ -968,18 +1009,18 @@ Blockly.Field.prototype.getTooltip = function() { * @return {!Element} Element to bind click handler to. * @protected */ -Blockly.Field.prototype.getClickTarget_ = function() { +Field.prototype.getClickTarget_ = function() { return this.clickTarget_ || this.getSvgRoot(); }; /** * Return the absolute coordinates of the top-left corner of this field. * The origin (0,0) is the top-left corner of the page body. - * @return {!Blockly.utils.Coordinate} Object with .x and .y properties. + * @return {!Coordinate} Object with .x and .y properties. * @protected */ -Blockly.Field.prototype.getAbsoluteXY_ = function() { - return Blockly.utils.style.getPageOffset( +Field.prototype.getAbsoluteXY_ = function() { + return getPageOffset( /** @type {!SVGRectElement} */ (this.getClickTarget_())); }; @@ -990,25 +1031,25 @@ Blockly.Field.prototype.getAbsoluteXY_ = function() { * @return {boolean} True if this field has any variable references. * @package */ -Blockly.Field.prototype.referencesVariables = function() { +Field.prototype.referencesVariables = function() { return false; }; /** * Search through the list of inputs and their fields in order to find the * parent input of a field. - * @return {Blockly.Input} The input that the field belongs to. + * @return {Input} The input that the field belongs to. * @package */ -Blockly.Field.prototype.getParentInput = function() { - var parentInput = null; - var block = this.sourceBlock_; - var inputs = block.inputList; +Field.prototype.getParentInput = function() { + let parentInput = null; + const block = this.sourceBlock_; + const inputs = block.inputList; - for (var idx = 0; idx < block.inputList.length; idx++) { - var input = inputs[idx]; - var fieldRows = input.fieldRow; - for (var j = 0; j < fieldRows.length; j++) { + for (let idx = 0; idx < block.inputList.length; idx++) { + const input = inputs[idx]; + const fieldRows = input.fieldRow; + for (let j = 0; j < fieldRows.length; j++) { if (fieldRows[j] === this) { parentInput = input; break; @@ -1022,7 +1063,7 @@ Blockly.Field.prototype.getParentInput = function() { * Returns whether or not we should flip the field in RTL. * @return {boolean} True if we should flip in RTL. */ -Blockly.Field.prototype.getFlipRtl = function() { +Field.prototype.getFlipRtl = function() { return false; }; @@ -1030,17 +1071,18 @@ Blockly.Field.prototype.getFlipRtl = function() { * Returns whether or not the field is tab navigable. * @return {boolean} True if the field is tab navigable. */ -Blockly.Field.prototype.isTabNavigable = function() { +Field.prototype.isTabNavigable = function() { return false; }; /** * Handles the given keyboard shortcut. - * @param {!Blockly.ShortcutRegistry.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. * @public */ -Blockly.Field.prototype.onShortcut = function(_shortcut) { +Field.prototype.onShortcut = function(_shortcut) { return false; }; @@ -1050,7 +1092,7 @@ Blockly.Field.prototype.onShortcut = function(_shortcut) { * field group. * @package */ -Blockly.Field.prototype.setCursorSvg = function(cursorSvg) { +Field.prototype.setCursorSvg = function(cursorSvg) { if (!cursorSvg) { this.cursorSvg_ = null; return; @@ -1066,7 +1108,7 @@ Blockly.Field.prototype.setCursorSvg = function(cursorSvg) { * field group. * @package */ -Blockly.Field.prototype.setMarkerSvg = function(markerSvg) { +Field.prototype.setMarkerSvg = function(markerSvg) { if (!markerSvg) { this.markerSvg_ = null; return; @@ -1080,14 +1122,16 @@ Blockly.Field.prototype.setMarkerSvg = function(markerSvg) { * Redraw any attached marker or cursor svgs if needed. * @protected */ -Blockly.Field.prototype.updateMarkers_ = function() { - var workspace = - /** @type {!Blockly.WorkspaceSvg} */ (this.sourceBlock_.workspace); +Field.prototype.updateMarkers_ = function() { + const workspace = + /** @type {!WorkspaceSvg} */ (this.sourceBlock_.workspace); if (workspace.keyboardAccessibilityMode && this.cursorSvg_) { workspace.getCursor().draw(); } if (workspace.keyboardAccessibilityMode && this.markerSvg_) { // TODO(#4592): Update all markers on the field. - workspace.getMarker(Blockly.MarkerManager.LOCAL_MARKER).draw(); + workspace.getMarker(MarkerManager.LOCAL_MARKER).draw(); } }; + +exports = Field; diff --git a/core/field_checkbox.js b/core/field_checkbox.js index 207b29f7f..d2ce60eaa 100644 --- a/core/field_checkbox.js +++ b/core/field_checkbox.js @@ -10,14 +10,15 @@ */ 'use strict'; -goog.provide('Blockly.FieldCheckbox'); +goog.module('Blockly.FieldCheckbox'); +goog.module.declareLegacyNamespace(); +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'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockChange'); -goog.require('Blockly.Field'); -goog.require('Blockly.fieldRegistry'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.object'); /** @@ -29,12 +30,13 @@ goog.require('Blockly.utils.object'); * returns a validated value ('TRUE' or 'FALSE'), 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/checkbox#creation} + * See the [field creation documentation]{@link + * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/checkbox#creation} * for a list of properties this parameter supports. - * @extends {Blockly.Field} + * @extends {Field} * @constructor */ -Blockly.FieldCheckbox = function(opt_value, opt_validator, opt_config) { +const FieldCheckbox = function(opt_value, opt_validator, opt_config) { /** * Character for the check mark. Used to apply a different check mark * character to individual fields. @@ -43,26 +45,26 @@ Blockly.FieldCheckbox = function(opt_value, opt_validator, opt_config) { */ this.checkChar_ = null; - Blockly.FieldCheckbox.superClass_.constructor.call( + FieldCheckbox.superClass_.constructor.call( this, opt_value, opt_validator, opt_config); }; -Blockly.utils.object.inherits(Blockly.FieldCheckbox, Blockly.Field); +inherits(FieldCheckbox, Field); /** * The default value for this field. * @type {*} * @protected */ -Blockly.FieldCheckbox.prototype.DEFAULT_VALUE = false; +FieldCheckbox.prototype.DEFAULT_VALUE = false; /** * Construct a FieldCheckbox from a JSON arg object. * @param {!Object} options A JSON object with options (checked). - * @return {!Blockly.FieldCheckbox} The new field instance. + * @return {!FieldCheckbox} The new field instance. * @package * @nocollapse */ -Blockly.FieldCheckbox.fromJson = function(options) { +FieldCheckbox.fromJson = function(options) { // `this` might be a subclass of FieldCheckbox if that class doesn't override // the static fromJson method. return new this(options['checked'], undefined, options); @@ -73,19 +75,19 @@ Blockly.FieldCheckbox.fromJson = function(options) { * @type {string} * @const */ -Blockly.FieldCheckbox.CHECK_CHAR = '\u2713'; +FieldCheckbox.CHECK_CHAR = '\u2713'; /** * Serializable fields are saved by the XML renderer, non-serializable fields * are not. Editable fields should also be serializable. * @type {boolean} */ -Blockly.FieldCheckbox.prototype.SERIALIZABLE = true; +FieldCheckbox.prototype.SERIALIZABLE = true; /** * Mouse cursor style when over the hotspot that initiates editability. */ -Blockly.FieldCheckbox.prototype.CURSOR = 'default'; +FieldCheckbox.prototype.CURSOR = 'default'; /** * Configure the field based on the given map of options. @@ -93,8 +95,8 @@ Blockly.FieldCheckbox.prototype.CURSOR = 'default'; * @protected * @override */ -Blockly.FieldCheckbox.prototype.configure_ = function(config) { - Blockly.FieldCheckbox.superClass_.configure_.call(this, config); +FieldCheckbox.prototype.configure_ = function(config) { + FieldCheckbox.superClass_.configure_.call(this, config); if (config['checkCharacter']) { this.checkChar_ = config['checkCharacter']; } @@ -104,10 +106,10 @@ Blockly.FieldCheckbox.prototype.configure_ = function(config) { * Create the block UI for this checkbox. * @package */ -Blockly.FieldCheckbox.prototype.initView = function() { - Blockly.FieldCheckbox.superClass_.initView.call(this); +FieldCheckbox.prototype.initView = function() { + FieldCheckbox.superClass_.initView.call(this); - Blockly.utils.dom.addClass( + dom.addClass( /** @type {!SVGTextElement} **/ (this.textElement_), 'blocklyCheckbox'); this.textElement_.style.display = this.value_ ? 'block' : 'none'; }; @@ -115,7 +117,7 @@ Blockly.FieldCheckbox.prototype.initView = function() { /** * @override */ -Blockly.FieldCheckbox.prototype.render_ = function() { +FieldCheckbox.prototype.render_ = function() { if (this.textContent_) { this.textContent_.nodeValue = this.getDisplayText_(); } @@ -125,8 +127,8 @@ Blockly.FieldCheckbox.prototype.render_ = function() { /** * @override */ -Blockly.FieldCheckbox.prototype.getDisplayText_ = function() { - return this.checkChar_ || Blockly.FieldCheckbox.CHECK_CHAR; +FieldCheckbox.prototype.getDisplayText_ = function() { + return this.checkChar_ || FieldCheckbox.CHECK_CHAR; }; /** @@ -134,7 +136,7 @@ Blockly.FieldCheckbox.prototype.getDisplayText_ = function() { * @param {?string} character The character to use for the check mark, or * null to use the default. */ -Blockly.FieldCheckbox.prototype.setCheckCharacter = function(character) { +FieldCheckbox.prototype.setCheckCharacter = function(character) { this.checkChar_ = character; this.forceRerender(); }; @@ -143,7 +145,7 @@ Blockly.FieldCheckbox.prototype.setCheckCharacter = function(character) { * Toggle the state of the checkbox on click. * @protected */ -Blockly.FieldCheckbox.prototype.showEditor_ = function() { +FieldCheckbox.prototype.showEditor_ = function() { this.setValue(!this.value_); }; @@ -153,7 +155,7 @@ Blockly.FieldCheckbox.prototype.showEditor_ = function() { * @return {?string} A valid value ('TRUE' or 'FALSE), or null if invalid. * @protected */ -Blockly.FieldCheckbox.prototype.doClassValidation_ = function(opt_newValue) { +FieldCheckbox.prototype.doClassValidation_ = function(opt_newValue) { if (opt_newValue === true || opt_newValue === 'TRUE') { return 'TRUE'; } @@ -169,7 +171,7 @@ Blockly.FieldCheckbox.prototype.doClassValidation_ = function(opt_newValue) { * that this is a either 'TRUE' or 'FALSE'. * @protected */ -Blockly.FieldCheckbox.prototype.doValueUpdate_ = function(newValue) { +FieldCheckbox.prototype.doValueUpdate_ = function(newValue) { this.value_ = this.convertValueToBool_(newValue); // Update visual. if (this.textElement_) { @@ -181,7 +183,7 @@ Blockly.FieldCheckbox.prototype.doValueUpdate_ = function(newValue) { * Get the value of this field, either 'TRUE' or 'FALSE'. * @return {string} The value of this field. */ -Blockly.FieldCheckbox.prototype.getValue = function() { +FieldCheckbox.prototype.getValue = function() { return this.value_ ? 'TRUE' : 'FALSE'; }; @@ -189,7 +191,7 @@ Blockly.FieldCheckbox.prototype.getValue = function() { * Get the boolean value of this field. * @return {boolean} The boolean value of this field. */ -Blockly.FieldCheckbox.prototype.getValueBoolean = function() { +FieldCheckbox.prototype.getValueBoolean = function() { return /** @type {boolean} */ (this.value_); }; @@ -198,7 +200,7 @@ Blockly.FieldCheckbox.prototype.getValueBoolean = function() { * @return {string} Text representing the value of this field * ('true' or 'false'). */ -Blockly.FieldCheckbox.prototype.getText = function() { +FieldCheckbox.prototype.getText = function() { return String(this.convertValueToBool_(this.value_)); }; @@ -211,7 +213,7 @@ Blockly.FieldCheckbox.prototype.getText = function() { * @return {boolean} The converted value. * @private */ -Blockly.FieldCheckbox.prototype.convertValueToBool_ = function(value) { +FieldCheckbox.prototype.convertValueToBool_ = function(value) { if (typeof value == 'string') { return value == 'TRUE'; } else { @@ -219,4 +221,6 @@ Blockly.FieldCheckbox.prototype.convertValueToBool_ = function(value) { } }; -Blockly.fieldRegistry.register('field_checkbox', Blockly.FieldCheckbox); +fieldRegistry.register('field_checkbox', FieldCheckbox); + +exports = FieldCheckbox; diff --git a/core/field_colour.js b/core/field_colour.js index 17d593f0e..a3dc0bf72 100644 --- a/core/field_colour.js +++ b/core/field_colour.js @@ -10,22 +10,24 @@ */ 'use strict'; -goog.provide('Blockly.FieldColour'); +goog.module('Blockly.FieldColour'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.browserEvents'); -goog.require('Blockly.Css'); -goog.require('Blockly.DropDownDiv'); +const Css = goog.require('Blockly.Css'); +const DropDownDiv = goog.require('Blockly.DropDownDiv'); +const Field = goog.require('Blockly.Field'); +const IdGenerator = goog.require('Blockly.utils.IdGenerator'); +const KeyCodes = goog.require('Blockly.utils.KeyCodes'); +const Size = goog.require('Blockly.utils.Size'); +const aria = goog.require('Blockly.utils.aria'); +const colour = goog.require('Blockly.utils.colour'); +const fieldRegistry = goog.require('Blockly.fieldRegistry'); +const {addClass, removeClass} = goog.require('Blockly.utils.dom'); +/* eslint-disable-next-line no-unused-vars */ +const {conditionalBind, unbind, Data} = goog.require('Blockly.browserEvents'); +const {inherits} = goog.require('Blockly.utils.object'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockChange'); -goog.require('Blockly.Field'); -goog.require('Blockly.fieldRegistry'); -goog.require('Blockly.utils.aria'); -goog.require('Blockly.utils.colour'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.IdGenerator'); -goog.require('Blockly.utils.KeyCodes'); -goog.require('Blockly.utils.object'); -goog.require('Blockly.utils.Size'); /** @@ -34,15 +36,17 @@ goog.require('Blockly.utils.Size'); * '#rrggbb' format. Defaults to the first value in the default colour array. * @param {Function=} opt_validator A function that is called to validate * changes to the field's value. Takes in a colour string & returns a - * validated colour string ('#rrggbb' format), or null to abort the change. + * validated colour string ('#rrggbb' format), or null to abort the + * change.Blockly. * @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/colour} + * See the [field creation documentation]{@link + * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/colour} * for a list of properties this parameter supports. - * @extends {Blockly.Field} + * @extends {Field} * @constructor */ -Blockly.FieldColour = function(opt_value, opt_validator, opt_config) { - Blockly.FieldColour.superClass_.constructor.call( +const FieldColour = function(opt_value, opt_validator, opt_config) { + FieldColour.superClass_.constructor.call( this, opt_value, opt_validator, opt_config); /** @@ -61,49 +65,49 @@ Blockly.FieldColour = function(opt_value, opt_validator, opt_config) { /** * Mouse click event data. - * @type {?Blockly.browserEvents.Data} + * @type {?Data} * @private */ this.onClickWrapper_ = null; /** * Mouse move event data. - * @type {?Blockly.browserEvents.Data} + * @type {?Data} * @private */ this.onMouseMoveWrapper_ = null; /** * Mouse enter event data. - * @type {?Blockly.browserEvents.Data} + * @type {?Data} * @private */ this.onMouseEnterWrapper_ = null; /** * Mouse leave event data. - * @type {?Blockly.browserEvents.Data} + * @type {?Data} * @private */ this.onMouseLeaveWrapper_ = null; /** * Key down event data. - * @type {?Blockly.browserEvents.Data} + * @type {?Data} * @private */ this.onKeyDownWrapper_ = null; }; -Blockly.utils.object.inherits(Blockly.FieldColour, Blockly.Field); +inherits(FieldColour, Field); /** * Construct a FieldColour from a JSON arg object. * @param {!Object} options A JSON object with options (colour). - * @return {!Blockly.FieldColour} The new field instance. + * @return {!FieldColour} The new field instance. * @package * @nocollapse */ -Blockly.FieldColour.fromJson = function(options) { +FieldColour.fromJson = function(options) { // `this` might be a subclass of FieldColour if that class doesn't override // the static fromJson method. return new this(options['colour'], undefined, options); @@ -114,12 +118,12 @@ Blockly.FieldColour.fromJson = function(options) { * are not. Editable fields should also be serializable. * @type {boolean} */ -Blockly.FieldColour.prototype.SERIALIZABLE = true; +FieldColour.prototype.SERIALIZABLE = true; /** * Mouse cursor style when over the hotspot that initiates the editor. */ -Blockly.FieldColour.prototype.CURSOR = 'default'; +FieldColour.prototype.CURSOR = 'default'; /** * Used to tell if the field needs to be rendered the next time the block is @@ -128,21 +132,21 @@ Blockly.FieldColour.prototype.CURSOR = 'default'; * @type {boolean} * @protected */ -Blockly.FieldColour.prototype.isDirty_ = false; +FieldColour.prototype.isDirty_ = false; /** * Array of colours used by this field. If null, use the global list. * @type {Array} * @private */ -Blockly.FieldColour.prototype.colours_ = null; +FieldColour.prototype.colours_ = null; /** * Array of colour tooltips used by this field. If null, use the global list. * @type {Array} * @private */ -Blockly.FieldColour.prototype.titles_ = null; +FieldColour.prototype.titles_ = null; /** * Number of colour columns used by this field. If 0, use the global setting. @@ -150,7 +154,7 @@ Blockly.FieldColour.prototype.titles_ = null; * @type {number} * @private */ -Blockly.FieldColour.prototype.columns_ = 0; +FieldColour.prototype.columns_ = 0; /** * Configure the field based on the given map of options. @@ -158,8 +162,8 @@ Blockly.FieldColour.prototype.columns_ = 0; * @protected * @override */ -Blockly.FieldColour.prototype.configure_ = function(config) { - Blockly.FieldColour.superClass_.configure_.call(this, config); +FieldColour.prototype.configure_ = function(config) { + FieldColour.superClass_.configure_.call(this, config); if (config['colourOptions']) { this.colours_ = config['colourOptions']; this.titles_ = config['colourTitles']; @@ -173,8 +177,8 @@ Blockly.FieldColour.prototype.configure_ = function(config) { * Create the block UI for this colour field. * @package */ -Blockly.FieldColour.prototype.initView = function() { - this.size_ = new Blockly.utils.Size( +FieldColour.prototype.initView = function() { + this.size_ = new Size( this.getConstants().FIELD_COLOUR_DEFAULT_WIDTH, this.getConstants().FIELD_COLOUR_DEFAULT_HEIGHT); if (!this.getConstants().FIELD_COLOUR_FULL_BLOCK) { @@ -188,7 +192,7 @@ Blockly.FieldColour.prototype.initView = function() { /** * @override */ -Blockly.FieldColour.prototype.applyColour = function() { +FieldColour.prototype.applyColour = function() { if (!this.getConstants().FIELD_COLOUR_FULL_BLOCK) { if (this.borderRect_) { this.borderRect_.style.fill = /** @type {string} */ (this.getValue()); @@ -205,11 +209,11 @@ Blockly.FieldColour.prototype.applyColour = function() { * @return {?string} A valid colour, or null if invalid. * @protected */ -Blockly.FieldColour.prototype.doClassValidation_ = function(opt_newValue) { +FieldColour.prototype.doClassValidation_ = function(opt_newValue) { if (typeof opt_newValue != 'string') { return null; } - return Blockly.utils.colour.parse(opt_newValue); + return colour.parse(opt_newValue); }; /** @@ -218,7 +222,7 @@ Blockly.FieldColour.prototype.doClassValidation_ = function(opt_newValue) { * that this is a colour in '#rrggbb' format. * @protected */ -Blockly.FieldColour.prototype.doValueUpdate_ = function(newValue) { +FieldColour.prototype.doValueUpdate_ = function(newValue) { this.value_ = newValue; if (this.borderRect_) { this.borderRect_.style.fill = /** @type {string} */ (newValue); @@ -232,8 +236,8 @@ Blockly.FieldColour.prototype.doValueUpdate_ = function(newValue) { * Get the text for this field. Used when the block is collapsed. * @return {string} Text representing the value of this field. */ -Blockly.FieldColour.prototype.getText = function() { - var colour = /** @type {string} */ (this.value_); +FieldColour.prototype.getText = function() { + let colour = /** @type {string} */ (this.value_); // Try to use #rgb format if possible, rather than #rrggbb. if (/^#(.)\1(.)\2(.)\3$/.test(colour)) { colour = '#' + colour[1] + colour[3] + colour[5]; @@ -247,7 +251,7 @@ Blockly.FieldColour.prototype.getText = function() { * All colour pickers use this unless overridden with setColours. * @type {!Array} */ -Blockly.FieldColour.COLOURS = [ +FieldColour.COLOURS = [ // grays '#ffffff', '#cccccc', '#c0c0c0', '#999999', '#666666', '#333333', '#000000', // reds @@ -275,7 +279,7 @@ Blockly.FieldColour.COLOURS = [ * @type {*} * @protected */ -Blockly.FieldColour.prototype.DEFAULT_VALUE = Blockly.FieldColour.COLOURS[0]; +FieldColour.prototype.DEFAULT_VALUE = FieldColour.COLOURS[0]; /** * An array of tooltip strings for the palette. If not the same length as @@ -283,23 +287,23 @@ Blockly.FieldColour.prototype.DEFAULT_VALUE = Blockly.FieldColour.COLOURS[0]; * All colour pickers use this unless overridden with setColours. * @type {!Array} */ -Blockly.FieldColour.TITLES = []; +FieldColour.TITLES = []; /** * Number of columns in the palette. * All colour pickers use this unless overridden with setColumns. */ -Blockly.FieldColour.COLUMNS = 7; +FieldColour.COLUMNS = 7; /** * Set a custom colour grid for this field. * @param {Array} colours Array of colours for this block, - * or null to use default (Blockly.FieldColour.COLOURS). + * or null to use default (FieldColour.COLOURS). * @param {Array=} opt_titles Optional array of colour tooltips, - * or null to use default (Blockly.FieldColour.TITLES). - * @return {!Blockly.FieldColour} Returns itself (for method chaining). + * or null to use default (FieldColour.TITLES). + * @return {!FieldColour} Returns itself (for method chaining). */ -Blockly.FieldColour.prototype.setColours = function(colours, opt_titles) { +FieldColour.prototype.setColours = function(colours, opt_titles) { this.colours_ = colours; if (opt_titles) { this.titles_ = opt_titles; @@ -310,10 +314,10 @@ Blockly.FieldColour.prototype.setColours = function(colours, opt_titles) { /** * Set a custom grid size for this field. * @param {number} columns Number of columns for this block, - * or 0 to use default (Blockly.FieldColour.COLUMNS). - * @return {!Blockly.FieldColour} Returns itself (for method chaining). + * or 0 to use default (FieldColour.COLUMNS). + * @return {!FieldColour} Returns itself (for method chaining). */ -Blockly.FieldColour.prototype.setColumns = function(columns) { +FieldColour.prototype.setColumns = function(columns) { this.columns_ = columns; return this; }; @@ -322,15 +326,14 @@ Blockly.FieldColour.prototype.setColumns = function(columns) { * Create and show the colour field's editor. * @protected */ -Blockly.FieldColour.prototype.showEditor_ = function() { +FieldColour.prototype.showEditor_ = function() { this.dropdownCreate_(); - Blockly.DropDownDiv.getContentDiv().appendChild(this.picker_); + DropDownDiv.getContentDiv().appendChild(this.picker_); - Blockly.DropDownDiv.showPositionedByField( - this, this.dropdownDispose_.bind(this)); + DropDownDiv.showPositionedByField(this, this.dropdownDispose_.bind(this)); // Focus so we can start receiving keyboard events. - this.picker_.focus({preventScroll:true}); + this.picker_.focus({preventScroll: true}); }; /** @@ -338,12 +341,12 @@ Blockly.FieldColour.prototype.showEditor_ = function() { * @param {!MouseEvent} e Mouse event. * @private */ -Blockly.FieldColour.prototype.onClick_ = function(e) { - var cell = /** @type {!Element} */ (e.target); - var colour = cell && cell.label; +FieldColour.prototype.onClick_ = function(e) { + const cell = /** @type {!Element} */ (e.target); + const colour = cell && cell.label; if (colour !== null) { this.setValue(colour); - Blockly.DropDownDiv.hideIfOwner(this); + DropDownDiv.hideIfOwner(this); } }; @@ -353,30 +356,30 @@ Blockly.FieldColour.prototype.onClick_ = function(e) { * @param {!KeyboardEvent} e Keyboard event. * @private */ -Blockly.FieldColour.prototype.onKeyDown_ = function(e) { - var handled = false; - if (e.keyCode === Blockly.utils.KeyCodes.UP) { +FieldColour.prototype.onKeyDown_ = function(e) { + let handled = false; + if (e.keyCode === KeyCodes.UP) { this.moveHighlightBy_(0, -1); handled = true; - } else if (e.keyCode === Blockly.utils.KeyCodes.DOWN) { + } else if (e.keyCode === KeyCodes.DOWN) { this.moveHighlightBy_(0, 1); handled = true; - } else if (e.keyCode === Blockly.utils.KeyCodes.LEFT) { + } else if (e.keyCode === KeyCodes.LEFT) { this.moveHighlightBy_(-1, 0); handled = true; - } else if (e.keyCode === Blockly.utils.KeyCodes.RIGHT) { + } else if (e.keyCode === KeyCodes.RIGHT) { this.moveHighlightBy_(1, 0); handled = true; - } else if (e.keyCode === Blockly.utils.KeyCodes.ENTER) { + } else if (e.keyCode === KeyCodes.ENTER) { // Select the highlighted colour. - var highlighted = this.getHighlighted_(); + const highlighted = this.getHighlighted_(); if (highlighted) { - var colour = highlighted && highlighted.label; + const colour = highlighted && highlighted.label; if (colour !== null) { this.setValue(colour); } } - Blockly.DropDownDiv.hideWithoutAnimation(); + DropDownDiv.hideWithoutAnimation(); handled = true; } if (handled) { @@ -390,13 +393,13 @@ Blockly.FieldColour.prototype.onKeyDown_ = function(e) { * @param {number} dy Change of y * @private */ -Blockly.FieldColour.prototype.moveHighlightBy_ = function(dx, dy) { - var colours = this.colours_ || Blockly.FieldColour.COLOURS; - var columns = this.columns_ || Blockly.FieldColour.COLUMNS; +FieldColour.prototype.moveHighlightBy_ = function(dx, dy) { + const colours = this.colours_ || FieldColour.COLOURS; + const columns = this.columns_ || FieldColour.COLUMNS; // Get the current x and y coordinates - var x = this.highlightedIndex_ % columns; - var y = Math.floor(this.highlightedIndex_ / columns); + let x = this.highlightedIndex_ % columns; + let y = Math.floor(this.highlightedIndex_ / columns); // Add the offset x += dx; @@ -414,8 +417,7 @@ Blockly.FieldColour.prototype.moveHighlightBy_ = function(dx, dy) { } else if (dx > 0) { // Move right one grid cell, even in RTL. // Loop to the start of the next row, if there's room. - if (x > columns - 1 && - y < Math.floor(colours.length / columns) - 1) { + if (x > columns - 1 && y < Math.floor(colours.length / columns) - 1) { x = 0; y++; } else if (x > columns - 1) { @@ -434,8 +436,9 @@ Blockly.FieldColour.prototype.moveHighlightBy_ = function(dx, dy) { } // Move the highlight to the new coordinates. - var cell = /** @type {!Element} */ (this.picker_.childNodes[y].childNodes[x]); - var index = (y * columns) + x; + const cell = + /** @type {!Element} */ (this.picker_.childNodes[y].childNodes[x]); + const index = (y * columns) + x; this.setHighlightedCell_(cell, index); }; @@ -444,9 +447,9 @@ Blockly.FieldColour.prototype.moveHighlightBy_ = function(dx, dy) { * @param {!MouseEvent} e Mouse event. * @private */ -Blockly.FieldColour.prototype.onMouseMove_ = function(e) { - var cell = /** @type {!Element} */ (e.target); - var index = cell && Number(cell.getAttribute('data-index')); +FieldColour.prototype.onMouseMove_ = function(e) { + const cell = /** @type {!Element} */ (e.target); + const index = cell && Number(cell.getAttribute('data-index')); if (index !== null && index !== this.highlightedIndex_) { this.setHighlightedCell_(cell, index); } @@ -456,8 +459,8 @@ Blockly.FieldColour.prototype.onMouseMove_ = function(e) { * Handle a mouse enter event. Focus the picker. * @private */ -Blockly.FieldColour.prototype.onMouseEnter_ = function() { - this.picker_.focus({preventScroll:true}); +FieldColour.prototype.onMouseEnter_ = function() { + this.picker_.focus({preventScroll: true}); }; /** @@ -465,11 +468,11 @@ Blockly.FieldColour.prototype.onMouseEnter_ = function() { * the currently highlighted colour. * @private */ -Blockly.FieldColour.prototype.onMouseLeave_ = function() { +FieldColour.prototype.onMouseLeave_ = function() { this.picker_.blur(); - var highlighted = this.getHighlighted_(); + const highlighted = this.getHighlighted_(); if (highlighted) { - Blockly.utils.dom.removeClass(highlighted, 'blocklyColourHighlighted'); + removeClass(highlighted, 'blocklyColourHighlighted'); } }; @@ -478,15 +481,15 @@ Blockly.FieldColour.prototype.onMouseLeave_ = function() { * @return {?HTMLElement} Highlighted item (null if none). * @private */ -Blockly.FieldColour.prototype.getHighlighted_ = function() { - var columns = this.columns_ || Blockly.FieldColour.COLUMNS; - var x = this.highlightedIndex_ % columns; - var y = Math.floor(this.highlightedIndex_ / columns); - var row = this.picker_.childNodes[y]; +FieldColour.prototype.getHighlighted_ = function() { + const columns = this.columns_ || FieldColour.COLUMNS; + const x = this.highlightedIndex_ % columns; + const y = Math.floor(this.highlightedIndex_ / columns); + const row = this.picker_.childNodes[y]; if (!row) { return null; } - var col = /** @type {HTMLElement} */ (row.childNodes[x]); + const col = /** @type {HTMLElement} */ (row.childNodes[x]); return col; }; @@ -496,60 +499,58 @@ Blockly.FieldColour.prototype.getHighlighted_ = function() { * @param {number} index the index of the new cell * @private */ -Blockly.FieldColour.prototype.setHighlightedCell_ = function(cell, index) { +FieldColour.prototype.setHighlightedCell_ = function(cell, index) { // Unhighlight the current item. - var highlighted = this.getHighlighted_(); + const highlighted = this.getHighlighted_(); if (highlighted) { - Blockly.utils.dom.removeClass(highlighted, 'blocklyColourHighlighted'); + removeClass(highlighted, 'blocklyColourHighlighted'); } // Highlight new item. - Blockly.utils.dom.addClass(cell, 'blocklyColourHighlighted'); + addClass(cell, 'blocklyColourHighlighted'); // Set new highlighted index. this.highlightedIndex_ = index; // Update accessibility roles. - Blockly.utils.aria.setState(/** @type {!Element} */ (this.picker_), - Blockly.utils.aria.State.ACTIVEDESCENDANT, cell.getAttribute('id')); + aria.setState( + /** @type {!Element} */ (this.picker_), aria.State.ACTIVEDESCENDANT, + cell.getAttribute('id')); }; /** * Create a colour picker dropdown editor. * @private */ -Blockly.FieldColour.prototype.dropdownCreate_ = function() { - var columns = this.columns_ || Blockly.FieldColour.COLUMNS; - var colours = this.colours_ || Blockly.FieldColour.COLOURS; - var titles = this.titles_ || Blockly.FieldColour.TITLES; - var selectedColour = this.getValue(); +FieldColour.prototype.dropdownCreate_ = function() { + const columns = this.columns_ || FieldColour.COLUMNS; + const colours = this.colours_ || FieldColour.COLOURS; + const titles = this.titles_ || FieldColour.TITLES; + const selectedColour = this.getValue(); // Create the palette. - var table = document.createElement('table'); + const table = document.createElement('table'); table.className = 'blocklyColourTable'; table.tabIndex = 0; table.dir = 'ltr'; - Blockly.utils.aria.setRole(table, Blockly.utils.aria.Role.GRID); - Blockly.utils.aria.setState(table, Blockly.utils.aria.State.EXPANDED, true); - Blockly.utils.aria.setState(table, Blockly.utils.aria.State.ROWCOUNT, - Math.floor(colours.length / columns)); - Blockly.utils.aria.setState(table, Blockly.utils.aria.State.COLCOUNT, - columns); - var row; - for (var i = 0; i < colours.length; i++) { + aria.setRole(table, aria.Role.GRID); + aria.setState(table, aria.State.EXPANDED, true); + aria.setState( + table, aria.State.ROWCOUNT, Math.floor(colours.length / columns)); + aria.setState(table, aria.State.COLCOUNT, columns); + let row; + for (let i = 0; i < colours.length; i++) { if (i % columns == 0) { row = document.createElement('tr'); - Blockly.utils.aria.setRole(row, Blockly.utils.aria.Role.ROW); + aria.setRole(row, aria.Role.ROW); table.appendChild(row); } - var cell = document.createElement('td'); + const cell = document.createElement('td'); row.appendChild(cell); cell.label = colours[i]; // This becomes the value, if clicked. cell.title = titles[i] || colours[i]; - cell.id = Blockly.utils.IdGenerator.getNextUniqueId(); + cell.id = IdGenerator.getNextUniqueId(); cell.setAttribute('data-index', i); - Blockly.utils.aria.setRole(cell, Blockly.utils.aria.Role.GRIDCELL); - Blockly.utils.aria.setState(cell, - Blockly.utils.aria.State.LABEL, colours[i]); - Blockly.utils.aria.setState(cell, - Blockly.utils.aria.State.SELECTED, colours[i] == selectedColour); + aria.setRole(cell, aria.Role.GRIDCELL); + aria.setState(cell, aria.State.LABEL, colours[i]); + aria.setState(cell, aria.State.SELECTED, colours[i] == selectedColour); cell.style.backgroundColor = colours[i]; if (colours[i] == selectedColour) { cell.className = 'blocklyColourSelected'; @@ -558,16 +559,16 @@ Blockly.FieldColour.prototype.dropdownCreate_ = function() { } // Configure event handler on the table to listen for any event in a cell. - this.onClickWrapper_ = Blockly.browserEvents.conditionalBind( - table, 'click', this, this.onClick_, true); - this.onMouseMoveWrapper_ = Blockly.browserEvents.conditionalBind( - table, 'mousemove', this, this.onMouseMove_, true); - this.onMouseEnterWrapper_ = Blockly.browserEvents.conditionalBind( - table, 'mouseenter', this, this.onMouseEnter_, true); - this.onMouseLeaveWrapper_ = Blockly.browserEvents.conditionalBind( - table, 'mouseleave', this, this.onMouseLeave_, true); - this.onKeyDownWrapper_ = Blockly.browserEvents.conditionalBind( - table, 'keydown', this, this.onKeyDown_); + this.onClickWrapper_ = + conditionalBind(table, 'click', this, this.onClick_, true); + this.onMouseMoveWrapper_ = + conditionalBind(table, 'mousemove', this, this.onMouseMove_, true); + this.onMouseEnterWrapper_ = + conditionalBind(table, 'mouseenter', this, this.onMouseEnter_, true); + this.onMouseLeaveWrapper_ = + conditionalBind(table, 'mouseleave', this, this.onMouseLeave_, true); + this.onKeyDownWrapper_ = + conditionalBind(table, 'keydown', this, this.onKeyDown_); this.picker_ = table; }; @@ -576,25 +577,25 @@ Blockly.FieldColour.prototype.dropdownCreate_ = function() { * Disposes of events and DOM-references belonging to the colour editor. * @private */ -Blockly.FieldColour.prototype.dropdownDispose_ = function() { +FieldColour.prototype.dropdownDispose_ = function() { if (this.onClickWrapper_) { - Blockly.browserEvents.unbind(this.onClickWrapper_); + unbind(this.onClickWrapper_); this.onClickWrapper_ = null; } if (this.onMouseMoveWrapper_) { - Blockly.browserEvents.unbind(this.onMouseMoveWrapper_); + unbind(this.onMouseMoveWrapper_); this.onMouseMoveWrapper_ = null; } if (this.onMouseEnterWrapper_) { - Blockly.browserEvents.unbind(this.onMouseEnterWrapper_); + unbind(this.onMouseEnterWrapper_); this.onMouseEnterWrapper_ = null; } if (this.onMouseLeaveWrapper_) { - Blockly.browserEvents.unbind(this.onMouseLeaveWrapper_); + unbind(this.onMouseLeaveWrapper_); this.onMouseLeaveWrapper_ = null; } if (this.onKeyDownWrapper_) { - Blockly.browserEvents.unbind(this.onKeyDownWrapper_); + unbind(this.onKeyDownWrapper_); this.onKeyDownWrapper_ = null; } this.picker_ = null; @@ -604,7 +605,7 @@ Blockly.FieldColour.prototype.dropdownDispose_ = function() { /** * CSS for colour picker. See css.js for use. */ -Blockly.Css.register([ +Css.register([ /* eslint-disable indent */ '.blocklyColourTable {', 'border-collapse: collapse;', @@ -637,4 +638,6 @@ Blockly.Css.register([ /* eslint-enable indent */ ]); -Blockly.fieldRegistry.register('field_colour', Blockly.FieldColour); +fieldRegistry.register('field_colour', FieldColour); + +exports = FieldColour; diff --git a/core/field_dropdown.js b/core/field_dropdown.js index 5dad752d8..ddb5a4e18 100644 --- a/core/field_dropdown.js +++ b/core/field_dropdown.js @@ -12,21 +12,22 @@ */ 'use strict'; -goog.provide('Blockly.FieldDropdown'); +goog.module('Blockly.FieldDropdown'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.DropDownDiv'); -goog.require('Blockly.Field'); -goog.require('Blockly.fieldRegistry'); -goog.require('Blockly.Menu'); -goog.require('Blockly.MenuItem'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.aria'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.object'); -goog.require('Blockly.utils.string'); -goog.require('Blockly.utils.Svg'); -goog.require('Blockly.utils.userAgent'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +const DropDownDiv = goog.require('Blockly.DropDownDiv'); +const Field = goog.require('Blockly.Field'); +const Menu = goog.require('Blockly.Menu'); +const MenuItem = goog.require('Blockly.MenuItem'); +const Svg = goog.require('Blockly.utils.Svg'); +const aria = goog.require('Blockly.utils.aria'); +const dom = goog.require('Blockly.utils.dom'); +const fieldRegistry = goog.require('Blockly.fieldRegistry'); +const userAgent = goog.require('Blockly.utils.userAgent'); +const {commonWordPrefix, commonWordSuffix, shortestStringLength} = goog.require('Blockly.utils.string'); +const {inherits} = goog.require('Blockly.utils.object'); +const {replaceMessageReferences} = goog.require('Blockly.utils'); /** @@ -38,22 +39,23 @@ goog.require('Blockly.utils.userAgent'); * option & returns a validated language-neutral dropdown option, 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/dropdown#creation} + * See the [field creation documentation]{@link + * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/dropdown#creation} * for a list of properties this parameter supports. - * @extends {Blockly.Field} + * @extends {Field} * @constructor * @throws {TypeError} If `menuGenerator` options are incorrectly structured. */ -Blockly.FieldDropdown = function(menuGenerator, opt_validator, opt_config) { +const FieldDropdown = function(menuGenerator, opt_validator, opt_config) { if (typeof menuGenerator != 'function') { - Blockly.FieldDropdown.validateOptions_(menuGenerator); + validateOptions(menuGenerator); } /** * An array of options for a dropdown list, * or a function which generates these options. * @type {(!Array| - * !function(this:Blockly.FieldDropdown): !Array)} + * !function(this:FieldDropdown): !Array)} * @protected */ this.menuGenerator_ = menuGenerator; @@ -90,19 +92,19 @@ Blockly.FieldDropdown = function(menuGenerator, opt_validator, opt_config) { this.selectedOption_ = this.getOptions(false)[0]; // Call parent's constructor. - Blockly.FieldDropdown.superClass_.constructor.call( + FieldDropdown.superClass_.constructor.call( this, this.selectedOption_[1], opt_validator, opt_config); /** * A reference to the currently selected menu item. - * @type {?Blockly.MenuItem} + * @type {?MenuItem} * @private */ this.selectedMenuItem_ = null; /** * The dropdown menu. - * @type {?Blockly.Menu} + * @type {?Menu} * @protected */ this.menu_ = null; @@ -128,27 +130,27 @@ Blockly.FieldDropdown = function(menuGenerator, opt_validator, opt_config) { */ this.svgArrow_ = null; }; -Blockly.utils.object.inherits(Blockly.FieldDropdown, Blockly.Field); +inherits(FieldDropdown, Field); /** * Dropdown image properties. * @typedef {{ - * src:string, - * alt:string, - * width:number, - * height:number - * }} - */ -Blockly.FieldDropdown.ImageProperties; + * src:string, + * alt:string, + * width:number, + * height:number + * }} + */ +FieldDropdown.ImageProperties; /** * Construct a FieldDropdown from a JSON arg object. * @param {!Object} options A JSON object with options (options). - * @return {!Blockly.FieldDropdown} The new field instance. + * @return {!FieldDropdown} The new field instance. * @package * @nocollapse */ -Blockly.FieldDropdown.fromJson = function(options) { +FieldDropdown.fromJson = function(options) { // `this` might be a subclass of FieldDropdown if that class doesn't override // the static fromJson method. return new this(options['options'], undefined, options); @@ -161,7 +163,7 @@ Blockly.FieldDropdown.fromJson = function(options) { * field's state. * @package */ -Blockly.FieldDropdown.prototype.fromXml = function(fieldElement) { +FieldDropdown.prototype.fromXml = function(fieldElement) { if (this.isOptionListDynamic()) { this.getOptions(false); } @@ -173,52 +175,48 @@ Blockly.FieldDropdown.prototype.fromXml = function(fieldElement) { * are not. Editable fields should also be serializable. * @type {boolean} */ -Blockly.FieldDropdown.prototype.SERIALIZABLE = true; +FieldDropdown.prototype.SERIALIZABLE = true; /** * Horizontal distance that a checkmark overhangs the dropdown. */ -Blockly.FieldDropdown.CHECKMARK_OVERHANG = 25; +FieldDropdown.CHECKMARK_OVERHANG = 25; /** * Maximum height of the dropdown menu, as a percentage of the viewport height. */ -Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH = 0.45; +FieldDropdown.MAX_MENU_HEIGHT_VH = 0.45; /** * The y offset from the top of the field to the top of the image, if an image * is selected. * @type {number} * @const - * @private */ -Blockly.FieldDropdown.IMAGE_Y_OFFSET = 5; +const IMAGE_Y_OFFSET = 5; /** * The total vertical padding above and below an image. * @type {number} * @const - * @private */ -Blockly.FieldDropdown.IMAGE_Y_PADDING = - Blockly.FieldDropdown.IMAGE_Y_OFFSET * 2; +const IMAGE_Y_PADDING = IMAGE_Y_OFFSET * 2; /** * Android can't (in 2014) display "▾", so use "▼" instead. */ -Blockly.FieldDropdown.ARROW_CHAR = - Blockly.utils.userAgent.ANDROID ? '\u25BC' : '\u25BE'; +FieldDropdown.ARROW_CHAR = userAgent.ANDROID ? '\u25BC' : '\u25BE'; /** * Mouse cursor style when over the hotspot that initiates the editor. */ -Blockly.FieldDropdown.prototype.CURSOR = 'default'; +FieldDropdown.prototype.CURSOR = 'default'; /** * Create the block UI for this dropdown. * @package */ -Blockly.FieldDropdown.prototype.initView = function() { +FieldDropdown.prototype.initView = function() { if (this.shouldAddBorderRect_()) { this.createBorderRect_(); } else { @@ -226,8 +224,7 @@ Blockly.FieldDropdown.prototype.initView = function() { } this.createTextElement_(); - this.imageElement_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.IMAGE, {}, this.fieldGroup_); + this.imageElement_ = dom.createSvgElement(Svg.IMAGE, {}, this.fieldGroup_); if (this.getConstants().FIELD_DROPDOWN_SVG_ARROW) { this.createSVGArrow_(); @@ -236,7 +233,7 @@ Blockly.FieldDropdown.prototype.initView = function() { } if (this.borderRect_) { - Blockly.utils.dom.addClass(this.borderRect_, 'blocklyDropdownRect'); + dom.addClass(this.borderRect_, 'blocklyDropdownRect'); } }; @@ -245,23 +242,21 @@ Blockly.FieldDropdown.prototype.initView = function() { * @return {boolean} True if the dropdown field should add a border rect. * @protected */ -Blockly.FieldDropdown.prototype.shouldAddBorderRect_ = function() { +FieldDropdown.prototype.shouldAddBorderRect_ = function() { return !this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW || (this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW && - !this.sourceBlock_.isShadow()); + !this.sourceBlock_.isShadow()); }; /** * Create a tspan based arrow. * @protected */ -Blockly.FieldDropdown.prototype.createTextArrow_ = function() { - this.arrow_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.TSPAN, {}, this.textElement_); +FieldDropdown.prototype.createTextArrow_ = function() { + this.arrow_ = dom.createSvgElement(Svg.TSPAN, {}, this.textElement_); this.arrow_.appendChild(document.createTextNode( - this.sourceBlock_.RTL ? - Blockly.FieldDropdown.ARROW_CHAR + ' ' : - ' ' + Blockly.FieldDropdown.ARROW_CHAR)); + this.sourceBlock_.RTL ? FieldDropdown.ARROW_CHAR + ' ' : + ' ' + FieldDropdown.ARROW_CHAR)); if (this.sourceBlock_.RTL) { this.textElement_.insertBefore(this.arrow_, this.textContent_); } else { @@ -273,13 +268,15 @@ Blockly.FieldDropdown.prototype.createTextArrow_ = function() { * Create an SVG based arrow. * @protected */ -Blockly.FieldDropdown.prototype.createSVGArrow_ = function() { - this.svgArrow_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.IMAGE, { +FieldDropdown.prototype.createSVGArrow_ = function() { + this.svgArrow_ = dom.createSvgElement( + Svg.IMAGE, { 'height': this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE + 'px', 'width': this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE + 'px' - }, this.fieldGroup_); - this.svgArrow_.setAttributeNS(Blockly.utils.dom.XLINK_NS, 'xlink:href', + }, + this.fieldGroup_); + this.svgArrow_.setAttributeNS( + dom.XLINK_NS, 'xlink:href', this.getConstants().FIELD_DROPDOWN_SVG_ARROW_DATAURI); }; @@ -289,31 +286,29 @@ Blockly.FieldDropdown.prototype.createSVGArrow_ = function() { * or undefined if triggered programmatically. * @protected */ -Blockly.FieldDropdown.prototype.showEditor_ = function(opt_e) { +FieldDropdown.prototype.showEditor_ = function(opt_e) { this.dropdownCreate_(); if (opt_e && typeof opt_e.clientX === 'number') { - this.menu_.openingCoords = - new Blockly.utils.Coordinate(opt_e.clientX, opt_e.clientY); + this.menu_.openingCoords = new Coordinate(opt_e.clientX, opt_e.clientY); } else { this.menu_.openingCoords = null; } // Element gets created in render. - this.menu_.render(Blockly.DropDownDiv.getContentDiv()); - var menuElement = /** @type {!Element} */ (this.menu_.getElement()); - Blockly.utils.dom.addClass(menuElement, 'blocklyDropdownMenu'); + this.menu_.render(DropDownDiv.getContentDiv()); + const menuElement = /** @type {!Element} */ (this.menu_.getElement()); + dom.addClass(menuElement, 'blocklyDropdownMenu'); if (this.getConstants().FIELD_DROPDOWN_COLOURED_DIV) { - var primaryColour = (this.sourceBlock_.isShadow()) ? + const primaryColour = (this.sourceBlock_.isShadow()) ? this.sourceBlock_.getParent().getColour() : this.sourceBlock_.getColour(); - var borderColour = (this.sourceBlock_.isShadow()) ? + const borderColour = (this.sourceBlock_.isShadow()) ? this.sourceBlock_.getParent().style.colourTertiary : this.sourceBlock_.style.colourTertiary; - Blockly.DropDownDiv.setColour(primaryColour, borderColour); + DropDownDiv.setColour(primaryColour, borderColour); } - Blockly.DropDownDiv.showPositionedByField( - this, this.dropdownDispose_.bind(this)); + DropDownDiv.showPositionedByField(this, this.dropdownDispose_.bind(this)); // Focusing needs to be handled after the menu is rendered and positioned. // Otherwise it will cause a page scroll to get the misplaced menu in @@ -331,25 +326,25 @@ Blockly.FieldDropdown.prototype.showEditor_ = function(opt_e) { * Create the dropdown editor. * @private */ -Blockly.FieldDropdown.prototype.dropdownCreate_ = function() { - var menu = new Blockly.Menu(); - menu.setRole(Blockly.utils.aria.Role.LISTBOX); +FieldDropdown.prototype.dropdownCreate_ = function() { + const menu = new Menu(); + menu.setRole(aria.Role.LISTBOX); this.menu_ = menu; - var options = this.getOptions(false); + const options = this.getOptions(false); this.selectedMenuItem_ = null; - for (var i = 0; i < options.length; i++) { - var content = options[i][0]; // Human-readable text or image. - var value = options[i][1]; // Language-neutral value. + for (let i = 0; i < options.length; i++) { + let content = options[i][0]; // Human-readable text or image. + const value = options[i][1]; // Language-neutral value. if (typeof content == 'object') { // An image, not text. - var image = new Image(content['width'], content['height']); + const image = new Image(content['width'], content['height']); image.src = content['src']; image.alt = content['alt'] || ''; content = image; } - var menuItem = new Blockly.MenuItem(content, value); - menuItem.setRole(Blockly.utils.aria.Role.OPTION); + const menuItem = new MenuItem(content, value); + menuItem.setRole(aria.Role.OPTION); menuItem.setRightToLeft(this.sourceBlock_.RTL); menuItem.setCheckable(true); menu.addChild(menuItem); @@ -365,7 +360,7 @@ Blockly.FieldDropdown.prototype.dropdownCreate_ = function() { * Disposes of events and DOM-references belonging to the dropdown editor. * @private */ -Blockly.FieldDropdown.prototype.dropdownDispose_ = function() { +FieldDropdown.prototype.dropdownDispose_ = function() { if (this.menu_) { this.menu_.dispose(); } @@ -376,21 +371,21 @@ Blockly.FieldDropdown.prototype.dropdownDispose_ = function() { /** * Handle an action in the dropdown menu. - * @param {!Blockly.MenuItem} menuItem The MenuItem selected within menu. + * @param {!MenuItem} menuItem The MenuItem selected within menu. * @private */ -Blockly.FieldDropdown.prototype.handleMenuActionEvent_ = function(menuItem) { - Blockly.DropDownDiv.hideIfOwner(this, true); - this.onItemSelected_(/** @type {!Blockly.Menu} */ (this.menu_), menuItem); +FieldDropdown.prototype.handleMenuActionEvent_ = function(menuItem) { + DropDownDiv.hideIfOwner(this, true); + this.onItemSelected_(/** @type {!Menu} */ (this.menu_), menuItem); }; /** * Handle the selection of an item in the dropdown menu. - * @param {!Blockly.Menu} menu The Menu component clicked. - * @param {!Blockly.MenuItem} menuItem The MenuItem selected within menu. + * @param {!Menu} menu The Menu component clicked. + * @param {!MenuItem} menuItem The MenuItem selected within menu. * @protected */ -Blockly.FieldDropdown.prototype.onItemSelected_ = function(menu, menuItem) { +FieldDropdown.prototype.onItemSelected_ = function(menu, menuItem) { this.setValue(menuItem.getValue()); }; @@ -399,21 +394,21 @@ Blockly.FieldDropdown.prototype.onItemSelected_ = function(menu, menuItem) { * Create prefix and/or suffix labels. * @private */ -Blockly.FieldDropdown.prototype.trimOptions_ = function() { - var options = this.menuGenerator_; +FieldDropdown.prototype.trimOptions_ = function() { + const options = this.menuGenerator_; if (!Array.isArray(options)) { return; } - var hasImages = false; + let hasImages = false; // Localize label text and image alt text. - for (var i = 0; i < options.length; i++) { - var label = options[i][0]; + for (let i = 0; i < options.length; i++) { + const label = options[i][0]; if (typeof label == 'string') { - options[i][0] = Blockly.utils.replaceMessageReferences(label); + options[i][0] = replaceMessageReferences(label); } else { if (label.alt != null) { - options[i][0].alt = Blockly.utils.replaceMessageReferences(label.alt); + options[i][0].alt = replaceMessageReferences(label.alt); } hasImages = true; } @@ -421,13 +416,13 @@ Blockly.FieldDropdown.prototype.trimOptions_ = function() { if (hasImages || options.length < 2) { return; // Do nothing if too few items or at least one label is an image. } - var strings = []; - for (var i = 0; i < options.length; i++) { + const strings = []; + for (let i = 0; i < options.length; i++) { strings.push(options[i][0]); } - var shortest = Blockly.utils.string.shortestStringLength(strings); - var prefixLength = Blockly.utils.string.commonWordPrefix(strings, shortest); - var suffixLength = Blockly.utils.string.commonWordSuffix(strings, shortest); + const shortest = shortestStringLength(strings); + const prefixLength = commonWordPrefix(strings, shortest); + const suffixLength = commonWordSuffix(strings, shortest); if (!prefixLength && !suffixLength) { return; } @@ -442,8 +437,8 @@ Blockly.FieldDropdown.prototype.trimOptions_ = function() { this.suffixField = strings[0].substr(1 - suffixLength); } - this.menuGenerator_ = Blockly.FieldDropdown.applyTrim_(options, prefixLength, - suffixLength); + this.menuGenerator_ = + FieldDropdown.applyTrim_(options, prefixLength, suffixLength); }; /** @@ -455,13 +450,12 @@ Blockly.FieldDropdown.prototype.trimOptions_ = function() { * @param {number} suffixLength The length of the common suffix * @return {!Array} A new array with all of the option text trimmed. */ -Blockly.FieldDropdown.applyTrim_ = function(options, - prefixLength, suffixLength) { - var newOptions = []; +FieldDropdown.applyTrim_ = function(options, prefixLength, suffixLength) { + const newOptions = []; // Remove the prefix and suffix from the options. - for (var i = 0; i < options.length; i++) { - var text = options[i][0]; - var value = options[i][1]; + for (let i = 0; i < options.length; i++) { + let text = options[i][0]; + const value = options[i][1]; text = text.substring(prefixLength, text.length - suffixLength); newOptions[i] = [text, value]; } @@ -472,7 +466,7 @@ Blockly.FieldDropdown.applyTrim_ = function(options, * @return {boolean} True if the option list is generated by a function. * Otherwise false. */ -Blockly.FieldDropdown.prototype.isOptionListDynamic = function() { +FieldDropdown.prototype.isOptionListDynamic = function() { return typeof this.menuGenerator_ == 'function'; }; @@ -484,11 +478,11 @@ Blockly.FieldDropdown.prototype.isOptionListDynamic = function() { * (human-readable text or image, language-neutral name). * @throws {TypeError} If generated options are incorrectly structured. */ -Blockly.FieldDropdown.prototype.getOptions = function(opt_useCache) { +FieldDropdown.prototype.getOptions = function(opt_useCache) { if (this.isOptionListDynamic()) { if (!this.generatedOptions_ || !opt_useCache) { this.generatedOptions_ = this.menuGenerator_.call(this); - Blockly.FieldDropdown.validateOptions_(this.generatedOptions_); + validateOptions(this.generatedOptions_); } return this.generatedOptions_; } @@ -501,10 +495,10 @@ Blockly.FieldDropdown.prototype.getOptions = function(opt_useCache) { * @return {?string} A valid language-neutral option, or null if invalid. * @protected */ -Blockly.FieldDropdown.prototype.doClassValidation_ = function(opt_newValue) { - var isValueValid = false; - var options = this.getOptions(true); - for (var i = 0, option; (option = options[i]); i++) { +FieldDropdown.prototype.doClassValidation_ = function(opt_newValue) { + let isValueValid = false; + const options = this.getOptions(true); + for (let i = 0, option; (option = options[i]); i++) { // Options are tuples of human-readable text and language-neutral values. if (option[1] == opt_newValue) { isValueValid = true; @@ -513,9 +507,10 @@ Blockly.FieldDropdown.prototype.doClassValidation_ = function(opt_newValue) { } if (!isValueValid) { if (this.sourceBlock_) { - console.warn('Cannot set the dropdown\'s value to an unavailable option.' + - ' Block type: ' + this.sourceBlock_.type + ', Field name: ' + this.name + - ', Value: ' + opt_newValue); + console.warn( + 'Cannot set the dropdown\'s value to an unavailable option.' + + ' Block type: ' + this.sourceBlock_.type + + ', Field name: ' + this.name + ', Value: ' + opt_newValue); } return null; } @@ -528,10 +523,10 @@ Blockly.FieldDropdown.prototype.doClassValidation_ = function(opt_newValue) { * that this is one of the valid dropdown options. * @protected */ -Blockly.FieldDropdown.prototype.doValueUpdate_ = function(newValue) { - Blockly.FieldDropdown.superClass_.doValueUpdate_.call(this, newValue); - var options = this.getOptions(true); - for (var i = 0, option; (option = options[i]); i++) { +FieldDropdown.prototype.doValueUpdate_ = function(newValue) { + FieldDropdown.superClass_.doValueUpdate_.call(this, newValue); + const options = this.getOptions(true); + for (let i = 0, option; (option = options[i]); i++) { if (option[1] == this.value_) { this.selectedOption_ = option; } @@ -542,13 +537,13 @@ Blockly.FieldDropdown.prototype.doValueUpdate_ = function(newValue) { * Updates the dropdown arrow to match the colour/style of the block. * @package */ -Blockly.FieldDropdown.prototype.applyColour = function() { +FieldDropdown.prototype.applyColour = function() { if (this.borderRect_) { - this.borderRect_.setAttribute('stroke', - this.sourceBlock_.style.colourTertiary); + this.borderRect_.setAttribute( + 'stroke', this.sourceBlock_.style.colourTertiary); if (this.menu_) { - this.borderRect_.setAttribute('fill', - this.sourceBlock_.style.colourTertiary); + this.borderRect_.setAttribute( + 'fill', this.sourceBlock_.style.colourTertiary); } else { this.borderRect_.setAttribute('fill', 'transparent'); } @@ -567,16 +562,16 @@ Blockly.FieldDropdown.prototype.applyColour = function() { * Draws the border with the correct width. * @protected */ -Blockly.FieldDropdown.prototype.render_ = function() { +FieldDropdown.prototype.render_ = function() { // Hide both elements. this.textContent_.nodeValue = ''; this.imageElement_.style.display = 'none'; // Show correct element. - var option = this.selectedOption_ && this.selectedOption_[0]; + const option = this.selectedOption_ && this.selectedOption_[0]; if (option && typeof option == 'object') { this.renderSelectedImage_( - /** @type {!Blockly.FieldDropdown.ImageProperties} */ (option)); + /** @type {!FieldDropdown.ImageProperties} */ (option)); } else { this.renderSelectedText_(); } @@ -586,32 +581,33 @@ Blockly.FieldDropdown.prototype.render_ = function() { /** * Renders the selected option, which must be an image. - * @param {!Blockly.FieldDropdown.ImageProperties} imageJson Selected + * @param {!FieldDropdown.ImageProperties} imageJson Selected * option that must be an image. * @private */ -Blockly.FieldDropdown.prototype.renderSelectedImage_ = function(imageJson) { +FieldDropdown.prototype.renderSelectedImage_ = function(imageJson) { this.imageElement_.style.display = ''; - this.imageElement_.setAttributeNS( - Blockly.utils.dom.XLINK_NS, 'xlink:href', imageJson.src); + this.imageElement_.setAttributeNS(dom.XLINK_NS, 'xlink:href', imageJson.src); this.imageElement_.setAttribute('height', imageJson.height); this.imageElement_.setAttribute('width', imageJson.width); - var imageHeight = Number(imageJson.height); - var imageWidth = Number(imageJson.width); + const imageHeight = Number(imageJson.height); + const imageWidth = Number(imageJson.width); // Height and width include the border rect. - var hasBorder = !!this.borderRect_; - var height = Math.max( + const hasBorder = !!this.borderRect_; + const height = Math.max( hasBorder ? this.getConstants().FIELD_DROPDOWN_BORDER_RECT_HEIGHT : 0, - imageHeight + Blockly.FieldDropdown.IMAGE_Y_PADDING); - var xPadding = hasBorder ? this.getConstants().FIELD_BORDER_RECT_X_PADDING : 0; - var arrowWidth = 0; + imageHeight + IMAGE_Y_PADDING); + const xPadding = + hasBorder ? this.getConstants().FIELD_BORDER_RECT_X_PADDING : 0; + let arrowWidth = 0; if (this.svgArrow_) { - arrowWidth = this.positionSVGArrow_(imageWidth + xPadding, height / 2 - - this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE / 2); + arrowWidth = this.positionSVGArrow_( + imageWidth + xPadding, + height / 2 - this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE / 2); } else { - arrowWidth = Blockly.utils.dom.getFastTextWidth( + arrowWidth = dom.getFastTextWidth( /** @type {!SVGTSpanElement} */ (this.arrow_), this.getConstants().FIELD_TEXT_FONTSIZE, this.getConstants().FIELD_TEXT_FONTWEIGHT, @@ -620,9 +616,9 @@ Blockly.FieldDropdown.prototype.renderSelectedImage_ = function(imageJson) { this.size_.width = imageWidth + arrowWidth + xPadding * 2; this.size_.height = height; - var arrowX = 0; + let arrowX = 0; if (this.sourceBlock_.RTL) { - var imageX = xPadding + arrowWidth; + const imageX = xPadding + arrowWidth; this.imageElement_.setAttribute('x', imageX); } else { arrowX = imageWidth + arrowWidth; @@ -638,27 +634,29 @@ Blockly.FieldDropdown.prototype.renderSelectedImage_ = function(imageJson) { * Renders the selected option, which must be text. * @private */ -Blockly.FieldDropdown.prototype.renderSelectedText_ = function() { +FieldDropdown.prototype.renderSelectedText_ = function() { // Retrieves the selected option to display through getText_. this.textContent_.nodeValue = this.getDisplayText_(); - Blockly.utils.dom.addClass(/** @type {!Element} */ (this.textElement_), - 'blocklyDropdownText'); + dom.addClass( + /** @type {!Element} */ (this.textElement_), 'blocklyDropdownText'); this.textElement_.setAttribute('text-anchor', 'start'); // Height and width include the border rect. - var hasBorder = !!this.borderRect_; - var height = Math.max( + const hasBorder = !!this.borderRect_; + const height = Math.max( hasBorder ? this.getConstants().FIELD_DROPDOWN_BORDER_RECT_HEIGHT : 0, this.getConstants().FIELD_TEXT_HEIGHT); - var textWidth = Blockly.utils.dom.getFastTextWidth(this.textElement_, - this.getConstants().FIELD_TEXT_FONTSIZE, + const textWidth = dom.getFastTextWidth( + this.textElement_, this.getConstants().FIELD_TEXT_FONTSIZE, this.getConstants().FIELD_TEXT_FONTWEIGHT, this.getConstants().FIELD_TEXT_FONTFAMILY); - var xPadding = hasBorder ? this.getConstants().FIELD_BORDER_RECT_X_PADDING : 0; - var arrowWidth = 0; + const xPadding = + hasBorder ? this.getConstants().FIELD_BORDER_RECT_X_PADDING : 0; + let arrowWidth = 0; if (this.svgArrow_) { - arrowWidth = this.positionSVGArrow_(textWidth + xPadding, height / 2 - - this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE / 2); + arrowWidth = this.positionSVGArrow_( + textWidth + xPadding, + height / 2 - this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE / 2); } this.size_.width = textWidth + arrowWidth + xPadding * 2; this.size_.height = height; @@ -673,17 +671,18 @@ Blockly.FieldDropdown.prototype.renderSelectedText_ = function() { * @return {number} Amount of space the arrow is taking up, in px. * @private */ -Blockly.FieldDropdown.prototype.positionSVGArrow_ = function(x, y) { +FieldDropdown.prototype.positionSVGArrow_ = function(x, y) { if (!this.svgArrow_) { return 0; } - var hasBorder = !!this.borderRect_; - var xPadding = hasBorder ? this.getConstants().FIELD_BORDER_RECT_X_PADDING : 0; - var textPadding = this.getConstants().FIELD_DROPDOWN_SVG_ARROW_PADDING; - var svgArrowSize = this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE; - var arrowX = this.sourceBlock_.RTL ? xPadding : x + textPadding; - this.svgArrow_.setAttribute('transform', - 'translate(' + arrowX + ',' + y + ')'); + const hasBorder = !!this.borderRect_; + const xPadding = + hasBorder ? this.getConstants().FIELD_BORDER_RECT_X_PADDING : 0; + const textPadding = this.getConstants().FIELD_DROPDOWN_SVG_ARROW_PADDING; + const svgArrowSize = this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE; + const arrowX = this.sourceBlock_.RTL ? xPadding : x + textPadding; + this.svgArrow_.setAttribute( + 'transform', 'translate(' + arrowX + ',' + y + ')'); return svgArrowSize + textPadding; }; @@ -695,11 +694,11 @@ Blockly.FieldDropdown.prototype.positionSVGArrow_ = function(x, y) { * @protected * @override */ -Blockly.FieldDropdown.prototype.getText_ = function() { +FieldDropdown.prototype.getText_ = function() { if (!this.selectedOption_) { return null; } - var option = this.selectedOption_[0]; + const option = this.selectedOption_[0]; if (typeof option == 'object') { return option['alt']; } @@ -710,35 +709,36 @@ Blockly.FieldDropdown.prototype.getText_ = function() { * Validates the data structure to be processed as an options list. * @param {?} options The proposed dropdown options. * @throws {TypeError} If proposed options are incorrectly structured. - * @private */ -Blockly.FieldDropdown.validateOptions_ = function(options) { +const validateOptions = function(options) { if (!Array.isArray(options)) { throw TypeError('FieldDropdown options must be an array.'); } if (!options.length) { throw TypeError('FieldDropdown options must not be an empty array.'); } - var foundError = false; - for (var i = 0; i < options.length; ++i) { - var tuple = options[i]; + let foundError = false; + for (let i = 0; i < options.length; ++i) { + const tuple = options[i]; if (!Array.isArray(tuple)) { foundError = true; console.error( 'Invalid option[' + i + ']: Each FieldDropdown option must be an ' + - 'array. Found: ', tuple); + 'array. Found: ', + tuple); } else if (typeof tuple[1] != 'string') { foundError = true; console.error( 'Invalid option[' + i + ']: Each FieldDropdown option id must be ' + - 'a string. Found ' + tuple[1] + ' in: ', tuple); - } else if (tuple[0] && - (typeof tuple[0] != 'string') && - (typeof tuple[0].src != 'string')) { + 'a string. Found ' + tuple[1] + ' in: ', + tuple); + } else if ( + tuple[0] && (typeof tuple[0] != 'string') && + (typeof tuple[0].src != 'string')) { foundError = true; console.error( 'Invalid option[' + i + ']: Each FieldDropdown option must have a ' + - 'string label or image description. Found' + tuple[0] + ' in: ', + 'string label or image description. Found' + tuple[0] + ' in: ', tuple); } } @@ -747,4 +747,6 @@ Blockly.FieldDropdown.validateOptions_ = function(options) { } }; -Blockly.fieldRegistry.register('field_dropdown', Blockly.FieldDropdown); +fieldRegistry.register('field_dropdown', FieldDropdown); + +exports = FieldDropdown; diff --git a/core/field_image.js b/core/field_image.js index eed381b63..9edc92c56 100644 --- a/core/field_image.js +++ b/core/field_image.js @@ -10,15 +10,16 @@ */ 'use strict'; -goog.provide('Blockly.FieldImage'); +goog.module('Blockly.FieldImage'); +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'); -goog.require('Blockly.utils.Size'); -goog.require('Blockly.utils.Svg'); +const Field = goog.require('Blockly.Field'); +const Size = goog.require('Blockly.utils.Size'); +const Svg = goog.require('Blockly.utils.Svg'); +const fieldRegistry = goog.require('Blockly.fieldRegistry'); +const {createSvgElement, XLINK_NS} = goog.require('Blockly.utils.dom'); +const {inherits} = goog.require('Blockly.utils.object'); +const {replaceMessageReferences} = goog.require('Blockly.utils'); /** @@ -27,32 +28,35 @@ goog.require('Blockly.utils.Svg'); * @param {!(string|number)} width Width of the image. * @param {!(string|number)} height Height of the image. * @param {string=} opt_alt Optional alt text for when block is collapsed. - * @param {function(!Blockly.FieldImage)=} opt_onClick Optional function to be + * @param {function(!FieldImage)=} opt_onClick Optional function to be * called when the image is clicked. If opt_onClick is defined, opt_alt must * also be defined. * @param {boolean=} opt_flipRtl Whether to flip the icon in RTL. * @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/image#creation} + * See the [field creation documentation]{@link + * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/image#creation} * for a list of properties this parameter supports. - * @extends {Blockly.Field} + * @extends {Field} * @constructor */ -Blockly.FieldImage = function(src, width, height, - opt_alt, opt_onClick, opt_flipRtl, opt_config) { +const FieldImage = function( + src, width, height, opt_alt, opt_onClick, opt_flipRtl, opt_config) { // Return early. if (!src) { throw Error('Src value of an image field is required'); } - src = Blockly.utils.replaceMessageReferences(src); - var imageHeight = Number(Blockly.utils.replaceMessageReferences(height)); - var imageWidth = Number(Blockly.utils.replaceMessageReferences(width)); + src = replaceMessageReferences(src); + const imageHeight = Number(replaceMessageReferences(height)); + const imageWidth = Number(replaceMessageReferences(width)); if (isNaN(imageHeight) || isNaN(imageWidth)) { - throw Error('Height and width values of an image field must cast to' + - ' numbers.'); + throw Error( + 'Height and width values of an image field must cast to' + + ' numbers.'); } if (imageHeight <= 0 || imageWidth <= 0) { - throw Error('Height and width values of an image field must be greater' + - ' than 0.'); + throw Error( + 'Height and width values of an image field must be greater' + + ' than 0.'); } // Initialize configurable properties. @@ -70,23 +74,21 @@ Blockly.FieldImage = function(src, width, height, */ this.altText_ = ''; - Blockly.FieldImage.superClass_.constructor.call( - this, src, null, opt_config); + FieldImage.superClass_.constructor.call(this, src, null, opt_config); if (!opt_config) { // If the config wasn't passed, do old configuration. this.flipRtl_ = !!opt_flipRtl; - this.altText_ = Blockly.utils.replaceMessageReferences(opt_alt) || ''; + this.altText_ = replaceMessageReferences(opt_alt) || ''; } // Initialize other properties. /** * The size of the area rendered by the field. - * @type {Blockly.utils.Size} + * @type {Size} * @protected * @override */ - this.size_ = new Blockly.utils.Size(imageWidth, - imageHeight + Blockly.FieldImage.Y_PADDING); + this.size_ = new Size(imageWidth, imageHeight + FieldImage.Y_PADDING); /** * Store the image height, since it is different from the field height. @@ -97,7 +99,7 @@ Blockly.FieldImage = function(src, width, height, /** * The function to be called when this field is clicked. - * @type {?function(!Blockly.FieldImage)} + * @type {?function(!FieldImage)} * @private */ this.clickHandler_ = null; @@ -113,29 +115,30 @@ Blockly.FieldImage = function(src, width, height, */ this.imageElement_ = null; }; -Blockly.utils.object.inherits(Blockly.FieldImage, Blockly.Field); +inherits(FieldImage, Field); /** * The default value for this field. * @type {*} * @protected */ -Blockly.FieldImage.prototype.DEFAULT_VALUE = ''; +FieldImage.prototype.DEFAULT_VALUE = ''; /** * Construct a FieldImage from a JSON arg object, * dereferencing any string table references. * @param {!Object} options A JSON object with options (src, width, height, * alt, and flipRtl). - * @return {!Blockly.FieldImage} The new field instance. + * @return {!FieldImage} The new field instance. * @package * @nocollapse */ -Blockly.FieldImage.fromJson = function(options) { +FieldImage.fromJson = function(options) { // `this` might be a subclass of FieldImage if that class doesn't override // the static fromJson method. - return new this(options['src'], options['width'], options['height'], - undefined, undefined, undefined, options); + return new this( + options['src'], options['width'], options['height'], undefined, undefined, + undefined, options); }; /** @@ -144,14 +147,14 @@ Blockly.FieldImage.fromJson = function(options) { * @type {number} * @private */ -Blockly.FieldImage.Y_PADDING = 1; +FieldImage.Y_PADDING = 1; /** * Editable fields usually show some sort of UI indicating they are * editable. This field should not. * @type {boolean} */ -Blockly.FieldImage.prototype.EDITABLE = false; +FieldImage.prototype.EDITABLE = false; /** * Used to tell if the field needs to be rendered the next time the block is @@ -160,7 +163,7 @@ Blockly.FieldImage.prototype.EDITABLE = false; * @type {boolean} * @protected */ -Blockly.FieldImage.prototype.isDirty_ = false; +FieldImage.prototype.isDirty_ = false; /** * Configure the field based on the given map of options. @@ -168,27 +171,26 @@ Blockly.FieldImage.prototype.isDirty_ = false; * @protected * @override */ -Blockly.FieldImage.prototype.configure_ = function(config) { - Blockly.FieldImage.superClass_.configure_.call(this, config); +FieldImage.prototype.configure_ = function(config) { + FieldImage.superClass_.configure_.call(this, config); this.flipRtl_ = !!config['flipRtl']; - this.altText_ = Blockly.utils.replaceMessageReferences(config['alt']) || ''; + this.altText_ = replaceMessageReferences(config['alt']) || ''; }; /** * Create the block UI for this image. * @package */ -Blockly.FieldImage.prototype.initView = function() { - this.imageElement_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.IMAGE, - { +FieldImage.prototype.initView = function() { + this.imageElement_ = createSvgElement( + Svg.IMAGE, { 'height': this.imageHeight_ + 'px', 'width': this.size_.width + 'px', 'alt': this.altText_ }, this.fieldGroup_); - this.imageElement_.setAttributeNS(Blockly.utils.dom.XLINK_NS, - 'xlink:href', /** @type {string} */ (this.value_)); + this.imageElement_.setAttributeNS( + XLINK_NS, 'xlink:href', /** @type {string} */ (this.value_)); if (this.clickHandler_) { this.imageElement_.style.cursor = 'pointer'; @@ -198,7 +200,7 @@ Blockly.FieldImage.prototype.initView = function() { /** * @override */ -Blockly.FieldImage.prototype.updateSize_ = function() { +FieldImage.prototype.updateSize_ = function() { // NOP }; @@ -208,7 +210,7 @@ Blockly.FieldImage.prototype.updateSize_ = function() { * @return {?string} A string, or null if invalid. * @protected */ -Blockly.FieldImage.prototype.doClassValidation_ = function(opt_newValue) { +FieldImage.prototype.doClassValidation_ = function(opt_newValue) { if (typeof opt_newValue != 'string') { return null; } @@ -221,11 +223,11 @@ Blockly.FieldImage.prototype.doClassValidation_ = function(opt_newValue) { * that this is a string. * @protected */ -Blockly.FieldImage.prototype.doValueUpdate_ = function(newValue) { +FieldImage.prototype.doValueUpdate_ = function(newValue) { this.value_ = newValue; if (this.imageElement_) { - this.imageElement_.setAttributeNS(Blockly.utils.dom.XLINK_NS, - 'xlink:href', String(this.value_)); + this.imageElement_.setAttributeNS( + XLINK_NS, 'xlink:href', String(this.value_)); } }; @@ -234,7 +236,7 @@ Blockly.FieldImage.prototype.doValueUpdate_ = function(newValue) { * @return {boolean} True if we should flip in RTL. * @override */ -Blockly.FieldImage.prototype.getFlipRtl = function() { +FieldImage.prototype.getFlipRtl = function() { return this.flipRtl_; }; @@ -243,7 +245,7 @@ Blockly.FieldImage.prototype.getFlipRtl = function() { * @param {?string} alt New alt text. * @public */ -Blockly.FieldImage.prototype.setAlt = function(alt) { +FieldImage.prototype.setAlt = function(alt) { if (alt == this.altText_) { return; } @@ -258,7 +260,7 @@ Blockly.FieldImage.prototype.setAlt = function(alt) { * call the handler. * @protected */ -Blockly.FieldImage.prototype.showEditor_ = function() { +FieldImage.prototype.showEditor_ = function() { if (this.clickHandler_) { this.clickHandler_(this); } @@ -266,10 +268,10 @@ Blockly.FieldImage.prototype.showEditor_ = function() { /** * Set the function that is called when this image is clicked. - * @param {?function(!Blockly.FieldImage)} func The function that is called + * @param {?function(!FieldImage)} func The function that is called * when the image is clicked, or null to remove. */ -Blockly.FieldImage.prototype.setOnClickHandler = function(func) { +FieldImage.prototype.setOnClickHandler = function(func) { this.clickHandler_ = func; }; @@ -281,8 +283,10 @@ Blockly.FieldImage.prototype.setOnClickHandler = function(func) { * @protected * @override */ -Blockly.FieldImage.prototype.getText_ = function() { +FieldImage.prototype.getText_ = function() { return this.altText_; }; -Blockly.fieldRegistry.register('field_image', Blockly.FieldImage); +fieldRegistry.register('field_image', FieldImage); + +exports = FieldImage; 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_label_serializable.js b/core/field_label_serializable.js index 0201db130..daabaa59f 100644 --- a/core/field_label_serializable.js +++ b/core/field_label_serializable.js @@ -11,12 +11,13 @@ */ 'use strict'; -goog.provide('Blockly.FieldLabelSerializable'); +goog.module('Blockly.FieldLabelSerializable'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.FieldLabel'); -goog.require('Blockly.fieldRegistry'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.object'); +const FieldLabel = goog.require('Blockly.FieldLabel'); +const fieldRegistry = goog.require('Blockly.fieldRegistry'); +const {inherits} = goog.require('Blockly.utils.object'); +const {replaceMessageReferences} = goog.require('Blockly.utils'); /** @@ -25,29 +26,29 @@ 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-serializable#creation} + * See the [field creation documentation]{@link + * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/label-serializable#creation} * for a list of properties this parameter supports. - * @extends {Blockly.FieldLabel} + * @extends {FieldLabel} * @constructor * */ -Blockly.FieldLabelSerializable = function(opt_value, opt_class, opt_config) { - Blockly.FieldLabelSerializable.superClass_.constructor.call( +const FieldLabelSerializable = function(opt_value, opt_class, opt_config) { + FieldLabelSerializable.superClass_.constructor.call( this, opt_value, opt_class, opt_config); }; -Blockly.utils.object.inherits(Blockly.FieldLabelSerializable, - Blockly.FieldLabel); +inherits(FieldLabelSerializable, FieldLabel); /** * Construct a FieldLabelSerializable from a JSON arg object, * dereferencing any string table references. * @param {!Object} options A JSON object with options (text, and class). - * @return {!Blockly.FieldLabelSerializable} The new field instance. + * @return {!FieldLabelSerializable} The new field instance. * @package * @nocollapse */ -Blockly.FieldLabelSerializable.fromJson = function(options) { - var text = Blockly.utils.replaceMessageReferences(options['text']); +FieldLabelSerializable.fromJson = function(options) { + const text = replaceMessageReferences(options['text']); // `this` might be a subclass of FieldLabelSerializable if that class doesn't // override the static fromJson method. return new this(text, undefined, options); @@ -58,14 +59,15 @@ Blockly.FieldLabelSerializable.fromJson = function(options) { * editable. This field should not. * @type {boolean} */ -Blockly.FieldLabelSerializable.prototype.EDITABLE = false; +FieldLabelSerializable.prototype.EDITABLE = false; /** * Serializable fields are saved by the XML renderer, non-serializable fields * are not. This field should be serialized, but only edited programmatically. * @type {boolean} */ -Blockly.FieldLabelSerializable.prototype.SERIALIZABLE = true; +FieldLabelSerializable.prototype.SERIALIZABLE = true; -Blockly.fieldRegistry.register( - 'field_label_serializable', Blockly.FieldLabelSerializable); +fieldRegistry.register('field_label_serializable', FieldLabelSerializable); + +exports = FieldLabelSerializable; diff --git a/core/field_multilineinput.js b/core/field_multilineinput.js index 887d4007f..4842429a5 100644 --- a/core/field_multilineinput.js +++ b/core/field_multilineinput.js @@ -12,20 +12,21 @@ */ 'use strict'; -goog.provide('Blockly.FieldMultilineInput'); +goog.module('Blockly.FieldMultilineInput'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Css'); -goog.require('Blockly.Field'); -goog.require('Blockly.fieldRegistry'); -goog.require('Blockly.FieldTextInput'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.aria'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.KeyCodes'); -goog.require('Blockly.utils.object'); -goog.require('Blockly.utils.Svg'); -goog.require('Blockly.utils.userAgent'); -goog.require('Blockly.WidgetDiv'); +const Css = goog.require('Blockly.Css'); +const Field = goog.require('Blockly.Field'); +const FieldTextInput = goog.require('Blockly.FieldTextInput'); +const KeyCodes = goog.require('Blockly.utils.KeyCodes'); +const Svg = goog.require('Blockly.utils.Svg'); +const WidgetDiv = goog.require('Blockly.WidgetDiv'); +const aria = goog.require('Blockly.utils.aria'); +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 {replaceMessageReferences} = goog.require('Blockly.utils'); /** @@ -37,14 +38,15 @@ goog.require('Blockly.WidgetDiv'); * text as an argument and returns either the accepted text, a replacement * text, 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/multiline-text-input#creation} + * See the [field creation documentation]{@link + * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/multiline-text-input#creation} * for a list of properties this parameter supports. - * @extends {Blockly.FieldTextInput} + * @extends {FieldTextInput} * @constructor */ -Blockly.FieldMultilineInput = function(opt_value, opt_validator, opt_config) { - Blockly.FieldMultilineInput.superClass_.constructor.call(this, - opt_value, opt_validator, opt_config); +const FieldMultilineInput = function(opt_value, opt_validator, opt_config) { + FieldMultilineInput.superClass_.constructor.call( + this, opt_value, opt_validator, opt_config); /** * The SVG group element that will contain a text element for each text row @@ -68,14 +70,13 @@ Blockly.FieldMultilineInput = function(opt_value, opt_validator, opt_config) { */ this.isOverflowedY_ = false; }; -Blockly.utils.object.inherits(Blockly.FieldMultilineInput, - Blockly.FieldTextInput); +inherits(FieldMultilineInput, FieldTextInput); /** * @override */ -Blockly.FieldMultilineInput.prototype.configure_ = function(config) { - Blockly.FieldMultilineInput.superClass_.configure_.call(this, config); +FieldMultilineInput.prototype.configure_ = function(config) { + FieldMultilineInput.superClass_.configure_.call(this, config); config.maxLines && this.setMaxLines(config.maxLines); }; @@ -83,12 +84,12 @@ Blockly.FieldMultilineInput.prototype.configure_ = function(config) { * Construct a FieldMultilineInput from a JSON arg object, * dereferencing any string table references. * @param {!Object} options A JSON object with options (text, and spellcheck). - * @return {!Blockly.FieldMultilineInput} The new field instance. + * @return {!FieldMultilineInput} The new field instance. * @package * @nocollapse */ -Blockly.FieldMultilineInput.fromJson = function(options) { - var text = Blockly.utils.replaceMessageReferences(options['text']); +FieldMultilineInput.fromJson = function(options) { + const text = replaceMessageReferences(options['text']); // `this` might be a subclass of FieldMultilineInput if that class doesn't // override the static fromJson method. return new this(text, undefined, options); @@ -101,7 +102,7 @@ Blockly.FieldMultilineInput.fromJson = function(options) { * @return {!Element} The element containing info about the field's state. * @package */ -Blockly.FieldMultilineInput.prototype.toXml = function(fieldElement) { +FieldMultilineInput.prototype.toXml = function(fieldElement) { // Replace '\n' characters with HTML-escaped equivalent ' '. This is // needed so the plain-text representation of the XML produced by // `Blockly.Xml.domToText` will appear on a single line (this is a limitation @@ -117,7 +118,7 @@ Blockly.FieldMultilineInput.prototype.toXml = function(fieldElement) { * field's state. * @package */ -Blockly.FieldMultilineInput.prototype.fromXml = function(fieldElement) { +FieldMultilineInput.prototype.fromXml = function(fieldElement) { this.setValue(fieldElement.textContent.replace(/ /g, '\n')); }; @@ -125,12 +126,13 @@ Blockly.FieldMultilineInput.prototype.fromXml = function(fieldElement) { * Create the block UI for this field. * @package */ -Blockly.FieldMultilineInput.prototype.initView = function() { +FieldMultilineInput.prototype.initView = function() { this.createBorderRect_(); - this.textGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, { + this.textGroup_ = dom.createSvgElement( + Svg.G, { 'class': 'blocklyEditableText', - }, this.fieldGroup_); + }, + this.fieldGroup_); }; /** @@ -140,17 +142,18 @@ Blockly.FieldMultilineInput.prototype.initView = function() { * @protected * @override */ -Blockly.FieldMultilineInput.prototype.getDisplayText_ = function() { - var textLines = this.getText(); +FieldMultilineInput.prototype.getDisplayText_ = function() { + let textLines = this.getText(); if (!textLines) { // Prevent the field from disappearing if empty. - return Blockly.Field.NBSP; + return Field.NBSP; } - var lines = textLines.split('\n'); + const lines = textLines.split('\n'); textLines = ''; - var displayLinesNumber = this.isOverflowedY_ ? this.maxLines_ : lines.length; - for (var i = 0; i < displayLinesNumber; i++) { - var text = lines[i]; + const displayLinesNumber = + this.isOverflowedY_ ? this.maxLines_ : lines.length; + for (let i = 0; i < displayLinesNumber; i++) { + let text = lines[i]; if (text.length > this.maxDisplayLength) { // Truncate displayed string and add an ellipsis ('...'). text = text.substring(0, this.maxDisplayLength - 4) + '...'; @@ -158,7 +161,7 @@ Blockly.FieldMultilineInput.prototype.getDisplayText_ = function() { text = text.substring(0, text.length - 3) + '...'; } // Replace whitespace with non-breaking spaces so the text doesn't collapse. - text = text.replace(/\s/g, Blockly.Field.NBSP); + text = text.replace(/\s/g, Field.NBSP); textLines += text; if (i !== displayLinesNumber - 1) { @@ -181,8 +184,8 @@ Blockly.FieldMultilineInput.prototype.getDisplayText_ = function() { * that this is a string. * @protected */ -Blockly.FieldMultilineInput.prototype.doValueUpdate_ = function(newValue) { - Blockly.FieldMultilineInput.superClass_.doValueUpdate_.call(this, newValue); +FieldMultilineInput.prototype.doValueUpdate_ = function(newValue) { + FieldMultilineInput.superClass_.doValueUpdate_.call(this, newValue); this.isOverflowedY_ = this.value_.split('\n').length > this.maxLines_; }; @@ -190,36 +193,37 @@ Blockly.FieldMultilineInput.prototype.doValueUpdate_ = function(newValue) { * Updates the text of the textElement. * @protected */ -Blockly.FieldMultilineInput.prototype.render_ = function() { +FieldMultilineInput.prototype.render_ = function() { // Remove all text group children. - var currentChild; + let currentChild; while ((currentChild = this.textGroup_.firstChild)) { this.textGroup_.removeChild(currentChild); } // Add in text elements into the group. - var lines = this.getDisplayText_().split('\n'); - var y = 0; - for (var i = 0; i < lines.length; i++) { - var lineHeight = this.getConstants().FIELD_TEXT_HEIGHT + + const lines = this.getDisplayText_().split('\n'); + let y = 0; + for (let i = 0; i < lines.length; i++) { + const lineHeight = this.getConstants().FIELD_TEXT_HEIGHT + this.getConstants().FIELD_BORDER_RECT_Y_PADDING; - var span = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.TEXT, { + const span = dom.createSvgElement( + Svg.TEXT, { 'class': 'blocklyText blocklyMultilineText', x: this.getConstants().FIELD_BORDER_RECT_X_PADDING, y: y + this.getConstants().FIELD_BORDER_RECT_Y_PADDING, dy: this.getConstants().FIELD_TEXT_BASELINE - }, this.textGroup_); + }, + this.textGroup_); span.appendChild(document.createTextNode(lines[i])); y += lineHeight; } if (this.isBeingEdited_) { - var htmlInput = /** @type {!HTMLElement} */(this.htmlInput_); + var htmlInput = /** @type {!HTMLElement} */ (this.htmlInput_); if (this.isOverflowedY_) { - Blockly.utils.dom.addClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY'); + dom.addClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY'); } else { - Blockly.utils.dom.removeClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY'); + dom.removeClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY'); } } @@ -234,15 +238,13 @@ Blockly.FieldMultilineInput.prototype.render_ = function() { } else { this.resizeEditor_(); } - var htmlInput = /** @type {!HTMLElement} */(this.htmlInput_); + var 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); } } }; @@ -251,13 +253,13 @@ Blockly.FieldMultilineInput.prototype.render_ = function() { * Updates the size of the field based on the text. * @protected */ -Blockly.FieldMultilineInput.prototype.updateSize_ = function() { - var nodes = this.textGroup_.childNodes; - var totalWidth = 0; - var totalHeight = 0; +FieldMultilineInput.prototype.updateSize_ = function() { + const nodes = this.textGroup_.childNodes; + let totalWidth = 0; + let totalHeight = 0; for (var i = 0; i < nodes.length; i++) { - var tspan = /** @type {!Element} */ (nodes[i]); - var textWidth = Blockly.utils.dom.getTextWidth(tspan); + const tspan = /** @type {!Element} */ (nodes[i]); + const textWidth = dom.getTextWidth(tspan); if (textWidth > totalWidth) { totalWidth = textWidth; } @@ -270,26 +272,28 @@ Blockly.FieldMultilineInput.prototype.updateSize_ = function() { // absolute longest line, even if it would be truncated after editing. // Otherwise we would get wrong editor width when there are more // lines than this.maxLines_. - var actualEditorLines = this.value_.split('\n'); - var dummyTextElement = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.TEXT,{'class': 'blocklyText blocklyMultilineText'}); - var fontSize = this.getConstants().FIELD_TEXT_FONTSIZE; - var fontWeight = this.getConstants().FIELD_TEXT_FONTWEIGHT; - var fontFamily = this.getConstants().FIELD_TEXT_FONTFAMILY; + const actualEditorLines = this.value_.split('\n'); + const dummyTextElement = dom.createSvgElement( + Svg.TEXT, {'class': 'blocklyText blocklyMultilineText'}); + const fontSize = this.getConstants().FIELD_TEXT_FONTSIZE; + const fontWeight = this.getConstants().FIELD_TEXT_FONTWEIGHT; + const fontFamily = this.getConstants().FIELD_TEXT_FONTFAMILY; for (var i = 0; i < actualEditorLines.length; i++) { if (actualEditorLines[i].length > this.maxDisplayLength) { - actualEditorLines[i] = actualEditorLines[i].substring(0, this.maxDisplayLength); + actualEditorLines[i] = + actualEditorLines[i].substring(0, this.maxDisplayLength); } dummyTextElement.textContent = actualEditorLines[i]; - var lineWidth = Blockly.utils.dom.getFastTextWidth( + const lineWidth = dom.getFastTextWidth( dummyTextElement, fontSize, fontWeight, fontFamily); if (lineWidth > totalWidth) { totalWidth = lineWidth; } } - var scrollbarWidth = this.htmlInput_.offsetWidth - this.htmlInput_.clientWidth; + const scrollbarWidth = + this.htmlInput_.offsetWidth - this.htmlInput_.clientWidth; totalWidth += scrollbarWidth; } if (this.borderRect_) { @@ -314,8 +318,9 @@ Blockly.FieldMultilineInput.prototype.updateSize_ = function() { * focus. Defaults to false. * @override */ -Blockly.FieldMultilineInput.prototype.showEditor_ = function(_opt_e, opt_quietInput) { - Blockly.FieldMultilineInput.superClass_.showEditor_.call(this, _opt_e, opt_quietInput); +FieldMultilineInput.prototype.showEditor_ = function(_opt_e, opt_quietInput) { + FieldMultilineInput.superClass_.showEditor_.call( + this, _opt_e, opt_quietInput); this.forceRerender(); }; @@ -324,24 +329,24 @@ Blockly.FieldMultilineInput.prototype.showEditor_ = function(_opt_e, opt_quietIn * @return {!HTMLTextAreaElement} The newly created text input editor. * @protected */ -Blockly.FieldMultilineInput.prototype.widgetCreate_ = function() { - var div = Blockly.WidgetDiv.DIV; - var scale = this.workspace_.getScale(); +FieldMultilineInput.prototype.widgetCreate_ = function() { + const div = WidgetDiv.DIV; + const scale = this.workspace_.getScale(); - var htmlInput = - /** @type {HTMLTextAreaElement} */ (document.createElement('textarea')); + const htmlInput = + /** @type {HTMLTextAreaElement} */ (document.createElement('textarea')); htmlInput.className = 'blocklyHtmlInput blocklyHtmlTextAreaInput'; htmlInput.setAttribute('spellcheck', this.spellcheck_); - var fontSize = (this.getConstants().FIELD_TEXT_FONTSIZE * scale) + 'pt'; + const fontSize = (this.getConstants().FIELD_TEXT_FONTSIZE * scale) + 'pt'; div.style.fontSize = fontSize; htmlInput.style.fontSize = fontSize; - var borderRadius = (Blockly.FieldTextInput.BORDERRADIUS * scale) + 'px'; + const borderRadius = (FieldTextInput.BORDERRADIUS * scale) + 'px'; htmlInput.style.borderRadius = borderRadius; - var paddingX = this.getConstants().FIELD_BORDER_RECT_X_PADDING * scale; - var paddingY = this.getConstants().FIELD_BORDER_RECT_Y_PADDING * scale / 2; - htmlInput.style.padding = paddingY + 'px ' + paddingX + 'px ' + paddingY + - 'px ' + paddingX + 'px'; - var lineHeight = this.getConstants().FIELD_TEXT_HEIGHT + + const paddingX = this.getConstants().FIELD_BORDER_RECT_X_PADDING * scale; + const paddingY = this.getConstants().FIELD_BORDER_RECT_Y_PADDING * scale / 2; + htmlInput.style.padding = + paddingY + 'px ' + paddingX + 'px ' + paddingY + 'px ' + paddingX + 'px'; + const lineHeight = this.getConstants().FIELD_TEXT_HEIGHT + this.getConstants().FIELD_BORDER_RECT_Y_PADDING; htmlInput.style.lineHeight = (lineHeight * scale) + 'px'; @@ -350,7 +355,7 @@ Blockly.FieldMultilineInput.prototype.widgetCreate_ = function() { htmlInput.value = htmlInput.defaultValue = this.getEditorText_(this.value_); htmlInput.untypedDefaultValue_ = this.value_; htmlInput.oldValue_ = null; - if (Blockly.utils.userAgent.GECKO) { + if (userAgent.GECKO) { // In FF, ensure the browser reflows before resizing to avoid issue #2777. setTimeout(this.resizeEditor_.bind(this), 0); } else { @@ -367,8 +372,9 @@ Blockly.FieldMultilineInput.prototype.widgetCreate_ = function() { * @param {number} maxLines Defines the maximum number of lines allowed, * before scrolling functionality is enabled. */ -Blockly.FieldMultilineInput.prototype.setMaxLines = function(maxLines) { - if (typeof maxLines === 'number' && maxLines > 0 && maxLines !== this.maxLines_) { +FieldMultilineInput.prototype.setMaxLines = function(maxLines) { + if (typeof maxLines === 'number' && maxLines > 0 && + maxLines !== this.maxLines_) { this.maxLines_ = maxLines; this.forceRerender(); } @@ -378,7 +384,7 @@ Blockly.FieldMultilineInput.prototype.setMaxLines = function(maxLines) { * Returns the maxLines config of this field. * @return {number} The maxLines config value. */ -Blockly.FieldMultilineInput.prototype.getMaxLines = function() { +FieldMultilineInput.prototype.getMaxLines = function() { return this.maxLines_; }; @@ -388,29 +394,29 @@ Blockly.FieldMultilineInput.prototype.getMaxLines = function() { * @param {!Event} e Keyboard event. * @protected */ -Blockly.FieldMultilineInput.prototype.onHtmlInputKeyDown_ = function(e) { - if (e.keyCode !== Blockly.utils.KeyCodes.ENTER) { - Blockly.FieldMultilineInput.superClass_.onHtmlInputKeyDown_.call(this, e); +FieldMultilineInput.prototype.onHtmlInputKeyDown_ = function(e) { + if (e.keyCode !== KeyCodes.ENTER) { + FieldMultilineInput.superClass_.onHtmlInputKeyDown_.call(this, e); } }; /** * CSS for multiline field. See css.js for use. */ -Blockly.Css.register([ - /* eslint-disable indent */ - '.blocklyHtmlTextAreaInput {', - 'font-family: monospace;', - 'resize: none;', - 'overflow: hidden;', - 'height: 100%;', - 'text-align: left;', - '}', - '.blocklyHtmlTextAreaInputOverflowedY {', - 'overflow-y: scroll;', - '}' - /* eslint-enable indent */ +Css.register([ + `.blocklyHtmlTextAreaInput { + font-family: monospace; + resize: none; + overflow: hidden; + height: 100%; + text-align: left; +}`, + `.blocklyHtmlTextAreaInputOverflowedY { + overflow-y: scroll; +}` ]); -Blockly.fieldRegistry.register('field_multilinetext', Blockly.FieldMultilineInput); +fieldRegistry.register('field_multilinetext', FieldMultilineInput); + +exports = FieldMultilineInput; diff --git a/core/field_number.js b/core/field_number.js index 369a161f8..8389f477f 100644 --- a/core/field_number.js +++ b/core/field_number.js @@ -10,12 +10,13 @@ */ 'use strict'; -goog.provide('Blockly.FieldNumber'); +goog.module('Blockly.FieldNumber'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.fieldRegistry'); -goog.require('Blockly.FieldTextInput'); -goog.require('Blockly.utils.aria'); -goog.require('Blockly.utils.object'); +const FieldTextInput = goog.require('Blockly.FieldTextInput'); +const aria = goog.require('Blockly.utils.aria'); +const {inherits} = goog.require('Blockly.utils.object'); +const {register} = goog.require('Blockly.fieldRegistry'); /** @@ -29,14 +30,14 @@ goog.require('Blockly.utils.object'); * changes to the field's value. Takes in a number & returns a validated * number, 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/number#creation} + * See the [field creation documentation]{@link + * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/number#creation} * for a list of properties this parameter supports. - * @extends {Blockly.FieldTextInput} + * @extends {FieldTextInput} * @constructor */ -Blockly.FieldNumber = function(opt_value, opt_min, opt_max, opt_precision, - opt_validator, opt_config) { - +const FieldNumber = function( + opt_value, opt_min, opt_max, opt_precision, opt_validator, opt_config) { /** * The minimum value this number field can contain. * @type {number} @@ -66,35 +67,35 @@ Blockly.FieldNumber = function(opt_value, opt_min, opt_max, opt_precision, */ this.decimalPlaces_ = null; - Blockly.FieldNumber.superClass_.constructor.call( + FieldNumber.superClass_.constructor.call( this, opt_value, opt_validator, opt_config); if (!opt_config) { // Only do one kind of configuration or the other. this.setConstraints(opt_min, opt_max, opt_precision); } }; -Blockly.utils.object.inherits(Blockly.FieldNumber, Blockly.FieldTextInput); +inherits(FieldNumber, FieldTextInput); /** * The default value for this field. * @type {*} * @protected */ -Blockly.FieldNumber.prototype.DEFAULT_VALUE = 0; +FieldNumber.prototype.DEFAULT_VALUE = 0; /** * Construct a FieldNumber from a JSON arg object. * @param {!Object} options A JSON object with options (value, min, max, and * precision). - * @return {!Blockly.FieldNumber} The new field instance. + * @return {!FieldNumber} The new field instance. * @package * @nocollapse */ -Blockly.FieldNumber.fromJson = function(options) { +FieldNumber.fromJson = function(options) { // `this` might be a subclass of FieldNumber if that class doesn't override // the static fromJson method. - return new this(options['value'], - undefined, undefined, undefined, undefined, options); + return new this( + options['value'], undefined, undefined, undefined, undefined, options); }; /** @@ -102,7 +103,7 @@ Blockly.FieldNumber.fromJson = function(options) { * are not. Editable fields should also be serializable. * @type {boolean} */ -Blockly.FieldNumber.prototype.SERIALIZABLE = true; +FieldNumber.prototype.SERIALIZABLE = true; /** * Configure the field based on the given map of options. @@ -110,8 +111,8 @@ Blockly.FieldNumber.prototype.SERIALIZABLE = true; * @protected * @override */ -Blockly.FieldNumber.prototype.configure_ = function(config) { - Blockly.FieldNumber.superClass_.configure_.call(this, config); +FieldNumber.prototype.configure_ = function(config) { + FieldNumber.superClass_.configure_.call(this, config); this.setMinInternal_(config['min']); this.setMaxInternal_(config['max']); this.setPrecisionInternal_(config['precision']); @@ -128,7 +129,7 @@ Blockly.FieldNumber.prototype.configure_ = function(config) { * @param {?(number|string|undefined)} max Maximum value. * @param {?(number|string|undefined)} precision Precision for value. */ -Blockly.FieldNumber.prototype.setConstraints = function(min, max, precision) { +FieldNumber.prototype.setConstraints = function(min, max, precision) { this.setMinInternal_(min); this.setMaxInternal_(max); this.setPrecisionInternal_(precision); @@ -139,7 +140,7 @@ Blockly.FieldNumber.prototype.setConstraints = function(min, max, precision) { * Sets the minimum value this field can contain. Updates the value to reflect. * @param {?(number|string|undefined)} min Minimum value. */ -Blockly.FieldNumber.prototype.setMin = function(min) { +FieldNumber.prototype.setMin = function(min) { this.setMinInternal_(min); this.setValue(this.getValue()); }; @@ -150,7 +151,7 @@ Blockly.FieldNumber.prototype.setMin = function(min) { * @param {?(number|string|undefined)} min Minimum value. * @private */ -Blockly.FieldNumber.prototype.setMinInternal_ = function(min) { +FieldNumber.prototype.setMinInternal_ = function(min) { if (min == null) { this.min_ = -Infinity; } else { @@ -166,7 +167,7 @@ Blockly.FieldNumber.prototype.setMinInternal_ = function(min) { * -Infinity. * @return {number} The current minimum value this field can contain. */ -Blockly.FieldNumber.prototype.getMin = function() { +FieldNumber.prototype.getMin = function() { return this.min_; }; @@ -174,7 +175,7 @@ Blockly.FieldNumber.prototype.getMin = function() { * Sets the maximum value this field can contain. Updates the value to reflect. * @param {?(number|string|undefined)} max Maximum value. */ -Blockly.FieldNumber.prototype.setMax = function(max) { +FieldNumber.prototype.setMax = function(max) { this.setMaxInternal_(max); this.setValue(this.getValue()); }; @@ -185,7 +186,7 @@ Blockly.FieldNumber.prototype.setMax = function(max) { * @param {?(number|string|undefined)} max Maximum value. * @private */ -Blockly.FieldNumber.prototype.setMaxInternal_ = function(max) { +FieldNumber.prototype.setMaxInternal_ = function(max) { if (max == null) { this.max_ = Infinity; } else { @@ -201,7 +202,7 @@ Blockly.FieldNumber.prototype.setMaxInternal_ = function(max) { * Infinity. * @return {number} The current maximum value this field can contain. */ -Blockly.FieldNumber.prototype.getMax = function() { +FieldNumber.prototype.getMax = function() { return this.max_; }; @@ -211,7 +212,7 @@ Blockly.FieldNumber.prototype.getMax = function() { * @param {?(number|string|undefined)} precision The number to which the * field's value is rounded. */ -Blockly.FieldNumber.prototype.setPrecision = function(precision) { +FieldNumber.prototype.setPrecision = function(precision) { this.setPrecisionInternal_(precision); this.setValue(this.getValue()); }; @@ -223,16 +224,16 @@ Blockly.FieldNumber.prototype.setPrecision = function(precision) { * field's value is rounded. * @private */ -Blockly.FieldNumber.prototype.setPrecisionInternal_ = function(precision) { +FieldNumber.prototype.setPrecisionInternal_ = function(precision) { this.precision_ = Number(precision) || 0; - var precisionString = String(this.precision_); + let precisionString = String(this.precision_); if (precisionString.indexOf('e') != -1) { // String() is fast. But it turns .0000001 into '1e-7'. // Use the much slower toLocaleString to access all the digits. precisionString = this.precision_.toLocaleString('en-US', {maximumFractionDigits: 20}); } - var decimalIndex = precisionString.indexOf('.'); + const decimalIndex = precisionString.indexOf('.'); if (decimalIndex == -1) { // If the precision is 0 (float) allow any number of decimals, // otherwise allow none. @@ -248,7 +249,7 @@ Blockly.FieldNumber.prototype.setPrecisionInternal_ = function(precision) { * the value is not rounded. * @return {number} The number to which this field's value is rounded. */ -Blockly.FieldNumber.prototype.getPrecision = function() { +FieldNumber.prototype.getPrecision = function() { return this.precision_; }; @@ -260,12 +261,12 @@ Blockly.FieldNumber.prototype.getPrecision = function() { * @protected * @override */ -Blockly.FieldNumber.prototype.doClassValidation_ = function(opt_newValue) { +FieldNumber.prototype.doClassValidation_ = function(opt_newValue) { if (opt_newValue === null) { return null; } // Clean up text. - var newValue = String(opt_newValue); + let newValue = String(opt_newValue); // TODO: Handle cases like 'ten', '1.203,14', etc. // 'O' is sometimes mistaken for '0' by inexperienced users. newValue = newValue.replace(/O/ig, '0'); @@ -275,7 +276,7 @@ Blockly.FieldNumber.prototype.doClassValidation_ = function(opt_newValue) { newValue = newValue.replace(/infinity/i, 'Infinity'); // Clean up number. - var n = Number(newValue || 0); + let n = Number(newValue || 0); if (isNaN(n)) { // Invalid number. return null; @@ -299,19 +300,19 @@ Blockly.FieldNumber.prototype.doClassValidation_ = function(opt_newValue) { * @protected * @override */ -Blockly.FieldNumber.prototype.widgetCreate_ = function() { - var htmlInput = Blockly.FieldNumber.superClass_.widgetCreate_.call(this); +FieldNumber.prototype.widgetCreate_ = function() { + const htmlInput = FieldNumber.superClass_.widgetCreate_.call(this); // Set the accessibility state if (this.min_ > -Infinity) { - Blockly.utils.aria.setState(htmlInput, - Blockly.utils.aria.State.VALUEMIN, this.min_); + aria.setState(htmlInput, aria.State.VALUEMIN, this.min_); } if (this.max_ < Infinity) { - Blockly.utils.aria.setState(htmlInput, - Blockly.utils.aria.State.VALUEMAX, this.max_); + aria.setState(htmlInput, aria.State.VALUEMAX, this.max_); } return htmlInput; }; -Blockly.fieldRegistry.register('field_number', Blockly.FieldNumber); +register('field_number', FieldNumber); + +exports = FieldNumber; diff --git a/core/field_registry.js b/core/field_registry.js index 7f431ff7d..97c149346 100644 --- a/core/field_registry.js +++ b/core/field_registry.js @@ -12,56 +12,62 @@ */ 'use strict'; -goog.provide('Blockly.fieldRegistry'); +goog.module('Blockly.fieldRegistry'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.registry'); - -goog.requireType('Blockly.Field'); -goog.requireType('Blockly.IRegistrableField'); +/* eslint-disable-next-line no-unused-vars */ +const Field = goog.requireType('Blockly.Field'); +/* eslint-disable-next-line no-unused-vars */ +const IRegistrableField = goog.requireType('Blockly.IRegistrableField'); +const registry = goog.require('Blockly.registry'); /** * Registers a field type. - * Blockly.fieldRegistry.fromJson uses this registry to + * fieldRegistry.fromJson uses this registry to * find the appropriate field type. * @param {string} type The field type name as used in the JSON definition. - * @param {!Blockly.IRegistrableField} fieldClass The field class containing a + * @param {!IRegistrableField} fieldClass The field class containing a * fromJson function that can construct an instance of the field. * @throws {Error} if the type name is empty, the field is already * registered, or the fieldClass is not an object containing a fromJson * function. */ -Blockly.fieldRegistry.register = function(type, fieldClass) { - Blockly.registry.register(Blockly.registry.Type.FIELD, type, fieldClass); +const register = function(type, fieldClass) { + registry.register(registry.Type.FIELD, type, fieldClass); }; +exports.register = register; /** * Unregisters the field registered with the given type. * @param {string} type The field type name as used in the JSON definition. */ -Blockly.fieldRegistry.unregister = function(type) { - Blockly.registry.unregister(Blockly.registry.Type.FIELD, type); +const unregister = function(type) { + registry.unregister(registry.Type.FIELD, type); }; +exports.unregister = unregister; /** * Construct a Field from a JSON arg object. * Finds the appropriate registered field by the type name as registered using - * Blockly.fieldRegistry.register. + * fieldRegistry.register. * @param {!Object} options A JSON object with a type and options specific * to the field type. - * @return {?Blockly.Field} The new field instance or null if a field wasn't + * @return {?Field} The new field instance or null if a field wasn't * found with the given type name - * @package */ -Blockly.fieldRegistry.fromJson = function(options) { - var fieldObject = /** @type {?Blockly.IRegistrableField} */ ( - Blockly.registry.getObject(Blockly.registry.Type.FIELD, options['type'])); +const fromJson = function(options) { + const fieldObject = /** @type {?IRegistrableField} */ ( + registry.getObject(registry.Type.FIELD, options['type'])); if (!fieldObject) { - console.warn('Blockly could not create a field of type ' + options['type'] + - '. The field is probably not being registered. This could be because' + - ' the file is not loaded, the field does not register itself (Issue' + - ' #1584), or the registration is not being reached.'); + console.warn( + 'Blockly could not create a field of type ' + options['type'] + + '. The field is probably not being registered. This could be because' + + ' the file is not loaded, the field does not register itself (Issue' + + ' #1584), or the registration is not being reached.'); return null; } return fieldObject.fromJson(options); }; +/** @package */ +exports.fromJson = fromJson; 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 18f2d20b4..f700d4a99 100644 --- a/core/field_variable.js +++ b/core/field_variable.js @@ -10,26 +10,24 @@ */ 'use strict'; -goog.provide('Blockly.FieldVariable'); +goog.module('Blockly.FieldVariable'); +goog.module.declareLegacyNamespace(); -/** @suppress {extraRequire} */ -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); +const Block = goog.requireType('Blockly.Block'); +const FieldDropdown = goog.require('Blockly.FieldDropdown'); +const Menu = goog.requireType('Blockly.Menu'); +const MenuItem = goog.requireType('Blockly.MenuItem'); +const Msg = goog.require('Blockly.Msg'); +const Size = goog.require('Blockly.utils.Size'); +const VariableModel = goog.require('Blockly.VariableModel'); +const Variables = goog.require('Blockly.Variables'); +const Xml = goog.require('Blockly.Xml'); +const fieldRegistry = goog.require('Blockly.fieldRegistry'); +const internalConstants = goog.require('Blockly.internalConstants'); +const {inherits} = goog.require('Blockly.utils.object'); +const {replaceMessageReferences} = goog.require('Blockly.utils'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockChange'); -goog.require('Blockly.FieldDropdown'); -goog.require('Blockly.fieldRegistry'); -goog.require('Blockly.Msg'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.object'); -goog.require('Blockly.utils.Size'); -goog.require('Blockly.VariableModel'); -goog.require('Blockly.Variables'); -goog.require('Blockly.Xml'); - -goog.requireType('Blockly.Block'); -goog.requireType('Blockly.Menu'); -goog.requireType('Blockly.MenuItem'); /** @@ -44,13 +42,14 @@ goog.requireType('Blockly.MenuItem'); * @param {string=} opt_defaultType The type of variable to create if this * field's value is not explicitly set. Defaults to ''. * @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/variable#creation} + * See the [field creation documentation]{@link + * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/variable#creation} * for a list of properties this parameter supports. - * @extends {Blockly.FieldDropdown} + * @extends {FieldDropdown} * @constructor */ -Blockly.FieldVariable = function(varName, opt_validator, opt_variableTypes, - opt_defaultType, opt_config) { +const FieldVariable = function( + varName, opt_validator, opt_variableTypes, opt_defaultType, opt_config) { // The FieldDropdown constructor expects the field's initial value to be // the first entry in the menu generator, which it may or may not be. // Just do the relevant parts of the constructor. @@ -59,10 +58,10 @@ Blockly.FieldVariable = function(varName, opt_validator, opt_variableTypes, * An array of options for a dropdown list, * or a function which generates these options. * @type {(!Array| - * !function(this:Blockly.FieldDropdown): !Array)} + * !function(this:FieldDropdown): !Array)} * @protected */ - this.menuGenerator_ = Blockly.FieldVariable.dropdownCreate; + this.menuGenerator_ = FieldVariable.dropdownCreate; /** * The initial variable name passed to this field's constructor, or an @@ -74,11 +73,11 @@ Blockly.FieldVariable = function(varName, opt_validator, opt_variableTypes, /** * The size of the area rendered by the field. - * @type {Blockly.utils.Size} + * @type {Size} * @protected * @override */ - this.size_ = new Blockly.utils.Size(0, 0); + this.size_ = new Size(0, 0); opt_config && this.configure_(opt_config); opt_validator && this.setValidator(opt_validator); @@ -87,19 +86,19 @@ Blockly.FieldVariable = function(varName, opt_validator, opt_variableTypes, this.setTypes_(opt_variableTypes, opt_defaultType); } }; -Blockly.utils.object.inherits(Blockly.FieldVariable, Blockly.FieldDropdown); +inherits(FieldVariable, FieldDropdown); /** * Construct a FieldVariable from a JSON arg object, * dereferencing any string table references. * @param {!Object} options A JSON object with options (variable, * variableTypes, and defaultType). - * @return {!Blockly.FieldVariable} The new field instance. + * @return {!FieldVariable} The new field instance. * @package * @nocollapse */ -Blockly.FieldVariable.fromJson = function(options) { - var varName = Blockly.utils.replaceMessageReferences(options['variable']); +FieldVariable.fromJson = function(options) { + const varName = replaceMessageReferences(options['variable']); // `this` might be a subclass of FieldVariable if that class doesn't override // the static fromJson method. return new this(varName, undefined, undefined, undefined, options); @@ -110,15 +109,15 @@ Blockly.FieldVariable.fromJson = function(options) { * are not. Editable fields should also be serializable. * @type {boolean} */ -Blockly.FieldVariable.prototype.SERIALIZABLE = true; +FieldVariable.prototype.SERIALIZABLE = true; /** * Configure the field based on the given map of options. * @param {!Object} config A map of options to configure the field based on. * @protected */ -Blockly.FieldVariable.prototype.configure_ = function(config) { - Blockly.FieldVariable.superClass_.configure_.call(this, config); +FieldVariable.prototype.configure_ = function(config) { + FieldVariable.superClass_.configure_.call(this, config); this.setTypes_(config['variableTypes'], config['defaultType']); }; @@ -128,13 +127,13 @@ Blockly.FieldVariable.prototype.configure_ = function(config) { * variable rather than let the value be invalid. * @package */ -Blockly.FieldVariable.prototype.initModel = function() { +FieldVariable.prototype.initModel = function() { if (this.variable_) { return; // Initialization already happened. } - var variable = Blockly.Variables.getOrCreateVariablePackage( - this.sourceBlock_.workspace, null, - this.defaultVariableName, this.defaultType_); + const variable = Variables.getOrCreateVariablePackage( + this.sourceBlock_.workspace, null, this.defaultVariableName, + this.defaultType_); // Don't call setValue because we don't want to cause a rerender. this.doValueUpdate_(variable.getId()); @@ -143,10 +142,10 @@ Blockly.FieldVariable.prototype.initModel = function() { /** * @override */ -Blockly.FieldVariable.prototype.shouldAddBorderRect_ = function() { - return Blockly.FieldVariable.superClass_.shouldAddBorderRect_.call(this) && - (!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW || - this.sourceBlock_.type != 'variables_get'); +FieldVariable.prototype.shouldAddBorderRect_ = function() { + return FieldVariable.superClass_.shouldAddBorderRect_.call(this) && + (!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW || + this.sourceBlock_.type != 'variables_get'); }; /** @@ -154,23 +153,24 @@ Blockly.FieldVariable.prototype.shouldAddBorderRect_ = function() { * @param {!Element} fieldElement The element containing information about the * variable field's state. */ -Blockly.FieldVariable.prototype.fromXml = function(fieldElement) { - var id = fieldElement.getAttribute('id'); - var variableName = fieldElement.textContent; +FieldVariable.prototype.fromXml = function(fieldElement) { + const id = fieldElement.getAttribute('id'); + const variableName = fieldElement.textContent; // 'variabletype' should be lowercase, but until July 2019 it was sometimes // recorded as 'variableType'. Thus we need to check for both. - var variableType = fieldElement.getAttribute('variabletype') || + const variableType = fieldElement.getAttribute('variabletype') || fieldElement.getAttribute('variableType') || ''; - var variable = Blockly.Variables.getOrCreateVariablePackage( + const variable = Variables.getOrCreateVariablePackage( this.sourceBlock_.workspace, id, variableName, variableType); // This should never happen :) if (variableType != null && variableType !== variable.type) { - throw Error('Serialized variable type with id \'' + - variable.getId() + '\' had type ' + variable.type + ', and ' + - 'does not match variable field that references it: ' + - Blockly.Xml.domToText(fieldElement) + '.'); + throw Error( + 'Serialized variable type with id \'' + variable.getId() + + '\' had type ' + variable.type + ', and ' + + 'does not match variable field that references it: ' + + Xml.domToText(fieldElement) + '.'); } this.setValue(variable.getId()); @@ -182,7 +182,7 @@ Blockly.FieldVariable.prototype.fromXml = function(fieldElement) { * field's state. * @return {!Element} The element containing info about the field's state. */ -Blockly.FieldVariable.prototype.toXml = function(fieldElement) { +FieldVariable.prototype.toXml = function(fieldElement) { // Make sure the variable is initialized. this.initModel(); @@ -196,20 +196,20 @@ Blockly.FieldVariable.prototype.toXml = function(fieldElement) { /** * Attach this field to a block. - * @param {!Blockly.Block} block The block containing this field. + * @param {!Block} block The block containing this field. */ -Blockly.FieldVariable.prototype.setSourceBlock = function(block) { +FieldVariable.prototype.setSourceBlock = function(block) { if (block.isShadow()) { throw Error('Variable fields are not allowed to exist on shadow blocks.'); } - Blockly.FieldVariable.superClass_.setSourceBlock.call(this, block); + FieldVariable.superClass_.setSourceBlock.call(this, block); }; /** * Get the variable's ID. * @return {string} Current variable's ID. */ -Blockly.FieldVariable.prototype.getValue = function() { +FieldVariable.prototype.getValue = function() { return this.variable_ ? this.variable_.getId() : null; }; @@ -218,7 +218,7 @@ Blockly.FieldVariable.prototype.getValue = function() { * @return {string} The selected variable's name, or the empty string if no * variable is selected. */ -Blockly.FieldVariable.prototype.getText = function() { +FieldVariable.prototype.getText = function() { return this.variable_ ? this.variable_.name : ''; }; @@ -226,11 +226,11 @@ Blockly.FieldVariable.prototype.getText = function() { * Get the variable model for the selected variable. * Not guaranteed to be in the variable map on the workspace (e.g. if accessed * after the variable has been deleted). - * @return {?Blockly.VariableModel} The selected variable, or null if none was + * @return {?VariableModel} The selected variable, or null if none was * selected. * @package */ -Blockly.FieldVariable.prototype.getVariable = function() { +FieldVariable.prototype.getVariable = function() { return this.variable_; }; @@ -241,7 +241,7 @@ Blockly.FieldVariable.prototype.getVariable = function() { * a block and workspace at that point. * @return {?Function} Validation function, or null. */ -Blockly.FieldVariable.prototype.getValidator = function() { +FieldVariable.prototype.getValidator = function() { // Validators shouldn't operate on the initial setValue call. // Normally this is achieved by calling setValidator after setValue, but // this is not a possibility with variable fields. @@ -257,20 +257,20 @@ Blockly.FieldVariable.prototype.getValidator = function() { * @return {?string} The validated ID, or null if invalid. * @protected */ -Blockly.FieldVariable.prototype.doClassValidation_ = function(opt_newValue) { +FieldVariable.prototype.doClassValidation_ = function(opt_newValue) { if (opt_newValue === null) { return null; } - var newId = /** @type {string} */ (opt_newValue); - var variable = Blockly.Variables.getVariable( - this.sourceBlock_.workspace, newId); + const newId = /** @type {string} */ (opt_newValue); + const variable = Variables.getVariable(this.sourceBlock_.workspace, newId); if (!variable) { - console.warn('Variable id doesn\'t point to a real variable! ' + + console.warn( + 'Variable id doesn\'t point to a real variable! ' + 'ID was ' + newId); return null; } // Type Checks. - var type = variable.type; + const type = variable.type; if (!this.typeIsAllowed_(type)) { console.warn('Variable type doesn\'t match this field! Type was ' + type); return null; @@ -286,10 +286,10 @@ Blockly.FieldVariable.prototype.doClassValidation_ = function(opt_newValue) { * @param {*} newId The value to be saved. * @protected */ -Blockly.FieldVariable.prototype.doValueUpdate_ = function(newId) { - this.variable_ = Blockly.Variables.getVariable( +FieldVariable.prototype.doValueUpdate_ = function(newId) { + this.variable_ = Variables.getVariable( this.sourceBlock_.workspace, /** @type {string} */ (newId)); - Blockly.FieldVariable.superClass_.doValueUpdate_.call(this, newId); + FieldVariable.superClass_.doValueUpdate_.call(this, newId); }; /** @@ -298,12 +298,12 @@ Blockly.FieldVariable.prototype.doValueUpdate_ = function(newId) { * @return {boolean} True if the type is in the list of allowed types. * @private */ -Blockly.FieldVariable.prototype.typeIsAllowed_ = function(type) { - var typeList = this.getVariableTypes_(); +FieldVariable.prototype.typeIsAllowed_ = function(type) { + const typeList = this.getVariableTypes_(); if (!typeList) { return true; // If it's null, all types are valid. } - for (var i = 0; i < typeList.length; i++) { + for (let i = 0; i < typeList.length; i++) { if (type == typeList[i]) { return true; } @@ -317,9 +317,9 @@ Blockly.FieldVariable.prototype.typeIsAllowed_ = function(type) { * @throws {Error} if variableTypes is an empty array. * @private */ -Blockly.FieldVariable.prototype.getVariableTypes_ = function() { +FieldVariable.prototype.getVariableTypes_ = function() { // TODO (#1513): Try to avoid calling this every time the field is edited. - var variableTypes = this.variableTypes; + let variableTypes = this.variableTypes; if (variableTypes === null) { // If variableTypes is null, return all variable types. if (this.sourceBlock_ && this.sourceBlock_.workspace) { @@ -329,9 +329,9 @@ Blockly.FieldVariable.prototype.getVariableTypes_ = function() { variableTypes = variableTypes || ['']; if (variableTypes.length == 0) { // Throw an error if variableTypes is an empty list. - var name = this.getText(); - throw Error('\'variableTypes\' of field variable ' + - name + ' was an empty list'); + const name = this.getText(); + throw Error( + '\'variableTypes\' of field variable ' + name + ' was an empty list'); } return variableTypes; }; @@ -346,29 +346,32 @@ Blockly.FieldVariable.prototype.getVariableTypes_ = function() { * field's value is not explicitly set. Defaults to ''. * @private */ -Blockly.FieldVariable.prototype.setTypes_ = function(opt_variableTypes, - opt_defaultType) { +FieldVariable.prototype.setTypes_ = function( + opt_variableTypes, opt_defaultType) { // If you expected that the default type would be the same as the only entry // in the variable types array, tell the Blockly team by commenting on #1499. - var defaultType = opt_defaultType || ''; + const defaultType = opt_defaultType || ''; + let variableTypes; // Set the allowable variable types. Null means all types on the workspace. if (opt_variableTypes == null || opt_variableTypes == undefined) { - var variableTypes = null; + variableTypes = null; } else if (Array.isArray(opt_variableTypes)) { - var variableTypes = opt_variableTypes; + variableTypes = opt_variableTypes; // Make sure the default type is valid. - var isInArray = false; - for (var i = 0; i < variableTypes.length; i++) { + let isInArray = false; + for (let i = 0; i < variableTypes.length; i++) { if (variableTypes[i] == defaultType) { isInArray = true; } } if (!isInArray) { - throw Error('Invalid default type \'' + defaultType + '\' in ' + + throw Error( + 'Invalid default type \'' + defaultType + '\' in ' + 'the definition of a FieldVariable'); } } else { - throw Error('\'variableTypes\' was not an array in the definition of ' + + throw Error( + '\'variableTypes\' was not an array in the definition of ' + 'a FieldVariable'); } // Only update the field once all checks pass. @@ -382,7 +385,7 @@ Blockly.FieldVariable.prototype.setTypes_ = function(opt_variableTypes, * be called by the block. * @package */ -Blockly.FieldVariable.prototype.refreshVariableName = function() { +FieldVariable.prototype.refreshVariableName = function() { this.forceRerender(); }; @@ -390,41 +393,40 @@ Blockly.FieldVariable.prototype.refreshVariableName = function() { * Return a sorted list of variable names for variable dropdown menus. * Include a special option at the end for creating a new variable name. * @return {!Array} Array of variable names/id tuples. - * @this {Blockly.FieldVariable} + * @this {FieldVariable} */ -Blockly.FieldVariable.dropdownCreate = function() { +FieldVariable.dropdownCreate = function() { if (!this.variable_) { - throw Error('Tried to call dropdownCreate on a variable field with no' + + throw Error( + 'Tried to call dropdownCreate on a variable field with no' + ' variable selected.'); } - var name = this.getText(); - var variableModelList = []; + const name = this.getText(); + let variableModelList = []; if (this.sourceBlock_ && this.sourceBlock_.workspace) { - var variableTypes = this.getVariableTypes_(); + const variableTypes = this.getVariableTypes_(); // Get a copy of the list, so that adding rename and new variable options // doesn't modify the workspace's list. - for (var i = 0; i < variableTypes.length; i++) { - var variableType = variableTypes[i]; - var variables = - this.sourceBlock_.workspace.getVariablesOfType(variableType); + for (let i = 0; i < variableTypes.length; i++) { + const variableType = variableTypes[i]; + const variables = + this.sourceBlock_.workspace.getVariablesOfType(variableType); variableModelList = variableModelList.concat(variables); } } - variableModelList.sort(Blockly.VariableModel.compareByName); + variableModelList.sort(VariableModel.compareByName); - var options = []; - for (var i = 0; i < variableModelList.length; i++) { + const options = []; + for (let i = 0; i < variableModelList.length; i++) { // Set the UUID as the internal representation of the variable. options[i] = [variableModelList[i].name, variableModelList[i].getId()]; } - options.push([Blockly.Msg['RENAME_VARIABLE'], Blockly.RENAME_VARIABLE_ID]); - if (Blockly.Msg['DELETE_VARIABLE']) { - options.push( - [ - Blockly.Msg['DELETE_VARIABLE'].replace('%1', name), - Blockly.DELETE_VARIABLE_ID - ] - ); + options.push([Msg['RENAME_VARIABLE'], internalConstants.RENAME_VARIABLE_ID]); + if (Msg['DELETE_VARIABLE']) { + options.push([ + Msg['DELETE_VARIABLE'].replace('%1', name), + internalConstants.DELETE_VARIABLE_ID + ]); } return options; @@ -434,20 +436,19 @@ Blockly.FieldVariable.dropdownCreate = function() { * Handle the selection of an item in the variable dropdown menu. * Special case the 'Rename variable...' and 'Delete variable...' options. * In the rename case, prompt the user for a new name. - * @param {!Blockly.Menu} menu The Menu component clicked. - * @param {!Blockly.MenuItem} menuItem The MenuItem selected within menu. + * @param {!Menu} menu The Menu component clicked. + * @param {!MenuItem} menuItem The MenuItem selected within menu. * @protected */ -Blockly.FieldVariable.prototype.onItemSelected_ = function(menu, menuItem) { - var id = menuItem.getValue(); +FieldVariable.prototype.onItemSelected_ = function(menu, menuItem) { + const id = menuItem.getValue(); // Handle special cases. if (this.sourceBlock_ && this.sourceBlock_.workspace) { - if (id == Blockly.RENAME_VARIABLE_ID) { + if (id == internalConstants.RENAME_VARIABLE_ID) { // Rename variable. - Blockly.Variables.renameVariable( - this.sourceBlock_.workspace, this.variable_); + Variables.renameVariable(this.sourceBlock_.workspace, this.variable_); return; - } else if (id == Blockly.DELETE_VARIABLE_ID) { + } else if (id == internalConstants.DELETE_VARIABLE_ID) { // Delete variable. this.sourceBlock_.workspace.deleteVariableById(this.variable_.getId()); return; @@ -463,8 +464,10 @@ Blockly.FieldVariable.prototype.onItemSelected_ = function(menu, menuItem) { * @package * @override */ -Blockly.FieldVariable.prototype.referencesVariables = function() { +FieldVariable.prototype.referencesVariables = function() { return true; }; -Blockly.fieldRegistry.register('field_variable', Blockly.FieldVariable); +fieldRegistry.register('field_variable', FieldVariable); + +exports = FieldVariable; 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_horizontal.js b/core/flyout_horizontal.js index 485d29617..7f1ad72fd 100644 --- a/core/flyout_horizontal.js +++ b/core/flyout_horizontal.js @@ -10,38 +10,36 @@ */ 'use strict'; -goog.provide('Blockly.HorizontalFlyout'); +goog.module('Blockly.HorizontalFlyout'); +goog.module.declareLegacyNamespace(); -/** @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'); +/* 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'); /** * 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.HorizontalFlyout = function(workspaceOptions) { - Blockly.HorizontalFlyout.superClass_.constructor.call(this, workspaceOptions); +const HorizontalFlyout = function(workspaceOptions) { + HorizontalFlyout.superClass_.constructor.call(this, workspaceOptions); this.horizontalLayout = true; }; -Blockly.utils.object.inherits(Blockly.HorizontalFlyout, Blockly.Flyout); +inherits(HorizontalFlyout, Flyout); /** * Sets the translation of the flyout to match the scrollbars. @@ -50,23 +48,24 @@ Blockly.utils.object.inherits(Blockly.HorizontalFlyout, Blockly.Flyout); * similar x property. * @protected */ -Blockly.HorizontalFlyout.prototype.setMetrics_ = function(xyRatio) { +HorizontalFlyout.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.x == 'number') { this.workspace_.scrollX = -(scrollMetrics.left + - (scrollMetrics.width - viewMetrics.width) * xyRatio.x); + (scrollMetrics.width - viewMetrics.width) * xyRatio.x); } - this.workspace_.translate(this.workspace_.scrollX + absoluteMetrics.left, + this.workspace_.translate( + this.workspace_.scrollX + absoluteMetrics.left, this.workspace_.scrollY + absoluteMetrics.top); }; @@ -74,7 +73,7 @@ Blockly.HorizontalFlyout.prototype.setMetrics_ = function(xyRatio) { * Calculates the x coordinate for the flyout position. * @return {number} X coordinate. */ -Blockly.HorizontalFlyout.prototype.getX = function() { +HorizontalFlyout.prototype.getX = function() { // X is always 0 since this is a horizontal flyout. return 0; }; @@ -83,17 +82,17 @@ Blockly.HorizontalFlyout.prototype.getX = function() { * Calculates the y coordinate for the flyout position. * @return {number} Y coordinate. */ -Blockly.HorizontalFlyout.prototype.getY = function() { +HorizontalFlyout.prototype.getY = function() { if (!this.isVisible()) { return 0; } - var metricsManager = this.targetWorkspace.getMetricsManager(); - var absoluteMetrics = metricsManager.getAbsoluteMetrics(); - var viewMetrics = metricsManager.getViewMetrics(); - var toolboxMetrics = metricsManager.getToolboxMetrics(); + const metricsManager = this.targetWorkspace.getMetricsManager(); + const absoluteMetrics = metricsManager.getAbsoluteMetrics(); + const viewMetrics = metricsManager.getViewMetrics(); + const toolboxMetrics = metricsManager.getToolboxMetrics(); - var y = 0; - var atTop = this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP; + let y = 0; + const atTop = this.toolboxPosition_ == Position.TOP; // 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. @@ -131,22 +130,22 @@ Blockly.HorizontalFlyout.prototype.getY = function() { /** * Move the flyout to the edge of the workspace. */ -Blockly.HorizontalFlyout.prototype.position = function() { +HorizontalFlyout.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 width for workspace metrics. this.width_ = targetWorkspaceViewMetrics.width; - var edgeWidth = targetWorkspaceViewMetrics.width - 2 * this.CORNER_RADIUS; - var edgeHeight = this.height_ - this.CORNER_RADIUS; + const edgeWidth = targetWorkspaceViewMetrics.width - 2 * this.CORNER_RADIUS; + const edgeHeight = this.height_ - 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); }; @@ -159,11 +158,10 @@ Blockly.HorizontalFlyout.prototype.position = function() { * rounded corners. * @private */ -Blockly.HorizontalFlyout.prototype.setBackgroundPath_ = function( - width, height) { - var atTop = this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP; +HorizontalFlyout.prototype.setBackgroundPath_ = function(width, height) { + const atTop = this.toolboxPosition_ == Position.TOP; // Start at top left. - var path = ['M 0,' + (atTop ? 0 : this.CORNER_RADIUS)]; + const path = ['M 0,' + (atTop ? 0 : this.CORNER_RADIUS)]; if (atTop) { // Top. @@ -171,20 +169,24 @@ Blockly.HorizontalFlyout.prototype.setBackgroundPath_ = function( // Right. path.push('v', height); // Bottom. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, + path.push( + 'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, -this.CORNER_RADIUS, this.CORNER_RADIUS); path.push('h', -width); // Left. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, + path.push( + 'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, -this.CORNER_RADIUS, -this.CORNER_RADIUS); path.push('z'); } else { // Top. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, + path.push( + 'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, this.CORNER_RADIUS, -this.CORNER_RADIUS); path.push('h', width); // Right. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, + path.push( + 'a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, this.CORNER_RADIUS, this.CORNER_RADIUS); path.push('v', height); // Bottom. @@ -198,7 +200,7 @@ Blockly.HorizontalFlyout.prototype.setBackgroundPath_ = function( /** * Scroll the flyout to the top. */ -Blockly.HorizontalFlyout.prototype.scrollToStart = function() { +HorizontalFlyout.prototype.scrollToStart = function() { this.workspace_.scrollbar.setX(this.RTL ? Infinity : 0); }; @@ -207,20 +209,20 @@ Blockly.HorizontalFlyout.prototype.scrollToStart = function() { * @param {!Event} e Mouse wheel scroll event. * @protected */ -Blockly.HorizontalFlyout.prototype.wheel_ = function(e) { - var scrollDelta = Blockly.utils.getScrollDeltaPixels(e); - var delta = scrollDelta.x || scrollDelta.y; +HorizontalFlyout.prototype.wheel_ = function(e) { + const scrollDelta = getScrollDeltaPixels(e); + const delta = scrollDelta.x || scrollDelta.y; if (delta) { - var metricsManager = this.workspace_.getMetricsManager(); - var scrollMetrics = metricsManager.getScrollMetrics(); - var viewMetrics = metricsManager.getViewMetrics(); + const metricsManager = this.workspace_.getMetricsManager(); + const scrollMetrics = metricsManager.getScrollMetrics(); + const viewMetrics = metricsManager.getViewMetrics(); - var pos = (viewMetrics.left - scrollMetrics.left) + delta; + const pos = (viewMetrics.left - scrollMetrics.left) + delta; this.workspace_.scrollbar.setX(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. @@ -235,39 +237,40 @@ Blockly.HorizontalFlyout.prototype.wheel_ = function(e) { * @param {!Array} gaps The visible gaps between blocks. * @protected */ -Blockly.HorizontalFlyout.prototype.layout_ = function(contents, gaps) { +HorizontalFlyout.prototype.layout_ = function(contents, gaps) { this.workspace_.scale = this.targetWorkspace.scale; - var margin = this.MARGIN; - var cursorX = margin + this.tabWidth_; - var cursorY = margin; + const margin = this.MARGIN; + let cursorX = margin + this.tabWidth_; + const cursorY = margin; if (this.RTL) { contents = contents.reverse(); } - 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(); + const root = block.getSvgRoot(); + const blockHW = block.getHeightWidth(); // Figure out where to place the block. - var tab = block.outputConnection ? this.tabWidth_ : 0; + const tab = block.outputConnection ? this.tabWidth_ : 0; + let moveX; if (this.RTL) { - var moveX = cursorX + blockHW.width; + moveX = cursorX + blockHW.width; } else { - var moveX = cursorX - tab; + moveX = cursorX - tab; } block.moveBy(moveX, cursorY); - var rect = this.createRect_(block, moveX, cursorY, blockHW, i); + const rect = this.createRect_(block, moveX, cursorY, blockHW, i); cursorX += (blockHW.width + gaps[i]); this.addBlockListeners_(root, block, rect); @@ -282,19 +285,19 @@ Blockly.HorizontalFlyout.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.HorizontalFlyout.prototype.isDragTowardWorkspace = function( +HorizontalFlyout.prototype.isDragTowardWorkspace = function( currentDragDeltaXY) { - var dx = currentDragDeltaXY.x; - var dy = currentDragDeltaXY.y; + 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 up or down dragging. if ((dragDirection < 90 + range && dragDirection > 90 - range) || (dragDirection > -90 - range && dragDirection < -90 + range)) { @@ -306,28 +309,28 @@ Blockly.HorizontalFlyout.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.HorizontalFlyout.prototype.getClientRect = function() { +HorizontalFlyout.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 top = flyoutRect.top; + const BIG_NUM = 1000000000; + const top = flyoutRect.top; - if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP) { - var height = flyoutRect.height; - return new Blockly.utils.Rect(-BIG_NUM, top + height, -BIG_NUM, BIG_NUM); + if (this.toolboxPosition_ == Position.TOP) { + const height = flyoutRect.height; + return new Rect(-BIG_NUM, top + height, -BIG_NUM, BIG_NUM); } else { // Bottom. - return new Blockly.utils.Rect(top, BIG_NUM, -BIG_NUM, BIG_NUM); + return new Rect(top, BIG_NUM, -BIG_NUM, BIG_NUM); } }; @@ -336,36 +339,37 @@ Blockly.HorizontalFlyout.prototype.getClientRect = function() { * For RTL: Lay out the blocks right-aligned. * @protected */ -Blockly.HorizontalFlyout.prototype.reflowInternal_ = function() { +HorizontalFlyout.prototype.reflowInternal_ = function() { this.workspace_.scale = this.getFlyoutScale(); - var flyoutHeight = 0; - var blocks = this.workspace_.getTopBlocks(false); - for (var i = 0, block; (block = blocks[i]); i++) { + let flyoutHeight = 0; + const blocks = this.workspace_.getTopBlocks(false); + for (let i = 0, block; (block = blocks[i]); i++) { flyoutHeight = Math.max(flyoutHeight, block.getHeightWidth().height); } - var buttons = this.buttons_; - for (var i = 0, button; (button = buttons[i]); i++) { + const buttons = this.buttons_; + for (let i = 0, button; (button = buttons[i]); i++) { flyoutHeight = Math.max(flyoutHeight, button.height); } flyoutHeight += this.MARGIN * 1.5; flyoutHeight *= this.workspace_.scale; - flyoutHeight += Blockly.Scrollbar.scrollbarThickness; + flyoutHeight += Scrollbar.scrollbarThickness; if (this.height_ != flyoutHeight) { - for (var i = 0, block; (block = blocks[i]); i++) { + for (let i = 0, block; (block = blocks[i]); i++) { if (block.flyoutRect_) { this.moveRectToBlock_(block.flyoutRect_, block); } } if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_ && - this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP && + this.toolboxPosition_ == Position.TOP && !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, this.targetWorkspace.scrollY + flyoutHeight); + this.targetWorkspace.scrollX, + this.targetWorkspace.scrollY + flyoutHeight); } // Record the height for workspace metrics and .position. @@ -375,5 +379,8 @@ Blockly.HorizontalFlyout.prototype.reflowInternal_ = function() { } }; -Blockly.registry.register(Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX, - Blockly.registry.DEFAULT, Blockly.HorizontalFlyout); +registry.register( + registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX, registry.DEFAULT, + HorizontalFlyout); + +exports = HorizontalFlyout; 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/generator.js b/core/generator.js index d2af08852..112c2f8a1 100644 --- a/core/generator.js +++ b/core/generator.js @@ -11,15 +11,18 @@ */ 'use strict'; -goog.provide('Blockly.Generator'); +goog.module('Blockly.Generator'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Block'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); -goog.require('Blockly.utils.deprecation'); - -goog.requireType('Blockly.Names'); -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 Names = goog.requireType('Blockly.Names'); +/* eslint-disable-next-line no-unused-vars */ +const Workspace = goog.requireType('Blockly.Workspace'); +const internalConstants = goog.require('Blockly.internalConstants'); +const deprecation = goog.require('Blockly.utils.deprecation'); +const {getMainWorkspace} = goog.require('Blockly'); /** @@ -27,7 +30,7 @@ goog.requireType('Blockly.Workspace'); * @param {string} name Language name of this generator. * @constructor */ -Blockly.Generator = function(name) { +const Generator = function(name) { this.name_ = name; this.FUNCTION_NAME_PLACEHOLDER_REGEXP_ = new RegExp(this.FUNCTION_NAME_PLACEHOLDER_, 'g'); @@ -39,7 +42,7 @@ Blockly.Generator = function(name) { * E.g. ' checkTimeout(%1);\n' * @type {?string} */ -Blockly.Generator.prototype.INFINITE_LOOP_TRAP = null; +Generator.prototype.INFINITE_LOOP_TRAP = null; /** * Arbitrary code to inject before every statement. @@ -47,7 +50,7 @@ Blockly.Generator.prototype.INFINITE_LOOP_TRAP = null; * E.g. 'highlight(%1);\n' * @type {?string} */ -Blockly.Generator.prototype.STATEMENT_PREFIX = null; +Generator.prototype.STATEMENT_PREFIX = null; /** * Arbitrary code to inject after every statement. @@ -55,27 +58,27 @@ Blockly.Generator.prototype.STATEMENT_PREFIX = null; * E.g. 'highlight(%1);\n' * @type {?string} */ -Blockly.Generator.prototype.STATEMENT_SUFFIX = null; +Generator.prototype.STATEMENT_SUFFIX = null; /** * The method of indenting. Defaults to two spaces, but language generators * may override this to increase indent or change to tabs. * @type {string} */ -Blockly.Generator.prototype.INDENT = ' '; +Generator.prototype.INDENT = ' '; /** * Maximum length for a comment before wrapping. Does not account for * indenting level. * @type {number} */ -Blockly.Generator.prototype.COMMENT_WRAP = 60; +Generator.prototype.COMMENT_WRAP = 60; /** * List of outer-inner pairings that do NOT require parentheses. * @type {!Array>} */ -Blockly.Generator.prototype.ORDER_OVERRIDES = []; +Generator.prototype.ORDER_OVERRIDES = []; /** * Whether the init method has been called. @@ -84,24 +87,24 @@ Blockly.Generator.prototype.ORDER_OVERRIDES = []; * initialized. If this flag is untouched, it will have no effect. * @type {?boolean} */ -Blockly.Generator.prototype.isInitialized = null; +Generator.prototype.isInitialized = null; /** * Generate code for all blocks in the workspace to the specified language. - * @param {!Blockly.Workspace=} workspace Workspace to generate code from. + * @param {!Workspace=} workspace Workspace to generate code from. * @return {string} Generated code. */ -Blockly.Generator.prototype.workspaceToCode = function(workspace) { +Generator.prototype.workspaceToCode = function(workspace) { if (!workspace) { // Backwards compatibility from before there could be multiple workspaces. console.warn('No workspace specified in workspaceToCode call. Guessing.'); - workspace = Blockly.getMainWorkspace(); + workspace = getMainWorkspace(); } - var code = []; + let code = []; this.init(workspace); - var blocks = workspace.getTopBlocks(true); - for (var i = 0, block; (block = blocks[i]); i++) { - var line = this.blockToCode(block); + const blocks = workspace.getTopBlocks(true); + for (let i = 0, block; (block = blocks[i]); i++) { + let line = this.blockToCode(block); if (Array.isArray(line)) { // Value blocks return tuples of code and operator order. // Top-level blocks don't care about operator order. @@ -141,20 +144,20 @@ Blockly.Generator.prototype.workspaceToCode = function(workspace) { * @param {string} prefix The common prefix. * @return {string} The prefixed lines of code. */ -Blockly.Generator.prototype.prefixLines = function(text, prefix) { +Generator.prototype.prefixLines = function(text, prefix) { return prefix + text.replace(/(?!\n$)\n/g, '\n' + prefix); }; /** * Recursively spider a tree of blocks, returning all their comments. - * @param {!Blockly.Block} block The block from which to start spidering. + * @param {!Block} block The block from which to start spidering. * @return {string} Concatenated list of comments. */ -Blockly.Generator.prototype.allNestedComments = function(block) { - var comments = []; - var blocks = block.getDescendants(true); - for (var i = 0; i < blocks.length; i++) { - var comment = blocks[i].getCommentText(); +Generator.prototype.allNestedComments = function(block) { + const comments = []; + const blocks = block.getDescendants(true); + for (let i = 0; i < blocks.length; i++) { + const comment = blocks[i].getCommentText(); if (comment) { comments.push(comment); } @@ -169,13 +172,13 @@ Blockly.Generator.prototype.allNestedComments = function(block) { /** * Generate code for the specified block (and attached blocks). * The generator must be initialized before calling this function. - * @param {Blockly.Block} block The block to generate code for. + * @param {Block} block The block to generate code for. * @param {boolean=} opt_thisOnly True to generate code for only this statement. * @return {string|!Array} For statement blocks, the generated code. * For value blocks, an array containing the generated code and an * operator order value. Returns '' if block is null. */ -Blockly.Generator.prototype.blockToCode = function(block, opt_thisOnly) { +Generator.prototype.blockToCode = function(block, opt_thisOnly) { if (this.isInitialized === false) { console.warn( 'Generator init was not called before blockToCode was called.'); @@ -192,16 +195,17 @@ Blockly.Generator.prototype.blockToCode = function(block, opt_thisOnly) { return opt_thisOnly ? '' : this.blockToCode(block.getChildren(false)[0]); } - var func = this[block.type]; + const func = this[block.type]; if (typeof func != 'function') { - throw Error('Language "' + this.name_ + '" does not know how to generate ' + + throw Error( + 'Language "' + this.name_ + '" does not know how to generate ' + 'code for block type "' + block.type + '".'); } // First argument to func.call is the value of 'this' in the generator. // Prior to 24 September 2013 'this' was the only way to access the block. // The current preferred method of accessing the block is through the second // argument to func.call, which becomes the first parameter to the generator. - var code = func.call(block, block); + let code = func.call(block, block); if (Array.isArray(code)) { // Value blocks return tuples of code and operator order. if (!block.outputConnection) { @@ -225,22 +229,22 @@ Blockly.Generator.prototype.blockToCode = function(block, opt_thisOnly) { /** * Generate code representing the specified value input. - * @param {!Blockly.Block} block The block containing the input. + * @param {!Block} block The block containing the input. * @param {string} name The name of the input. * @param {number} outerOrder The maximum binding strength (minimum order value) * of any operators adjacent to "block". * @return {string} Generated code or '' if no blocks are connected or the * specified input does not exist. */ -Blockly.Generator.prototype.valueToCode = function(block, name, outerOrder) { +Generator.prototype.valueToCode = function(block, name, outerOrder) { if (isNaN(outerOrder)) { throw TypeError('Expecting valid order from block: ' + block.type); } - var targetBlock = block.getInputTargetBlock(name); + const targetBlock = block.getInputTargetBlock(name); if (!targetBlock) { return ''; } - var tuple = this.blockToCode(targetBlock); + const tuple = this.blockToCode(targetBlock); if (tuple === '') { // Disabled block. return ''; @@ -250,20 +254,20 @@ Blockly.Generator.prototype.valueToCode = function(block, name, outerOrder) { if (!Array.isArray(tuple)) { throw TypeError('Expecting tuple from value block: ' + targetBlock.type); } - var code = tuple[0]; - var innerOrder = tuple[1]; + let code = tuple[0]; + const innerOrder = tuple[1]; if (isNaN(innerOrder)) { - throw TypeError('Expecting valid order from value block: ' + - targetBlock.type); + throw TypeError( + 'Expecting valid order from value block: ' + targetBlock.type); } if (!code) { return ''; } // Add parentheses if needed. - var parensNeeded = false; - var outerOrderClass = Math.floor(outerOrder); - var innerOrderClass = Math.floor(innerOrder); + let parensNeeded = false; + const outerOrderClass = Math.floor(outerOrder); + const innerOrderClass = Math.floor(innerOrder); if (outerOrderClass <= innerOrderClass) { if (outerOrderClass == innerOrderClass && (outerOrderClass == 0 || outerOrderClass == 99)) { @@ -277,7 +281,7 @@ Blockly.Generator.prototype.valueToCode = function(block, name, outerOrder) { // wrap the code in parentheses. parensNeeded = true; // Check for special exceptions. - for (var i = 0; i < this.ORDER_OVERRIDES.length; i++) { + for (let i = 0; i < this.ORDER_OVERRIDES.length; i++) { if (this.ORDER_OVERRIDES[i][0] == outerOrder && this.ORDER_OVERRIDES[i][1] == innerOrder) { parensNeeded = false; @@ -299,17 +303,18 @@ Blockly.Generator.prototype.valueToCode = function(block, name, outerOrder) { * statement input. Indent the code. * This is mainly used in generators. When trying to generate code to evaluate * look at using workspaceToCode or blockToCode. - * @param {!Blockly.Block} block The block containing the input. + * @param {!Block} block The block containing the input. * @param {string} name The name of the input. * @return {string} Generated code or '' if no blocks are connected. */ -Blockly.Generator.prototype.statementToCode = function(block, name) { - var targetBlock = block.getInputTargetBlock(name); - var code = this.blockToCode(targetBlock); +Generator.prototype.statementToCode = function(block, name) { + const targetBlock = block.getInputTargetBlock(name); + let code = this.blockToCode(targetBlock); // Value blocks must return code and order of operations info. // Statement blocks must only return code. if (typeof code != 'string') { - throw TypeError('Expecting code from statement block: ' + + throw TypeError( + 'Expecting code from statement block: ' + (targetBlock && targetBlock.type)); } if (code) { @@ -324,21 +329,24 @@ Blockly.Generator.prototype.statementToCode = function(block, name) { * statement executes), and a statement prefix to the end of the loop block * (right before the loop statement executes). * @param {string} branch Code for loop contents. - * @param {!Blockly.Block} block Enclosing block. + * @param {!Block} block Enclosing block. * @return {string} Loop contents, with infinite loop trap added. */ -Blockly.Generator.prototype.addLoopTrap = function(branch, block) { +Generator.prototype.addLoopTrap = function(branch, block) { if (this.INFINITE_LOOP_TRAP) { - branch = this.prefixLines(this.injectId(this.INFINITE_LOOP_TRAP, block), - this.INDENT) + branch; + branch = this.prefixLines( + this.injectId(this.INFINITE_LOOP_TRAP, block), this.INDENT) + + branch; } if (this.STATEMENT_SUFFIX && !block.suppressPrefixSuffix) { - branch = this.prefixLines(this.injectId(this.STATEMENT_SUFFIX, block), - this.INDENT) + branch; + branch = this.prefixLines( + this.injectId(this.STATEMENT_SUFFIX, block), this.INDENT) + + branch; } if (this.STATEMENT_PREFIX && !block.suppressPrefixSuffix) { - branch = branch + this.prefixLines(this.injectId(this.STATEMENT_PREFIX, - block), this.INDENT); + branch = branch + + this.prefixLines( + this.injectId(this.STATEMENT_PREFIX, block), this.INDENT); } return branch; }; @@ -347,11 +355,11 @@ Blockly.Generator.prototype.addLoopTrap = function(branch, block) { * Inject a block ID into a message to replace '%1'. * Used for STATEMENT_PREFIX, STATEMENT_SUFFIX, and INFINITE_LOOP_TRAP. * @param {string} msg Code snippet with '%1'. - * @param {!Blockly.Block} block Block which has an ID. + * @param {!Block} block Block which has an ID. * @return {string} Code snippet with ID. */ -Blockly.Generator.prototype.injectId = function(msg, block) { - var id = block.id.replace(/\$/g, '$$$$'); // Issue 251. +Generator.prototype.injectId = function(msg, block) { + const id = block.id.replace(/\$/g, '$$$$'); // Issue 251. return msg.replace(/%1/g, '\'' + id + '\''); }; @@ -360,33 +368,33 @@ Blockly.Generator.prototype.injectId = function(msg, block) { * @type {string} * @protected */ -Blockly.Generator.prototype.RESERVED_WORDS_ = ''; +Generator.prototype.RESERVED_WORDS_ = ''; /** * Add one or more words to the list of reserved words for this language. * @param {string} words Comma-separated list of words to add to the list. * No spaces. Duplicates are ok. */ -Blockly.Generator.prototype.addReservedWords = function(words) { +Generator.prototype.addReservedWords = function(words) { this.RESERVED_WORDS_ += words + ','; }; /** * This is used as a placeholder in functions defined using - * Blockly.Generator.provideFunction_. It must not be legal code that could + * Generator.provideFunction_. It must not be legal code that could * legitimately appear in a function definition (or comment), and it must * not confuse the regular expression parser. * @type {string} * @protected */ -Blockly.Generator.prototype.FUNCTION_NAME_PLACEHOLDER_ = '{leCUI8hutHZI4480Dc}'; +Generator.prototype.FUNCTION_NAME_PLACEHOLDER_ = '{leCUI8hutHZI4480Dc}'; /** * A dictionary of definitions to be printed before the code. * @type {!Object|undefined} * @protected */ -Blockly.Generator.prototype.definitions_; +Generator.prototype.definitions_; /** * A dictionary mapping desired function names in definitions_ to actual @@ -394,36 +402,34 @@ Blockly.Generator.prototype.definitions_; * @type {!Object|undefined} * @protected */ -Blockly.Generator.prototype.functionNames_; +Generator.prototype.functionNames_; /** * A database of variable and procedure names. - * @type {!Blockly.Names|undefined} + * @type {!Names|undefined} * @protected */ -Blockly.Generator.prototype.nameDB_; +Generator.prototype.nameDB_; -Object.defineProperty(Blockly.Generator.prototype, 'variableDB_', { +Object.defineProperty(Generator.prototype, 'variableDB_', { /** * Getter. * @deprecated 'variableDB_' was renamed to 'nameDB_' (May 2021). - * @this {Blockly.Generator} - * @return {!Blockly.Names|undefined} Name database. + * @this {Generator} + * @return {!Names|undefined} Name database. */ get: function() { - Blockly.utils.deprecation.warn( - 'variableDB_', 'May 2021', 'May 2026', 'nameDB_'); + deprecation.warn('variableDB_', 'May 2021', 'May 2026', 'nameDB_'); return this.nameDB_; }, /** * Setter. * @deprecated 'variableDB_' was renamed to 'nameDB_' (May 2021). - * @this {Blockly.Generator} - * @param {!Blockly.Names|undefined} nameDb New name database. + * @this {Generator} + * @param {!Names|undefined} nameDb New name database. */ set: function(nameDb) { - Blockly.utils.deprecation.warn( - 'variableDB_', 'May 2021', 'May 2026', 'nameDB_'); + deprecation.warn('variableDB_', 'May 2021', 'May 2026', 'nameDB_'); this.nameDB_ = nameDb; } }); @@ -440,7 +446,7 @@ Object.defineProperty(Blockly.Generator.prototype, 'variableDB_', { * "listRandom", not "random"). There is no danger of colliding with reserved * words, or user-defined variable or procedure names. * - * The code gets output when Blockly.Generator.finish() is called. + * The code gets output when Generator.finish() is called. * * @param {string} desiredName The desired name of the function * (e.g. mathIsPrime). @@ -449,18 +455,18 @@ Object.defineProperty(Blockly.Generator.prototype, 'variableDB_', { * from desiredName if the former has already been taken by the user. * @protected */ -Blockly.Generator.prototype.provideFunction_ = function(desiredName, code) { +Generator.prototype.provideFunction_ = function(desiredName, code) { if (!this.definitions_[desiredName]) { - var functionName = this.nameDB_.getDistinctName(desiredName, - Blockly.PROCEDURE_CATEGORY_NAME); + const functionName = this.nameDB_.getDistinctName( + desiredName, internalConstants.PROCEDURE_CATEGORY_NAME); this.functionNames_[desiredName] = functionName; - var codeText = code.join('\n').replace( + let codeText = code.join('\n').replace( this.FUNCTION_NAME_PLACEHOLDER_REGEXP_, functionName); // Change all ' ' indents into the desired indent. // To avoid an infinite loop of replacements, change all indents to '\0' // character first, then replace them all with the indent. // We are assuming that no provided functions contain a literal null char. - var oldCodeText; + let oldCodeText; while (oldCodeText != codeText) { oldCodeText = codeText; codeText = codeText.replace(/^(( {2})*) {2}/gm, '$1\0'); @@ -475,9 +481,9 @@ Blockly.Generator.prototype.provideFunction_ = function(desiredName, code) { * Hook for code to run before code generation starts. * Subclasses may override this, e.g. to initialise the database of variable * names. - * @param {!Blockly.Workspace} _workspace Workspace to generate code from. + * @param {!Workspace} _workspace Workspace to generate code from. */ -Blockly.Generator.prototype.init = function(_workspace) { +Generator.prototype.init = function(_workspace) { // Optionally override // Create a dictionary of definitions to be printed before the code. this.definitions_ = Object.create(null); @@ -493,14 +499,14 @@ Blockly.Generator.prototype.init = function(_workspace) { * Subclasses may override this, e.g. to generate code for statements following * the block, or to handle comments for the specified block and any connected * value blocks. - * @param {!Blockly.Block} _block The current block. + * @param {!Block} _block The current block. * @param {string} code The code created for this block. * @param {boolean=} _opt_thisOnly True to generate code for only this * statement. * @return {string} Code with comments and subsequent blocks added. * @protected */ -Blockly.Generator.prototype.scrub_ = function(_block, code, _opt_thisOnly) { +Generator.prototype.scrub_ = function(_block, code, _opt_thisOnly) { // Optionally override return code; }; @@ -512,7 +518,7 @@ Blockly.Generator.prototype.scrub_ = function(_block, code, _opt_thisOnly) { * @param {string} code Generated code. * @return {string} Completed code. */ -Blockly.Generator.prototype.finish = function(code) { +Generator.prototype.finish = function(code) { // Optionally override // Clean up temporary data. delete this.definitions_; @@ -528,7 +534,9 @@ Blockly.Generator.prototype.finish = function(code) { * @param {string} line Line of generated code. * @return {string} Legal line of code. */ -Blockly.Generator.prototype.scrubNakedValue = function(line) { +Generator.prototype.scrubNakedValue = function(line) { // Optionally override return line; }; + +exports = Generator; diff --git a/core/gesture.js b/core/gesture.js index 55378930b..933930e44 100644 --- a/core/gesture.js +++ b/core/gesture.js @@ -11,31 +11,39 @@ */ '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'); +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'); +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'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); -goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.Click'); -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'); /** @@ -47,15 +55,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; @@ -63,15 +71,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; @@ -79,7 +87,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; @@ -87,7 +95,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; @@ -97,7 +105,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; @@ -106,7 +114,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; @@ -116,7 +124,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; @@ -161,7 +169,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; @@ -169,21 +177,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; @@ -191,14 +199,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; @@ -230,24 +238,24 @@ Blockly.Gesture = function(e, creatorWorkspace) { * @type {boolean} * @private */ - this.healStack_ = !Blockly.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_) { @@ -266,9 +274,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_(); @@ -279,24 +287,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.FLYOUT_DRAG_RADIUS : Blockly.DRAG_RADIUS; + const limitRadius = this.flyout_ ? internalConstants.FLYOUT_DRAG_RADIUS : + internalConstants.DRAG_RADIUS; this.hasExceededDragRadius_ = currentDragDelta > limitRadius; return this.hasExceededDragRadius_; @@ -314,7 +321,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 +334,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 +355,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 +374,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 +400,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 +409,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 +422,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 +445,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 +461,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 +475,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 +497,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 +514,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 +525,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 +540,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 +559,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 +601,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 +612,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 +624,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 +646,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 +662,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 +688,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 +704,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 +725,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 +735,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 +744,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 +770,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 +787,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 +798,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 +814,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 +826,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 +845,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 +858,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 +869,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 +890,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 +902,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 +915,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 +928,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 +943,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 +955,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 +976,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 +994,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/grid.js b/core/grid.js index 56171ef50..1a1d5f2a3 100644 --- a/core/grid.js +++ b/core/grid.js @@ -11,11 +11,12 @@ */ 'use strict'; -goog.provide('Blockly.Grid'); +goog.module('Blockly.Grid'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.Svg'); -goog.require('Blockly.utils.userAgent'); +const Svg = goog.require('Blockly.utils.Svg'); +const dom = goog.require('Blockly.utils.dom'); +const userAgent = goog.require('Blockly.utils.userAgent'); /** @@ -27,7 +28,7 @@ goog.require('Blockly.utils.userAgent'); * https://developers.google.com/blockly/guides/configure/web/grid * @constructor */ -Blockly.Grid = function(pattern, options) { +const Grid = function(pattern, options) { /** * The grid's SVG pattern, created during injection. * @type {!SVGElement} @@ -61,8 +62,8 @@ Blockly.Grid = function(pattern, options) { * @type {SVGElement} * @private */ - this.line2_ = this.line1_ && - (/** @type {SVGElement} */ (this.line1_.nextSibling)); + this.line2_ = + this.line1_ && (/** @type {SVGElement} */ (this.line1_.nextSibling)); /** * Whether blocks should snap to the grid. @@ -78,14 +79,14 @@ Blockly.Grid = function(pattern, options) { * @type {number} * @private */ -Blockly.Grid.prototype.scale_ = 1; +Grid.prototype.scale_ = 1; /** * Dispose of this grid and unlink from the DOM. * @package * @suppress {checkTypes} */ -Blockly.Grid.prototype.dispose = function() { +Grid.prototype.dispose = function() { this.gridPattern_ = null; }; @@ -94,7 +95,7 @@ Blockly.Grid.prototype.dispose = function() { * @return {boolean} True if blocks should snap, false otherwise. * @package */ -Blockly.Grid.prototype.shouldSnap = function() { +Grid.prototype.shouldSnap = function() { return this.snapToGrid_; }; @@ -103,7 +104,7 @@ Blockly.Grid.prototype.shouldSnap = function() { * @return {number} The spacing of the grid points. * @package */ -Blockly.Grid.prototype.getSpacing = function() { +Grid.prototype.getSpacing = function() { return this.spacing_; }; @@ -113,7 +114,7 @@ Blockly.Grid.prototype.getSpacing = function() { * @return {string} The pattern ID. * @package */ -Blockly.Grid.prototype.getPatternId = function() { +Grid.prototype.getPatternId = function() { return this.gridPattern_.id; }; @@ -122,17 +123,17 @@ Blockly.Grid.prototype.getPatternId = function() { * @param {number} scale The new workspace scale. * @package */ -Blockly.Grid.prototype.update = function(scale) { +Grid.prototype.update = function(scale) { this.scale_ = scale; // MSIE freaks if it sees a 0x0 pattern, so set empty patterns to 100x100. - var safeSpacing = (this.spacing_ * scale) || 100; + const safeSpacing = (this.spacing_ * scale) || 100; this.gridPattern_.setAttribute('width', safeSpacing); this.gridPattern_.setAttribute('height', safeSpacing); - var half = Math.floor(this.spacing_ / 2) + 0.5; - var start = half - this.length_ / 2; - var end = half + this.length_ / 2; + let half = Math.floor(this.spacing_ / 2) + 0.5; + let start = half - this.length_ / 2; + let end = half + this.length_ / 2; half *= scale; start *= scale; @@ -153,8 +154,7 @@ Blockly.Grid.prototype.update = function(scale) { * @param {number} y2 The new y end position of the line (in px). * @private */ -Blockly.Grid.prototype.setLineAttributes_ = function(line, width, - x1, x2, y1, y2) { +Grid.prototype.setLineAttributes_ = function(line, width, x1, x2, y1, y2) { if (line) { line.setAttribute('stroke-width', width); line.setAttribute('x1', x1); @@ -171,11 +171,11 @@ Blockly.Grid.prototype.setLineAttributes_ = function(line, width, * @param {number} y The new y position of the grid (in px). * @package */ -Blockly.Grid.prototype.moveTo = function(x, y) { +Grid.prototype.moveTo = function(x, y) { this.gridPattern_.setAttribute('x', x); this.gridPattern_.setAttribute('y', y); - if (Blockly.utils.userAgent.IE || Blockly.utils.userAgent.EDGE) { + if (userAgent.IE || userAgent.EDGE) { // IE/Edge doesn't notice that the x/y offsets have changed. // Force an update. this.update(this.scale_); @@ -190,33 +190,30 @@ Blockly.Grid.prototype.moveTo = function(x, y) { * @return {!SVGElement} The SVG element for the grid pattern. * @package */ -Blockly.Grid.createDom = function(rnd, gridOptions, defs) { +Grid.createDom = function(rnd, gridOptions, defs) { /* */ - var gridPattern = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.PATTERN, - { - 'id': 'blocklyGridPattern' + rnd, - 'patternUnits': 'userSpaceOnUse' - }, defs); + const gridPattern = dom.createSvgElement( + Svg.PATTERN, + {'id': 'blocklyGridPattern' + rnd, 'patternUnits': 'userSpaceOnUse'}, + defs); if (gridOptions['length'] > 0 && gridOptions['spacing'] > 0) { - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.LINE, - {'stroke': gridOptions['colour']}, gridPattern); + dom.createSvgElement( + Svg.LINE, {'stroke': gridOptions['colour']}, gridPattern); if (gridOptions['length'] > 1) { - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.LINE, - {'stroke': gridOptions['colour']}, gridPattern); + dom.createSvgElement( + Svg.LINE, {'stroke': gridOptions['colour']}, gridPattern); } // x1, y1, x1, x2 properties will be set later in update. } else { // Edge 16 doesn't handle empty patterns - Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.LINE, {}, gridPattern); + dom.createSvgElement(Svg.LINE, {}, gridPattern); } return gridPattern; }; + +exports = Grid; diff --git a/core/icon.js b/core/icon.js index c5f3477cd..69ff3ef37 100644 --- a/core/icon.js +++ b/core/icon.js @@ -10,29 +10,31 @@ */ 'use strict'; -goog.provide('Blockly.Icon'); +goog.module('Blockly.Icon'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.browserEvents'); -goog.require('Blockly.utils'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.Size'); -goog.require('Blockly.utils.Svg'); - -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.Bubble'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +/* eslint-disable-next-line no-unused-vars */ +const Bubble = goog.requireType('Blockly.Bubble'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +const Size = goog.require('Blockly.utils.Size'); +const Svg = goog.require('Blockly.utils.Svg'); +const browserEvents = goog.require('Blockly.browserEvents'); +const dom = goog.require('Blockly.utils.dom'); +const {getRelativeXY, isRightButton} = goog.require('Blockly.utils'); /** * Class for an icon. - * @param {Blockly.BlockSvg} block The block associated with this icon. + * @param {BlockSvg} block The block associated with this icon. * @constructor * @abstract */ -Blockly.Icon = function(block) { +const Icon = function(block) { /** * The block this icon is attached to. - * @type {Blockly.BlockSvg} + * @type {BlockSvg} * @protected */ this.block_ = block; @@ -47,31 +49,32 @@ Blockly.Icon = function(block) { /** * Does this icon get hidden when the block is collapsed. */ -Blockly.Icon.prototype.collapseHidden = true; +Icon.prototype.collapseHidden = true; /** * Height and width of icons. + * @const */ -Blockly.Icon.prototype.SIZE = 17; +Icon.prototype.SIZE = 17; /** * Bubble UI (if visible). - * @type {?Blockly.Bubble} + * @type {?Bubble} * @protected */ -Blockly.Icon.prototype.bubble_ = null; +Icon.prototype.bubble_ = null; /** * Absolute coordinate of icon's center. - * @type {?Blockly.utils.Coordinate} + * @type {?Coordinate} * @protected */ -Blockly.Icon.prototype.iconXY_ = null; +Icon.prototype.iconXY_ = null; /** * Create the icon on the block. */ -Blockly.Icon.prototype.createIcon = function() { +Icon.prototype.createIcon = function() { if (this.iconGroup_) { // Icon already exists. return; @@ -81,17 +84,16 @@ Blockly.Icon.prototype.createIcon = function() { ... */ - this.iconGroup_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.G, - {'class': 'blocklyIconGroup'}, null); + this.iconGroup_ = + dom.createSvgElement(Svg.G, {'class': 'blocklyIconGroup'}, null); if (this.block_.isInFlyout) { - Blockly.utils.dom.addClass( + dom.addClass( /** @type {!Element} */ (this.iconGroup_), 'blocklyIconGroupReadonly'); } this.drawIcon_(this.iconGroup_); this.block_.getSvgRoot().appendChild(this.iconGroup_); - Blockly.browserEvents.conditionalBind( + browserEvents.conditionalBind( this.iconGroup_, 'mouseup', this, this.iconClick_); this.updateEditable(); }; @@ -99,9 +101,9 @@ Blockly.Icon.prototype.createIcon = function() { /** * Dispose of this icon. */ -Blockly.Icon.prototype.dispose = function() { +Icon.prototype.dispose = function() { // Dispose of and unlink the icon. - Blockly.utils.dom.removeNode(this.iconGroup_); + dom.removeNode(this.iconGroup_); this.iconGroup_ = null; // Dispose of and unlink the bubble. this.setVisible(false); @@ -111,7 +113,7 @@ Blockly.Icon.prototype.dispose = function() { /** * Add or remove the UI indicating if this icon may be clicked or not. */ -Blockly.Icon.prototype.updateEditable = function() { +Icon.prototype.updateEditable = function() { // No-op on the base class. }; @@ -119,7 +121,7 @@ Blockly.Icon.prototype.updateEditable = function() { * Is the associated bubble visible? * @return {boolean} True if the bubble is visible. */ -Blockly.Icon.prototype.isVisible = function() { +Icon.prototype.isVisible = function() { return !!this.bubble_; }; @@ -128,12 +130,12 @@ Blockly.Icon.prototype.isVisible = function() { * @param {!Event} e Mouse click event. * @protected */ -Blockly.Icon.prototype.iconClick_ = function(e) { +Icon.prototype.iconClick_ = function(e) { if (this.block_.workspace.isDragging()) { // Drag operation is concluding. Don't open the editor. return; } - if (!this.block_.isInFlyout && !Blockly.utils.isRightButton(e)) { + if (!this.block_.isInFlyout && !isRightButton(e)) { this.setVisible(!this.isVisible()); } }; @@ -141,7 +143,7 @@ Blockly.Icon.prototype.iconClick_ = function(e) { /** * Change the colour of the associated bubble to match its block. */ -Blockly.Icon.prototype.applyColour = function() { +Icon.prototype.applyColour = function() { if (this.isVisible()) { this.bubble_.setColour(this.block_.style.colourPrimary); } @@ -149,9 +151,9 @@ Blockly.Icon.prototype.applyColour = function() { /** * Notification that the icon has moved. Update the arrow accordingly. - * @param {!Blockly.utils.Coordinate} xy Absolute location in workspace coordinates. + * @param {!Coordinate} xy Absolute location in workspace coordinates. */ -Blockly.Icon.prototype.setIconLocation = function(xy) { +Icon.prototype.setIconLocation = function(xy) { this.iconXY_ = xy; if (this.isVisible()) { this.bubble_.setAnchorLocation(xy); @@ -162,25 +164,25 @@ Blockly.Icon.prototype.setIconLocation = function(xy) { * Notification that the icon has moved, but we don't really know where. * Recompute the icon's location from scratch. */ -Blockly.Icon.prototype.computeIconLocation = function() { +Icon.prototype.computeIconLocation = function() { // Find coordinates for the centre of the icon and update the arrow. - var blockXY = this.block_.getRelativeToSurfaceXY(); - var iconXY = Blockly.utils.getRelativeXY( + const blockXY = this.block_.getRelativeToSurfaceXY(); + const iconXY = getRelativeXY( /** @type {!SVGElement} */ (this.iconGroup_)); - var newXY = new Blockly.utils.Coordinate( + const newXY = new Coordinate( blockXY.x + iconXY.x + this.SIZE / 2, blockXY.y + iconXY.y + this.SIZE / 2); - if (!Blockly.utils.Coordinate.equals(this.getIconLocation(), newXY)) { + if (!Coordinate.equals(this.getIconLocation(), newXY)) { this.setIconLocation(newXY); } }; /** * Returns the center of the block's icon relative to the surface. - * @return {?Blockly.utils.Coordinate} Object with x and y properties in + * @return {?Coordinate} Object with x and y properties in * workspace coordinates. */ -Blockly.Icon.prototype.getIconLocation = function() { +Icon.prototype.getIconLocation = function() { return this.iconXY_; }; @@ -188,12 +190,11 @@ Blockly.Icon.prototype.getIconLocation = function() { * Get the size of the icon as used for rendering. * This differs from the actual size of the icon, because it bulges slightly * out of its row rather than increasing the height of its row. - * @return {!Blockly.utils.Size} Height and width. + * @return {!Size} Height and width. */ // TODO (#2562): Remove getCorrectedSize. -Blockly.Icon.prototype.getCorrectedSize = function() { - return new Blockly.utils.Size( - Blockly.Icon.prototype.SIZE, Blockly.Icon.prototype.SIZE - 2); +Icon.prototype.getCorrectedSize = function() { + return new Size(Icon.prototype.SIZE, Icon.prototype.SIZE - 2); }; /** @@ -201,10 +202,12 @@ Blockly.Icon.prototype.getCorrectedSize = function() { * @param {!Element} group The icon group. * @protected */ -Blockly.Icon.prototype.drawIcon_; +Icon.prototype.drawIcon_; /** * Show or hide the icon. * @param {boolean} visible True if the icon should be visible. */ -Blockly.Icon.prototype.setVisible; +Icon.prototype.setVisible; + +exports = Icon; diff --git a/core/input.js b/core/input.js index 57189c278..afa7a3358 100644 --- a/core/input.js +++ b/core/input.js @@ -10,33 +10,36 @@ */ 'use strict'; -goog.provide('Blockly.Input'); +goog.module('Blockly.Input'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.Connection'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); -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} */ @@ -44,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 = []; }; @@ -58,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; }; @@ -92,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.'); } @@ -109,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, })); @@ -136,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(); @@ -152,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(); @@ -176,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_; }; @@ -184,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'; } @@ -221,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(); } }; @@ -231,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.'); } @@ -243,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; @@ -259,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.'); } @@ -273,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.'); } @@ -283,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(); } }; @@ -296,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) { @@ -305,3 +308,5 @@ Blockly.Input.prototype.dispose = function() { } this.sourceBlock_ = null; }; + +exports = Input; diff --git a/core/insertion_marker_manager.js b/core/insertion_marker_manager.js index d0fea4502..614f7e70b 100644 --- a/core/insertion_marker_manager.js +++ b/core/insertion_marker_manager.js @@ -15,9 +15,8 @@ goog.provide('Blockly.InsertionMarkerManager'); goog.require('Blockly.blockAnimations'); goog.require('Blockly.ComponentManager'); goog.require('Blockly.connectionTypes'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.Events'); +goog.require('Blockly.internalConstants'); goog.requireType('Blockly.BlockSvg'); goog.requireType('Blockly.RenderedConnection'); @@ -378,8 +377,10 @@ Blockly.InsertionMarkerManager.prototype.shouldUpdatePreviews_ = function( var yDiff = this.localConnection_.y + dxy.y - this.closestConnection_.y; var curDistance = Math.sqrt(xDiff * xDiff + yDiff * yDiff); // Slightly prefer the existing preview over a new preview. - return !(candidateClosest && radius > curDistance - - Blockly.CURRENT_CONNECTION_PREFERENCE); + return !( + candidateClosest && + radius > curDistance - + Blockly.internalConstants.CURRENT_CONNECTION_PREFERENCE); } else if (!this.localConnection_ && !this.closestConnection_) { // We weren't showing a preview before, but we should now. return true; @@ -439,9 +440,9 @@ Blockly.InsertionMarkerManager.prototype.getStartRadius_ = function() { // By increasing radiusConnection when a connection already exists, // we never "lose" the connection from the offset. if (this.closestConnection_ && this.localConnection_) { - return Blockly.CONNECTING_SNAP_RADIUS; + return Blockly.internalConstants.CONNECTING_SNAP_RADIUS; } - return Blockly.SNAP_RADIUS; + return Blockly.internalConstants.SNAP_RADIUS; }; /** diff --git a/core/interfaces/i_accessibility.js b/core/interfaces/i_accessibility.js deleted file mode 100644 index 30d724959..000000000 --- a/core/interfaces/i_accessibility.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @fileoverview AST Node and keyboard navigation interfaces. - * @author samelh@google.com (Sam El-Husseini) - */ - -'use strict'; - -goog.provide('Blockly.IASTNodeLocation'); -goog.provide('Blockly.IASTNodeLocationSvg'); -goog.provide('Blockly.IASTNodeLocationWithBlock'); -goog.provide('Blockly.IKeyboardAccessible'); - -goog.requireType('Blockly.Block'); -goog.requireType('Blockly.ShortcutRegistry'); - - -/** - * An AST node location interface. - * @interface - */ -Blockly.IASTNodeLocation = function() {}; - -/** - * An AST node location SVG interface. - * @interface - * @extends {Blockly.IASTNodeLocation} - */ -Blockly.IASTNodeLocationSvg = function() {}; - -/** - * Add the marker SVG to this node's SVG group. - * @param {SVGElement} markerSvg The SVG root of the marker to be added to the - * SVG group. - */ -Blockly.IASTNodeLocationSvg.prototype.setMarkerSvg; - -/** - * Add the cursor SVG to this node's SVG group. - * @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the - * SVG group. - */ -Blockly.IASTNodeLocationSvg.prototype.setCursorSvg; - -/** - * An AST node location that has an associated block. - * @interface - * @extends {Blockly.IASTNodeLocation} - */ -Blockly.IASTNodeLocationWithBlock = function() {}; - -/** - * Get the source block associated with this node. - * @return {Blockly.Block} The source block. - */ -Blockly.IASTNodeLocationWithBlock.prototype.getSourceBlock; - - -/** - * An interface for an object that handles keyboard shortcuts. - * @interface - */ -Blockly.IKeyboardAccessible = function() {}; - -/** - * Handles the given keyboard shortcut. - * @param {!Blockly.ShortcutRegistry.KeyboardShortcut} shortcut The shortcut to be handled. - * @return {boolean} True if the shortcut has been handled, false otherwise. - */ -Blockly.IKeyboardAccessible.prototype.onShortcut; diff --git a/core/interfaces/i_ast_node_location.js b/core/interfaces/i_ast_node_location.js new file mode 100644 index 000000000..0ebec8ebd --- /dev/null +++ b/core/interfaces/i_ast_node_location.js @@ -0,0 +1,23 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for an AST node location. + * @author samelh@google.com (Sam El-Husseini) + */ + +'use strict'; + +goog.module('Blockly.IASTNodeLocation'); +goog.module.declareLegacyNamespace(); + +/** + * An AST node location interface. + * @interface + */ +const IASTNodeLocation = function() {}; + +exports = IASTNodeLocation; diff --git a/core/interfaces/i_ast_node_location_svg.js b/core/interfaces/i_ast_node_location_svg.js new file mode 100644 index 000000000..526fbffa3 --- /dev/null +++ b/core/interfaces/i_ast_node_location_svg.js @@ -0,0 +1,42 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for an AST node location SVG. + * @author samelh@google.com (Sam El-Husseini) + */ + +'use strict'; + +goog.module('Blockly.IASTNodeLocationSvg'); +goog.module.declareLegacyNamespace(); + +/* eslint-disable-next-line no-unused-vars */ +const IASTNodeLocation = goog.require('Blockly.IASTNodeLocation'); + + +/** + * An AST node location SVG interface. + * @interface + * @extends {IASTNodeLocation} + */ +const IASTNodeLocationSvg = function() {}; + +/** + * Add the marker SVG to this node's SVG group. + * @param {SVGElement} markerSvg The SVG root of the marker to be added to the + * SVG group. + */ +IASTNodeLocationSvg.prototype.setMarkerSvg; + +/** + * Add the cursor SVG to this node's SVG group. + * @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the + * SVG group. + */ +IASTNodeLocationSvg.prototype.setCursorSvg; + +exports = IASTNodeLocationSvg; diff --git a/core/interfaces/i_ast_node_location_with_block.js b/core/interfaces/i_ast_node_location_with_block.js new file mode 100644 index 000000000..002db0ad8 --- /dev/null +++ b/core/interfaces/i_ast_node_location_with_block.js @@ -0,0 +1,37 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for an AST node location that has an associated + * block. + * @author samelh@google.com (Sam El-Husseini) + */ + +'use strict'; + +goog.module('Blockly.IASTNodeLocationWithBlock'); +goog.module.declareLegacyNamespace(); + +/* eslint-disable-next-line no-unused-vars */ +const Block = goog.requireType('Blockly.Block'); +/* eslint-disable-next-line no-unused-vars */ +const IASTNodeLocation = goog.require('Blockly.IASTNodeLocation'); + + +/** + * An AST node location that has an associated block. + * @interface + * @extends {IASTNodeLocation} + */ +const IASTNodeLocationWithBlock = function() {}; + +/** + * Get the source block associated with this node. + * @return {Block} The source block. + */ +IASTNodeLocationWithBlock.prototype.getSourceBlock; + +exports = IASTNodeLocationWithBlock; diff --git a/core/interfaces/i_autohideable.js b/core/interfaces/i_autohideable.js index ff976c549..0ccbf310a 100644 --- a/core/interfaces/i_autohideable.js +++ b/core/interfaces/i_autohideable.js @@ -12,21 +12,25 @@ 'use strict'; -goog.provide('Blockly.IAutoHideable'); +goog.module('Blockly.IAutoHideable'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.IComponent'); +/* eslint-disable-next-line no-unused-vars */ +const IComponent = goog.require('Blockly.IComponent'); /** * Interface for a component that can be automatically hidden. - * @extends {Blockly.IComponent} + * @extends {IComponent} * @interface */ -Blockly.IAutoHideable = function() {}; +const IAutoHideable = function() {}; /** * Hides the component. Called in Blockly.hideChaff. * @param {boolean} onlyClosePopups Whether only popups should be closed. * Flyouts should not be closed if this is true. */ -Blockly.IAutoHideable.prototype.autoHide; +IAutoHideable.prototype.autoHide; + +exports = IAutoHideable; diff --git a/core/interfaces/i_block_dragger.js b/core/interfaces/i_block_dragger.js index ec7b79ac6..b87cd9865 100644 --- a/core/interfaces/i_block_dragger.js +++ b/core/interfaces/i_block_dragger.js @@ -11,48 +11,53 @@ 'use strict'; -goog.provide('Blockly.IBlockDragger'); +goog.module('Blockly.IBlockDragger'); +goog.module.declareLegacyNamespace(); -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.utils.Coordinate'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +/* eslint-disable-next-line no-unused-vars */ +const Coordinate = goog.requireType('Blockly.utils.Coordinate'); /** * A block dragger interface. * @interface */ -Blockly.IBlockDragger = function() {}; +const IBlockDragger = function() {}; /** * Start dragging a block. This includes moving it to the drag surface. - * @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. * @param {boolean} healStack Whether or not to heal the stack after * disconnecting. */ -Blockly.IBlockDragger.prototype.startDrag; +IBlockDragger.prototype.startDrag; /** * Execute a step of block dragging, based on the given event. Update the * display accordingly. * @param {!Event} e The most recent move event. - * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has + * @param {!Coordinate} currentDragDeltaXY How far the pointer has * moved from the position at the start of the drag, in pixel units. */ -Blockly.IBlockDragger.prototype.drag; +IBlockDragger.prototype.drag; /** * Finish a block drag and put the block back on the workspace. * @param {!Event} e The mouseup/touchend event. - * @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has + * @param {!Coordinate} currentDragDeltaXY How far the pointer has * moved from the position at the start of the drag, in pixel units. */ -Blockly.IBlockDragger.prototype.endDrag; +IBlockDragger.prototype.endDrag; /** * Get a list of the insertion markers that currently exist. 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. */ -Blockly.IBlockDragger.prototype.getInsertionMarkers; +IBlockDragger.prototype.getInsertionMarkers; + +exports = IBlockDragger; diff --git a/core/interfaces/i_bounded_element.js b/core/interfaces/i_bounded_element.js index bc5ffeee6..f2c84633e 100644 --- a/core/interfaces/i_bounded_element.js +++ b/core/interfaces/i_bounded_element.js @@ -11,28 +11,32 @@ 'use strict'; -goog.provide('Blockly.IBoundedElement'); +goog.module('Blockly.IBoundedElement'); +goog.module.declareLegacyNamespace(); -goog.requireType('Blockly.utils.Rect'); +/* eslint-disable-next-line no-unused-vars */ +const Rect = goog.requireType('Blockly.utils.Rect'); /** * A bounded element interface. * @interface */ -Blockly.IBoundedElement = function() {}; +const IBoundedElement = function() {}; /** * Returns the coordinates of a bounded element describing the dimensions of the * element. * Coordinate system: workspace coordinates. - * @return {!Blockly.utils.Rect} Object with coordinates of the bounded element. + * @return {!Rect} Object with coordinates of the bounded element. */ -Blockly.IBoundedElement.prototype.getBoundingRectangle; +IBoundedElement.prototype.getBoundingRectangle; /** * Move the element by a relative offset. * @param {number} dx Horizontal offset in workspace units. * @param {number} dy Vertical offset in workspace units. */ -Blockly.IBoundedElement.prototype.moveBy; +IBoundedElement.prototype.moveBy; + +exports = IBoundedElement; diff --git a/core/interfaces/i_bubble.js b/core/interfaces/i_bubble.js index 7fae99edf..b6e9736d7 100644 --- a/core/interfaces/i_bubble.js +++ b/core/interfaces/i_bubble.js @@ -11,35 +11,39 @@ 'use strict'; -goog.provide('Blockly.IBubble'); +goog.module('Blockly.IBubble'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.IContextMenu'); -goog.require('Blockly.IDraggable'); - -goog.requireType('Blockly.BlockDragSurfaceSvg'); -goog.requireType('Blockly.utils.Coordinate'); +/* eslint-disable-next-line no-unused-vars */ +const BlockDragSurfaceSvg = goog.requireType('Blockly.BlockDragSurfaceSvg'); +/* eslint-disable-next-line no-unused-vars */ +const Coordinate = goog.requireType('Blockly.utils.Coordinate'); +/* eslint-disable-next-line no-unused-vars */ +const IContextMenu = goog.require('Blockly.IContextMenu'); +/* eslint-disable-next-line no-unused-vars */ +const IDraggable = goog.require('Blockly.IDraggable'); /** * A bubble interface. * @interface - * @extends {Blockly.IDraggable} - * @extends {Blockly.IContextMenu} + * @extends {IDraggable} + * @extends {IContextMenu} */ -Blockly.IBubble = function() {}; +const IBubble = function() {}; /** * Return the coordinates of the top-left corner of this bubble's body relative * to the drawing surface's origin (0,0), in workspace units. - * @return {!Blockly.utils.Coordinate} Object with .x and .y properties. + * @return {!Coordinate} Object with .x and .y properties. */ -Blockly.IBubble.prototype.getRelativeToSurfaceXY; +IBubble.prototype.getRelativeToSurfaceXY; /** * Return the root node of the bubble's SVG group. * @return {!SVGElement} The root SVG node of the bubble's group. */ -Blockly.IBubble.prototype.getSvgRoot; +IBubble.prototype.getSvgRoot; /** * Set whether auto-layout of this bubble is enabled. The first time a bubble @@ -48,39 +52,41 @@ Blockly.IBubble.prototype.getSvgRoot; * @param {boolean} enable True if auto-layout should be enabled, false * otherwise. */ -Blockly.IBubble.prototype.setAutoLayout; +IBubble.prototype.setAutoLayout; /** * Triggers a move callback if one exists at the end of a drag. * @param {boolean} adding True if adding, false if removing. */ -Blockly.IBubble.prototype.setDragging; +IBubble.prototype.setDragging; /** * Move this bubble during a drag, taking into account whether or not there is * a drag surface. - * @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. */ -Blockly.IBubble.prototype.moveDuringDrag; +IBubble.prototype.moveDuringDrag; /** * Move the bubble to the specified location in workspace coordinates. * @param {number} x The x position to move to. * @param {number} y The y position to move to. */ -Blockly.IBubble.prototype.moveTo; +IBubble.prototype.moveTo; /** * Update the style of this bubble when it is dragged over a delete area. * @param {boolean} enable True if the bubble is about to be deleted, false * otherwise. */ -Blockly.IBubble.prototype.setDeleteStyle; +IBubble.prototype.setDeleteStyle; /** * Dispose of this bubble. */ -Blockly.IBubble.prototype.dispose; +IBubble.prototype.dispose; + +exports = IBubble; diff --git a/core/interfaces/i_collapsible_toolbox_item.js b/core/interfaces/i_collapsible_toolbox_item.js new file mode 100644 index 000000000..45bd3ae3e --- /dev/null +++ b/core/interfaces/i_collapsible_toolbox_item.js @@ -0,0 +1,50 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for a collapsible toolbox item. + * @author kozbial@google.com (Monica Kozbial) + */ + +'use strict'; + +goog.module('Blockly.ICollapsibleToolboxItem'); +goog.module.declareLegacyNamespace(); + +/* eslint-disable-next-line no-unused-vars */ +const ISelectableToolboxItem = goog.require('Blockly.ISelectableToolboxItem'); +/* eslint-disable-next-line no-unused-vars */ +const IToolboxItem = goog.requireType('Blockly.IToolboxItem'); + + +/** + * Interface for an item in the toolbox that can be collapsed. + * @extends {ISelectableToolboxItem} + * @interface + */ +const ICollapsibleToolboxItem = function() {}; + +/** + * Gets any children toolbox items. (ex. Gets the subcategories) + * @return {!Array} The child toolbox items. + */ +ICollapsibleToolboxItem.prototype.getChildToolboxItems; + +/** + * Whether the toolbox item is expanded to show its child subcategories. + * @return {boolean} True if the toolbox item shows its children, false if it + * is collapsed. + * @public + */ +ICollapsibleToolboxItem.prototype.isExpanded; + +/** + * Toggles whether or not the toolbox item is expanded. + * @public + */ +ICollapsibleToolboxItem.prototype.toggleExpanded; + +exports = ICollapsibleToolboxItem; diff --git a/core/interfaces/i_component.js b/core/interfaces/i_component.js index efb195966..d1acc592f 100644 --- a/core/interfaces/i_component.js +++ b/core/interfaces/i_component.js @@ -12,7 +12,8 @@ 'use strict'; -goog.provide('Blockly.IComponent'); +goog.module('Blockly.IComponent'); +goog.module.declareLegacyNamespace(); /** @@ -20,11 +21,13 @@ goog.provide('Blockly.IComponent'); * ComponentManager. * @interface */ -Blockly.IComponent = function() {}; +const IComponent = function() {}; /** * The unique id for this component that is used to register with the * ComponentManager. * @type {string} */ -Blockly.IComponent.id; +IComponent.id; + +exports = IComponent; diff --git a/core/interfaces/i_connection_checker.js b/core/interfaces/i_connection_checker.js index 4b6120da1..d0eb21e24 100644 --- a/core/interfaces/i_connection_checker.js +++ b/core/interfaces/i_connection_checker.js @@ -11,23 +11,26 @@ */ 'use strict'; -goog.provide('Blockly.IConnectionChecker'); +goog.module('Blockly.IConnectionChecker'); +goog.module.declareLegacyNamespace(); -goog.requireType('Blockly.Connection'); -goog.requireType('Blockly.RenderedConnection'); +/* eslint-disable-next-line no-unused-vars */ +const Connection = goog.requireType('Blockly.Connection'); +/* eslint-disable-next-line no-unused-vars */ +const RenderedConnection = goog.requireType('Blockly.RenderedConnection'); /** * Class for connection type checking logic. * @interface */ -Blockly.IConnectionChecker = function() {}; +const IConnectionChecker = function() {}; /** * Check whether the current connection can connect with the target * connection. - * @param {Blockly.Connection} a Connection to check compatibility with. - * @param {Blockly.Connection} b Connection to check compatibility with. + * @param {Connection} a Connection to check compatibility with. + * @param {Connection} b Connection to check compatibility with. * @param {boolean} isDragging True if the connection is being made by dragging * a block. * @param {number=} opt_distance The max allowable distance between the @@ -35,61 +38,63 @@ Blockly.IConnectionChecker = function() {}; * @return {boolean} Whether the connection is legal. * @public */ -Blockly.IConnectionChecker.prototype.canConnect; +IConnectionChecker.prototype.canConnect; /** * Checks whether the current connection can connect with the target * connection, and return an error code if there are problems. - * @param {Blockly.Connection} a Connection to check compatibility with. - * @param {Blockly.Connection} b Connection to check compatibility with. + * @param {Connection} a Connection to check compatibility with. + * @param {Connection} b Connection to check compatibility with. * @param {boolean} isDragging True if the connection is being made by dragging * a block. * @param {number=} opt_distance The max allowable distance between the * connections for drag checks. - * @return {number} Blockly.Connection.CAN_CONNECT if the connection is legal, + * @return {number} Connection.CAN_CONNECT if the connection is legal, * an error code otherwise. * @public */ -Blockly.IConnectionChecker.prototype.canConnectWithReason; +IConnectionChecker.prototype.canConnectWithReason; /** * Helper method that translates a connection error code into a string. * @param {number} errorCode The error code. - * @param {Blockly.Connection} a One of the two connections being checked. - * @param {Blockly.Connection} b The second of the two connections being + * @param {Connection} a One of the two connections being checked. + * @param {Connection} b The second of the two connections being * checked. * @return {string} A developer-readable error string. * @public */ -Blockly.IConnectionChecker.prototype.getErrorMessage; +IConnectionChecker.prototype.getErrorMessage; /** * Check that connecting the given connections is safe, meaning that it would * not break any of Blockly's basic assumptions (e.g. no self connections). - * @param {Blockly.Connection} a The first of the connections to check. - * @param {Blockly.Connection} b The second of the connections to check. + * @param {Connection} a The first of the connections to check. + * @param {Connection} b The second of the connections to check. * @return {number} An enum with the reason this connection is safe or unsafe. * @public */ -Blockly.IConnectionChecker.prototype.doSafetyChecks; +IConnectionChecker.prototype.doSafetyChecks; /** * Check whether this connection is compatible with another connection with * respect to the value type system. E.g. square_root("Hello") is not * compatible. - * @param {!Blockly.Connection} a Connection to compare. - * @param {!Blockly.Connection} b Connection to compare against. + * @param {!Connection} a Connection to compare. + * @param {!Connection} b Connection to compare against. * @return {boolean} True if the connections share a type. * @public */ -Blockly.IConnectionChecker.prototype.doTypeChecks; +IConnectionChecker.prototype.doTypeChecks; /** * Check whether this connection can be made by dragging. - * @param {!Blockly.RenderedConnection} a Connection to compare. - * @param {!Blockly.RenderedConnection} b Connection to compare against. + * @param {!RenderedConnection} a Connection to compare. + * @param {!RenderedConnection} b Connection to compare against. * @param {number} distance The maximum allowable distance between connections. * @return {boolean} True if the connection is allowed during a drag. * @public */ -Blockly.IConnectionChecker.prototype.doDragChecks; +IConnectionChecker.prototype.doDragChecks; + +exports = IConnectionChecker; diff --git a/core/interfaces/i_contextmenu.js b/core/interfaces/i_contextmenu.js index fcc406b05..79117d5ed 100644 --- a/core/interfaces/i_contextmenu.js +++ b/core/interfaces/i_contextmenu.js @@ -11,16 +11,19 @@ 'use strict'; -goog.provide('Blockly.IContextMenu'); +goog.module('Blockly.IContextMenu'); +goog.module.declareLegacyNamespace(); /** * @interface */ -Blockly.IContextMenu = function() {}; +const IContextMenu = function() {}; /** * Show the context menu for this object. * @param {!Event} e Mouse event. */ -Blockly.IContextMenu.prototype.showContextMenu; +IContextMenu.prototype.showContextMenu; + +exports = IContextMenu; diff --git a/core/interfaces/i_copyable.js b/core/interfaces/i_copyable.js index 4aeac9776..87b776600 100644 --- a/core/interfaces/i_copyable.js +++ b/core/interfaces/i_copyable.js @@ -11,30 +11,35 @@ 'use strict'; -goog.provide('Blockly.ICopyable'); +goog.module('Blockly.ICopyable'); +goog.module.declareLegacyNamespace(); -goog.requireType('Blockly.ISelectable'); -goog.requireType('Blockly.WorkspaceSvg'); +/* eslint-disable-next-line no-unused-vars */ +const ISelectable = goog.requireType('Blockly.ISelectable'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); /** - * @extends {Blockly.ISelectable} + * @extends {ISelectable} * @interface */ -Blockly.ICopyable = function() {}; +const ICopyable = function() {}; /** * Encode for copying. - * @return {?Blockly.ICopyable.CopyData} Copy metadata. + * @return {?ICopyable.CopyData} Copy metadata. */ -Blockly.ICopyable.prototype.toCopyData; +ICopyable.prototype.toCopyData; /** * Copy Metadata. * @typedef {{ * xml:!Element, - * source:Blockly.WorkspaceSvg, + * source:WorkspaceSvg, * typeCounts:?Object * }} */ -Blockly.ICopyable.CopyData; +ICopyable.CopyData; + +exports = ICopyable; diff --git a/core/interfaces/i_deletable.js b/core/interfaces/i_deletable.js index 8e8524863..ff24023d9 100644 --- a/core/interfaces/i_deletable.js +++ b/core/interfaces/i_deletable.js @@ -11,17 +11,20 @@ 'use strict'; -goog.provide('Blockly.IDeletable'); +goog.module('Blockly.IDeletable'); +goog.module.declareLegacyNamespace(); /** * The interface for an object that can be deleted. * @interface */ -Blockly.IDeletable = function() {}; +const IDeletable = function() {}; /** * Get whether this object is deletable or not. * @return {boolean} True if deletable. */ -Blockly.IDeletable.prototype.isDeletable; +IDeletable.prototype.isDeletable; + +exports = IDeletable; diff --git a/core/interfaces/i_delete_area.js b/core/interfaces/i_delete_area.js index 31f53350e..845d7dddb 100644 --- a/core/interfaces/i_delete_area.js +++ b/core/interfaces/i_delete_area.js @@ -12,31 +12,35 @@ 'use strict'; -goog.provide('Blockly.IDeleteArea'); +goog.module('Blockly.IDeleteArea'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.IDragTarget'); - -goog.requireType('Blockly.IDraggable'); +/* eslint-disable-next-line no-unused-vars */ +const IDraggable = goog.requireType('Blockly.IDraggable'); +/* eslint-disable-next-line no-unused-vars */ +const IDragTarget = goog.require('Blockly.IDragTarget'); /** * Interface for a component that can delete a block or bubble that is dropped * on top of it. - * @extends {Blockly.IDragTarget} + * @extends {IDragTarget} * @interface */ -Blockly.IDeleteArea = function() {}; +const IDeleteArea = function() {}; /** * Returns whether the provided block or bubble would be deleted if dropped on * this area. * This method should check if the element is deletable and is always called * before onDragEnter/onDragOver/onDragExit. - * @param {!Blockly.IDraggable} element The block or bubble currently being + * @param {!IDraggable} element The block or bubble currently being * dragged. * @param {boolean} couldConnect Whether the element could could connect to * another. * @return {boolean} Whether the element provided would be deleted if dropped on * this area. */ -Blockly.IDeleteArea.prototype.wouldDelete; +IDeleteArea.prototype.wouldDelete; + +exports = IDeleteArea; diff --git a/core/interfaces/i_drag_target.js b/core/interfaces/i_drag_target.js index 0af765d57..6b777781d 100644 --- a/core/interfaces/i_drag_target.js +++ b/core/interfaces/i_drag_target.js @@ -12,67 +12,73 @@ 'use strict'; -goog.provide('Blockly.IDragTarget'); +goog.module('Blockly.IDragTarget'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.IComponent'); +/* eslint-disable-next-line no-unused-vars */ +const IComponent = goog.require('Blockly.IComponent'); +/* eslint-disable-next-line no-unused-vars */ +const IDraggable = goog.requireType('Blockly.IDraggable'); +/* eslint-disable-next-line no-unused-vars */ +const Rect = goog.requireType('Blockly.utils.Rect'); -goog.requireType('Blockly.IDraggable'); -goog.requireType('Blockly.utils.Rect'); /** * Interface for a component with custom behaviour when a block or bubble is * dragged over or dropped on top of it. - * @extends {Blockly.IComponent} + * @extends {IComponent} * @interface */ -Blockly.IDragTarget = function() {}; +const IDragTarget = 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.IDragTarget.prototype.getClientRect; +IDragTarget.prototype.getClientRect; /** * Handles when a cursor with a block or bubble enters this drag target. - * @param {!Blockly.IDraggable} dragElement The block or bubble currently being + * @param {!IDraggable} dragElement The block or bubble currently being * dragged. */ -Blockly.IDragTarget.prototype.onDragEnter; +IDragTarget.prototype.onDragEnter; /** * Handles when a cursor with a block or bubble is dragged over this drag * target. - * @param {!Blockly.IDraggable} dragElement The block or bubble currently being + * @param {!IDraggable} dragElement The block or bubble currently being * dragged. */ -Blockly.IDragTarget.prototype.onDragOver; +IDragTarget.prototype.onDragOver; /** * Handles when a cursor with a block or bubble exits this drag target. - * @param {!Blockly.IDraggable} dragElement The block or bubble currently being + * @param {!IDraggable} dragElement The block or bubble currently being * dragged. */ -Blockly.IDragTarget.prototype.onDragExit; +IDragTarget.prototype.onDragExit; /** * Handles when a block or bubble is dropped on this component. * Should not handle delete here. - * @param {!Blockly.IDraggable} dragElement The block or bubble currently being + * @param {!IDraggable} dragElement The block or bubble currently being * dragged. */ -Blockly.IDragTarget.prototype.onDrop; +IDragTarget.prototype.onDrop; /** * Returns whether the provided block or bubble should not be moved after being * dropped on this component. If true, the element will return to where it was * when the drag started. - * @param {!Blockly.IDraggable} dragElement The block or bubble currently being + * @param {!IDraggable} dragElement The block or bubble currently being * dragged. * @return {boolean} Whether the block or bubble provided should be returned to * drag start. */ -Blockly.IDragTarget.prototype.shouldPreventMove; +IDragTarget.prototype.shouldPreventMove; + +exports = IDragTarget; diff --git a/core/interfaces/i_draggable.js b/core/interfaces/i_draggable.js index f140555a1..5d7e17d53 100644 --- a/core/interfaces/i_draggable.js +++ b/core/interfaces/i_draggable.js @@ -11,14 +11,18 @@ 'use strict'; -goog.provide('Blockly.IDraggable'); +goog.module('Blockly.IDraggable'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.IDeletable'); +/* eslint-disable-next-line no-unused-vars */ +const IDeletable = goog.require('Blockly.IDeletable'); /** * The interface for an object that can be dragged. - * @extends {Blockly.IDeletable} + * @extends {IDeletable} * @interface */ -Blockly.IDraggable = function() {}; +const IDraggable = function() {}; + +exports = IDraggable; diff --git a/core/interfaces/i_flyout.js b/core/interfaces/i_flyout.js index b819c3347..23c76dd0b 100644 --- a/core/interfaces/i_flyout.js +++ b/core/interfaces/i_flyout.js @@ -11,179 +11,188 @@ 'use strict'; -goog.provide('Blockly.IFlyout'); +goog.module('Blockly.IFlyout'); +goog.module.declareLegacyNamespace(); -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.IRegistrable'); -goog.requireType('Blockly.utils.Coordinate'); -goog.requireType('Blockly.utils.Svg'); -goog.requireType('Blockly.utils.toolbox'); -goog.requireType('Blockly.WorkspaceSvg'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +/* eslint-disable-next-line no-unused-vars */ +const Coordinate = goog.requireType('Blockly.utils.Coordinate'); +/* eslint-disable-next-line no-unused-vars */ +const IRegistrable = goog.require('Blockly.IRegistrable'); +/* eslint-disable-next-line no-unused-vars */ +const Svg = goog.requireType('Blockly.utils.Svg'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +/* eslint-disable-next-line no-unused-vars */ +const {FlyoutDefinition} = goog.requireType('Blockly.utils.toolbox'); /** * Interface for a flyout. - * @extends {Blockly.IRegistrable} + * @extends {IRegistrable} * @interface */ -Blockly.IFlyout = function() {}; +const IFlyout = function() {}; /** * Whether the flyout is laid out horizontally or not. * @type {boolean} */ -Blockly.IFlyout.prototype.horizontalLayout; +IFlyout.prototype.horizontalLayout; /** * Is RTL vs LTR. * @type {boolean} */ -Blockly.IFlyout.prototype.RTL; +IFlyout.prototype.RTL; /** * The target workspace - * @type {?Blockly.WorkspaceSvg} + * @type {?WorkspaceSvg} */ -Blockly.IFlyout.prototype.targetWorkspace; +IFlyout.prototype.targetWorkspace; /** * Margin around the edges of the blocks in the flyout. * @type {number} * @const */ -Blockly.IFlyout.prototype.MARGIN; +IFlyout.prototype.MARGIN; /** * Does the flyout automatically close when a block is created? * @type {boolean} */ -Blockly.IFlyout.prototype.autoClose; +IFlyout.prototype.autoClose; /** * Corner radius of the flyout background. * @type {number} * @const */ -Blockly.IFlyout.prototype.CORNER_RADIUS; +IFlyout.prototype.CORNER_RADIUS; /** * 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.IFlyout.prototype.createDom; +IFlyout.prototype.createDom; /** * Initializes the flyout. - * @param {!Blockly.WorkspaceSvg} targetWorkspace The workspace in which to + * @param {!WorkspaceSvg} targetWorkspace The workspace in which to * create new blocks. */ -Blockly.IFlyout.prototype.init; +IFlyout.prototype.init; /** * Dispose of this flyout. * Unlink from all DOM elements to prevent memory leaks. */ -Blockly.IFlyout.prototype.dispose; +IFlyout.prototype.dispose; /** * Get the width of the flyout. * @return {number} The width of the flyout. */ -Blockly.IFlyout.prototype.getWidth; +IFlyout.prototype.getWidth; /** * Get the height of the flyout. * @return {number} The width of the flyout. */ -Blockly.IFlyout.prototype.getHeight; +IFlyout.prototype.getHeight; /** * Get the workspace inside the flyout. - * @return {!Blockly.WorkspaceSvg} The workspace inside the flyout. + * @return {!WorkspaceSvg} The workspace inside the flyout. */ -Blockly.IFlyout.prototype.getWorkspace; +IFlyout.prototype.getWorkspace; /** * Is the flyout visible? * @return {boolean} True if visible. */ -Blockly.IFlyout.prototype.isVisible; +IFlyout.prototype.isVisible; /** * Set whether the flyout is visible. A value of true does not necessarily mean * that the flyout is shown. It could be hidden because its container is hidden. * @param {boolean} visible True if visible. */ -Blockly.IFlyout.prototype.setVisible; +IFlyout.prototype.setVisible; /** * Set whether this flyout's container is visible. * @param {boolean} visible Whether the container is visible. */ -Blockly.IFlyout.prototype.setContainerVisible; +IFlyout.prototype.setContainerVisible; /** * Hide and empty the flyout. */ -Blockly.IFlyout.prototype.hide; +IFlyout.prototype.hide; /** * Show and populate the flyout. - * @param {!Blockly.utils.toolbox.FlyoutDefinition|string} flyoutDef Contents to + * @param {!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.IFlyout.prototype.show; +IFlyout.prototype.show; /** * 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. */ -Blockly.IFlyout.prototype.createBlock; +IFlyout.prototype.createBlock; /** * Reflow blocks and their mats. */ -Blockly.IFlyout.prototype.reflow; +IFlyout.prototype.reflow; /** * @return {boolean} True if this flyout may be scrolled with a scrollbar or by * dragging. */ -Blockly.IFlyout.prototype.isScrollable; +IFlyout.prototype.isScrollable; /** * Calculates the x coordinate for the flyout position. * @return {number} X coordinate. */ -Blockly.IFlyout.prototype.getX; +IFlyout.prototype.getX; /** * Calculates the y coordinate for the flyout position. * @return {number} Y coordinate. */ -Blockly.IFlyout.prototype.getY; +IFlyout.prototype.getY; /** * Position the flyout. * @return {void} */ -Blockly.IFlyout.prototype.position; +IFlyout.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. */ -Blockly.IFlyout.prototype.isDragTowardWorkspace; +IFlyout.prototype.isDragTowardWorkspace; + +exports = IFlyout; diff --git a/core/interfaces/i_keyboard_accessible.js b/core/interfaces/i_keyboard_accessible.js new file mode 100644 index 000000000..04704a2fe --- /dev/null +++ b/core/interfaces/i_keyboard_accessible.js @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for objects that handle keyboard shortcuts. + * @author samelh@google.com (Sam El-Husseini) + */ + +'use strict'; + +goog.module('Blockly.IKeyboardAccessible'); +goog.module.declareLegacyNamespace(); + +/* eslint-disable-next-line no-unused-vars */ +const ShortcutRegistry = goog.requireType('Blockly.ShortcutRegistry'); + + +/** + * An interface for an object that handles keyboard shortcuts. + * @interface + */ +const IKeyboardAccessible = function() {}; + +/** + * Handles the given keyboard shortcut. + * @param {!ShortcutRegistry.KeyboardShortcut} shortcut The shortcut to be + * handled. + * @return {boolean} True if the shortcut has been handled, false otherwise. + */ +IKeyboardAccessible.prototype.onShortcut; + +exports = IKeyboardAccessible; diff --git a/core/interfaces/i_metrics_manager.js b/core/interfaces/i_metrics_manager.js index 916f14d5d..db1f575c1 100644 --- a/core/interfaces/i_metrics_manager.js +++ b/core/interfaces/i_metrics_manager.js @@ -11,92 +11,96 @@ 'use strict'; -goog.provide('Blockly.IMetricsManager'); +goog.module('Blockly.IMetricsManager'); +goog.module.declareLegacyNamespace(); -goog.requireType('Blockly.MetricsManager'); -goog.requireType('Blockly.utils.Metrics'); -goog.requireType('Blockly.utils.Size'); +/* eslint-disable-next-line no-unused-vars */ +const Metrics = goog.requireType('Blockly.utils.Metrics'); +/* eslint-disable-next-line no-unused-vars */ +const Size = goog.requireType('Blockly.utils.Size'); +/* eslint-disable-next-line no-unused-vars */ +const {AbsoluteMetrics, ContainerRegion, ToolboxMetrics} = goog.requireType('Blockly.MetricsManager'); /** * Interface for a metrics manager. * @interface */ -Blockly.IMetricsManager = function() {}; +const IMetricsManager = function() {}; /** * Returns whether the scroll area has fixed edges. * @return {boolean} Whether the scroll area has fixed edges. * @package */ -Blockly.IMetricsManager.prototype.hasFixedEdges; +IMetricsManager.prototype.hasFixedEdges; /** * Returns the metrics for the scroll area of the workspace. * @param {boolean=} opt_getWorkspaceCoordinates True to get the scroll metrics * in workspace coordinates, false to get them in pixel coordinates. - * @param {!Blockly.MetricsManager.ContainerRegion=} opt_viewMetrics The view + * @param {!ContainerRegion=} opt_viewMetrics The view * metrics if they have been previously computed. Passing in null may cause * the view metrics to be computed again, if it is needed. - * @param {!Blockly.MetricsManager.ContainerRegion=} opt_contentMetrics The + * @param {!ContainerRegion=} opt_contentMetrics The * content metrics if they have been previously computed. Passing in null * may cause the content metrics to be computed again, if it is needed. - * @return {!Blockly.MetricsManager.ContainerRegion} The metrics for the scroll + * @return {!ContainerRegion} The metrics for the scroll * container */ -Blockly.IMetricsManager.prototype.getScrollMetrics; +IMetricsManager.prototype.getScrollMetrics; /** * Gets the width and the height of the flyout on the workspace in pixel * coordinates. Returns 0 for the width and height if the workspace has a * category toolbox instead of a simple toolbox. * @param {boolean=} opt_own Whether to only return the workspace's own flyout. - * @return {!Blockly.MetricsManager.ToolboxMetrics} The width and height of the + * @return {!ToolboxMetrics} The width and height of the * flyout. * @public */ -Blockly.IMetricsManager.prototype.getFlyoutMetrics; +IMetricsManager.prototype.getFlyoutMetrics; /** * Gets the width, height and position of the toolbox on the workspace in pixel * coordinates. Returns 0 for the width and height if the workspace has a simple * toolbox instead of a category toolbox. To get the width and height of a * simple toolbox @see {@link getFlyoutMetrics}. - * @return {!Blockly.MetricsManager.ToolboxMetrics} The object with the width, + * @return {!ToolboxMetrics} The object with the width, * height and position of the toolbox. * @public */ -Blockly.IMetricsManager.prototype.getToolboxMetrics; +IMetricsManager.prototype.getToolboxMetrics; /** * Gets the width and height of the workspace's parent SVG element in pixel * coordinates. This area includes the toolbox and the visible workspace area. - * @return {!Blockly.utils.Size} The width and height of the workspace's parent + * @return {!Size} The width and height of the workspace's parent * SVG element. * @public */ -Blockly.IMetricsManager.prototype.getSvgMetrics; +IMetricsManager.prototype.getSvgMetrics; /** * Gets the absolute left and absolute top in pixel coordinates. * This is where the visible workspace starts in relation to the SVG container. - * @return {!Blockly.MetricsManager.AbsoluteMetrics} The absolute metrics for + * @return {!AbsoluteMetrics} The absolute metrics for * the workspace. * @public */ -Blockly.IMetricsManager.prototype.getAbsoluteMetrics; +IMetricsManager.prototype.getAbsoluteMetrics; /** * Gets the metrics for the visible workspace in either pixel or workspace * coordinates. The visible workspace does not include the toolbox or flyout. * @param {boolean=} opt_getWorkspaceCoordinates True to get the view metrics in * workspace coordinates, false to get them in pixel coordinates. - * @return {!Blockly.MetricsManager.ContainerRegion} The width, height, top and + * @return {!ContainerRegion} The width, height, top and * left of the viewport in either workspace coordinates or pixel * coordinates. * @public */ -Blockly.IMetricsManager.prototype.getViewMetrics; +IMetricsManager.prototype.getViewMetrics; /** * Gets content metrics in either pixel or workspace coordinates. @@ -104,11 +108,11 @@ Blockly.IMetricsManager.prototype.getViewMetrics; * workspace (workspace comments and blocks). * @param {boolean=} opt_getWorkspaceCoordinates True to get the content metrics * in workspace coordinates, false to get them in pixel coordinates. - * @return {!Blockly.MetricsManager.ContainerRegion} The + * @return {!ContainerRegion} The * metrics for the content container. * @public */ -Blockly.IMetricsManager.prototype.getContentMetrics; +IMetricsManager.prototype.getContentMetrics; /** * Returns an object with all the metrics required to size scrollbars for a @@ -138,8 +142,10 @@ Blockly.IMetricsManager.prototype.getContentMetrics; * .flyoutHeight: Height of the flyout if it is always open. Otherwise zero. * .toolboxPosition: Top, bottom, left or right. Use TOOLBOX_AT constants to * compare. - * @return {!Blockly.utils.Metrics} Contains size and position metrics of a top + * @return {!Metrics} Contains size and position metrics of a top * level workspace. * @public */ -Blockly.IMetricsManager.prototype.getMetrics; +IMetricsManager.prototype.getMetrics; + +exports = IMetricsManager; diff --git a/core/interfaces/i_movable.js b/core/interfaces/i_movable.js index bc0c3bf9f..25a92d6bb 100644 --- a/core/interfaces/i_movable.js +++ b/core/interfaces/i_movable.js @@ -11,17 +11,20 @@ 'use strict'; -goog.provide('Blockly.IMovable'); +goog.module('Blockly.IMovable'); +goog.module.declareLegacyNamespace(); /** * The interface for an object that is movable. * @interface */ -Blockly.IMovable = function() {}; +const IMovable = function() {}; /** * Get whether this is movable or not. * @return {boolean} True if movable. */ -Blockly.IMovable.prototype.isMovable; +IMovable.prototype.isMovable; + +exports = IMovable; diff --git a/core/interfaces/i_positionable.js b/core/interfaces/i_positionable.js index 356510c81..1fe773add 100644 --- a/core/interfaces/i_positionable.js +++ b/core/interfaces/i_positionable.js @@ -11,33 +11,38 @@ 'use strict'; -goog.provide('Blockly.IPositionable'); +goog.module('Blockly.IPositionable'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.IComponent'); - -goog.requireType('Blockly.MetricsManager'); -goog.requireType('Blockly.utils.Rect'); +/* eslint-disable-next-line no-unused-vars */ +const IComponent = goog.require('Blockly.IComponent'); +/* eslint-disable-next-line no-unused-vars */ +const Rect = goog.requireType('Blockly.utils.Rect'); +/* eslint-disable-next-line no-unused-vars */ +const {UiMetrics} = goog.requireType('Blockly.MetricsManager'); /** * Interface for a component that is positioned on top of the workspace. - * @extends {Blockly.IComponent} + * @extends {IComponent} * @interface */ -Blockly.IPositionable = function() {}; +const IPositionable = function() {}; /** * Positions the element. Called when the window is resized. - * @param {!Blockly.MetricsManager.UiMetrics} metrics The workspace metrics. - * @param {!Array} savedPositions List of rectangles that + * @param {!UiMetrics} metrics The workspace metrics. + * @param {!Array} savedPositions List of rectangles that * are already on the workspace. */ -Blockly.IPositionable.prototype.position; +IPositionable.prototype.position; /** * 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.IPositionable.prototype.getBoundingRectangle; +IPositionable.prototype.getBoundingRectangle; + +exports = IPositionable; diff --git a/core/interfaces/i_registrable.js b/core/interfaces/i_registrable.js index f7b8ca719..5698ad313 100644 --- a/core/interfaces/i_registrable.js +++ b/core/interfaces/i_registrable.js @@ -12,11 +12,14 @@ 'use strict'; -goog.provide('Blockly.IRegistrable'); +goog.module('Blockly.IRegistrable'); +goog.module.declareLegacyNamespace(); /** * The interface for a Blockly component that can be registered. * @interface */ -Blockly.IRegistrable = function() {}; +const IRegistrable = function() {}; + +exports = IRegistrable; diff --git a/core/interfaces/i_registrable_field.js b/core/interfaces/i_registrable_field.js index 1d49edad2..c9d04325d 100644 --- a/core/interfaces/i_registrable_field.js +++ b/core/interfaces/i_registrable_field.js @@ -11,21 +11,26 @@ 'use strict'; -goog.provide('Blockly.IRegistrableField'); +goog.module('Blockly.IRegistrableField'); +goog.module.declareLegacyNamespace(); + +/* eslint-disable-next-line no-unused-vars */ +const Field = goog.requireType('Blockly.Field'); -goog.requireType('Blockly.Field'); /** * A registrable field. * Note: We are not using an interface here as we are interested in defining the * static methods of a field rather than the instance methods. * @typedef {{ - * fromJson:Blockly.IRegistrableField.fromJson + * fromJson:IRegistrableField.fromJson * }} */ -Blockly.IRegistrableField; +let IRegistrableField; /** - * @typedef {function(!Object): Blockly.Field} + * @typedef {function(!Object): Field} */ -Blockly.IRegistrableField.fromJson; +IRegistrableField.fromJson; + +exports = IRegistrableField; diff --git a/core/interfaces/i_selectable.js b/core/interfaces/i_selectable.js index e3d817fde..d3355f9ab 100644 --- a/core/interfaces/i_selectable.js +++ b/core/interfaces/i_selectable.js @@ -11,7 +11,8 @@ 'use strict'; -goog.provide('Blockly.ISelectable'); +goog.module('Blockly.ISelectable'); +goog.module.declareLegacyNamespace(); goog.requireType('Blockly.IDeletable'); goog.requireType('Blockly.IMovable'); @@ -23,21 +24,23 @@ goog.requireType('Blockly.IMovable'); * @extends {Blockly.IMovable} * @interface */ -Blockly.ISelectable = function() {}; +const ISelectable = function() {}; /** * @type {string} */ -Blockly.ISelectable.prototype.id; +ISelectable.prototype.id; /** * Select this. Highlight it visually. * @return {void} */ -Blockly.ISelectable.prototype.select; +ISelectable.prototype.select; /** * Unselect this. Unhighlight it visually. * @return {void} */ -Blockly.ISelectable.prototype.unselect; +ISelectable.prototype.unselect; + +exports = ISelectable; diff --git a/core/interfaces/i_selectable_toolbox_item.js b/core/interfaces/i_selectable_toolbox_item.js new file mode 100644 index 000000000..cefe35740 --- /dev/null +++ b/core/interfaces/i_selectable_toolbox_item.js @@ -0,0 +1,70 @@ +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview The interface for a selectable toolbox item. + * @author aschmiedt@google.com (Abby Schmiedt) + */ + +'use strict'; + +goog.module('Blockly.ISelectableToolboxItem'); +goog.module.declareLegacyNamespace(); + +/* eslint-disable-next-line no-unused-vars */ +const IToolboxItem = goog.require('Blockly.IToolboxItem'); +/* eslint-disable-next-line no-unused-vars */ +const {FlyoutItemInfoArray} = goog.requireType('Blockly.utils.toolbox'); + + +/** + * Interface for an item in the toolbox that can be selected. + * @extends {IToolboxItem} + * @interface + */ +const ISelectableToolboxItem = function() {}; + +/** + * Gets the name of the toolbox item. Used for emitting events. + * @return {string} The name of the toolbox item. + * @public + */ +ISelectableToolboxItem.prototype.getName; + +/** + * Gets the contents of the toolbox item. These are items that are meant to be + * displayed in the flyout. + * @return {!FlyoutItemInfoArray|string} The definition + * of items to be displayed in the flyout. + * @public + */ +ISelectableToolboxItem.prototype.getContents; + +/** + * Sets the current toolbox item as selected. + * @param {boolean} _isSelected True if this category is selected, false + * otherwise. + * @public + */ +ISelectableToolboxItem.prototype.setSelected; + +/** + * Gets the HTML element that is clickable. + * The parent toolbox element receives clicks. The parent toolbox will add an ID + * to this element so it can pass the onClick event to the correct toolboxItem. + * @return {!Element} The HTML element that receives clicks. + * @public + */ +ISelectableToolboxItem.prototype.getClickTarget; + +/** + * Handles when the toolbox item is clicked. + * @param {!Event} _e Click event to handle. + * @public + */ +ISelectableToolboxItem.prototype.onClick; + +exports = ISelectableToolboxItem; diff --git a/core/interfaces/i_styleable.js b/core/interfaces/i_styleable.js index 944ee9d65..14dea3ce1 100644 --- a/core/interfaces/i_styleable.js +++ b/core/interfaces/i_styleable.js @@ -11,23 +11,26 @@ 'use strict'; -goog.provide('Blockly.IStyleable'); +goog.module('Blockly.IStyleable'); +goog.module.declareLegacyNamespace(); /** * Interface for an object that a style can be added to. * @interface */ -Blockly.IStyleable = function() {}; +const IStyleable = function() {}; /** * Adds a style on the toolbox. Usually used to change the cursor. * @param {string} style The name of the class to add. */ -Blockly.IStyleable.prototype.addStyle; +IStyleable.prototype.addStyle; /** * Removes a style from the toolbox. Usually used to change the cursor. * @param {string} style The name of the class to remove. */ -Blockly.IStyleable.prototype.removeStyle; +IStyleable.prototype.removeStyle; + +exports = IStyleable; diff --git a/core/interfaces/i_toolbox.js b/core/interfaces/i_toolbox.js index 208be48cc..0c7e7deb3 100644 --- a/core/interfaces/i_toolbox.js +++ b/core/interfaces/i_toolbox.js @@ -11,90 +11,96 @@ 'use strict'; -goog.provide('Blockly.IToolbox'); +goog.module('Blockly.IToolbox'); +goog.module.declareLegacyNamespace(); -goog.requireType('Blockly.IFlyout'); -goog.requireType('Blockly.IRegistrable'); -goog.requireType('Blockly.IToolboxItem'); -goog.requireType('Blockly.utils.toolbox'); -goog.requireType('Blockly.WorkspaceSvg'); +/* eslint-disable-next-line no-unused-vars */ +const IFlyout = goog.requireType('Blockly.IFlyout'); +/* eslint-disable-next-line no-unused-vars */ +const IRegistrable = goog.require('Blockly.IRegistrable'); +/* eslint-disable-next-line no-unused-vars */ +const IToolboxItem = goog.requireType('Blockly.IToolboxItem'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +/* eslint-disable-next-line no-unused-vars */ +const {ToolboxInfo} = goog.requireType('Blockly.utils.toolbox'); /** * Interface for a toolbox. - * @extends {Blockly.IRegistrable} + * @extends {IRegistrable} * @interface */ -Blockly.IToolbox = function() {}; +const IToolbox = function() {}; /** * Initializes the toolbox. * @return {void} */ -Blockly.IToolbox.prototype.init; +IToolbox.prototype.init; /** * Fills the toolbox with new toolbox items and removes any old contents. - * @param {!Blockly.utils.toolbox.ToolboxInfo} toolboxDef Object holding information + * @param {!ToolboxInfo} toolboxDef Object holding information * for creating a toolbox. */ -Blockly.IToolbox.prototype.render; +IToolbox.prototype.render; /** * Gets the width of the toolbox. * @return {number} The width of the toolbox. */ -Blockly.IToolbox.prototype.getWidth; +IToolbox.prototype.getWidth; /** * Gets the height of the toolbox. * @return {number} The width of the toolbox. */ -Blockly.IToolbox.prototype.getHeight; +IToolbox.prototype.getHeight; /** * Gets the toolbox flyout. - * @return {?Blockly.IFlyout} The toolbox flyout. + * @return {?IFlyout} The toolbox flyout. */ -Blockly.IToolbox.prototype.getFlyout; +IToolbox.prototype.getFlyout; /** * Gets the workspace for the toolbox. - * @return {!Blockly.WorkspaceSvg} The parent workspace for the toolbox. + * @return {!WorkspaceSvg} The parent workspace for the toolbox. */ -Blockly.IToolbox.prototype.getWorkspace; +IToolbox.prototype.getWorkspace; /** * Gets whether or not the toolbox is horizontal. * @return {boolean} True if the toolbox is horizontal, false if the toolbox is * vertical. */ -Blockly.IToolbox.prototype.isHorizontal; +IToolbox.prototype.isHorizontal; /** * Positions the toolbox based on whether it is a horizontal toolbox and whether * the workspace is in rtl. * @return {void} */ -Blockly.IToolbox.prototype.position; +IToolbox.prototype.position; /** * Handles resizing the toolbox when a toolbox item resizes. * @return {void} */ -Blockly.IToolbox.prototype.handleToolboxItemResize; +IToolbox.prototype.handleToolboxItemResize; /** * Unhighlights any previously selected item. * @return {void} */ -Blockly.IToolbox.prototype.clearSelection; +IToolbox.prototype.clearSelection; /** * Updates the category colours and background colour of selected categories. * @return {void} */ -Blockly.IToolbox.prototype.refreshTheme; +IToolbox.prototype.refreshTheme; /** * Updates the flyout's content without closing it. Should be used in response @@ -102,30 +108,32 @@ Blockly.IToolbox.prototype.refreshTheme; * procedures. * @return {void} */ -Blockly.IToolbox.prototype.refreshSelection; +IToolbox.prototype.refreshSelection; /** * Sets the visibility of the toolbox. * @param {boolean} isVisible True if toolbox should be visible. */ -Blockly.IToolbox.prototype.setVisible; +IToolbox.prototype.setVisible; /** * Selects the toolbox item by it's position in the list of toolbox items. * @param {number} position The position of the item to select. * @return {void} */ -Blockly.IToolbox.prototype.selectItemByPosition; +IToolbox.prototype.selectItemByPosition; /** * Gets the selected item. - * @return {?Blockly.IToolboxItem} The selected item, or null if no item is + * @return {?IToolboxItem} The selected item, or null if no item is * currently selected. */ -Blockly.IToolbox.prototype.getSelectedItem; +IToolbox.prototype.getSelectedItem; /** * Disposes of this toolbox. * @return {void} */ -Blockly.IToolbox.prototype.dispose; +IToolbox.prototype.dispose; + +exports = IToolbox; diff --git a/core/interfaces/i_toolbox_item.js b/core/interfaces/i_toolbox_item.js index afd6191f7..061b7ae27 100644 --- a/core/interfaces/i_toolbox_item.js +++ b/core/interfaces/i_toolbox_item.js @@ -11,18 +11,15 @@ 'use strict'; -goog.provide('Blockly.ICollapsibleToolboxItem'); -goog.provide('Blockly.ISelectableToolboxItem'); -goog.provide('Blockly.IToolboxItem'); - -goog.requireType('Blockly.utils.toolbox'); +goog.module('Blockly.IToolboxItem'); +goog.module.declareLegacyNamespace(); /** * Interface for an item in the toolbox. * @interface */ -Blockly.IToolboxItem = function() {}; +const IToolboxItem = function() {}; /** * Initializes the toolbox item. @@ -31,21 +28,21 @@ Blockly.IToolboxItem = function() {}; * @return {void} * @public */ -Blockly.IToolboxItem.prototype.init; +IToolboxItem.prototype.init; /** * Gets the div for the toolbox item. * @return {?Element} The div for the toolbox item. * @public */ -Blockly.IToolboxItem.prototype.getDiv; +IToolboxItem.prototype.getDiv; /** * Gets a unique identifier for this toolbox item. * @return {string} The ID for the toolbox item. * @public */ -Blockly.IToolboxItem.prototype.getId; +IToolboxItem.prototype.getId; /** * Gets the parent if the toolbox item is nested. @@ -53,105 +50,33 @@ Blockly.IToolboxItem.prototype.getId; * this toolbox item is not nested. * @public */ -Blockly.IToolboxItem.prototype.getParent; +IToolboxItem.prototype.getParent; /** * Gets the nested level of the category. * @return {number} The nested level of the category. * @package */ -Blockly.IToolboxItem.prototype.getLevel; +IToolboxItem.prototype.getLevel; /** * Whether the toolbox item is selectable. * @return {boolean} True if the toolbox item can be selected. * @public */ -Blockly.IToolboxItem.prototype.isSelectable; +IToolboxItem.prototype.isSelectable; /** * Whether the toolbox item is collapsible. * @return {boolean} True if the toolbox item is collapsible. * @public */ -Blockly.IToolboxItem.prototype.isCollapsible; +IToolboxItem.prototype.isCollapsible; /** * Dispose of this toolbox item. No-op by default. * @public */ -Blockly.IToolboxItem.prototype.dispose; +IToolboxItem.prototype.dispose; -/** - * Interface for an item in the toolbox that can be selected. - * @extends {Blockly.IToolboxItem} - * @interface - */ -Blockly.ISelectableToolboxItem = function() {}; - -/** - * Gets the name of the toolbox item. Used for emitting events. - * @return {string} The name of the toolbox item. - * @public - */ -Blockly.ISelectableToolboxItem.prototype.getName; - -/** - * Gets the contents of the toolbox item. These are items that are meant to be - * displayed in the flyout. - * @return {!Blockly.utils.toolbox.FlyoutItemInfoArray|string} The definition - * of items to be displayed in the flyout. - * @public - */ -Blockly.ISelectableToolboxItem.prototype.getContents; - -/** - * Sets the current toolbox item as selected. - * @param {boolean} _isSelected True if this category is selected, false - * otherwise. - * @public - */ -Blockly.ISelectableToolboxItem.prototype.setSelected; - -/** - * Gets the HTML element that is clickable. - * The parent toolbox element receives clicks. The parent toolbox will add an ID - * to this element so it can pass the onClick event to the correct toolboxItem. - * @return {!Element} The HTML element that receives clicks. - * @public - */ -Blockly.ISelectableToolboxItem.prototype.getClickTarget; - -/** - * Handles when the toolbox item is clicked. - * @param {!Event} _e Click event to handle. - * @public - */ -Blockly.ISelectableToolboxItem.prototype.onClick; - -/** - * Interface for an item in the toolbox that can be collapsed. - * @extends {Blockly.ISelectableToolboxItem} - * @interface - */ -Blockly.ICollapsibleToolboxItem = function() {}; - -/** - * Gets any children toolbox items. (ex. Gets the subcategories) - * @return {!Array} The child toolbox items. - */ -Blockly.ICollapsibleToolboxItem.prototype.getChildToolboxItems; - -/** - * Whether the toolbox item is expanded to show its child subcategories. - * @return {boolean} True if the toolbox item shows its children, false if it - * is collapsed. - * @public - */ -Blockly.ICollapsibleToolboxItem.prototype.isExpanded; - -/** - * Toggles whether or not the toolbox item is expanded. - * @public - */ -Blockly.ICollapsibleToolboxItem.prototype.toggleExpanded; +exports = IToolboxItem; diff --git a/core/internal_constants.js b/core/internal_constants.js new file mode 100644 index 000000000..b97c723b4 --- /dev/null +++ b/core/internal_constants.js @@ -0,0 +1,218 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Module that provides constants for use inside Blockly. Do not + * use these constants outside of the core library. + * @author fenichel@google.com (Rachel Fenichel) + * @package + */ +'use strict'; + +goog.module('Blockly.internalConstants'); +goog.module.declareLegacyNamespace(); + +const connectionTypes = goog.require('Blockly.connectionTypes'); + + +/** + * The multiplier for scroll wheel deltas using the line delta mode. + * @type {number} + */ +const LINE_MODE_MULTIPLIER = 40; +exports.LINE_MODE_MULTIPLIER = LINE_MODE_MULTIPLIER; + +/** + * The multiplier for scroll wheel deltas using the page delta mode. + * @type {number} + */ +const PAGE_MODE_MULTIPLIER = 125; +exports.PAGE_MODE_MULTIPLIER = PAGE_MODE_MULTIPLIER; + +/** + * Number of pixels the mouse must move before a drag starts. + */ +const DRAG_RADIUS = 5; +exports.DRAG_RADIUS = DRAG_RADIUS; + +/** + * Number of pixels the mouse must move before a drag/scroll starts from the + * flyout. Because the drag-intention is determined when this is reached, it is + * larger than DRAG_RADIUS so that the drag-direction is clearer. + */ +const FLYOUT_DRAG_RADIUS = 10; +exports.FLYOUT_DRAG_RADIUS = FLYOUT_DRAG_RADIUS; + +/** + * Maximum misalignment between connections for them to snap together. + */ +const SNAP_RADIUS = 28; +exports.SNAP_RADIUS = SNAP_RADIUS; + +/** + * Maximum misalignment between connections for them to snap together, + * when a connection is already highlighted. + */ +const CONNECTING_SNAP_RADIUS = SNAP_RADIUS; +exports.CONNECTING_SNAP_RADIUS = CONNECTING_SNAP_RADIUS; + +/** + * How much to prefer staying connected to the current connection over moving to + * a new connection. The current previewed connection is considered to be this + * much closer to the matching connection on the block than it actually is. + */ +const CURRENT_CONNECTION_PREFERENCE = 8; +exports.CURRENT_CONNECTION_PREFERENCE = CURRENT_CONNECTION_PREFERENCE; + +/** + * Delay in ms between trigger and bumping unconnected block out of alignment. + */ +const BUMP_DELAY = 250; +exports.BUMP_DELAY = BUMP_DELAY; + +/** + * Maximum randomness in workspace units for bumping a block. + */ +const BUMP_RANDOMNESS = 10; +exports.BUMP_RANDOMNESS = BUMP_RANDOMNESS; + +/** + * Number of characters to truncate a collapsed block to. + */ +const COLLAPSE_CHARS = 30; +exports.COLLAPSE_CHARS = COLLAPSE_CHARS; + +/** + * Length in ms for a touch to become a long press. + */ +const LONGPRESS = 750; +exports.LONGPRESS = LONGPRESS; + +/** + * Prevent a sound from playing if another sound preceded it within this many + * milliseconds. + */ +const SOUND_LIMIT = 100; +exports.SOUND_LIMIT = SOUND_LIMIT; + +/** + * When dragging a block out of a stack, split the stack in two (true), or drag + * out the block healing the stack (false). + */ +const DRAG_STACK = true; +exports.DRAG_STACK = DRAG_STACK; + +/** + * The richness of block colours, regardless of the hue. + * Must be in the range of 0 (inclusive) to 1 (exclusive). + */ +const HSV_SATURATION = 0.45; +exports.HSV_SATURATION = HSV_SATURATION; + +/** + * The intensity of block colours, regardless of the hue. + * Must be in the range of 0 (inclusive) to 1 (exclusive). + */ +const HSV_VALUE = 0.65; +exports.HSV_VALUE = HSV_VALUE; + +/** + * Sprited icons and images. + */ +const SPRITE = { + width: 96, + height: 124, + url: 'sprites.png' +}; +exports.SPRITE = SPRITE; + +/** + * ENUM for no drag operation. + * @const + */ +const DRAG_NONE = 0; +exports.DRAG_NONE = DRAG_NONE; + +/** + * ENUM for inside the sticky DRAG_RADIUS. + * @const + */ +const DRAG_STICKY = 1; +exports.DRAG_STICKY = DRAG_STICKY; + +/** + * ENUM for inside the non-sticky DRAG_RADIUS, for differentiating between + * clicks and drags. + * @const + */ +const DRAG_BEGIN = 1; +exports.DRAG_BEGIN = DRAG_BEGIN; + +/** + * ENUM for freely draggable (outside the DRAG_RADIUS, if one applies). + * @const + */ +const DRAG_FREE = 2; +exports.DRAG_FREE = DRAG_FREE; + +/** + * Lookup table for determining the opposite type of a connection. + * @const + */ +const OPPOSITE_TYPE = []; +OPPOSITE_TYPE[connectionTypes.INPUT_VALUE] = connectionTypes.OUTPUT_VALUE; +OPPOSITE_TYPE[connectionTypes.OUTPUT_VALUE] = connectionTypes.INPUT_VALUE; +OPPOSITE_TYPE[connectionTypes.NEXT_STATEMENT] = + connectionTypes.PREVIOUS_STATEMENT; +OPPOSITE_TYPE[connectionTypes.PREVIOUS_STATEMENT] = + connectionTypes.NEXT_STATEMENT; + +exports.OPPOSITE_TYPE = OPPOSITE_TYPE; + +/** + * String for use in the "custom" attribute of a category in toolbox XML. + * This string indicates that the category should be dynamically populated with + * variable blocks. + * @const {string} + */ +const VARIABLE_CATEGORY_NAME = 'VARIABLE'; +exports.VARIABLE_CATEGORY_NAME = VARIABLE_CATEGORY_NAME; + +/** + * String for use in the "custom" attribute of a category in toolbox XML. + * This string indicates that the category should be dynamically populated with + * variable blocks. + * @const {string} + */ +const VARIABLE_DYNAMIC_CATEGORY_NAME = 'VARIABLE_DYNAMIC'; +exports.VARIABLE_DYNAMIC_CATEGORY_NAME = VARIABLE_DYNAMIC_CATEGORY_NAME; + +/** + * String for use in the "custom" attribute of a category in toolbox XML. + * This string indicates that the category should be dynamically populated with + * procedure blocks. + * @const {string} + */ +const PROCEDURE_CATEGORY_NAME = 'PROCEDURE'; +exports.PROCEDURE_CATEGORY_NAME = PROCEDURE_CATEGORY_NAME; + +/** + * String for use in the dropdown created in field_variable. + * This string indicates that this option in the dropdown is 'Rename + * variable...' and if selected, should trigger the prompt to rename a variable. + * @const {string} + */ +const RENAME_VARIABLE_ID = 'RENAME_VARIABLE_ID'; +exports.RENAME_VARIABLE_ID = RENAME_VARIABLE_ID; + +/** + * String for use in the dropdown created in field_variable. + * This string indicates that this option in the dropdown is 'Delete the "%1" + * variable' and if selected, should trigger the prompt to delete a variable. + * @const {string} + */ +const DELETE_VARIABLE_ID = 'DELETE_VARIABLE_ID'; +exports.DELETE_VARIABLE_ID = DELETE_VARIABLE_ID; diff --git a/core/keyboard_nav/ast_node.js b/core/keyboard_nav/ast_node.js index 37145a090..d86a22a4c 100644 --- a/core/keyboard_nav/ast_node.js +++ b/core/keyboard_nav/ast_node.js @@ -13,8 +13,6 @@ goog.provide('Blockly.ASTNode'); goog.require('Blockly.connectionTypes'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.utils.Coordinate'); goog.requireType('Blockly.Block'); @@ -420,7 +418,7 @@ Blockly.ASTNode.prototype.findPrevForField_ = function() { */ Blockly.ASTNode.prototype.navigateBetweenStacks_ = function(forward) { var curLocation = this.getLocation(); - if (!(curLocation instanceof Blockly.Block)) { + if (curLocation.getSourceBlock) { curLocation = /** @type {!Blockly.IASTNodeLocationWithBlock} */ ( curLocation).getSourceBlock(); } diff --git a/core/keyboard_nav/basic_cursor.js b/core/keyboard_nav/basic_cursor.js index e38031321..e9780e119 100644 --- a/core/keyboard_nav/basic_cursor.js +++ b/core/keyboard_nav/basic_cursor.js @@ -11,11 +11,13 @@ */ 'use strict'; -goog.provide('Blockly.BasicCursor'); +goog.module('Blockly.BasicCursor'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.ASTNode'); -goog.require('Blockly.Cursor'); -goog.require('Blockly.registry'); +const ASTNode = goog.require('Blockly.ASTNode'); +const Cursor = goog.require('Blockly.Cursor'); +const {register, Type} = goog.require('Blockly.registry'); +const {inherits} = goog.require('Blockly.utils.object'); /** @@ -23,31 +25,31 @@ goog.require('Blockly.registry'); * This will allow the user to get to all nodes in the AST by hitting next or * previous. * @constructor - * @extends {Blockly.Cursor} + * @extends {Cursor} */ -Blockly.BasicCursor = function() { - Blockly.BasicCursor.superClass_.constructor.call(this); +const BasicCursor = function() { + BasicCursor.superClass_.constructor.call(this); }; -Blockly.utils.object.inherits(Blockly.BasicCursor, Blockly.Cursor); +inherits(BasicCursor, Cursor); /** * Name used for registering a basic cursor. * @const {string} */ -Blockly.BasicCursor.registrationName = 'basicCursor'; +BasicCursor.registrationName = 'basicCursor'; /** * Find the next node in the pre order traversal. - * @return {Blockly.ASTNode} The next node, or null if the current node is + * @return {?ASTNode} The next node, or null if the current node is * not set or there is no next value. * @override */ -Blockly.BasicCursor.prototype.next = function() { - var curNode = this.getCurNode(); +BasicCursor.prototype.next = function() { + const curNode = this.getCurNode(); if (!curNode) { return null; } - var newNode = this.getNextNode_(curNode, this.validNode_); + const newNode = this.getNextNode_(curNode, this.validNode_); if (newNode) { this.setCurNode(newNode); @@ -59,26 +61,26 @@ Blockly.BasicCursor.prototype.next = function() { * For a basic cursor we only have the ability to go next and previous, so * in will also allow the user to get to the next node in the pre order * traversal. - * @return {Blockly.ASTNode} The next node, or null if the current node is + * @return {?ASTNode} The next node, or null if the current node is * not set or there is no next value. * @override */ -Blockly.BasicCursor.prototype.in = function() { +BasicCursor.prototype.in = function() { return this.next(); }; /** * Find the previous node in the pre order traversal. - * @return {Blockly.ASTNode} The previous node, or null if the current node + * @return {?ASTNode} The previous node, or null if the current node * is not set or there is no previous value. * @override */ -Blockly.BasicCursor.prototype.prev = function() { - var curNode = this.getCurNode(); +BasicCursor.prototype.prev = function() { + const curNode = this.getCurNode(); if (!curNode) { return null; } - var newNode = this.getPreviousNode_(curNode, this.validNode_); + const newNode = this.getPreviousNode_(curNode, this.validNode_); if (newNode) { this.setCurNode(newNode); @@ -90,11 +92,11 @@ Blockly.BasicCursor.prototype.prev = function() { * For a basic cursor we only have the ability to go next and previous, so * out will allow the user to get to the previous node in the pre order * traversal. - * @return {Blockly.ASTNode} The previous node, or null if the current node is + * @return {?ASTNode} The previous node, or null if the current node is * not set or there is no previous value. * @override */ -Blockly.BasicCursor.prototype.out = function() { +BasicCursor.prototype.out = function() { return this.prev(); }; @@ -102,23 +104,23 @@ Blockly.BasicCursor.prototype.out = function() { * Uses pre order traversal to navigate the Blockly AST. This will allow * a user to easily navigate the entire Blockly AST without having to go in * and out levels on the tree. - * @param {Blockly.ASTNode} node The current position in the AST. - * @param {!function(Blockly.ASTNode) : boolean} isValid A function true/false + * @param {?ASTNode} node The current position in the AST. + * @param {!function(ASTNode) : boolean} isValid A function true/false * depending on whether the given node should be traversed. - * @return {Blockly.ASTNode} The next node in the traversal. + * @return {?ASTNode} The next node in the traversal. * @protected */ -Blockly.BasicCursor.prototype.getNextNode_ = function(node, isValid) { +BasicCursor.prototype.getNextNode_ = function(node, isValid) { if (!node) { return null; } - var newNode = node.in() || node.next(); + const newNode = node.in() || node.next(); if (isValid(newNode)) { return newNode; } else if (newNode) { return this.getNextNode_(newNode, isValid); } - var siblingOrParent = this.findSiblingOrParent_(node.out()); + const siblingOrParent = this.findSiblingOrParent_(node.out()); if (isValid(siblingOrParent)) { return siblingOrParent; } else if (siblingOrParent) { @@ -131,18 +133,18 @@ Blockly.BasicCursor.prototype.getNextNode_ = function(node, isValid) { * Reverses the pre order traversal in order to find the previous node. This * will allow a user to easily navigate the entire Blockly AST without having to * go in and out levels on the tree. - * @param {Blockly.ASTNode} node The current position in the AST. - * @param {!function(Blockly.ASTNode) : boolean} isValid A function true/false + * @param {?ASTNode} node The current position in the AST. + * @param {!function(ASTNode) : boolean} isValid A function true/false * depending on whether the given node should be traversed. - * @return {Blockly.ASTNode} The previous node in the traversal or null if no + * @return {?ASTNode} The previous node in the traversal or null if no * previous node exists. * @protected */ -Blockly.BasicCursor.prototype.getPreviousNode_ = function(node, isValid) { +BasicCursor.prototype.getPreviousNode_ = function(node, isValid) { if (!node) { return null; } - var newNode = node.prev(); + let newNode = node.prev(); if (newNode) { newNode = this.getRightMostChild_(newNode); @@ -160,19 +162,16 @@ Blockly.BasicCursor.prototype.getPreviousNode_ = function(node, isValid) { /** * Decides what nodes to traverse and which ones to skip. Currently, it * skips output, stack and workspace nodes. - * @param {Blockly.ASTNode} node The AST node to check whether it is valid. + * @param {?ASTNode} node The AST node to check whether it is valid. * @return {boolean} True if the node should be visited, false otherwise. * @protected */ -Blockly.BasicCursor.prototype.validNode_ = function(node) { - var isValid = false; - var type = node && node.getType(); - if (type == Blockly.ASTNode.types.OUTPUT || - type == Blockly.ASTNode.types.INPUT || - type == Blockly.ASTNode.types.FIELD || - type == Blockly.ASTNode.types.NEXT || - type == Blockly.ASTNode.types.PREVIOUS || - type == Blockly.ASTNode.types.WORKSPACE) { +BasicCursor.prototype.validNode_ = function(node) { + let isValid = false; + const type = node && node.getType(); + if (type == ASTNode.types.OUTPUT || type == ASTNode.types.INPUT || + type == ASTNode.types.FIELD || type == ASTNode.types.NEXT || + type == ASTNode.types.PREVIOUS || type == ASTNode.types.WORKSPACE) { isValid = true; } return isValid; @@ -180,16 +179,16 @@ Blockly.BasicCursor.prototype.validNode_ = function(node) { /** * From the given node find either the next valid sibling or parent. - * @param {Blockly.ASTNode} node The current position in the AST. - * @return {Blockly.ASTNode} The parent AST node or null if there are no + * @param {?ASTNode} node The current position in the AST. + * @return {?ASTNode} The parent AST node or null if there are no * valid parents. * @private */ -Blockly.BasicCursor.prototype.findSiblingOrParent_ = function(node) { +BasicCursor.prototype.findSiblingOrParent_ = function(node) { if (!node) { return null; } - var nextNode = node.next(); + const nextNode = node.next(); if (nextNode) { return nextNode; } @@ -199,22 +198,22 @@ Blockly.BasicCursor.prototype.findSiblingOrParent_ = function(node) { /** * Get the right most child of a node. - * @param {Blockly.ASTNode} node The node to find the right most child of. - * @return {Blockly.ASTNode} The right most child of the given node, or the node + * @param {?ASTNode} node The node to find the right most child of. + * @return {?ASTNode} The right most child of the given node, or the node * if no child exists. * @private */ -Blockly.BasicCursor.prototype.getRightMostChild_ = function(node) { +BasicCursor.prototype.getRightMostChild_ = function(node) { if (!node.in()) { return node; } - var newNode = node.in(); + let newNode = node.in(); while (newNode.next()) { newNode = newNode.next(); } return this.getRightMostChild_(newNode); }; -Blockly.registry.register( - Blockly.registry.Type.CURSOR, Blockly.BasicCursor.registrationName, - Blockly.BasicCursor); +register(Type.CURSOR, BasicCursor.registrationName, BasicCursor); + +exports = BasicCursor; diff --git a/core/keyboard_nav/cursor.js b/core/keyboard_nav/cursor.js index 882be726a..de3d97498 100644 --- a/core/keyboard_nav/cursor.js +++ b/core/keyboard_nav/cursor.js @@ -11,46 +11,47 @@ */ 'use strict'; -goog.provide('Blockly.Cursor'); +goog.module('Blockly.Cursor'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.ASTNode'); -goog.require('Blockly.Marker'); -goog.require('Blockly.registry'); -goog.require('Blockly.utils.object'); +const ASTNode = goog.require('Blockly.ASTNode'); +const Marker = goog.require('Blockly.Marker'); +const {DEFAULT, register, Type} = goog.require('Blockly.registry'); +const {inherits} = goog.require('Blockly.utils.object'); /** * Class for a cursor. * A cursor controls how a user navigates the Blockly AST. * @constructor - * @extends {Blockly.Marker} + * @extends {Marker} */ -Blockly.Cursor = function() { - Blockly.Cursor.superClass_.constructor.call(this); +const Cursor = function() { + Cursor.superClass_.constructor.call(this); /** * @override */ this.type = 'cursor'; }; -Blockly.utils.object.inherits(Blockly.Cursor, Blockly.Marker); +inherits(Cursor, Marker); /** * Find the next connection, field, or block. - * @return {Blockly.ASTNode} The next element, or null if the current node is + * @return {ASTNode} The next element, or null if the current node is * not set or there is no next value. * @public */ -Blockly.Cursor.prototype.next = function() { - var curNode = this.getCurNode(); +Cursor.prototype.next = function() { + const curNode = this.getCurNode(); if (!curNode) { return null; } - var newNode = curNode.next(); + let newNode = curNode.next(); while (newNode && newNode.next() && - (newNode.getType() == Blockly.ASTNode.types.NEXT || - newNode.getType() == Blockly.ASTNode.types.BLOCK)) { + (newNode.getType() == ASTNode.types.NEXT || + newNode.getType() == ASTNode.types.BLOCK)) { newNode = newNode.next(); } @@ -62,22 +63,22 @@ Blockly.Cursor.prototype.next = function() { /** * Find the in connection or field. - * @return {Blockly.ASTNode} The in element, or null if the current node is + * @return {ASTNode} The in element, or null if the current node is * not set or there is no in value. * @public */ -Blockly.Cursor.prototype.in = function() { - var curNode = this.getCurNode(); +Cursor.prototype.in = function() { + let curNode = this.getCurNode(); if (!curNode) { return null; } // If we are on a previous or output connection, go to the block level before // performing next operation. - if (curNode.getType() == Blockly.ASTNode.types.PREVIOUS || - curNode.getType() == Blockly.ASTNode.types.OUTPUT) { + if (curNode.getType() == ASTNode.types.PREVIOUS || + curNode.getType() == ASTNode.types.OUTPUT) { curNode = curNode.next(); } - var newNode = curNode.in(); + const newNode = curNode.in(); if (newNode) { this.setCurNode(newNode); @@ -87,20 +88,20 @@ Blockly.Cursor.prototype.in = function() { /** * Find the previous connection, field, or block. - * @return {Blockly.ASTNode} The previous element, or null if the current node + * @return {ASTNode} The previous element, or null if the current node * is not set or there is no previous value. * @public */ -Blockly.Cursor.prototype.prev = function() { - var curNode = this.getCurNode(); +Cursor.prototype.prev = function() { + const curNode = this.getCurNode(); if (!curNode) { return null; } - var newNode = curNode.prev(); + let newNode = curNode.prev(); while (newNode && newNode.prev() && - (newNode.getType() == Blockly.ASTNode.types.NEXT || - newNode.getType() == Blockly.ASTNode.types.BLOCK)) { + (newNode.getType() == ASTNode.types.NEXT || + newNode.getType() == ASTNode.types.BLOCK)) { newNode = newNode.prev(); } @@ -112,18 +113,18 @@ Blockly.Cursor.prototype.prev = function() { /** * Find the out connection, field, or block. - * @return {Blockly.ASTNode} The out element, or null if the current node is + * @return {ASTNode} The out element, or null if the current node is * not set or there is no out value. * @public */ -Blockly.Cursor.prototype.out = function() { - var curNode = this.getCurNode(); +Cursor.prototype.out = function() { + const curNode = this.getCurNode(); if (!curNode) { return null; } - var newNode = curNode.out(); + let newNode = curNode.out(); - if (newNode && newNode.getType() == Blockly.ASTNode.types.BLOCK) { + if (newNode && newNode.getType() == ASTNode.types.BLOCK) { newNode = newNode.prev() || newNode; } @@ -133,5 +134,6 @@ Blockly.Cursor.prototype.out = function() { return newNode; }; -Blockly.registry.register( - Blockly.registry.Type.CURSOR, Blockly.registry.DEFAULT, Blockly.Cursor); +register(Type.CURSOR, DEFAULT, Cursor); + +exports = Cursor; diff --git a/core/keyboard_nav/tab_navigate_cursor.js b/core/keyboard_nav/tab_navigate_cursor.js index 7d43a79f8..77fc5a2a2 100644 --- a/core/keyboard_nav/tab_navigate_cursor.js +++ b/core/keyboard_nav/tab_navigate_cursor.js @@ -11,40 +11,43 @@ */ 'use strict'; -goog.provide('Blockly.TabNavigateCursor'); +goog.module('Blockly.TabNavigateCursor'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.ASTNode'); -goog.require('Blockly.BasicCursor'); -goog.require('Blockly.utils.object'); - -goog.requireType('Blockly.Field'); +const ASTNode = goog.require('Blockly.ASTNode'); +const BasicCursor = goog.require('Blockly.BasicCursor'); +/* eslint-disable-next-line no-unused-vars */ +const Field = goog.requireType('Blockly.Field'); +const {inherits} = goog.require('Blockly.utils.object'); /** * A cursor for navigating between tab navigable fields. * @constructor - * @extends {Blockly.BasicCursor} + * @extends {BasicCursor} */ -Blockly.TabNavigateCursor = function() { - Blockly.TabNavigateCursor.superClass_.constructor.call(this); +const TabNavigateCursor = function() { + TabNavigateCursor.superClass_.constructor.call(this); }; -Blockly.utils.object.inherits(Blockly.TabNavigateCursor, Blockly.BasicCursor); +inherits(TabNavigateCursor, BasicCursor); /** * Skip all nodes except for tab navigable fields. - * @param {Blockly.ASTNode} node The AST node to check whether it is valid. + * @param {?ASTNode} node The AST node to check whether it is valid. * @return {boolean} True if the node should be visited, false otherwise. * @override */ -Blockly.TabNavigateCursor.prototype.validNode_ = function(node) { - var isValid = false; - var type = node && node.getType(); +TabNavigateCursor.prototype.validNode_ = function(node) { + let isValid = false; + const type = node && node.getType(); if (node) { - var location = /** @type {Blockly.Field} */ (node.getLocation()); - if (type == Blockly.ASTNode.types.FIELD && - location && location.isTabNavigable() && location.isClickable()) { + const location = /** @type {Field} */ (node.getLocation()); + if (type == ASTNode.types.FIELD && location && location.isTabNavigable() && + location.isClickable()) { isValid = true; } } return isValid; }; + +exports = TabNavigateCursor; 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/menu.js b/core/menu.js index 97f47248a..91cfb4d36 100644 --- a/core/menu.js +++ b/core/menu.js @@ -10,29 +10,31 @@ */ 'use strict'; -goog.provide('Blockly.Menu'); +goog.module('Blockly.Menu'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.browserEvents'); -goog.require('Blockly.utils.aria'); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.KeyCodes'); -goog.require('Blockly.utils.style'); - -goog.requireType('Blockly.MenuItem'); -goog.requireType('Blockly.utils.Size'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +/* eslint-disable-next-line no-unused-vars */ +const MenuItem = goog.requireType('Blockly.MenuItem'); +const KeyCodes = goog.require('Blockly.utils.KeyCodes'); +/* eslint-disable-next-line no-unused-vars */ +const Size = goog.requireType('Blockly.utils.Size'); +const aria = goog.require('Blockly.utils.aria'); +const browserEvents = goog.require('Blockly.browserEvents'); +const dom = goog.require('Blockly.utils.dom'); +const style = goog.require('Blockly.utils.style'); /** * A basic menu class. * @constructor */ -Blockly.Menu = function() { +const Menu = function() { /** * Array of menu items. * (Nulls are never in the array, but typing the array as nullable prevents * the compiler from objecting to .indexOf(null)) - * @type {!Array} + * @type {!Array} * @private */ this.menuItems_ = []; @@ -41,7 +43,7 @@ Blockly.Menu = function() { * Coordinates of the mousedown event that caused this menu to open. Used to * prevent the consequent mouseup event due to a simple click from activating * a menu item immediately. - * @type {?Blockly.utils.Coordinate} + * @type {?Coordinate} * @package */ this.openingCoords = null; @@ -49,42 +51,42 @@ Blockly.Menu = function() { /** * This is the element that we will listen to the real focus events on. * A value of null means no menu item is highlighted. - * @type {?Blockly.MenuItem} + * @type {?MenuItem} * @private */ this.highlightedItem_ = null; /** * Mouse over event data. - * @type {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @private */ this.mouseOverHandler_ = null; /** * Click event data. - * @type {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @private */ this.clickHandler_ = null; /** * Mouse enter event data. - * @type {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @private */ this.mouseEnterHandler_ = null; /** * Mouse leave event data. - * @type {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @private */ this.mouseLeaveHandler_ = null; /** * Key down event data. - * @type {?Blockly.browserEvents.Data} + * @type {?browserEvents.Data} * @private */ this.onKeyDownHandler_ = null; @@ -98,7 +100,7 @@ Blockly.Menu = function() { /** * ARIA name for this menu. - * @type {?Blockly.utils.aria.Role} + * @type {?aria.Role} * @private */ this.roleName_ = null; @@ -107,9 +109,9 @@ Blockly.Menu = function() { /** * Add a new menu item to the bottom of this menu. - * @param {!Blockly.MenuItem} menuItem Menu item to append. + * @param {!MenuItem} menuItem Menu item to append. */ -Blockly.Menu.prototype.addChild = function(menuItem) { +Menu.prototype.addChild = function(menuItem) { this.menuItems_.push(menuItem); }; @@ -117,32 +119,33 @@ Blockly.Menu.prototype.addChild = function(menuItem) { * Creates the menu DOM. * @param {!Element} container Element upon which to append this menu. */ -Blockly.Menu.prototype.render = function(container) { - var element = /** @type {!HTMLDivElement} */ (document.createElement('div')); +Menu.prototype.render = function(container) { + const element = + /** @type {!HTMLDivElement} */ (document.createElement('div')); // goog-menu is deprecated, use blocklyMenu. May 2020. element.className = 'blocklyMenu goog-menu blocklyNonSelectable'; element.tabIndex = 0; if (this.roleName_) { - Blockly.utils.aria.setRole(element, this.roleName_); + aria.setRole(element, this.roleName_); } this.element_ = element; // Add menu items. - for (var i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) { + for (let i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) { element.appendChild(menuItem.createDom()); } // Add event handlers. - this.mouseOverHandler_ = Blockly.browserEvents.conditionalBind( - element, 'mouseover', this, this.handleMouseOver_, true); - this.clickHandler_ = Blockly.browserEvents.conditionalBind( - element, 'click', this, this.handleClick_, true); - this.mouseEnterHandler_ = Blockly.browserEvents.conditionalBind( + this.mouseOverHandler_ = + browserEvents.conditionalBind(element, 'mouseover', this, this.handleMouseOver_, true); + this.clickHandler_ = + browserEvents.conditionalBind(element, 'click', this, this.handleClick_, true); + this.mouseEnterHandler_ = browserEvents.conditionalBind( element, 'mouseenter', this, this.handleMouseEnter_, true); - this.mouseLeaveHandler_ = Blockly.browserEvents.conditionalBind( + this.mouseLeaveHandler_ = browserEvents.conditionalBind( element, 'mouseleave', this, this.handleMouseLeave_, true); - this.onKeyDownHandler_ = Blockly.browserEvents.conditionalBind( - element, 'keydown', this, this.handleKeyEvent_); + this.onKeyDownHandler_ = + browserEvents.conditionalBind(element, 'keydown', this, this.handleKeyEvent_); container.appendChild(element); }; @@ -152,7 +155,7 @@ Blockly.Menu.prototype.render = function(container) { * @return {?Element} The DOM element. * @package */ -Blockly.Menu.prototype.getElement = function() { +Menu.prototype.getElement = function() { return this.element_; }; @@ -160,11 +163,11 @@ Blockly.Menu.prototype.getElement = function() { * Focus the menu element. * @package */ -Blockly.Menu.prototype.focus = function() { - var el = this.getElement(); +Menu.prototype.focus = function() { + const el = this.getElement(); if (el) { - el.focus({preventScroll:true}); - Blockly.utils.dom.addClass(el, 'blocklyFocused'); + el.focus({preventScroll: true}); + dom.addClass(el, 'blocklyFocused'); } }; @@ -172,51 +175,51 @@ Blockly.Menu.prototype.focus = function() { * Blur the menu element. * @private */ -Blockly.Menu.prototype.blur_ = function() { - var el = this.getElement(); +Menu.prototype.blur_ = function() { + const el = this.getElement(); if (el) { el.blur(); - Blockly.utils.dom.removeClass(el, 'blocklyFocused'); + dom.removeClass(el, 'blocklyFocused'); } }; /** * Set the menu accessibility role. - * @param {!Blockly.utils.aria.Role} roleName role name. + * @param {!aria.Role} roleName role name. * @package */ -Blockly.Menu.prototype.setRole = function(roleName) { +Menu.prototype.setRole = function(roleName) { this.roleName_ = roleName; }; /** * Dispose of this menu. */ -Blockly.Menu.prototype.dispose = function() { +Menu.prototype.dispose = function() { // Remove event handlers. if (this.mouseOverHandler_) { - Blockly.browserEvents.unbind(this.mouseOverHandler_); + browserEvents.unbind(this.mouseOverHandler_); this.mouseOverHandler_ = null; } if (this.clickHandler_) { - Blockly.browserEvents.unbind(this.clickHandler_); + browserEvents.unbind(this.clickHandler_); this.clickHandler_ = null; } if (this.mouseEnterHandler_) { - Blockly.browserEvents.unbind(this.mouseEnterHandler_); + browserEvents.unbind(this.mouseEnterHandler_); this.mouseEnterHandler_ = null; } if (this.mouseLeaveHandler_) { - Blockly.browserEvents.unbind(this.mouseLeaveHandler_); + browserEvents.unbind(this.mouseLeaveHandler_); this.mouseLeaveHandler_ = null; } if (this.onKeyDownHandler_) { - Blockly.browserEvents.unbind(this.onKeyDownHandler_); + browserEvents.unbind(this.onKeyDownHandler_); this.onKeyDownHandler_ = null; } // Remove menu items. - for (var i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) { + for (let i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) { menuItem.dispose(); } this.element_ = null; @@ -228,19 +231,19 @@ Blockly.Menu.prototype.dispose = function() { * Returns the child menu item that owns the given DOM element, * or null if no such menu item is found. * @param {Element} elem DOM element whose owner is to be returned. - * @return {?Blockly.MenuItem} Menu item for which the DOM element belongs to. + * @return {?MenuItem} Menu item for which the DOM element belongs to. * @private */ -Blockly.Menu.prototype.getMenuItem_ = function(elem) { - var menuElem = this.getElement(); +Menu.prototype.getMenuItem_ = function(elem) { + const menuElem = this.getElement(); // Node might be the menu border (resulting in no associated menu item), or // a menu item's div, or some element within the menu item. // Walk up parents until one meets either the menu's root element, or // a menu item's div. while (elem && elem != menuElem) { - if (Blockly.utils.dom.hasClass(elem, 'blocklyMenuItem')) { + if (dom.hasClass(elem, 'blocklyMenuItem')) { // Having found a menu item's div, locate that menu item in this menu. - for (var i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) { + for (let i = 0, menuItem; (menuItem = this.menuItems_[i]); i++) { if (menuItem.getElement() == elem) { return menuItem; } @@ -255,11 +258,11 @@ Blockly.Menu.prototype.getMenuItem_ = function(elem) { /** * Highlights the given menu item, or clears highlighting if null. - * @param {?Blockly.MenuItem} item Item to highlight, or null. + * @param {?MenuItem} item Item to highlight, or null. * @package */ -Blockly.Menu.prototype.setHighlighted = function(item) { - var currentHighlighted = this.highlightedItem_; +Menu.prototype.setHighlighted = function(item) { + const currentHighlighted = this.highlightedItem_; if (currentHighlighted) { currentHighlighted.setHighlighted(false); this.highlightedItem_ = null; @@ -269,12 +272,11 @@ Blockly.Menu.prototype.setHighlighted = function(item) { this.highlightedItem_ = item; // Bring the highlighted item into view. This has no effect if the menu is // not scrollable. - var el = /** @type {!Element} */ (this.getElement()); - Blockly.utils.style.scrollIntoContainerView( + const el = /** @type {!Element} */ (this.getElement()); + style.scrollIntoContainerView( /** @type {!Element} */ (item.getElement()), el); - Blockly.utils.aria.setState(el, Blockly.utils.aria.State.ACTIVEDESCENDANT, - item.getId()); + aria.setState(el, aria.State.ACTIVEDESCENDANT, item.getId()); } }; @@ -283,8 +285,8 @@ Blockly.Menu.prototype.setHighlighted = function(item) { * highlighted). * @package */ -Blockly.Menu.prototype.highlightNext = function() { - var index = this.menuItems_.indexOf(this.highlightedItem_); +Menu.prototype.highlightNext = function() { + const index = this.menuItems_.indexOf(this.highlightedItem_); this.highlightHelper_(index, 1); }; @@ -293,8 +295,8 @@ Blockly.Menu.prototype.highlightNext = function() { * currently highlighted). * @package */ -Blockly.Menu.prototype.highlightPrevious = function() { - var index = this.menuItems_.indexOf(this.highlightedItem_); +Menu.prototype.highlightPrevious = function() { + const index = this.menuItems_.indexOf(this.highlightedItem_); this.highlightHelper_(index < 0 ? this.menuItems_.length : index, -1); }; @@ -302,7 +304,7 @@ Blockly.Menu.prototype.highlightPrevious = function() { * Highlights the first highlightable item. * @private */ -Blockly.Menu.prototype.highlightFirst_ = function() { +Menu.prototype.highlightFirst_ = function() { this.highlightHelper_(-1, 1); }; @@ -310,7 +312,7 @@ Blockly.Menu.prototype.highlightFirst_ = function() { * Highlights the last highlightable item. * @private */ -Blockly.Menu.prototype.highlightLast_ = function() { +Menu.prototype.highlightLast_ = function() { this.highlightHelper_(this.menuItems_.length, -1); }; @@ -321,9 +323,9 @@ Blockly.Menu.prototype.highlightLast_ = function() { * @param {number} delta Step direction: 1 to go down, -1 to go up. * @private */ -Blockly.Menu.prototype.highlightHelper_ = function(startIndex, delta) { - var index = startIndex + delta; - var menuItem; +Menu.prototype.highlightHelper_ = function(startIndex, delta) { + let index = startIndex + delta; + let menuItem; while ((menuItem = this.menuItems_[index])) { if (menuItem.isEnabled()) { this.setHighlighted(menuItem); @@ -340,8 +342,8 @@ Blockly.Menu.prototype.highlightHelper_ = function(startIndex, delta) { * @param {!Event} e Mouse event to handle. * @private */ -Blockly.Menu.prototype.handleMouseOver_ = function(e) { - var menuItem = this.getMenuItem_(/** @type {Element} */ (e.target)); +Menu.prototype.handleMouseOver_ = function(e) { + const menuItem = this.getMenuItem_(/** @type {Element} */ (e.target)); if (menuItem) { if (menuItem.isEnabled()) { @@ -359,13 +361,13 @@ Blockly.Menu.prototype.handleMouseOver_ = function(e) { * @param {!Event} e Click event to handle. * @private */ -Blockly.Menu.prototype.handleClick_ = function(e) { - var oldCoords = this.openingCoords; +Menu.prototype.handleClick_ = function(e) { + const oldCoords = this.openingCoords; // Clear out the saved opening coords immediately so they're not used twice. this.openingCoords = null; if (oldCoords && typeof e.clientX == 'number') { - var newCoords = new Blockly.utils.Coordinate(e.clientX, e.clientY); - if (Blockly.utils.Coordinate.distance(oldCoords, newCoords) < 1) { + const newCoords = new Coordinate(e.clientX, e.clientY); + if (Coordinate.distance(oldCoords, newCoords) < 1) { // This menu was opened by a mousedown and we're handling the consequent // click event. The coords haven't changed, meaning this was the same // opening event. Don't do the usual behavior because the menu just popped @@ -374,7 +376,7 @@ Blockly.Menu.prototype.handleClick_ = function(e) { } } - var menuItem = this.getMenuItem_(/** @type {Element} */ (e.target)); + const menuItem = this.getMenuItem_(/** @type {Element} */ (e.target)); if (menuItem) { menuItem.performAction(); } @@ -385,7 +387,7 @@ Blockly.Menu.prototype.handleClick_ = function(e) { * @param {!Event} _e Mouse event to handle. * @private */ -Blockly.Menu.prototype.handleMouseEnter_ = function(_e) { +Menu.prototype.handleMouseEnter_ = function(_e) { this.focus(); }; @@ -394,7 +396,7 @@ Blockly.Menu.prototype.handleMouseEnter_ = function(_e) { * @param {!Event} _e Mouse event to handle. * @private */ -Blockly.Menu.prototype.handleMouseLeave_ = function(_e) { +Menu.prototype.handleMouseLeave_ = function(_e) { if (this.getElement()) { this.blur_(); this.setHighlighted(null); @@ -409,7 +411,7 @@ Blockly.Menu.prototype.handleMouseLeave_ = function(_e) { * @param {!Event} e Key event to handle. * @private */ -Blockly.Menu.prototype.handleKeyEvent_ = function(e) { +Menu.prototype.handleKeyEvent_ = function(e) { if (!this.menuItems_.length) { // Empty menu. return; @@ -419,30 +421,30 @@ Blockly.Menu.prototype.handleKeyEvent_ = function(e) { return; } - var highlighted = this.highlightedItem_; + const highlighted = this.highlightedItem_; switch (e.keyCode) { - case Blockly.utils.KeyCodes.ENTER: - case Blockly.utils.KeyCodes.SPACE: + case KeyCodes.ENTER: + case KeyCodes.SPACE: if (highlighted) { highlighted.performAction(); } break; - case Blockly.utils.KeyCodes.UP: + case KeyCodes.UP: this.highlightPrevious(); break; - case Blockly.utils.KeyCodes.DOWN: + case KeyCodes.DOWN: this.highlightNext(); break; - case Blockly.utils.KeyCodes.PAGE_UP: - case Blockly.utils.KeyCodes.HOME: + case KeyCodes.PAGE_UP: + case KeyCodes.HOME: this.highlightFirst_(); break; - case Blockly.utils.KeyCodes.PAGE_DOWN: - case Blockly.utils.KeyCodes.END: + case KeyCodes.PAGE_DOWN: + case KeyCodes.END: this.highlightLast_(); break; @@ -457,13 +459,16 @@ Blockly.Menu.prototype.handleKeyEvent_ = function(e) { /** * Get the size of a rendered menu. - * @return {!Blockly.utils.Size} Object with width and height properties. + * @return {!Size} Object with width and height properties. * @package */ -Blockly.Menu.prototype.getSize = function() { - var menuDom = this.getElement(); - var menuSize = Blockly.utils.style.getSize(/** @type {!Element} */ (menuDom)); +Menu.prototype.getSize = function() { + const menuDom = this.getElement(); + const menuSize = style.getSize(/** @type {!Element} */ + (menuDom)); // Recalculate height for the total content, not only box height. menuSize.height = menuDom.scrollHeight; return menuSize; }; + +exports = Menu; diff --git a/core/mutator.js b/core/mutator.js index 1bd6d0988..2733964c7 100644 --- a/core/mutator.js +++ b/core/mutator.js @@ -20,6 +20,7 @@ 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'); @@ -444,7 +445,7 @@ Blockly.Mutator.prototype.workspaceChanged_ = function(e) { Blockly.Events.setGroup(group); block.bumpNeighbours(); Blockly.Events.setGroup(false); - }, Blockly.BUMP_DELAY); + }, Blockly.internalConstants.BUMP_DELAY); } // Don't update the bubble until the drag has ended, to avoid moving blocks diff --git a/core/names.js b/core/names.js index 3abd27f9e..a559321cf 100644 --- a/core/names.js +++ b/core/names.js @@ -12,8 +12,7 @@ goog.provide('Blockly.Names'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); +goog.require('Blockly.internalConstants'); goog.require('Blockly.Msg'); goog.requireType('Blockly.VariableMap'); @@ -77,7 +76,7 @@ Blockly.Names.prototype.setVariableMap = function(map) { /** * Get the name for a user-defined variable, based on its ID. * This should only be used for variables of realm - * Blockly.VARIABLE_CATEGORY_NAME. + * Blockly.internalConstants.VARIABLE_CATEGORY_NAME. * @param {string} id The ID to look up in the variable map. * @return {?string} The name of the referenced variable, or null if there was * no variable map or the variable was not found in the map. @@ -106,7 +105,8 @@ Blockly.Names.prototype.getNameForUserVariable_ = function(id) { Blockly.Names.prototype.populateVariables = function(workspace) { var variables = Blockly.Variables.allUsedVarModels(workspace); for (var i = 0; i < variables.length; i++) { - this.getName(variables[i].getId(), Blockly.VARIABLE_CATEGORY_NAME); + this.getName( + variables[i].getId(), Blockly.internalConstants.VARIABLE_CATEGORY_NAME); } }; @@ -119,7 +119,8 @@ Blockly.Names.prototype.populateProcedures = function(workspace) { // Flatten the return vs no-return procedure lists. procedures = procedures[0].concat(procedures[1]); for (var i = 0; i < procedures.length; i++) { - this.getName(procedures[i][0], Blockly.PROCEDURE_CATEGORY_NAME); + this.getName( + procedures[i][0], Blockly.internalConstants.PROCEDURE_CATEGORY_NAME); } }; @@ -133,7 +134,7 @@ Blockly.Names.prototype.populateProcedures = function(workspace) { */ Blockly.Names.prototype.getName = function(nameOrId, realm) { var name = nameOrId; - if (realm == Blockly.VARIABLE_CATEGORY_NAME) { + if (realm == Blockly.internalConstants.VARIABLE_CATEGORY_NAME) { var varName = this.getNameForUserVariable_(nameOrId); if (varName) { // Successful ID lookup. @@ -142,7 +143,7 @@ Blockly.Names.prototype.getName = function(nameOrId, realm) { } var normalizedName = name.toLowerCase(); - var isVar = realm == Blockly.VARIABLE_CATEGORY_NAME || + var isVar = realm == Blockly.internalConstants.VARIABLE_CATEGORY_NAME || realm == Blockly.Names.DEVELOPER_VARIABLE_TYPE; var prefix = isVar ? this.variablePrefix_ : ''; @@ -189,7 +190,7 @@ Blockly.Names.prototype.getDistinctName = function(name, realm) { } safeName += i; this.dbReverse_[safeName] = true; - var isVar = realm == Blockly.VARIABLE_CATEGORY_NAME || + var isVar = realm == Blockly.internalConstants.VARIABLE_CATEGORY_NAME || realm == Blockly.Names.DEVELOPER_VARIABLE_TYPE; var prefix = isVar ? this.variablePrefix_ : ''; return prefix + safeName; diff --git a/core/procedures.js b/core/procedures.js index 984ef03fa..3323bb130 100644 --- a/core/procedures.js +++ b/core/procedures.js @@ -17,12 +17,11 @@ goog.provide('Blockly.Procedures'); goog.require('Blockly.Blocks'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.BlockChange'); goog.require('Blockly.Field'); +goog.require('Blockly.internalConstants'); goog.require('Blockly.Msg'); goog.require('Blockly.Names'); goog.require('Blockly.utils.xml'); @@ -37,9 +36,10 @@ goog.requireType('Blockly.WorkspaceSvg'); /** * Constant to separate procedure names from variables and generated functions * when running generators. - * @deprecated Use Blockly.PROCEDURE_CATEGORY_NAME + * @deprecated Use Blockly.internalConstants.PROCEDURE_CATEGORY_NAME */ -Blockly.Procedures.NAME_TYPE = Blockly.PROCEDURE_CATEGORY_NAME; +Blockly.Procedures.NAME_TYPE = + Blockly.internalConstants.PROCEDURE_CATEGORY_NAME; /** * The default argument for a procedures_mutatorarg block. diff --git a/core/rendered_connection.js b/core/rendered_connection.js index f9d3864e3..cddda9200 100644 --- a/core/rendered_connection.js +++ b/core/rendered_connection.js @@ -14,8 +14,7 @@ goog.provide('Blockly.RenderedConnection'); goog.require('Blockly.Connection'); goog.require('Blockly.connectionTypes'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); +goog.require('Blockly.internalConstants'); goog.require('Blockly.utils'); goog.require('Blockly.utils.Coordinate'); goog.require('Blockly.utils.deprecation'); @@ -51,8 +50,9 @@ Blockly.RenderedConnection = function(source, type) { * @const {!Blockly.ConnectionDB} * @private */ - this.dbOpposite_ = source.workspace - .connectionDBList[Blockly.OPPOSITE_TYPE[type]]; + this.dbOpposite_ = + source.workspace + .connectionDBList[Blockly.internalConstants.OPPOSITE_TYPE[type]]; /** * Workspace units, (0, 0) is top left of block. @@ -173,17 +173,23 @@ Blockly.RenderedConnection.prototype.bumpAwayFrom = function(staticConnection) { // Raise it to the top for extra visibility. var selected = Blockly.selected == rootBlock; selected || rootBlock.addSelect(); - var dx = (staticConnection.x + Blockly.SNAP_RADIUS + - Math.floor(Math.random() * Blockly.BUMP_RANDOMNESS)) - this.x; - var dy = (staticConnection.y + Blockly.SNAP_RADIUS + - Math.floor(Math.random() * Blockly.BUMP_RANDOMNESS)) - this.y; + var dx = + (staticConnection.x + Blockly.internalConstants.SNAP_RADIUS + + Math.floor(Math.random() * Blockly.internalConstants.BUMP_RANDOMNESS)) - + this.x; + var dy = + (staticConnection.y + Blockly.internalConstants.SNAP_RADIUS + + Math.floor(Math.random() * Blockly.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.SNAP_RADIUS - - Math.floor(Math.random() * Blockly.BUMP_RANDOMNESS)) - this.x; + dx = (staticConnection.x - Blockly.internalConstants.SNAP_RADIUS - + Math.floor( + Math.random() * Blockly.internalConstants.BUMP_RANDOMNESS)) - + this.x; } rootBlock.moveBy(dx, dy); selected || rootBlock.removeSelect(); @@ -466,7 +472,7 @@ Blockly.RenderedConnection.prototype.onFailedConnect = this.bumpAwayFrom(otherConnection); Blockly.Events.setGroup(false); } - }.bind(this), Blockly.BUMP_DELAY); + }.bind(this), Blockly.internalConstants.BUMP_DELAY); } }; diff --git a/core/renderers/common/constants.js b/core/renderers/common/constants.js index a21ef85aa..5e5ecb747 100644 --- a/core/renderers/common/constants.js +++ b/core/renderers/common/constants.js @@ -10,21 +10,20 @@ */ 'use strict'; -goog.provide('Blockly.blockRendering.ConstantProvider'); +goog.module('Blockly.blockRendering.ConstantProvider'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.connectionTypes'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); -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'); /** @@ -32,8 +31,7 @@ goog.requireType('Blockly.Theme'); * @constructor * @package */ -Blockly.blockRendering.ConstantProvider = function() { - +const ConstantProvider = function() { /** * The size of an empty spacer. * @type {number} @@ -216,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. @@ -305,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. @@ -351,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 @@ -403,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} @@ -527,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. @@ -579,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]); } @@ -602,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; @@ -643,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}); }; /** @@ -717,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; +}; /** @@ -774,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; }; @@ -792,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}; }; /** @@ -815,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}; }; /** @@ -838,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' @@ -848,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, @@ -892,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, @@ -922,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, @@ -944,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, @@ -989,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'); @@ -1016,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); /* @@ -1025,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); /* @@ -1041,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, @@ -1058,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', @@ -1079,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; @@ -1090,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; @@ -1156,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; @@ -1184,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 {', @@ -1256,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/debugger.js b/core/renderers/common/debugger.js index 0e99fc613..a6ab9d387 100644 --- a/core/renderers/common/debugger.js +++ b/core/renderers/common/debugger.js @@ -17,8 +17,6 @@ goog.require('Blockly.blockRendering.RenderInfo'); goog.require('Blockly.blockRendering.Row'); goog.require('Blockly.blockRendering.Types'); goog.require('Blockly.connectionTypes'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.utils.dom'); goog.require('Blockly.utils.Svg'); diff --git a/core/renderers/common/drawer.js b/core/renderers/common/drawer.js index f91b97d7a..2dde92d3f 100644 --- a/core/renderers/common/drawer.js +++ b/core/renderers/common/drawer.js @@ -10,29 +10,36 @@ */ 'use strict'; -goog.provide('Blockly.blockRendering.Drawer'); +goog.module('Blockly.blockRendering.Drawer'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.blockRendering.RenderInfo'); -goog.require('Blockly.blockRendering.Row'); -goog.require('Blockly.blockRendering.Types'); -goog.require('Blockly.utils.svgPaths'); - -goog.requireType('Blockly.blockRendering.ConstantProvider'); -goog.requireType('Blockly.blockRendering.Field'); -goog.requireType('Blockly.blockRendering.Icon'); -goog.requireType('Blockly.blockRendering.InlineInput'); -goog.requireType('Blockly.BlockSvg'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +/* eslint-disable-next-line no-unused-vars */ +const ConstantProvider = goog.requireType('Blockly.blockRendering.ConstantProvider'); +/* eslint-disable-next-line no-unused-vars */ +const Field = goog.requireType('Blockly.blockRendering.Field'); +/* eslint-disable-next-line no-unused-vars */ +const Icon = goog.requireType('Blockly.blockRendering.Icon'); +/* eslint-disable-next-line no-unused-vars */ +const InlineInput = goog.requireType('Blockly.blockRendering.InlineInput'); +/* eslint-disable-next-line no-unused-vars */ +const RenderInfo = goog.requireType('Blockly.blockRendering.RenderInfo'); +/* eslint-disable-next-line no-unused-vars */ +const Row = goog.require('Blockly.blockRendering.Row'); +const Types = goog.require('Blockly.blockRendering.Types'); +const svgPaths = goog.require('Blockly.utils.svgPaths'); /** * An object that draws a block based on the given rendering information. - * @param {!Blockly.BlockSvg} block The block to render. - * @param {!Blockly.blockRendering.RenderInfo} info An object containing all + * @param {!BlockSvg} block The block to render. + * @param {!RenderInfo} info An object containing all * information needed to render this block. * @package * @constructor */ -Blockly.blockRendering.Drawer = function(block, info) { +const Drawer = function(block, info) { this.block_ = block; this.info_ = info; this.topLeft_ = block.getRelativeToSurfaceXY(); @@ -41,7 +48,7 @@ Blockly.blockRendering.Drawer = function(block, info) { /** * The renderer's constant provider. - * @type {!Blockly.blockRendering.ConstantProvider} + * @type {!ConstantProvider} * @protected */ this.constants_ = info.getRenderer().getConstants(); @@ -57,7 +64,7 @@ Blockly.blockRendering.Drawer = function(block, info) { * required. * @package */ -Blockly.blockRendering.Drawer.prototype.draw = function() { +Drawer.prototype.draw = function() { this.hideHiddenIcons_(); this.drawOutline_(); this.drawInternals_(); @@ -78,7 +85,7 @@ Blockly.blockRendering.Drawer.prototype.draw = function() { * render. Anything that needs to be kept around should be set in this function. * @protected */ -Blockly.blockRendering.Drawer.prototype.recordSizeOnBlock_ = function() { +Drawer.prototype.recordSizeOnBlock_ = function() { // This is used when the block is reporting its size to anyone else. // The dark path adds to the size of the block in both X and Y. this.block_.height = this.info_.height; @@ -89,8 +96,8 @@ Blockly.blockRendering.Drawer.prototype.recordSizeOnBlock_ = function() { * Hide icons that were marked as hidden. * @protected */ -Blockly.blockRendering.Drawer.prototype.hideHiddenIcons_ = function() { - for (var i = 0, iconInfo; (iconInfo = this.info_.hiddenIcons[i]); i++) { +Drawer.prototype.hideHiddenIcons_ = function() { + for (let i = 0, iconInfo; (iconInfo = this.info_.hiddenIcons[i]); i++) { iconInfo.icon.iconGroup_.setAttribute('display', 'none'); } }; @@ -99,10 +106,10 @@ Blockly.blockRendering.Drawer.prototype.hideHiddenIcons_ = function() { * Create the outline of the block. This is a single continuous path. * @protected */ -Blockly.blockRendering.Drawer.prototype.drawOutline_ = function() { +Drawer.prototype.drawOutline_ = function() { this.drawTop_(); - for (var r = 1; r < this.info_.rows.length - 1; r++) { - var row = this.info_.rows[r]; + for (let r = 1; r < this.info_.rows.length - 1; r++) { + const row = this.info_.rows[r]; if (row.hasJaggedEdge) { this.drawJaggedEdge_(row); } else if (row.hasStatement) { @@ -123,91 +130,80 @@ Blockly.blockRendering.Drawer.prototype.drawOutline_ = function() { * details such as hats and rounded corners. * @protected */ -Blockly.blockRendering.Drawer.prototype.drawTop_ = function() { - var topRow = this.info_.topRow; - var elements = topRow.elements; +Drawer.prototype.drawTop_ = function() { + const topRow = this.info_.topRow; + const elements = topRow.elements; this.positionPreviousConnection_(); - this.outlinePath_ += - Blockly.utils.svgPaths.moveBy(topRow.xPos, this.info_.startY); - for (var i = 0, elem; (elem = elements[i]); i++) { - if (Blockly.blockRendering.Types.isLeftRoundedCorner(elem)) { - this.outlinePath_ += - this.constants_.OUTSIDE_CORNERS.topLeft; - } else if (Blockly.blockRendering.Types.isRightRoundedCorner(elem)) { - this.outlinePath_ += - this.constants_.OUTSIDE_CORNERS.topRight; - } else if (Blockly.blockRendering.Types.isPreviousConnection(elem)) { + this.outlinePath_ += svgPaths.moveBy(topRow.xPos, this.info_.startY); + for (let i = 0, elem; (elem = elements[i]); i++) { + if (Types.isLeftRoundedCorner(elem)) { + this.outlinePath_ += this.constants_.OUTSIDE_CORNERS.topLeft; + } else if (Types.isRightRoundedCorner(elem)) { + this.outlinePath_ += this.constants_.OUTSIDE_CORNERS.topRight; + } else if (Types.isPreviousConnection(elem)) { this.outlinePath_ += elem.shape.pathLeft; - } else if (Blockly.blockRendering.Types.isHat(elem)) { + } else if (Types.isHat(elem)) { this.outlinePath_ += this.constants_.START_HAT.path; - } else if (Blockly.blockRendering.Types.isSpacer(elem)) { - this.outlinePath_ += Blockly.utils.svgPaths.lineOnAxis('h', elem.width); + } else if (Types.isSpacer(elem)) { + this.outlinePath_ += svgPaths.lineOnAxis('h', elem.width); } // No branch for a square corner, because it's a no-op. } - this.outlinePath_ += Blockly.utils.svgPaths.lineOnAxis('v', topRow.height); + this.outlinePath_ += svgPaths.lineOnAxis('v', topRow.height); }; /** * Add steps for the jagged edge of a row on a collapsed block. - * @param {!Blockly.blockRendering.Row} row The row to draw the side of. + * @param {!Row} row The row to draw the side of. * @protected */ -Blockly.blockRendering.Drawer.prototype.drawJaggedEdge_ = function(row) { - var remainder = - row.height - this.constants_.JAGGED_TEETH.height; - this.outlinePath_ += this.constants_.JAGGED_TEETH.path + - Blockly.utils.svgPaths.lineOnAxis('v', remainder); +Drawer.prototype.drawJaggedEdge_ = function(row) { + const remainder = row.height - this.constants_.JAGGED_TEETH.height; + this.outlinePath_ += + this.constants_.JAGGED_TEETH.path + svgPaths.lineOnAxis('v', remainder); }; /** * Add steps for an external value input, rendered as a notch in the side * of the block. - * @param {!Blockly.blockRendering.Row} row The row that this input - * belongs to. + * @param {!Row} row The row that this input belongs to. * @protected */ -Blockly.blockRendering.Drawer.prototype.drawValueInput_ = function(row) { - var input = row.getLastInput(); +Drawer.prototype.drawValueInput_ = function(row) { + const input = row.getLastInput(); this.positionExternalValueConnection_(row); - var pathDown = (typeof input.shape.pathDown == "function") ? + const pathDown = (typeof input.shape.pathDown == 'function') ? input.shape.pathDown(input.height) : input.shape.pathDown; - this.outlinePath_ += - Blockly.utils.svgPaths.lineOnAxis('H', input.xPos + input.width) + - pathDown + - Blockly.utils.svgPaths.lineOnAxis('v', row.height - input.connectionHeight); + this.outlinePath_ += svgPaths.lineOnAxis('H', input.xPos + input.width) + + pathDown + svgPaths.lineOnAxis('v', row.height - input.connectionHeight); }; /** * Add steps for a statement input. - * @param {!Blockly.blockRendering.Row} row The row that this input - * belongs to. + * @param {!Row} row The row that this input belongs to. * @protected */ -Blockly.blockRendering.Drawer.prototype.drawStatementInput_ = function(row) { - var input = row.getLastInput(); +Drawer.prototype.drawStatementInput_ = function(row) { + const input = row.getLastInput(); // Where to start drawing the notch, which is on the right side in LTR. - var x = input.xPos + input.notchOffset + input.shape.width; + const x = input.xPos + input.notchOffset + input.shape.width; - var innerTopLeftCorner = - input.shape.pathRight + - Blockly.utils.svgPaths.lineOnAxis('h', - -(input.notchOffset - this.constants_.INSIDE_CORNERS.width)) + + const innerTopLeftCorner = input.shape.pathRight + + svgPaths.lineOnAxis( + 'h', -(input.notchOffset - this.constants_.INSIDE_CORNERS.width)) + this.constants_.INSIDE_CORNERS.pathTop; - var innerHeight = - row.height - (2 * this.constants_.INSIDE_CORNERS.height); + const innerHeight = row.height - (2 * this.constants_.INSIDE_CORNERS.height); - this.outlinePath_ += Blockly.utils.svgPaths.lineOnAxis('H', x) + - innerTopLeftCorner + - Blockly.utils.svgPaths.lineOnAxis('v', innerHeight) + + this.outlinePath_ += svgPaths.lineOnAxis('H', x) + innerTopLeftCorner + + svgPaths.lineOnAxis('v', innerHeight) + this.constants_.INSIDE_CORNERS.pathBottom + - Blockly.utils.svgPaths.lineOnAxis('H', row.xPos + row.width); + svgPaths.lineOnAxis('H', row.xPos + row.width); this.positionStatementInputConnection_(row); }; @@ -215,13 +211,11 @@ Blockly.blockRendering.Drawer.prototype.drawStatementInput_ = function(row) { /** * Add steps for the right side of a row that does not have value or * statement input connections. - * @param {!Blockly.blockRendering.Row} row The row to draw the - * side of. + * @param {!Row} row The row to draw the side of. * @protected */ -Blockly.blockRendering.Drawer.prototype.drawRightSideRow_ = function(row) { - this.outlinePath_ += - Blockly.utils.svgPaths.lineOnAxis('V', row.yPos + row.height); +Drawer.prototype.drawRightSideRow_ = function(row) { + this.outlinePath_ += svgPaths.lineOnAxis('V', row.yPos + row.height); }; @@ -230,30 +224,30 @@ Blockly.blockRendering.Drawer.prototype.drawRightSideRow_ = function(row) { * for the next connection. * @protected */ -Blockly.blockRendering.Drawer.prototype.drawBottom_ = function() { - var bottomRow = this.info_.bottomRow; - var elems = bottomRow.elements; +Drawer.prototype.drawBottom_ = function() { + const bottomRow = this.info_.bottomRow; + const elems = bottomRow.elements; this.positionNextConnection_(); - var rightCornerYOffset = 0; - var outlinePath = ''; - for (var i = elems.length - 1, elem; (elem = elems[i]); i--) { - if (Blockly.blockRendering.Types.isNextConnection(elem)) { + let rightCornerYOffset = 0; + let outlinePath = ''; + for (let i = elems.length - 1, elem; (elem = elems[i]); i--) { + if (Types.isNextConnection(elem)) { outlinePath += elem.shape.pathRight; - } else if (Blockly.blockRendering.Types.isLeftSquareCorner(elem)) { - outlinePath += Blockly.utils.svgPaths.lineOnAxis('H', bottomRow.xPos); - } else if (Blockly.blockRendering.Types.isLeftRoundedCorner(elem)) { + } else if (Types.isLeftSquareCorner(elem)) { + outlinePath += svgPaths.lineOnAxis('H', bottomRow.xPos); + } else if (Types.isLeftRoundedCorner(elem)) { outlinePath += this.constants_.OUTSIDE_CORNERS.bottomLeft; - } else if (Blockly.blockRendering.Types.isRightRoundedCorner(elem)) { + } else if (Types.isRightRoundedCorner(elem)) { outlinePath += this.constants_.OUTSIDE_CORNERS.bottomRight; rightCornerYOffset = this.constants_.OUTSIDE_CORNERS.rightHeight; - } else if (Blockly.blockRendering.Types.isSpacer(elem)) { - outlinePath += Blockly.utils.svgPaths.lineOnAxis('h', elem.width * -1); + } else if (Types.isSpacer(elem)) { + outlinePath += svgPaths.lineOnAxis('h', elem.width * -1); } } - this.outlinePath_ += Blockly.utils.svgPaths.lineOnAxis('V', - bottomRow.baseline - rightCornerYOffset); + this.outlinePath_ += + svgPaths.lineOnAxis('V', bottomRow.baseline - rightCornerYOffset); this.outlinePath_ += outlinePath; }; @@ -262,21 +256,19 @@ Blockly.blockRendering.Drawer.prototype.drawBottom_ = function() { * connection * @protected */ -Blockly.blockRendering.Drawer.prototype.drawLeft_ = function() { - var outputConnection = this.info_.outputConnection; +Drawer.prototype.drawLeft_ = function() { + const outputConnection = this.info_.outputConnection; this.positionOutputConnection_(); if (outputConnection) { - var tabBottom = outputConnection.connectionOffsetY + - outputConnection.height; - var pathUp = (typeof outputConnection.shape.pathUp == "function") ? + const tabBottom = + outputConnection.connectionOffsetY + outputConnection.height; + const pathUp = (typeof outputConnection.shape.pathUp == 'function') ? outputConnection.shape.pathUp(outputConnection.height) : outputConnection.shape.pathUp; // Draw a line up to the bottom of the tab. - this.outlinePath_ += - Blockly.utils.svgPaths.lineOnAxis('V', tabBottom) + - pathUp; + this.outlinePath_ += svgPaths.lineOnAxis('V', tabBottom) + pathUp; } // Close off the path. This draws a vertical line up to the start of the // block's path, which may be either a rounded or a sharp corner. @@ -288,16 +280,15 @@ Blockly.blockRendering.Drawer.prototype.drawLeft_ = function() { * not depend on the outer path for placement. * @protected */ -Blockly.blockRendering.Drawer.prototype.drawInternals_ = function() { - for (var i = 0, row; (row = this.info_.rows[i]); i++) { - for (var j = 0, elem; (elem = row.elements[j]); j++) { - if (Blockly.blockRendering.Types.isInlineInput(elem)) { +Drawer.prototype.drawInternals_ = function() { + for (let i = 0, row; (row = this.info_.rows[i]); i++) { + for (let j = 0, elem; (elem = row.elements[j]); j++) { + if (Types.isInlineInput(elem)) { this.drawInlineInput_( - /** @type {!Blockly.blockRendering.InlineInput} */ (elem)); - } else if (Blockly.blockRendering.Types.isIcon(elem) || - Blockly.blockRendering.Types.isField(elem)) { + /** @type {!InlineInput} */ (elem)); + } else if (Types.isIcon(elem) || Types.isField(elem)) { this.layoutField_( - /** @type {!Blockly.blockRendering.Field|!Blockly.blockRendering.Icon} */ + /** @type {!Field|!Icon} */ (elem)); } } @@ -306,20 +297,21 @@ Blockly.blockRendering.Drawer.prototype.drawInternals_ = function() { /** * Push a field or icon's new position to its SVG root. - * @param {!Blockly.blockRendering.Icon|!Blockly.blockRendering.Field} fieldInfo + * @param {!Icon|!Field} fieldInfo * The rendering information for the field or icon. * @protected */ -Blockly.blockRendering.Drawer.prototype.layoutField_ = function(fieldInfo) { - if (Blockly.blockRendering.Types.isField(fieldInfo)) { - var svgGroup = fieldInfo.field.getSvgRoot(); - } else if (Blockly.blockRendering.Types.isIcon(fieldInfo)) { - var svgGroup = fieldInfo.icon.iconGroup_; +Drawer.prototype.layoutField_ = function(fieldInfo) { + let svgGroup; + if (Types.isField(fieldInfo)) { + svgGroup = fieldInfo.field.getSvgRoot(); + } else if (Types.isIcon(fieldInfo)) { + svgGroup = fieldInfo.icon.iconGroup_; } - var yPos = fieldInfo.centerline - fieldInfo.height / 2; - var xPos = fieldInfo.xPos; - var scale = ''; + const yPos = fieldInfo.centerline - fieldInfo.height / 2; + let xPos = fieldInfo.xPos; + let scale = ''; if (this.info_.RTL) { xPos = -(xPos + fieldInfo.width); if (fieldInfo.flipRtl) { @@ -327,7 +319,7 @@ Blockly.blockRendering.Drawer.prototype.layoutField_ = function(fieldInfo) { scale = 'scale(-1 1)'; } } - if (Blockly.blockRendering.Types.isIcon(fieldInfo)) { + if (Types.isIcon(fieldInfo)) { svgGroup.setAttribute('display', 'block'); svgGroup.setAttribute('transform', 'translate(' + xPos + ',' + yPos + ')'); fieldInfo.icon.computeIconLocation(); @@ -345,26 +337,24 @@ Blockly.blockRendering.Drawer.prototype.layoutField_ = function(fieldInfo) { /** * Add steps for an inline input. - * @param {!Blockly.blockRendering.InlineInput} input The information about the + * @param {!InlineInput} input The information about the * input to render. * @protected */ -Blockly.blockRendering.Drawer.prototype.drawInlineInput_ = function(input) { - var width = input.width; - var height = input.height; - var yPos = input.centerline - height / 2; +Drawer.prototype.drawInlineInput_ = function(input) { + const width = input.width; + const height = input.height; + const yPos = input.centerline - height / 2; - var connectionTop = input.connectionOffsetY; - var connectionBottom = input.connectionHeight + connectionTop; - var connectionRight = input.xPos + input.connectionWidth; + const connectionTop = input.connectionOffsetY; + const connectionBottom = input.connectionHeight + connectionTop; + const connectionRight = input.xPos + input.connectionWidth; - this.inlinePath_ += Blockly.utils.svgPaths.moveTo(connectionRight, yPos) + - Blockly.utils.svgPaths.lineOnAxis('v', connectionTop) + - input.shape.pathDown + - Blockly.utils.svgPaths.lineOnAxis('v', height - connectionBottom) + - Blockly.utils.svgPaths.lineOnAxis('h', width - input.connectionWidth) + - Blockly.utils.svgPaths.lineOnAxis('v', -height) + - 'z'; + this.inlinePath_ += svgPaths.moveTo(connectionRight, yPos) + + svgPaths.lineOnAxis('v', connectionTop) + input.shape.pathDown + + svgPaths.lineOnAxis('v', height - connectionBottom) + + svgPaths.lineOnAxis('h', width - input.connectionWidth) + + svgPaths.lineOnAxis('v', -height) + 'z'; this.positionInlineInputConnection_(input); }; @@ -373,21 +363,21 @@ Blockly.blockRendering.Drawer.prototype.drawInlineInput_ = function(input) { * Position the connection on an inline value input, taking into account * RTL and the small gap between the parent block and child block which lets the * parent block's dark path show through. - * @param {Blockly.blockRendering.InlineInput} input The information about + * @param {InlineInput} input The information about * the input that the connection is on. * @protected */ -Blockly.blockRendering.Drawer.prototype.positionInlineInputConnection_ = function(input) { - var yPos = input.centerline - input.height / 2; +Drawer.prototype.positionInlineInputConnection_ = function(input) { + const yPos = input.centerline - input.height / 2; // Move the connection. if (input.connectionModel) { // xPos already contains info about startX - var connX = input.xPos + input.connectionWidth + input.connectionOffsetX; + let connX = input.xPos + input.connectionWidth + input.connectionOffsetX; if (this.info_.RTL) { connX *= -1; } - input.connectionModel.setOffsetInBlock(connX, - yPos + input.connectionOffsetY); + input.connectionModel.setOffsetInBlock( + connX, yPos + input.connectionOffsetY); } }; @@ -395,13 +385,13 @@ Blockly.blockRendering.Drawer.prototype.positionInlineInputConnection_ = functio * Position the connection on a statement input, taking into account * RTL and the small gap between the parent block and child block which lets the * parent block's dark path show through. - * @param {!Blockly.blockRendering.Row} row The row that the connection is on. + * @param {!Row} row The row that the connection is on. * @protected */ -Blockly.blockRendering.Drawer.prototype.positionStatementInputConnection_ = function(row) { - var input = row.getLastInput(); +Drawer.prototype.positionStatementInputConnection_ = function(row) { + const input = row.getLastInput(); if (input.connectionModel) { - var connX = row.xPos + row.statementEdge + input.notchOffset; + let connX = row.xPos + row.statementEdge + input.notchOffset; if (this.info_.RTL) { connX *= -1; } @@ -413,13 +403,13 @@ Blockly.blockRendering.Drawer.prototype.positionStatementInputConnection_ = func * Position the connection on an external value input, taking into account * RTL and the small gap between the parent block and child block which lets the * parent block's dark path show through. - * @param {!Blockly.blockRendering.Row} row The row that the connection is on. + * @param {!Row} row The row that the connection is on. * @protected */ -Blockly.blockRendering.Drawer.prototype.positionExternalValueConnection_ = function(row) { - var input = row.getLastInput(); +Drawer.prototype.positionExternalValueConnection_ = function(row) { + const input = row.getLastInput(); if (input.connectionModel) { - var connX = row.xPos + row.width; + let connX = row.xPos + row.width; if (this.info_.RTL) { connX *= -1; } @@ -431,11 +421,11 @@ Blockly.blockRendering.Drawer.prototype.positionExternalValueConnection_ = funct * Position the previous connection on a block. * @protected */ -Blockly.blockRendering.Drawer.prototype.positionPreviousConnection_ = function() { - var topRow = this.info_.topRow; +Drawer.prototype.positionPreviousConnection_ = function() { + const topRow = this.info_.topRow; if (topRow.connection) { - var x = topRow.xPos + topRow.notchOffset; - var connX = (this.info_.RTL ? -x : x); + const x = topRow.xPos + topRow.notchOffset; + const connX = (this.info_.RTL ? -x : x); topRow.connection.connectionModel.setOffsetInBlock(connX, 0); } }; @@ -444,13 +434,13 @@ Blockly.blockRendering.Drawer.prototype.positionPreviousConnection_ = function() * Position the next connection on a block. * @protected */ -Blockly.blockRendering.Drawer.prototype.positionNextConnection_ = function() { - var bottomRow = this.info_.bottomRow; +Drawer.prototype.positionNextConnection_ = function() { + const bottomRow = this.info_.bottomRow; if (bottomRow.connection) { - var connInfo = bottomRow.connection; - var x = connInfo.xPos; // Already contains info about startX. - var connX = (this.info_.RTL ? -x : x); + const connInfo = bottomRow.connection; + const x = connInfo.xPos; // Already contains info about startX. + const connX = (this.info_.RTL ? -x : x); connInfo.connectionModel.setOffsetInBlock(connX, bottomRow.baseline); } }; @@ -459,11 +449,13 @@ Blockly.blockRendering.Drawer.prototype.positionNextConnection_ = function() { * Position the output connection on a block. * @protected */ -Blockly.blockRendering.Drawer.prototype.positionOutputConnection_ = function() { +Drawer.prototype.positionOutputConnection_ = function() { if (this.info_.outputConnection) { - var x = this.info_.startX + this.info_.outputConnection.connectionOffsetX; - var connX = this.info_.RTL ? -x : x; - this.block_.outputConnection.setOffsetInBlock(connX, - this.info_.outputConnection.connectionOffsetY); + const x = this.info_.startX + this.info_.outputConnection.connectionOffsetX; + const connX = this.info_.RTL ? -x : x; + this.block_.outputConnection.setOffsetInBlock( + connX, this.info_.outputConnection.connectionOffsetY); } }; + +exports = Drawer; diff --git a/core/renderers/common/info.js b/core/renderers/common/info.js index f3eac053a..0f8548192 100644 --- a/core/renderers/common/info.js +++ b/core/renderers/common/info.js @@ -10,37 +10,45 @@ */ 'use strict'; -goog.provide('Blockly.blockRendering.RenderInfo'); +goog.module('Blockly.blockRendering.RenderInfo'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.blockRendering.BottomRow'); -goog.require('Blockly.blockRendering.ExternalValueInput'); -goog.require('Blockly.blockRendering.Field'); -goog.require('Blockly.blockRendering.Hat'); -goog.require('Blockly.blockRendering.InlineInput'); -goog.require('Blockly.blockRendering.InputRow'); -goog.require('Blockly.blockRendering.InRowSpacer'); -goog.require('Blockly.blockRendering.JaggedEdge'); -goog.require('Blockly.blockRendering.Measurable'); -goog.require('Blockly.blockRendering.NextConnection'); -goog.require('Blockly.blockRendering.OutputConnection'); -goog.require('Blockly.blockRendering.PreviousConnection'); -goog.require('Blockly.blockRendering.RoundCorner'); -goog.require('Blockly.blockRendering.Row'); -goog.require('Blockly.blockRendering.SpacerRow'); -goog.require('Blockly.blockRendering.SquareCorner'); -goog.require('Blockly.blockRendering.StatementInput'); -goog.require('Blockly.blockRendering.TopRow'); -goog.require('Blockly.blockRendering.Types'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); -goog.require('Blockly.inputTypes'); +/* eslint-disable-next-line no-unused-vars */ +const BlockSvg = goog.requireType('Blockly.BlockSvg'); +const BottomRow = goog.require('Blockly.blockRendering.BottomRow'); +/* eslint-disable-next-line no-unused-vars */ +const ConstantProvider = goog.requireType('Blockly.blockRendering.ConstantProvider'); +const ExternalValueInput = goog.require('Blockly.blockRendering.ExternalValueInput'); +const Field = goog.require('Blockly.blockRendering.Field'); +const Hat = goog.require('Blockly.blockRendering.Hat'); +const Icon = goog.require('Blockly.blockRendering.Icon'); +const InlineInput = goog.require('Blockly.blockRendering.InlineInput'); +/* eslint-disable-next-line no-unused-vars */ +const Input = goog.requireType('Blockly.Input'); +const InputRow = goog.require('Blockly.blockRendering.InputRow'); +const InRowSpacer = goog.require('Blockly.blockRendering.InRowSpacer'); +const JaggedEdge = goog.require('Blockly.blockRendering.JaggedEdge'); +/* eslint-disable-next-line no-unused-vars */ +const Measurable = goog.require('Blockly.blockRendering.Measurable'); +const NextConnection = goog.require('Blockly.blockRendering.NextConnection'); +const OutputConnection = goog.require('Blockly.blockRendering.OutputConnection'); +const PreviousConnection = goog.require('Blockly.blockRendering.PreviousConnection'); +/* eslint-disable-next-line no-unused-vars */ +const RenderedConnection = goog.requireType('Blockly.RenderedConnection'); +/* eslint-disable-next-line no-unused-vars */ +const Renderer = goog.requireType('Blockly.blockRendering.Renderer'); +/* eslint-disable-next-line no-unused-vars */ +const RoundCorner = goog.require('Blockly.blockRendering.RoundCorner'); +/* eslint-disable-next-line no-unused-vars */ +const Row = goog.require('Blockly.blockRendering.Row'); +const SpacerRow = goog.require('Blockly.blockRendering.SpacerRow'); +const SquareCorner = goog.require('Blockly.blockRendering.SquareCorner'); +const StatementInput = goog.require('Blockly.blockRendering.StatementInput'); +const TopRow = goog.require('Blockly.blockRendering.TopRow'); +const Types = goog.require('Blockly.blockRendering.Types'); +const {ALIGN} = goog.require('Blockly.constants'); +const {DUMMY, STATEMENT, VALUE} = goog.require('Blockly.inputTypes'); -goog.requireType('Blockly.blockRendering.ConstantProvider'); -goog.requireType('Blockly.blockRendering.Icon'); -goog.requireType('Blockly.blockRendering.Renderer'); -goog.requireType('Blockly.BlockSvg'); -goog.requireType('Blockly.Input'); -goog.requireType('Blockly.RenderedConnection'); /** @@ -50,24 +58,24 @@ goog.requireType('Blockly.RenderedConnection'); * may choose to rerender when getSize() is called). However, calling it * repeatedly may be expensive. * - * @param {!Blockly.blockRendering.Renderer} renderer The renderer in use. - * @param {!Blockly.BlockSvg} block The block to measure. + * @param {!Renderer} renderer The renderer in use. + * @param {!BlockSvg} block The block to measure. * @constructor * @package */ -Blockly.blockRendering.RenderInfo = function(renderer, block) { +const RenderInfo = function(renderer, block) { this.block_ = block; /** * The block renderer in use. - * @type {!Blockly.blockRendering.Renderer} + * @type {!Renderer} * @protected */ this.renderer_ = renderer; /** * The renderer's constant provider. - * @type {!Blockly.blockRendering.ConstantProvider} + * @type {!ConstantProvider} * @protected */ this.constants_ = this.renderer_.getConstants(); @@ -75,12 +83,13 @@ Blockly.blockRendering.RenderInfo = function(renderer, block) { /** * A measurable representing the output connection if the block has one. * Otherwise null. - * @type {Blockly.blockRendering.OutputConnection} + * @type {OutputConnection} */ - this.outputConnection = !block.outputConnection ? null : - new Blockly.blockRendering.OutputConnection( + this.outputConnection = !block.outputConnection ? + null : + new OutputConnection( this.constants_, - /** @type {Blockly.RenderedConnection} */(block.outputConnection)); + /** @type {RenderedConnection} */ (block.outputConnection)); /** * Whether the block should be rendered as a single line, either because it's @@ -135,33 +144,33 @@ Blockly.blockRendering.RenderInfo = function(renderer, block) { /** * An array of Row objects containing sizing information. - * @type {!Array} + * @type {!Array} */ this.rows = []; /** * An array of input rows on the block. - * @type {!Array} + * @type {!Array} */ this.inputRows = []; /** * An array of measurable objects containing hidden icons. - * @type {!Array} + * @type {!Array} */ this.hiddenIcons = []; /** * An object with rendering information about the top row of the block. - * @type {!Blockly.blockRendering.TopRow} + * @type {!TopRow} */ - this.topRow = new Blockly.blockRendering.TopRow(this.constants_); + this.topRow = new TopRow(this.constants_); /** * An object with rendering information about the bottom row of the block. - * @type {!Blockly.blockRendering.BottomRow} + * @type {!BottomRow} */ - this.bottomRow = new Blockly.blockRendering.BottomRow(this.constants_); + this.bottomRow = new BottomRow(this.constants_); // The position of the start point for drawing, relative to the block's // location. @@ -171,10 +180,10 @@ Blockly.blockRendering.RenderInfo = function(renderer, block) { /** * Get the block renderer in use. - * @return {!Blockly.blockRendering.Renderer} The block renderer in use. + * @return {!Renderer} The block renderer in use. * @package */ -Blockly.blockRendering.RenderInfo.prototype.getRenderer = function() { +RenderInfo.prototype.getRenderer = function() { return this.renderer_; }; @@ -188,7 +197,7 @@ Blockly.blockRendering.RenderInfo.prototype.getRenderer = function() { * * @package */ -Blockly.blockRendering.RenderInfo.prototype.measure = function() { +RenderInfo.prototype.measure = function() { this.createRows_(); this.addElemSpacing_(); this.addRowSpacing_(); @@ -202,16 +211,16 @@ Blockly.blockRendering.RenderInfo.prototype.measure = function() { * block. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() { +RenderInfo.prototype.createRows_ = function() { this.populateTopRow_(); this.rows.push(this.topRow); - var activeRow = new Blockly.blockRendering.InputRow(this.constants_); + let activeRow = new InputRow(this.constants_); this.inputRows.push(activeRow); // Icons always go on the first row, before anything else. - var icons = this.block_.getIcons(); - for (var i = 0, icon; (icon = icons[i]); i++) { - var iconInfo = new Blockly.blockRendering.Icon(this.constants_, icon); + const icons = this.block_.getIcons(); + for (let i = 0, icon; (icon = icons[i]); i++) { + const iconInfo = new Icon(this.constants_, icon); if (this.isCollapsed && icon.collapseHidden) { this.hiddenIcons.push(iconInfo); } else { @@ -219,24 +228,23 @@ Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() { } } - var lastInput = null; + let lastInput = null; // Loop across all of the inputs on the block, creating objects for anything // that needs to be rendered and breaking the block up into visual rows. - for (var i = 0, input; (input = this.block_.inputList[i]); i++) { + for (let i = 0, input; (input = this.block_.inputList[i]); i++) { if (!input.isVisible()) { continue; } if (this.shouldStartNewRow_(input, lastInput)) { // Finish this row and create a new one. this.rows.push(activeRow); - activeRow = new Blockly.blockRendering.InputRow(this.constants_); + activeRow = new InputRow(this.constants_); this.inputRows.push(activeRow); } // All of the fields in an input go on the same row. - for (var j = 0, field; (field = input.fieldRow[j]); j++) { - activeRow.elements.push( - new Blockly.blockRendering.Field(this.constants_, field, input)); + for (let j = 0, field; (field = input.fieldRow[j]); j++) { + activeRow.elements.push(new Field(this.constants_, field, input)); } this.addInput_(input, activeRow); lastInput = input; @@ -244,8 +252,7 @@ Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() { if (this.isCollapsed) { activeRow.hasJaggedEdge = true; - activeRow.elements.push( - new Blockly.blockRendering.JaggedEdge(this.constants_)); + activeRow.elements.push(new JaggedEdge(this.constants_)); } if (activeRow.elements.length || activeRow.hasDummyInput) { @@ -259,31 +266,31 @@ Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() { * Create all non-spacer elements that belong on the top row. * @package */ -Blockly.blockRendering.RenderInfo.prototype.populateTopRow_ = function() { - var hasPrevious = !!this.block_.previousConnection; - var hasHat = (this.block_.hat ? - this.block_.hat === 'cap' : this.constants_.ADD_START_HATS) && +RenderInfo.prototype.populateTopRow_ = function() { + const hasPrevious = !!this.block_.previousConnection; + const hasHat = (this.block_.hat ? this.block_.hat === 'cap' : + this.constants_.ADD_START_HATS) && !this.outputConnection && !hasPrevious; - var cornerClass = this.topRow.hasLeftSquareCorner(this.block_) ? - Blockly.blockRendering.SquareCorner : Blockly.blockRendering.RoundCorner; + let cornerClass = + this.topRow.hasLeftSquareCorner(this.block_) ? SquareCorner : RoundCorner; this.topRow.elements.push(new cornerClass(this.constants_)); if (hasHat) { - var hat = new Blockly.blockRendering.Hat(this.constants_); + const hat = new Hat(this.constants_); this.topRow.elements.push(hat); this.topRow.capline = hat.ascenderHeight; } else if (hasPrevious) { this.topRow.hasPreviousConnection = true; - this.topRow.connection = new Blockly.blockRendering.PreviousConnection( + this.topRow.connection = new PreviousConnection( this.constants_, - /** @type {Blockly.RenderedConnection} */ + /** @type {RenderedConnection} */ (this.block_.previousConnection)); this.topRow.elements.push(this.topRow.connection); } - var precedesStatement = this.block_.inputList.length && - this.block_.inputList[0].type == Blockly.inputTypes.STATEMENT; + const precedesStatement = this.block_.inputList.length && + this.block_.inputList[0].type == STATEMENT; // This is the minimum height for the row. If one of its elements has a // greater height it will be overwritten in the compute pass. @@ -294,8 +301,8 @@ Blockly.blockRendering.RenderInfo.prototype.populateTopRow_ = function() { this.topRow.minHeight = this.constants_.TOP_ROW_MIN_HEIGHT; } - cornerClass = this.topRow.hasRightSquareCorner(this.block_) ? - Blockly.blockRendering.SquareCorner : Blockly.blockRendering.RoundCorner; + cornerClass = this.topRow.hasRightSquareCorner(this.block_) ? SquareCorner : + RoundCorner; this.topRow.elements.push(new cornerClass(this.constants_, 'right')); }; @@ -303,79 +310,72 @@ Blockly.blockRendering.RenderInfo.prototype.populateTopRow_ = function() { * Create all non-spacer elements that belong on the bottom row. * @package */ -Blockly.blockRendering.RenderInfo.prototype.populateBottomRow_ = function() { +RenderInfo.prototype.populateBottomRow_ = function() { this.bottomRow.hasNextConnection = !!this.block_.nextConnection; - var followsStatement = this.block_.inputList.length && - this.block_.inputList[this.block_.inputList.length - 1].type == - Blockly.inputTypes.STATEMENT; + const followsStatement = this.block_.inputList.length && + this.block_.inputList[this.block_.inputList.length - 1].type == STATEMENT; // This is the minimum height for the row. If one of its elements has a // greater height it will be overwritten in the compute pass. if (followsStatement) { this.bottomRow.minHeight = - this.constants_.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT; + this.constants_.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT; } else { this.bottomRow.minHeight = this.constants_.BOTTOM_ROW_MIN_HEIGHT; } - var leftSquareCorner = this.bottomRow.hasLeftSquareCorner(this.block_); + const leftSquareCorner = this.bottomRow.hasLeftSquareCorner(this.block_); if (leftSquareCorner) { - this.bottomRow.elements.push( - new Blockly.blockRendering.SquareCorner(this.constants_)); + this.bottomRow.elements.push(new SquareCorner(this.constants_)); } else { - this.bottomRow.elements.push( - new Blockly.blockRendering.RoundCorner(this.constants_)); + this.bottomRow.elements.push(new RoundCorner(this.constants_)); } if (this.bottomRow.hasNextConnection) { - this.bottomRow.connection = new Blockly.blockRendering.NextConnection( + this.bottomRow.connection = new NextConnection( this.constants_, - /** @type {Blockly.RenderedConnection} */ (this.block_.nextConnection)); + /** @type {RenderedConnection} */ (this.block_.nextConnection)); this.bottomRow.elements.push(this.bottomRow.connection); } - var rightSquareCorner = this.bottomRow.hasRightSquareCorner(this.block_); + const rightSquareCorner = this.bottomRow.hasRightSquareCorner(this.block_); if (rightSquareCorner) { - this.bottomRow.elements.push( - new Blockly.blockRendering.SquareCorner(this.constants_, 'right')); + this.bottomRow.elements.push(new SquareCorner(this.constants_, 'right')); } else { - this.bottomRow.elements.push( - new Blockly.blockRendering.RoundCorner(this.constants_, 'right')); + this.bottomRow.elements.push(new RoundCorner(this.constants_, 'right')); } }; /** * Add an input element to the active row, if needed, and record the type of the * input on the row. - * @param {!Blockly.Input} input The input to record information about. - * @param {!Blockly.blockRendering.Row} activeRow The row that is currently being + * @param {!Input} input The input to record information about. + * @param {!Row} activeRow The row that is currently being * populated. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.addInput_ = function(input, activeRow) { +RenderInfo.prototype.addInput_ = function(input, activeRow) { // Non-dummy inputs have visual representations onscreen. - if (this.isInline && input.type == Blockly.inputTypes.VALUE) { - activeRow.elements.push( - new Blockly.blockRendering.InlineInput(this.constants_, input)); + if (this.isInline && input.type == VALUE) { + activeRow.elements.push(new InlineInput(this.constants_, input)); activeRow.hasInlineInput = true; - } else if (input.type == Blockly.inputTypes.STATEMENT) { - activeRow.elements.push( - new Blockly.blockRendering.StatementInput(this.constants_, input)); + } else if (input.type == STATEMENT) { + activeRow.elements.push(new StatementInput(this.constants_, input)); activeRow.hasStatement = true; - } else if (input.type == Blockly.inputTypes.VALUE) { - activeRow.elements.push( - new Blockly.blockRendering.ExternalValueInput(this.constants_, input)); + } else if (input.type == VALUE) { + activeRow.elements.push(new ExternalValueInput(this.constants_, input)); activeRow.hasExternalInput = true; - } else if (input.type == Blockly.inputTypes.DUMMY) { + } else if (input.type == DUMMY) { // Dummy inputs have no visual representation, but the information is still // important. - activeRow.minHeight = Math.max(activeRow.minHeight, + activeRow.minHeight = Math.max( + activeRow.minHeight, input.getSourceBlock() && input.getSourceBlock().isShadow() ? - this.constants_.DUMMY_INPUT_SHADOW_MIN_HEIGHT : - this.constants_.DUMMY_INPUT_MIN_HEIGHT); + this.constants_.DUMMY_INPUT_SHADOW_MIN_HEIGHT : + this.constants_.DUMMY_INPUT_MIN_HEIGHT); activeRow.hasDummyInput = true; } if (activeRow.align == null) { @@ -385,25 +385,23 @@ Blockly.blockRendering.RenderInfo.prototype.addInput_ = function(input, activeRo /** * Decide whether to start a new row between the two Blockly.Inputs. - * @param {!Blockly.Input} input The first input to consider - * @param {Blockly.Input} lastInput The input that follows. + * @param {!Input} input The first input to consider + * @param {Input} lastInput The input that follows. * @return {boolean} True if the next input should be rendered on a new row. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.shouldStartNewRow_ = function(input, lastInput) { +RenderInfo.prototype.shouldStartNewRow_ = function(input, lastInput) { // If this is the first input, just add to the existing row. // That row is either empty or has some icons in it. if (!lastInput) { return false; } // A statement input or an input following one always gets a new row. - if (input.type == Blockly.inputTypes.STATEMENT || - lastInput.type == Blockly.inputTypes.STATEMENT) { + if (input.type == STATEMENT || lastInput.type == STATEMENT) { return true; } // Value and dummy inputs get new row if inputs are not inlined. - if (input.type == Blockly.inputTypes.VALUE || - input.type == Blockly.inputTypes.DUMMY) { + if (input.type == VALUE || input.type == DUMMY) { return !this.isInline; } return false; @@ -413,29 +411,28 @@ Blockly.blockRendering.RenderInfo.prototype.shouldStartNewRow_ = function(input, * Add horizontal spacing between and around elements within each row. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.addElemSpacing_ = function() { - for (var i = 0, row; (row = this.rows[i]); i++) { - var oldElems = row.elements; +RenderInfo.prototype.addElemSpacing_ = function() { + for (let i = 0, row; (row = this.rows[i]); i++) { + const oldElems = row.elements; row.elements = []; // No spacing needed before the corner on the top row or the bottom row. if (row.startsWithElemSpacer()) { // There's a spacer before the first element in the row. - row.elements.push(new Blockly.blockRendering.InRowSpacer( + row.elements.push(new InRowSpacer( this.constants_, this.getInRowSpacing_(null, oldElems[0]))); } if (!oldElems.length) { continue; } - for (var e = 0; e < oldElems.length - 1; e++) { + for (let e = 0; e < oldElems.length - 1; e++) { row.elements.push(oldElems[e]); - var spacing = this.getInRowSpacing_(oldElems[e], oldElems[e + 1]); - row.elements.push( - new Blockly.blockRendering.InRowSpacer(this.constants_, spacing)); + const spacing = this.getInRowSpacing_(oldElems[e], oldElems[e + 1]); + row.elements.push(new InRowSpacer(this.constants_, spacing)); } row.elements.push(oldElems[oldElems.length - 1]); if (row.endsWithElemSpacer()) { // There's a spacer after the last element in the row. - row.elements.push(new Blockly.blockRendering.InRowSpacer( + row.elements.push(new InRowSpacer( this.constants_, this.getInRowSpacing_(oldElems[oldElems.length - 1], null))); } @@ -446,42 +443,40 @@ Blockly.blockRendering.RenderInfo.prototype.addElemSpacing_ = function() { * Calculate the width of a spacer element in a row based on the previous and * next elements in that row. For instance, extra padding is added between two * editable fields. - * @param {Blockly.blockRendering.Measurable} prev The element before the + * @param {Measurable} prev The element before the * spacer. - * @param {Blockly.blockRendering.Measurable} next The element after the spacer. + * @param {Measurable} next The element after the spacer. * @return {number} The size of the spacing between the two elements. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.getInRowSpacing_ = function(prev, next) { +RenderInfo.prototype.getInRowSpacing_ = function(prev, next) { if (!prev) { // Statement input padding. - if (next && Blockly.blockRendering.Types.isStatementInput(next)) { + if (next && Types.isStatementInput(next)) { return this.constants_.STATEMENT_INPUT_PADDING_LEFT; } } // Between inputs and the end of the row. - if (prev && Blockly.blockRendering.Types.isInput(prev) && !next) { - if (Blockly.blockRendering.Types.isExternalInput(prev)) { + if (prev && Types.isInput(prev) && !next) { + if (Types.isExternalInput(prev)) { return this.constants_.NO_PADDING; - } else if (Blockly.blockRendering.Types.isInlineInput(prev)) { + } else if (Types.isInlineInput(prev)) { return this.constants_.LARGE_PADDING; - } else if (Blockly.blockRendering.Types.isStatementInput(prev)) { + } else if (Types.isStatementInput(prev)) { return this.constants_.NO_PADDING; } } // Spacing between a square corner and a previous or next connection - if (prev && Blockly.blockRendering.Types.isLeftSquareCorner(prev) && next) { - if (Blockly.blockRendering.Types.isPreviousConnection(next) || - Blockly.blockRendering.Types.isNextConnection(next)) { + if (prev && Types.isLeftSquareCorner(prev) && next) { + if (Types.isPreviousConnection(next) || Types.isNextConnection(next)) { return next.notchOffset; } } // Spacing between a rounded corner and a previous or next connection. - if (prev && Blockly.blockRendering.Types.isLeftRoundedCorner(prev) && next) { - if (Blockly.blockRendering.Types.isPreviousConnection(next) || - Blockly.blockRendering.Types.isNextConnection(next)) { + if (prev && Types.isLeftRoundedCorner(prev) && next) { + if (Types.isPreviousConnection(next) || Types.isNextConnection(next)) { return next.notchOffset - this.constants_.CORNER_RADIUS; } } @@ -490,21 +485,21 @@ Blockly.blockRendering.RenderInfo.prototype.getInRowSpacing_ = function(prev, ne }; /** - * Figure out where the right edge of the block and right edge of statement inputs - * should be placed. + * Figure out where the right edge of the block and right edge of statement + * inputs should be placed. * @protected */ // TODO: More cleanup. -Blockly.blockRendering.RenderInfo.prototype.computeBounds_ = function() { - var widestStatementRowFields = 0; - var blockWidth = 0; - var widestRowWithConnectedBlocks = 0; - for (var i = 0, row; (row = this.rows[i]); i++) { +RenderInfo.prototype.computeBounds_ = function() { + let widestStatementRowFields = 0; + let blockWidth = 0; + let widestRowWithConnectedBlocks = 0; + for (let i = 0, row; (row = this.rows[i]); i++) { row.measure(); blockWidth = Math.max(blockWidth, row.width); if (row.hasStatement) { - var statementInput = row.getLastInput(); - var innerWidth = row.width - statementInput.width; + const statementInput = row.getLastInput(); + const innerWidth = row.width - statementInput.width; widestStatementRowFields = Math.max(widestStatementRowFields, innerWidth); } widestRowWithConnectedBlocks = @@ -514,7 +509,7 @@ Blockly.blockRendering.RenderInfo.prototype.computeBounds_ = function() { this.statementEdge = widestStatementRowFields; this.width = blockWidth; - for (var i = 0, row; (row = this.rows[i]); i++) { + for (let i = 0, row; (row = this.rows[i]); i++) { if (row.hasStatement) { row.statementEdge = this.statementEdge; } @@ -535,19 +530,19 @@ Blockly.blockRendering.RenderInfo.prototype.computeBounds_ = function() { * the sizes of all rows. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.alignRowElements_ = function() { - for (var i = 0, row; (row = this.rows[i]); i++) { +RenderInfo.prototype.alignRowElements_ = function() { + for (let i = 0, row; (row = this.rows[i]); i++) { if (row.hasStatement) { this.alignStatementRow_( - /** @type {!Blockly.blockRendering.InputRow} */ (row)); + /** @type {!InputRow} */ (row)); } else { - var currentWidth = row.width; - var desiredWidth = this.getDesiredRowWidth_(row); - var missingSpace = desiredWidth - currentWidth; + const currentWidth = row.width; + const desiredWidth = this.getDesiredRowWidth_(row); + const missingSpace = desiredWidth - currentWidth; if (missingSpace > 0) { this.addAlignmentPadding_(row, missingSpace); } - if (Blockly.blockRendering.Types.isTopOrBottomRow(row)) { + if (Types.isTopOrBottomRow(row)) { row.widthWithConnectedBlocks = row.width; } } @@ -556,12 +551,11 @@ Blockly.blockRendering.RenderInfo.prototype.alignRowElements_ = function() { /** * Calculate the desired width of an input row. - * @param {!Blockly.blockRendering.Row} _row The input row. + * @param {!Row} _row The input row. * @return {number} The desired width of the input row. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.getDesiredRowWidth_ = function( - _row) { +RenderInfo.prototype.getDesiredRowWidth_ = function(_row) { return this.width - this.startX; }; @@ -569,27 +563,26 @@ Blockly.blockRendering.RenderInfo.prototype.getDesiredRowWidth_ = function( * Modify the given row to add the given amount of padding around its fields. * The exact location of the padding is based on the alignment property of the * last input in the field. - * @param {Blockly.blockRendering.Row} row The row to add padding to. + * @param {Row} row The row to add padding to. * @param {number} missingSpace How much padding to add. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.addAlignmentPadding_ = function(row, - missingSpace) { - var firstSpacer = row.getFirstSpacer(); - var lastSpacer = row.getLastSpacer(); +RenderInfo.prototype.addAlignmentPadding_ = function(row, missingSpace) { + const firstSpacer = row.getFirstSpacer(); + const lastSpacer = row.getLastSpacer(); if (row.hasExternalInput || row.hasStatement) { row.widthWithConnectedBlocks += missingSpace; } // Decide where the extra padding goes. - if (row.align == Blockly.constants.ALIGN.LEFT) { + if (row.align == ALIGN.LEFT) { // Add padding to the end of the row. lastSpacer.width += missingSpace; - } else if (row.align == Blockly.constants.ALIGN.CENTRE) { + } else if (row.align == ALIGN.CENTRE) { // Split the padding between the beginning and end of the row. firstSpacer.width += missingSpace / 2; lastSpacer.width += missingSpace / 2; - } else if (row.align == Blockly.constants.ALIGN.RIGHT) { + } else if (row.align == ALIGN.RIGHT) { // Add padding at the beginning of the row. firstSpacer.width += missingSpace; } else { @@ -602,15 +595,15 @@ Blockly.blockRendering.RenderInfo.prototype.addAlignmentPadding_ = function(row, /** * Align the elements of a statement row based on computed bounds. * Unlike other types of rows, statement rows add space in multiple places. - * @param {!Blockly.blockRendering.InputRow} row The statement row to resize. + * @param {!InputRow} row The statement row to resize. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.alignStatementRow_ = function(row) { - var statementInput = row.getLastInput(); - var currentWidth = row.width - statementInput.width; - var desiredWidth = this.statementEdge; +RenderInfo.prototype.alignStatementRow_ = function(row) { + const statementInput = row.getLastInput(); + let currentWidth = row.width - statementInput.width; + let desiredWidth = this.statementEdge; // Add padding before the statement input. - var missingSpace = desiredWidth - currentWidth; + const missingSpace = desiredWidth - currentWidth; if (missingSpace > 0) { this.addAlignmentPadding_(row, missingSpace); } @@ -621,19 +614,19 @@ Blockly.blockRendering.RenderInfo.prototype.alignStatementRow_ = function(row) { statementInput.width += (desiredWidth - currentWidth); statementInput.height = Math.max(statementInput.height, row.height); row.width += (desiredWidth - currentWidth); - row.widthWithConnectedBlocks = Math.max(row.width, - this.statementEdge + row.connectedBlockWidths); + row.widthWithConnectedBlocks = + Math.max(row.width, this.statementEdge + row.connectedBlockWidths); }; /** * Add spacers between rows and set their sizes. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.addRowSpacing_ = function() { - var oldRows = this.rows; +RenderInfo.prototype.addRowSpacing_ = function() { + const oldRows = this.rows; this.rows = []; - for (var r = 0; r < oldRows.length; r++) { + for (let r = 0; r < oldRows.length; r++) { this.rows.push(oldRows[r]); if (r != oldRows.length - 1) { this.rows.push(this.makeSpacerRow_(oldRows[r], oldRows[r + 1])); @@ -643,16 +636,15 @@ Blockly.blockRendering.RenderInfo.prototype.addRowSpacing_ = function() { /** * Create a spacer row to go between prev and next, and set its size. - * @param {!Blockly.blockRendering.Row} prev The previous row. - * @param {!Blockly.blockRendering.Row} next The next row. - * @return {!Blockly.blockRendering.SpacerRow} The newly created spacer row. + * @param {!Row} prev The previous row. + * @param {!Row} next The next row. + * @return {!SpacerRow} The newly created spacer row. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.makeSpacerRow_ = function(prev, next) { - var height = this.getSpacerRowHeight_(prev, next); - var width = this.getSpacerRowWidth_(prev, next); - var spacer = new Blockly.blockRendering.SpacerRow( - this.constants_, height, width); +RenderInfo.prototype.makeSpacerRow_ = function(prev, next) { + const height = this.getSpacerRowHeight_(prev, next); + const width = this.getSpacerRowWidth_(prev, next); + const spacer = new SpacerRow(this.constants_, height, width); if (prev.hasStatement) { spacer.followsStatement = true; } @@ -664,25 +656,23 @@ Blockly.blockRendering.RenderInfo.prototype.makeSpacerRow_ = function(prev, next /** * Calculate the width of a spacer row. - * @param {!Blockly.blockRendering.Row} _prev The row before the spacer. - * @param {!Blockly.blockRendering.Row} _next The row after the spacer. + * @param {!Row} _prev The row before the spacer. + * @param {!Row} _next The row after the spacer. * @return {number} The desired width of the spacer row between these two rows. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.getSpacerRowWidth_ = function( - _prev, _next) { +RenderInfo.prototype.getSpacerRowWidth_ = function(_prev, _next) { return this.width - this.startX; }; /** * Calculate the height of a spacer row. - * @param {!Blockly.blockRendering.Row} _prev The row before the spacer. - * @param {!Blockly.blockRendering.Row} _next The row after the spacer. + * @param {!Row} _prev The row before the spacer. + * @param {!Row} _next The row after the spacer. * @return {number} The desired height of the spacer row between these two rows. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.getSpacerRowHeight_ = function( - _prev, _next) { +RenderInfo.prototype.getSpacerRowHeight_ = function(_prev, _next) { return this.constants_.MEDIUM_PADDING; }; @@ -691,26 +681,25 @@ Blockly.blockRendering.RenderInfo.prototype.getSpacerRowHeight_ = function( * This base implementation puts the centerline at the middle of the row * vertically, with no special cases. You will likely need extra logic to * handle (at minimum) top and bottom rows. - * @param {!Blockly.blockRendering.Row} row The row containing the element. - * @param {!Blockly.blockRendering.Measurable} elem The element to place. + * @param {!Row} row The row containing the element. + * @param {!Measurable} elem The element to place. * @return {number} The desired centerline of the given element, as an offset * from the top left of the block. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.getElemCenterline_ = function(row, - elem) { - if (Blockly.blockRendering.Types.isSpacer(elem)) { +RenderInfo.prototype.getElemCenterline_ = function(row, elem) { + if (Types.isSpacer(elem)) { return row.yPos + elem.height / 2; } - if (Blockly.blockRendering.Types.isBottomRow(row)) { - var baseline = row.yPos + row.height - row.descenderHeight; - if (Blockly.blockRendering.Types.isNextConnection(elem)) { + if (Types.isBottomRow(row)) { + const baseline = row.yPos + row.height - row.descenderHeight; + if (Types.isNextConnection(elem)) { return baseline + elem.height / 2; } return baseline - elem.height / 2; } - if (Blockly.blockRendering.Types.isTopRow(row)) { - if (Blockly.blockRendering.Types.isHat(elem)) { + if (Types.isTopRow(row)) { + if (Types.isHat(elem)) { return row.capline - elem.height / 2; } return row.capline + elem.height / 2; @@ -721,15 +710,14 @@ Blockly.blockRendering.RenderInfo.prototype.getElemCenterline_ = function(row, /** * Record final position information on elements on the given row, for use in * drawing. At minimum this records xPos and centerline on each element. - * @param {!Blockly.blockRendering.Row} row The row containing the elements. + * @param {!Row} row The row containing the elements. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.recordElemPositions_ = function( - row) { - var xCursor = row.xPos; - for (var j = 0, elem; (elem = row.elements[j]); j++) { +RenderInfo.prototype.recordElemPositions_ = function(row) { + let xCursor = row.xPos; + for (let j = 0, elem; (elem = row.elements[j]); j++) { // Now that row heights are finalized, make spacers use the row height. - if (Blockly.blockRendering.Types.isSpacer(elem)) { + if (Types.isSpacer(elem)) { elem.height = row.height; } elem.xPos = xCursor; @@ -743,13 +731,13 @@ Blockly.blockRendering.RenderInfo.prototype.recordElemPositions_ = function( * store the y position of each row, and record the height of the full block. * @protected */ -Blockly.blockRendering.RenderInfo.prototype.finalize_ = function() { +RenderInfo.prototype.finalize_ = function() { // Performance note: this could be combined with the draw pass, if the time // that this takes is excessive. But it shouldn't be, because it only // accesses and sets properties that already exist on the objects. - var widestRowWithConnectedBlocks = 0; - var yCursor = 0; - for (var i = 0, row; (row = this.rows[i]); i++) { + let widestRowWithConnectedBlocks = 0; + let yCursor = 0; + for (let i = 0, row; (row = this.rows[i]); i++) { row.yPos = yCursor; row.xPos = this.startX; yCursor += row.height; @@ -761,9 +749,9 @@ Blockly.blockRendering.RenderInfo.prototype.finalize_ = function() { if (this.outputConnection && this.block_.nextConnection && this.block_.nextConnection.isConnected()) { // Include width of connected block in value to stack width measurement. - widestRowWithConnectedBlocks = - Math.max(widestRowWithConnectedBlocks, - this.block_.nextConnection.targetBlock().getHeightWidth().width); + widestRowWithConnectedBlocks = Math.max( + widestRowWithConnectedBlocks, + this.block_.nextConnection.targetBlock().getHeightWidth().width); } this.widthWithChildren = widestRowWithConnectedBlocks + this.startX; @@ -772,3 +760,5 @@ Blockly.blockRendering.RenderInfo.prototype.finalize_ = function() { this.startY = this.topRow.capline; this.bottomRow.baseline = yCursor - this.bottomRow.descenderHeight; }; + +exports = RenderInfo; diff --git a/core/renderers/common/marker_svg.js b/core/renderers/common/marker_svg.js index f9559e071..36d12b119 100644 --- a/core/renderers/common/marker_svg.js +++ b/core/renderers/common/marker_svg.js @@ -15,8 +15,6 @@ goog.provide('Blockly.blockRendering.MarkerSvg'); goog.require('Blockly.ASTNode'); goog.require('Blockly.connectionTypes'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.MarkerMove'); diff --git a/core/renderers/common/renderer.js b/core/renderers/common/renderer.js index 77df5e518..37e4a883a 100644 --- a/core/renderers/common/renderer.js +++ b/core/renderers/common/renderer.js @@ -20,8 +20,6 @@ goog.require('Blockly.blockRendering.MarkerSvg'); goog.require('Blockly.blockRendering.PathObject'); goog.require('Blockly.blockRendering.RenderInfo'); goog.require('Blockly.connectionTypes'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.InsertionMarkerManager'); goog.require('Blockly.IRegistrable'); diff --git a/core/renderers/geras/info.js b/core/renderers/geras/info.js index ffc515a17..121e3b353 100644 --- a/core/renderers/geras/info.js +++ b/core/renderers/geras/info.js @@ -19,8 +19,6 @@ goog.require('Blockly.blockRendering.InputRow'); goog.require('Blockly.blockRendering.InRowSpacer'); goog.require('Blockly.blockRendering.RenderInfo'); goog.require('Blockly.blockRendering.Types'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.geras.InlineInput'); goog.require('Blockly.geras.StatementInput'); goog.require('Blockly.inputTypes'); diff --git a/core/renderers/zelos/constants.js b/core/renderers/zelos/constants.js index bb039250a..2070197cf 100644 --- a/core/renderers/zelos/constants.js +++ b/core/renderers/zelos/constants.js @@ -15,8 +15,6 @@ goog.provide('Blockly.zelos.ConstantProvider'); goog.require('Blockly.blockRendering.ConstantProvider'); goog.require('Blockly.connectionTypes'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.utils.colour'); goog.require('Blockly.utils.dom'); goog.require('Blockly.utils.object'); diff --git a/core/renderers/zelos/info.js b/core/renderers/zelos/info.js index b7dc3d972..078031756 100644 --- a/core/renderers/zelos/info.js +++ b/core/renderers/zelos/info.js @@ -18,8 +18,6 @@ goog.require('Blockly.blockRendering.InRowSpacer'); goog.require('Blockly.blockRendering.Measurable'); goog.require('Blockly.blockRendering.RenderInfo'); goog.require('Blockly.blockRendering.Types'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.FieldImage'); goog.require('Blockly.FieldLabel'); goog.require('Blockly.FieldTextInput'); diff --git a/core/renderers/zelos/renderer.js b/core/renderers/zelos/renderer.js index d192fa178..3c5287bbb 100644 --- a/core/renderers/zelos/renderer.js +++ b/core/renderers/zelos/renderer.js @@ -15,8 +15,6 @@ goog.provide('Blockly.zelos.Renderer'); goog.require('Blockly.blockRendering'); goog.require('Blockly.blockRendering.Renderer'); goog.require('Blockly.connectionTypes'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.InsertionMarkerManager'); goog.require('Blockly.utils.object'); goog.require('Blockly.zelos.ConstantProvider'); 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/touch.js b/core/touch.js index b6668c398..7dc578663 100644 --- a/core/touch.js +++ b/core/touch.js @@ -16,8 +16,7 @@ */ goog.provide('Blockly.Touch'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); +goog.require('Blockly.internalConstants'); goog.require('Blockly.utils'); goog.require('Blockly.utils.global'); goog.require('Blockly.utils.string'); @@ -107,8 +106,7 @@ Blockly.longStart = function(e, gesture) { if (gesture) { gesture.handleRightClick(e); } - - }, Blockly.LONGPRESS); + }, Blockly.internalConstants.LONGPRESS); }; /** diff --git a/core/trashcan.js b/core/trashcan.js index 831a26ba4..619299b21 100644 --- a/core/trashcan.js +++ b/core/trashcan.js @@ -14,13 +14,12 @@ goog.provide('Blockly.Trashcan'); goog.require('Blockly.browserEvents'); goog.require('Blockly.ComponentManager'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.DeleteArea'); goog.require('Blockly.Events'); /** @suppress {extraRequire} */ goog.require('Blockly.Events.TrashcanOpen'); goog.require('Blockly.IAutoHideable'); +goog.require('Blockly.internalConstants'); goog.require('Blockly.IPositionable'); goog.require('Blockly.Options'); goog.require('Blockly.registry'); @@ -316,17 +315,18 @@ Blockly.Trashcan.prototype.createDom = function() { }, clip); var body = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.IMAGE, - { - 'width': Blockly.SPRITE.width, + Blockly.utils.Svg.IMAGE, { + 'width': Blockly.internalConstants.SPRITE.width, 'x': -this.SPRITE_LEFT_, - 'height': Blockly.SPRITE.height, + 'height': Blockly.internalConstants.SPRITE.height, 'y': -this.SPRITE_TOP_, 'clip-path': 'url(#blocklyTrashBodyClipPath' + rnd + ')' }, this.svgGroup_); - body.setAttributeNS(Blockly.utils.dom.XLINK_NS, 'xlink:href', - this.workspace_.options.pathToMedia + Blockly.SPRITE.url); + body.setAttributeNS( + Blockly.utils.dom.XLINK_NS, 'xlink:href', + this.workspace_.options.pathToMedia + + Blockly.internalConstants.SPRITE.url); clip = Blockly.utils.dom.createSvgElement( Blockly.utils.Svg.CLIPPATH, @@ -336,17 +336,18 @@ Blockly.Trashcan.prototype.createDom = function() { Blockly.utils.Svg.RECT, {'width': this.WIDTH_, 'height': this.LID_HEIGHT_}, clip); this.svgLid_ = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.IMAGE, - { - 'width': Blockly.SPRITE.width, + Blockly.utils.Svg.IMAGE, { + 'width': Blockly.internalConstants.SPRITE.width, 'x': -this.SPRITE_LEFT_, - 'height': Blockly.SPRITE.height, + 'height': Blockly.internalConstants.SPRITE.height, 'y': -this.SPRITE_TOP_, 'clip-path': 'url(#blocklyTrashLidClipPath' + rnd + ')' }, this.svgGroup_); - this.svgLid_.setAttributeNS(Blockly.utils.dom.XLINK_NS, 'xlink:href', - this.workspace_.options.pathToMedia + Blockly.SPRITE.url); + this.svgLid_.setAttributeNS( + Blockly.utils.dom.XLINK_NS, 'xlink:href', + this.workspace_.options.pathToMedia + + Blockly.internalConstants.SPRITE.url); // bindEventWithChecks_ quashes events too aggressively. See: // https://groups.google.com/forum/#!topic/blockly/QF4yB9Wx00s diff --git a/core/utils.js b/core/utils.js index 171e83422..8213d38d9 100644 --- a/core/utils.js +++ b/core/utils.js @@ -18,8 +18,7 @@ */ goog.provide('Blockly.utils'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); +goog.require('Blockly.internalConstants'); goog.require('Blockly.Msg'); goog.require('Blockly.utils.colour'); goog.require('Blockly.utils.Coordinate'); @@ -194,13 +193,13 @@ Blockly.utils.getScrollDeltaPixels = function(e) { }; case 0x01: // Line mode. return { - x: e.deltaX * Blockly.LINE_MODE_MULTIPLIER, - y: e.deltaY * Blockly.LINE_MODE_MULTIPLIER + x: e.deltaX * Blockly.internalConstants.LINE_MODE_MULTIPLIER, + y: e.deltaY * Blockly.internalConstants.LINE_MODE_MULTIPLIER }; case 0x02: // Page mode. return { - x: e.deltaX * Blockly.PAGE_MODE_MULTIPLIER, - y: e.deltaY * Blockly.PAGE_MODE_MULTIPLIER + x: e.deltaX * Blockly.internalConstants.PAGE_MODE_MULTIPLIER, + y: e.deltaY * Blockly.internalConstants.PAGE_MODE_MULTIPLIER }; } }; @@ -634,8 +633,9 @@ Blockly.utils.parseBlockColour = function(colour) { if (!isNaN(hue) && 0 <= hue && hue <= 360) { return { hue: hue, - hex: Blockly.utils.colour.hsvToHex(hue, Blockly.HSV_SATURATION, - Blockly.HSV_VALUE * 255) + hex: Blockly.utils.colour.hsvToHex( + hue, Blockly.internalConstants.HSV_SATURATION, + Blockly.internalConstants.HSV_VALUE * 255) }; } else { var hex = Blockly.utils.colour.parse(dereferenced); diff --git a/core/utils/colour.js b/core/utils/colour.js index b64b81eb5..29ba0187c 100644 --- a/core/utils/colour.js +++ b/core/utils/colour.js @@ -16,7 +16,8 @@ * @name Blockly.utils.colour * @namespace */ -goog.provide('Blockly.utils.colour'); +goog.module('Blockly.utils.colour'); +goog.module.declareLegacyNamespace(); /** @@ -30,9 +31,9 @@ goog.provide('Blockly.utils.colour'); * @return {?string} A string containing a hex representation of the colour, * or null if can't be parsed. */ -Blockly.utils.colour.parse = function(str) { +const parse = function(str) { str = String(str).toLowerCase().trim(); - var hex = Blockly.utils.colour.names[str]; + let hex = names[str]; if (hex) { // e.g. 'red' return hex; @@ -47,18 +48,19 @@ Blockly.utils.colour.parse = function(str) { // e.g. '#0f8' return ['#', hex[1], hex[1], hex[2], hex[2], hex[3], hex[3]].join(''); } - var rgb = str.match(/^(?:rgb)?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/); + const rgb = str.match(/^(?:rgb)?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/); if (rgb) { // e.g. 'rgb(0, 128, 255)' - var r = Number(rgb[1]); - var g = Number(rgb[2]); - var b = Number(rgb[3]); + const r = Number(rgb[1]); + const g = Number(rgb[2]); + const b = Number(rgb[3]); if (r >= 0 && r < 256 && g >= 0 && g < 256 && b >= 0 && b < 256) { - return Blockly.utils.colour.rgbToHex(r, g, b); + return rgbToHex(r, g, b); } } return null; }; +exports.parse = parse; /** * Converts a colour from RGB to hex representation. @@ -67,13 +69,14 @@ Blockly.utils.colour.parse = function(str) { * @param {number} b Amount of blue, int between 0 and 255. * @return {string} Hex representation of the colour. */ -Blockly.utils.colour.rgbToHex = function(r, g, b) { - var rgb = (r << 16) | (g << 8) | b; +const rgbToHex = function(r, g, b) { + const rgb = (r << 16) | (g << 8) | b; if (r < 0x10) { return '#' + (0x1000000 | rgb).toString(16).substr(1); } return '#' + rgb.toString(16); }; +exports.rgbToHex = rgbToHex; /** * Converts a colour to RGB. @@ -81,19 +84,20 @@ Blockly.utils.colour.rgbToHex = function(r, g, b) { * colour format ('#ff0000', 'red', '0xff000', etc). * @return {!Array} RGB representation of the colour. */ -Blockly.utils.colour.hexToRgb = function(colour) { - var hex = Blockly.utils.colour.parse(colour); +const hexToRgb = function(colour) { + const hex = parse(colour); if (!hex) { return [0, 0, 0]; } - var rgb = parseInt(hex.substr(1), 16); - var r = rgb >> 16; - var g = (rgb >> 8) & 255; - var b = rgb & 255; + const rgb = parseInt(hex.substr(1), 16); + const r = rgb >> 16; + const g = (rgb >> 8) & 255; + const b = rgb & 255; return [r, g, b]; }; +exports.hexToRgb = hexToRgb; /** * Converts an HSV triplet to hex representation. @@ -102,20 +106,20 @@ Blockly.utils.colour.hexToRgb = function(colour) { * @param {number} v Brightness in [0, 255]. * @return {string} Hex representation of the colour. */ -Blockly.utils.colour.hsvToHex = function(h, s, v) { - var red = 0; - var green = 0; - var blue = 0; +const hsvToHex = function(h, s, v) { + let red = 0; + let green = 0; + let blue = 0; if (s == 0) { red = v; green = v; blue = v; } else { - var sextant = Math.floor(h / 60); - var remainder = (h / 60) - sextant; - var val1 = v * (1 - s); - var val2 = v * (1 - (s * remainder)); - var val3 = v * (1 - (s * (1 - remainder))); + const sextant = Math.floor(h / 60); + const remainder = (h / 60) - sextant; + const val1 = v * (1 - s); + const val2 = v * (1 - (s * remainder)); + const val3 = v * (1 - (s * (1 - remainder))); switch (sextant) { case 1: red = val2; @@ -150,9 +154,9 @@ Blockly.utils.colour.hsvToHex = function(h, s, v) { break; } } - return Blockly.utils.colour.rgbToHex( - Math.floor(red), Math.floor(green), Math.floor(blue)); + return rgbToHex(Math.floor(red), Math.floor(green), Math.floor(blue)); }; +exports.hsvToHex = hsvToHex; /** * Blend two colours together, using the specified factor to indicate the @@ -163,22 +167,23 @@ Blockly.utils.colour.hsvToHex = function(h, s, v) { * Values should be in the range [0, 1]. * @return {?string} Combined colour represented in hex. */ -Blockly.utils.colour.blend = function(colour1, colour2, factor) { - var hex1 = Blockly.utils.colour.parse(colour1); +const blend = function(colour1, colour2, factor) { + const hex1 = parse(colour1); if (!hex1) { return null; } - var hex2 = Blockly.utils.colour.parse(colour2); + const hex2 = parse(colour2); if (!hex2) { return null; } - var rgb1 = Blockly.utils.colour.hexToRgb(hex1); - var rgb2 = Blockly.utils.colour.hexToRgb(hex2); - var r = Math.round(rgb2[0] + factor * (rgb1[0] - rgb2[0])); - var g = Math.round(rgb2[1] + factor * (rgb1[1] - rgb2[1])); - var b = Math.round(rgb2[2] + factor * (rgb1[2] - rgb2[2])); - return Blockly.utils.colour.rgbToHex(r, g, b); + const rgb1 = hexToRgb(hex1); + const rgb2 = hexToRgb(hex2); + const r = Math.round(rgb2[0] + factor * (rgb1[0] - rgb2[0])); + const g = Math.round(rgb2[1] + factor * (rgb1[1] - rgb2[1])); + const b = Math.round(rgb2[2] + factor * (rgb1[2] - rgb2[2])); + return rgbToHex(r, g, b); }; +exports.blend = blend; /** * A map that contains the 16 basic colour keywords as defined by W3C: @@ -188,7 +193,7 @@ Blockly.utils.colour.blend = function(colour1, colour2, factor) { * * @type {!Object} */ -Blockly.utils.colour.names = { +const names = { 'aqua': '#00ffff', 'black': '#000000', 'blue': '#0000ff', @@ -206,3 +211,4 @@ Blockly.utils.colour.names = { 'white': '#ffffff', 'yellow': '#ffff00' }; +exports.names = names; diff --git a/core/utils/coordinate.js b/core/utils/coordinate.js index edf513b28..ca5a248d3 100644 --- a/core/utils/coordinate.js +++ b/core/utils/coordinate.js @@ -16,8 +16,8 @@ * @name Blockly.utils.Coordinate * @namespace */ -goog.provide('Blockly.utils.Coordinate'); - +goog.module('Blockly.utils.Coordinate'); +goog.module.declareLegacyNamespace(); /** * Class for representing coordinates and positions. @@ -26,7 +26,7 @@ goog.provide('Blockly.utils.Coordinate'); * @struct * @constructor */ -Blockly.utils.Coordinate = function(x, y) { +const Coordinate = function(x, y) { /** * X-value * @type {number} @@ -42,11 +42,11 @@ Blockly.utils.Coordinate = function(x, y) { /** * Compares coordinates for equality. - * @param {?Blockly.utils.Coordinate} a A Coordinate. - * @param {?Blockly.utils.Coordinate} b A Coordinate. + * @param {?Coordinate} a A Coordinate. + * @param {?Coordinate} b A Coordinate. * @return {boolean} True iff the coordinates are equal, or if both are null. */ -Blockly.utils.Coordinate.equals = function(a, b) { +Coordinate.equals = function(a, b) { if (a == b) { return true; } @@ -58,62 +58,62 @@ Blockly.utils.Coordinate.equals = function(a, b) { /** * Returns the distance between two coordinates. - * @param {!Blockly.utils.Coordinate} a A Coordinate. - * @param {!Blockly.utils.Coordinate} b A Coordinate. + * @param {!Coordinate} a A Coordinate. + * @param {!Coordinate} b A Coordinate. * @return {number} The distance between `a` and `b`. */ -Blockly.utils.Coordinate.distance = function(a, b) { - var dx = a.x - b.x; - var dy = a.y - b.y; +Coordinate.distance = function(a, b) { + const dx = a.x - b.x; + const dy = a.y - b.y; return Math.sqrt(dx * dx + dy * dy); }; /** * Returns the magnitude of a coordinate. - * @param {!Blockly.utils.Coordinate} a A Coordinate. + * @param {!Coordinate} a A Coordinate. * @return {number} The distance between the origin and `a`. */ -Blockly.utils.Coordinate.magnitude = function(a) { +Coordinate.magnitude = function(a) { return Math.sqrt(a.x * a.x + a.y * a.y); }; /** * Returns the difference between two coordinates as a new - * Blockly.utils.Coordinate. - * @param {!Blockly.utils.Coordinate|!SVGPoint} a An x/y coordinate. - * @param {!Blockly.utils.Coordinate|!SVGPoint} b An x/y coordinate. - * @return {!Blockly.utils.Coordinate} A Coordinate representing the difference + * Coordinate. + * @param {!Coordinate|!SVGPoint} a An x/y coordinate. + * @param {!Coordinate|!SVGPoint} b An x/y coordinate. + * @return {!Coordinate} A Coordinate representing the difference * between `a` and `b`. */ -Blockly.utils.Coordinate.difference = function(a, b) { - return new Blockly.utils.Coordinate(a.x - b.x, a.y - b.y); +Coordinate.difference = function(a, b) { + return new Coordinate(a.x - b.x, a.y - b.y); }; /** - * Returns the sum of two coordinates as a new Blockly.utils.Coordinate. - * @param {!Blockly.utils.Coordinate|!SVGPoint} a An x/y coordinate. - * @param {!Blockly.utils.Coordinate|!SVGPoint} b An x/y coordinate. - * @return {!Blockly.utils.Coordinate} A Coordinate representing the sum of + * Returns the sum of two coordinates as a new Coordinate. + * @param {!Coordinate|!SVGPoint} a An x/y coordinate. + * @param {!Coordinate|!SVGPoint} b An x/y coordinate. + * @return {!Coordinate} A Coordinate representing the sum of * the two coordinates. */ -Blockly.utils.Coordinate.sum = function(a, b) { - return new Blockly.utils.Coordinate(a.x + b.x, a.y + b.y); +Coordinate.sum = function(a, b) { + return new Coordinate(a.x + b.x, a.y + b.y); }; /** * Creates a new copy of this coordinate. - * @return {!Blockly.utils.Coordinate} A copy of this coordinate. + * @return {!Coordinate} A copy of this coordinate. */ -Blockly.utils.Coordinate.prototype.clone = function() { - return new Blockly.utils.Coordinate(this.x, this.y); +Coordinate.prototype.clone = function() { + return new Coordinate(this.x, this.y); }; /** * Scales this coordinate by the given scale factor. * @param {number} s The scale factor to use for both x and y dimensions. - * @return {!Blockly.utils.Coordinate} This coordinate after scaling. + * @return {!Coordinate} This coordinate after scaling. */ -Blockly.utils.Coordinate.prototype.scale = function(s) { +Coordinate.prototype.scale = function(s) { this.x *= s; this.y *= s; return this; @@ -124,10 +124,12 @@ Blockly.utils.Coordinate.prototype.scale = function(s) { * respectively. * @param {number} tx The value to translate x by. * @param {number} ty The value to translate y by. - * @return {!Blockly.utils.Coordinate} This coordinate after translating. + * @return {!Coordinate} This coordinate after translating. */ -Blockly.utils.Coordinate.prototype.translate = function(tx, ty) { +Coordinate.prototype.translate = function(tx, ty) { this.x += tx; this.y += ty; return this; }; + +exports = Coordinate; diff --git a/core/utils/deprecation.js b/core/utils/deprecation.js index ad798b1ab..870294172 100644 --- a/core/utils/deprecation.js +++ b/core/utils/deprecation.js @@ -28,7 +28,6 @@ goog.module.declareLegacyNamespace(); * deprecation date. * @param {string=} opt_use The name of a function or property to use instead, * if any. - * @package */ const warn = function(name, deprecationDate, deletionDate, opt_use) { let msg = name + ' was deprecated on ' + deprecationDate + @@ -38,5 +37,5 @@ const warn = function(name, deprecationDate, deletionDate, opt_use) { } console.warn(msg); }; - -exports = {warn}; +/** @package */ +exports.warn = warn; diff --git a/core/utils/idgenerator.js b/core/utils/idgenerator.js index 6ad7bcf55..537dfde2b 100644 --- a/core/utils/idgenerator.js +++ b/core/utils/idgenerator.js @@ -23,7 +23,6 @@ goog.module.declareLegacyNamespace(); /** * Next unique ID to use. * @type {number} - * @private */ let nextId = 0; @@ -36,5 +35,4 @@ let nextId = 0; const getNextUniqueId = function() { return 'blockly-' + (nextId++).toString(36); }; - -exports = {getNextUniqueId}; +exports.getNextUniqueId = getNextUniqueId; diff --git a/core/utils/math.js b/core/utils/math.js index dade91c21..9b717d065 100644 --- a/core/utils/math.js +++ b/core/utils/math.js @@ -29,6 +29,7 @@ goog.module.declareLegacyNamespace(); const toRadians = function(angleDegrees) { return angleDegrees * Math.PI / 180; }; +exports.toRadians = toRadians; /** * Converts radians to degrees. @@ -39,6 +40,7 @@ const toRadians = function(angleDegrees) { const toDegrees = function(angleRadians) { return angleRadians * 180 / Math.PI; }; +exports.toDegrees = toDegrees; /** * Clamp the provided number between the lower bound and the upper bound. @@ -55,9 +57,4 @@ const clamp = function(lowerBound, number, upperBound) { } return Math.max(lowerBound, Math.min(number, upperBound)); }; - -exports = { - toRadians, - toDegrees, - clamp -}; +exports.clamp = clamp; diff --git a/core/utils/metrics.js b/core/utils/metrics.js index 226ef0734..55cadfae9 100644 --- a/core/utils/metrics.js +++ b/core/utils/metrics.js @@ -14,139 +14,142 @@ * @name Blockly.utils.Metrics * @namespace */ -goog.provide('Blockly.utils.Metrics'); +goog.module('Blockly.utils.Metrics'); +goog.module.declareLegacyNamespace(); /** * @record */ -Blockly.utils.Metrics = function() {}; +const Metrics = function() {}; /** * Height of the visible portion of the workspace. * @type {number} */ -Blockly.utils.Metrics.prototype.viewHeight; +Metrics.prototype.viewHeight; /** * Width of the visible portion of the workspace. * @type {number} */ -Blockly.utils.Metrics.prototype.viewWidth; +Metrics.prototype.viewWidth; /** * Height of the content. * @type {number} */ -Blockly.utils.Metrics.prototype.contentHeight; +Metrics.prototype.contentHeight; /** * Width of the content. * @type {number} */ -Blockly.utils.Metrics.prototype.contentWidth; +Metrics.prototype.contentWidth; /** * Height of the scroll area. * @type {number} */ -Blockly.utils.Metrics.prototype.scrollHeight; +Metrics.prototype.scrollHeight; /** * Width of the scroll area. * @type {number} */ -Blockly.utils.Metrics.prototype.scrollWidth; +Metrics.prototype.scrollWidth; /** * Top-edge of the visible portion of the workspace, relative to the workspace * origin. * @type {number} */ -Blockly.utils.Metrics.prototype.viewTop; +Metrics.prototype.viewTop; /** * Left-edge of the visible portion of the workspace, relative to the workspace * origin. * @type {number} */ -Blockly.utils.Metrics.prototype.viewLeft; +Metrics.prototype.viewLeft; /** * Top-edge of the content, relative to the workspace origin. * @type {number} */ -Blockly.utils.Metrics.prototype.contentTop; +Metrics.prototype.contentTop; /** * Left-edge of the content relative to the workspace origin. * @type {number} */ -Blockly.utils.Metrics.prototype.contentLeft; +Metrics.prototype.contentLeft; /** * Top-edge of the scroll area, relative to the workspace origin. * @type {number} */ -Blockly.utils.Metrics.prototype.scrollTop; +Metrics.prototype.scrollTop; /** * Left-edge of the scroll area relative to the workspace origin. * @type {number} */ -Blockly.utils.Metrics.prototype.scrollLeft; +Metrics.prototype.scrollLeft; /** * Top-edge of the visible portion of the workspace, relative to the blocklyDiv. * @type {number} */ -Blockly.utils.Metrics.prototype.absoluteTop; +Metrics.prototype.absoluteTop; /** * Left-edge of the visible portion of the workspace, relative to the * blocklyDiv. * @type {number} */ -Blockly.utils.Metrics.prototype.absoluteLeft; +Metrics.prototype.absoluteLeft; /** * Height of the Blockly div (the view + the toolbox, simple of otherwise). * @type {number} */ -Blockly.utils.Metrics.prototype.svgHeight; +Metrics.prototype.svgHeight; /** * Width of the Blockly div (the view + the toolbox, simple or otherwise). * @type {number} */ -Blockly.utils.Metrics.prototype.svgWidth; +Metrics.prototype.svgWidth; /** * Width of the toolbox, if it exists. Otherwise zero. * @type {number} */ -Blockly.utils.Metrics.prototype.toolboxWidth; +Metrics.prototype.toolboxWidth; /** * Height of the toolbox, if it exists. Otherwise zero. * @type {number} */ -Blockly.utils.Metrics.prototype.toolboxHeight; +Metrics.prototype.toolboxHeight; /** * Top, bottom, left or right. Use TOOLBOX_AT constants to compare. * @type {number} */ -Blockly.utils.Metrics.prototype.toolboxPosition; +Metrics.prototype.toolboxPosition; /** * Width of the flyout if it is always open. Otherwise zero. * @type {number} */ -Blockly.utils.Metrics.prototype.flyoutWidth; +Metrics.prototype.flyoutWidth; /** * Height of the flyout if it is always open. Otherwise zero. * @type {number} */ -Blockly.utils.Metrics.prototype.flyoutHeight; +Metrics.prototype.flyoutHeight; + +exports = Metrics; diff --git a/core/utils/object.js b/core/utils/object.js index dae55ec51..3507d33ab 100644 --- a/core/utils/object.js +++ b/core/utils/object.js @@ -40,6 +40,7 @@ const inherits = function(childCtor, parentCtor) { // Alternatively, one could use this instead: // Object.setPrototypeOf(childCtor.prototype, parentCtor.prototype); }; +exports.inherits = inherits; /** * Copies all the members of a source object to a target object. @@ -51,6 +52,7 @@ const mixin = function(target, source) { target[x] = source[x]; } }; +exports.mixin = mixin; /** * Complete a deep merge of all members of a source object with a target object. @@ -68,6 +70,7 @@ const deepMerge = function(target, source) { } return target; }; +exports.deepMerge = deepMerge; /** * Returns an array of a given object's own enumerable property values. @@ -83,10 +86,4 @@ const values = function(obj) { return obj[e]; }); }; - -exports = { - inherits, - mixin, - deepMerge, - values, -}; +exports.values = values; diff --git a/core/utils/rect.js b/core/utils/rect.js index 128ec4eae..85ade5388 100644 --- a/core/utils/rect.js +++ b/core/utils/rect.js @@ -16,7 +16,8 @@ * @name Blockly.utils.Rect * @namespace */ -goog.provide('Blockly.utils.Rect'); +goog.module('Blockly.utils.Rect'); +goog.module.declareLegacyNamespace(); /** @@ -28,7 +29,7 @@ goog.provide('Blockly.utils.Rect'); * @struct * @constructor */ -Blockly.utils.Rect = function(top, bottom, left, right) { +const Rect = function(top, bottom, left, right) { /** @type {number} */ this.top = top; @@ -49,7 +50,7 @@ Blockly.utils.Rect = function(top, bottom, left, right) { * @param {number} y The y coordinate to test for containment. * @return {boolean} Whether this rectangle contains given coordinate. */ -Blockly.utils.Rect.prototype.contains = function(x, y) { +Rect.prototype.contains = function(x, y) { return x >= this.left && x <= this.right && y >= this.top && y <= this.bottom; }; @@ -60,7 +61,10 @@ Blockly.utils.Rect.prototype.contains = function(x, y) { * intersection with. * @return {boolean} Whether this rectangle intersects the provided rectangle. */ -Blockly.utils.Rect.prototype.intersects = function(other) { - return !(this.left > other.right || this.right < other.left || +Rect.prototype.intersects = function(other) { + return !( + this.left > other.right || this.right < other.left || this.top > other.bottom || this.bottom < other.top); }; + +exports = Rect; 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/utils/style.js b/core/utils/style.js index 1c169453d..0fbd22093 100644 --- a/core/utils/style.js +++ b/core/utils/style.js @@ -16,53 +16,54 @@ * @name Blockly.utils.style * @namespace */ -goog.provide('Blockly.utils.style'); +goog.module('Blockly.utils.style'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.utils.Coordinate'); -goog.require('Blockly.utils.Size'); +const Coordinate = goog.require('Blockly.utils.Coordinate'); +const Size = goog.require('Blockly.utils.Size'); /** * Gets the height and width of an element. * Similar to Closure's goog.style.getSize * @param {!Element} element Element to get size of. - * @return {!Blockly.utils.Size} Object with width/height properties. + * @return {!Size} Object with width/height properties. */ -Blockly.utils.style.getSize = function(element) { - if (Blockly.utils.style.getStyle_(element, 'display') != 'none') { - return Blockly.utils.style.getSizeWithDisplay_(element); +const getSize = function(element) { + if (getStyle(element, 'display') != 'none') { + return getSizeWithDisplay(element); } // Evaluate size with a temporary element. - var style = element.style; - var originalDisplay = style.display; - var originalVisibility = style.visibility; - var originalPosition = style.position; + const style = element.style; + const originalDisplay = style.display; + const originalVisibility = style.visibility; + const originalPosition = style.position; style.visibility = 'hidden'; style.position = 'absolute'; style.display = 'inline'; - var offsetWidth = /** @type {!HTMLElement} */ (element).offsetWidth; - var offsetHeight = /** @type {!HTMLElement} */ (element).offsetHeight; + const offsetWidth = /** @type {!HTMLElement} */ (element).offsetWidth; + const offsetHeight = /** @type {!HTMLElement} */ (element).offsetHeight; style.display = originalDisplay; style.position = originalPosition; style.visibility = originalVisibility; - return new Blockly.utils.Size(offsetWidth, offsetHeight); + return new Size(offsetWidth, offsetHeight); }; +exports.getSize = getSize; /** * Gets the height and width of an element when the display is not none. * @param {!Element} element Element to get size of. - * @return {!Blockly.utils.Size} Object with width/height properties. - * @private + * @return {!Size} Object with width/height properties. */ -Blockly.utils.style.getSizeWithDisplay_ = function(element) { - var offsetWidth = /** @type {!HTMLElement} */ (element).offsetWidth; - var offsetHeight = /** @type {!HTMLElement} */ (element).offsetHeight; - return new Blockly.utils.Size(offsetWidth, offsetHeight); +const getSizeWithDisplay = function(element) { + const offsetWidth = /** @type {!HTMLElement} */ (element).offsetWidth; + const offsetHeight = /** @type {!HTMLElement} */ (element).offsetHeight; + return new Size(offsetWidth, offsetHeight); }; /** @@ -77,11 +78,9 @@ Blockly.utils.style.getSizeWithDisplay_ = function(element) { * @param {!Element} element Element to get style of. * @param {string} style Property to get (must be camelCase, not CSS-style). * @return {string} Style value. - * @private */ -Blockly.utils.style.getStyle_ = function(element, style) { - return Blockly.utils.style.getComputedStyle(element, style) || - Blockly.utils.style.getCascadedStyle(element, style) || +const getStyle = function(element, style) { + return getComputedStyle(element, style) || getCascadedStyle(element, style) || (element.style && element.style[style]); }; @@ -97,9 +96,9 @@ Blockly.utils.style.getStyle_ = function(element, style) { * @param {string} property Property to get (camel-case). * @return {string} Style value. */ -Blockly.utils.style.getComputedStyle = function(element, property) { +const getComputedStyle = function(element, property) { if (document.defaultView && document.defaultView.getComputedStyle) { - var styles = document.defaultView.getComputedStyle(element, null); + const styles = document.defaultView.getComputedStyle(element, null); if (styles) { // element.style[..] is undefined for browser specific styles // as 'filter'. @@ -109,6 +108,7 @@ Blockly.utils.style.getComputedStyle = function(element, property) { return ''; }; +exports.getComputedStyle = getComputedStyle; /** * Gets the cascaded style value of a node, or null if the value cannot be @@ -120,25 +120,26 @@ Blockly.utils.style.getComputedStyle = function(element, property) { * @param {string} style Property to get (camel-case). * @return {string} Style value. */ -Blockly.utils.style.getCascadedStyle = function(element, style) { +const getCascadedStyle = function(element, style) { return /** @type {string} */ ( element.currentStyle ? element.currentStyle[style] : null); }; +exports.getCascadedStyle = getCascadedStyle; /** * Returns a Coordinate object relative to the top-left of the HTML document. * Similar to Closure's goog.style.getPageOffset * @param {!Element} el Element to get the page offset for. - * @return {!Blockly.utils.Coordinate} The page offset. + * @return {!Coordinate} The page offset. */ -Blockly.utils.style.getPageOffset = function(el) { - var pos = new Blockly.utils.Coordinate(0, 0); - var box = el.getBoundingClientRect(); - var documentElement = document.documentElement; +const getPageOffset = function(el) { + const pos = new Coordinate(0, 0); + const box = el.getBoundingClientRect(); + const documentElement = document.documentElement; // Must add the scroll coordinates in to get the absolute page offset // of element since getBoundingClientRect returns relative coordinates to // the viewport. - var scrollCoord = new Blockly.utils.Coordinate( + const scrollCoord = new Coordinate( window.pageXOffset || documentElement.scrollLeft, window.pageYOffset || documentElement.scrollTop); pos.x = box.left + scrollCoord.x; @@ -146,19 +147,21 @@ Blockly.utils.style.getPageOffset = function(el) { return pos; }; +exports.getPageOffset = getPageOffset; /** * Calculates the viewport coordinates relative to the document. * Similar to Closure's goog.style.getViewportPageOffset - * @return {!Blockly.utils.Coordinate} The page offset of the viewport. + * @return {!Coordinate} The page offset of the viewport. */ -Blockly.utils.style.getViewportPageOffset = function() { - var body = document.body; - var documentElement = document.documentElement; - var scrollLeft = body.scrollLeft || documentElement.scrollLeft; - var scrollTop = body.scrollTop || documentElement.scrollTop; - return new Blockly.utils.Coordinate(scrollLeft, scrollTop); +const getViewportPageOffset = function() { + const body = document.body; + const documentElement = document.documentElement; + const scrollLeft = body.scrollLeft || documentElement.scrollLeft; + const scrollTop = body.scrollTop || documentElement.scrollTop; + return new Coordinate(scrollLeft, scrollTop); }; +exports.getViewportPageOffset = getViewportPageOffset; /** * Shows or hides an element from the page. Hiding the element is done by @@ -172,9 +175,10 @@ Blockly.utils.style.getViewportPageOffset = function() { * @param {*} isShown True to render the element in its default style, * false to disable rendering the element. */ -Blockly.utils.style.setElementShown = function(el, isShown) { +const setElementShown = function(el, isShown) { el.style.display = isShown ? '' : 'none'; }; +exports.setElementShown = setElementShown; /** * Returns true if the element is using right to left (RTL) direction. @@ -183,9 +187,10 @@ Blockly.utils.style.setElementShown = function(el, isShown) { * @param {!Element} el The element to test. * @return {boolean} True for right to left, false for left to right. */ -Blockly.utils.style.isRightToLeft = function(el) { - return 'rtl' == Blockly.utils.style.getStyle_(el, 'direction'); +const isRightToLeft = function(el) { + return 'rtl' == getStyle(el, 'direction'); }; +exports.isRightToLeft = isRightToLeft; /** * Gets the computed border widths (on all sides) in pixels @@ -193,11 +198,11 @@ Blockly.utils.style.isRightToLeft = function(el) { * @param {!Element} element The element to get the border widths for. * @return {!Object} The computed border widths. */ -Blockly.utils.style.getBorderBox = function(element) { - var left = Blockly.utils.style.getComputedStyle(element, 'borderLeftWidth'); - var right = Blockly.utils.style.getComputedStyle(element, 'borderRightWidth'); - var top = Blockly.utils.style.getComputedStyle(element, 'borderTopWidth'); - var bottom = Blockly.utils.style.getComputedStyle(element, 'borderBottomWidth'); +const getBorderBox = function(element) { + const left = getComputedStyle(element, 'borderLeftWidth'); + const right = getComputedStyle(element, 'borderRightWidth'); + const top = getComputedStyle(element, 'borderTopWidth'); + const bottom = getComputedStyle(element, 'borderBottomWidth'); return { top: parseFloat(top), @@ -206,6 +211,7 @@ Blockly.utils.style.getBorderBox = function(element) { left: parseFloat(left) }; }; +exports.getBorderBox = getBorderBox; /** * Changes the scroll position of `container` with the minimum amount so @@ -220,14 +226,12 @@ Blockly.utils.style.getBorderBox = function(element) { * @param {boolean=} opt_center Whether to center the element in the container. * Defaults to false. */ -Blockly.utils.style.scrollIntoContainerView = function( - element, container, opt_center) { - var offset = - Blockly.utils.style.getContainerOffsetToScrollInto(element, - container, opt_center); +const scrollIntoContainerView = function(element, container, opt_center) { + const offset = getContainerOffsetToScrollInto(element, container, opt_center); container.scrollLeft = offset.x; container.scrollTop = offset.y; }; +exports.scrollIntoContainerView = scrollIntoContainerView; /** * Calculate the scroll position of `container` with the minimum amount so @@ -241,27 +245,26 @@ Blockly.utils.style.scrollIntoContainerView = function( * document scroll element will be used. * @param {boolean=} opt_center Whether to center the element in the container. * Defaults to false. - * @return {!Blockly.utils.Coordinate} The new scroll position of the container, + * @return {!Coordinate} The new scroll position of the container, * in form of goog.math.Coordinate(scrollLeft, scrollTop). */ -Blockly.utils.style.getContainerOffsetToScrollInto = function( - element, container, opt_center) { +const getContainerOffsetToScrollInto = function(element, container, opt_center) { // Absolute position of the element's border's top left corner. - var elementPos = Blockly.utils.style.getPageOffset(element); + const elementPos = getPageOffset(element); // Absolute position of the container's border's top left corner. - var containerPos = Blockly.utils.style.getPageOffset(container); - var containerBorder = Blockly.utils.style.getBorderBox(container); + const containerPos = getPageOffset(container); + const containerBorder = getBorderBox(container); // Relative pos. of the element's border box to the container's content box. - var relX = elementPos.x - containerPos.x - containerBorder.left; - var relY = elementPos.y - containerPos.y - containerBorder.top; + const relX = elementPos.x - containerPos.x - containerBorder.left; + const relY = elementPos.y - containerPos.y - containerBorder.top; // How much the element can move in the container, i.e. the difference between // the element's bottom-right-most and top-left-most position where it's // fully visible. - var elementSize = Blockly.utils.style.getSizeWithDisplay_(element); - var spaceX = container.clientWidth - elementSize.width; - var spaceY = container.clientHeight - elementSize.height; - var scrollLeft = container.scrollLeft; - var scrollTop = container.scrollTop; + const elementSize = getSizeWithDisplay(element); + const spaceX = container.clientWidth - elementSize.width; + const spaceY = container.clientHeight - elementSize.height; + let scrollLeft = container.scrollLeft; + let scrollTop = container.scrollTop; if (opt_center) { // All browsers round non-integer scroll positions down. scrollLeft += relX - spaceX / 2; @@ -277,5 +280,6 @@ Blockly.utils.style.getContainerOffsetToScrollInto = function( scrollLeft += Math.min(relX, Math.max(relX - spaceX, 0)); scrollTop += Math.min(relY, Math.max(relY - spaceY, 0)); } - return new Blockly.utils.Coordinate(scrollLeft, scrollTop); + return new Coordinate(scrollLeft, scrollTop); }; +exports.getContainerOffsetToScrollInto = getContainerOffsetToScrollInto; diff --git a/core/utils/svg_paths.js b/core/utils/svg_paths.js index e123dca28..7286e8bc6 100644 --- a/core/utils/svg_paths.js +++ b/core/utils/svg_paths.js @@ -15,7 +15,8 @@ * @name Blockly.utils.svgPaths * @namespace */ -goog.provide('Blockly.utils.svgPaths'); +goog.module('Blockly.utils.svgPaths'); +goog.module.declareLegacyNamespace(); /** @@ -26,11 +27,11 @@ goog.provide('Blockly.utils.svgPaths'); * @param {number} x The x coordinate. * @param {number} y The y coordinate. * @return {string} A string of the format ' x,y ' - * @public */ -Blockly.utils.svgPaths.point = function(x, y) { +const point = function(x, y) { return ' ' + x + ',' + y + ' '; }; +exports.point = point; /** * Draw a cubic or quadratic curve. See @@ -38,16 +39,16 @@ Blockly.utils.svgPaths.point = function(x, y) { * These coordinates are unitless and hence in the user coordinate system. * @param {string} command The command to use. * Should be one of: c, C, s, S, q, Q. - * @param {!Array} points An array containing all of the points to pass to the - * curve command, in order. The points are represented as strings of the - * format ' x, y '. + * @param {!Array} points An array containing all of the points to pass + * to the curve command, in order. The points are represented as strings of + * the format ' x, y '. * @return {string} A string defining one or more Bezier curves. See the MDN * documentation for exact format. - * @public */ -Blockly.utils.svgPaths.curve = function(command, points) { +const curve = function(command, points) { return ' ' + command + points.join(''); }; +exports.curve = curve; /** * Move the cursor to the given position without drawing a line. @@ -57,11 +58,11 @@ Blockly.utils.svgPaths.curve = function(command, points) { * @param {number} x The absolute x coordinate. * @param {number} y The absolute y coordinate. * @return {string} A string of the format ' M x,y ' - * @public */ -Blockly.utils.svgPaths.moveTo = function(x, y) { +const moveTo = function(x, y) { return ' M ' + x + ',' + y + ' '; }; +exports.moveTo = moveTo; /** * Move the cursor to the given position without drawing a line. @@ -71,11 +72,11 @@ Blockly.utils.svgPaths.moveTo = function(x, y) { * @param {number} dx The relative x coordinate. * @param {number} dy The relative y coordinate. * @return {string} A string of the format ' m dx,dy ' - * @public */ -Blockly.utils.svgPaths.moveBy = function(dx, dy) { +const moveBy = function(dx, dy) { return ' m ' + dx + ',' + dy + ' '; }; +exports.moveBy = moveBy; /** * Draw a line from the current point to the end point, which is the current @@ -85,11 +86,11 @@ Blockly.utils.svgPaths.moveBy = function(dx, dy) { * @param {number} dx The relative x coordinate. * @param {number} dy The relative y coordinate. * @return {string} A string of the format ' l dx,dy ' - * @public */ -Blockly.utils.svgPaths.lineTo = function(dx, dy) { +const lineTo = function(dx, dy) { return ' l ' + dx + ',' + dy + ' '; }; +exports.lineTo = lineTo; /** * Draw multiple lines connecting all of the given points in order. This is @@ -100,11 +101,11 @@ Blockly.utils.svgPaths.lineTo = function(dx, dy) { * draw lines to, in order. The points are represented as strings of the * format ' dx,dy '. * @return {string} A string of the format ' l (dx,dy)+ ' - * @public */ -Blockly.utils.svgPaths.line = function(points) { +const line = function(points) { return ' l' + points.join(''); }; +exports.line = line; /** * Draw a horizontal or vertical line. @@ -117,11 +118,11 @@ Blockly.utils.svgPaths.line = function(points) { * @param {number} val The coordinate to pass to the command. It may be * absolute or relative. * @return {string} A string of the format ' command val ' - * @public */ -Blockly.utils.svgPaths.lineOnAxis = function(command, val) { +const lineOnAxis = function(command, val) { return ' ' + command + ' ' + val + ' '; }; +exports.lineOnAxis = lineOnAxis; /** * Draw an elliptical arc curve. @@ -135,8 +136,8 @@ Blockly.utils.svgPaths.lineOnAxis = function(command, val) { * specified either in absolute or relative coordinates depending on the * command. * @return {string} A string of the format 'command radius radius flags point' - * @public */ -Blockly.utils.svgPaths.arc = function(command, flags, radius, point) { +const arc = function(command, flags, radius, point) { return command + ' ' + radius + ' ' + radius + ' ' + flags + point; }; +exports.arc = arc; diff --git a/core/utils/toolbox.js b/core/utils/toolbox.js index e9a9d2b2a..6dabc1fd5 100644 --- a/core/utils/toolbox.js +++ b/core/utils/toolbox.js @@ -14,15 +14,15 @@ * @name Blockly.utils.toolbox * @namespace */ -goog.provide('Blockly.utils.toolbox'); - -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); -goog.require('Blockly.Xml'); - -goog.requireType('Blockly.ToolboxCategory'); -goog.requireType('Blockly.ToolboxSeparator'); +goog.module('Blockly.utils.toolbox'); +goog.module.declareLegacyNamespace(); +const userAgent = goog.require('Blockly.utils.userAgent'); +/* eslint-disable-next-line no-unused-vars */ +const {CssConfig: CategoryCssConfig} = goog.requireType('Blockly.ToolboxCategory'); +/* eslint-disable-next-line no-unused-vars */ +const {CssConfig: SeparatorCssConfig} = goog.requireType('Blockly.ToolboxSeparator'); +const {textToDom} = goog.require('Blockly.Xml'); /** * The information needed to create a block in the toolbox. @@ -34,7 +34,8 @@ goog.requireType('Blockly.ToolboxSeparator'); * disabled: (string|boolean|undefined) * }} */ -Blockly.utils.toolbox.BlockInfo; +let BlockInfo; +exports.BlockInfo = BlockInfo; /** * The information needed to create a separator in the toolbox. @@ -42,10 +43,11 @@ Blockly.utils.toolbox.BlockInfo; * kind:string, * id:(string|undefined), * gap:(number|undefined), - * cssconfig:(!Blockly.ToolboxSeparator.CssConfig|undefined) + * cssconfig:(!SeparatorCssConfig|undefined) * }} */ -Blockly.utils.toolbox.SeparatorInfo; +let SeparatorInfo; +exports.SeparatorInfo = SeparatorInfo; /** * The information needed to create a button in the toolbox. @@ -55,7 +57,8 @@ Blockly.utils.toolbox.SeparatorInfo; * callbackkey:string * }} */ -Blockly.utils.toolbox.ButtonInfo; +let ButtonInfo; +exports.ButtonInfo = ButtonInfo; /** * The information needed to create a label in the toolbox. @@ -65,29 +68,32 @@ Blockly.utils.toolbox.ButtonInfo; * id:(string|undefined) * }} */ -Blockly.utils.toolbox.LabelInfo; +let LabelInfo; +exports.LabelInfo = LabelInfo; /** * The information needed to create either a button or a label in the flyout. - * @typedef {Blockly.utils.toolbox.ButtonInfo| - * Blockly.utils.toolbox.LabelInfo} + * @typedef {ButtonInfo| + * LabelInfo} */ -Blockly.utils.toolbox.ButtonOrLabelInfo; +let ButtonOrLabelInfo; +exports.ButtonOrLabelInfo = ButtonOrLabelInfo; /** * The information needed to create a category in the toolbox. * @typedef {{ * kind:string, * name:string, - * contents:!Array, + * contents:!Array, * id:(string|undefined), * categorystyle:(string|undefined), * colour:(string|undefined), - * cssconfig:(!Blockly.ToolboxCategory.CssConfig|undefined), + * cssconfig:(!CategoryCssConfig|undefined), * hidden:(string|undefined) * }} */ -Blockly.utils.toolbox.StaticCategoryInfo; +let StaticCategoryInfo; +exports.StaticCategoryInfo = StaticCategoryInfo; /** * The information needed to create a custom category. @@ -97,69 +103,77 @@ Blockly.utils.toolbox.StaticCategoryInfo; * id:(string|undefined), * categorystyle:(string|undefined), * colour:(string|undefined), - * cssconfig:(!Blockly.ToolboxCategory.CssConfig|undefined), + * cssconfig:(!CategoryCssConfig|undefined), * hidden:(string|undefined) * }} */ -Blockly.utils.toolbox.DynamicCategoryInfo; +let DynamicCategoryInfo; +exports.DynamicCategoryInfo = DynamicCategoryInfo; /** * The information needed to create either a dynamic or static category. - * @typedef {Blockly.utils.toolbox.StaticCategoryInfo| - * Blockly.utils.toolbox.DynamicCategoryInfo} + * @typedef {StaticCategoryInfo| + * DynamicCategoryInfo} */ -Blockly.utils.toolbox.CategoryInfo; +let CategoryInfo; +exports.CategoryInfo = CategoryInfo; /** * Any information that can be used to create an item in the toolbox. - * @typedef {Blockly.utils.toolbox.FlyoutItemInfo| - * Blockly.utils.toolbox.StaticCategoryInfo} + * @typedef {FlyoutItemInfo| + * StaticCategoryInfo} */ -Blockly.utils.toolbox.ToolboxItemInfo; +let ToolboxItemInfo; +exports.ToolboxItemInfo = ToolboxItemInfo; /** * All the different types that can be displayed in a flyout. - * @typedef {Blockly.utils.toolbox.BlockInfo| - * Blockly.utils.toolbox.SeparatorInfo| - * Blockly.utils.toolbox.ButtonInfo| - * Blockly.utils.toolbox.LabelInfo| - * Blockly.utils.toolbox.DynamicCategoryInfo} + * @typedef {BlockInfo| + * SeparatorInfo| + * ButtonInfo| + * LabelInfo| + * DynamicCategoryInfo} */ -Blockly.utils.toolbox.FlyoutItemInfo; +let FlyoutItemInfo; +exports.FlyoutItemInfo = FlyoutItemInfo; /** * The JSON definition of a toolbox. * @typedef {{ * kind:(string|undefined), - * contents:!Array + * contents:!Array * }} */ -Blockly.utils.toolbox.ToolboxInfo; +let ToolboxInfo; +exports.ToolboxInfo = ToolboxInfo; /** * An array holding flyout items. * @typedef { - * Array + * Array * } */ -Blockly.utils.toolbox.FlyoutItemInfoArray; +let FlyoutItemInfoArray; +exports.FlyoutItemInfoArray = FlyoutItemInfoArray; /** * All of the different types that can create a toolbox. * @typedef {Node| - * Blockly.utils.toolbox.ToolboxInfo| + * ToolboxInfo| * string} */ -Blockly.utils.toolbox.ToolboxDefinition; +let ToolboxDefinition; +exports.ToolboxDefinition = ToolboxDefinition; /** * All of the different types that can be used to show items in a flyout. - * @typedef {Blockly.utils.toolbox.FlyoutItemInfoArray| + * @typedef {FlyoutItemInfoArray| * NodeList| - * Blockly.utils.toolbox.ToolboxInfo| + * ToolboxInfo| * Array} */ -Blockly.utils.toolbox.FlyoutDefinition; +let FlyoutDefinition; +exports.FlyoutDefinition = FlyoutDefinition; /** * The name used to identify a toolbox that has category like items. @@ -168,67 +182,68 @@ Blockly.utils.toolbox.FlyoutDefinition; * 'category'. * @const {string} */ -Blockly.utils.toolbox.CATEGORY_TOOLBOX_KIND = 'categoryToolbox'; +const CATEGORY_TOOLBOX_KIND = 'categoryToolbox'; /** * The name used to identify a toolbox that has no categories and is displayed * as a simple flyout displaying blocks, buttons, or labels. * @const {string} */ -Blockly.utils.toolbox.FLYOUT_TOOLBOX_KIND = 'flyoutToolbox'; +const FLYOUT_TOOLBOX_KIND = 'flyoutToolbox'; /** * Position of the toolbox and/or flyout relative to the workspace. * @enum {number} */ -Blockly.utils.toolbox.Position = { +const Position = { TOP: 0, BOTTOM: 1, LEFT: 2, RIGHT: 3 }; +exports.Position = Position; /** * Converts the toolbox definition into toolbox JSON. - * @param {?Blockly.utils.toolbox.ToolboxDefinition} toolboxDef The definition + * @param {?ToolboxDefinition} toolboxDef The definition * of the toolbox in one of its many forms. - * @return {?Blockly.utils.toolbox.ToolboxInfo} Object holding information + * @return {?ToolboxInfo} Object holding information * for creating a toolbox. - * @package */ -Blockly.utils.toolbox.convertToolboxDefToJson = function(toolboxDef) { +const convertToolboxDefToJson = function(toolboxDef) { if (!toolboxDef) { return null; } if (toolboxDef instanceof Element || typeof toolboxDef == 'string') { - toolboxDef = Blockly.utils.toolbox.parseToolboxTree(toolboxDef); - toolboxDef = Blockly.utils.toolbox.convertToToolboxJson_(toolboxDef); + toolboxDef = parseToolboxTree(toolboxDef); + toolboxDef = convertToToolboxJson(toolboxDef); } - var toolboxJson = /** @type {Blockly.utils.toolbox.ToolboxInfo} */ (toolboxDef); - Blockly.utils.toolbox.validateToolbox_(toolboxJson); + const toolboxJson = /** @type {ToolboxInfo} */ (toolboxDef); + validateToolbox(toolboxJson); return toolboxJson; }; +/** @package */ +exports.convertToolboxDefToJson = convertToolboxDefToJson; /** * Validates the toolbox JSON fields have been set correctly. - * @param {!Blockly.utils.toolbox.ToolboxInfo} toolboxJson Object holding + * @param {!ToolboxInfo} toolboxJson Object holding * information for creating a toolbox. * @throws {Error} if the toolbox is not the correct format. - * @private */ -Blockly.utils.toolbox.validateToolbox_ = function(toolboxJson) { - var toolboxKind = toolboxJson['kind']; - var toolboxContents = toolboxJson['contents']; +const validateToolbox = function(toolboxJson) { + const toolboxKind = toolboxJson['kind']; + const toolboxContents = toolboxJson['contents']; if (toolboxKind) { - if (toolboxKind != Blockly.utils.toolbox.FLYOUT_TOOLBOX_KIND && - toolboxKind != Blockly.utils.toolbox.CATEGORY_TOOLBOX_KIND) { - throw Error('Invalid toolbox kind ' + toolboxKind + '.' + - ' Please supply either ' + - Blockly.utils.toolbox.FLYOUT_TOOLBOX_KIND + ' or ' + - Blockly.utils.toolbox.CATEGORY_TOOLBOX_KIND); + if (toolboxKind != FLYOUT_TOOLBOX_KIND && + toolboxKind != CATEGORY_TOOLBOX_KIND) { + throw Error( + 'Invalid toolbox kind ' + toolboxKind + '.' + + ' Please supply either ' + FLYOUT_TOOLBOX_KIND + ' or ' + + CATEGORY_TOOLBOX_KIND); } } if (!toolboxContents) { @@ -238,12 +253,11 @@ Blockly.utils.toolbox.validateToolbox_ = function(toolboxJson) { /** * Converts the flyout definition into a list of flyout items. - * @param {?Blockly.utils.toolbox.FlyoutDefinition} flyoutDef The definition of + * @param {?FlyoutDefinition} flyoutDef The definition of * the flyout in one of its many forms. - * @return {!Blockly.utils.toolbox.FlyoutItemInfoArray} A list of flyout items. - * @package + * @return {!FlyoutItemInfoArray} A list of flyout items. */ -Blockly.utils.toolbox.convertFlyoutDefToJsonArray = function(flyoutDef) { +const convertFlyoutDefToJsonArray = function(flyoutDef) { if (!flyoutDef) { return []; } @@ -258,64 +272,67 @@ Blockly.utils.toolbox.convertFlyoutDefToJsonArray = function(flyoutDef) { return flyoutDef; } - return Blockly.utils.toolbox.xmlToJsonArray_( - /** @type {!Array|!NodeList} */ (flyoutDef)); + return xmlToJsonArray(/** @type {!Array|!NodeList} */ (flyoutDef)); }; +/** @package */ +exports.convertFlyoutDefToJsonArray = convertFlyoutDefToJsonArray; /** * Whether or not the toolbox definition has categories. - * @param {?Blockly.utils.toolbox.ToolboxInfo} toolboxJson Object holding + * @param {?ToolboxInfo} toolboxJson Object holding * information for creating a toolbox. * @return {boolean} True if the toolbox has categories. - * @package */ -Blockly.utils.toolbox.hasCategories = function(toolboxJson) { +const hasCategories = function(toolboxJson) { if (!toolboxJson) { return false; } - var toolboxKind = toolboxJson['kind']; + const toolboxKind = toolboxJson['kind']; if (toolboxKind) { - return toolboxKind == Blockly.utils.toolbox.CATEGORY_TOOLBOX_KIND; + return toolboxKind == CATEGORY_TOOLBOX_KIND; } - var categories = toolboxJson['contents'].filter(function(item) { + const categories = toolboxJson['contents'].filter(function(item) { return item['kind'].toUpperCase() == 'CATEGORY'; }); return !!categories.length; }; +/** @package */ +exports.hasCategories = hasCategories; /** * Whether or not the category is collapsible. - * @param {!Blockly.utils.toolbox.CategoryInfo} categoryInfo Object holing + * @param {!CategoryInfo} categoryInfo Object holing * information for creating a category. * @return {boolean} True if the category has subcategories. - * @package */ -Blockly.utils.toolbox.isCategoryCollapsible = function(categoryInfo) { +const isCategoryCollapsible = function(categoryInfo) { if (!categoryInfo || !categoryInfo['contents']) { return false; } - var categories = categoryInfo['contents'].filter(function(item) { + const categories = categoryInfo['contents'].filter(function(item) { return item['kind'].toUpperCase() == 'CATEGORY'; }); return !!categories.length; }; +/** @package */ +exports.isCategoryCollapsible = isCategoryCollapsible; /** * Parses the provided toolbox definition into a consistent format. - * @param {Node} toolboxDef The definition of the toolbox in one of its many forms. - * @return {!Blockly.utils.toolbox.ToolboxInfo} Object holding information + * @param {Node} toolboxDef The definition of the toolbox in one of its many + * forms. + * @return {!ToolboxInfo} Object holding information * for creating a toolbox. - * @private */ -Blockly.utils.toolbox.convertToToolboxJson_ = function(toolboxDef) { - var contents = Blockly.utils.toolbox.xmlToJsonArray_( +const convertToToolboxJson = function(toolboxDef) { + const contents = xmlToJsonArray( /** @type {!Node|!Array} */ (toolboxDef)); - var toolboxJson = {'contents': contents}; + const toolboxJson = {'contents': contents}; if (toolboxDef instanceof Node) { - Blockly.utils.toolbox.addAttributes_(toolboxDef, toolboxJson); + addAttributes(toolboxDef, toolboxJson); } return toolboxJson; }; @@ -324,25 +341,24 @@ Blockly.utils.toolbox.convertToToolboxJson_ = function(toolboxDef) { * Converts the xml for a toolbox to JSON. * @param {!Node|!Array|!NodeList} toolboxDef The * definition of the toolbox in one of its many forms. - * @return {!Blockly.utils.toolbox.FlyoutItemInfoArray| - * !Array} A list of objects in + * @return {!FlyoutItemInfoArray| + * !Array} A list of objects in * the toolbox. - * @private */ -Blockly.utils.toolbox.xmlToJsonArray_ = function(toolboxDef) { - var arr = []; +const xmlToJsonArray = function(toolboxDef) { + const arr = []; // If it is a node it will have children. - var childNodes = toolboxDef.childNodes; + let childNodes = toolboxDef.childNodes; if (!childNodes) { // Otherwise the toolboxDef is an array or collection. childNodes = toolboxDef; } - for (var i = 0, child; (child = childNodes[i]); i++) { + for (let i = 0, child; (child = childNodes[i]); i++) { if (!child.tagName) { continue; } - var obj = {}; - var tagName = child.tagName.toUpperCase(); + const obj = {}; + const tagName = child.tagName.toUpperCase(); obj['kind'] = tagName; // Store the XML for a block. @@ -350,11 +366,11 @@ Blockly.utils.toolbox.xmlToJsonArray_ = function(toolboxDef) { obj['blockxml'] = child; } else if (child.childNodes && child.childNodes.length > 0) { // Get the contents of a category - obj['contents'] = Blockly.utils.toolbox.xmlToJsonArray_(child); + obj['contents'] = xmlToJsonArray(child); } // Add XML attributes to object - Blockly.utils.toolbox.addAttributes_(child, obj); + addAttributes(child, obj); arr.push(obj); } return arr; @@ -364,11 +380,10 @@ Blockly.utils.toolbox.xmlToJsonArray_ = function(toolboxDef) { * Adds the attributes on the node to the given object. * @param {!Node} node The node to copy the attributes from. * @param {!Object} obj The object to copy the attributes to. - * @private */ -Blockly.utils.toolbox.addAttributes_ = function(node, obj) { - for (var j = 0; j < node.attributes.length; j++) { - var attr = node.attributes[j]; +const addAttributes = function(node, obj) { + for (let j = 0; j < node.attributes.length; j++) { + const attr = node.attributes[j]; if (attr.nodeName.indexOf('css-') > -1) { obj['cssconfig'] = obj['cssconfig'] || {}; obj['cssconfig'][attr.nodeName.replace('css-', '')] = attr.value; @@ -384,10 +399,10 @@ Blockly.utils.toolbox.addAttributes_ = function(node, obj) { * of same. * @return {?Node} DOM tree of blocks, or null. */ -Blockly.utils.toolbox.parseToolboxTree = function(toolboxDef) { +const parseToolboxTree = function(toolboxDef) { if (toolboxDef) { if (typeof toolboxDef != 'string') { - if (Blockly.utils.userAgent.IE && toolboxDef.outerHTML) { + if (userAgent.IE && toolboxDef.outerHTML) { // In this case the tree will not have been properly built by the // browser. The HTML will be contained in the element, but it will // not have the proper DOM structure since the browser doesn't support @@ -398,7 +413,7 @@ Blockly.utils.toolbox.parseToolboxTree = function(toolboxDef) { } } if (typeof toolboxDef == 'string') { - toolboxDef = Blockly.Xml.textToDom(toolboxDef); + toolboxDef = textToDom(toolboxDef); if (toolboxDef.nodeName.toLowerCase() != 'xml') { throw TypeError('Toolbox should be an document.'); } @@ -408,3 +423,4 @@ Blockly.utils.toolbox.parseToolboxTree = function(toolboxDef) { } return toolboxDef; }; +exports.parseToolboxTree = parseToolboxTree; diff --git a/core/variables.js b/core/variables.js index 1c091898e..223838a2b 100644 --- a/core/variables.js +++ b/core/variables.js @@ -17,8 +17,7 @@ goog.provide('Blockly.Variables'); goog.require('Blockly.Blocks'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); +goog.require('Blockly.internalConstants'); goog.require('Blockly.Msg'); goog.require('Blockly.utils'); goog.require('Blockly.utils.xml'); @@ -31,9 +30,9 @@ goog.requireType('Blockly.Workspace'); /** * Constant to separate variable names from procedures and generated functions * when running generators. - * @deprecated Use Blockly.VARIABLE_CATEGORY_NAME + * @deprecated Use Blockly.internalConstants.VARIABLE_CATEGORY_NAME */ -Blockly.Variables.NAME_TYPE = Blockly.VARIABLE_CATEGORY_NAME; +Blockly.Variables.NAME_TYPE = Blockly.internalConstants.VARIABLE_CATEGORY_NAME; /** * Find all user-created variables that are in use in the workspace. diff --git a/core/workspace_audio.js b/core/workspace_audio.js index 954b8f892..378c19287 100644 --- a/core/workspace_audio.js +++ b/core/workspace_audio.js @@ -13,8 +13,7 @@ goog.provide('Blockly.WorkspaceAudio'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); +goog.require('Blockly.internalConstants'); goog.require('Blockly.utils'); goog.require('Blockly.utils.global'); goog.require('Blockly.utils.userAgent'); @@ -135,7 +134,7 @@ Blockly.WorkspaceAudio.prototype.play = function(name, opt_volume) { // Don't play one sound on top of another. var now = new Date; if (this.lastSound_ != null && - now - this.lastSound_ < Blockly.SOUND_LIMIT) { + now - this.lastSound_ < Blockly.internalConstants.SOUND_LIMIT) { return; } this.lastSound_ = now; diff --git a/core/workspace_svg.js b/core/workspace_svg.js index 21ee217ae..1c3cee44f 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -17,8 +17,6 @@ goog.require('Blockly.BlockSvg'); goog.require('Blockly.browserEvents'); goog.require('Blockly.ComponentManager'); goog.require('Blockly.ConnectionDB'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.ContextMenu'); goog.require('Blockly.ContextMenuRegistry'); goog.require('Blockly.Events'); @@ -31,6 +29,7 @@ goog.require('Blockly.Events.ViewportChange'); goog.require('Blockly.Gesture'); goog.require('Blockly.Grid'); goog.require('Blockly.IASTNodeLocationSvg'); +goog.require('Blockly.internalConstants'); goog.require('Blockly.MarkerManager'); /** @suppress {extraRequire} */ goog.require('Blockly.MetricsManager'); @@ -181,15 +180,18 @@ Blockly.WorkspaceSvg = function( this.flyoutButtonCallbacks_ = Object.create(null); if (Blockly.Variables && Blockly.Variables.flyoutCategory) { - this.registerToolboxCategoryCallback(Blockly.VARIABLE_CATEGORY_NAME, + this.registerToolboxCategoryCallback( + Blockly.internalConstants.VARIABLE_CATEGORY_NAME, Blockly.Variables.flyoutCategory); } if (Blockly.VariablesDynamic && Blockly.VariablesDynamic.flyoutCategory) { - this.registerToolboxCategoryCallback(Blockly.VARIABLE_DYNAMIC_CATEGORY_NAME, + this.registerToolboxCategoryCallback( + Blockly.internalConstants.VARIABLE_DYNAMIC_CATEGORY_NAME, Blockly.VariablesDynamic.flyoutCategory); } if (Blockly.Procedures && Blockly.Procedures.flyoutCategory) { - this.registerToolboxCategoryCallback(Blockly.PROCEDURE_CATEGORY_NAME, + this.registerToolboxCategoryCallback( + Blockly.internalConstants.PROCEDURE_CATEGORY_NAME, Blockly.Procedures.flyoutCategory); this.addChangeListener(Blockly.Procedures.mutatorOpenListener); } @@ -1521,7 +1523,8 @@ Blockly.WorkspaceSvg.prototype.pasteBlock_ = function(xmlBlock) { // Check for blocks in snap range to any of its connections. var connections = block.getConnections_(false); for (var i = 0, connection; (connection = connections[i]); i++) { - var neighbour = connection.closest(Blockly.SNAP_RADIUS, + var neighbour = connection.closest( + Blockly.internalConstants.SNAP_RADIUS, new Blockly.utils.Coordinate(blockX, blockY)); if (neighbour.connection) { collide = true; @@ -1531,11 +1534,11 @@ Blockly.WorkspaceSvg.prototype.pasteBlock_ = function(xmlBlock) { } if (collide) { if (this.RTL) { - blockX -= Blockly.SNAP_RADIUS; + blockX -= Blockly.internalConstants.SNAP_RADIUS; } else { - blockX += Blockly.SNAP_RADIUS; + blockX += Blockly.internalConstants.SNAP_RADIUS; } - blockY += Blockly.SNAP_RADIUS * 2; + blockY += Blockly.internalConstants.SNAP_RADIUS * 2; } } while (collide); block.moveBy(blockX, blockY); diff --git a/core/xml.js b/core/xml.js index 4140d6528..e581bfd01 100644 --- a/core/xml.js +++ b/core/xml.js @@ -15,9 +15,6 @@ * @namespace */ goog.provide('Blockly.Xml'); - -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); goog.require('Blockly.Events'); goog.require('Blockly.inputTypes'); goog.require('Blockly.utils'); diff --git a/core/zoom_controls.js b/core/zoom_controls.js index 96ff41ac4..37c1cb17d 100644 --- a/core/zoom_controls.js +++ b/core/zoom_controls.js @@ -10,36 +10,37 @@ */ 'use strict'; -goog.provide('Blockly.ZoomControls'); +goog.module('Blockly.ZoomControls'); +goog.module.declareLegacyNamespace(); -goog.require('Blockly.browserEvents'); -goog.require('Blockly.ComponentManager'); -/** @suppress {extraRequire} */ -goog.require('Blockly.constants'); -goog.require('Blockly.Css'); -goog.require('Blockly.Events'); +const Blockly = goog.require('Blockly'); +const ComponentManager = goog.require('Blockly.ComponentManager'); +const Css = goog.require('Blockly.Css'); +const Events = goog.require('Blockly.Events'); +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.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; @@ -54,7 +55,7 @@ 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} + * @type {?browserEvents.Data} * @private */ this.onZoomResetWrapper_ = null; @@ -62,7 +63,7 @@ Blockly.ZoomControls = function(workspace) { /** * 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} + * @type {?browserEvents.Data} * @private */ this.onZoomInWrapper_ = null; @@ -70,7 +71,7 @@ Blockly.ZoomControls = function(workspace) { /** * 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} + * @type {?browserEvents.Data} * @private */ this.onZoomOutWrapper_ = null; @@ -103,7 +104,7 @@ Blockly.ZoomControls = function(workspace) { * @const * @private */ -Blockly.ZoomControls.prototype.WIDTH_ = 32; +ZoomControls.prototype.WIDTH_ = 32; /** * Height of each zoom control. @@ -111,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. @@ -119,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. @@ -127,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. @@ -135,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()) { @@ -197,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; }; @@ -210,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); }; @@ -248,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_ + ')'); }; /** @@ -310,47 +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.SPRITE.width, - 'height': Blockly.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.SPRITE.url); + zoomoutSvg.setAttributeNS( + 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,47 +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.SPRITE.width, - 'height': Blockly.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.SPRITE.url); + zoominSvg.setAttributeNS( + 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)); }; @@ -413,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. }; /** @@ -429,46 +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.SPRITE.width, - 'height': Blockly.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.SPRITE.url); + zoomresetSvg.setAttributeNS( + 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)); }; @@ -477,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/demos/code/code.js b/demos/code/code.js index 0c2765325..2377203a2 100644 --- a/demos/code/code.js +++ b/demos/code/code.js @@ -549,8 +549,14 @@ Code.initLanguage = function() { /** * Execute the user's code. * Just a quick and dirty eval. Catch infinite loops. + * @param {Event} event Event created from listener bound to the function. */ -Code.runJS = function() { +Code.runJS = function(event) { + // Prevent code from being executed twice on touchscreens. + if (event.type == 'touchend') { + event.preventDefault(); + } + Blockly.JavaScript.INFINITE_LOOP_TRAP = 'checkTimeout();\n'; var timeouts = 0; var checkTimeout = function() { diff --git a/package-lock.json b/package-lock.json index d70d69a71..899eb7600 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16916,45 +16916,45 @@ } }, "google-closure-compiler": { - "version": "20210505.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20210505.0.0.tgz", - "integrity": "sha512-moeYaj4S6YTdOOvjv1ZLdUld/2YXw7q1GqUUHJJd+rE/uViyesozg8yKQZWcB3tvurhb+qEvFFet8CYoeaQHng==", + "version": "20210601.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20210601.0.0.tgz", + "integrity": "sha512-lzzEoG2VTB7uUjnWnMyeZMU163w69HJpM27yh8Up9Ha5McHZeESjt3NRwU8cWMbCRdY06nFbRCDIVCRcadHCiw==", "dev": true, "requires": { "chalk": "2.x", - "google-closure-compiler-java": "^20210505.0.0", - "google-closure-compiler-linux": "^20210505.0.0", - "google-closure-compiler-osx": "^20210505.0.0", - "google-closure-compiler-windows": "^20210505.0.0", + "google-closure-compiler-java": "^20210601.0.0", + "google-closure-compiler-linux": "^20210601.0.0", + "google-closure-compiler-osx": "^20210601.0.0", + "google-closure-compiler-windows": "^20210601.0.0", "minimist": "1.x", "vinyl": "2.x", "vinyl-sourcemaps-apply": "^0.2.0" } }, "google-closure-compiler-java": { - "version": "20210505.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20210505.0.0.tgz", - "integrity": "sha512-h+DfQAaaCLFmmtasOS8eyh0M4D+JInTJfEP4byV5R1cnMninpGGLHOG3PNgLLzkXkIO/fu4ILEcVzoGmgJEoMA==", + "version": "20210601.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20210601.0.0.tgz", + "integrity": "sha512-bH6nIwOmp4qDWvlbXx5/DE3XA2aDGQoCpmRYZJGONY1Sy6Xfbq0ioXRHH9eBDP9hxhCJ5Sd/K89A0NZ8Nz9RJA==", "dev": true }, "google-closure-compiler-linux": { - "version": "20210505.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20210505.0.0.tgz", - "integrity": "sha512-ADN2kFfIR1NiR24kLYb4YkX4MeXDJaT5OfRQEkiuIdZMtd28oEkm80LxCGuC7ftKEixoMm3f9/OG01B4U+xsnA==", + "version": "20210601.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20210601.0.0.tgz", + "integrity": "sha512-rnEQt7zz/1P1SfPhJiHQpfCgMPrsVVyEgDs09h67xn6+LXa9L0RP+hrJDEHqSWwjDPz0BkfUUv6zkqZvp1h/lw==", "dev": true, "optional": true }, "google-closure-compiler-osx": { - "version": "20210505.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20210505.0.0.tgz", - "integrity": "sha512-JTwdh23aD2pwRU4QZjujxp/+rGfhex3utNWEdUDRMNpUGstUK7XPCDG8jNBtUpyuRiXFnpZa90qButqRgotQBA==", + "version": "20210601.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20210601.0.0.tgz", + "integrity": "sha512-A5r4s/WthR2iLMM0mxsluw8EW2AcOomC5ri/H6FjzpMq0RVEnLTgaGYdXolUAfEzH/7XtJJT2+JkYk3HSLCtrg==", "dev": true, "optional": true }, "google-closure-compiler-windows": { - "version": "20210505.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20210505.0.0.tgz", - "integrity": "sha512-bKTbg/f4ak72OggEMaH/7oExqOO9dS+TxwGhoovYOt/YaVR/8MDfGdxsOhqoiboiFwYysTPz8bwINjYQK6AwnA==", + "version": "20210601.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20210601.0.0.tgz", + "integrity": "sha512-6r94bPShnB0XXh9+5/qXGDHJN2PQGhF9yJPcgBZj+FAZlQGzlYkT0pkyp+loZT3lG+YRbjD28Lgo7xMcY4xgkA==", "dev": true, "optional": true }, @@ -21533,9 +21533,9 @@ "dev": true }, "typescript": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", - "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true }, "typescript-closure-tools": { diff --git a/package.json b/package.json index dda2766d2..6026bc4ec 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "publish:beta": "gulp publishBeta", "recompile": "gulp recompile", "release": "gulp gitCreateRC", - "start": "http-server -o /tests/playground.html", + "start": "http-server ./ -o /tests/playground.html", "test": "tests/run_all_tests.sh", "test:generators": "tests/scripts/run_generators.sh", "test:compile:advanced": "gulp buildAdvancedCompilationTest", @@ -74,7 +74,7 @@ "clang-format": "^1.5.0", "concurrently": "^6.0.0", "eslint": "^7.28.0", - "google-closure-compiler": "^20210505.0.0", + "google-closure-compiler": "^20210601.0.0", "google-closure-deps": "^20210601.0.0", "gulp": "^4.0.2", "gulp-concat": "^2.6.1", diff --git a/scripts/goog_module/convert-file.sh b/scripts/goog_module/convert-file.sh new file mode 100755 index 000000000..ebf791d3b --- /dev/null +++ b/scripts/goog_module/convert-file.sh @@ -0,0 +1,344 @@ +#!/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. +####################################### +COLOR_NONE="\033[0m" +GREEN="\033[0;32m" +BLUE="\033[0;34m" +ORANGE="\033[0;33m" +RED="\033[0;31m" +success() { + echo -e "${GREEN}[SUCCESS]:${COLOR_NONE} $*" >&2 +} +inf() { + echo -e "${BLUE}[INFO]:${COLOR_NONE} $*" >&2 +} +warn() { + echo -e "${ORANGE}[WARN]:${COLOR_NONE} $*" >&2 +} +err() { + echo -e "${RED}[ERROR]:${COLOR_NONE} $*" >&2 +} +reenter_instructions() { + echo -e "${ORANGE}$*${COLOR_NONE}" >&2 +} + +####################################### +# Checks whether the provided filepath exists. +# Arguments: +# The filepath to check for existence. +# Optional: Whether to log an error. +####################################### +verify-filepath() { + local filepath="$1" + local no_log="$2" + if [[ ! -f "${filepath}" ]]; then + if [[ -z "${no_log}" || "${no_log}" == 'true' ]]; then + err "File ${filepath} does not exist" + fi + return 1 + fi +} + +####################################### +# Creates a commit with a message based on the specified step and file. +# Arguments: +# Which conversion step this message is for. +# The filepath of the file being converted. +####################################### +commit-step() { + local step="$1" + local filepath="$2" + if [[ -z "${step}" ]]; then + err "Missing argument (1-4)" + return 1 + fi + if [[ -z "${filepath}" ]]; then + err "Missing argument filepath" + return 1 + fi + verify-filepath "${filepath}" + if [[ $? -eq 1 ]]; then return 1; fi + + local message='' + case $1 in + 1) + message="Migrate ${filepath} to ES6 const/let" + ;; + 2) + message="Migrate ${filepath} to goog.module" + ;; + 3) + message="Migrate ${filepath} named requires" + ;; + 4) + message="clang-format ${filepath}" + ;; + *) + err 'INVALID ARGUMENT' + return 1 + ;; + esac + git add . + if [[ -z $(git status --porcelain) ]]; then + success "Nothing to commit" + return 0 + fi + git commit -m "${message}" + success "created commit with message: \"${message}\"" +} + +####################################### +# Runs step 2 of the automated conversion. +# Arguments: +# The filepath of the file being converted. +####################################### +step2 () { + local filepath="$1" + + inf "Updating goog.provide declaration..." + perl -pi -e 's/^goog\.provide(\([^\)]+\)\;)/goog\.module\1\ngoog.module.declareLegacyNamespace\(\)\;/' "${filepath}" + + inf "Extracting module name..." + local module_name=$(perl -ne 'print m/(?<=^goog\.module\('\'')([^'\'']+)/' "${filepath}") + if [[ -z "${module_name}" ]]; then + err "Could not extract module name" + return 1 + fi + inf "Extracted module name \"${module_name}\"" + + if [[ $(grep "${module_name} = " "${filepath}") ]]; then + local class_name=$(echo "${module_name}" | perl -ne 'print m/(\w+)$/') + inf "Found class \"${class_name}\" in file." + inf "Updating class declaration..." + perl -pi -e 's/^('"${module_name}"') =/const '"${class_name}"' =/g' "${filepath}" + + inf "Updating local references to class..." + perl -pi -e 's/'"${module_name}"'(?!['\''\w])/'"${class_name}"'/g' "${filepath}" + + inf "Appending class export to end of file..." + echo "" >> "${filepath}" + echo "exports = ${class_name};" >> "${filepath}" + + npm run build:deps + + success "Completed automated conversion to goog.module. Please manually review before committing." + return 0 + fi + + # No top level class. + inf 'Updating top-level property declarations...' + perl -pi -e 's/^'"${module_name}"'\.([^ ]+) =/const \1 =/g' "${filepath}" + inf "Updating local references to module..." + perl -pi -e 's/'"${module_name}"'\.([^ ]+)/\1/g' "${filepath}" + + npm run build:deps + success "Completed automation for step 2. Please manually review and add exports for non-private top-level functions." +} + +####################################### +# Runs step 3 of the automated conversion. +# Arguments: +# The filepath of the file being converted. +####################################### +step3() { + inf "Extracting module name..." + local module_name=$(perl -ne 'print m/(?<=^goog\.module\('\'')([^'\'']+)/' "${filepath}") + if [[ -z "${module_name}" ]]; then + err "Could not extract module name" + return 1 + fi + inf "Extracted module name \"${module_name}\"" + + local requires=$(perl -nle 'print $& while m{(?:(?<=^goog.require\('\'')|(?<=^goog.requireType\('\''))[^'\'']+}g' "${filepath}") + + # Process each require + echo "${requires}" | while read -r require; do + inf "Processing require \"${require}\"" + local usages=$(perl -nle 'print $& while m{'"${require}"'(?!'\'')}g' "${filepath}" | wc -l) + + if [[ "${usages}" -eq "0" ]]; then + warn "Unused require \"${require}\"" + continue + fi + + local require_name=$(echo "${require}" | perl -pe 's/(\w+\.)+(\w+)/\2/g') + inf "Updating require declaration for ${require}..." + perl -pi -e 's/^(goog\.(require|requireType)\('\'"${require}"\''\);)/const '"${require_name}"' = \1/' "${filepath}" + + # Parse property access of module + local direct_access_count=$(perl -nle 'print $& while m{'"${require}"'[^\.'\'']}g' "${filepath}" | wc -l) + local properties_accessed=$(perl -nle 'print $& while m{(?<='"${require}"'\.)(?!prototype)\w+}g' "${filepath}" | sort -u) + + # Detect requires overlap + # (ex: Blockly.utils require and Blockly.utils.dom also in requires) + local requires_overlap=$(echo "${requires}" | perl -nle 'print $& while m{(?<='"${require}"'\.)\w+}g') + if [[ -n "${requires_overlap}" ]]; then + while read -r requires_overlap_prop; do + properties_accessed=$(echo "${properties_accessed}" | perl -pe 's/'"${requires_overlap_prop}"'//g') + done <<<"${requires_overlap}" + fi + # Detect module name overlap + # (ex: Blockly require and Blockly.ContextMenuItems module being converted) + local module_overlap=$(echo "${module_name}" | perl -nle 'print $& while m{(?<='"${require}"'\.)\w+}g') + if [[ -n "${module_overlap}" ]]; then + properties_accessed=$(echo "${properties_accessed}" | perl -pe 's/'"${module_overlap}"'//g') + fi + properties_accessed=$(echo "${properties_accessed}" | perl -pe 's/\s+/ /g' | xargs) + + if [[ -n "${properties_accessed}" ]]; then + local comma_properties=$(echo "${properties_accessed}" | perl -pe 's/\s+/, /g' | perl -pe 's/, $//') + inf "Detected references of ${require}: ${comma_properties}" + + for require_prop in $(echo "${properties_accessed}"); do + inf "Updating references of ${require}.${require_prop} to ${require_name}.${require_prop}..." + perl -pi -e 's/'"${require}"'\.'"${require_prop}"'(?!\w)/'"${require_name}"'\.'"${require_prop}"'/g' "${filepath}" + done + fi + + inf "Updating direct references of ${require} to ${require_name}..." + perl -pi -e 's/'"${require}"'(?!['\''\w\.])/'"${require_name}"'/g' "${filepath}" + done + + local missing_requires=$(perl -nle'print $& while m{(? |-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]" +} + +####################################### +# Main entry point. +####################################### +main() { + if [ "$1" = "" ]; then + help + else + local filepath="" + # Support filepath as first argument. + verify-filepath "$1" "false" + if [[ $? -eq 0 ]]; then + filepath="$1" + shift + fi + + local command="$1" + shift + case $command in + -c) commit-step "$@" "${filepath}" ;; + -s) run-step "$@" "${filepath}" ;; + *) err "INVALID ARGUMENT ${command}";; + esac + fi +} + +main "$@" diff --git a/tests/deps.js b/tests/deps.js index 3f6eae7a5..805416071 100644 --- a/tests/deps.js +++ b/tests/deps.js @@ -8,28 +8,28 @@ goog.addDependency('../../blocks/text.js', ['Blockly.Blocks.texts', 'Blockly.Con goog.addDependency('../../blocks/variables.js', ['Blockly.Blocks.variables', 'Blockly.Constants.Variables'], ['Blockly', 'Blockly.Blocks', 'Blockly.FieldLabel', 'Blockly.FieldVariable']); goog.addDependency('../../blocks/variables_dynamic.js', ['Blockly.Constants.VariablesDynamic'], ['Blockly', 'Blockly.Blocks', 'Blockly.FieldLabel', 'Blockly.FieldVariable']); goog.addDependency('../../core/block.js', ['Blockly.Block'], ['Blockly.ASTNode', 'Blockly.Blocks', 'Blockly.Connection', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Extensions', 'Blockly.IASTNodeLocation', 'Blockly.IDeletable', 'Blockly.Input', 'Blockly.Tooltip', 'Blockly.Workspace', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.object'], {'lang': 'es5'}); -goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations'], ['Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom']); -goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.IBlockDragger', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom']); -goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.IASTNodeLocationSvg', 'Blockly.IBoundedElement', 'Blockly.ICopyable', 'Blockly.IDraggable', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Xml', 'Blockly.blockAnimations', 'Blockly.blockRendering.IPathObject', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.ComponentManager', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Procedures', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox']); -goog.addDependency('../../core/blocks.js', ['Blockly.Blocks'], []); +goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations'], ['Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.IBlockDragger', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.IASTNodeLocationSvg', 'Blockly.IBoundedElement', 'Blockly.ICopyable', 'Blockly.IDraggable', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Xml', 'Blockly.blockAnimations', 'Blockly.blockRendering.IPathObject', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.ComponentManager', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Procedures', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox']); +goog.addDependency('../../core/blocks.js', ['Blockly.Blocks'], [], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/browser_events.js', ['Blockly.browserEvents'], ['Blockly.Touch', 'Blockly.utils.global']); goog.addDependency('../../core/bubble.js', ['Blockly.Bubble'], ['Blockly.IBubble', 'Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.ComponentManager', 'Blockly.Events', 'Blockly.Events.CommentMove', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate']); -goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/component_manager.js', ['Blockly.ComponentManager'], []); -goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.deprecation']); -goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.IConnectionChecker', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.registry']); -goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.RenderedConnection', 'Blockly.connectionTypes', 'Blockly.constants']); -goog.addDependency('../../core/connection_types.js', ['Blockly.connectionTypes'], []); -goog.addDependency('../../core/constants.js', ['Blockly.constants'], ['Blockly.connectionTypes']); -goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.ComponentManager', 'Blockly.Events', 'Blockly.Events.CommentMove', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/component_manager.js', ['Blockly.ComponentManager'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.IConnectionChecker', 'Blockly.connectionTypes', 'Blockly.internalConstants', 'Blockly.registry'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.RenderedConnection', 'Blockly.connectionTypes', 'Blockly.constants'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/connection_types.js', ['Blockly.connectionTypes'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/constants.js', ['Blockly.constants'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent']); goog.addDependency('../../core/contextmenu_items.js', ['Blockly.ContextMenuItems'], ['Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.constants', 'Blockly.inputTypes'], {'lang': 'es5'}); goog.addDependency('../../core/contextmenu_registry.js', ['Blockly.ContextMenuRegistry'], [], {'lang': 'es5'}); -goog.addDependency('../../core/css.js', ['Blockly.Css'], [], {'lang': 'es5'}); -goog.addDependency('../../core/delete_area.js', ['Blockly.DeleteArea'], ['Blockly.BlockSvg', 'Blockly.DragTarget', 'Blockly.IDeleteArea']); -goog.addDependency('../../core/drag_target.js', ['Blockly.DragTarget'], ['Blockly.IDragTarget']); +goog.addDependency('../../core/css.js', ['Blockly.Css'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/delete_area.js', ['Blockly.DeleteArea'], ['Blockly.BlockSvg', 'Blockly.DragTarget', 'Blockly.IDeleteArea', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/drag_target.js', ['Blockly.DragTarget'], ['Blockly.IDragTarget'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/dropdowndiv.js', ['Blockly.DropDownDiv'], ['Blockly.utils.Rect', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.style']); goog.addDependency('../../core/events/block_events.js', ['Blockly.Events.BlockBase', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Events.Change', 'Blockly.Events.Create', 'Blockly.Events.Delete', 'Blockly.Events.Move'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml']); goog.addDependency('../../core/events/events.js', ['Blockly.Events'], ['Blockly.registry', 'Blockly.utils']); @@ -47,86 +47,92 @@ goog.addDependency('../../core/events/ui_events.js', ['Blockly.Events.Ui', 'Bloc goog.addDependency('../../core/events/variable_events.js', ['Blockly.Events.VarBase', 'Blockly.Events.VarCreate', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object']); goog.addDependency('../../core/events/workspace_events.js', ['Blockly.Events.FinishedLoading'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es5'}); goog.addDependency('../../core/events/ws_comment_events.js', ['Blockly.Events.CommentBase', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml']); -goog.addDependency('../../core/extensions.js', ['Blockly.Extensions'], ['Blockly.utils']); -goog.addDependency('../../core/field.js', ['Blockly.Field'], ['Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Gesture', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible', 'Blockly.IRegistrable', 'Blockly.MarkerManager', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style', 'Blockly.utils.userAgent'], {'lang': 'es5'}); +goog.addDependency('../../core/extensions.js', ['Blockly.Extensions'], ['Blockly.utils'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/field.js', ['Blockly.Field'], ['Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Gesture', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible', 'Blockly.IRegistrable', 'Blockly.MarkerManager', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/field_angle.js', ['Blockly.FieldAngle'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/field_checkbox.js', ['Blockly.FieldCheckbox'], ['Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils.dom', 'Blockly.utils.object']); -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']); -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']); -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']); -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_serializable.js', ['Blockly.FieldLabelSerializable'], ['Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.object']); -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': 'es5'}); -goog.addDependency('../../core/field_number.js', ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'Blockly.fieldRegistry', 'Blockly.utils.aria', 'Blockly.utils.object']); -goog.addDependency('../../core/field_registry.js', ['Blockly.fieldRegistry'], ['Blockly.registry']); -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_variable.js', ['Blockly.FieldVariable'], ['Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.object']); -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/field_checkbox.js', ['Blockly.FieldCheckbox'], ['Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +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'], {'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', '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', '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': 'es5'}); -goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['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']); -goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly.Block', 'Blockly.constants', 'Blockly.utils.deprecation']); -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.constants', 'Blockly.utils', 'Blockly.utils.Coordinate']); -goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom']); +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'], {'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.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.constants', '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.constants'], {'lang': 'es5'}); -goog.addDependency('../../core/interfaces/i_accessibility.js', ['Blockly.IASTNodeLocation', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible'], []); -goog.addDependency('../../core/interfaces/i_autohideable.js', ['Blockly.IAutoHideable'], ['Blockly.IComponent']); -goog.addDependency('../../core/interfaces/i_block_dragger.js', ['Blockly.IBlockDragger'], []); -goog.addDependency('../../core/interfaces/i_bounded_element.js', ['Blockly.IBoundedElement'], []); -goog.addDependency('../../core/interfaces/i_bubble.js', ['Blockly.IBubble'], ['Blockly.IContextMenu', 'Blockly.IDraggable']); -goog.addDependency('../../core/interfaces/i_component.js', ['Blockly.IComponent'], []); -goog.addDependency('../../core/interfaces/i_connection_checker.js', ['Blockly.IConnectionChecker'], []); -goog.addDependency('../../core/interfaces/i_contextmenu.js', ['Blockly.IContextMenu'], []); -goog.addDependency('../../core/interfaces/i_copyable.js', ['Blockly.ICopyable'], []); -goog.addDependency('../../core/interfaces/i_deletable.js', ['Blockly.IDeletable'], []); -goog.addDependency('../../core/interfaces/i_delete_area.js', ['Blockly.IDeleteArea'], ['Blockly.IDragTarget']); -goog.addDependency('../../core/interfaces/i_drag_target.js', ['Blockly.IDragTarget'], ['Blockly.IComponent']); -goog.addDependency('../../core/interfaces/i_draggable.js', ['Blockly.IDraggable'], ['Blockly.IDeletable']); -goog.addDependency('../../core/interfaces/i_flyout.js', ['Blockly.IFlyout'], []); -goog.addDependency('../../core/interfaces/i_metrics_manager.js', ['Blockly.IMetricsManager'], []); -goog.addDependency('../../core/interfaces/i_movable.js', ['Blockly.IMovable'], []); -goog.addDependency('../../core/interfaces/i_positionable.js', ['Blockly.IPositionable'], ['Blockly.IComponent']); -goog.addDependency('../../core/interfaces/i_registrable.js', ['Blockly.IRegistrable'], []); -goog.addDependency('../../core/interfaces/i_registrable_field.js', ['Blockly.IRegistrableField'], []); -goog.addDependency('../../core/interfaces/i_selectable.js', ['Blockly.ISelectable'], []); -goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable'], []); -goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], []); -goog.addDependency('../../core/interfaces/i_toolbox_item.js', ['Blockly.ICollapsibleToolboxItem', 'Blockly.ISelectableToolboxItem', 'Blockly.IToolboxItem'], []); -goog.addDependency('../../core/keyboard_nav/ast_node.js', ['Blockly.ASTNode'], ['Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Coordinate'], {'lang': 'es5'}); -goog.addDependency('../../core/keyboard_nav/basic_cursor.js', ['Blockly.BasicCursor'], ['Blockly.ASTNode', 'Blockly.Cursor', 'Blockly.registry'], {'lang': 'es5'}); -goog.addDependency('../../core/keyboard_nav/cursor.js', ['Blockly.Cursor'], ['Blockly.ASTNode', 'Blockly.Marker', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es5'}); +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'}); +goog.addDependency('../../core/interfaces/i_ast_node_location_svg.js', ['Blockly.IASTNodeLocationSvg'], ['Blockly.IASTNodeLocation'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_ast_node_location_with_block.js', ['Blockly.IASTNodeLocationWithBlock'], ['Blockly.IASTNodeLocation'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_autohideable.js', ['Blockly.IAutoHideable'], ['Blockly.IComponent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_block_dragger.js', ['Blockly.IBlockDragger'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_bounded_element.js', ['Blockly.IBoundedElement'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_bubble.js', ['Blockly.IBubble'], ['Blockly.IContextMenu', 'Blockly.IDraggable'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_collapsible_toolbox_item.js', ['Blockly.ICollapsibleToolboxItem'], ['Blockly.ISelectableToolboxItem'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_component.js', ['Blockly.IComponent'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_connection_checker.js', ['Blockly.IConnectionChecker'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_contextmenu.js', ['Blockly.IContextMenu'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_copyable.js', ['Blockly.ICopyable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_deletable.js', ['Blockly.IDeletable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_delete_area.js', ['Blockly.IDeleteArea'], ['Blockly.IDragTarget'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_drag_target.js', ['Blockly.IDragTarget'], ['Blockly.IComponent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_draggable.js', ['Blockly.IDraggable'], ['Blockly.IDeletable'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_flyout.js', ['Blockly.IFlyout'], ['Blockly.IRegistrable'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_keyboard_accessible.js', ['Blockly.IKeyboardAccessible'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_metrics_manager.js', ['Blockly.IMetricsManager'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_movable.js', ['Blockly.IMovable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_positionable.js', ['Blockly.IPositionable'], ['Blockly.IComponent'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_registrable.js', ['Blockly.IRegistrable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_registrable_field.js', ['Blockly.IRegistrableField'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_selectable.js', ['Blockly.ISelectable'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_selectable_toolbox_item.js', ['Blockly.ISelectableToolboxItem'], ['Blockly.IToolboxItem'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable'], [], {'lang': 'es6', 'module': 'goog'}); +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/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/tab_navigate_cursor.js', ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object']); -goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], ['Blockly.Cursor', 'Blockly.Marker']); -goog.addDependency('../../core/menu.js', ['Blockly.Menu'], ['Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.style']); +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'], [], {'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.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml']); -goog.addDependency('../../core/names.js', ['Blockly.Names'], ['Blockly.Msg', 'Blockly.constants']); +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/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.constants', 'Blockly.utils.xml']); +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.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object']); +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/renderers/common/block_rendering.js', ['Blockly.blockRendering'], ['Blockly.registry']); -goog.addDependency('../../core/renderers/common/constants.js', ['Blockly.blockRendering.ConstantProvider'], ['Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent'], {'lang': 'es5'}); -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.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'}); -goog.addDependency('../../core/renderers/common/drawer.js', ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.svgPaths']); +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.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']); -goog.addDependency('../../core/renderers/common/marker_svg.js', ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode', 'Blockly.Events', 'Blockly.Events.MarkerMove', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom']); +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/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', 'Blockly.constants']); +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']); goog.addDependency('../../core/renderers/geras/highlight_constants.js', ['Blockly.geras.HighlightConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.svgPaths'], {'lang': 'es5'}); goog.addDependency('../../core/renderers/geras/highlighter.js', ['Blockly.geras.Highlighter'], ['Blockly.blockRendering.Types', 'Blockly.utils.svgPaths']); -goog.addDependency('../../core/renderers/geras/info.js', ['Blockly.geras', 'Blockly.geras.RenderInfo'], ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.geras.InlineInput', 'Blockly.geras.StatementInput', 'Blockly.inputTypes', 'Blockly.utils.object']); +goog.addDependency('../../core/renderers/geras/info.js', ['Blockly.geras', 'Blockly.geras.RenderInfo'], ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.geras.InlineInput', 'Blockly.geras.StatementInput', 'Blockly.inputTypes', 'Blockly.utils.object']); goog.addDependency('../../core/renderers/geras/measurables/inputs.js', ['Blockly.geras.InlineInput', 'Blockly.geras.StatementInput'], ['Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.StatementInput', 'Blockly.utils.object']); goog.addDependency('../../core/renderers/geras/path_object.js', ['Blockly.geras.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.PathObject', 'Blockly.geras.ConstantProvider', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object']); goog.addDependency('../../core/renderers/geras/renderer.js', ['Blockly.geras.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.geras.ConstantProvider', 'Blockly.geras.Drawer', 'Blockly.geras.HighlightConstantProvider', 'Blockly.geras.PathObject', 'Blockly.geras.RenderInfo', 'Blockly.utils.object']); @@ -142,68 +148,68 @@ goog.addDependency('../../core/renderers/minimalist/info.js', ['Blockly.minimali goog.addDependency('../../core/renderers/minimalist/renderer.js', ['Blockly.minimalist.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.minimalist.ConstantProvider', 'Blockly.minimalist.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object']); goog.addDependency('../../core/renderers/thrasos/info.js', ['Blockly.thrasos', 'Blockly.thrasos.RenderInfo'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); goog.addDependency('../../core/renderers/thrasos/renderer.js', ['Blockly.thrasos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.thrasos.RenderInfo', 'Blockly.utils.object']); -goog.addDependency('../../core/renderers/zelos/constants.js', ['Blockly.zelos.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es5'}); +goog.addDependency('../../core/renderers/zelos/constants.js', ['Blockly.zelos.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.connectionTypes', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es5'}); goog.addDependency('../../core/renderers/zelos/drawer.js', ['Blockly.zelos.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.utils.object', 'Blockly.utils.svgPaths', 'Blockly.zelos.RenderInfo']); -goog.addDependency('../../core/renderers/zelos/info.js', ['Blockly.zelos', 'Blockly.zelos.RenderInfo'], ['Blockly.FieldImage', 'Blockly.FieldLabel', 'Blockly.FieldTextInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils.object', 'Blockly.zelos.BottomRow', 'Blockly.zelos.RightConnectionShape', 'Blockly.zelos.TopRow']); +goog.addDependency('../../core/renderers/zelos/info.js', ['Blockly.zelos', 'Blockly.zelos.RenderInfo'], ['Blockly.FieldImage', 'Blockly.FieldLabel', 'Blockly.FieldTextInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.inputTypes', 'Blockly.utils.object', 'Blockly.zelos.BottomRow', 'Blockly.zelos.RightConnectionShape', 'Blockly.zelos.TopRow']); goog.addDependency('../../core/renderers/zelos/marker_svg.js', ['Blockly.zelos.MarkerSvg'], ['Blockly.blockRendering.MarkerSvg', 'Blockly.utils.Svg', 'Blockly.utils.dom']); goog.addDependency('../../core/renderers/zelos/measurables/inputs.js', ['Blockly.zelos.StatementInput'], ['Blockly.blockRendering.StatementInput', 'Blockly.utils.object']); goog.addDependency('../../core/renderers/zelos/measurables/row_elements.js', ['Blockly.zelos.RightConnectionShape'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); goog.addDependency('../../core/renderers/zelos/measurables/rows.js', ['Blockly.zelos.BottomRow', 'Blockly.zelos.TopRow'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.TopRow', 'Blockly.utils.object']); goog.addDependency('../../core/renderers/zelos/path_object.js', ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider']); -goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo']); +goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.connectionTypes', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo']); 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', 'Blockly.utils.object']); 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/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']); goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.utils.string']); -goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.constants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.string']); +goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.string']); goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.object']); -goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.IAutoHideable', 'Blockly.IPositionable', 'Blockly.Options', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'}); -goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.constants', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.colour', 'Blockly.utils.global', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.userAgent']); -goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], [], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], []); -goog.addDependency('../../core/utils/coordinate.js', ['Blockly.utils.Coordinate'], []); +goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.IAutoHideable', 'Blockly.IPositionable', 'Blockly.Options', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'}); +goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.internalConstants', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.colour', 'Blockly.utils.global', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.userAgent']); +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/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'}); goog.addDependency('../../core/utils/math.js', ['Blockly.utils.math'], [], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/utils/metrics.js', ['Blockly.utils.Metrics'], []); +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'], []); -goog.addDependency('../../core/utils/size.js', ['Blockly.utils.Size'], []); +goog.addDependency('../../core/utils/rect.js', ['Blockly.utils.Rect'], [], {'lang': 'es6', 'module': 'goog'}); +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']); +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'], []); -goog.addDependency('../../core/utils/svg_paths.js', ['Blockly.utils.svgPaths'], []); -goog.addDependency('../../core/utils/toolbox.js', ['Blockly.utils.toolbox'], ['Blockly.Xml', 'Blockly.constants']); +goog.addDependency('../../core/utils/svg_paths.js', ['Blockly.utils.svgPaths'], [], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/utils/toolbox.js', ['Blockly.utils.toolbox'], ['Blockly.Xml', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); 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/variables.js', ['Blockly.Variables'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Xml', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.xml']); +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/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.constants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es5'}); +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_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.constants', '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.constants', '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.constants', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'}); +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', '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/mocha/workspace_svg_test.js b/tests/mocha/workspace_svg_test.js index 339a19a98..d79707d08 100644 --- a/tests/mocha/workspace_svg_test.js +++ b/tests/mocha/workspace_svg_test.js @@ -112,11 +112,6 @@ suite('WorkspaceSvg', function() { this.workspace.updateToolbox({'contents': []}); }.bind(this), 'Existing toolbox has categories. Can\'t change mode.'); }); - test('Passing in string as toolboxdef', function() { - var parseToolboxFake = sinon.spy(Blockly.utils.toolbox, 'parseToolboxTree'); - this.workspace.updateToolbox(''); - sinon.assert.calledOnce(parseToolboxFake); - }); }); suite('addTopBlock', function() { diff --git a/tests/run_all_tests.sh b/tests/run_all_tests.sh index f6c7c0f8c..ccb18cf9c 100755 --- a/tests/run_all_tests.sh +++ b/tests/run_all_tests.sh @@ -49,7 +49,10 @@ run_test_command () { } # Lint the codebase. -run_test_command "eslint" "eslint ." +# Skip for CI environments, because linting is run separately. +if [ -z $CI ]; then + run_test_command "eslint" "eslint ." +fi # Run the full usual build process. run_test_command "build" "npm run build" diff --git a/tests/scripts/update_metadata.sh b/tests/scripts/update_metadata.sh new file mode 100755 index 000000000..d3b97f3ab --- /dev/null +++ b/tests/scripts/update_metadata.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Determines the size of generated files and updates check_metadata.sh to +# reflect the new values. + +gzip -k build/blockly_compressed.js +gzip -k build/blocks_compressed.js + +blockly_size=$(wc -c < "build/blockly_compressed.js") +blocks_size=$(wc -c < "build/blocks_compressed.js") +blockly_gz_size=$(wc -c < "build/blockly_compressed.js.gz") +blocks_gz_size=$(wc -c < "build/blocks_compressed.js.gz") +quarter=$(date "+Q%q %Y") +version=$(npx -c 'echo "$npm_package_version"') + +replacement="# ${quarter}\t${version}\t${blockly_size}\n" +replacement+="readonly BLOCKLY_SIZE_EXPECTED=${blockly_size}" +sed -ri "s/readonly BLOCKLY_SIZE_EXPECTED=[0-9]+/${replacement}/g" \ + tests/scripts/check_metadata.sh + +replacement="# ${quarter}\t${version}\t${blocks_size}\n" +replacement+="readonly BLOCKS_SIZE_EXPECTED=${blocks_size}" +sed -ri "s/readonly BLOCKS_SIZE_EXPECTED=[0-9]+/${replacement}/g" \ + tests/scripts/check_metadata.sh + +replacement="# ${quarter}\t${version}\t${blockly_gz_size}\n" +replacement+="readonly BLOCKLY_GZ_SIZE_EXPECTED=${blockly_gz_size}" +sed -ri "s/readonly BLOCKLY_GZ_SIZE_EXPECTED=[0-9]+/${replacement}/g" \ + tests/scripts/check_metadata.sh + +replacement="# ${quarter}\t${version}\t${blocks_gz_size}\n" +replacement+="readonly BLOCKS_GZ_SIZE_EXPECTED=${blocks_gz_size}" +sed -ri "s/readonly BLOCKS_GZ_SIZE_EXPECTED=[0-9]+/${replacement}/g" \ + tests/scripts/check_metadata.sh \ No newline at end of file