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/tests/deps.js b/tests/deps.js index 5cadf3977..3f1ac7e7e 100644 --- a/tests/deps.js +++ b/tests/deps.js @@ -108,7 +108,7 @@ goog.addDependency('../../core/keyboard_nav/cursor.js', ['Blockly.Cursor'], ['Bl 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'], {'lang': 'es6', 'module': 'goog'}); 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/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']);