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/tests/deps.js b/tests/deps.js index bfe2639f5..da56c39f2 100644 --- a/tests/deps.js +++ b/tests/deps.js @@ -52,7 +52,7 @@ goog.addDependency('../../core/field.js', ['Blockly.Field'], ['Blockly.DropDownD 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'], {'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']); +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']); 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']);