@blockdia/scratch-blocks 0.1.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 (243) hide show
  1. package/.nvmrc +1 -0
  2. package/LICENSE +674 -0
  3. package/README.md +57 -0
  4. package/TRADEMARK +1 -0
  5. package/blockly_compressed_horizontal.js +2268 -0
  6. package/blockly_compressed_vertical.js +2296 -0
  7. package/blockly_uncompressed_horizontal.js +1212 -0
  8. package/blockly_uncompressed_vertical.js +1212 -0
  9. package/blocks_common/colour.js +61 -0
  10. package/blocks_common/math.js +159 -0
  11. package/blocks_common/matrix.js +54 -0
  12. package/blocks_common/note.js +58 -0
  13. package/blocks_common/text.js +57 -0
  14. package/blocks_compressed.js +37 -0
  15. package/blocks_compressed_horizontal.js +68 -0
  16. package/blocks_compressed_vertical.js +216 -0
  17. package/blocks_horizontal/control.js +212 -0
  18. package/blocks_horizontal/default_toolbox.js +139 -0
  19. package/blocks_horizontal/event.js +190 -0
  20. package/blocks_horizontal/wedo.js +325 -0
  21. package/blocks_vertical/control.js +532 -0
  22. package/blocks_vertical/data.js +666 -0
  23. package/blocks_vertical/default_toolbox.js +571 -0
  24. package/blocks_vertical/event.js +329 -0
  25. package/blocks_vertical/extensions.js +294 -0
  26. package/blocks_vertical/looks.js +591 -0
  27. package/blocks_vertical/motion.js +587 -0
  28. package/blocks_vertical/operators.js +470 -0
  29. package/blocks_vertical/procedures.js +1051 -0
  30. package/blocks_vertical/sensing.js +555 -0
  31. package/blocks_vertical/sound.js +246 -0
  32. package/blocks_vertical/vertical_extensions.js +289 -0
  33. package/build/gen_blocks.js +1 -0
  34. package/build/test_expect.js +1 -0
  35. package/build/test_input.js +1 -0
  36. package/build.py +647 -0
  37. package/cleanup.sh +101 -0
  38. package/core/block.js +1837 -0
  39. package/core/block_animations.js +107 -0
  40. package/core/block_drag_surface.js +299 -0
  41. package/core/block_dragger.js +424 -0
  42. package/core/block_events.js +531 -0
  43. package/core/block_render_svg_horizontal.js +892 -0
  44. package/core/block_render_svg_vertical.js +1734 -0
  45. package/core/block_svg.js +1355 -0
  46. package/core/blockly.js +620 -0
  47. package/core/blocks.js +37 -0
  48. package/core/bubble.js +664 -0
  49. package/core/bubble_dragger.js +285 -0
  50. package/core/colours.js +177 -0
  51. package/core/comment.js +293 -0
  52. package/core/comment_events.js +539 -0
  53. package/core/connection.js +776 -0
  54. package/core/connection_db.js +300 -0
  55. package/core/constants.js +408 -0
  56. package/core/contextmenu.js +534 -0
  57. package/core/css.js +1354 -0
  58. package/core/data_category.js +490 -0
  59. package/core/dragged_connection_manager.js +260 -0
  60. package/core/dropdowndiv.js +408 -0
  61. package/core/events.js +429 -0
  62. package/core/events_abstract.js +113 -0
  63. package/core/extensions.js +450 -0
  64. package/core/field.js +810 -0
  65. package/core/field_angle.js +410 -0
  66. package/core/field_checkbox.js +133 -0
  67. package/core/field_colour.js +253 -0
  68. package/core/field_colour_slider.js +387 -0
  69. package/core/field_date.js +353 -0
  70. package/core/field_dropdown.js +447 -0
  71. package/core/field_iconmenu.js +309 -0
  72. package/core/field_image.js +200 -0
  73. package/core/field_label.js +136 -0
  74. package/core/field_label_serializable.js +125 -0
  75. package/core/field_matrix.js +566 -0
  76. package/core/field_note.js +850 -0
  77. package/core/field_number.js +366 -0
  78. package/core/field_numberdropdown.js +77 -0
  79. package/core/field_textdropdown.js +164 -0
  80. package/core/field_textinput.js +675 -0
  81. package/core/field_textinput_removable.js +105 -0
  82. package/core/field_variable.js +385 -0
  83. package/core/field_variable_getter.js +185 -0
  84. package/core/field_vertical_separator.js +161 -0
  85. package/core/flyout_base.js +935 -0
  86. package/core/flyout_button.js +324 -0
  87. package/core/flyout_dragger.js +83 -0
  88. package/core/flyout_extension_category_header.js +159 -0
  89. package/core/flyout_horizontal.js +475 -0
  90. package/core/flyout_vertical.js +770 -0
  91. package/core/generator.js +426 -0
  92. package/core/gesture.js +1010 -0
  93. package/core/grid.js +227 -0
  94. package/core/icon.js +205 -0
  95. package/core/inject.js +496 -0
  96. package/core/input.js +285 -0
  97. package/core/insertion_marker_manager.js +678 -0
  98. package/core/intersection_observer.js +102 -0
  99. package/core/msg.js +62 -0
  100. package/core/mutator.js +426 -0
  101. package/core/names.js +198 -0
  102. package/core/options.js +244 -0
  103. package/core/procedures.js +739 -0
  104. package/core/rendered_connection.js +417 -0
  105. package/core/scratch_block_comment.js +646 -0
  106. package/core/scratch_blocks_utils.js +246 -0
  107. package/core/scratch_bubble.js +699 -0
  108. package/core/scratch_events.js +131 -0
  109. package/core/scratch_msgs.js +85 -0
  110. package/core/scrollbar.js +875 -0
  111. package/core/toolbox.js +803 -0
  112. package/core/tooltip.js +337 -0
  113. package/core/touch.js +226 -0
  114. package/core/trashcan.js +343 -0
  115. package/core/ui_events.js +91 -0
  116. package/core/ui_menu_utils.js +68 -0
  117. package/core/utils.js +825 -0
  118. package/core/variable_events.js +259 -0
  119. package/core/variable_map.js +415 -0
  120. package/core/variable_model.js +116 -0
  121. package/core/variables.js +674 -0
  122. package/core/warning.js +199 -0
  123. package/core/widgetdiv.js +344 -0
  124. package/core/workspace.js +673 -0
  125. package/core/workspace_audio.js +170 -0
  126. package/core/workspace_comment.js +426 -0
  127. package/core/workspace_comment_render_svg.js +706 -0
  128. package/core/workspace_comment_svg.js +609 -0
  129. package/core/workspace_drag_surface_svg.js +195 -0
  130. package/core/workspace_dragger.js +132 -0
  131. package/core/workspace_svg.js +2382 -0
  132. package/core/xml.js +930 -0
  133. package/core/zoom_controls.js +301 -0
  134. package/dist/horizontal.js +222 -0
  135. package/dist/vertical.js +222 -0
  136. package/dist/web/horizontal.js +232 -0
  137. package/dist/web/vertical.js +232 -0
  138. package/i18n/common.py +234 -0
  139. package/i18n/create_messages.py +162 -0
  140. package/i18n/create_scratch_msgs.js +69 -0
  141. package/i18n/dedup_json.py +73 -0
  142. package/i18n/js_to_json.js +46 -0
  143. package/i18n/js_to_json.py +136 -0
  144. package/i18n/json_to_js.js +52 -0
  145. package/i18n/json_to_js.py +185 -0
  146. package/i18n/sync_tx_translations.js +111 -0
  147. package/i18n/test_scratch_msgs.js +87 -0
  148. package/i18n/tests.py +47 -0
  149. package/i18n/xliff_to_json.py +232 -0
  150. package/local_build.sh +70 -0
  151. package/media/click.mp3 +0 -0
  152. package/media/click.ogg +0 -0
  153. package/media/click.wav +0 -0
  154. package/media/comment-arrow-down.svg +10 -0
  155. package/media/comment-arrow-up.svg +10 -0
  156. package/media/delete-x.svg +10 -0
  157. package/media/delete.mp3 +0 -0
  158. package/media/delete.ogg +0 -0
  159. package/media/delete.wav +0 -0
  160. package/media/dropdown-arrow-dark.svg +1 -0
  161. package/media/dropdown-arrow.svg +1 -0
  162. package/media/extensions/microbit-block-icon.svg +130 -0
  163. package/media/extensions/music-block-icon.svg +17 -0
  164. package/media/extensions/pen-block-icon.svg +19 -0
  165. package/media/extensions/wedo2-block-icon.svg +36 -0
  166. package/media/eyedropper.svg +22 -0
  167. package/media/green-flag.svg +17 -0
  168. package/media/handclosed.cur +0 -0
  169. package/media/handdelete.cur +0 -0
  170. package/media/handopen.cur +0 -0
  171. package/media/icons/arrow.svg +12 -0
  172. package/media/icons/arrow_button.svg +1 -0
  173. package/media/icons/control_forever.svg +1 -0
  174. package/media/icons/control_repeat.svg +1 -0
  175. package/media/icons/control_stop.svg +1 -0
  176. package/media/icons/control_wait.svg +1 -0
  177. package/media/icons/event_broadcast_blue.svg +1 -0
  178. package/media/icons/event_broadcast_coral.svg +1 -0
  179. package/media/icons/event_broadcast_green.svg +1 -0
  180. package/media/icons/event_broadcast_magenta.svg +1 -0
  181. package/media/icons/event_broadcast_orange.svg +1 -0
  182. package/media/icons/event_broadcast_purple.svg +1 -0
  183. package/media/icons/event_when-broadcast-received_blue.svg +1 -0
  184. package/media/icons/event_when-broadcast-received_coral.svg +1 -0
  185. package/media/icons/event_when-broadcast-received_green.svg +1 -0
  186. package/media/icons/event_when-broadcast-received_magenta.svg +1 -0
  187. package/media/icons/event_when-broadcast-received_orange.svg +1 -0
  188. package/media/icons/event_when-broadcast-received_purple.svg +1 -0
  189. package/media/icons/event_whenflagclicked.svg +1 -0
  190. package/media/icons/remove.svg +19 -0
  191. package/media/icons/set-led_blue.svg +1 -0
  192. package/media/icons/set-led_coral.svg +1 -0
  193. package/media/icons/set-led_green.svg +1 -0
  194. package/media/icons/set-led_magenta.svg +1 -0
  195. package/media/icons/set-led_mystery.svg +1 -0
  196. package/media/icons/set-led_orange.svg +1 -0
  197. package/media/icons/set-led_purple.svg +1 -0
  198. package/media/icons/set-led_white.svg +1 -0
  199. package/media/icons/set-led_yellow.svg +1 -0
  200. package/media/icons/wedo_motor-clockwise.svg +1 -0
  201. package/media/icons/wedo_motor-counterclockwise.svg +1 -0
  202. package/media/icons/wedo_motor-speed_fast.svg +1 -0
  203. package/media/icons/wedo_motor-speed_med.svg +1 -0
  204. package/media/icons/wedo_motor-speed_slow.svg +1 -0
  205. package/media/icons/wedo_when-distance_close.svg +1 -0
  206. package/media/icons/wedo_when-tilt-backward.svg +1 -0
  207. package/media/icons/wedo_when-tilt-forward.svg +1 -0
  208. package/media/icons/wedo_when-tilt-left.svg +1 -0
  209. package/media/icons/wedo_when-tilt-right.svg +1 -0
  210. package/media/icons/wedo_when-tilt.svg +1 -0
  211. package/media/repeat.svg +18 -0
  212. package/media/rotate-left.svg +1 -0
  213. package/media/rotate-right.svg +1 -0
  214. package/media/sprites.png +0 -0
  215. package/media/status-not-ready.svg +13 -0
  216. package/media/status-ready.svg +13 -0
  217. package/media/zoom-in.svg +1 -0
  218. package/media/zoom-out.svg +1 -0
  219. package/media/zoom-reset.svg +1 -0
  220. package/msg/js/en.js +290 -0
  221. package/msg/json/en.json +285 -0
  222. package/msg/messages.js +359 -0
  223. package/msg/scratch_msgs.js +22969 -0
  224. package/package.json +60 -0
  225. package/pull_from_blockly.sh +151 -0
  226. package/renovate.json5 +15 -0
  227. package/shim/blockly_compressed_horizontal-blocks_compressed.js +1 -0
  228. package/shim/blockly_compressed_horizontal.Blockly.js +1 -0
  229. package/shim/blockly_compressed_horizontal.goog.js +1 -0
  230. package/shim/blockly_compressed_horizontal.js +1 -0
  231. package/shim/blockly_compressed_vertical-blocks_compressed.js +1 -0
  232. package/shim/blockly_compressed_vertical.Blockly.js +1 -0
  233. package/shim/blockly_compressed_vertical.goog.js +1 -0
  234. package/shim/blockly_compressed_vertical.js +1 -0
  235. package/shim/blocks_compressed_horizontal-blockly_compressed_horizontal-messages.js +1 -0
  236. package/shim/blocks_compressed_horizontal.js +1 -0
  237. package/shim/blocks_compressed_vertical-blockly_compressed_vertical-messages.js +1 -0
  238. package/shim/blocks_compressed_vertical.js +1 -0
  239. package/shim/gh-pages.js +1 -0
  240. package/shim/horizontal.js +1 -0
  241. package/shim/index.js +17 -0
  242. package/shim/vertical.js +1 -0
  243. package/universal-python.js +82 -0
@@ -0,0 +1,366 @@
1
+ /**
2
+ * @license
3
+ * Visual Blocks Editor
4
+ *
5
+ * Copyright 2016 Massachusetts Institute of Technology
6
+ * All rights reserved.
7
+ *
8
+ * Licensed under the Apache License, Version 2.0 (the "License");
9
+ * you may not use this file except in compliance with the License.
10
+ * You may obtain a copy of the License at
11
+ *
12
+ * http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ */
20
+
21
+ /**
22
+ * @fileoverview Field for numbers. Includes validator and numpad on touch.
23
+ * @author tmickel@mit.edu (Tim Mickel)
24
+ */
25
+ 'use strict';
26
+
27
+ goog.provide('Blockly.FieldNumber');
28
+
29
+ goog.require('Blockly.FieldTextInput');
30
+ goog.require('Blockly.Touch');
31
+ goog.require('goog.math');
32
+ goog.require('goog.userAgent');
33
+
34
+ /**
35
+ * Class for an editable number field.
36
+ * In scratch-blocks, the min/max/precision properties are only used
37
+ * to construct a restrictor on typable characters, and to inform the pop-up
38
+ * numpad on touch devices.
39
+ * These properties are included here (i.e. instead of just accepting a
40
+ * decimalAllowed, negativeAllowed) to maintain API compatibility with Blockly
41
+ * and Blockly for Android.
42
+ * @param {(string|number)=} opt_value The initial content of the field. The value
43
+ * should cast to a number, and if it does not, '0' will be used.
44
+ * @param {(string|number)=} opt_min Minimum value.
45
+ * @param {(string|number)=} opt_max Maximum value.
46
+ * @param {(string|number)=} opt_precision Precision for value.
47
+ * @param {Function=} opt_validator An optional function that is called
48
+ * to validate any constraints on what the user entered. Takes the new
49
+ * text as an argument and returns the accepted text or null to abort
50
+ * the change.
51
+ * @extends {Blockly.FieldTextInput}
52
+ * @constructor
53
+ */
54
+ Blockly.FieldNumber = function(opt_value, opt_min, opt_max, opt_precision,
55
+ opt_validator) {
56
+ var numRestrictor = this.getNumRestrictor(opt_min, opt_max, opt_precision);
57
+ opt_value = (opt_value && !isNaN(opt_value)) ? String(opt_value) : '0';
58
+ Blockly.FieldNumber.superClass_.constructor.call(
59
+ this, opt_value, opt_validator, numRestrictor);
60
+ this.addArgType('number');
61
+ };
62
+ goog.inherits(Blockly.FieldNumber, Blockly.FieldTextInput);
63
+
64
+ /**
65
+ * Construct a FieldNumber from a JSON arg object.
66
+ * @param {!Object} options A JSON object with options (value, min, max, and
67
+ * precision).
68
+ * @returns {!Blockly.FieldNumber} The new field instance.
69
+ * @package
70
+ * @nocollapse
71
+ */
72
+ Blockly.FieldNumber.fromJson = function(options) {
73
+ return new Blockly.FieldNumber(options['value'],
74
+ options['min'], options['max'], options['precision']);
75
+ };
76
+
77
+ /**
78
+ * Fixed width of the num-pad drop-down, in px.
79
+ * @type {number}
80
+ * @const
81
+ */
82
+ Blockly.FieldNumber.DROPDOWN_WIDTH = 168;
83
+
84
+ /**
85
+ * Buttons for the num-pad, in order from the top left.
86
+ * Values are strings of the number or symbol will be added to the field text
87
+ * when the button is pressed.
88
+ * @type {Array.<string>}
89
+ * @const
90
+ */
91
+ // Calculator order
92
+ Blockly.FieldNumber.NUMPAD_BUTTONS =
93
+ ['7', '8', '9', '4', '5', '6', '1', '2', '3', '.', '0', '-', ' '];
94
+
95
+ /**
96
+ * Src for the delete icon to be shown on the num-pad.
97
+ * @type {string}
98
+ * @const
99
+ */
100
+ Blockly.FieldNumber.NUMPAD_DELETE_ICON = 'data:image/svg+xml;utf8,' +
101
+ '<svg ' +
102
+ 'xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">' +
103
+ '<path d="M28.89,11.45H16.79a2.86,2.86,0,0,0-2,.84L9.09,1' +
104
+ '8a2.85,2.85,0,0,0,0,4l5.69,5.69a2.86,2.86,0,0,0,2,.84h12' +
105
+ '.1a2.86,2.86,0,0,0,2.86-2.86V14.31A2.86,2.86,0,0,0,28.89' +
106
+ ',11.45ZM27.15,22.73a1,1,0,0,1,0,1.41,1,1,0,0,1-.71.3,1,1' +
107
+ ',0,0,1-.71-0.3L23,21.41l-2.73,2.73a1,1,0,0,1-1.41,0,1,1,' +
108
+ '0,0,1,0-1.41L21.59,20l-2.73-2.73a1,1,0,0,1,0-1.41,1,1,0,' +
109
+ '0,1,1.41,0L23,18.59l2.73-2.73a1,1,0,1,1,1.42,1.41L24.42,20Z" fill="' +
110
+ Blockly.Colours.numPadText + '"/></svg>';
111
+
112
+ /**
113
+ * Currently active field during an edit.
114
+ * Used to give a reference to the num-pad button callbacks.
115
+ * @type {?FieldNumber}
116
+ * @private
117
+ */
118
+ Blockly.FieldNumber.activeField_ = null;
119
+
120
+ /**
121
+ * Return an appropriate restrictor, depending on whether this FieldNumber
122
+ * allows decimal or negative numbers.
123
+ * @param {number|string|undefined} opt_min Minimum value.
124
+ * @param {number|string|undefined} opt_max Maximum value.
125
+ * @param {number|string|undefined} opt_precision Precision for value.
126
+ * @return {!RegExp} Regular expression for this FieldNumber's restrictor.
127
+ */
128
+ Blockly.FieldNumber.prototype.getNumRestrictor = function(opt_min, opt_max,
129
+ opt_precision) {
130
+ this.setConstraints_(opt_min, opt_max, opt_precision);
131
+ var pattern = "[\\d]"; // Always allow digits.
132
+ if (this.decimalAllowed_) {
133
+ pattern += "|[\\.]";
134
+ }
135
+ if (this.negativeAllowed_) {
136
+ pattern += "|[-]";
137
+ }
138
+ if (this.exponentialAllowed_) {
139
+ pattern += "|[eE]";
140
+ }
141
+ return new RegExp(pattern);
142
+ };
143
+
144
+ /**
145
+ * Set the constraints for this field.
146
+ * @param {number=} opt_min Minimum number allowed.
147
+ * @param {number=} opt_max Maximum number allowed.
148
+ * @param {number=} opt_precision Step allowed between numbers
149
+ */
150
+ Blockly.FieldNumber.prototype.setConstraints_ = function(opt_min, opt_max,
151
+ opt_precision) {
152
+ this.decimalAllowed_ = (typeof opt_precision == 'undefined') ||
153
+ isNaN(opt_precision) || (opt_precision == 0) ||
154
+ (Math.floor(opt_precision) != opt_precision);
155
+ this.negativeAllowed_ = (typeof opt_min == 'undefined') || isNaN(opt_min) ||
156
+ opt_min < 0;
157
+ this.exponentialAllowed_ = this.decimalAllowed_;
158
+ };
159
+
160
+ /**
161
+ * Show the inline free-text editor on top of the text and the num-pad if
162
+ * appropriate.
163
+ * @private
164
+ */
165
+ Blockly.FieldNumber.prototype.showEditor_ = function() {
166
+ Blockly.FieldNumber.activeField_ = this;
167
+ // Do not focus on mobile devices so we can show the num-pad
168
+ var showNumPad = this.useTouchInteraction_;
169
+ Blockly.FieldNumber.superClass_.showEditor_.call(this, false, showNumPad);
170
+
171
+ // Show a numeric keypad in the drop-down on touch
172
+ if (showNumPad) {
173
+ this.showNumPad_();
174
+ }
175
+ };
176
+
177
+ /**
178
+ * Show the number pad.
179
+ * @private
180
+ */
181
+ Blockly.FieldNumber.prototype.showNumPad_ = function() {
182
+ // If there is an existing drop-down someone else owns, hide it immediately
183
+ // and clear it.
184
+ Blockly.DropDownDiv.hideWithoutAnimation();
185
+ Blockly.DropDownDiv.clearContent();
186
+
187
+ var contentDiv = Blockly.DropDownDiv.getContentDiv();
188
+
189
+ // Accessibility properties
190
+ contentDiv.setAttribute('role', 'menu');
191
+ contentDiv.setAttribute('aria-haspopup', 'true');
192
+
193
+ this.addButtons_(contentDiv);
194
+
195
+ // Set colour and size of drop-down
196
+ Blockly.DropDownDiv.setColour(this.sourceBlock_.parentBlock_.getColour(),
197
+ this.sourceBlock_.getColourTertiary());
198
+ contentDiv.style.width = Blockly.FieldNumber.DROPDOWN_WIDTH + 'px';
199
+
200
+ this.position_();
201
+ };
202
+
203
+ /**
204
+ * Figure out where to place the drop-down, and move it there.
205
+ * @private
206
+ */
207
+ Blockly.FieldNumber.prototype.position_ = function() {
208
+ // Calculate positioning for the drop-down
209
+ // sourceBlock_ is the rendered shadow field input box
210
+ var scale = this.sourceBlock_.workspace.scale;
211
+ var bBox = this.sourceBlock_.getHeightWidth();
212
+ bBox.width *= scale;
213
+ bBox.height *= scale;
214
+ var position = this.getAbsoluteXY_();
215
+ // If we can fit it, render below the shadow block
216
+ var primaryX = position.x + bBox.width / 2;
217
+ var primaryY = position.y + bBox.height;
218
+ // If we can't fit it, render above the entire parent block
219
+ var secondaryX = primaryX;
220
+ var secondaryY = position.y;
221
+
222
+ Blockly.DropDownDiv.setBoundsElement(
223
+ this.sourceBlock_.workspace.getParentSvg().parentNode);
224
+ Blockly.DropDownDiv.show(this, primaryX, primaryY, secondaryX, secondaryY,
225
+ this.onHide_.bind(this));
226
+ };
227
+
228
+ /**
229
+ * Add number, punctuation, and erase buttons to the numeric keypad's content
230
+ * div.
231
+ * @param {Element} contentDiv The div for the numeric keypad.
232
+ * @private
233
+ */
234
+ Blockly.FieldNumber.prototype.addButtons_ = function(contentDiv) {
235
+ var buttonColour = this.sourceBlock_.parentBlock_.getColour();
236
+ var buttonBorderColour = this.sourceBlock_.parentBlock_.getColourTertiary();
237
+
238
+ // Add numeric keypad buttons
239
+ var buttons = Blockly.FieldNumber.NUMPAD_BUTTONS;
240
+ for (var i = 0, buttonText; buttonText = buttons[i]; i++) {
241
+ var button = document.createElement('button');
242
+ button.setAttribute('role', 'menuitem');
243
+ button.setAttribute('class', 'blocklyNumPadButton');
244
+ button.setAttribute('style',
245
+ 'background:' + buttonColour + ';' +
246
+ 'border: 1px solid ' + buttonBorderColour + ';');
247
+ button.title = buttonText;
248
+ button.textContent = buttonText;
249
+ Blockly.bindEvent_(button, 'mousedown', button,
250
+ Blockly.FieldNumber.numPadButtonTouch);
251
+ if (buttonText == '.' && !this.decimalAllowed_) {
252
+ // Don't show the decimal point for inputs that must be round numbers
253
+ button.setAttribute('style', 'visibility: hidden');
254
+ } else if (buttonText == '-' && !this.negativeAllowed_) {
255
+ continue;
256
+ } else if (buttonText == ' ' && !this.negativeAllowed_) {
257
+ continue;
258
+ } else if (buttonText == ' ' && this.negativeAllowed_) {
259
+ button.setAttribute('style', 'visibility: hidden');
260
+ }
261
+ contentDiv.appendChild(button);
262
+ }
263
+ // Add erase button to the end
264
+ var eraseButton = document.createElement('button');
265
+ eraseButton.setAttribute('role', 'menuitem');
266
+ eraseButton.setAttribute('class', 'blocklyNumPadButton');
267
+ eraseButton.setAttribute('style',
268
+ 'background:' + buttonColour + ';' +
269
+ 'border: 1px solid ' + buttonBorderColour + ';');
270
+ eraseButton.title = 'Delete';
271
+
272
+ var eraseImage = document.createElement('img');
273
+ eraseImage.src = Blockly.FieldNumber.NUMPAD_DELETE_ICON;
274
+ eraseButton.appendChild(eraseImage);
275
+
276
+ Blockly.bindEvent_(eraseButton, 'mousedown', null,
277
+ Blockly.FieldNumber.numPadEraseButtonTouch);
278
+ contentDiv.appendChild(eraseButton);
279
+ };
280
+
281
+ /**
282
+ * Call for when a num-pad number or punctuation button is touched.
283
+ * Determine what the user is inputting and update the text field appropriately.
284
+ * @param {Event} e DOM event triggering the touch.
285
+ */
286
+ Blockly.FieldNumber.numPadButtonTouch = function(e) {
287
+ // String of the button (e.g., '7')
288
+ var spliceValue = this.innerHTML;
289
+ // Old value of the text field
290
+ var oldValue = Blockly.FieldTextInput.htmlInput_.value;
291
+ // Determine the selected portion of the text field
292
+ var selectionStart = Blockly.FieldTextInput.htmlInput_.selectionStart;
293
+ var selectionEnd = Blockly.FieldTextInput.htmlInput_.selectionEnd;
294
+
295
+ // Splice in the new value
296
+ var newValue = oldValue.slice(0, selectionStart) + spliceValue +
297
+ oldValue.slice(selectionEnd);
298
+
299
+ // Set new value and advance the cursor
300
+ Blockly.FieldNumber.updateDisplay_(newValue, selectionStart + spliceValue.length);
301
+
302
+ // This is just a click.
303
+ Blockly.Touch.clearTouchIdentifier();
304
+
305
+ // Prevent default to not lose input focus
306
+ e.preventDefault();
307
+ };
308
+
309
+ /**
310
+ * Call for when the num-pad erase button is touched.
311
+ * Determine what the user is asking to erase, and erase it.
312
+ * @param {Event} e DOM event triggering the touch.
313
+ */
314
+ Blockly.FieldNumber.numPadEraseButtonTouch = function(e) {
315
+ // Old value of the text field
316
+ var oldValue = Blockly.FieldTextInput.htmlInput_.value;
317
+ // Determine what is selected to erase (if anything)
318
+ var selectionStart = Blockly.FieldTextInput.htmlInput_.selectionStart;
319
+ var selectionEnd = Blockly.FieldTextInput.htmlInput_.selectionEnd;
320
+
321
+ // If selection is zero-length, shift start to the left 1 character
322
+ if (selectionStart == selectionEnd) {
323
+ selectionStart = Math.max(0, selectionStart - 1);
324
+ }
325
+
326
+ // Cut out selected range
327
+ var newValue = oldValue.slice(0, selectionStart) +
328
+ oldValue.slice(selectionEnd);
329
+
330
+ Blockly.FieldNumber.updateDisplay_(newValue, selectionStart);
331
+
332
+ // This is just a click.
333
+ Blockly.Touch.clearTouchIdentifier();
334
+
335
+ // Prevent default to not lose input focus which resets cursors in Chrome
336
+ e.preventDefault();
337
+ };
338
+
339
+ /**
340
+ * Update the displayed value and resize/scroll the text field as needed.
341
+ * @param {string} newValue The new text to display.
342
+ * @param {string} newSelection The new index to put the cursor
343
+ * @private.
344
+ */
345
+ Blockly.FieldNumber.updateDisplay_ = function(newValue, newSelection) {
346
+ var htmlInput = Blockly.FieldTextInput.htmlInput_;
347
+ // Updates the display. The actual setValue occurs when editing ends.
348
+ htmlInput.value = newValue;
349
+ // Resize and scroll the text field appropriately
350
+ Blockly.FieldNumber.superClass_.resizeEditor_.call(
351
+ Blockly.FieldNumber.activeField_);
352
+ htmlInput.setSelectionRange(newSelection, newSelection);
353
+ htmlInput.scrollLeft = htmlInput.scrollWidth;
354
+ Blockly.FieldNumber.activeField_.validate_();
355
+ };
356
+
357
+ /**
358
+ * Callback for when the drop-down is hidden.
359
+ */
360
+ Blockly.FieldNumber.prototype.onHide_ = function() {
361
+ // Clear accessibility properties
362
+ Blockly.DropDownDiv.content_.removeAttribute('role');
363
+ Blockly.DropDownDiv.content_.removeAttribute('aria-haspopup');
364
+ };
365
+
366
+ Blockly.Field.register('field_number', Blockly.FieldNumber);
@@ -0,0 +1,77 @@
1
+ /**
2
+ * @license
3
+ * Visual Blocks Editor
4
+ *
5
+ * Copyright 2013 Google Inc.
6
+ * https://developers.google.com/blockly/
7
+ *
8
+ * Licensed under the Apache License, Version 2.0 (the "License");
9
+ * you may not use this file except in compliance with the License.
10
+ * You may obtain a copy of the License at
11
+ *
12
+ * http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ */
20
+
21
+ /**
22
+ * @fileoverview Combination number + drop-down field
23
+ * @author tmickel@mit.edu (Tim Mickel)
24
+ */
25
+ 'use strict';
26
+
27
+ goog.provide('Blockly.FieldNumberDropdown');
28
+
29
+ goog.require('Blockly.FieldTextDropdown');
30
+ goog.require('goog.userAgent');
31
+
32
+
33
+ /**
34
+ * Class for a combination number + drop-down field.
35
+ * @param {number|string} value The initial content of the field.
36
+ * @param {(!Array.<!Array.<string>>|!Function)} menuGenerator An array of
37
+ * options for a dropdown list, or a function which generates these options.
38
+ * @param {number|string|undefined} opt_min Minimum value.
39
+ * @param {number|string|undefined} opt_max Maximum value.
40
+ * @param {number|string|undefined} opt_precision Precision for value.
41
+ * @param {Function=} opt_validator An optional function that is called
42
+ * to validate any constraints on what the user entered. Takes the new
43
+ * text as an argument and returns the accepted text or null to abort
44
+ * the change.
45
+ * @extends {Blockly.FieldTextInput}
46
+ * @constructor
47
+ */
48
+ Blockly.FieldNumberDropdown = function(value, menuGenerator, opt_min, opt_max,
49
+ opt_precision, opt_validator) {
50
+ this.setConstraints_ = Blockly.FieldNumber.prototype.setConstraints_;
51
+
52
+ var numRestrictor = Blockly.FieldNumber.prototype.getNumRestrictor.call(
53
+ this, opt_min, opt_max, opt_precision
54
+ );
55
+ Blockly.FieldNumberDropdown.superClass_.constructor.call(
56
+ this, value, menuGenerator, opt_validator, numRestrictor
57
+ );
58
+ this.addArgType('numberdropdown');
59
+ };
60
+ goog.inherits(Blockly.FieldNumberDropdown, Blockly.FieldTextDropdown);
61
+
62
+ /**
63
+ * Construct a FieldTextDropdown from a JSON arg object,
64
+ * dereferencing any string table references.
65
+ * @param {!Object} element A JSON object with options.
66
+ * @returns {!Blockly.FieldNumberDropdown} The new field instance.
67
+ * @package
68
+ * @nocollapse
69
+ */
70
+ Blockly.FieldNumberDropdown.fromJson = function(element) {
71
+ return new Blockly.FieldNumberDropdown(
72
+ element['value'], element['options'],
73
+ element['min'], element['max'], element['precision']
74
+ );
75
+ };
76
+
77
+ Blockly.Field.register('field_numberdropdown', Blockly.FieldNumberDropdown);
@@ -0,0 +1,164 @@
1
+ /**
2
+ * @license
3
+ * Visual Blocks Editor
4
+ *
5
+ * Copyright 2013 Google Inc.
6
+ * https://developers.google.com/blockly/
7
+ *
8
+ * Licensed under the Apache License, Version 2.0 (the "License");
9
+ * you may not use this file except in compliance with the License.
10
+ * You may obtain a copy of the License at
11
+ *
12
+ * http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ */
20
+
21
+ /**
22
+ * @fileoverview Combination text + drop-down field
23
+ * @author tmickel@mit.edu (Tim Mickel)
24
+ */
25
+ 'use strict';
26
+
27
+ goog.provide('Blockly.FieldTextDropdown');
28
+
29
+ goog.require('Blockly.DropDownDiv');
30
+ goog.require('Blockly.FieldDropdown');
31
+ goog.require('Blockly.FieldTextInput');
32
+ goog.require('goog.userAgent');
33
+
34
+
35
+ /**
36
+ * Class for a combination text + drop-down field.
37
+ * @param {string} text The initial content of the text field.
38
+ * @param {(!Array.<!Array.<string>>|!Function)} menuGenerator An array of
39
+ * options for a dropdown list, or a function which generates these options.
40
+ * @param {Function=} opt_validator An optional function that is called
41
+ * to validate any constraints on what the user entered. Takes the new
42
+ * text as an argument and returns the accepted text or null to abort
43
+ * the change.
44
+ * @param {RegExp=} opt_restrictor An optional regular expression to restrict
45
+ * typed text to. Text that doesn't match the restrictor will never show
46
+ * in the text field.
47
+ * @extends {Blockly.FieldTextInput}
48
+ * @constructor
49
+ */
50
+ Blockly.FieldTextDropdown = function(text, menuGenerator, opt_validator, opt_restrictor) {
51
+ this.menuGenerator_ = menuGenerator;
52
+ Blockly.FieldDropdown.prototype.trimOptions_.call(this);
53
+ Blockly.FieldTextDropdown.superClass_.constructor.call(this, text, opt_validator, opt_restrictor);
54
+ this.addArgType('textdropdown');
55
+ };
56
+ goog.inherits(Blockly.FieldTextDropdown, Blockly.FieldTextInput);
57
+
58
+ /**
59
+ * Construct a FieldTextDropdown from a JSON arg object,
60
+ * dereferencing any string table references.
61
+ * @param {!Object} element A JSON object with options.
62
+ * @returns {!Blockly.FieldTextDropdown} The new field instance.
63
+ * @package
64
+ * @nocollapse
65
+ */
66
+ Blockly.FieldTextDropdown.fromJson = function(element) {
67
+ var field =
68
+ new Blockly.FieldTextDropdown(element['text'], element['options']);
69
+ if (typeof element['spellcheck'] == 'boolean') {
70
+ field.setSpellcheck(element['spellcheck']);
71
+ }
72
+ return field;
73
+ };
74
+
75
+ /**
76
+ * Install this text drop-down field on a block.
77
+ */
78
+ Blockly.FieldTextDropdown.prototype.init = function() {
79
+ if (this.fieldGroup_) {
80
+ // Text input + dropdown has already been initialized once.
81
+ return;
82
+ }
83
+ Blockly.FieldTextDropdown.superClass_.init.call(this);
84
+ // Add dropdown arrow: "option ▾" (LTR) or "▾ אופציה" (RTL)
85
+ // Positioned on render, after text size is calculated.
86
+ if (!this.arrow_) {
87
+ /** @type {Number} */
88
+ this.arrowSize_ = 12;
89
+ /** @type {Number} */
90
+ this.arrowX_ = 0;
91
+ /** @type {Number} */
92
+ this.arrowY_ = 11;
93
+ this.arrow_ = Blockly.utils.createSvgElement('image',
94
+ {
95
+ 'height': this.arrowSize_ + 'px',
96
+ 'width': this.arrowSize_ + 'px'
97
+ });
98
+ this.arrow_.setAttributeNS('http://www.w3.org/1999/xlink',
99
+ 'xlink:href', Blockly.mainWorkspace.options.pathToMedia + 'dropdown-arrow-dark.svg');
100
+ this.arrow_.style.cursor = 'pointer';
101
+ this.fieldGroup_.appendChild(this.arrow_);
102
+ this.mouseUpWrapper_ =
103
+ Blockly.bindEvent_(this.arrow_, 'mouseup', this, this.showDropdown_);
104
+ }
105
+ // Prevent the drop-down handler from changing the field colour on open.
106
+ this.disableColourChange_ = true;
107
+ };
108
+
109
+ /**
110
+ * Close the input widget if this input is being deleted.
111
+ */
112
+ Blockly.FieldTextDropdown.prototype.dispose = function() {
113
+ if (this.mouseUpWrapper_) {
114
+ Blockly.unbindEvent_(this.mouseUpWrapper_);
115
+ this.mouseUpWrapper_ = null;
116
+ Blockly.Touch.clearTouchIdentifier();
117
+ }
118
+ Blockly.FieldTextDropdown.superClass_.dispose.call(this);
119
+ };
120
+
121
+ /**
122
+ * If the drop-down isn't open, show the text editor.
123
+ */
124
+ Blockly.FieldTextDropdown.prototype.showEditor_ = function() {
125
+ if (!this.dropDownOpen_) {
126
+ Blockly.FieldTextDropdown.superClass_.showEditor_.call(this, null, null,
127
+ true, function() {
128
+ // When the drop-down arrow is clicked, hide text editor and show drop-down.
129
+ Blockly.WidgetDiv.hide();
130
+ this.showDropdown_();
131
+ Blockly.Touch.clearTouchIdentifier();
132
+ });
133
+ }
134
+ };
135
+
136
+ /**
137
+ * Return a list of the options for this dropdown.
138
+ * See: Blockly.FieldDropDown.prototype.getOptions_.
139
+ * @return {!Array.<!Array.<string>>} Array of option tuples:
140
+ * (human-readable text, language-neutral name).
141
+ * @private
142
+ */
143
+ Blockly.FieldTextDropdown.prototype.getOptions_ = Blockly.FieldDropdown.prototype.getOptions_;
144
+
145
+ /**
146
+ * Position a drop-down arrow at the appropriate location at render-time.
147
+ * See: Blockly.FieldDropDown.prototype.positionArrow.
148
+ * @param {number} x X position the arrow is being rendered at, in px.
149
+ * @return {number} Amount of space the arrow is taking up, in px.
150
+ */
151
+ Blockly.FieldTextDropdown.prototype.positionArrow = Blockly.FieldDropdown.prototype.positionArrow;
152
+
153
+ /**
154
+ * Create the dropdown menu.
155
+ * @private
156
+ */
157
+ Blockly.FieldTextDropdown.prototype.showDropdown_ = Blockly.FieldDropdown.prototype.showEditor_;
158
+
159
+ /**
160
+ * Callback when the drop-down menu is hidden.
161
+ */
162
+ Blockly.FieldTextDropdown.prototype.onHide = Blockly.FieldDropdown.prototype.onHide;
163
+
164
+ Blockly.Field.register('field_textdropdown', Blockly.FieldTextDropdown);