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
|
@@ -31,7 +31,7 @@ JavaScript['math_arithmetic'] = function(block) {
|
|
|
31
31
|
'MINUS': [' - ', JavaScript.ORDER_SUBTRACTION],
|
|
32
32
|
'MULTIPLY': [' * ', JavaScript.ORDER_MULTIPLICATION],
|
|
33
33
|
'DIVIDE': [' / ', JavaScript.ORDER_DIVISION],
|
|
34
|
-
'POWER': [null, JavaScript.ORDER_NONE] // Handle power separately.
|
|
34
|
+
'POWER': [null, JavaScript.ORDER_NONE], // Handle power separately.
|
|
35
35
|
};
|
|
36
36
|
const tuple = OPERATORS[block.getFieldValue('OP')];
|
|
37
37
|
const operator = tuple[0];
|
|
@@ -137,11 +137,10 @@ JavaScript['math_constant'] = function(block) {
|
|
|
137
137
|
const CONSTANTS = {
|
|
138
138
|
'PI': ['Math.PI', JavaScript.ORDER_MEMBER],
|
|
139
139
|
'E': ['Math.E', JavaScript.ORDER_MEMBER],
|
|
140
|
-
'GOLDEN_RATIO':
|
|
141
|
-
['(1 + Math.sqrt(5)) / 2', JavaScript.ORDER_DIVISION],
|
|
140
|
+
'GOLDEN_RATIO': ['(1 + Math.sqrt(5)) / 2', JavaScript.ORDER_DIVISION],
|
|
142
141
|
'SQRT2': ['Math.SQRT2', JavaScript.ORDER_MEMBER],
|
|
143
142
|
'SQRT1_2': ['Math.SQRT1_2', JavaScript.ORDER_MEMBER],
|
|
144
|
-
'INFINITY': ['Infinity', JavaScript.ORDER_ATOMIC]
|
|
143
|
+
'INFINITY': ['Infinity', JavaScript.ORDER_ATOMIC],
|
|
145
144
|
};
|
|
146
145
|
return CONSTANTS[block.getFieldValue('CONSTANT')];
|
|
147
146
|
};
|
|
@@ -149,60 +148,54 @@ JavaScript['math_constant'] = function(block) {
|
|
|
149
148
|
JavaScript['math_number_property'] = function(block) {
|
|
150
149
|
// Check if a number is even, odd, prime, whole, positive, or negative
|
|
151
150
|
// or if it is divisible by certain number. Returns true or false.
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
const PROPERTIES = {
|
|
152
|
+
'EVEN': [' % 2 === 0', JavaScript.ORDER_MODULUS, JavaScript.ORDER_EQUALITY],
|
|
153
|
+
'ODD': [' % 2 === 1', JavaScript.ORDER_MODULUS, JavaScript.ORDER_EQUALITY],
|
|
154
|
+
'WHOLE': [' % 1 === 0', JavaScript.ORDER_MODULUS,
|
|
155
|
+
JavaScript.ORDER_EQUALITY],
|
|
156
|
+
'POSITIVE': [' > 0', JavaScript.ORDER_RELATIONAL,
|
|
157
|
+
JavaScript.ORDER_RELATIONAL],
|
|
158
|
+
'NEGATIVE': [' < 0', JavaScript.ORDER_RELATIONAL,
|
|
159
|
+
JavaScript.ORDER_RELATIONAL],
|
|
160
|
+
'DIVISIBLE_BY': [null, JavaScript.ORDER_MODULUS, JavaScript.ORDER_EQUALITY],
|
|
161
|
+
'PRIME': [null, JavaScript.ORDER_NONE, JavaScript.ORDER_FUNCTION_CALL],
|
|
162
|
+
};
|
|
163
|
+
const dropdownProperty = block.getFieldValue('PROPERTY');
|
|
164
|
+
const [suffix, inputOrder, outputOrder] = PROPERTIES[dropdownProperty];
|
|
165
|
+
const numberToCheck = JavaScript.valueToCode(block, 'NUMBER_TO_CHECK',
|
|
166
|
+
inputOrder) || '0';
|
|
155
167
|
let code;
|
|
156
|
-
if (
|
|
168
|
+
if (dropdownProperty === 'PRIME') {
|
|
157
169
|
// Prime is a special case as it is not a one-liner test.
|
|
158
|
-
const functionName = JavaScript.provideFunction_(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
' return true;',
|
|
164
|
-
' }',
|
|
165
|
-
' // False if n is NaN, negative, is 1, or not whole.',
|
|
166
|
-
' // And false if n is divisible by 2 or 3.',
|
|
167
|
-
' if (isNaN(n) || n <= 1 || n % 1 !== 0 || n % 2 === 0 ||' +
|
|
168
|
-
' n % 3 === 0) {',
|
|
169
|
-
' return false;',
|
|
170
|
-
' }',
|
|
171
|
-
' // Check all the numbers of form 6k +/- 1, up to sqrt(n).',
|
|
172
|
-
' for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {',
|
|
173
|
-
' if (n % (x - 1) === 0 || n % (x + 1) === 0) {',
|
|
174
|
-
' return false;',
|
|
175
|
-
' }',
|
|
176
|
-
' }',
|
|
177
|
-
' return true;',
|
|
178
|
-
'}']);
|
|
179
|
-
code = functionName + '(' + number_to_check + ')';
|
|
180
|
-
return [code, JavaScript.ORDER_FUNCTION_CALL];
|
|
170
|
+
const functionName = JavaScript.provideFunction_('mathIsPrime', `
|
|
171
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(n) {
|
|
172
|
+
// https://en.wikipedia.org/wiki/Primality_test#Naive_methods
|
|
173
|
+
if (n == 2 || n == 3) {
|
|
174
|
+
return true;
|
|
181
175
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
break;
|
|
192
|
-
case 'POSITIVE':
|
|
193
|
-
code = number_to_check + ' > 0';
|
|
194
|
-
break;
|
|
195
|
-
case 'NEGATIVE':
|
|
196
|
-
code = number_to_check + ' < 0';
|
|
197
|
-
break;
|
|
198
|
-
case 'DIVISIBLE_BY': {
|
|
199
|
-
const divisor = JavaScript.valueToCode(block, 'DIVISOR',
|
|
200
|
-
JavaScript.ORDER_MODULUS) || '0';
|
|
201
|
-
code = number_to_check + ' % ' + divisor + ' === 0';
|
|
202
|
-
break;
|
|
176
|
+
// False if n is NaN, negative, is 1, or not whole.
|
|
177
|
+
// And false if n is divisible by 2 or 3.
|
|
178
|
+
if (isNaN(n) || n <= 1 || n % 1 !== 0 || n % 2 === 0 || n % 3 === 0) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
// Check all the numbers of form 6k +/- 1, up to sqrt(n).
|
|
182
|
+
for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {
|
|
183
|
+
if (n % (x - 1) === 0 || n % (x + 1) === 0) {
|
|
184
|
+
return false;
|
|
203
185
|
}
|
|
204
186
|
}
|
|
205
|
-
return
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
`);
|
|
190
|
+
code = functionName + '(' + numberToCheck + ')';
|
|
191
|
+
} else if (dropdownProperty === 'DIVISIBLE_BY') {
|
|
192
|
+
const divisor = JavaScript.valueToCode(block, 'DIVISOR',
|
|
193
|
+
JavaScript.ORDER_MODULUS) || '0';
|
|
194
|
+
code = numberToCheck + ' % ' + divisor + ' === 0';
|
|
195
|
+
} else {
|
|
196
|
+
code = numberToCheck + suffix;
|
|
197
|
+
}
|
|
198
|
+
return [code, outputOrder];
|
|
206
199
|
};
|
|
207
200
|
|
|
208
201
|
JavaScript['math_change'] = function(block) {
|
|
@@ -243,13 +236,11 @@ JavaScript['math_on_list'] = function(block) {
|
|
|
243
236
|
break;
|
|
244
237
|
case 'AVERAGE': {
|
|
245
238
|
// mathMean([null,null,1,3]) === 2.0.
|
|
246
|
-
const functionName = JavaScript.provideFunction_(
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
'myList.length;',
|
|
252
|
-
'}']);
|
|
239
|
+
const functionName = JavaScript.provideFunction_('mathMean', `
|
|
240
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(myList) {
|
|
241
|
+
return myList.reduce(function(x, y) {return x + y;}) / myList.length;
|
|
242
|
+
}
|
|
243
|
+
`);
|
|
253
244
|
list = JavaScript.valueToCode(block, 'LIST',
|
|
254
245
|
JavaScript.ORDER_NONE) || '[]';
|
|
255
246
|
code = functionName + '(' + list + ')';
|
|
@@ -257,21 +248,18 @@ JavaScript['math_on_list'] = function(block) {
|
|
|
257
248
|
}
|
|
258
249
|
case 'MEDIAN': {
|
|
259
250
|
// mathMedian([null,null,1,3]) === 2.0.
|
|
260
|
-
const functionName = JavaScript.provideFunction_(
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
' return localList[(localList.length - 1) / 2];',
|
|
273
|
-
' }',
|
|
274
|
-
'}']);
|
|
251
|
+
const functionName = JavaScript.provideFunction_('mathMedian', `
|
|
252
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(myList) {
|
|
253
|
+
var localList = myList.filter(function (x) {return typeof x === \'number\';});
|
|
254
|
+
if (!localList.length) return null;
|
|
255
|
+
localList.sort(function(a, b) {return b - a;});
|
|
256
|
+
if (localList.length % 2 === 0) {
|
|
257
|
+
return (localList[localList.length / 2 - 1] + localList[localList.length / 2]) / 2;
|
|
258
|
+
} else {
|
|
259
|
+
return localList[(localList.length - 1) / 2];
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
`);
|
|
275
263
|
list = JavaScript.valueToCode(block, 'LIST',
|
|
276
264
|
JavaScript.ORDER_NONE) || '[]';
|
|
277
265
|
code = functionName + '(' + list + ')';
|
|
@@ -281,70 +269,67 @@ JavaScript['math_on_list'] = function(block) {
|
|
|
281
269
|
// As a list of numbers can contain more than one mode,
|
|
282
270
|
// the returned result is provided as an array.
|
|
283
271
|
// Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1].
|
|
284
|
-
const functionName = JavaScript.provideFunction_(
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
'}']);
|
|
272
|
+
const functionName = JavaScript.provideFunction_('mathModes', `
|
|
273
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(values) {
|
|
274
|
+
var modes = [];
|
|
275
|
+
var counts = [];
|
|
276
|
+
var maxCount = 0;
|
|
277
|
+
for (var i = 0; i < values.length; i++) {
|
|
278
|
+
var value = values[i];
|
|
279
|
+
var found = false;
|
|
280
|
+
var thisCount;
|
|
281
|
+
for (var j = 0; j < counts.length; j++) {
|
|
282
|
+
if (counts[j][0] === value) {
|
|
283
|
+
thisCount = ++counts[j][1];
|
|
284
|
+
found = true;
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (!found) {
|
|
289
|
+
counts.push([value, 1]);
|
|
290
|
+
thisCount = 1;
|
|
291
|
+
}
|
|
292
|
+
maxCount = Math.max(thisCount, maxCount);
|
|
293
|
+
}
|
|
294
|
+
for (var j = 0; j < counts.length; j++) {
|
|
295
|
+
if (counts[j][1] === maxCount) {
|
|
296
|
+
modes.push(counts[j][0]);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return modes;
|
|
300
|
+
}
|
|
301
|
+
`);
|
|
315
302
|
list = JavaScript.valueToCode(block, 'LIST',
|
|
316
303
|
JavaScript.ORDER_NONE) || '[]';
|
|
317
304
|
code = functionName + '(' + list + ')';
|
|
318
305
|
break;
|
|
319
306
|
}
|
|
320
307
|
case 'STD_DEV': {
|
|
321
|
-
const functionName = JavaScript.provideFunction_(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
'}']);
|
|
308
|
+
const functionName = JavaScript.provideFunction_('mathStandardDeviation', `
|
|
309
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(numbers) {
|
|
310
|
+
var n = numbers.length;
|
|
311
|
+
if (!n) return null;
|
|
312
|
+
var mean = numbers.reduce(function(x, y) {return x + y;}) / n;
|
|
313
|
+
var variance = 0;
|
|
314
|
+
for (var j = 0; j < n; j++) {
|
|
315
|
+
variance += Math.pow(numbers[j] - mean, 2);
|
|
316
|
+
}
|
|
317
|
+
variance = variance / n;
|
|
318
|
+
return Math.sqrt(variance);
|
|
319
|
+
}
|
|
320
|
+
`);
|
|
335
321
|
list = JavaScript.valueToCode(block, 'LIST',
|
|
336
322
|
JavaScript.ORDER_NONE) || '[]';
|
|
337
323
|
code = functionName + '(' + list + ')';
|
|
338
324
|
break;
|
|
339
325
|
}
|
|
340
326
|
case 'RANDOM': {
|
|
341
|
-
const functionName = JavaScript.provideFunction_(
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
'}']);
|
|
327
|
+
const functionName = JavaScript.provideFunction_('mathRandomList', `
|
|
328
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(list) {
|
|
329
|
+
var x = Math.floor(Math.random() * list.length);
|
|
330
|
+
return list[x];
|
|
331
|
+
}
|
|
332
|
+
`);
|
|
348
333
|
list = JavaScript.valueToCode(block, 'LIST',
|
|
349
334
|
JavaScript.ORDER_NONE) || '[]';
|
|
350
335
|
code = functionName + '(' + list + ')';
|
|
@@ -385,18 +370,17 @@ JavaScript['math_random_int'] = function(block) {
|
|
|
385
370
|
JavaScript.ORDER_NONE) || '0';
|
|
386
371
|
const argument1 = JavaScript.valueToCode(block, 'TO',
|
|
387
372
|
JavaScript.ORDER_NONE) || '0';
|
|
388
|
-
const functionName = JavaScript.provideFunction_(
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
'}']);
|
|
373
|
+
const functionName = JavaScript.provideFunction_('mathRandomInt', `
|
|
374
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(a, b) {
|
|
375
|
+
if (a > b) {
|
|
376
|
+
// Swap a and b to ensure a is smaller.
|
|
377
|
+
var c = a;
|
|
378
|
+
a = b;
|
|
379
|
+
b = c;
|
|
380
|
+
}
|
|
381
|
+
return Math.floor(Math.random() * (b - a + 1) + a);
|
|
382
|
+
}
|
|
383
|
+
`);
|
|
400
384
|
const code = functionName + '(' + argument0 + ', ' + argument1 + ')';
|
|
401
385
|
return [code, JavaScript.ORDER_FUNCTION_CALL];
|
|
402
386
|
};
|
|
@@ -71,18 +71,18 @@ JavaScript['text_join'] = function(block) {
|
|
|
71
71
|
// Create a string made up of any number of elements of any type.
|
|
72
72
|
switch (block.itemCount_) {
|
|
73
73
|
case 0:
|
|
74
|
-
return ['
|
|
74
|
+
return ["''", JavaScript.ORDER_ATOMIC];
|
|
75
75
|
case 1: {
|
|
76
76
|
const element = JavaScript.valueToCode(block, 'ADD0',
|
|
77
|
-
JavaScript.ORDER_NONE) || '
|
|
77
|
+
JavaScript.ORDER_NONE) || "''";
|
|
78
78
|
const codeAndOrder = forceString(element);
|
|
79
79
|
return codeAndOrder;
|
|
80
80
|
}
|
|
81
81
|
case 2: {
|
|
82
82
|
const element0 = JavaScript.valueToCode(block, 'ADD0',
|
|
83
|
-
JavaScript.ORDER_NONE) || '
|
|
83
|
+
JavaScript.ORDER_NONE) || "''";
|
|
84
84
|
const element1 = JavaScript.valueToCode(block, 'ADD1',
|
|
85
|
-
JavaScript.ORDER_NONE) || '
|
|
85
|
+
JavaScript.ORDER_NONE) || "''";
|
|
86
86
|
const code = forceString(element0)[0] +
|
|
87
87
|
' + ' + forceString(element1)[0];
|
|
88
88
|
return [code, JavaScript.ORDER_ADDITION];
|
|
@@ -91,7 +91,7 @@ JavaScript['text_join'] = function(block) {
|
|
|
91
91
|
const elements = new Array(block.itemCount_);
|
|
92
92
|
for (let i = 0; i < block.itemCount_; i++) {
|
|
93
93
|
elements[i] = JavaScript.valueToCode(block, 'ADD' + i,
|
|
94
|
-
JavaScript.ORDER_NONE) || '
|
|
94
|
+
JavaScript.ORDER_NONE) || "''";
|
|
95
95
|
}
|
|
96
96
|
const code = '[' + elements.join(',') + '].join(\'\')';
|
|
97
97
|
return [code, JavaScript.ORDER_FUNCTION_CALL];
|
|
@@ -104,7 +104,7 @@ JavaScript['text_append'] = function(block) {
|
|
|
104
104
|
const varName = JavaScript.nameDB_.getName(
|
|
105
105
|
block.getFieldValue('VAR'), NameType.VARIABLE);
|
|
106
106
|
const value = JavaScript.valueToCode(block, 'TEXT',
|
|
107
|
-
JavaScript.ORDER_NONE) || '
|
|
107
|
+
JavaScript.ORDER_NONE) || "''";
|
|
108
108
|
const code = varName + ' += ' +
|
|
109
109
|
forceString(value)[0] + ';\n';
|
|
110
110
|
return code;
|
|
@@ -113,14 +113,14 @@ JavaScript['text_append'] = function(block) {
|
|
|
113
113
|
JavaScript['text_length'] = function(block) {
|
|
114
114
|
// String or array length.
|
|
115
115
|
const text = JavaScript.valueToCode(block, 'VALUE',
|
|
116
|
-
JavaScript.ORDER_MEMBER) || '
|
|
116
|
+
JavaScript.ORDER_MEMBER) || "''";
|
|
117
117
|
return [text + '.length', JavaScript.ORDER_MEMBER];
|
|
118
118
|
};
|
|
119
119
|
|
|
120
120
|
JavaScript['text_isEmpty'] = function(block) {
|
|
121
121
|
// Is the string null or array empty?
|
|
122
122
|
const text = JavaScript.valueToCode(block, 'VALUE',
|
|
123
|
-
JavaScript.ORDER_MEMBER) || '
|
|
123
|
+
JavaScript.ORDER_MEMBER) || "''";
|
|
124
124
|
return ['!' + text + '.length', JavaScript.ORDER_LOGICAL_NOT];
|
|
125
125
|
};
|
|
126
126
|
|
|
@@ -129,9 +129,9 @@ JavaScript['text_indexOf'] = function(block) {
|
|
|
129
129
|
const operator = block.getFieldValue('END') === 'FIRST' ?
|
|
130
130
|
'indexOf' : 'lastIndexOf';
|
|
131
131
|
const substring = JavaScript.valueToCode(block, 'FIND',
|
|
132
|
-
JavaScript.ORDER_NONE) || '
|
|
132
|
+
JavaScript.ORDER_NONE) || "''";
|
|
133
133
|
const text = JavaScript.valueToCode(block, 'VALUE',
|
|
134
|
-
JavaScript.ORDER_MEMBER) || '
|
|
134
|
+
JavaScript.ORDER_MEMBER) || "''";
|
|
135
135
|
const code = text + '.' + operator + '(' + substring + ')';
|
|
136
136
|
// Adjust index if using one-based indices.
|
|
137
137
|
if (block.workspace.options.oneBasedIndex) {
|
|
@@ -146,8 +146,7 @@ JavaScript['text_charAt'] = function(block) {
|
|
|
146
146
|
const where = block.getFieldValue('WHERE') || 'FROM_START';
|
|
147
147
|
const textOrder = (where === 'RANDOM') ? JavaScript.ORDER_NONE :
|
|
148
148
|
JavaScript.ORDER_MEMBER;
|
|
149
|
-
const text = JavaScript.valueToCode(block, 'VALUE',
|
|
150
|
-
textOrder) || '\'\'';
|
|
149
|
+
const text = JavaScript.valueToCode(block, 'VALUE', textOrder) || "''";
|
|
151
150
|
switch (where) {
|
|
152
151
|
case 'FIRST': {
|
|
153
152
|
const code = text + '.charAt(0)';
|
|
@@ -169,13 +168,12 @@ JavaScript['text_charAt'] = function(block) {
|
|
|
169
168
|
return [code, JavaScript.ORDER_FUNCTION_CALL];
|
|
170
169
|
}
|
|
171
170
|
case 'RANDOM': {
|
|
172
|
-
const functionName = JavaScript.provideFunction_(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
'}']);
|
|
171
|
+
const functionName = JavaScript.provideFunction_('textRandomLetter', `
|
|
172
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(text) {
|
|
173
|
+
var x = Math.floor(Math.random() * text.length);
|
|
174
|
+
return text[x];
|
|
175
|
+
}
|
|
176
|
+
`);
|
|
179
177
|
const code = functionName + '(' + text + ')';
|
|
180
178
|
return [code, JavaScript.ORDER_FUNCTION_CALL];
|
|
181
179
|
}
|
|
@@ -191,8 +189,7 @@ JavaScript['text_getSubstring'] = function(block) {
|
|
|
191
189
|
where2 !== 'FROM_END' && where2 !== 'LAST');
|
|
192
190
|
const textOrder = requiresLengthCall ? JavaScript.ORDER_MEMBER :
|
|
193
191
|
JavaScript.ORDER_NONE;
|
|
194
|
-
const text = JavaScript.valueToCode(block, 'STRING',
|
|
195
|
-
textOrder) || '\'\'';
|
|
192
|
+
const text = JavaScript.valueToCode(block, 'STRING', textOrder) || "''";
|
|
196
193
|
let code;
|
|
197
194
|
if (where1 === 'FIRST' && where2 === 'LAST') {
|
|
198
195
|
code = text;
|
|
@@ -238,22 +235,20 @@ JavaScript['text_getSubstring'] = function(block) {
|
|
|
238
235
|
const at2 = JavaScript.getAdjusted(block, 'AT2');
|
|
239
236
|
const wherePascalCase = {'FIRST': 'First', 'LAST': 'Last',
|
|
240
237
|
'FROM_START': 'FromStart', 'FROM_END': 'FromEnd'};
|
|
238
|
+
// The value for 'FROM_END' and'FROM_START' depends on `at` so
|
|
239
|
+
// we add it as a parameter.
|
|
240
|
+
const at1Param =
|
|
241
|
+
(where1 === 'FROM_END' || where1 === 'FROM_START') ? ', at1' : '';
|
|
242
|
+
const at2Param =
|
|
243
|
+
(where2 === 'FROM_END' || where2 === 'FROM_START') ? ', at2' : '';
|
|
241
244
|
const functionName = JavaScript.provideFunction_(
|
|
242
|
-
'subsequence' + wherePascalCase[where1] + wherePascalCase[where2],
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
((where2 === 'FROM_END' || where2 === 'FROM_START') ? ', at2' :
|
|
250
|
-
'') +
|
|
251
|
-
') {',
|
|
252
|
-
' var start = ' + getSubstringIndex('sequence', where1, 'at1') + ';',
|
|
253
|
-
' var end = ' + getSubstringIndex('sequence', where2, 'at2') +
|
|
254
|
-
' + 1;',
|
|
255
|
-
' return sequence.slice(start, end);', '}'
|
|
256
|
-
]);
|
|
245
|
+
'subsequence' + wherePascalCase[where1] + wherePascalCase[where2], `
|
|
246
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(sequence${at1Param}${at2Param}) {
|
|
247
|
+
var start = ${getSubstringIndex('sequence', where1, 'at1')};
|
|
248
|
+
var end = ${getSubstringIndex('sequence', where2, 'at2')} + 1;
|
|
249
|
+
return sequence.slice(start, end);
|
|
250
|
+
}
|
|
251
|
+
`);
|
|
257
252
|
code = functionName + '(' + text +
|
|
258
253
|
// The value for 'FROM_END' and 'FROM_START' depends on `at` so we
|
|
259
254
|
// pass it.
|
|
@@ -269,27 +264,23 @@ JavaScript['text_changeCase'] = function(block) {
|
|
|
269
264
|
const OPERATORS = {
|
|
270
265
|
'UPPERCASE': '.toUpperCase()',
|
|
271
266
|
'LOWERCASE': '.toLowerCase()',
|
|
272
|
-
'TITLECASE': null
|
|
267
|
+
'TITLECASE': null,
|
|
273
268
|
};
|
|
274
269
|
const operator = OPERATORS[block.getFieldValue('CASE')];
|
|
275
|
-
const textOrder = operator ? JavaScript.ORDER_MEMBER :
|
|
276
|
-
|
|
277
|
-
const text = JavaScript.valueToCode(block, 'TEXT',
|
|
278
|
-
textOrder) || '\'\'';
|
|
270
|
+
const textOrder = operator ? JavaScript.ORDER_MEMBER : JavaScript.ORDER_NONE;
|
|
271
|
+
const text = JavaScript.valueToCode(block, 'TEXT', textOrder) || "''";
|
|
279
272
|
let code;
|
|
280
273
|
if (operator) {
|
|
281
274
|
// Upper and lower case are functions built into JavaScript.
|
|
282
275
|
code = text + operator;
|
|
283
276
|
} else {
|
|
284
277
|
// Title case is not a native JavaScript function. Define one.
|
|
285
|
-
const functionName = JavaScript.provideFunction_(
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
'txt.substring(1).toLowerCase();});',
|
|
292
|
-
'}']);
|
|
278
|
+
const functionName = JavaScript.provideFunction_('textToTitleCase', `
|
|
279
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(str) {
|
|
280
|
+
return str.replace(/\\S+/g,
|
|
281
|
+
function(txt) {return txt[0].toUpperCase() + txt.substring(1).toLowerCase();});
|
|
282
|
+
}
|
|
283
|
+
`);
|
|
293
284
|
code = functionName + '(' + text + ')';
|
|
294
285
|
}
|
|
295
286
|
return [code, JavaScript.ORDER_FUNCTION_CALL];
|
|
@@ -300,18 +291,18 @@ JavaScript['text_trim'] = function(block) {
|
|
|
300
291
|
const OPERATORS = {
|
|
301
292
|
'LEFT': ".replace(/^[\\s\\xa0]+/, '')",
|
|
302
293
|
'RIGHT': ".replace(/[\\s\\xa0]+$/, '')",
|
|
303
|
-
'BOTH': '.trim()'
|
|
294
|
+
'BOTH': '.trim()',
|
|
304
295
|
};
|
|
305
296
|
const operator = OPERATORS[block.getFieldValue('MODE')];
|
|
306
297
|
const text = JavaScript.valueToCode(block, 'TEXT',
|
|
307
|
-
JavaScript.ORDER_MEMBER) || '
|
|
298
|
+
JavaScript.ORDER_MEMBER) || "''";
|
|
308
299
|
return [text + operator, JavaScript.ORDER_FUNCTION_CALL];
|
|
309
300
|
};
|
|
310
301
|
|
|
311
302
|
JavaScript['text_print'] = function(block) {
|
|
312
303
|
// Print statement.
|
|
313
304
|
const msg = JavaScript.valueToCode(block, 'TEXT',
|
|
314
|
-
JavaScript.ORDER_NONE) || '
|
|
305
|
+
JavaScript.ORDER_NONE) || "''";
|
|
315
306
|
return 'window.alert(' + msg + ');\n';
|
|
316
307
|
};
|
|
317
308
|
|
|
@@ -323,8 +314,7 @@ JavaScript['text_prompt_ext'] = function(block) {
|
|
|
323
314
|
msg = JavaScript.quote_(block.getFieldValue('TEXT'));
|
|
324
315
|
} else {
|
|
325
316
|
// External message.
|
|
326
|
-
msg = JavaScript.valueToCode(block, 'TEXT',
|
|
327
|
-
JavaScript.ORDER_NONE) || '\'\'';
|
|
317
|
+
msg = JavaScript.valueToCode(block, 'TEXT', JavaScript.ORDER_NONE) || "''";
|
|
328
318
|
}
|
|
329
319
|
let code = 'window.prompt(' + msg + ')';
|
|
330
320
|
const toNumber = block.getFieldValue('TYPE') === 'NUMBER';
|
|
@@ -338,48 +328,44 @@ JavaScript['text_prompt'] = JavaScript['text_prompt_ext'];
|
|
|
338
328
|
|
|
339
329
|
JavaScript['text_count'] = function(block) {
|
|
340
330
|
const text = JavaScript.valueToCode(block, 'TEXT',
|
|
341
|
-
JavaScript.ORDER_NONE) || '
|
|
331
|
+
JavaScript.ORDER_NONE) || "''";
|
|
342
332
|
const sub = JavaScript.valueToCode(block, 'SUB',
|
|
343
|
-
JavaScript.ORDER_NONE) || '
|
|
344
|
-
const functionName = JavaScript.provideFunction_(
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
'}']);
|
|
333
|
+
JavaScript.ORDER_NONE) || "''";
|
|
334
|
+
const functionName = JavaScript.provideFunction_('textCount', `
|
|
335
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(haystack, needle) {
|
|
336
|
+
if (needle.length === 0) {
|
|
337
|
+
return haystack.length + 1;
|
|
338
|
+
} else {
|
|
339
|
+
return haystack.split(needle).length - 1;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
`);
|
|
354
343
|
const code = functionName + '(' + text + ', ' + sub + ')';
|
|
355
344
|
return [code, JavaScript.ORDER_FUNCTION_CALL];
|
|
356
345
|
};
|
|
357
346
|
|
|
358
347
|
JavaScript['text_replace'] = function(block) {
|
|
359
348
|
const text = JavaScript.valueToCode(block, 'TEXT',
|
|
360
|
-
JavaScript.ORDER_NONE) || '
|
|
349
|
+
JavaScript.ORDER_NONE) || "''";
|
|
361
350
|
const from = JavaScript.valueToCode(block, 'FROM',
|
|
362
|
-
JavaScript.ORDER_NONE) || '
|
|
363
|
-
const to = JavaScript.valueToCode(block, 'TO',
|
|
364
|
-
JavaScript.ORDER_NONE) || '\'\'';
|
|
351
|
+
JavaScript.ORDER_NONE) || "''";
|
|
352
|
+
const to = JavaScript.valueToCode(block, 'TO', JavaScript.ORDER_NONE) || "''";
|
|
365
353
|
// The regex escaping code below is taken from the implementation of
|
|
366
354
|
// goog.string.regExpEscape.
|
|
367
|
-
const functionName = JavaScript.provideFunction_(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
' return haystack.replace(new RegExp(needle, \'g\'), replacement);',
|
|
375
|
-
'}']);
|
|
355
|
+
const functionName = JavaScript.provideFunction_('textReplace', `
|
|
356
|
+
function ${JavaScript.FUNCTION_NAME_PLACEHOLDER_}(haystack, needle, replacement) {
|
|
357
|
+
needle = needle.replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1')
|
|
358
|
+
.replace(/\\x08/g, '\\\\x08');
|
|
359
|
+
return haystack.replace(new RegExp(needle, \'g\'), replacement);
|
|
360
|
+
}
|
|
361
|
+
`);
|
|
376
362
|
const code = functionName + '(' + text + ', ' + from + ', ' + to + ')';
|
|
377
363
|
return [code, JavaScript.ORDER_FUNCTION_CALL];
|
|
378
364
|
};
|
|
379
365
|
|
|
380
366
|
JavaScript['text_reverse'] = function(block) {
|
|
381
367
|
const text = JavaScript.valueToCode(block, 'TEXT',
|
|
382
|
-
JavaScript.ORDER_MEMBER) || '
|
|
383
|
-
const code = text +
|
|
368
|
+
JavaScript.ORDER_MEMBER) || "''";
|
|
369
|
+
const code = text + ".split('').reverse().join('')";
|
|
384
370
|
return [code, JavaScript.ORDER_FUNCTION_CALL];
|
|
385
371
|
};
|