@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.
- package/.nvmrc +1 -0
- package/LICENSE +674 -0
- package/README.md +57 -0
- package/TRADEMARK +1 -0
- package/blockly_compressed_horizontal.js +2268 -0
- package/blockly_compressed_vertical.js +2296 -0
- package/blockly_uncompressed_horizontal.js +1212 -0
- package/blockly_uncompressed_vertical.js +1212 -0
- package/blocks_common/colour.js +61 -0
- package/blocks_common/math.js +159 -0
- package/blocks_common/matrix.js +54 -0
- package/blocks_common/note.js +58 -0
- package/blocks_common/text.js +57 -0
- package/blocks_compressed.js +37 -0
- package/blocks_compressed_horizontal.js +68 -0
- package/blocks_compressed_vertical.js +216 -0
- package/blocks_horizontal/control.js +212 -0
- package/blocks_horizontal/default_toolbox.js +139 -0
- package/blocks_horizontal/event.js +190 -0
- package/blocks_horizontal/wedo.js +325 -0
- package/blocks_vertical/control.js +532 -0
- package/blocks_vertical/data.js +666 -0
- package/blocks_vertical/default_toolbox.js +571 -0
- package/blocks_vertical/event.js +329 -0
- package/blocks_vertical/extensions.js +294 -0
- package/blocks_vertical/looks.js +591 -0
- package/blocks_vertical/motion.js +587 -0
- package/blocks_vertical/operators.js +470 -0
- package/blocks_vertical/procedures.js +1051 -0
- package/blocks_vertical/sensing.js +555 -0
- package/blocks_vertical/sound.js +246 -0
- package/blocks_vertical/vertical_extensions.js +289 -0
- package/build/gen_blocks.js +1 -0
- package/build/test_expect.js +1 -0
- package/build/test_input.js +1 -0
- package/build.py +647 -0
- package/cleanup.sh +101 -0
- package/core/block.js +1837 -0
- package/core/block_animations.js +107 -0
- package/core/block_drag_surface.js +299 -0
- package/core/block_dragger.js +424 -0
- package/core/block_events.js +531 -0
- package/core/block_render_svg_horizontal.js +892 -0
- package/core/block_render_svg_vertical.js +1734 -0
- package/core/block_svg.js +1355 -0
- package/core/blockly.js +620 -0
- package/core/blocks.js +37 -0
- package/core/bubble.js +664 -0
- package/core/bubble_dragger.js +285 -0
- package/core/colours.js +177 -0
- package/core/comment.js +293 -0
- package/core/comment_events.js +539 -0
- package/core/connection.js +776 -0
- package/core/connection_db.js +300 -0
- package/core/constants.js +408 -0
- package/core/contextmenu.js +534 -0
- package/core/css.js +1354 -0
- package/core/data_category.js +490 -0
- package/core/dragged_connection_manager.js +260 -0
- package/core/dropdowndiv.js +408 -0
- package/core/events.js +429 -0
- package/core/events_abstract.js +113 -0
- package/core/extensions.js +450 -0
- package/core/field.js +810 -0
- package/core/field_angle.js +410 -0
- package/core/field_checkbox.js +133 -0
- package/core/field_colour.js +253 -0
- package/core/field_colour_slider.js +387 -0
- package/core/field_date.js +353 -0
- package/core/field_dropdown.js +447 -0
- package/core/field_iconmenu.js +309 -0
- package/core/field_image.js +200 -0
- package/core/field_label.js +136 -0
- package/core/field_label_serializable.js +125 -0
- package/core/field_matrix.js +566 -0
- package/core/field_note.js +850 -0
- package/core/field_number.js +366 -0
- package/core/field_numberdropdown.js +77 -0
- package/core/field_textdropdown.js +164 -0
- package/core/field_textinput.js +675 -0
- package/core/field_textinput_removable.js +105 -0
- package/core/field_variable.js +385 -0
- package/core/field_variable_getter.js +185 -0
- package/core/field_vertical_separator.js +161 -0
- package/core/flyout_base.js +935 -0
- package/core/flyout_button.js +324 -0
- package/core/flyout_dragger.js +83 -0
- package/core/flyout_extension_category_header.js +159 -0
- package/core/flyout_horizontal.js +475 -0
- package/core/flyout_vertical.js +770 -0
- package/core/generator.js +426 -0
- package/core/gesture.js +1010 -0
- package/core/grid.js +227 -0
- package/core/icon.js +205 -0
- package/core/inject.js +496 -0
- package/core/input.js +285 -0
- package/core/insertion_marker_manager.js +678 -0
- package/core/intersection_observer.js +102 -0
- package/core/msg.js +62 -0
- package/core/mutator.js +426 -0
- package/core/names.js +198 -0
- package/core/options.js +244 -0
- package/core/procedures.js +739 -0
- package/core/rendered_connection.js +417 -0
- package/core/scratch_block_comment.js +646 -0
- package/core/scratch_blocks_utils.js +246 -0
- package/core/scratch_bubble.js +699 -0
- package/core/scratch_events.js +131 -0
- package/core/scratch_msgs.js +85 -0
- package/core/scrollbar.js +875 -0
- package/core/toolbox.js +803 -0
- package/core/tooltip.js +337 -0
- package/core/touch.js +226 -0
- package/core/trashcan.js +343 -0
- package/core/ui_events.js +91 -0
- package/core/ui_menu_utils.js +68 -0
- package/core/utils.js +825 -0
- package/core/variable_events.js +259 -0
- package/core/variable_map.js +415 -0
- package/core/variable_model.js +116 -0
- package/core/variables.js +674 -0
- package/core/warning.js +199 -0
- package/core/widgetdiv.js +344 -0
- package/core/workspace.js +673 -0
- package/core/workspace_audio.js +170 -0
- package/core/workspace_comment.js +426 -0
- package/core/workspace_comment_render_svg.js +706 -0
- package/core/workspace_comment_svg.js +609 -0
- package/core/workspace_drag_surface_svg.js +195 -0
- package/core/workspace_dragger.js +132 -0
- package/core/workspace_svg.js +2382 -0
- package/core/xml.js +930 -0
- package/core/zoom_controls.js +301 -0
- package/dist/horizontal.js +222 -0
- package/dist/vertical.js +222 -0
- package/dist/web/horizontal.js +232 -0
- package/dist/web/vertical.js +232 -0
- package/i18n/common.py +234 -0
- package/i18n/create_messages.py +162 -0
- package/i18n/create_scratch_msgs.js +69 -0
- package/i18n/dedup_json.py +73 -0
- package/i18n/js_to_json.js +46 -0
- package/i18n/js_to_json.py +136 -0
- package/i18n/json_to_js.js +52 -0
- package/i18n/json_to_js.py +185 -0
- package/i18n/sync_tx_translations.js +111 -0
- package/i18n/test_scratch_msgs.js +87 -0
- package/i18n/tests.py +47 -0
- package/i18n/xliff_to_json.py +232 -0
- package/local_build.sh +70 -0
- package/media/click.mp3 +0 -0
- package/media/click.ogg +0 -0
- package/media/click.wav +0 -0
- package/media/comment-arrow-down.svg +10 -0
- package/media/comment-arrow-up.svg +10 -0
- package/media/delete-x.svg +10 -0
- package/media/delete.mp3 +0 -0
- package/media/delete.ogg +0 -0
- package/media/delete.wav +0 -0
- package/media/dropdown-arrow-dark.svg +1 -0
- package/media/dropdown-arrow.svg +1 -0
- package/media/extensions/microbit-block-icon.svg +130 -0
- package/media/extensions/music-block-icon.svg +17 -0
- package/media/extensions/pen-block-icon.svg +19 -0
- package/media/extensions/wedo2-block-icon.svg +36 -0
- package/media/eyedropper.svg +22 -0
- package/media/green-flag.svg +17 -0
- package/media/handclosed.cur +0 -0
- package/media/handdelete.cur +0 -0
- package/media/handopen.cur +0 -0
- package/media/icons/arrow.svg +12 -0
- package/media/icons/arrow_button.svg +1 -0
- package/media/icons/control_forever.svg +1 -0
- package/media/icons/control_repeat.svg +1 -0
- package/media/icons/control_stop.svg +1 -0
- package/media/icons/control_wait.svg +1 -0
- package/media/icons/event_broadcast_blue.svg +1 -0
- package/media/icons/event_broadcast_coral.svg +1 -0
- package/media/icons/event_broadcast_green.svg +1 -0
- package/media/icons/event_broadcast_magenta.svg +1 -0
- package/media/icons/event_broadcast_orange.svg +1 -0
- package/media/icons/event_broadcast_purple.svg +1 -0
- package/media/icons/event_when-broadcast-received_blue.svg +1 -0
- package/media/icons/event_when-broadcast-received_coral.svg +1 -0
- package/media/icons/event_when-broadcast-received_green.svg +1 -0
- package/media/icons/event_when-broadcast-received_magenta.svg +1 -0
- package/media/icons/event_when-broadcast-received_orange.svg +1 -0
- package/media/icons/event_when-broadcast-received_purple.svg +1 -0
- package/media/icons/event_whenflagclicked.svg +1 -0
- package/media/icons/remove.svg +19 -0
- package/media/icons/set-led_blue.svg +1 -0
- package/media/icons/set-led_coral.svg +1 -0
- package/media/icons/set-led_green.svg +1 -0
- package/media/icons/set-led_magenta.svg +1 -0
- package/media/icons/set-led_mystery.svg +1 -0
- package/media/icons/set-led_orange.svg +1 -0
- package/media/icons/set-led_purple.svg +1 -0
- package/media/icons/set-led_white.svg +1 -0
- package/media/icons/set-led_yellow.svg +1 -0
- package/media/icons/wedo_motor-clockwise.svg +1 -0
- package/media/icons/wedo_motor-counterclockwise.svg +1 -0
- package/media/icons/wedo_motor-speed_fast.svg +1 -0
- package/media/icons/wedo_motor-speed_med.svg +1 -0
- package/media/icons/wedo_motor-speed_slow.svg +1 -0
- package/media/icons/wedo_when-distance_close.svg +1 -0
- package/media/icons/wedo_when-tilt-backward.svg +1 -0
- package/media/icons/wedo_when-tilt-forward.svg +1 -0
- package/media/icons/wedo_when-tilt-left.svg +1 -0
- package/media/icons/wedo_when-tilt-right.svg +1 -0
- package/media/icons/wedo_when-tilt.svg +1 -0
- package/media/repeat.svg +18 -0
- package/media/rotate-left.svg +1 -0
- package/media/rotate-right.svg +1 -0
- package/media/sprites.png +0 -0
- package/media/status-not-ready.svg +13 -0
- package/media/status-ready.svg +13 -0
- package/media/zoom-in.svg +1 -0
- package/media/zoom-out.svg +1 -0
- package/media/zoom-reset.svg +1 -0
- package/msg/js/en.js +290 -0
- package/msg/json/en.json +285 -0
- package/msg/messages.js +359 -0
- package/msg/scratch_msgs.js +22969 -0
- package/package.json +60 -0
- package/pull_from_blockly.sh +151 -0
- package/renovate.json5 +15 -0
- package/shim/blockly_compressed_horizontal-blocks_compressed.js +1 -0
- package/shim/blockly_compressed_horizontal.Blockly.js +1 -0
- package/shim/blockly_compressed_horizontal.goog.js +1 -0
- package/shim/blockly_compressed_horizontal.js +1 -0
- package/shim/blockly_compressed_vertical-blocks_compressed.js +1 -0
- package/shim/blockly_compressed_vertical.Blockly.js +1 -0
- package/shim/blockly_compressed_vertical.goog.js +1 -0
- package/shim/blockly_compressed_vertical.js +1 -0
- package/shim/blocks_compressed_horizontal-blockly_compressed_horizontal-messages.js +1 -0
- package/shim/blocks_compressed_horizontal.js +1 -0
- package/shim/blocks_compressed_vertical-blockly_compressed_vertical-messages.js +1 -0
- package/shim/blocks_compressed_vertical.js +1 -0
- package/shim/gh-pages.js +1 -0
- package/shim/horizontal.js +1 -0
- package/shim/index.js +17 -0
- package/shim/vertical.js +1 -0
- 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);
|