blockly 7.20211209.4 → 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.
Files changed (262) hide show
  1. package/blockly.d.ts +18963 -18432
  2. package/blockly.min.js +852 -844
  3. package/blockly_compressed.js +669 -664
  4. package/blockly_compressed.js.map +1 -1
  5. package/blocks/blocks.js +47 -0
  6. package/blocks/colour.js +13 -3
  7. package/blocks/lists.js +22 -13
  8. package/blocks/logic.js +13 -3
  9. package/blocks/loops.js +24 -11
  10. package/blocks/math.js +12 -3
  11. package/blocks/procedures.js +41 -27
  12. package/blocks/text.js +22 -13
  13. package/blocks/variables.js +14 -3
  14. package/blocks/variables_dynamic.js +13 -3
  15. package/blocks_compressed.js +146 -141
  16. package/blocks_compressed.js.map +1 -1
  17. package/core/block.js +1869 -1814
  18. package/core/block_drag_surface.js +201 -200
  19. package/core/block_dragger.js +377 -373
  20. package/core/block_svg.js +1593 -1479
  21. package/core/blockly.js +8 -22
  22. package/core/blocks.js +9 -2
  23. package/core/browser_events.js +22 -5
  24. package/core/bubble.js +841 -797
  25. package/core/bubble_dragger.js +213 -206
  26. package/core/bump_objects.js +2 -2
  27. package/core/clipboard.js +9 -9
  28. package/core/comment.js +353 -332
  29. package/core/common.js +46 -17
  30. package/core/component_manager.js +181 -174
  31. package/core/config.js +87 -0
  32. package/core/connection.js +595 -584
  33. package/core/connection_checker.js +242 -244
  34. package/core/connection_db.js +235 -230
  35. package/core/contextmenu.js +9 -6
  36. package/core/contextmenu_items.js +1 -2
  37. package/core/contextmenu_registry.js +93 -89
  38. package/core/css.js +474 -474
  39. package/core/delete_area.js +45 -42
  40. package/core/drag_target.js +57 -56
  41. package/core/dropdowndiv.js +153 -163
  42. package/core/events/events.js +2 -2
  43. package/core/events/events_abstract.js +89 -77
  44. package/core/events/events_block_base.js +37 -36
  45. package/core/events/events_block_change.js +130 -124
  46. package/core/events/events_block_create.js +73 -71
  47. package/core/events/events_block_delete.js +84 -82
  48. package/core/events/events_block_drag.js +50 -49
  49. package/core/events/events_block_move.js +147 -140
  50. package/core/events/events_bubble_open.js +51 -50
  51. package/core/events/events_click.js +48 -44
  52. package/core/events/events_comment_base.js +72 -69
  53. package/core/events/events_comment_change.js +63 -61
  54. package/core/events/events_comment_create.js +44 -42
  55. package/core/events/events_comment_delete.js +42 -40
  56. package/core/events/events_comment_move.js +106 -104
  57. package/core/events/events_marker_move.js +65 -64
  58. package/core/events/events_selected.js +46 -45
  59. package/core/events/events_theme_change.js +36 -35
  60. package/core/events/events_toolbox_item_select.js +46 -45
  61. package/core/events/events_trashcan_open.js +37 -36
  62. package/core/events/events_ui.js +47 -46
  63. package/core/events/events_ui_base.js +30 -29
  64. package/core/events/events_var_base.js +37 -36
  65. package/core/events/events_var_create.js +50 -48
  66. package/core/events/events_var_delete.js +50 -48
  67. package/core/events/events_var_rename.js +51 -49
  68. package/core/events/events_viewport.js +66 -65
  69. package/core/events/utils.js +29 -14
  70. package/core/events/workspace_events.js +49 -55
  71. package/core/extensions.js +4 -3
  72. package/core/field.js +1061 -997
  73. package/core/field_angle.js +462 -442
  74. package/core/field_checkbox.js +194 -182
  75. package/core/field_colour.js +519 -505
  76. package/core/field_dropdown.js +617 -598
  77. package/core/field_image.js +229 -220
  78. package/core/field_label.js +102 -91
  79. package/core/field_label_serializable.js +42 -41
  80. package/core/field_multilineinput.js +372 -358
  81. package/core/field_number.js +272 -253
  82. package/core/field_textinput.js +499 -467
  83. package/core/field_variable.js +458 -420
  84. package/core/flyout_base.js +1005 -952
  85. package/core/flyout_button.js +277 -260
  86. package/core/flyout_horizontal.js +304 -302
  87. package/core/flyout_metrics_manager.js +64 -64
  88. package/core/flyout_vertical.js +306 -300
  89. package/core/generator.js +459 -446
  90. package/core/gesture.js +829 -813
  91. package/core/grid.js +166 -163
  92. package/core/icon.js +168 -159
  93. package/core/inject.js +7 -5
  94. package/core/input.js +257 -248
  95. package/core/insertion_marker_manager.js +655 -624
  96. package/core/internal_constants.js +0 -129
  97. package/core/keyboard_nav/ast_node.js +605 -596
  98. package/core/keyboard_nav/basic_cursor.js +166 -165
  99. package/core/keyboard_nav/cursor.js +99 -97
  100. package/core/keyboard_nav/marker.js +83 -79
  101. package/core/keyboard_nav/tab_navigate_cursor.js +18 -23
  102. package/core/marker_manager.js +153 -141
  103. package/core/menu.js +377 -372
  104. package/core/menuitem.js +223 -217
  105. package/core/metrics_manager.js +403 -390
  106. package/core/mutator.js +468 -437
  107. package/core/names.js +229 -188
  108. package/core/options.js +290 -284
  109. package/core/procedures.js +29 -17
  110. package/core/registry.js +19 -16
  111. package/core/rendered_connection.js +482 -463
  112. package/core/renderers/common/block_rendering.js +9 -3
  113. package/core/renderers/common/constants.js +1119 -1112
  114. package/core/renderers/common/debug.js +14 -0
  115. package/core/renderers/common/debugger.js +338 -316
  116. package/core/renderers/common/drawer.js +380 -370
  117. package/core/renderers/common/i_path_object.js +2 -2
  118. package/core/renderers/common/info.js +626 -618
  119. package/core/renderers/common/marker_svg.js +579 -541
  120. package/core/renderers/common/path_object.js +203 -200
  121. package/core/renderers/common/renderer.js +220 -218
  122. package/core/renderers/geras/constants.js +36 -36
  123. package/core/renderers/geras/drawer.js +155 -147
  124. package/core/renderers/geras/highlight_constants.js +244 -238
  125. package/core/renderers/geras/highlighter.js +231 -179
  126. package/core/renderers/geras/info.js +392 -369
  127. package/core/renderers/geras/measurables/inline_input.js +25 -19
  128. package/core/renderers/geras/measurables/statement_input.js +23 -17
  129. package/core/renderers/geras/path_object.js +106 -121
  130. package/core/renderers/geras/renderer.js +96 -98
  131. package/core/renderers/measurables/base.js +30 -18
  132. package/core/renderers/measurables/bottom_row.js +83 -80
  133. package/core/renderers/measurables/connection.js +22 -15
  134. package/core/renderers/measurables/external_value_input.js +35 -22
  135. package/core/renderers/measurables/field.js +35 -20
  136. package/core/renderers/measurables/hat.js +18 -13
  137. package/core/renderers/measurables/icon.js +24 -17
  138. package/core/renderers/measurables/in_row_spacer.js +15 -13
  139. package/core/renderers/measurables/inline_input.js +43 -33
  140. package/core/renderers/measurables/input_connection.js +41 -28
  141. package/core/renderers/measurables/input_row.js +50 -44
  142. package/core/renderers/measurables/jagged_edge.js +14 -12
  143. package/core/renderers/measurables/next_connection.js +16 -14
  144. package/core/renderers/measurables/output_connection.js +26 -20
  145. package/core/renderers/measurables/previous_connection.js +16 -15
  146. package/core/renderers/measurables/round_corner.js +20 -18
  147. package/core/renderers/measurables/row.js +184 -168
  148. package/core/renderers/measurables/spacer_row.js +38 -23
  149. package/core/renderers/measurables/square_corner.js +18 -16
  150. package/core/renderers/measurables/statement_input.js +23 -20
  151. package/core/renderers/measurables/top_row.js +88 -85
  152. package/core/renderers/minimalist/constants.js +8 -7
  153. package/core/renderers/minimalist/drawer.js +11 -10
  154. package/core/renderers/minimalist/info.js +18 -18
  155. package/core/renderers/minimalist/renderer.js +40 -39
  156. package/core/renderers/thrasos/info.js +258 -248
  157. package/core/renderers/thrasos/renderer.js +20 -20
  158. package/core/renderers/zelos/constants.js +898 -873
  159. package/core/renderers/zelos/drawer.js +186 -169
  160. package/core/renderers/zelos/info.js +502 -479
  161. package/core/renderers/zelos/marker_svg.js +129 -115
  162. package/core/renderers/zelos/measurables/bottom_row.js +31 -30
  163. package/core/renderers/zelos/measurables/inputs.js +22 -21
  164. package/core/renderers/zelos/measurables/row_elements.js +14 -13
  165. package/core/renderers/zelos/measurables/top_row.js +34 -33
  166. package/core/renderers/zelos/path_object.js +181 -180
  167. package/core/renderers/zelos/renderer.js +91 -92
  168. package/core/scrollbar.js +759 -713
  169. package/core/scrollbar_pair.js +250 -245
  170. package/core/serialization/blocks.js +19 -9
  171. package/core/serialization/workspaces.js +3 -2
  172. package/core/shortcut_registry.js +286 -277
  173. package/core/sprites.js +31 -0
  174. package/core/theme.js +135 -141
  175. package/core/theme_manager.js +147 -143
  176. package/core/toolbox/category.js +602 -576
  177. package/core/toolbox/collapsible_category.js +226 -227
  178. package/core/toolbox/separator.js +70 -61
  179. package/core/toolbox/toolbox.js +934 -927
  180. package/core/toolbox/toolbox_item.js +115 -99
  181. package/core/tooltip.js +108 -35
  182. package/core/touch.js +8 -3
  183. package/core/touch_gesture.js +254 -251
  184. package/core/trashcan.js +606 -595
  185. package/core/utils/coordinate.js +97 -95
  186. package/core/utils/dom.js +2 -2
  187. package/core/utils/global.js +2 -0
  188. package/core/utils/rect.js +41 -37
  189. package/core/utils/sentinel.js +25 -0
  190. package/core/utils/size.js +30 -27
  191. package/core/utils/svg.js +18 -16
  192. package/core/variable_map.js +325 -341
  193. package/core/variable_model.js +55 -54
  194. package/core/variables.js +9 -2
  195. package/core/variables_dynamic.js +3 -1
  196. package/core/warning.js +126 -120
  197. package/core/widgetdiv.js +4 -4
  198. package/core/workspace.js +685 -664
  199. package/core/workspace_audio.js +124 -118
  200. package/core/workspace_comment.js +308 -298
  201. package/core/workspace_comment_svg.js +1029 -951
  202. package/core/workspace_drag_surface_svg.js +147 -140
  203. package/core/workspace_dragger.js +70 -71
  204. package/core/workspace_svg.js +2322 -2297
  205. package/core/xml.js +30 -20
  206. package/core/zoom_controls.js +431 -439
  207. package/dart_compressed.js +40 -43
  208. package/dart_compressed.js.map +1 -1
  209. package/generators/dart/colour.js +56 -64
  210. package/generators/dart/lists.js +61 -50
  211. package/generators/dart/math.js +160 -148
  212. package/generators/dart/text.js +83 -61
  213. package/generators/javascript/colour.js +37 -34
  214. package/generators/javascript/lists.js +50 -43
  215. package/generators/javascript/math.js +123 -139
  216. package/generators/javascript/text.js +67 -81
  217. package/generators/lua/colour.js +25 -23
  218. package/generators/lua/lists.js +97 -69
  219. package/generators/lua/logic.js +1 -2
  220. package/generators/lua/math.js +182 -144
  221. package/generators/lua/text.js +116 -99
  222. package/generators/php/colour.js +38 -32
  223. package/generators/php/lists.js +109 -89
  224. package/generators/php/math.js +90 -81
  225. package/generators/php/text.js +63 -61
  226. package/generators/python/colour.js +18 -18
  227. package/generators/python/lists.js +38 -30
  228. package/generators/python/loops.js +12 -8
  229. package/generators/python/math.js +104 -106
  230. package/generators/python/text.js +34 -30
  231. package/javascript_compressed.js +37 -39
  232. package/javascript_compressed.js.map +1 -1
  233. package/lua_compressed.js +39 -42
  234. package/lua_compressed.js.map +1 -1
  235. package/msg/az.js +2 -2
  236. package/msg/be.js +4 -4
  237. package/msg/cs.js +15 -15
  238. package/msg/de.js +1 -1
  239. package/msg/diq.js +1 -1
  240. package/msg/eo.js +1 -1
  241. package/msg/es.js +1 -1
  242. package/msg/fa.js +1 -1
  243. package/msg/fr.js +4 -4
  244. package/msg/he.js +1 -1
  245. package/msg/hr.js +2 -2
  246. package/msg/hy.js +2 -2
  247. package/msg/id.js +12 -12
  248. package/msg/inh.js +14 -14
  249. package/msg/ja.js +7 -7
  250. package/msg/lv.js +29 -29
  251. package/msg/pa.js +3 -3
  252. package/msg/smn.js +436 -0
  253. package/msg/te.js +1 -1
  254. package/msg/yue.js +1 -1
  255. package/msg/zh-hans.js +3 -3
  256. package/msg/zh-hant.js +3 -3
  257. package/package.json +7 -6
  258. package/php_compressed.js +38 -42
  259. package/php_compressed.js.map +1 -1
  260. package/python_compressed.js +26 -25
  261. package/python_compressed.js.map +1 -1
  262. package/blocks/all.js +0 -23
package/core/comment.js CHANGED
@@ -19,7 +19,6 @@ const Css = goog.require('Blockly.Css');
19
19
  const browserEvents = goog.require('Blockly.browserEvents');
20
20
  const dom = goog.require('Blockly.utils.dom');
21
21
  const eventUtils = goog.require('Blockly.Events.utils');
22
- const object = goog.require('Blockly.utils.object');
23
22
  const userAgent = goog.require('Blockly.utils.userAgent');
24
23
  /* eslint-disable-next-line no-unused-vars */
25
24
  const {BlockSvg} = goog.requireType('Blockly.BlockSvg');
@@ -44,384 +43,406 @@ goog.require('Blockly.Warning');
44
43
 
45
44
  /**
46
45
  * Class for a comment.
47
- * @param {!Block} block The block associated with this comment.
48
46
  * @extends {Icon}
49
- * @constructor
50
47
  * @alias Blockly.Comment
51
48
  */
52
- const Comment = function(block) {
53
- Comment.superClass_.constructor.call(this, block);
54
-
49
+ class Comment extends Icon {
55
50
  /**
56
- * The model for this comment.
57
- * @type {!Block.CommentModel}
58
- * @private
51
+ * @param {!BlockSvg} block The block associated with this comment.
59
52
  */
60
- this.model_ = block.commentModel;
61
- // If someone creates the comment directly instead of calling
62
- // block.setCommentText we want to make sure the text is non-null;
63
- this.model_.text = this.model_.text || '';
53
+ constructor(block) {
54
+ super(block);
55
+
56
+ /**
57
+ * The model for this comment.
58
+ * @type {!Block.CommentModel}
59
+ * @private
60
+ */
61
+ this.model_ = block.commentModel;
62
+ // If someone creates the comment directly instead of calling
63
+ // block.setCommentText we want to make sure the text is non-null;
64
+ this.model_.text = this.model_.text || '';
65
+
66
+ /**
67
+ * The model's text value at the start of an edit.
68
+ * Used to tell if an event should be fired at the end of an edit.
69
+ * @type {?string}
70
+ * @private
71
+ */
72
+ this.cachedText_ = '';
73
+
74
+ /**
75
+ * Mouse up event data.
76
+ * @type {?browserEvents.Data}
77
+ * @private
78
+ */
79
+ this.onMouseUpWrapper_ = null;
80
+
81
+ /**
82
+ * Wheel event data.
83
+ * @type {?browserEvents.Data}
84
+ * @private
85
+ */
86
+ this.onWheelWrapper_ = null;
87
+
88
+ /**
89
+ * Change event data.
90
+ * @type {?browserEvents.Data}
91
+ * @private
92
+ */
93
+ this.onChangeWrapper_ = null;
94
+
95
+ /**
96
+ * Input event data.
97
+ * @type {?browserEvents.Data}
98
+ * @private
99
+ */
100
+ this.onInputWrapper_ = null;
101
+
102
+ /**
103
+ * The SVG element that contains the text edit area, or null if not created.
104
+ * @type {?SVGForeignObjectElement}
105
+ * @private
106
+ */
107
+ this.foreignObject_ = null;
108
+
109
+ /**
110
+ * The editable text area, or null if not created.
111
+ * @type {?Element}
112
+ * @private
113
+ */
114
+ this.textarea_ = null;
115
+
116
+ /**
117
+ * The top-level node of the comment text, or null if not created.
118
+ * @type {?SVGTextElement}
119
+ * @private
120
+ */
121
+ this.paragraphElement_ = null;
122
+
123
+ this.createIcon();
124
+ }
64
125
 
65
126
  /**
66
- * The model's text value at the start of an edit.
67
- * Used to tell if an event should be fired at the end of an edit.
68
- * @type {?string}
69
- * @private
127
+ * Draw the comment icon.
128
+ * @param {!Element} group The icon group.
129
+ * @protected
70
130
  */
71
- this.cachedText_ = '';
131
+ drawIcon_(group) {
132
+ // Circle.
133
+ dom.createSvgElement(
134
+ Svg.CIRCLE,
135
+ {'class': 'blocklyIconShape', 'r': '8', 'cx': '8', 'cy': '8'}, group);
136
+ // Can't use a real '?' text character since different browsers and
137
+ // operating systems render it differently. Body of question mark.
138
+ dom.createSvgElement(
139
+ Svg.PATH, {
140
+ 'class': 'blocklyIconSymbol',
141
+ 'd': 'm6.8,10h2c0.003,-0.617 0.271,-0.962 0.633,-1.266 2.875,-2.405' +
142
+ '0.607,-5.534 -3.765,-3.874v1.7c3.12,-1.657 3.698,0.118 2.336,1.25' +
143
+ '-1.201,0.998 -1.201,1.528 -1.204,2.19z',
144
+ },
145
+ group);
146
+ // Dot of question mark.
147
+ dom.createSvgElement(
148
+ Svg.RECT, {
149
+ 'class': 'blocklyIconSymbol',
150
+ 'x': '6.8',
151
+ 'y': '10.78',
152
+ 'height': '2',
153
+ 'width': '2',
154
+ },
155
+ group);
156
+ }
72
157
 
73
158
  /**
74
- * Mouse up event data.
75
- * @type {?browserEvents.Data}
159
+ * Create the editor for the comment's bubble.
160
+ * @return {!SVGElement} The top-level node of the editor.
76
161
  * @private
77
162
  */
78
- this.onMouseUpWrapper_ = null;
163
+ createEditor_() {
164
+ /* Create the editor. Here's the markup that will be generated in
165
+ * editable mode:
166
+ <foreignObject x="8" y="8" width="164" height="164">
167
+ <body xmlns="http://www.w3.org/1999/xhtml" class="blocklyMinimalBody">
168
+ <textarea xmlns="http://www.w3.org/1999/xhtml"
169
+ class="blocklyCommentTextarea"
170
+ style="height: 164px; width: 164px;"></textarea>
171
+ </body>
172
+ </foreignObject>
173
+ * For non-editable mode see Warning.textToDom_.
174
+ */
175
+
176
+ this.foreignObject_ = dom.createSvgElement(
177
+ Svg.FOREIGNOBJECT, {'x': Bubble.BORDER_WIDTH, 'y': Bubble.BORDER_WIDTH},
178
+ null);
179
+
180
+ const body = document.createElementNS(dom.HTML_NS, 'body');
181
+ body.setAttribute('xmlns', dom.HTML_NS);
182
+ body.className = 'blocklyMinimalBody';
183
+
184
+ this.textarea_ = document.createElementNS(dom.HTML_NS, 'textarea');
185
+ const textarea = this.textarea_;
186
+ textarea.className = 'blocklyCommentTextarea';
187
+ textarea.setAttribute('dir', this.block_.RTL ? 'RTL' : 'LTR');
188
+ textarea.value = this.model_.text;
189
+ this.resizeTextarea_();
190
+
191
+ body.appendChild(textarea);
192
+ this.foreignObject_.appendChild(body);
193
+
194
+ // Ideally this would be hooked to the focus event for the comment.
195
+ // However doing so in Firefox swallows the cursor for unknown reasons.
196
+ // So this is hooked to mouseup instead. No big deal.
197
+ this.onMouseUpWrapper_ = browserEvents.conditionalBind(
198
+ textarea, 'mouseup', this, this.startEdit_, true, true);
199
+ // Don't zoom with mousewheel.
200
+ this.onWheelWrapper_ =
201
+ browserEvents.conditionalBind(textarea, 'wheel', this, function(e) {
202
+ e.stopPropagation();
203
+ });
204
+ this.onChangeWrapper_ = browserEvents.conditionalBind(
205
+ textarea, 'change', this,
206
+ /**
207
+ * @this {Comment}
208
+ * @param {Event} _e Unused event parameter.
209
+ */
210
+ function(_e) {
211
+ if (this.cachedText_ !== this.model_.text) {
212
+ eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
213
+ this.block_, 'comment', null, this.cachedText_,
214
+ this.model_.text));
215
+ }
216
+ });
217
+ this.onInputWrapper_ = browserEvents.conditionalBind(
218
+ textarea, 'input', this,
219
+ /**
220
+ * @this {Comment}
221
+ * @param {Event} _e Unused event parameter.
222
+ */
223
+ function(_e) {
224
+ this.model_.text = textarea.value;
225
+ });
226
+
227
+ setTimeout(textarea.focus.bind(textarea), 0);
228
+
229
+ return this.foreignObject_;
230
+ }
79
231
 
80
232
  /**
81
- * Wheel event data.
82
- * @type {?browserEvents.Data}
83
- * @private
233
+ * Add or remove editability of the comment.
234
+ * @override
84
235
  */
85
- this.onWheelWrapper_ = null;
236
+ updateEditable() {
237
+ super.updateEditable();
238
+ if (this.isVisible()) {
239
+ // Recreate the bubble with the correct UI.
240
+ this.disposeBubble_();
241
+ this.createBubble_();
242
+ }
243
+ }
86
244
 
87
245
  /**
88
- * Change event data.
89
- * @type {?browserEvents.Data}
246
+ * Callback function triggered when the bubble has resized.
247
+ * Resize the text area accordingly.
90
248
  * @private
91
249
  */
92
- this.onChangeWrapper_ = null;
250
+ onBubbleResize_() {
251
+ if (!this.isVisible()) {
252
+ return;
253
+ }
254
+ this.model_.size = this.bubble_.getBubbleSize();
255
+ this.resizeTextarea_();
256
+ }
93
257
 
94
258
  /**
95
- * Input event data.
96
- * @type {?browserEvents.Data}
259
+ * Resizes the text area to match the size defined on the model (which is
260
+ * the size of the bubble).
97
261
  * @private
98
262
  */
99
- this.onInputWrapper_ = null;
100
-
101
- this.createIcon();
102
- };
103
- object.inherits(Comment, Icon);
104
-
105
- /**
106
- * Draw the comment icon.
107
- * @param {!Element} group The icon group.
108
- * @protected
109
- */
110
- Comment.prototype.drawIcon_ = function(group) {
111
- // Circle.
112
- dom.createSvgElement(
113
- Svg.CIRCLE, {'class': 'blocklyIconShape', 'r': '8', 'cx': '8', 'cy': '8'},
114
- group);
115
- // Can't use a real '?' text character since different browsers and operating
116
- // systems render it differently.
117
- // Body of question mark.
118
- dom.createSvgElement(
119
- Svg.PATH, {
120
- 'class': 'blocklyIconSymbol',
121
- 'd': 'm6.8,10h2c0.003,-0.617 0.271,-0.962 0.633,-1.266 2.875,-2.405' +
122
- '0.607,-5.534 -3.765,-3.874v1.7c3.12,-1.657 3.698,0.118 2.336,1.25' +
123
- '-1.201,0.998 -1.201,1.528 -1.204,2.19z',
124
- },
125
- group);
126
- // Dot of question mark.
127
- dom.createSvgElement(
128
- Svg.RECT, {
129
- 'class': 'blocklyIconSymbol',
130
- 'x': '6.8',
131
- 'y': '10.78',
132
- 'height': '2',
133
- 'width': '2',
134
- },
135
- group);
136
- };
263
+ resizeTextarea_() {
264
+ const size = this.model_.size;
265
+ const doubleBorderWidth = 2 * Bubble.BORDER_WIDTH;
266
+ const widthMinusBorder = size.width - doubleBorderWidth;
267
+ const heightMinusBorder = size.height - doubleBorderWidth;
268
+ this.foreignObject_.setAttribute('width', widthMinusBorder);
269
+ this.foreignObject_.setAttribute('height', heightMinusBorder);
270
+ this.textarea_.style.width = (widthMinusBorder - 4) + 'px';
271
+ this.textarea_.style.height = (heightMinusBorder - 4) + 'px';
272
+ }
137
273
 
138
- /**
139
- * Create the editor for the comment's bubble.
140
- * @return {!SVGElement} The top-level node of the editor.
141
- * @private
142
- */
143
- Comment.prototype.createEditor_ = function() {
144
- /* Create the editor. Here's the markup that will be generated in
145
- * editable mode:
146
- <foreignObject x="8" y="8" width="164" height="164">
147
- <body xmlns="http://www.w3.org/1999/xhtml" class="blocklyMinimalBody">
148
- <textarea xmlns="http://www.w3.org/1999/xhtml"
149
- class="blocklyCommentTextarea"
150
- style="height: 164px; width: 164px;"></textarea>
151
- </body>
152
- </foreignObject>
153
- * For non-editable mode see Warning.textToDom_.
274
+ /**
275
+ * Show or hide the comment bubble.
276
+ * @param {boolean} visible True if the bubble should be visible.
154
277
  */
155
-
156
- this.foreignObject_ = dom.createSvgElement(
157
- Svg.FOREIGNOBJECT, {'x': Bubble.BORDER_WIDTH, 'y': Bubble.BORDER_WIDTH},
158
- null);
159
-
160
- const body = document.createElementNS(dom.HTML_NS, 'body');
161
- body.setAttribute('xmlns', dom.HTML_NS);
162
- body.className = 'blocklyMinimalBody';
163
-
164
- this.textarea_ = document.createElementNS(dom.HTML_NS, 'textarea');
165
- const textarea = this.textarea_;
166
- textarea.className = 'blocklyCommentTextarea';
167
- textarea.setAttribute('dir', this.block_.RTL ? 'RTL' : 'LTR');
168
- textarea.value = this.model_.text;
169
- this.resizeTextarea_();
170
-
171
- body.appendChild(textarea);
172
- this.foreignObject_.appendChild(body);
173
-
174
- // Ideally this would be hooked to the focus event for the comment.
175
- // However doing so in Firefox swallows the cursor for unknown reasons.
176
- // So this is hooked to mouseup instead. No big deal.
177
- this.onMouseUpWrapper_ = browserEvents.conditionalBind(
178
- textarea, 'mouseup', this, this.startEdit_, true, true);
179
- // Don't zoom with mousewheel.
180
- this.onWheelWrapper_ =
181
- browserEvents.conditionalBind(textarea, 'wheel', this, function(e) {
182
- e.stopPropagation();
183
- });
184
- this.onChangeWrapper_ = browserEvents.conditionalBind(
185
- textarea, 'change', this,
186
- /**
187
- * @this {Comment}
188
- * @param {Event} _e Unused event parameter.
189
- */
190
- function(_e) {
191
- if (this.cachedText_ !== this.model_.text) {
192
- eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
193
- this.block_, 'comment', null, this.cachedText_,
194
- this.model_.text));
195
- }
196
- });
197
- this.onInputWrapper_ = browserEvents.conditionalBind(
198
- textarea, 'input', this,
199
- /**
200
- * @this {Comment}
201
- * @param {Event} _e Unused event parameter.
202
- */
203
- function(_e) {
204
- this.model_.text = textarea.value;
205
- });
206
-
207
- setTimeout(textarea.focus.bind(textarea), 0);
208
-
209
- return this.foreignObject_;
210
- };
211
-
212
- /**
213
- * Add or remove editability of the comment.
214
- * @override
215
- */
216
- Comment.prototype.updateEditable = function() {
217
- Comment.superClass_.updateEditable.call(this);
218
- if (this.isVisible()) {
219
- // Recreate the bubble with the correct UI.
220
- this.disposeBubble_();
221
- this.createBubble_();
278
+ setVisible(visible) {
279
+ if (visible === this.isVisible()) {
280
+ return;
281
+ }
282
+ eventUtils.fire(new (eventUtils.get(eventUtils.BUBBLE_OPEN))(
283
+ this.block_, visible, 'comment'));
284
+ this.model_.pinned = visible;
285
+ if (visible) {
286
+ this.createBubble_();
287
+ } else {
288
+ this.disposeBubble_();
289
+ }
222
290
  }
223
- };
224
291
 
225
- /**
226
- * Callback function triggered when the bubble has resized.
227
- * Resize the text area accordingly.
228
- * @private
229
- */
230
- Comment.prototype.onBubbleResize_ = function() {
231
- if (!this.isVisible()) {
232
- return;
292
+ /**
293
+ * Show the bubble. Handles deciding if it should be editable or not.
294
+ * @private
295
+ */
296
+ createBubble_() {
297
+ if (!this.block_.isEditable() || userAgent.IE) {
298
+ // MSIE does not support foreignobject; textareas are impossible.
299
+ // https://docs.microsoft.com/en-us/openspecs/ie_standards/ms-svg/56e6e04c-7c8c-44dd-8100-bd745ee42034
300
+ // Always treat comments in IE as uneditable.
301
+ this.createNonEditableBubble_();
302
+ } else {
303
+ this.createEditableBubble_();
304
+ }
233
305
  }
234
- this.model_.size = this.bubble_.getBubbleSize();
235
- this.resizeTextarea_();
236
- };
237
306
 
238
- /**
239
- * Resizes the text area to match the size defined on the model (which is
240
- * the size of the bubble).
241
- * @private
242
- */
243
- Comment.prototype.resizeTextarea_ = function() {
244
- const size = this.model_.size;
245
- const doubleBorderWidth = 2 * Bubble.BORDER_WIDTH;
246
- const widthMinusBorder = size.width - doubleBorderWidth;
247
- const heightMinusBorder = size.height - doubleBorderWidth;
248
- this.foreignObject_.setAttribute('width', widthMinusBorder);
249
- this.foreignObject_.setAttribute('height', heightMinusBorder);
250
- this.textarea_.style.width = (widthMinusBorder - 4) + 'px';
251
- this.textarea_.style.height = (heightMinusBorder - 4) + 'px';
252
- };
253
-
254
- /**
255
- * Show or hide the comment bubble.
256
- * @param {boolean} visible True if the bubble should be visible.
257
- */
258
- Comment.prototype.setVisible = function(visible) {
259
- if (visible === this.isVisible()) {
260
- return;
261
- }
262
- eventUtils.fire(new (eventUtils.get(eventUtils.BUBBLE_OPEN))(
263
- this.block_, visible, 'comment'));
264
- this.model_.pinned = visible;
265
- if (visible) {
266
- this.createBubble_();
267
- } else {
268
- this.disposeBubble_();
307
+ /**
308
+ * Show an editable bubble.
309
+ * @private
310
+ */
311
+ createEditableBubble_() {
312
+ this.bubble_ = new Bubble(
313
+ /** @type {!WorkspaceSvg} */ (this.block_.workspace),
314
+ this.createEditor_(), this.block_.pathObject.svgPath,
315
+ /** @type {!Coordinate} */ (this.iconXY_), this.model_.size.width,
316
+ this.model_.size.height);
317
+ // Expose this comment's block's ID on its top-level SVG group.
318
+ this.bubble_.setSvgId(this.block_.id);
319
+ this.bubble_.registerResizeEvent(this.onBubbleResize_.bind(this));
320
+ this.applyColour();
269
321
  }
270
- };
271
322
 
272
- /**
273
- * Show the bubble. Handles deciding if it should be editable or not.
274
- * @private
275
- */
276
- Comment.prototype.createBubble_ = function() {
277
- if (!this.block_.isEditable() || userAgent.IE) {
278
- // MSIE does not support foreignobject; textareas are impossible.
279
- // https://docs.microsoft.com/en-us/openspecs/ie_standards/ms-svg/56e6e04c-7c8c-44dd-8100-bd745ee42034
280
- // Always treat comments in IE as uneditable.
281
- this.createNonEditableBubble_();
282
- } else {
283
- this.createEditableBubble_();
323
+ /**
324
+ * Show a non-editable bubble.
325
+ * @private
326
+ * @suppress {checkTypes} Suppress `this` type mismatch.
327
+ */
328
+ createNonEditableBubble_() {
329
+ // TODO (#2917): It would be great if the comment could support line breaks.
330
+ this.paragraphElement_ = Bubble.textToDom(this.block_.getCommentText());
331
+ this.bubble_ = Bubble.createNonEditableBubble(
332
+ this.paragraphElement_, /** @type {!BlockSvg} */ (this.block_),
333
+ /** @type {!Coordinate} */ (this.iconXY_));
334
+ this.applyColour();
284
335
  }
285
- };
286
-
287
- /**
288
- * Show an editable bubble.
289
- * @private
290
- */
291
- Comment.prototype.createEditableBubble_ = function() {
292
- this.bubble_ = new Bubble(
293
- /** @type {!WorkspaceSvg} */ (this.block_.workspace),
294
- this.createEditor_(), this.block_.pathObject.svgPath,
295
- /** @type {!Coordinate} */ (this.iconXY_), this.model_.size.width,
296
- this.model_.size.height);
297
- // Expose this comment's block's ID on its top-level SVG group.
298
- this.bubble_.setSvgId(this.block_.id);
299
- this.bubble_.registerResizeEvent(this.onBubbleResize_.bind(this));
300
- this.applyColour();
301
- };
302
-
303
- /**
304
- * Show a non-editable bubble.
305
- * @private
306
- * @suppress {checkTypes} Suppress `this` type mismatch.
307
- */
308
- Comment.prototype.createNonEditableBubble_ = function() {
309
- // TODO (#2917): It would be great if the comment could support line breaks.
310
- this.paragraphElement_ = Bubble.textToDom(this.block_.getCommentText());
311
- this.bubble_ = Bubble.createNonEditableBubble(
312
- this.paragraphElement_, /** @type {!BlockSvg} */ (this.block_),
313
- /** @type {!Coordinate} */ (this.iconXY_));
314
- this.applyColour();
315
- };
316
336
 
317
- /**
318
- * Dispose of the bubble.
319
- * @private
320
- * @suppress {checkTypes} Suppress `this` type mismatch.
321
- */
322
- Comment.prototype.disposeBubble_ = function() {
323
- if (this.onMouseUpWrapper_) {
324
- browserEvents.unbind(this.onMouseUpWrapper_);
325
- this.onMouseUpWrapper_ = null;
326
- }
327
- if (this.onWheelWrapper_) {
328
- browserEvents.unbind(this.onWheelWrapper_);
329
- this.onWheelWrapper_ = null;
330
- }
331
- if (this.onChangeWrapper_) {
332
- browserEvents.unbind(this.onChangeWrapper_);
333
- this.onChangeWrapper_ = null;
334
- }
335
- if (this.onInputWrapper_) {
336
- browserEvents.unbind(this.onInputWrapper_);
337
- this.onInputWrapper_ = null;
337
+ /**
338
+ * Dispose of the bubble.
339
+ * @private
340
+ * @suppress {checkTypes} Suppress `this` type mismatch.
341
+ */
342
+ disposeBubble_() {
343
+ if (this.onMouseUpWrapper_) {
344
+ browserEvents.unbind(this.onMouseUpWrapper_);
345
+ this.onMouseUpWrapper_ = null;
346
+ }
347
+ if (this.onWheelWrapper_) {
348
+ browserEvents.unbind(this.onWheelWrapper_);
349
+ this.onWheelWrapper_ = null;
350
+ }
351
+ if (this.onChangeWrapper_) {
352
+ browserEvents.unbind(this.onChangeWrapper_);
353
+ this.onChangeWrapper_ = null;
354
+ }
355
+ if (this.onInputWrapper_) {
356
+ browserEvents.unbind(this.onInputWrapper_);
357
+ this.onInputWrapper_ = null;
358
+ }
359
+ this.bubble_.dispose();
360
+ this.bubble_ = null;
361
+ this.textarea_ = null;
362
+ this.foreignObject_ = null;
363
+ this.paragraphElement_ = null;
338
364
  }
339
- this.bubble_.dispose();
340
- this.bubble_ = null;
341
- this.textarea_ = null;
342
- this.foreignObject_ = null;
343
- this.paragraphElement_ = null;
344
- };
345
365
 
346
- /**
347
- * Callback fired when an edit starts.
348
- *
349
- * Bring the comment to the top of the stack when clicked on. Also cache the
350
- * current text so it can be used to fire a change event.
351
- * @param {!Event} _e Mouse up event.
352
- * @private
353
- */
354
- Comment.prototype.startEdit_ = function(_e) {
355
- if (this.bubble_.promote()) {
356
- // Since the act of moving this node within the DOM causes a loss of focus,
357
- // we need to reapply the focus.
358
- this.textarea_.focus();
366
+ /**
367
+ * Callback fired when an edit starts.
368
+ *
369
+ * Bring the comment to the top of the stack when clicked on. Also cache the
370
+ * current text so it can be used to fire a change event.
371
+ * @param {!Event} _e Mouse up event.
372
+ * @private
373
+ */
374
+ startEdit_(_e) {
375
+ if (this.bubble_.promote()) {
376
+ // Since the act of moving this node within the DOM causes a loss of
377
+ // focus, we need to reapply the focus.
378
+ this.textarea_.focus();
379
+ }
380
+
381
+ this.cachedText_ = this.model_.text;
359
382
  }
360
383
 
361
- this.cachedText_ = this.model_.text;
362
- };
363
-
364
- /**
365
- * Get the dimensions of this comment's bubble.
366
- * @return {Size} Object with width and height properties.
367
- */
368
- Comment.prototype.getBubbleSize = function() {
369
- return this.model_.size;
370
- };
384
+ /**
385
+ * Get the dimensions of this comment's bubble.
386
+ * @return {Size} Object with width and height properties.
387
+ */
388
+ getBubbleSize() {
389
+ return this.model_.size;
390
+ }
371
391
 
372
- /**
373
- * Size this comment's bubble.
374
- * @param {number} width Width of the bubble.
375
- * @param {number} height Height of the bubble.
376
- */
377
- Comment.prototype.setBubbleSize = function(width, height) {
378
- if (this.bubble_) {
379
- this.bubble_.setBubbleSize(width, height);
380
- } else {
381
- this.model_.size.width = width;
382
- this.model_.size.height = height;
392
+ /**
393
+ * Size this comment's bubble.
394
+ * @param {number} width Width of the bubble.
395
+ * @param {number} height Height of the bubble.
396
+ */
397
+ setBubbleSize(width, height) {
398
+ if (this.bubble_) {
399
+ this.bubble_.setBubbleSize(width, height);
400
+ } else {
401
+ this.model_.size.width = width;
402
+ this.model_.size.height = height;
403
+ }
383
404
  }
384
- };
385
405
 
386
- /**
387
- * Update the comment's view to match the model.
388
- * @package
389
- */
390
- Comment.prototype.updateText = function() {
391
- if (this.textarea_) {
392
- this.textarea_.value = this.model_.text;
393
- } else if (this.paragraphElement_) {
394
- // Non-Editable mode.
395
- // TODO (#2917): If 2917 gets added this will probably need to be updated.
396
- this.paragraphElement_.firstChild.textContent = this.model_.text;
406
+ /**
407
+ * Update the comment's view to match the model.
408
+ * @package
409
+ */
410
+ updateText() {
411
+ if (this.textarea_) {
412
+ this.textarea_.value = this.model_.text;
413
+ } else if (this.paragraphElement_) {
414
+ // Non-Editable mode.
415
+ // TODO (#2917): If 2917 gets added this will probably need to be updated.
416
+ this.paragraphElement_.firstChild.textContent = this.model_.text;
417
+ }
397
418
  }
398
- };
399
419
 
400
- /**
401
- * Dispose of this comment.
402
- *
403
- * If you want to receive a comment "delete" event (newValue: null), then this
404
- * should not be called directly. Instead call block.setCommentText(null);
405
- */
406
- Comment.prototype.dispose = function() {
407
- this.block_.comment = null;
408
- Icon.prototype.dispose.call(this);
409
- };
420
+ /**
421
+ * Dispose of this comment.
422
+ *
423
+ * If you want to receive a comment "delete" event (newValue: null), then this
424
+ * should not be called directly. Instead call block.setCommentText(null);
425
+ */
426
+ dispose() {
427
+ this.block_.comment = null;
428
+ Icon.prototype.dispose.call(this);
429
+ }
430
+ }
410
431
 
411
432
  /**
412
433
  * CSS for block comment. See css.js for use.
413
434
  */
414
435
  Css.register(`
415
- .blocklyCommentTextarea {
416
- background-color: #fef49c;
417
- border: 0;
418
- display: block;
419
- margin: 0;
420
- outline: 0;
421
- padding: 3px;
422
- resize: none;
423
- text-overflow: hidden;
424
- }
436
+ .blocklyCommentTextarea {
437
+ background-color: #fef49c;
438
+ border: 0;
439
+ display: block;
440
+ margin: 0;
441
+ outline: 0;
442
+ padding: 3px;
443
+ resize: none;
444
+ text-overflow: hidden;
445
+ }
425
446
  `);
426
447
 
427
448
  exports.Comment = Comment;