mirror of
https://github.com/scratchfoundation/scratch-blocks.git
synced 2025-08-28 22:10:31 -04:00
Text+drop-downs and number+drop-downs (#662)
* Don't force text-centering around FIELD_WIDTH if arrow present * Add dark arrow asset * Refactor FieldNumber restrictor generator to be static * Allow disabling of FieldDropDown colour changing * Add FieldTextDropDown and FieldNumberDropDown * Add number drop-downs to list blocks * Add docs * Update `setArgType` -> `addArgType` * Ensure arrow only created once * Update list index min * Refactor shared components of num restriction * Line breaks * Clear touch identifier * Clear touch identifier when text drop-down closed * Inheritance simplification
This commit is contained in:
parent
38ae0dcaf8
commit
d65c274652
12 changed files with 374 additions and 49 deletions
|
@ -206,6 +206,66 @@ Blockly.Blocks['data_listcontents'] = {
|
|||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['data_listindexall'] = {
|
||||
/**
|
||||
* List index menu, with all option.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": "%1",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_numberdropdown",
|
||||
"name": "INDEX",
|
||||
"value": "1",
|
||||
"min": 1,
|
||||
"precision": 1,
|
||||
"options": [
|
||||
["1", "1"],
|
||||
["last", "last"],
|
||||
["all", "all"]
|
||||
]
|
||||
}
|
||||
],
|
||||
"output": "String",
|
||||
"category": Blockly.Categories.data,
|
||||
"outputShape": Blockly.OUTPUT_SHAPE_ROUND,
|
||||
"colour": Blockly.Colours.textField
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['data_listindexrandom'] = {
|
||||
/**
|
||||
* List index menu, with random option.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": "%1",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_numberdropdown",
|
||||
"name": "INDEX",
|
||||
"value": "1",
|
||||
"min": 1,
|
||||
"precision": 1,
|
||||
"options": [
|
||||
["1", "1"],
|
||||
["last", "last"],
|
||||
["random", "random"]
|
||||
]
|
||||
}
|
||||
],
|
||||
"output": "String",
|
||||
"category": Blockly.Categories.data,
|
||||
"outputShape": Blockly.OUTPUT_SHAPE_ROUND,
|
||||
"colour": Blockly.Colours.textField
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['data_addtolist'] = {
|
||||
/**
|
||||
* Block to add item to list.
|
||||
|
|
|
@ -132,7 +132,7 @@ Blockly.Block = function(workspace, prototypeName, opt_id) {
|
|||
* @private
|
||||
*/
|
||||
this.outputShape_ = null;
|
||||
|
||||
|
||||
/**
|
||||
* @type {?string}
|
||||
* @private
|
||||
|
@ -1243,6 +1243,18 @@ Blockly.Block.prototype.interpolate_ = function(message, args, lastDummyAlign) {
|
|||
field.setSpellcheck(element['spellcheck']);
|
||||
}
|
||||
break;
|
||||
case 'field_textdropdown':
|
||||
field = new Blockly.FieldTextDropdown(element['text'], element['options']);
|
||||
if (typeof element['spellcheck'] == 'boolean') {
|
||||
field.setSpellcheck(element['spellcheck']);
|
||||
}
|
||||
break;
|
||||
case 'field_numberdropdown':
|
||||
field = new Blockly.FieldNumberDropdown(
|
||||
element['value'], element['options'],
|
||||
element['min'], element['max'], element['precision']
|
||||
);
|
||||
break;
|
||||
case 'field_angle':
|
||||
field = new Blockly.FieldAngle(element['angle']);
|
||||
break;
|
||||
|
|
|
@ -40,7 +40,9 @@ goog.require('Blockly.FieldDropdown');
|
|||
goog.require('Blockly.FieldIconMenu');
|
||||
goog.require('Blockly.FieldImage');
|
||||
goog.require('Blockly.FieldTextInput');
|
||||
goog.require('Blockly.FieldTextDropdown');
|
||||
goog.require('Blockly.FieldNumber');
|
||||
goog.require('Blockly.FieldNumberDropdown');
|
||||
goog.require('Blockly.FieldVariable');
|
||||
goog.require('Blockly.Generator');
|
||||
goog.require('Blockly.Msg');
|
||||
|
|
|
@ -198,6 +198,10 @@ Blockly.Css.CONTENT = [
|
|||
'-webkit-transform-origin: 0 0;',
|
||||
'}',
|
||||
|
||||
'.blocklyTextDropDownArrow {',
|
||||
'position: absolute;',
|
||||
'}',
|
||||
|
||||
'.blocklyNonSelectable {',
|
||||
'user-select: none;',
|
||||
'-moz-user-select: none;',
|
||||
|
|
|
@ -366,8 +366,9 @@ Blockly.Field.prototype.render_ = function() {
|
|||
}
|
||||
// In a text-editing shadow block's field,
|
||||
// if half the text length is not at least center of
|
||||
// visible field (FIELD_WIDTH), center it there instead.
|
||||
if (this.sourceBlock_.isShadow()) {
|
||||
// visible field (FIELD_WIDTH), center it there instead,
|
||||
// unless there is a drop-down arrow.
|
||||
if (this.sourceBlock_.isShadow() && !this.positionArrow) {
|
||||
var minOffset = Blockly.BlockSvg.FIELD_WIDTH / 2;
|
||||
if (this.sourceBlock_.RTL) {
|
||||
// X position starts at the left edge of the block, in both RTL and LTR.
|
||||
|
|
|
@ -129,6 +129,7 @@ Blockly.FieldDropdown.prototype.init = function() {
|
|||
* @private
|
||||
*/
|
||||
Blockly.FieldDropdown.prototype.showEditor_ = function() {
|
||||
this.dropDownOpen_ = true;
|
||||
// If there is an existing drop-down someone else owns, hide it immediately and clear it.
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
Blockly.DropDownDiv.clearContent();
|
||||
|
@ -224,12 +225,14 @@ Blockly.FieldDropdown.prototype.showEditor_ = function() {
|
|||
menuDom.focus();
|
||||
|
||||
// Update colour to look selected.
|
||||
if (this.sourceBlock_.isShadow()) {
|
||||
this.savedPrimary_ = this.sourceBlock_.getColour();
|
||||
this.sourceBlock_.setColour(this.sourceBlock_.getColourTertiary(),
|
||||
this.sourceBlock_.getColourSecondary(), this.sourceBlock_.getColourTertiary());
|
||||
} else if (this.box_) {
|
||||
this.box_.setAttribute('fill', this.sourceBlock_.getColourTertiary());
|
||||
if (!this.disableColourChange_) {
|
||||
if (this.sourceBlock_.isShadow()) {
|
||||
this.savedPrimary_ = this.sourceBlock_.getColour();
|
||||
this.sourceBlock_.setColour(this.sourceBlock_.getColourTertiary(),
|
||||
this.sourceBlock_.getColourSecondary(), this.sourceBlock_.getColourTertiary());
|
||||
} else if (this.box_) {
|
||||
this.box_.setAttribute('fill', this.sourceBlock_.getColourTertiary());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -237,12 +240,15 @@ Blockly.FieldDropdown.prototype.showEditor_ = function() {
|
|||
* Callback for when the drop-down is hidden.
|
||||
*/
|
||||
Blockly.FieldDropdown.prototype.onHide = function() {
|
||||
this.dropDownOpen_ = false;
|
||||
// Update colour to look selected.
|
||||
if (this.sourceBlock_.isShadow()) {
|
||||
this.sourceBlock_.setColour(this.savedPrimary_,
|
||||
this.sourceBlock_.getColourSecondary(), this.sourceBlock_.getColourTertiary());
|
||||
} else if (this.box_) {
|
||||
this.box_.setAttribute('fill', this.sourceBlock_.getColour());
|
||||
if (!this.disableColourChange_) {
|
||||
if (this.sourceBlock_.isShadow()) {
|
||||
this.sourceBlock_.setColour(this.savedPrimary_,
|
||||
this.sourceBlock_.getColourSecondary(), this.sourceBlock_.getColourTertiary());
|
||||
} else if (this.box_) {
|
||||
this.box_.setAttribute('fill', this.sourceBlock_.getColour());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -366,6 +372,11 @@ Blockly.FieldDropdown.prototype.setText = function(text) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Position a drop-down arrow at the appropriate location at render-time.
|
||||
* @param {number} x X position the arrow is being rendered at, in px.
|
||||
* @return {number} Amount of space the arrow is taking up, in px.
|
||||
*/
|
||||
Blockly.FieldDropdown.prototype.positionArrow = function(x) {
|
||||
var addedWidth = 0;
|
||||
if (this.sourceBlock_.RTL) {
|
||||
|
|
|
@ -30,25 +30,6 @@ goog.require('Blockly.FieldTextInput');
|
|||
goog.require('goog.math');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* Return an appropriate restrictor, depending on whether this FieldNumber
|
||||
* allows decimal or negative numbers.
|
||||
* @param {boolean} decimalAllowed Whether number may have decimal/float component.
|
||||
* @param {boolean} negativeAllowed Whether number may be negative.
|
||||
* @return {!RegExp} Regular expression for this FieldNumber's restrictor.
|
||||
*/
|
||||
var getNumRestrictor = function(decimalAllowed, negativeAllowed) {
|
||||
var pattern = "[\\d]"; // Always allow digits.
|
||||
if (decimalAllowed) {
|
||||
pattern += "|[\\.]";
|
||||
}
|
||||
if (negativeAllowed) {
|
||||
pattern += "|[-]";
|
||||
}
|
||||
return new RegExp(pattern);
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for an editable number field.
|
||||
* In scratch-blocks, the min/max/precision properties are only used
|
||||
|
@ -67,11 +48,7 @@ var getNumRestrictor = function(decimalAllowed, negativeAllowed) {
|
|||
* @constructor
|
||||
*/
|
||||
Blockly.FieldNumber = function(value, opt_min, opt_max, opt_precision, opt_validator) {
|
||||
this.decimalAllowed_ = (typeof opt_precision == 'undefined') || isNaN(opt_precision) ||
|
||||
(opt_precision == 0) ||
|
||||
(Math.floor(opt_precision) != opt_precision);
|
||||
this.negativeAllowed_ = (typeof opt_min == 'undefined') || isNaN(opt_min) || opt_min < 0;
|
||||
var numRestrictor = getNumRestrictor(this.decimalAllowed_, this.negativeAllowed_);
|
||||
var numRestrictor = this.getNumRestrictor(opt_min, opt_max, opt_precision);
|
||||
Blockly.FieldNumber.superClass_.constructor.call(this, value, opt_validator, numRestrictor);
|
||||
this.addArgType('number');
|
||||
};
|
||||
|
@ -126,6 +103,28 @@ Blockly.FieldNumber.NUMPAD_DELETE_ICON = 'data:image/svg+xml;utf8,' +
|
|||
*/
|
||||
Blockly.FieldNumber.activeField_ = null;
|
||||
|
||||
/**
|
||||
* Return an appropriate restrictor, depending on whether this FieldNumber
|
||||
* allows decimal or negative numbers.
|
||||
* @param {number|string|undefined} opt_min Minimum value.
|
||||
* @param {number|string|undefined} opt_max Maximum value.
|
||||
* @param {number|string|undefined} opt_precision Precision for value.
|
||||
* @return {!RegExp} Regular expression for this FieldNumber's restrictor.
|
||||
*/
|
||||
Blockly.FieldNumber.prototype.getNumRestrictor = function(opt_min, opt_max, opt_precision) {
|
||||
this.decimalAllowed_ = (typeof opt_precision == 'undefined') || isNaN(opt_precision) ||
|
||||
(opt_precision == 0) || (Math.floor(opt_precision) != opt_precision);
|
||||
this.negativeAllowed_ = (typeof opt_min == 'undefined') || isNaN(opt_min) || opt_min < 0;
|
||||
var pattern = "[\\d]"; // Always allow digits.
|
||||
if (this.decimalAllowed_) {
|
||||
pattern += "|[\\.]";
|
||||
}
|
||||
if (this.negativeAllowed_) {
|
||||
pattern += "|[-]";
|
||||
}
|
||||
return new RegExp(pattern);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the constraints for this field.
|
||||
* @param {number=} opt_min Minimum number allowed.
|
||||
|
@ -134,8 +133,7 @@ Blockly.FieldNumber.activeField_ = null;
|
|||
*/
|
||||
Blockly.FieldNumber.prototype.setConstraints_ = function(opt_min, opt_max, opt_precision) {
|
||||
this.decimalAllowed_ = (typeof opt_precision == 'undefined') || isNaN(opt_precision) ||
|
||||
(opt_precision == 0) ||
|
||||
(Math.floor(opt_precision) != opt_precision);
|
||||
(opt_precision == 0) || (Math.floor(opt_precision) != opt_precision);
|
||||
this.negativeAllowed_ = (typeof opt_min == 'undefined') || isNaN(opt_min) || opt_min < 0;
|
||||
};
|
||||
|
||||
|
|
58
core/field_numberdropdown.js
Normal file
58
core/field_numberdropdown.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2013 Google Inc.
|
||||
* https://developers.google.com/blockly/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Combination number + drop-down field
|
||||
* @author tmickel@mit.edu (Tim Mickel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.FieldNumberDropdown');
|
||||
|
||||
goog.require('Blockly.FieldTextDropdown');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a combination number + drop-down field.
|
||||
* @param {number|string} value The initial content of the field.
|
||||
* @param {(!Array.<!Array.<string>>|!Function)} menuGenerator An array of
|
||||
* options for a dropdown list, or a function which generates these options.
|
||||
* @param {number|string|undefined} opt_min Minimum value.
|
||||
* @param {number|string|undefined} opt_max Maximum value.
|
||||
* @param {number|string|undefined} opt_precision Precision for value.
|
||||
* @param {Function=} opt_validator An optional function that is called
|
||||
* to validate any constraints on what the user entered. Takes the new
|
||||
* text as an argument and returns the accepted text or null to abort
|
||||
* the change.
|
||||
* @extends {Blockly.FieldTextInput}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.FieldNumberDropdown = function(value, menuGenerator, opt_min, opt_max, opt_precision, opt_validator) {
|
||||
var numRestrictor = Blockly.FieldNumber.prototype.getNumRestrictor.call(
|
||||
this, opt_min, opt_max, opt_precision
|
||||
);
|
||||
Blockly.FieldNumberDropdown.superClass_.constructor.call(
|
||||
this, value, menuGenerator, opt_validator, numRestrictor
|
||||
);
|
||||
this.addArgType('numberdropdown');
|
||||
};
|
||||
|
||||
goog.inherits(Blockly.FieldNumberDropdown, Blockly.FieldTextDropdown);
|
141
core/field_textdropdown.js
Normal file
141
core/field_textdropdown.js
Normal file
|
@ -0,0 +1,141 @@
|
|||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2013 Google Inc.
|
||||
* https://developers.google.com/blockly/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Combination text + drop-down field
|
||||
* @author tmickel@mit.edu (Tim Mickel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.FieldTextDropdown');
|
||||
|
||||
goog.require('Blockly.DropDownDiv');
|
||||
goog.require('Blockly.FieldDropdown');
|
||||
goog.require('Blockly.FieldTextInput');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a combination text + drop-down field.
|
||||
* @param {string} text The initial content of the text field.
|
||||
* @param {(!Array.<!Array.<string>>|!Function)} menuGenerator An array of
|
||||
* options for a dropdown list, or a function which generates these options.
|
||||
* @param {Function=} opt_validator An optional function that is called
|
||||
* to validate any constraints on what the user entered. Takes the new
|
||||
* text as an argument and returns the accepted text or null to abort
|
||||
* the change.
|
||||
* @param {RegExp=} opt_restrictor An optional regular expression to restrict
|
||||
* typed text to. Text that doesn't match the restrictor will never show
|
||||
* in the text field.
|
||||
* @extends {Blockly.FieldTextInput}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.FieldTextDropdown = function(text, menuGenerator, opt_validator, opt_restrictor) {
|
||||
this.menuGenerator_ = menuGenerator;
|
||||
Blockly.FieldDropdown.prototype.trimOptions_.call(this);
|
||||
Blockly.FieldTextDropdown.superClass_.constructor.call(this, text, opt_validator, opt_restrictor);
|
||||
this.addArgType('textdropdown');
|
||||
};
|
||||
goog.inherits(Blockly.FieldTextDropdown, Blockly.FieldTextInput);
|
||||
|
||||
/**
|
||||
* Install this text drop-down field on a block.
|
||||
*/
|
||||
Blockly.FieldTextDropdown.prototype.init = function() {
|
||||
Blockly.FieldTextDropdown.superClass_.init.call(this);
|
||||
// Add dropdown arrow: "option ▾" (LTR) or "▾ אופציה" (RTL)
|
||||
// Positioned on render, after text size is calculated.
|
||||
if (!this.arrow_) {
|
||||
/** @type {Number} */
|
||||
this.arrowSize_ = 12;
|
||||
/** @type {Number} */
|
||||
this.arrowX_ = 0;
|
||||
/** @type {Number} */
|
||||
this.arrowY_ = 11;
|
||||
this.arrow_ = Blockly.createSvgElement('image', {
|
||||
'height': this.arrowSize_ + 'px',
|
||||
'width': this.arrowSize_ + 'px'
|
||||
});
|
||||
this.arrow_.setAttributeNS('http://www.w3.org/1999/xlink',
|
||||
'xlink:href', Blockly.mainWorkspace.options.pathToMedia + 'dropdown-arrow-dark.svg');
|
||||
this.arrow_.style.cursor = 'pointer';
|
||||
this.fieldGroup_.appendChild(this.arrow_);
|
||||
this.mouseUpWrapper_ =
|
||||
Blockly.bindEvent_(this.arrow_, 'mouseup', this,
|
||||
this.showDropdown_);
|
||||
}
|
||||
// Prevent the drop-down handler from changing the field colour on open.
|
||||
this.disableColourChange_ = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the input widget if this input is being deleted.
|
||||
*/
|
||||
Blockly.FieldTextDropdown.prototype.dispose = function() {
|
||||
if (this.mouseUpWrapper_) {
|
||||
Blockly.unbindEvent_(this.mouseUpWrapper_);
|
||||
this.mouseUpWrapper_ = null;
|
||||
Blockly.Touch.clearTouchIdentifier();
|
||||
}
|
||||
Blockly.FieldTextDropdown.superClass_.dispose.call(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* If the drop-down isn't open, show the text editor.
|
||||
*/
|
||||
Blockly.FieldTextDropdown.prototype.showEditor_ = function() {
|
||||
if (!this.dropDownOpen_) {
|
||||
Blockly.FieldTextDropdown.superClass_.showEditor_.call(this, null, null,
|
||||
true, function() {
|
||||
// When the drop-down arrow is clicked, hide text editor and show drop-down.
|
||||
Blockly.WidgetDiv.hide();
|
||||
this.showDropdown_();
|
||||
Blockly.Touch.clearTouchIdentifier();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a list of the options for this dropdown.
|
||||
* See: Blockly.FieldDropDown.prototype.getOptions_.
|
||||
* @return {!Array.<!Array.<string>>} Array of option tuples:
|
||||
* (human-readable text, language-neutral name).
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldTextDropdown.prototype.getOptions_ = Blockly.FieldDropdown.prototype.getOptions_;
|
||||
|
||||
/**
|
||||
* Position a drop-down arrow at the appropriate location at render-time.
|
||||
* See: Blockly.FieldDropDown.prototype.positionArrow.
|
||||
* @param {number} x X position the arrow is being rendered at, in px.
|
||||
* @return {number} Amount of space the arrow is taking up, in px.
|
||||
*/
|
||||
Blockly.FieldTextDropdown.prototype.positionArrow = Blockly.FieldDropdown.prototype.positionArrow;
|
||||
|
||||
/**
|
||||
* Create the dropdown menu.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldTextDropdown.prototype.showDropdown_ = Blockly.FieldDropdown.prototype.showEditor_;
|
||||
|
||||
/**
|
||||
* Callback when the drop-down menu is hidden.
|
||||
*/
|
||||
Blockly.FieldTextDropdown.prototype.onHide = Blockly.FieldDropdown.prototype.onHide;
|
|
@ -152,9 +152,12 @@ Blockly.FieldTextInput.prototype.setRestrictor = function(restrictor) {
|
|||
* focus. Defaults to false.
|
||||
* @param {boolean=} opt_readOnly True if editor should be created with HTML
|
||||
* input set to read-only, to prevent virtual keyboards.
|
||||
* @param {boolean=} opt_withArrow True to show drop-down arrow in text editor.
|
||||
* @param {Function=} opt_arrowCallback Callback for when drop-down arrow clicked.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput, opt_readOnly) {
|
||||
Blockly.FieldTextInput.prototype.showEditor_ = function(
|
||||
opt_quietInput, opt_readOnly, opt_withArrow, opt_arrowCallback) {
|
||||
this.workspace_ = this.sourceBlock_.workspace;
|
||||
var quietInput = opt_quietInput || false;
|
||||
var readOnly = opt_readOnly || false;
|
||||
|
@ -175,6 +178,36 @@ Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput, opt_read
|
|||
Blockly.FieldTextInput.htmlInput_ = htmlInput;
|
||||
div.appendChild(htmlInput);
|
||||
|
||||
if (opt_withArrow) {
|
||||
// Move text in input to account for displayed drop-down arrow.
|
||||
if (this.sourceBlock_.RTL) {
|
||||
htmlInput.style.paddingLeft = (this.arrowSize_+ Blockly.BlockSvg.DROPDOWN_ARROW_PADDING) + 'px';
|
||||
} else {
|
||||
htmlInput.style.paddingRight = (this.arrowSize_ + Blockly.BlockSvg.DROPDOWN_ARROW_PADDING) + 'px';
|
||||
}
|
||||
// Create the arrow.
|
||||
var dropDownArrow =
|
||||
goog.dom.createDom(goog.dom.TagName.IMG, 'blocklyTextDropDownArrow');
|
||||
dropDownArrow.setAttribute('src',
|
||||
Blockly.mainWorkspace.options.pathToMedia + 'dropdown-arrow-dark.svg');
|
||||
dropDownArrow.style.width = this.arrowSize_ + 'px';
|
||||
dropDownArrow.style.height = this.arrowSize_ + 'px';
|
||||
dropDownArrow.style.top = this.arrowY_ + 'px';
|
||||
dropDownArrow.style.cursor = 'pointer';
|
||||
// Magic number for positioning the drop-down arrow on top of the text editor.
|
||||
var dropdownArrowMagic = '11px';
|
||||
if (this.sourceBlock_.RTL) {
|
||||
dropDownArrow.style.left = dropdownArrowMagic;
|
||||
} else {
|
||||
dropDownArrow.style.right = dropdownArrowMagic;
|
||||
}
|
||||
if (opt_arrowCallback) {
|
||||
htmlInput.dropDownArrowMouseWrapper_ = Blockly.bindEvent_(dropDownArrow,
|
||||
'mousedown', this, opt_arrowCallback);
|
||||
}
|
||||
div.appendChild(dropDownArrow);
|
||||
}
|
||||
|
||||
htmlInput.value = htmlInput.defaultValue = this.text_;
|
||||
htmlInput.oldValue_ = null;
|
||||
this.validate_();
|
||||
|
@ -379,6 +412,7 @@ Blockly.FieldTextInput.prototype.resizeEditor_ = function() {
|
|||
if (this.sourceBlock_.RTL) {
|
||||
xy.x += width;
|
||||
xy.x -= div.offsetWidth * scale;
|
||||
xy.x += 1 * scale;
|
||||
}
|
||||
// Shift by a few pixels to line up exactly.
|
||||
xy.y += 1 * scale;
|
||||
|
@ -438,6 +472,9 @@ Blockly.FieldTextInput.prototype.widgetDispose_ = function() {
|
|||
Blockly.unbindEvent_(htmlInput.onKeyUpWrapper_);
|
||||
Blockly.unbindEvent_(htmlInput.onKeyPressWrapper_);
|
||||
Blockly.unbindEvent_(htmlInput.onInputWrapper_);
|
||||
if (htmlInput.dropDownArrowMouseWrapper_) {
|
||||
Blockly.unbindEvent_(htmlInput.dropDownArrowMouseWrapper_);
|
||||
}
|
||||
thisField.workspace_.removeChangeListener(
|
||||
htmlInput.onWorkspaceChangeWrapper_);
|
||||
|
||||
|
|
1
media/dropdown-arrow-dark.svg
Normal file
1
media/dropdown-arrow-dark.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="12.71" height="8.79" viewBox="0 0 12.71 8.79"><title>dropdown-arrow</title><g opacity="0.1"><path d="M12.71,2.44A2.41,2.41,0,0,1,12,4.16L8.08,8.08a2.45,2.45,0,0,1-3.45,0L0.72,4.16A2.42,2.42,0,0,1,0,2.44,2.48,2.48,0,0,1,.71.71C1,0.47,1.43,0,6.36,0S11.75,0.46,12,.71A2.44,2.44,0,0,1,12.71,2.44Z" fill="#231f20"/></g><path d="M6.36,7.79a1.43,1.43,0,0,1-1-.42L1.42,3.45a1.44,1.44,0,0,1,0-2c0.56-.56,9.31-0.56,9.87,0a1.44,1.44,0,0,1,0,2L7.37,7.37A1.43,1.43,0,0,1,6.36,7.79Z" fill="#575E75"/></svg>
|
After Width: | Height: | Size: 573 B |
|
@ -750,15 +750,15 @@
|
|||
</block>
|
||||
<block type="data_deleteoflist">
|
||||
<value name="INDEX">
|
||||
<shadow type="math_integer">
|
||||
<field name="NUM">1</field>
|
||||
<shadow type="data_listindexall">
|
||||
<field name="INDEX">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="data_insertatlist">
|
||||
<value name="INDEX">
|
||||
<shadow type="math_integer">
|
||||
<field name="NUM">1</field>
|
||||
<shadow type="data_listindexrandom">
|
||||
<field name="INDEX">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="ITEM">
|
||||
|
@ -769,8 +769,8 @@
|
|||
</block>
|
||||
<block type="data_replaceitemoflist">
|
||||
<value name="INDEX">
|
||||
<shadow type="math_integer">
|
||||
<field name="NUM">1</field>
|
||||
<shadow type="data_listindexrandom">
|
||||
<field name="INDEX">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="ITEM">
|
||||
|
@ -781,8 +781,8 @@
|
|||
</block>
|
||||
<block type="data_itemoflist">
|
||||
<value name="INDEX">
|
||||
<shadow type="math_integer">
|
||||
<field name="NUM">1</field>
|
||||
<shadow type="data_listindexrandom">
|
||||
<field name="INDEX">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue