Merge pull request #5174 from alschmiedt/migrate_menu

Migrate core/menu.js to goog.module syntax
This commit is contained in:
alschmiedt
2021-07-23 11:51:00 -07:00
committed by GitHub
2 changed files with 101 additions and 96 deletions

View File

@@ -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<Blockly.MenuItem>}
* @type {!Array<MenuItem>}
* @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;

View File

@@ -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']);