mirror of
https://github.com/google/blockly.git
synced 2026-01-10 02:17:09 +01:00
Fix bug with dropdown menu propagating the opening click event to a menu item (#3570)
* Prevent dropdown field menu from propagating a click event onto a menu item when the dropdown appears above the field
This commit is contained in:
@@ -25,6 +25,7 @@ goog.provide('Blockly.Menu');
|
||||
|
||||
goog.require('Blockly.Component');
|
||||
goog.require('Blockly.utils.aria');
|
||||
goog.require('Blockly.utils.Coordinate');
|
||||
goog.require('Blockly.utils.dom');
|
||||
goog.require('Blockly.utils.object');
|
||||
|
||||
@@ -37,6 +38,15 @@ goog.require('Blockly.utils.object');
|
||||
Blockly.Menu = function() {
|
||||
Blockly.Component.call(this);
|
||||
|
||||
/**
|
||||
* 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}
|
||||
* @package
|
||||
*/
|
||||
this.openingCoords = null;
|
||||
|
||||
/**
|
||||
* This is the element that we will listen to the real focus events on.
|
||||
* A value of -1 means no menuitem is highlighted.
|
||||
@@ -432,6 +442,20 @@ Blockly.Menu.prototype.handleMouseOver_ = function(e) {
|
||||
* @private
|
||||
*/
|
||||
Blockly.Menu.prototype.handleClick_ = function(e) {
|
||||
var 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) {
|
||||
// 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
|
||||
// up under the mouse and the user didn't mean to activate this item.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var menuItem = this.getMenuItem(/** @type {Node} */ (e.target));
|
||||
|
||||
if (menuItem && menuItem.handleClick(e)) {
|
||||
|
||||
@@ -204,6 +204,8 @@ Blockly.Field.prototype.getText_;
|
||||
* An optional method that can be defined to show an editor when the field is
|
||||
* clicked. Blockly will automatically set the field as clickable if this
|
||||
* method is defined.
|
||||
* @param {Event=} opt_e Optional mouse event that triggered the field to open,
|
||||
* or undefined if triggered programatically.
|
||||
* @return {void}
|
||||
* @protected
|
||||
*/
|
||||
@@ -602,11 +604,13 @@ Blockly.Field.prototype.render_ = function() {
|
||||
|
||||
/**
|
||||
* Show an editor when the field is clicked only if the field is clickable.
|
||||
* @param {Event=} opt_e Optional mouse event that triggered the field to open,
|
||||
* or undefined if triggered programatically.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Field.prototype.showEditor = function() {
|
||||
Blockly.Field.prototype.showEditor = function(opt_e) {
|
||||
if (this.isClickable()) {
|
||||
this.showEditor_();
|
||||
this.showEditor_(opt_e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -256,15 +256,17 @@ Blockly.FieldAngle.prototype.render_ = function() {
|
||||
|
||||
/**
|
||||
* Create and show the angle field's editor.
|
||||
* @param {Event=} opt_e Optional mouse event that triggered the field to open,
|
||||
* or undefined if triggered programatically.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldAngle.prototype.showEditor_ = function() {
|
||||
Blockly.FieldAngle.prototype.showEditor_ = function(opt_e) {
|
||||
// Mobile browsers have issues with in-line textareas (focus & keyboards).
|
||||
var noFocus =
|
||||
Blockly.utils.userAgent.MOBILE ||
|
||||
Blockly.utils.userAgent.ANDROID ||
|
||||
Blockly.utils.userAgent.IPAD;
|
||||
Blockly.FieldAngle.superClass_.showEditor_.call(this, noFocus);
|
||||
Blockly.FieldAngle.superClass_.showEditor_.call(this, opt_e, noFocus);
|
||||
|
||||
var editor = this.dropdownCreate_();
|
||||
Blockly.DropDownDiv.getContentDiv().appendChild(editor);
|
||||
|
||||
@@ -34,6 +34,7 @@ goog.require('Blockly.MenuItem');
|
||||
goog.require('Blockly.navigation');
|
||||
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.Size');
|
||||
@@ -267,10 +268,18 @@ Blockly.FieldDropdown.prototype.createSVGArrow_ = function() {
|
||||
|
||||
/**
|
||||
* Create a dropdown menu under the text.
|
||||
* @param {Event=} opt_e Optional mouse event that triggered the field to open,
|
||||
* or undefined if triggered programatically.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldDropdown.prototype.showEditor_ = function() {
|
||||
Blockly.FieldDropdown.prototype.showEditor_ = function(opt_e) {
|
||||
this.menu_ = this.dropdownCreate_();
|
||||
if (opt_e && typeof opt_e.clientX === 'number') {
|
||||
this.menu_.openingCoords =
|
||||
new Blockly.utils.Coordinate(opt_e.clientX, opt_e.clientY);
|
||||
} else {
|
||||
this.menu_.openingCoords = null;
|
||||
}
|
||||
// Element gets created in render.
|
||||
this.menu_.render(Blockly.DropDownDiv.getContentDiv());
|
||||
Blockly.utils.dom.addClass(
|
||||
|
||||
@@ -285,11 +285,14 @@ Blockly.FieldTextInput.prototype.setSpellcheck = function(check) {
|
||||
|
||||
/**
|
||||
* Show the inline free-text editor on top of the text.
|
||||
* @param {Event=} _opt_e Optional mouse event that triggered the field to open,
|
||||
* or undefined if triggered programatically.
|
||||
* @param {boolean=} opt_quietInput True if editor should be created without
|
||||
* focus. Defaults to false.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput) {
|
||||
Blockly.FieldTextInput.prototype.showEditor_ = function(_opt_e,
|
||||
opt_quietInput) {
|
||||
this.workspace_ = this.sourceBlock_.workspace;
|
||||
var quietInput = opt_quietInput || false;
|
||||
if (!quietInput && (Blockly.utils.userAgent.MOBILE ||
|
||||
|
||||
@@ -731,7 +731,7 @@ Blockly.Gesture.prototype.doBubbleClick_ = function() {
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.doFieldClick_ = function() {
|
||||
this.startField_.showEditor();
|
||||
this.startField_.showEditor(this.mostRecentEvent_);
|
||||
this.bringBlockToFront_();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user