@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,309 @@
|
|
|
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 Icon picker input field.
|
|
23
|
+
* This is primarily for use in Scratch Horizontal blocks.
|
|
24
|
+
* Pops open a drop-down with icons; when an icon is selected, it replaces
|
|
25
|
+
* the icon (image field) in the original block.
|
|
26
|
+
* @author tmickel@mit.edu (Tim Mickel)
|
|
27
|
+
*/
|
|
28
|
+
'use strict';
|
|
29
|
+
|
|
30
|
+
goog.provide('Blockly.FieldIconMenu');
|
|
31
|
+
|
|
32
|
+
goog.require('Blockly.DropDownDiv');
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Class for an icon menu field.
|
|
36
|
+
* @param {Object} icons List of icons. These take the same options as an Image Field.
|
|
37
|
+
* @extends {Blockly.Field}
|
|
38
|
+
* @constructor
|
|
39
|
+
*/
|
|
40
|
+
Blockly.FieldIconMenu = function(icons) {
|
|
41
|
+
/** @type {object} */
|
|
42
|
+
this.icons_ = icons;
|
|
43
|
+
// Example:
|
|
44
|
+
// [{src: '...', width: 20, height: 20, alt: '...', value: 'machine_value'}, ...]
|
|
45
|
+
// First icon provides the default values.
|
|
46
|
+
var defaultValue = icons[0].value;
|
|
47
|
+
Blockly.FieldIconMenu.superClass_.constructor.call(this, defaultValue);
|
|
48
|
+
this.addArgType('iconmenu');
|
|
49
|
+
};
|
|
50
|
+
goog.inherits(Blockly.FieldIconMenu, Blockly.Field);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Construct a FieldIconMenu from a JSON arg object.
|
|
54
|
+
* @param {!Object} element A JSON object with options.
|
|
55
|
+
* @returns {!Blockly.FieldIconMenu} The new field instance.
|
|
56
|
+
* @package
|
|
57
|
+
* @nocollapse
|
|
58
|
+
*/
|
|
59
|
+
Blockly.FieldIconMenu.fromJson = function(element) {
|
|
60
|
+
return new Blockly.FieldIconMenu(element['options']);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Fixed width of the drop-down, in px. Icon buttons will flow inside this width.
|
|
65
|
+
* @type {number}
|
|
66
|
+
* @const
|
|
67
|
+
*/
|
|
68
|
+
Blockly.FieldIconMenu.DROPDOWN_WIDTH = 168;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Save the primary colour of the source block while the menu is open, for reset.
|
|
72
|
+
* @type {number|string}
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
Blockly.FieldIconMenu.savedPrimary_ = null;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Called when the field is placed on a block.
|
|
79
|
+
* @param {Block} block The owning block.
|
|
80
|
+
*/
|
|
81
|
+
Blockly.FieldIconMenu.prototype.init = function(block) {
|
|
82
|
+
if (this.fieldGroup_) {
|
|
83
|
+
// Icon menu has already been initialized once.
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// Render the arrow icon
|
|
87
|
+
// Fixed sizes in px. Saved for creating the flip transform of the menu renders above the button.
|
|
88
|
+
var arrowSize = 12;
|
|
89
|
+
/** @type {Number} */
|
|
90
|
+
this.arrowX_ = 18;
|
|
91
|
+
/** @type {Number} */
|
|
92
|
+
this.arrowY_ = 10;
|
|
93
|
+
if (block.RTL) {
|
|
94
|
+
// In RTL, the icon position is flipped and rendered from the right (offset by width)
|
|
95
|
+
this.arrowX_ = -this.arrowX_ - arrowSize;
|
|
96
|
+
}
|
|
97
|
+
/** @type {Element} */
|
|
98
|
+
this.arrowIcon_ = Blockly.utils.createSvgElement('image', {
|
|
99
|
+
'height': arrowSize + 'px',
|
|
100
|
+
'width': arrowSize + 'px',
|
|
101
|
+
'transform': 'translate(' + this.arrowX_ + ',' + this.arrowY_ + ')'
|
|
102
|
+
});
|
|
103
|
+
this.arrowIcon_.setAttributeNS('http://www.w3.org/1999/xlink',
|
|
104
|
+
'xlink:href', Blockly.mainWorkspace.options.pathToMedia + 'dropdown-arrow.svg');
|
|
105
|
+
block.getSvgRoot().appendChild(this.arrowIcon_);
|
|
106
|
+
Blockly.FieldIconMenu.superClass_.init.call(this, block);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Mouse cursor style when over the hotspot that initiates the editor.
|
|
111
|
+
* @const
|
|
112
|
+
*/
|
|
113
|
+
Blockly.FieldIconMenu.prototype.CURSOR = 'default';
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Set the language-neutral value for this icon drop-down menu.
|
|
117
|
+
* @param {?string} newValue New value.
|
|
118
|
+
* @override
|
|
119
|
+
*/
|
|
120
|
+
Blockly.FieldIconMenu.prototype.setValue = function(newValue) {
|
|
121
|
+
if (newValue === null || newValue === this.value_) {
|
|
122
|
+
return; // No change
|
|
123
|
+
}
|
|
124
|
+
if (this.sourceBlock_ && Blockly.Events.isEnabled()) {
|
|
125
|
+
Blockly.Events.fire(new Blockly.Events.Change(
|
|
126
|
+
this.sourceBlock_, 'field', this.name, this.value_, newValue));
|
|
127
|
+
}
|
|
128
|
+
this.value_ = newValue;
|
|
129
|
+
// Find the relevant icon in this.icons_ to get the image src.
|
|
130
|
+
this.setParentFieldImage(this.getSrcForValue(this.value_));
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Find the parent block's FieldImage and set its src.
|
|
135
|
+
* @param {?string} src New src for the parent block FieldImage.
|
|
136
|
+
* @private
|
|
137
|
+
*/
|
|
138
|
+
Blockly.FieldIconMenu.prototype.setParentFieldImage = function(src) {
|
|
139
|
+
// Only attempt if we have a set sourceBlock_ and parentBlock_
|
|
140
|
+
// It's possible that this function could be called before
|
|
141
|
+
// a parent block is set; in that case, fail silently.
|
|
142
|
+
if (this.sourceBlock_ && this.sourceBlock_.parentBlock_) {
|
|
143
|
+
var parentBlock = this.sourceBlock_.parentBlock_;
|
|
144
|
+
// Loop through all inputs' fields to find the first FieldImage
|
|
145
|
+
for (var i = 0, input; input = parentBlock.inputList[i]; i++) {
|
|
146
|
+
for (var j = 0, field; field = input.fieldRow[j]; j++) {
|
|
147
|
+
if (field instanceof Blockly.FieldImage) {
|
|
148
|
+
// Src for a FieldImage is stored in its value.
|
|
149
|
+
field.setValue(src);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get the language-neutral value from this drop-down menu.
|
|
159
|
+
* @return {string} Current language-neutral value.
|
|
160
|
+
*/
|
|
161
|
+
Blockly.FieldIconMenu.prototype.getValue = function() {
|
|
162
|
+
return this.value_;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* For a language-neutral value, get the src for the image that represents it.
|
|
167
|
+
* @param {string} value Language-neutral value to look up.
|
|
168
|
+
* @return {string} Src to image representing value
|
|
169
|
+
*/
|
|
170
|
+
Blockly.FieldIconMenu.prototype.getSrcForValue = function(value) {
|
|
171
|
+
for (var i = 0, icon; icon = this.icons_[i]; i++) {
|
|
172
|
+
if (icon.value === value) {
|
|
173
|
+
return icon.src;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Show the drop-down menu for editing this field.
|
|
180
|
+
* @private
|
|
181
|
+
*/
|
|
182
|
+
Blockly.FieldIconMenu.prototype.showEditor_ = function() {
|
|
183
|
+
// If there is an existing drop-down we own, this is a request to hide the drop-down.
|
|
184
|
+
if (Blockly.DropDownDiv.hideIfOwner(this)) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// If there is an existing drop-down someone else owns, hide it immediately and clear it.
|
|
188
|
+
Blockly.DropDownDiv.hideWithoutAnimation();
|
|
189
|
+
Blockly.DropDownDiv.clearContent();
|
|
190
|
+
// Populate the drop-down with the icons for this field.
|
|
191
|
+
var contentDiv = Blockly.DropDownDiv.getContentDiv();
|
|
192
|
+
// Accessibility properties
|
|
193
|
+
contentDiv.setAttribute('role', 'menu');
|
|
194
|
+
contentDiv.setAttribute('aria-haspopup', 'true');
|
|
195
|
+
for (var i = 0, icon; icon = this.icons_[i]; i++) {
|
|
196
|
+
// Icons with the type property placeholder take up space but don't have any functionality
|
|
197
|
+
// Use for special-case layouts
|
|
198
|
+
if (icon.type == 'placeholder') {
|
|
199
|
+
var placeholder = document.createElement('span');
|
|
200
|
+
placeholder.setAttribute('class', 'blocklyDropDownPlaceholder');
|
|
201
|
+
placeholder.style.width = icon.width + 'px';
|
|
202
|
+
placeholder.style.height = icon.height + 'px';
|
|
203
|
+
contentDiv.appendChild(placeholder);
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
var button = document.createElement('button');
|
|
207
|
+
button.setAttribute('id', ':' + i); // For aria-activedescendant
|
|
208
|
+
button.setAttribute('role', 'menuitem');
|
|
209
|
+
button.setAttribute('class', 'blocklyDropDownButton');
|
|
210
|
+
button.title = icon.alt;
|
|
211
|
+
button.style.width = icon.width + 'px';
|
|
212
|
+
button.style.height = icon.height + 'px';
|
|
213
|
+
var backgroundColor = this.sourceBlock_.getColour();
|
|
214
|
+
if (icon.value == this.getValue()) {
|
|
215
|
+
// This icon is selected, show it in a different colour
|
|
216
|
+
backgroundColor = this.sourceBlock_.getColourTertiary();
|
|
217
|
+
button.setAttribute('aria-selected', 'true');
|
|
218
|
+
}
|
|
219
|
+
button.style.backgroundColor = backgroundColor;
|
|
220
|
+
button.style.borderColor = this.sourceBlock_.getColourTertiary();
|
|
221
|
+
Blockly.bindEvent_(button, 'click', this, this.buttonClick_);
|
|
222
|
+
Blockly.bindEvent_(button, 'mouseup', this, this.buttonClick_);
|
|
223
|
+
// These are applied manually instead of using the :hover pseudoclass
|
|
224
|
+
// because Android has a bad long press "helper" menu and green highlight
|
|
225
|
+
// that we must prevent with ontouchstart preventDefault
|
|
226
|
+
Blockly.bindEvent_(button, 'mousedown', button, function(e) {
|
|
227
|
+
this.setAttribute('class', 'blocklyDropDownButton blocklyDropDownButtonHover');
|
|
228
|
+
e.preventDefault();
|
|
229
|
+
});
|
|
230
|
+
Blockly.bindEvent_(button, 'mouseover', button, function() {
|
|
231
|
+
this.setAttribute('class', 'blocklyDropDownButton blocklyDropDownButtonHover');
|
|
232
|
+
contentDiv.setAttribute('aria-activedescendant', this.id);
|
|
233
|
+
});
|
|
234
|
+
Blockly.bindEvent_(button, 'mouseout', button, function() {
|
|
235
|
+
this.setAttribute('class', 'blocklyDropDownButton');
|
|
236
|
+
contentDiv.removeAttribute('aria-activedescendant');
|
|
237
|
+
});
|
|
238
|
+
var buttonImg = document.createElement('img');
|
|
239
|
+
buttonImg.src = icon.src;
|
|
240
|
+
//buttonImg.alt = icon.alt;
|
|
241
|
+
// Upon click/touch, we will be able to get the clicked element as e.target
|
|
242
|
+
// Store a data attribute on all possible click targets so we can match it to the icon.
|
|
243
|
+
button.setAttribute('data-value', icon.value);
|
|
244
|
+
buttonImg.setAttribute('data-value', icon.value);
|
|
245
|
+
button.appendChild(buttonImg);
|
|
246
|
+
contentDiv.appendChild(button);
|
|
247
|
+
}
|
|
248
|
+
contentDiv.style.width = Blockly.FieldIconMenu.DROPDOWN_WIDTH + 'px';
|
|
249
|
+
|
|
250
|
+
Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(), this.sourceBlock_.getColourTertiary());
|
|
251
|
+
Blockly.DropDownDiv.setCategory(this.sourceBlock_.parentBlock_.getCategory());
|
|
252
|
+
|
|
253
|
+
// Update source block colour to look selected
|
|
254
|
+
this.savedPrimary_ = this.sourceBlock_.getColour();
|
|
255
|
+
this.sourceBlock_.setColour(this.sourceBlock_.getColourSecondary(),
|
|
256
|
+
this.sourceBlock_.getColourSecondary(),
|
|
257
|
+
this.sourceBlock_.getColourTertiary(),
|
|
258
|
+
this.sourceBlock_.getColourQuaternary());
|
|
259
|
+
|
|
260
|
+
var scale = this.sourceBlock_.workspace.scale;
|
|
261
|
+
// Offset for icon-type horizontal blocks.
|
|
262
|
+
var secondaryYOffset = (
|
|
263
|
+
-(Blockly.BlockSvg.MIN_BLOCK_Y * scale) - (Blockly.BlockSvg.FIELD_Y_OFFSET * scale)
|
|
264
|
+
);
|
|
265
|
+
var renderedPrimary = Blockly.DropDownDiv.showPositionedByBlock(
|
|
266
|
+
this, this.sourceBlock_, this.onHide_.bind(this), secondaryYOffset);
|
|
267
|
+
if (!renderedPrimary) {
|
|
268
|
+
// Adjust for rotation
|
|
269
|
+
var arrowX = this.arrowX_ + Blockly.DropDownDiv.ARROW_SIZE / 1.5 + 1;
|
|
270
|
+
var arrowY = this.arrowY_ + Blockly.DropDownDiv.ARROW_SIZE / 1.5;
|
|
271
|
+
// Flip the arrow on the button
|
|
272
|
+
this.arrowIcon_.setAttribute('transform',
|
|
273
|
+
'translate(' + arrowX + ',' + arrowY + ') rotate(180)');}
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Callback for when a button is clicked inside the drop-down.
|
|
278
|
+
* Should be bound to the FieldIconMenu.
|
|
279
|
+
* @param {Event} e DOM event for the click/touch
|
|
280
|
+
* @private
|
|
281
|
+
*/
|
|
282
|
+
Blockly.FieldIconMenu.prototype.buttonClick_ = function(e) {
|
|
283
|
+
var value = e.target.getAttribute('data-value');
|
|
284
|
+
this.setValue(value);
|
|
285
|
+
Blockly.DropDownDiv.hide();
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Callback for when the drop-down is hidden.
|
|
290
|
+
*/
|
|
291
|
+
Blockly.FieldIconMenu.prototype.onHide_ = function() {
|
|
292
|
+
// Reset the button colour and clear accessibility properties
|
|
293
|
+
// Only attempt to do this reset if sourceBlock_ is not disposed.
|
|
294
|
+
// It could become disposed before an onHide_, for example,
|
|
295
|
+
// when a block is dragged from the flyout.
|
|
296
|
+
if (this.sourceBlock_) {
|
|
297
|
+
this.sourceBlock_.setColour(this.savedPrimary_,
|
|
298
|
+
this.sourceBlock_.getColourSecondary(),
|
|
299
|
+
this.sourceBlock_.getColourTertiary(),
|
|
300
|
+
this.sourceBlock_.getColourQuaternary());
|
|
301
|
+
}
|
|
302
|
+
Blockly.DropDownDiv.content_.removeAttribute('role');
|
|
303
|
+
Blockly.DropDownDiv.content_.removeAttribute('aria-haspopup');
|
|
304
|
+
Blockly.DropDownDiv.content_.removeAttribute('aria-activedescendant');
|
|
305
|
+
// Unflip the arrow if appropriate
|
|
306
|
+
this.arrowIcon_.setAttribute('transform', 'translate(' + this.arrowX_ + ',' + this.arrowY_ + ')');
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
Blockly.Field.register('field_iconmenu', Blockly.FieldIconMenu);
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Visual Blocks Editor
|
|
4
|
+
*
|
|
5
|
+
* Copyright 2012 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 Image field. Used for pictures, icons, etc.
|
|
23
|
+
* @author fraser@google.com (Neil Fraser)
|
|
24
|
+
*/
|
|
25
|
+
'use strict';
|
|
26
|
+
|
|
27
|
+
goog.provide('Blockly.FieldImage');
|
|
28
|
+
|
|
29
|
+
goog.require('Blockly.Field');
|
|
30
|
+
goog.require('goog.dom');
|
|
31
|
+
goog.require('goog.math.Size');
|
|
32
|
+
goog.require('goog.userAgent');
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Class for an image on a block.
|
|
37
|
+
* @param {string} src The URL of the image.
|
|
38
|
+
* @param {number} width Width of the image.
|
|
39
|
+
* @param {number} height Height of the image.
|
|
40
|
+
* @param {string=} opt_alt Optional alt text for when block is collapsed.
|
|
41
|
+
* @param {boolean} flip_rtl Whether to flip the icon in RTL
|
|
42
|
+
* @extends {Blockly.Field}
|
|
43
|
+
* @constructor
|
|
44
|
+
*/
|
|
45
|
+
Blockly.FieldImage = function(src, width, height, opt_alt, flip_rtl) {
|
|
46
|
+
this.sourceBlock_ = null;
|
|
47
|
+
|
|
48
|
+
// Ensure height and width are numbers. Strings are bad at math.
|
|
49
|
+
this.height_ = Number(height);
|
|
50
|
+
this.width_ = Number(width);
|
|
51
|
+
this.size_ = new goog.math.Size(this.width_, this.height_);
|
|
52
|
+
this.text_ = opt_alt || '';
|
|
53
|
+
this.flipRTL_ = flip_rtl;
|
|
54
|
+
this.setValue(src);
|
|
55
|
+
};
|
|
56
|
+
goog.inherits(Blockly.FieldImage, Blockly.Field);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Construct a FieldImage from a JSON arg object,
|
|
60
|
+
* dereferencing any string table references.
|
|
61
|
+
* @param {!Object} options A JSON object with options (src, width, height, alt,
|
|
62
|
+
* and flipRtl/flip_rtl).
|
|
63
|
+
* @returns {!Blockly.FieldImage} The new field instance.
|
|
64
|
+
* @package
|
|
65
|
+
* @nocollapse
|
|
66
|
+
*/
|
|
67
|
+
Blockly.FieldImage.fromJson = function(options) {
|
|
68
|
+
var src = Blockly.utils.replaceMessageReferences(options['src']);
|
|
69
|
+
var width = Number(Blockly.utils.replaceMessageReferences(options['width']));
|
|
70
|
+
var height =
|
|
71
|
+
Number(Blockly.utils.replaceMessageReferences(options['height']));
|
|
72
|
+
var alt = Blockly.utils.replaceMessageReferences(options['alt']);
|
|
73
|
+
var flip_rtl = !!options['flip_rtl'] || !!options['flipRtl'];
|
|
74
|
+
return new Blockly.FieldImage(src, width, height, alt, flip_rtl);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Editable fields are saved by the XML renderer, non-editable fields are not.
|
|
79
|
+
*/
|
|
80
|
+
Blockly.FieldImage.prototype.EDITABLE = false;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Install this image on a block.
|
|
84
|
+
*/
|
|
85
|
+
Blockly.FieldImage.prototype.init = function() {
|
|
86
|
+
if (this.fieldGroup_) {
|
|
87
|
+
// Image has already been initialized once.
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// Build the DOM.
|
|
91
|
+
/** @type {SVGElement} */
|
|
92
|
+
this.fieldGroup_ = Blockly.utils.createSvgElement('g', {}, null);
|
|
93
|
+
if (!this.visible_) {
|
|
94
|
+
this.fieldGroup_.style.display = 'none';
|
|
95
|
+
}
|
|
96
|
+
/** @type {SVGElement} */
|
|
97
|
+
this.imageElement_ = Blockly.utils.createSvgElement(
|
|
98
|
+
'image',
|
|
99
|
+
{
|
|
100
|
+
'height': this.height_ + 'px',
|
|
101
|
+
'width': this.width_ + 'px'
|
|
102
|
+
},
|
|
103
|
+
this.fieldGroup_);
|
|
104
|
+
this.setValue(this.src_);
|
|
105
|
+
this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_);
|
|
106
|
+
|
|
107
|
+
// Configure the field to be transparent with respect to tooltips.
|
|
108
|
+
this.setTooltip(this.sourceBlock_);
|
|
109
|
+
Blockly.Tooltip.bindMouseEvents(this.imageElement_);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Dispose of all DOM objects belonging to this text.
|
|
114
|
+
*/
|
|
115
|
+
Blockly.FieldImage.prototype.dispose = function() {
|
|
116
|
+
goog.dom.removeNode(this.fieldGroup_);
|
|
117
|
+
this.fieldGroup_ = null;
|
|
118
|
+
this.imageElement_ = null;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Change the tooltip text for this field.
|
|
123
|
+
* @param {string|!Element} newTip Text for tooltip or a parent element to
|
|
124
|
+
* link to for its tooltip.
|
|
125
|
+
*/
|
|
126
|
+
Blockly.FieldImage.prototype.setTooltip = function(newTip) {
|
|
127
|
+
this.imageElement_.tooltip = newTip;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get the source URL of this image.
|
|
132
|
+
* @return {string} Current text.
|
|
133
|
+
* @override
|
|
134
|
+
*/
|
|
135
|
+
Blockly.FieldImage.prototype.getValue = function() {
|
|
136
|
+
return this.src_;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Set the source URL of this image.
|
|
141
|
+
* @param {?string} src New source.
|
|
142
|
+
* @override
|
|
143
|
+
*/
|
|
144
|
+
Blockly.FieldImage.prototype.setValue = function(src) {
|
|
145
|
+
if (src === null) {
|
|
146
|
+
// No change if null.
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this.src_ = src;
|
|
150
|
+
if (this.imageElement_) {
|
|
151
|
+
// Extension blocks can't rely on having access to pathToMedia, so we allow this fake URL
|
|
152
|
+
// protocol instead.
|
|
153
|
+
var mediaPrefix = 'media://';
|
|
154
|
+
if (src.startsWith(mediaPrefix)) {
|
|
155
|
+
var pathToMedia = this.sourceBlock_.workspace.options.pathToMedia;
|
|
156
|
+
src = pathToMedia + src.substring(mediaPrefix.length);
|
|
157
|
+
}
|
|
158
|
+
this.imageElement_.setAttributeNS('http://www.w3.org/1999/xlink',
|
|
159
|
+
'xlink:href', src || '');
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get whether to flip this image in RTL
|
|
165
|
+
* @return {boolean} True if we should flip in RTL.
|
|
166
|
+
*/
|
|
167
|
+
Blockly.FieldImage.prototype.getFlipRTL = function() {
|
|
168
|
+
return this.flipRTL_;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Set the alt text of this image.
|
|
173
|
+
* @param {?string} alt New alt text.
|
|
174
|
+
* @override
|
|
175
|
+
*/
|
|
176
|
+
Blockly.FieldImage.prototype.setText = function(alt) {
|
|
177
|
+
if (alt === null) {
|
|
178
|
+
// No change if null.
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
this.text_ = alt;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Images are fixed width, no need to render.
|
|
186
|
+
* @private
|
|
187
|
+
*/
|
|
188
|
+
Blockly.FieldImage.prototype.render_ = function() {
|
|
189
|
+
// NOP
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Images are fixed width, no need to update.
|
|
194
|
+
* @private
|
|
195
|
+
*/
|
|
196
|
+
Blockly.FieldImage.prototype.updateWidth = function() {
|
|
197
|
+
// NOP
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
Blockly.Field.register('field_image', Blockly.FieldImage);
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Visual Blocks Editor
|
|
4
|
+
*
|
|
5
|
+
* Copyright 2012 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 Non-editable text field. Used for titles, labels, etc.
|
|
23
|
+
* @author fraser@google.com (Neil Fraser)
|
|
24
|
+
*/
|
|
25
|
+
'use strict';
|
|
26
|
+
|
|
27
|
+
goog.provide('Blockly.FieldLabel');
|
|
28
|
+
|
|
29
|
+
goog.require('Blockly.Field');
|
|
30
|
+
goog.require('Blockly.Tooltip');
|
|
31
|
+
goog.require('goog.dom');
|
|
32
|
+
goog.require('goog.math.Size');
|
|
33
|
+
goog.require('goog.userAgent');
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Class for a non-editable field.
|
|
38
|
+
* @param {string} text The initial content of the field.
|
|
39
|
+
* @param {string=} opt_class Optional CSS class for the field's text.
|
|
40
|
+
* @extends {Blockly.Field}
|
|
41
|
+
* @constructor
|
|
42
|
+
*/
|
|
43
|
+
Blockly.FieldLabel = function(text, opt_class) {
|
|
44
|
+
this.size_ = new goog.math.Size(0, 0);
|
|
45
|
+
this.class_ = opt_class;
|
|
46
|
+
this.setValue(text);
|
|
47
|
+
};
|
|
48
|
+
goog.inherits(Blockly.FieldLabel, Blockly.Field);
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Construct a FieldLabel from a JSON arg object,
|
|
52
|
+
* dereferencing any string table references.
|
|
53
|
+
* @param {!Object} options A JSON object with options (text, and class).
|
|
54
|
+
* @returns {!Blockly.FieldLabel} The new field instance.
|
|
55
|
+
* @package
|
|
56
|
+
* @nocollapse
|
|
57
|
+
*/
|
|
58
|
+
Blockly.FieldLabel.fromJson = function(options) {
|
|
59
|
+
var text = Blockly.utils.replaceMessageReferences(options['text']);
|
|
60
|
+
return new Blockly.FieldLabel(text, options['class']);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Editable fields usually show some sort of UI for the user to change them.
|
|
65
|
+
* @type {boolean}
|
|
66
|
+
* @public
|
|
67
|
+
*/
|
|
68
|
+
Blockly.FieldLabel.prototype.EDITABLE = false;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Serializable fields are saved by the XML renderer, non-serializable fields
|
|
72
|
+
* are not. Editable fields should be serialized.
|
|
73
|
+
* @type {boolean}
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
Blockly.FieldLabel.prototype.SERIALIZABLE = false;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Install this text on a block.
|
|
80
|
+
*/
|
|
81
|
+
Blockly.FieldLabel.prototype.init = function() {
|
|
82
|
+
if (this.textElement_) {
|
|
83
|
+
// Text has already been initialized once.
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// Build the DOM.
|
|
87
|
+
this.textElement_ = Blockly.utils.createSvgElement('text',
|
|
88
|
+
{
|
|
89
|
+
'class': 'blocklyText',
|
|
90
|
+
'y': Blockly.BlockSvg.FIELD_TOP_PADDING,
|
|
91
|
+
'text-anchor': 'middle',
|
|
92
|
+
'dominant-baseline': 'middle',
|
|
93
|
+
'dy': goog.userAgent.EDGE_OR_IE ? Blockly.Field.IE_TEXT_OFFSET : '0'
|
|
94
|
+
}, null);
|
|
95
|
+
if (this.class_) {
|
|
96
|
+
Blockly.utils.addClass(this.textElement_, this.class_);
|
|
97
|
+
}
|
|
98
|
+
if (!this.visible_) {
|
|
99
|
+
this.textElement_.style.display = 'none';
|
|
100
|
+
}
|
|
101
|
+
this.sourceBlock_.getSvgRoot().appendChild(this.textElement_);
|
|
102
|
+
|
|
103
|
+
// Configure the field to be transparent with respect to tooltips.
|
|
104
|
+
this.textElement_.tooltip = this.sourceBlock_;
|
|
105
|
+
Blockly.Tooltip.bindMouseEvents(this.textElement_);
|
|
106
|
+
// Force a render.
|
|
107
|
+
this.render_();
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Dispose of all DOM objects belonging to this text.
|
|
112
|
+
*/
|
|
113
|
+
Blockly.FieldLabel.prototype.dispose = function() {
|
|
114
|
+
goog.dom.removeNode(this.textElement_);
|
|
115
|
+
this.textElement_ = null;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Gets the group element for this field.
|
|
120
|
+
* Used for measuring the size and for positioning.
|
|
121
|
+
* @return {!Element} The group element.
|
|
122
|
+
*/
|
|
123
|
+
Blockly.FieldLabel.prototype.getSvgRoot = function() {
|
|
124
|
+
return /** @type {!Element} */ (this.textElement_);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Change the tooltip text for this field.
|
|
129
|
+
* @param {string|!Element} newTip Text for tooltip or a parent element to
|
|
130
|
+
* link to for its tooltip.
|
|
131
|
+
*/
|
|
132
|
+
Blockly.FieldLabel.prototype.setTooltip = function(newTip) {
|
|
133
|
+
this.textElement_.tooltip = newTip;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
Blockly.Field.register('field_label', Blockly.FieldLabel);
|