blockly 7.20211209.2 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/blockly.d.ts +18963 -18432
- package/blockly.min.js +852 -844
- package/blockly_compressed.js +669 -664
- package/blockly_compressed.js.map +1 -1
- package/blocks/blocks.js +47 -0
- package/blocks/colour.js +13 -3
- package/blocks/lists.js +22 -13
- package/blocks/logic.js +13 -3
- package/blocks/loops.js +24 -11
- package/blocks/math.js +12 -3
- package/blocks/procedures.js +41 -27
- package/blocks/text.js +22 -13
- package/blocks/variables.js +14 -3
- package/blocks/variables_dynamic.js +13 -3
- package/blocks_compressed.js +146 -141
- package/blocks_compressed.js.map +1 -1
- package/core/block.js +1869 -1814
- package/core/block_drag_surface.js +201 -200
- package/core/block_dragger.js +377 -373
- package/core/block_svg.js +1593 -1479
- package/core/blockly.js +8 -22
- package/core/blocks.js +9 -2
- package/core/browser_events.js +22 -5
- package/core/bubble.js +841 -797
- package/core/bubble_dragger.js +213 -206
- package/core/bump_objects.js +2 -2
- package/core/clipboard.js +9 -9
- package/core/comment.js +353 -332
- package/core/common.js +46 -17
- package/core/component_manager.js +181 -174
- package/core/config.js +87 -0
- package/core/connection.js +595 -584
- package/core/connection_checker.js +242 -244
- package/core/connection_db.js +235 -230
- package/core/contextmenu.js +9 -6
- package/core/contextmenu_items.js +1 -2
- package/core/contextmenu_registry.js +93 -89
- package/core/css.js +474 -474
- package/core/delete_area.js +45 -42
- package/core/drag_target.js +57 -56
- package/core/dropdowndiv.js +153 -163
- package/core/events/events.js +2 -2
- package/core/events/events_abstract.js +89 -77
- package/core/events/events_block_base.js +37 -36
- package/core/events/events_block_change.js +130 -124
- package/core/events/events_block_create.js +73 -71
- package/core/events/events_block_delete.js +84 -82
- package/core/events/events_block_drag.js +50 -49
- package/core/events/events_block_move.js +147 -140
- package/core/events/events_bubble_open.js +51 -50
- package/core/events/events_click.js +48 -44
- package/core/events/events_comment_base.js +72 -69
- package/core/events/events_comment_change.js +63 -61
- package/core/events/events_comment_create.js +44 -42
- package/core/events/events_comment_delete.js +42 -40
- package/core/events/events_comment_move.js +106 -104
- package/core/events/events_marker_move.js +65 -64
- package/core/events/events_selected.js +46 -45
- package/core/events/events_theme_change.js +36 -35
- package/core/events/events_toolbox_item_select.js +46 -45
- package/core/events/events_trashcan_open.js +37 -36
- package/core/events/events_ui.js +47 -46
- package/core/events/events_ui_base.js +30 -29
- package/core/events/events_var_base.js +37 -36
- package/core/events/events_var_create.js +50 -48
- package/core/events/events_var_delete.js +50 -48
- package/core/events/events_var_rename.js +51 -49
- package/core/events/events_viewport.js +66 -65
- package/core/events/utils.js +29 -14
- package/core/events/workspace_events.js +49 -55
- package/core/extensions.js +4 -3
- package/core/field.js +1061 -997
- package/core/field_angle.js +462 -442
- package/core/field_checkbox.js +194 -182
- package/core/field_colour.js +519 -505
- package/core/field_dropdown.js +617 -598
- package/core/field_image.js +229 -220
- package/core/field_label.js +102 -91
- package/core/field_label_serializable.js +42 -41
- package/core/field_multilineinput.js +372 -358
- package/core/field_number.js +272 -253
- package/core/field_textinput.js +499 -467
- package/core/field_variable.js +458 -420
- package/core/flyout_base.js +1005 -952
- package/core/flyout_button.js +277 -260
- package/core/flyout_horizontal.js +304 -302
- package/core/flyout_metrics_manager.js +64 -64
- package/core/flyout_vertical.js +306 -300
- package/core/generator.js +459 -446
- package/core/gesture.js +829 -813
- package/core/grid.js +166 -163
- package/core/icon.js +168 -159
- package/core/inject.js +7 -5
- package/core/input.js +257 -248
- package/core/insertion_marker_manager.js +655 -624
- package/core/internal_constants.js +0 -129
- package/core/keyboard_nav/ast_node.js +605 -596
- package/core/keyboard_nav/basic_cursor.js +166 -165
- package/core/keyboard_nav/cursor.js +99 -97
- package/core/keyboard_nav/marker.js +83 -79
- package/core/keyboard_nav/tab_navigate_cursor.js +18 -23
- package/core/marker_manager.js +153 -141
- package/core/menu.js +377 -372
- package/core/menuitem.js +223 -217
- package/core/metrics_manager.js +403 -390
- package/core/mutator.js +468 -437
- package/core/names.js +229 -188
- package/core/options.js +290 -284
- package/core/procedures.js +29 -17
- package/core/registry.js +19 -16
- package/core/rendered_connection.js +482 -463
- package/core/renderers/common/block_rendering.js +9 -3
- package/core/renderers/common/constants.js +1119 -1112
- package/core/renderers/common/debug.js +14 -0
- package/core/renderers/common/debugger.js +338 -316
- package/core/renderers/common/drawer.js +380 -370
- package/core/renderers/common/i_path_object.js +2 -2
- package/core/renderers/common/info.js +626 -618
- package/core/renderers/common/marker_svg.js +579 -541
- package/core/renderers/common/path_object.js +203 -200
- package/core/renderers/common/renderer.js +220 -218
- package/core/renderers/geras/constants.js +36 -36
- package/core/renderers/geras/drawer.js +155 -147
- package/core/renderers/geras/highlight_constants.js +244 -238
- package/core/renderers/geras/highlighter.js +231 -179
- package/core/renderers/geras/info.js +392 -369
- package/core/renderers/geras/measurables/inline_input.js +25 -19
- package/core/renderers/geras/measurables/statement_input.js +23 -17
- package/core/renderers/geras/path_object.js +106 -121
- package/core/renderers/geras/renderer.js +96 -98
- package/core/renderers/measurables/base.js +30 -18
- package/core/renderers/measurables/bottom_row.js +83 -80
- package/core/renderers/measurables/connection.js +22 -15
- package/core/renderers/measurables/external_value_input.js +35 -22
- package/core/renderers/measurables/field.js +35 -20
- package/core/renderers/measurables/hat.js +18 -13
- package/core/renderers/measurables/icon.js +24 -17
- package/core/renderers/measurables/in_row_spacer.js +15 -13
- package/core/renderers/measurables/inline_input.js +43 -33
- package/core/renderers/measurables/input_connection.js +41 -28
- package/core/renderers/measurables/input_row.js +50 -44
- package/core/renderers/measurables/jagged_edge.js +14 -12
- package/core/renderers/measurables/next_connection.js +16 -14
- package/core/renderers/measurables/output_connection.js +26 -20
- package/core/renderers/measurables/previous_connection.js +16 -15
- package/core/renderers/measurables/round_corner.js +20 -18
- package/core/renderers/measurables/row.js +184 -168
- package/core/renderers/measurables/spacer_row.js +38 -23
- package/core/renderers/measurables/square_corner.js +18 -16
- package/core/renderers/measurables/statement_input.js +23 -20
- package/core/renderers/measurables/top_row.js +88 -85
- package/core/renderers/minimalist/constants.js +8 -7
- package/core/renderers/minimalist/drawer.js +11 -10
- package/core/renderers/minimalist/info.js +18 -18
- package/core/renderers/minimalist/renderer.js +40 -39
- package/core/renderers/thrasos/info.js +258 -248
- package/core/renderers/thrasos/renderer.js +20 -20
- package/core/renderers/zelos/constants.js +898 -873
- package/core/renderers/zelos/drawer.js +186 -169
- package/core/renderers/zelos/info.js +502 -479
- package/core/renderers/zelos/marker_svg.js +129 -115
- package/core/renderers/zelos/measurables/bottom_row.js +31 -30
- package/core/renderers/zelos/measurables/inputs.js +22 -21
- package/core/renderers/zelos/measurables/row_elements.js +14 -13
- package/core/renderers/zelos/measurables/top_row.js +34 -33
- package/core/renderers/zelos/path_object.js +181 -180
- package/core/renderers/zelos/renderer.js +91 -92
- package/core/scrollbar.js +759 -713
- package/core/scrollbar_pair.js +250 -245
- package/core/serialization/blocks.js +19 -9
- package/core/serialization/workspaces.js +3 -2
- package/core/shortcut_registry.js +286 -277
- package/core/sprites.js +31 -0
- package/core/theme.js +135 -141
- package/core/theme_manager.js +147 -143
- package/core/toolbox/category.js +602 -576
- package/core/toolbox/collapsible_category.js +226 -227
- package/core/toolbox/separator.js +70 -61
- package/core/toolbox/toolbox.js +934 -927
- package/core/toolbox/toolbox_item.js +115 -99
- package/core/tooltip.js +108 -35
- package/core/touch.js +8 -3
- package/core/touch_gesture.js +254 -251
- package/core/trashcan.js +606 -595
- package/core/utils/coordinate.js +97 -95
- package/core/utils/dom.js +2 -2
- package/core/utils/global.js +2 -0
- package/core/utils/rect.js +41 -37
- package/core/utils/sentinel.js +25 -0
- package/core/utils/size.js +30 -27
- package/core/utils/svg.js +18 -16
- package/core/variable_map.js +325 -341
- package/core/variable_model.js +55 -54
- package/core/variables.js +9 -2
- package/core/variables_dynamic.js +3 -1
- package/core/warning.js +126 -120
- package/core/widgetdiv.js +4 -4
- package/core/workspace.js +685 -664
- package/core/workspace_audio.js +124 -118
- package/core/workspace_comment.js +308 -298
- package/core/workspace_comment_svg.js +1029 -951
- package/core/workspace_drag_surface_svg.js +147 -140
- package/core/workspace_dragger.js +70 -71
- package/core/workspace_svg.js +2322 -2297
- package/core/xml.js +30 -20
- package/core/zoom_controls.js +431 -439
- package/dart_compressed.js +40 -43
- package/dart_compressed.js.map +1 -1
- package/generators/dart/colour.js +56 -64
- package/generators/dart/lists.js +61 -50
- package/generators/dart/math.js +160 -148
- package/generators/dart/text.js +83 -61
- package/generators/javascript/colour.js +37 -34
- package/generators/javascript/lists.js +50 -43
- package/generators/javascript/math.js +123 -139
- package/generators/javascript/text.js +67 -81
- package/generators/lua/colour.js +25 -23
- package/generators/lua/lists.js +97 -69
- package/generators/lua/logic.js +1 -2
- package/generators/lua/math.js +182 -144
- package/generators/lua/text.js +116 -99
- package/generators/php/colour.js +38 -32
- package/generators/php/lists.js +109 -89
- package/generators/php/math.js +90 -81
- package/generators/php/text.js +63 -61
- package/generators/python/colour.js +18 -18
- package/generators/python/lists.js +38 -30
- package/generators/python/loops.js +12 -8
- package/generators/python/math.js +104 -106
- package/generators/python/text.js +34 -30
- package/javascript_compressed.js +37 -39
- package/javascript_compressed.js.map +1 -1
- package/lua_compressed.js +39 -42
- package/lua_compressed.js.map +1 -1
- package/msg/az.js +2 -2
- package/msg/be.js +4 -4
- package/msg/cs.js +15 -15
- package/msg/de.js +1 -1
- package/msg/diq.js +1 -1
- package/msg/eo.js +1 -1
- package/msg/es.js +1 -1
- package/msg/fa.js +1 -1
- package/msg/fr.js +4 -4
- package/msg/he.js +1 -1
- package/msg/hr.js +2 -2
- package/msg/hy.js +2 -2
- package/msg/id.js +12 -12
- package/msg/inh.js +14 -14
- package/msg/ja.js +7 -7
- package/msg/lv.js +29 -29
- package/msg/pa.js +3 -3
- package/msg/smn.js +436 -0
- package/msg/te.js +1 -1
- package/msg/yue.js +1 -1
- package/msg/zh-hans.js +3 -3
- package/msg/zh-hant.js +3 -3
- package/package.json +7 -6
- package/php_compressed.js +38 -42
- package/php_compressed.js.map +1 -1
- package/python_compressed.js +26 -25
- package/python_compressed.js.map +1 -1
- package/blocks/all.js +0 -23
|
@@ -20,428 +20,442 @@ const WidgetDiv = goog.require('Blockly.WidgetDiv');
|
|
|
20
20
|
const aria = goog.require('Blockly.utils.aria');
|
|
21
21
|
const dom = goog.require('Blockly.utils.dom');
|
|
22
22
|
const fieldRegistry = goog.require('Blockly.fieldRegistry');
|
|
23
|
-
const object = goog.require('Blockly.utils.object');
|
|
24
23
|
const parsing = goog.require('Blockly.utils.parsing');
|
|
25
24
|
const userAgent = goog.require('Blockly.utils.userAgent');
|
|
26
25
|
const {FieldTextInput} = goog.require('Blockly.FieldTextInput');
|
|
27
26
|
const {Field} = goog.require('Blockly.Field');
|
|
28
27
|
const {KeyCodes} = goog.require('Blockly.utils.KeyCodes');
|
|
28
|
+
/* eslint-disable-next-line no-unused-vars */
|
|
29
|
+
const {Sentinel} = goog.requireType('Blockly.utils.Sentinel');
|
|
29
30
|
const {Svg} = goog.require('Blockly.utils.Svg');
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Class for an editable text area field.
|
|
34
|
-
* @param {string=} opt_value The initial content of the field. Should cast to a
|
|
35
|
-
* string. Defaults to an empty string if null or undefined.
|
|
36
|
-
* @param {Function=} opt_validator An optional function that is called
|
|
37
|
-
* to validate any constraints on what the user entered. Takes the new
|
|
38
|
-
* text as an argument and returns either the accepted text, a replacement
|
|
39
|
-
* text, or null to abort the change.
|
|
40
|
-
* @param {Object=} opt_config A map of options used to configure the field.
|
|
41
|
-
* See the [field creation documentation]{@link
|
|
42
|
-
* https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/multiline-text-input#creation}
|
|
43
|
-
* for a list of properties this parameter supports.
|
|
44
35
|
* @extends {FieldTextInput}
|
|
45
|
-
* @constructor
|
|
46
36
|
* @alias Blockly.FieldMultilineInput
|
|
47
37
|
*/
|
|
48
|
-
|
|
49
|
-
FieldMultilineInput.superClass_.constructor.call(
|
|
50
|
-
this, opt_value, opt_validator, opt_config);
|
|
51
|
-
|
|
38
|
+
class FieldMultilineInput extends FieldTextInput {
|
|
52
39
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
40
|
+
* @param {(string|!Sentinel)=} opt_value The initial content of the
|
|
41
|
+
* field. Should cast to a string. Defaults to an empty string if null or
|
|
42
|
+
* undefined.
|
|
43
|
+
* Also accepts Field.SKIP_SETUP if you wish to skip setup (only used by
|
|
44
|
+
* subclasses that want to handle configuration and setting the field
|
|
45
|
+
* value after their own constructors have run).
|
|
46
|
+
* @param {Function=} opt_validator An optional function that is called
|
|
47
|
+
* to validate any constraints on what the user entered. Takes the new
|
|
48
|
+
* text as an argument and returns either the accepted text, a replacement
|
|
49
|
+
* text, or null to abort the change.
|
|
50
|
+
* @param {Object=} opt_config A map of options used to configure the field.
|
|
51
|
+
* See the [field creation documentation]{@link
|
|
52
|
+
* https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/multiline-text-input#creation}
|
|
53
|
+
* for a list of properties this parameter supports.
|
|
56
54
|
*/
|
|
57
|
-
|
|
55
|
+
constructor(opt_value, opt_validator, opt_config) {
|
|
56
|
+
super(Field.SKIP_SETUP);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The SVG group element that will contain a text element for each text row
|
|
60
|
+
* when initialized.
|
|
61
|
+
* @type {SVGGElement}
|
|
62
|
+
*/
|
|
63
|
+
this.textGroup_ = null;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Defines the maximum number of lines of field.
|
|
67
|
+
* If exceeded, scrolling functionality is enabled.
|
|
68
|
+
* @type {number}
|
|
69
|
+
* @protected
|
|
70
|
+
*/
|
|
71
|
+
this.maxLines_ = Infinity;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Whether Y overflow is currently occurring.
|
|
75
|
+
* @type {boolean}
|
|
76
|
+
* @protected
|
|
77
|
+
*/
|
|
78
|
+
this.isOverflowedY_ = false;
|
|
79
|
+
|
|
80
|
+
if (opt_value === Field.SKIP_SETUP) return;
|
|
81
|
+
if (opt_config) this.configure_(opt_config);
|
|
82
|
+
this.setValue(opt_value);
|
|
83
|
+
if (opt_validator) this.setValidator(opt_validator);
|
|
84
|
+
}
|
|
58
85
|
|
|
59
86
|
/**
|
|
60
|
-
*
|
|
61
|
-
* If exceeded, scrolling functionality is enabled.
|
|
62
|
-
* @type {number}
|
|
63
|
-
* @protected
|
|
87
|
+
* @override
|
|
64
88
|
*/
|
|
65
|
-
|
|
89
|
+
configure_(config) {
|
|
90
|
+
super.configure_(config);
|
|
91
|
+
config.maxLines && this.setMaxLines(config.maxLines);
|
|
92
|
+
}
|
|
66
93
|
|
|
67
94
|
/**
|
|
68
|
-
*
|
|
69
|
-
* @
|
|
70
|
-
*
|
|
95
|
+
* Serializes this field's value to XML. Should only be called by Blockly.Xml.
|
|
96
|
+
* @param {!Element} fieldElement The element to populate with info about the
|
|
97
|
+
* field's state.
|
|
98
|
+
* @return {!Element} The element containing info about the field's state.
|
|
99
|
+
* @package
|
|
71
100
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
FieldMultilineInput.prototype.configure_ = function(config) {
|
|
80
|
-
FieldMultilineInput.superClass_.configure_.call(this, config);
|
|
81
|
-
config.maxLines && this.setMaxLines(config.maxLines);
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Construct a FieldMultilineInput from a JSON arg object,
|
|
86
|
-
* dereferencing any string table references.
|
|
87
|
-
* @param {!Object} options A JSON object with options (text, and spellcheck).
|
|
88
|
-
* @return {!FieldMultilineInput} The new field instance.
|
|
89
|
-
* @package
|
|
90
|
-
* @nocollapse
|
|
91
|
-
*/
|
|
92
|
-
FieldMultilineInput.fromJson = function(options) {
|
|
93
|
-
const text = parsing.replaceMessageReferences(options['text']);
|
|
94
|
-
// `this` might be a subclass of FieldMultilineInput if that class doesn't
|
|
95
|
-
// override the static fromJson method.
|
|
96
|
-
return new this(text, undefined, options);
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Serializes this field's value to XML. Should only be called by Blockly.Xml.
|
|
101
|
-
* @param {!Element} fieldElement The element to populate with info about the
|
|
102
|
-
* field's state.
|
|
103
|
-
* @return {!Element} The element containing info about the field's state.
|
|
104
|
-
* @package
|
|
105
|
-
*/
|
|
106
|
-
FieldMultilineInput.prototype.toXml = function(fieldElement) {
|
|
107
|
-
// Replace '\n' characters with HTML-escaped equivalent '
'. This is
|
|
108
|
-
// needed so the plain-text representation of the XML produced by
|
|
109
|
-
// `Blockly.Xml.domToText` will appear on a single line (this is a limitation
|
|
110
|
-
// of the plain-text format).
|
|
111
|
-
fieldElement.textContent = this.getValue().replace(/\n/g, ' ');
|
|
112
|
-
return fieldElement;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Sets the field's value based on the given XML element. Should only be
|
|
117
|
-
* called by Blockly.Xml.
|
|
118
|
-
* @param {!Element} fieldElement The element containing info about the
|
|
119
|
-
* field's state.
|
|
120
|
-
* @package
|
|
121
|
-
*/
|
|
122
|
-
FieldMultilineInput.prototype.fromXml = function(fieldElement) {
|
|
123
|
-
this.setValue(fieldElement.textContent.replace(/ /g, '\n'));
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Saves this field's value.
|
|
128
|
-
* @return {*} The state of this field.
|
|
129
|
-
* @package
|
|
130
|
-
*/
|
|
131
|
-
FieldMultilineInput.prototype.saveState = function() {
|
|
132
|
-
const legacyState = this.saveLegacyState(FieldMultilineInput);
|
|
133
|
-
if (legacyState !== null) {
|
|
134
|
-
return legacyState;
|
|
101
|
+
toXml(fieldElement) {
|
|
102
|
+
// Replace '\n' characters with HTML-escaped equivalent '
'. This is
|
|
103
|
+
// needed so the plain-text representation of the XML produced by
|
|
104
|
+
// `Blockly.Xml.domToText` will appear on a single line (this is a
|
|
105
|
+
// limitation of the plain-text format).
|
|
106
|
+
fieldElement.textContent = this.getValue().replace(/\n/g, ' ');
|
|
107
|
+
return fieldElement;
|
|
135
108
|
}
|
|
136
|
-
return this.getValue();
|
|
137
|
-
};
|
|
138
109
|
|
|
139
|
-
/**
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Sets the field's value based on the given XML element. Should only be
|
|
112
|
+
* called by Blockly.Xml.
|
|
113
|
+
* @param {!Element} fieldElement The element containing info about the
|
|
114
|
+
* field's state.
|
|
115
|
+
* @package
|
|
116
|
+
*/
|
|
117
|
+
fromXml(fieldElement) {
|
|
118
|
+
this.setValue(fieldElement.textContent.replace(/ /g, '\n'));
|
|
148
119
|
}
|
|
149
|
-
this.setValue(state);
|
|
150
|
-
};
|
|
151
120
|
|
|
152
|
-
/**
|
|
153
|
-
|
|
154
|
-
*
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
},
|
|
162
|
-
this.fieldGroup_);
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Get the text from this field as displayed on screen. May differ from getText
|
|
167
|
-
* due to ellipsis, and other formatting.
|
|
168
|
-
* @return {string} Currently displayed text.
|
|
169
|
-
* @protected
|
|
170
|
-
* @override
|
|
171
|
-
*/
|
|
172
|
-
FieldMultilineInput.prototype.getDisplayText_ = function() {
|
|
173
|
-
let textLines = this.getText();
|
|
174
|
-
if (!textLines) {
|
|
175
|
-
// Prevent the field from disappearing if empty.
|
|
176
|
-
return Field.NBSP;
|
|
177
|
-
}
|
|
178
|
-
const lines = textLines.split('\n');
|
|
179
|
-
textLines = '';
|
|
180
|
-
const displayLinesNumber =
|
|
181
|
-
this.isOverflowedY_ ? this.maxLines_ : lines.length;
|
|
182
|
-
for (let i = 0; i < displayLinesNumber; i++) {
|
|
183
|
-
let text = lines[i];
|
|
184
|
-
if (text.length > this.maxDisplayLength) {
|
|
185
|
-
// Truncate displayed string and add an ellipsis ('...').
|
|
186
|
-
text = text.substring(0, this.maxDisplayLength - 4) + '...';
|
|
187
|
-
} else if (this.isOverflowedY_ && i === displayLinesNumber - 1) {
|
|
188
|
-
text = text.substring(0, text.length - 3) + '...';
|
|
121
|
+
/**
|
|
122
|
+
* Saves this field's value.
|
|
123
|
+
* @return {*} The state of this field.
|
|
124
|
+
* @package
|
|
125
|
+
*/
|
|
126
|
+
saveState() {
|
|
127
|
+
const legacyState = this.saveLegacyState(FieldMultilineInput);
|
|
128
|
+
if (legacyState !== null) {
|
|
129
|
+
return legacyState;
|
|
189
130
|
}
|
|
190
|
-
|
|
191
|
-
|
|
131
|
+
return this.getValue();
|
|
132
|
+
}
|
|
192
133
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
134
|
+
/**
|
|
135
|
+
* Sets the field's value based on the given state.
|
|
136
|
+
* @param {*} state The state of the variable to assign to this variable
|
|
137
|
+
* field.
|
|
138
|
+
* @override
|
|
139
|
+
* @package
|
|
140
|
+
*/
|
|
141
|
+
loadState(state) {
|
|
142
|
+
if (this.loadLegacyState(Field, state)) {
|
|
143
|
+
return;
|
|
196
144
|
}
|
|
145
|
+
this.setValue(state);
|
|
197
146
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Create the block UI for this field.
|
|
150
|
+
* @package
|
|
151
|
+
*/
|
|
152
|
+
initView() {
|
|
153
|
+
this.createBorderRect_();
|
|
154
|
+
this.textGroup_ = dom.createSvgElement(
|
|
155
|
+
Svg.G, {
|
|
156
|
+
'class': 'blocklyEditableText',
|
|
157
|
+
},
|
|
158
|
+
this.fieldGroup_);
|
|
201
159
|
}
|
|
202
|
-
return textLines;
|
|
203
|
-
};
|
|
204
160
|
|
|
205
|
-
/**
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
161
|
+
/**
|
|
162
|
+
* Get the text from this field as displayed on screen. May differ from
|
|
163
|
+
* getText due to ellipsis, and other formatting.
|
|
164
|
+
* @return {string} Currently displayed text.
|
|
165
|
+
* @protected
|
|
166
|
+
* @override
|
|
167
|
+
*/
|
|
168
|
+
getDisplayText_() {
|
|
169
|
+
let textLines = this.getText();
|
|
170
|
+
if (!textLines) {
|
|
171
|
+
// Prevent the field from disappearing if empty.
|
|
172
|
+
return Field.NBSP;
|
|
173
|
+
}
|
|
174
|
+
const lines = textLines.split('\n');
|
|
175
|
+
textLines = '';
|
|
176
|
+
const displayLinesNumber =
|
|
177
|
+
this.isOverflowedY_ ? this.maxLines_ : lines.length;
|
|
178
|
+
for (let i = 0; i < displayLinesNumber; i++) {
|
|
179
|
+
let text = lines[i];
|
|
180
|
+
if (text.length > this.maxDisplayLength) {
|
|
181
|
+
// Truncate displayed string and add an ellipsis ('...').
|
|
182
|
+
text = text.substring(0, this.maxDisplayLength - 4) + '...';
|
|
183
|
+
} else if (this.isOverflowedY_ && i === displayLinesNumber - 1) {
|
|
184
|
+
text = text.substring(0, text.length - 3) + '...';
|
|
185
|
+
}
|
|
186
|
+
// Replace whitespace with non-breaking spaces so the text doesn't
|
|
187
|
+
// collapse.
|
|
188
|
+
text = text.replace(/\s/g, Field.NBSP);
|
|
218
189
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
190
|
+
textLines += text;
|
|
191
|
+
if (i !== displayLinesNumber - 1) {
|
|
192
|
+
textLines += '\n';
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (this.sourceBlock_.RTL) {
|
|
196
|
+
// The SVG is LTR, force value to be RTL.
|
|
197
|
+
textLines += '\u200F';
|
|
198
|
+
}
|
|
199
|
+
return textLines;
|
|
228
200
|
}
|
|
229
201
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
},
|
|
243
|
-
this.textGroup_);
|
|
244
|
-
span.appendChild(document.createTextNode(lines[i]));
|
|
245
|
-
y += lineHeight;
|
|
202
|
+
/**
|
|
203
|
+
* Called by setValue if the text input is valid. Updates the value of the
|
|
204
|
+
* field, and updates the text of the field if it is not currently being
|
|
205
|
+
* edited (i.e. handled by the htmlInput_). Is being redefined here to update
|
|
206
|
+
* overflow state of the field.
|
|
207
|
+
* @param {*} newValue The value to be saved. The default validator guarantees
|
|
208
|
+
* that this is a string.
|
|
209
|
+
* @protected
|
|
210
|
+
*/
|
|
211
|
+
doValueUpdate_(newValue) {
|
|
212
|
+
super.doValueUpdate_(newValue);
|
|
213
|
+
this.isOverflowedY_ = this.value_.split('\n').length > this.maxLines_;
|
|
246
214
|
}
|
|
247
215
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
216
|
+
/**
|
|
217
|
+
* Updates the text of the textElement.
|
|
218
|
+
* @protected
|
|
219
|
+
*/
|
|
220
|
+
render_() {
|
|
221
|
+
// Remove all text group children.
|
|
222
|
+
let currentChild;
|
|
223
|
+
while ((currentChild = this.textGroup_.firstChild)) {
|
|
224
|
+
this.textGroup_.removeChild(currentChild);
|
|
254
225
|
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
this.updateSize_();
|
|
258
226
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
227
|
+
// Add in text elements into the group.
|
|
228
|
+
const lines = this.getDisplayText_().split('\n');
|
|
229
|
+
let y = 0;
|
|
230
|
+
for (let i = 0; i < lines.length; i++) {
|
|
231
|
+
const lineHeight = this.getConstants().FIELD_TEXT_HEIGHT +
|
|
232
|
+
this.getConstants().FIELD_BORDER_RECT_Y_PADDING;
|
|
233
|
+
const span = dom.createSvgElement(
|
|
234
|
+
Svg.TEXT, {
|
|
235
|
+
'class': 'blocklyText blocklyMultilineText',
|
|
236
|
+
'x': this.getConstants().FIELD_BORDER_RECT_X_PADDING,
|
|
237
|
+
'y': y + this.getConstants().FIELD_BORDER_RECT_Y_PADDING,
|
|
238
|
+
'dy': this.getConstants().FIELD_TEXT_BASELINE,
|
|
239
|
+
},
|
|
240
|
+
this.textGroup_);
|
|
241
|
+
span.appendChild(document.createTextNode(lines[i]));
|
|
242
|
+
y += lineHeight;
|
|
267
243
|
}
|
|
268
|
-
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
244
|
+
|
|
245
|
+
if (this.isBeingEdited_) {
|
|
246
|
+
const htmlInput = /** @type {!HTMLElement} */ (this.htmlInput_);
|
|
247
|
+
if (this.isOverflowedY_) {
|
|
248
|
+
dom.addClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY');
|
|
249
|
+
} else {
|
|
250
|
+
dom.removeClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY');
|
|
251
|
+
}
|
|
275
252
|
}
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
253
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
254
|
+
this.updateSize_();
|
|
255
|
+
|
|
256
|
+
if (this.isBeingEdited_) {
|
|
257
|
+
if (this.sourceBlock_.RTL) {
|
|
258
|
+
// in RTL, we need to let the browser reflow before resizing
|
|
259
|
+
// in order to get the correct bounding box of the borderRect
|
|
260
|
+
// avoiding issue #2777.
|
|
261
|
+
setTimeout(this.resizeEditor_.bind(this), 0);
|
|
262
|
+
} else {
|
|
263
|
+
this.resizeEditor_();
|
|
264
|
+
}
|
|
265
|
+
const htmlInput = /** @type {!HTMLElement} */ (this.htmlInput_);
|
|
266
|
+
if (!this.isTextValid_) {
|
|
267
|
+
dom.addClass(htmlInput, 'blocklyInvalidInput');
|
|
268
|
+
aria.setState(htmlInput, aria.State.INVALID, true);
|
|
269
|
+
} else {
|
|
270
|
+
dom.removeClass(htmlInput, 'blocklyInvalidInput');
|
|
271
|
+
aria.setState(htmlInput, aria.State.INVALID, false);
|
|
272
|
+
}
|
|
292
273
|
}
|
|
293
|
-
totalHeight += this.getConstants().FIELD_TEXT_HEIGHT +
|
|
294
|
-
(i > 0 ? this.getConstants().FIELD_BORDER_RECT_Y_PADDING : 0);
|
|
295
274
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
if (actualEditorLines[i].length > this.maxDisplayLength) {
|
|
311
|
-
actualEditorLines[i] =
|
|
312
|
-
actualEditorLines[i].substring(0, this.maxDisplayLength);
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Updates the size of the field based on the text.
|
|
278
|
+
* @protected
|
|
279
|
+
*/
|
|
280
|
+
updateSize_() {
|
|
281
|
+
const nodes = this.textGroup_.childNodes;
|
|
282
|
+
let totalWidth = 0;
|
|
283
|
+
let totalHeight = 0;
|
|
284
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
285
|
+
const tspan = /** @type {!Element} */ (nodes[i]);
|
|
286
|
+
const textWidth = dom.getTextWidth(tspan);
|
|
287
|
+
if (textWidth > totalWidth) {
|
|
288
|
+
totalWidth = textWidth;
|
|
313
289
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
290
|
+
totalHeight += this.getConstants().FIELD_TEXT_HEIGHT +
|
|
291
|
+
(i > 0 ? this.getConstants().FIELD_BORDER_RECT_Y_PADDING : 0);
|
|
292
|
+
}
|
|
293
|
+
if (this.isBeingEdited_) {
|
|
294
|
+
// The default width is based on the longest line in the display text,
|
|
295
|
+
// but when it's being edited, width should be calculated based on the
|
|
296
|
+
// absolute longest line, even if it would be truncated after editing.
|
|
297
|
+
// Otherwise we would get wrong editor width when there are more
|
|
298
|
+
// lines than this.maxLines_.
|
|
299
|
+
const actualEditorLines = this.value_.split('\n');
|
|
300
|
+
const dummyTextElement = dom.createSvgElement(
|
|
301
|
+
Svg.TEXT, {'class': 'blocklyText blocklyMultilineText'});
|
|
302
|
+
const fontSize = this.getConstants().FIELD_TEXT_FONTSIZE;
|
|
303
|
+
const fontWeight = this.getConstants().FIELD_TEXT_FONTWEIGHT;
|
|
304
|
+
const fontFamily = this.getConstants().FIELD_TEXT_FONTFAMILY;
|
|
305
|
+
|
|
306
|
+
for (let i = 0; i < actualEditorLines.length; i++) {
|
|
307
|
+
if (actualEditorLines[i].length > this.maxDisplayLength) {
|
|
308
|
+
actualEditorLines[i] =
|
|
309
|
+
actualEditorLines[i].substring(0, this.maxDisplayLength);
|
|
310
|
+
}
|
|
311
|
+
dummyTextElement.textContent = actualEditorLines[i];
|
|
312
|
+
const lineWidth = dom.getFastTextWidth(
|
|
313
|
+
dummyTextElement, fontSize, fontWeight, fontFamily);
|
|
314
|
+
if (lineWidth > totalWidth) {
|
|
315
|
+
totalWidth = lineWidth;
|
|
316
|
+
}
|
|
319
317
|
}
|
|
318
|
+
|
|
319
|
+
const scrollbarWidth =
|
|
320
|
+
this.htmlInput_.offsetWidth - this.htmlInput_.clientWidth;
|
|
321
|
+
totalWidth += scrollbarWidth;
|
|
322
|
+
}
|
|
323
|
+
if (this.borderRect_) {
|
|
324
|
+
totalHeight += this.getConstants().FIELD_BORDER_RECT_Y_PADDING * 2;
|
|
325
|
+
totalWidth += this.getConstants().FIELD_BORDER_RECT_X_PADDING * 2;
|
|
326
|
+
this.borderRect_.setAttribute('width', totalWidth);
|
|
327
|
+
this.borderRect_.setAttribute('height', totalHeight);
|
|
320
328
|
}
|
|
329
|
+
this.size_.width = totalWidth;
|
|
330
|
+
this.size_.height = totalHeight;
|
|
321
331
|
|
|
322
|
-
|
|
323
|
-
this.htmlInput_.offsetWidth - this.htmlInput_.clientWidth;
|
|
324
|
-
totalWidth += scrollbarWidth;
|
|
332
|
+
this.positionBorderRect_();
|
|
325
333
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Show the inline free-text editor on top of the text.
|
|
337
|
+
* Overrides the default behaviour to force rerender in order to
|
|
338
|
+
* correct block size, based on editor text.
|
|
339
|
+
* @param {Event=} _opt_e Optional mouse event that triggered the field to
|
|
340
|
+
* open, or undefined if triggered programmatically.
|
|
341
|
+
* @param {boolean=} opt_quietInput True if editor should be created without
|
|
342
|
+
* focus. Defaults to false.
|
|
343
|
+
* @override
|
|
344
|
+
*/
|
|
345
|
+
showEditor_(_opt_e, opt_quietInput) {
|
|
346
|
+
super.showEditor_(_opt_e, opt_quietInput);
|
|
347
|
+
this.forceRerender();
|
|
331
348
|
}
|
|
332
|
-
this.size_.width = totalWidth;
|
|
333
|
-
this.size_.height = totalHeight;
|
|
334
349
|
|
|
335
|
-
|
|
336
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Create the text input editor widget.
|
|
352
|
+
* @return {!HTMLTextAreaElement} The newly created text input editor.
|
|
353
|
+
* @protected
|
|
354
|
+
*/
|
|
355
|
+
widgetCreate_() {
|
|
356
|
+
const div = WidgetDiv.getDiv();
|
|
357
|
+
const scale = this.workspace_.getScale();
|
|
358
|
+
|
|
359
|
+
const htmlInput =
|
|
360
|
+
/** @type {HTMLTextAreaElement} */ (document.createElement('textarea'));
|
|
361
|
+
htmlInput.className = 'blocklyHtmlInput blocklyHtmlTextAreaInput';
|
|
362
|
+
htmlInput.setAttribute('spellcheck', this.spellcheck_);
|
|
363
|
+
const fontSize = (this.getConstants().FIELD_TEXT_FONTSIZE * scale) + 'pt';
|
|
364
|
+
div.style.fontSize = fontSize;
|
|
365
|
+
htmlInput.style.fontSize = fontSize;
|
|
366
|
+
const borderRadius = (FieldTextInput.BORDERRADIUS * scale) + 'px';
|
|
367
|
+
htmlInput.style.borderRadius = borderRadius;
|
|
368
|
+
const paddingX = this.getConstants().FIELD_BORDER_RECT_X_PADDING * scale;
|
|
369
|
+
const paddingY =
|
|
370
|
+
this.getConstants().FIELD_BORDER_RECT_Y_PADDING * scale / 2;
|
|
371
|
+
htmlInput.style.padding = paddingY + 'px ' + paddingX + 'px ' + paddingY +
|
|
372
|
+
'px ' + paddingX + 'px';
|
|
373
|
+
const lineHeight = this.getConstants().FIELD_TEXT_HEIGHT +
|
|
374
|
+
this.getConstants().FIELD_BORDER_RECT_Y_PADDING;
|
|
375
|
+
htmlInput.style.lineHeight = (lineHeight * scale) + 'px';
|
|
337
376
|
|
|
338
|
-
|
|
339
|
-
* Show the inline free-text editor on top of the text.
|
|
340
|
-
* Overrides the default behaviour to force rerender in order to
|
|
341
|
-
* correct block size, based on editor text.
|
|
342
|
-
* @param {Event=} _opt_e Optional mouse event that triggered the field to open,
|
|
343
|
-
* or undefined if triggered programmatically.
|
|
344
|
-
* @param {boolean=} opt_quietInput True if editor should be created without
|
|
345
|
-
* focus. Defaults to false.
|
|
346
|
-
* @override
|
|
347
|
-
*/
|
|
348
|
-
FieldMultilineInput.prototype.showEditor_ = function(_opt_e, opt_quietInput) {
|
|
349
|
-
FieldMultilineInput.superClass_.showEditor_.call(
|
|
350
|
-
this, _opt_e, opt_quietInput);
|
|
351
|
-
this.forceRerender();
|
|
352
|
-
};
|
|
377
|
+
div.appendChild(htmlInput);
|
|
353
378
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
const htmlInput =
|
|
364
|
-
/** @type {HTMLTextAreaElement} */ (document.createElement('textarea'));
|
|
365
|
-
htmlInput.className = 'blocklyHtmlInput blocklyHtmlTextAreaInput';
|
|
366
|
-
htmlInput.setAttribute('spellcheck', this.spellcheck_);
|
|
367
|
-
const fontSize = (this.getConstants().FIELD_TEXT_FONTSIZE * scale) + 'pt';
|
|
368
|
-
div.style.fontSize = fontSize;
|
|
369
|
-
htmlInput.style.fontSize = fontSize;
|
|
370
|
-
const borderRadius = (FieldTextInput.BORDERRADIUS * scale) + 'px';
|
|
371
|
-
htmlInput.style.borderRadius = borderRadius;
|
|
372
|
-
const paddingX = this.getConstants().FIELD_BORDER_RECT_X_PADDING * scale;
|
|
373
|
-
const paddingY = this.getConstants().FIELD_BORDER_RECT_Y_PADDING * scale / 2;
|
|
374
|
-
htmlInput.style.padding =
|
|
375
|
-
paddingY + 'px ' + paddingX + 'px ' + paddingY + 'px ' + paddingX + 'px';
|
|
376
|
-
const lineHeight = this.getConstants().FIELD_TEXT_HEIGHT +
|
|
377
|
-
this.getConstants().FIELD_BORDER_RECT_Y_PADDING;
|
|
378
|
-
htmlInput.style.lineHeight = (lineHeight * scale) + 'px';
|
|
379
|
-
|
|
380
|
-
div.appendChild(htmlInput);
|
|
381
|
-
|
|
382
|
-
htmlInput.value = htmlInput.defaultValue = this.getEditorText_(this.value_);
|
|
383
|
-
htmlInput.untypedDefaultValue_ = this.value_;
|
|
384
|
-
htmlInput.oldValue_ = null;
|
|
385
|
-
if (userAgent.GECKO) {
|
|
386
|
-
// In FF, ensure the browser reflows before resizing to avoid issue #2777.
|
|
387
|
-
setTimeout(this.resizeEditor_.bind(this), 0);
|
|
388
|
-
} else {
|
|
389
|
-
this.resizeEditor_();
|
|
390
|
-
}
|
|
379
|
+
htmlInput.value = htmlInput.defaultValue = this.getEditorText_(this.value_);
|
|
380
|
+
htmlInput.untypedDefaultValue_ = this.value_;
|
|
381
|
+
htmlInput.oldValue_ = null;
|
|
382
|
+
if (userAgent.GECKO) {
|
|
383
|
+
// In FF, ensure the browser reflows before resizing to avoid issue #2777.
|
|
384
|
+
setTimeout(this.resizeEditor_.bind(this), 0);
|
|
385
|
+
} else {
|
|
386
|
+
this.resizeEditor_();
|
|
387
|
+
}
|
|
391
388
|
|
|
392
|
-
|
|
389
|
+
this.bindInputEvents_(htmlInput);
|
|
393
390
|
|
|
394
|
-
|
|
395
|
-
}
|
|
391
|
+
return htmlInput;
|
|
392
|
+
}
|
|
396
393
|
|
|
397
|
-
/**
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
394
|
+
/**
|
|
395
|
+
* Sets the maxLines config for this field.
|
|
396
|
+
* @param {number} maxLines Defines the maximum number of lines allowed,
|
|
397
|
+
* before scrolling functionality is enabled.
|
|
398
|
+
*/
|
|
399
|
+
setMaxLines(maxLines) {
|
|
400
|
+
if (typeof maxLines === 'number' && maxLines > 0 &&
|
|
401
|
+
maxLines !== this.maxLines_) {
|
|
402
|
+
this.maxLines_ = maxLines;
|
|
403
|
+
this.forceRerender();
|
|
404
|
+
}
|
|
407
405
|
}
|
|
408
|
-
};
|
|
409
406
|
|
|
410
|
-
/**
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
}
|
|
407
|
+
/**
|
|
408
|
+
* Returns the maxLines config of this field.
|
|
409
|
+
* @return {number} The maxLines config value.
|
|
410
|
+
*/
|
|
411
|
+
getMaxLines() {
|
|
412
|
+
return this.maxLines_;
|
|
413
|
+
}
|
|
417
414
|
|
|
418
|
-
/**
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
415
|
+
/**
|
|
416
|
+
* Handle key down to the editor. Override the text input definition of this
|
|
417
|
+
* so as to not close the editor when enter is typed in.
|
|
418
|
+
* @param {!Event} e Keyboard event.
|
|
419
|
+
* @protected
|
|
420
|
+
*/
|
|
421
|
+
onHtmlInputKeyDown_(e) {
|
|
422
|
+
if (e.keyCode !== KeyCodes.ENTER) {
|
|
423
|
+
super.onHtmlInputKeyDown_(e);
|
|
424
|
+
}
|
|
427
425
|
}
|
|
428
|
-
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Construct a FieldMultilineInput from a JSON arg object,
|
|
429
|
+
* dereferencing any string table references.
|
|
430
|
+
* @param {!Object} options A JSON object with options (text, and spellcheck).
|
|
431
|
+
* @return {!FieldMultilineInput} The new field instance.
|
|
432
|
+
* @package
|
|
433
|
+
* @nocollapse
|
|
434
|
+
* @override
|
|
435
|
+
*/
|
|
436
|
+
static fromJson(options) {
|
|
437
|
+
const text = parsing.replaceMessageReferences(options['text']);
|
|
438
|
+
// `this` might be a subclass of FieldMultilineInput if that class doesn't
|
|
439
|
+
// override the static fromJson method.
|
|
440
|
+
return new this(text, undefined, options);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
429
443
|
|
|
430
444
|
/**
|
|
431
445
|
* CSS for multiline field. See css.js for use.
|
|
432
446
|
*/
|
|
433
447
|
Css.register(`
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
448
|
+
.blocklyHtmlTextAreaInput {
|
|
449
|
+
font-family: monospace;
|
|
450
|
+
resize: none;
|
|
451
|
+
overflow: hidden;
|
|
452
|
+
height: 100%;
|
|
453
|
+
text-align: left;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.blocklyHtmlTextAreaInputOverflowedY {
|
|
457
|
+
overflow-y: scroll;
|
|
458
|
+
}
|
|
445
459
|
`);
|
|
446
460
|
|
|
447
461
|
fieldRegistry.register('field_multilinetext', FieldMultilineInput);
|