Skip to content
Permalink
master
Switch branches/tags
Go to file
* fix: Fix downloading screenshots on the playground.

* fix: Resolve lint warning about unused variable.
21 contributors

Users who have contributed to this file

@NeilFraser @rachel-fenichel @BeksOmega @samelhusseini @alschmiedt @AnmAtAnm @moniika @espertus @cpcallen @timdawborn @picklesrus @daarond
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Blockly Playground</title>
<!-- This script loads uncompressed when on localhost and loads compressed when it is being hosted.
Please add any other dependencies to playgrounds/prepare.js.-->
<script src="playgrounds/prepare.js"></script>
<script src="playgrounds/screenshot.js"></script>
<script src="../node_modules/@blockly/dev-tools/dist/index.js"></script>
<script type=module>
import Blockly from './playgrounds/blockly.mjs';
const IS_UNCOMPRESSED = Boolean(window.BlocklyLoader); // See prepare.js
var workspace = null;
function start() {
setBackgroundColour();
// Parse the URL arguments.
var match = location.search.match(/dir=([^&]+)/);
var rtl = match && match[1] == 'rtl';
document.forms.options.elements.dir.selectedIndex = Number(rtl);
var toolbox = getToolboxElement();
setToolboxDropdown();
match = location.search.match(/side=([^&]+)/);
var autoimport = !!location.search.match(/autoimport=([^&]+)/);
// Create main workspace.
workspace = Blockly.inject('blocklyDiv',
{
comments: true,
collapse: true,
disable: true,
grid:
{
spacing: 25,
length: 3,
colour: '#ccc',
snap: true
},
horizontalLayout: false,
maxBlocks: Infinity,
maxInstances: {'test_basic_limit_instances': 3},
maxTrashcanContents: 256,
media: '../media/',
oneBasedIndex: true,
readOnly: false,
rtl: rtl,
move: {
scrollbars: true,
drag: true,
wheel: false,
},
toolbox: toolbox,
toolboxPosition: 'start',
renderer: 'geras',
zoom:
{
controls: true,
wheel: true,
startScale: 1.0,
maxScale: 4,
minScale: 0.25,
scaleSpeed: 1.1
}
});
initToolbox(workspace);
workspace.configureContextMenu = configureContextMenu;
// Restore previously displayed text.
if (sessionStorage) {
var text = sessionStorage.getItem('textarea');
if (text) {
document.getElementById('importExport').value = text;
}
// Restore event logging state.
var logMainEventsState = sessionStorage.getItem('logEvents');
logEvents(Boolean(Number(logMainEventsState)));
var logToolboxFlyoutEventsState = sessionStorage.getItem('logFlyoutEvents');
logFlyoutEvents(Boolean(Number(logToolboxFlyoutEventsState)));
} else {
// MSIE 11 does not support sessionStorage on file:// URLs.
logEvents(false);
}
taChange();
if (autoimport) {
load();
}
addEventHandlers();
}
function setBackgroundColour() {
// Set background colour to differentiate between compressed and uncompressed mode.
if (IS_UNCOMPRESSED) {
document.body.style.backgroundColor = '#d6d6ff'; // Familiar lilac.
} else {
document.body.style.backgroundColor = '#60fcfc'; // Unfamiliar blue.
}
}
function getToolboxSuffix() {
var match = location.search.match(/toolbox=([^&]+)/);
// Default to the basic toolbox with categories and untyped variables,
// but override that if the toolbox type is set in the URL.
return (match ? match[1] : 'categories');
}
function getToolboxElement() {
var toolboxSuffix = getToolboxSuffix();
if (toolboxSuffix == 'test-blocks') {
if (typeof window.toolboxTestBlocks !== 'undefined') {
return toolboxTestBlocks;
} else {
alert('You need to run \'npm install\' in order to use the test blocks.');
toolboxSuffix = 'categories';
}
}
// The three possible values are: "simple", "categories",
// "categories-typed-variables".
return document.getElementById('toolbox-' + toolboxSuffix);
}
function setToolboxDropdown() {
var toolboxNames = [
'toolbox-categories',
'toolbox-categories-typed-variables',
'toolbox-simple',
'toolbox-test-blocks'
];
var toolboxSuffix = getToolboxSuffix();
document.forms.options.elements.toolbox.selectedIndex =
toolboxNames.indexOf('toolbox-' + toolboxSuffix);
}
function initToolbox(workspace) {
var toolboxSuffix = getToolboxSuffix();
if (toolboxSuffix == 'test-blocks' &&
typeof window.toolboxTestBlocksInit !== 'undefined') {
toolboxTestBlocksInit(workspace);
}
}
function saveXml() {
var output = document.getElementById('importExport');
var xml = Blockly.Xml.workspaceToDom(workspace);
output.value = Blockly.Xml.domToPrettyText(xml);
output.focus();
output.select();
taChange();
}
function saveJson() {
var output = document.getElementById('importExport');
var state = Blockly.serialization.workspaces.save(workspace);
output.value = JSON.stringify(state, null, 2);
output.focus();
output.select();
taChange();
}
function load() {
var input = document.getElementById('importExport');
if (!input.value) {
return;
}
var valid = saveIsValid(input.value);
if (valid.json) {
var state = JSON.parse(input.value);
Blockly.serialization.workspaces.load(state, workspace);
} else if (valid.xml) {
var xml = Blockly.Xml.textToDom(input.value);
Blockly.Xml.domToWorkspace(xml, workspace);
}
taChange();
}
function toCode(lang) {
var output = document.getElementById('importExport');
output.value = Blockly[lang].workspaceToCode(workspace);
taChange();
}
// Disable the "Load" button if the save state is invalid.
// Preserve text between page reloads.
function taChange() {
var textarea = document.getElementById('importExport');
if (sessionStorage) {
sessionStorage.setItem('textarea', textarea.value);
}
var valid = saveIsValid(textarea.value);
document.getElementById('import').disabled = !valid.json && !valid.xml;
}
function saveIsValid(save) {
var validJson = true;
try {
JSON.parse(save);
} catch (e) {
validJson = false;
}
var validXml = true
try {
Blockly.Xml.textToDom(save);
} catch (e) {
validXml = false;
}
return {
json: validJson,
xml: validXml
}
}
function logEvents(state) {
var checkbox = document.getElementById('logCheck');
checkbox.checked = state;
if (sessionStorage) {
sessionStorage.setItem('logEvents', Number(state));
}
if (state) {
workspace.addChangeListener(logger);
} else {
workspace.removeChangeListener(logger);
}
}
function logFlyoutEvents(state) {
var checkbox = document.getElementById('logFlyoutCheck');
checkbox.checked = state;
if (sessionStorage) {
sessionStorage.setItem('logFlyoutEvents', Number(state));
}
var flyoutWorkspace = workspace.getFlyout().getWorkspace();
if (state) {
flyoutWorkspace.addChangeListener(logger);
} else {
flyoutWorkspace.removeChangeListener(logger);
}
}
function configureContextMenu(menuOptions, e) {
var screenshotOption = {
text: 'Download Screenshot',
enabled: workspace.getTopBlocks().length,
callback: function() {
downloadScreenshot(workspace);
}
};
menuOptions.push(screenshotOption);
// Adds a default-sized workspace comment to the workspace.
menuOptions.push(Blockly.ContextMenu.workspaceCommentOption(workspace, e));
}
function logger(e) {
console.log(e);
}
function airstrike(n) {
var prototypes = [];
var toolbox = getToolboxElement();
var blocks = toolbox.getElementsByTagName('block');
for (var i = 0, block; block = blocks[i]; i++) {
prototypes.push(block.getAttribute('type'));
}
for (var i = 0; i < n; i++) {
var prototype = prototypes[Math.floor(Math.random() * prototypes.length)];
var block = workspace.newBlock(prototype);
block.initSvg();
block.getSvgRoot().setAttribute('transform', 'translate(' +
Math.round(Math.random() * 450 + 40) + ', ' +
Math.round(Math.random() * 600 + 40) + ')');
block.render();
}
}
function spaghetti(n) {
var xml = spaghettiXml;
for(var i = 0; i < n; i++) {
xml = xml.replace(/(<(statement|next)( name="DO0")?>)<\//g,
'$1' + spaghettiXml + '</');
}
xml = '<xml xmlns="https://developers.google.com/blockly/xml">' + xml + '</xml>';
var dom = Blockly.Xml.textToDom(xml);
console.time('Spaghetti domToWorkspace');
Blockly.Xml.domToWorkspace(dom, workspace);
console.timeEnd('Spaghetti domToWorkspace');
}
var spaghettiXml = [
' <block type="controls_if">',
' <value name="IF0">',
' <block type="logic_compare">',
' <field name="OP">EQ</field>',
' <value name="A">',
' <block type="math_arithmetic">',
' <field name="OP">MULTIPLY</field>',
' <value name="A">',
' <block type="math_number">',
' <field name="NUM">6</field>',
' </block>',
' </value>',
' <value name="B">',
' <block type="math_number">',
' <field name="NUM">7</field>',
' </block>',
' </value>',
' </block>',
' </value>',
' <value name="B">',
' <block type="math_number">',
' <field name="NUM">42</field>',
' </block>',
' </value>',
' </block>',
' </value>',
' <statement name="DO0"></statement>',
' <next></next>',
' </block>'].join('\n');
function jsoSpaghetti(n) {
var str = spaghettiJs;
for (var i = 0; i < n; i++) {
str = str.replace(/{}/g, `{"block":${spaghettiJs}}`);
}
var obj = {
'blocks': {
'blocks': [
JSON.parse(str)
]
}
};
console.time('Spaghetti serialization');
Blockly.serialization.workspaces.load(obj, workspace);
console.timeEnd('Spaghetti serialization');
}
var spaghettiJs = JSON.stringify({
'type': 'controls_if',
'inputs': {
'IF0': {
'block': {
'type': 'logic_compare',
'fields': {
'OP': 'EQ',
},
'inputs': {
'A': {
'block': {
'type': 'math_arithmetic',
'fields': {
'OP': 'MULTIPLY',
},
'inputs': {
'A': {
'block': {
'type': 'math_number',
'fields': {
'NUM': 6
}
}
},
'B': {
'block': {
'type': 'math_number',
'fields': {
'NUM': 7
}
}
}
}
}
},
'B': {
'block': {
'type': 'math_number',
'fields': {
'NUM': 42
}
}
}
}
}
},
'DO0': { }
},
'next': { }
});
// Call start(). Because this <script> has type=module, it is
// automatically deferred, so it will not be run until after the
// document has been parsed, but before firing DOMContentLoaded.
function addEventHandlers() {
document.getElementById('save-json').addEventListener('click', saveJson);
document.getElementById('save-xml').addEventListener('click', saveXml);
document.getElementById('import').addEventListener('click', load);
document.getElementById('to-code-js')
.addEventListener('click', () => toCode('JavaScript'));
document.getElementById('to-code-py')
.addEventListener('click', () => toCode('Python'));
document.getElementById('to-code-php')
.addEventListener('click', () => toCode('PHP'));
document.getElementById('to-code-lua')
.addEventListener('click', () => toCode('Lua'));
document.getElementById('to-code-dart')
.addEventListener('click', () => toCode('Dart'));
document.getElementById('airstrike')
.addEventListener('click', () => airstrike(100));
document.getElementById('spaghetti-xml')
.addEventListener('click', () => spaghetti(8));
document.getElementById('spaghetti-js')
.addEventListener('click', () => jsoSpaghetti(8));
document.getElementById('logCheck')
.addEventListener('click', function() { logEvents(this.checked) });
document.getElementById('logFlyoutCheck')
.addEventListener('click', function() { logFlyoutEvents(this.checked) });
document.getElementById('importExport').addEventListener('change', taChange);
document.getElementById('importExport').addEventListener('keyup', taChange);
document.getElementById('show')
.addEventListener('click', function() { workspace.setVisible(true); });
document.getElementById('hide')
.addEventListener('click', function() { workspace.setVisible(false); });
}
start();
</script>
<style>
html, body {
height: 100%;
}
body {
background-color: #fff;
font-family: sans-serif;
overflow: hidden;
}
h1 {
font-weight: normal;
font-size: 140%;
}
#blocklyDiv {
float: right;
height: 95%;
width: 70%;
}
#importExport {
font-family: monospace;
}
.ioLabel>.blocklyFlyoutLabelText {
font-style: italic;
}
#blocklyDiv.renderingDebug .blockRenderDebug {
display: block;
}
.playgroundToggleOptions {
list-style: none;
padding: 0;
}
.playgroundToggleOptions li {
margin-top: 1em;
}
.zelos-renderer .blocklyFlyoutButton .blocklyText {
font-size: 1.5rem;
}
</style>
</head>
<body>
<div id="blocklyDiv"></div>
<h1>Blockly Playground</h1>
<p>
<input id="show" type="button" value="Show"></input> -
<input id="hide" type="button" value="Hide"></input> -
<a href="playgrounds/advanced_playground.html">Advanced</a>
</p>
<form id="options">
<select name="dir" onchange="document.forms.options.submit()">
<option value="ltr">LTR</option>
<option value="rtl">RTL</option>
</select>
<select name="toolbox" onchange="document.forms.options.submit()">
<option value="categories">Categories (untyped variables)</option>
<option value="categories-typed-variables">Categories (typed variables)</option>
<option value="simple">Simple</option>
<option value="test-blocks">Test Blocks</option>
</select>
</form>
<p>
<input id="save-json" type="button" value="Save JSON">
<input id="save-xml" type="button" value="Save XML">
<input type="button" value="Load" id="import">
<br>
<input id="to-code-js" type="button" value="To JavaScript">
<input id="to-code-py" type="button" value="To Python">
<input id="to-code-php" type="button" value="To PHP">
<input id="to-code-lua" type="button" value="To Lua">
<input id="to-code-dart" type="button" value="To Dart">
<br>
<textarea id="importExport" style="width: 26%; height: 12em"></textarea>
</p>
<p>
Stress test: &nbsp;
<input id="airstrike" type="button" value="Airstrike!">
<input id="spaghetti-xml" type="button" value="Spaghetti!">
<input id="spaghetti-js" type="button" value="JS Spaghetti!">
</p>
<ul class="playgroundToggleOptions">
<li>
<label for="logCheck">Log main workspace events:</label>
<input type="checkbox" id="logCheck">
</li>
<li>
<label for="logFlyoutCheck">Log flyout events:</label>
<input type="checkbox" id="logFlyoutCheck">
</li>
</ul>
<!-- The next three blocks of XML are sample toolboxes for testing basic
configurations. For more information on building toolboxes, see https://developers.google.com/blockly/guides/configure/web/toolbox -->
<!-- toolbox-simple is an always-open flyout with no category menu.
Always-open flyouts are a good idea if you have a small number of blocks. -->
<xml xmlns="https://developers.google.com/blockly/xml" id="toolbox-simple" style="display: none">
<block type="controls_ifelse"></block>
<block type="logic_compare"></block>
<!-- <block type="control_repeat"></block> -->
<block type="logic_operation"></block>
<block type="controls_repeat_ext">
<value name="TIMES">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
</block>
<block type="logic_operation"></block>
<block type="logic_negate"></block>
<block type="logic_boolean"></block>
<block type="logic_null" disabled="true"></block>
<block type="logic_ternary"></block>
<block type="text_charAt">
<value name="VALUE">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
</block>
</xml>
<!-- toolbox-categories has a category menu and an auto-closing flyout. The
Variables category uses untyped variable blocks.
See https://developers.google.com/blockly/guides/create-custom-blocks/variables#untyped_variable_blocks for more information. -->
<xml xmlns="https://developers.google.com/blockly/xml" id="toolbox-categories" style="display: none">
<category name="Logic" categorystyle="logic_category">
<block type="controls_if"></block>
<block type="logic_compare"></block>
<block type="logic_operation"></block>
<block type="logic_negate"></block>
<block type="logic_boolean"></block>
<block type="logic_null" disabled="true"></block>
<block type="logic_ternary"></block>
</category>
<category name="Loops" categorystyle="loop_category">
<block type="controls_repeat_ext">
<value name="TIMES">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
</block>
<block type="controls_repeat" disabled="true"></block>
<block type="controls_whileUntil"></block>
<block type="controls_for">
<value name="FROM">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="TO">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
<value name="BY">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>
<block type="controls_forEach"></block>
<block type="controls_flow_statements"></block>
</category>
<category name="Math" categorystyle="math_category">
<block type="math_number" gap="32">
<field name="NUM">123</field>
</block>
<block type="math_arithmetic">
<value name="A">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="B">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>
<block type="math_single">
<value name="NUM">
<shadow type="math_number">
<field name="NUM">9</field>
</shadow>
</value>
</block>
<block type="math_trig">
<value name="NUM">
<shadow type="math_number">
<field name="NUM">45</field>
</shadow>
</value>
</block>
<block type="math_constant"></block>
<block type="math_number_property">
<value name="NUMBER_TO_CHECK">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
</block>
<block type="math_round">
<value name="NUM">
<shadow type="math_number">
<field name="NUM">3.1</field>
</shadow>
</value>
</block>
<block type="math_on_list"></block>
<block type="math_modulo">
<value name="DIVIDEND">
<shadow type="math_number">
<field name="NUM">64</field>
</shadow>
</value>
<value name="DIVISOR">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
</block>
<block type="math_constrain">
<value name="VALUE">
<shadow type="math_number">
<field name="NUM">50</field>
</shadow>
</value>
<value name="LOW">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="HIGH">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>
<block type="math_random_int">
<value name="FROM">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="TO">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>
<block type="math_random_float"></block>
<block type="math_atan2">
<value name="X">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="Y">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>
</category>
<category name="Text" categorystyle="text_category">
<block type="text"></block>
<block type="text_multiline"></block>
<block type="text_join"></block>
<block type="text_append">
<value name="TEXT">
<shadow type="text"></shadow>
</value>
</block>
<block type="text_length">
<value name="VALUE">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_isEmpty">
<value name="VALUE">
<shadow type="text">
<field name="TEXT"></field>
</shadow>
</value>
</block>
<block type="text_indexOf">
<value name="VALUE">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
<value name="FIND">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_charAt">
<value name="VALUE">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
</block>
<block type="text_getSubstring">
<value name="STRING">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
</block>
<block type="text_changeCase">
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_trim">
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_count">
<value name="SUB">
<shadow type="text"></shadow>
</value>
<value name="TEXT">
<shadow type="text"></shadow>
</value>
</block>
<block type="text_replace">
<value name="FROM">
<shadow type="text"></shadow>
</value>
<value name="TO">
<shadow type="text"></shadow>
</value>
<value name="TEXT">
<shadow type="text"></shadow>
</value>
</block>
<block type="text_reverse">
<value name="TEXT">
<shadow type="text"></shadow>
</value>
</block>
<label text="Input/Output:" web-class="ioLabel"></label>
<block type="text_print">
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_prompt_ext">
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
</category>
<category name="Lists" categorystyle="list_category">
<block type="lists_create_with">
<mutation items="0"></mutation>
</block>
<block type="lists_create_with"></block>
<block type="lists_repeat">
<value name="NUM">
<shadow type="math_number">
<field name="NUM">5</field>
</shadow>
</value>
</block>
<block type="lists_length"></block>
<block type="lists_isEmpty"></block>
<block type="lists_indexOf">
<value name="VALUE">
<block type="variables_get">
<field name="VAR">list</field>
</block>
</value>
</block>
<block type="lists_getIndex">
<value name="VALUE">
<block type="variables_get">
<field name="VAR">list</field>
</block>
</value>
</block>
<block type="lists_setIndex">
<value name="LIST">
<block type="variables_get">
<field name="VAR">list</field>
</block>
</value>
</block>
<block type="lists_getSublist">
<value name="LIST">
<block type="variables_get">
<field name="VAR">list</field>
</block>
</value>
</block>
<block type="lists_split">
<value name="DELIM">
<shadow type="text">
<field name="TEXT">,</field>
</shadow>
</value>
</block>
<block type="lists_sort"></block>
<block type="lists_reverse"></block>
</category>
<category name="Colour" categorystyle="colour_category">
<block type="colour_picker"></block>
<block type="colour_random"></block>
<block type="colour_rgb">
<value name="RED">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="GREEN">
<shadow type="math_number">
<field name="NUM">50</field>
</shadow>
</value>
<value name="BLUE">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
</block>
<block type="colour_blend">
<value name="COLOUR1">
<shadow type="colour_picker">
<field name="COLOUR">#ff0000</field>
</shadow>
</value>
<value name="COLOUR2">
<shadow type="colour_picker">
<field name="COLOUR">#3333ff</field>
</shadow>
</value>
<value name="RATIO">
<shadow type="math_number">
<field name="NUM">0.5</field>
</shadow>
</value>
</block>
</category>
<sep></sep>
<category name="Variables" categorystyle="variable_category" custom="VARIABLE"></category>
<category name="Functions" categorystyle="procedure_category" custom="PROCEDURE"></category>
</xml>
<!-- toolbox-categories-typed-variables has a category menu and an
auto-closing flyout. The Variables category uses typed variable blocks.
See https://developers.google.com/blockly/guides/create-custom-blocks/variables#typed_variable_blocks for more information. -->
<xml xmlns="https://developers.google.com/blockly/xml" id="toolbox-categories-typed-variables" style="display: none">
<category name="Logic" categorystyle="logic_category">
<block type="controls_if"></block>
<block type="logic_compare"></block>
<block type="logic_operation"></block>
<block type="logic_negate"></block>
<block type="logic_boolean"></block>
<block type="logic_null" disabled="true"></block>
<block type="logic_ternary"></block>
</category>
<category name="Loops" categorystyle="loop_category">
<block type="controls_repeat_ext">
<value name="TIMES">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
</block>
<block type="controls_repeat" disabled="true"></block>
<block type="controls_whileUntil"></block>
<block type="controls_for">
<value name="FROM">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="TO">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
<value name="BY">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>
<block type="controls_forEach"></block>
<block type="controls_flow_statements"></block>
</category>
<category name="Math" categorystyle="math_category">
<block type="math_number" gap="32">
<field name="NUM">123</field>
</block>
<block type="math_arithmetic">
<value name="A">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="B">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>
<block type="math_single">
<value name="NUM">
<shadow type="math_number">
<field name="NUM">9</field>
</shadow>
</value>
</block>
<block type="math_trig">
<value name="NUM">
<shadow type="math_number">
<field name="NUM">45</field>
</shadow>
</value>
</block>
<block type="math_constant"></block>
<block type="math_number_property">
<value name="NUMBER_TO_CHECK">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
</block>
<block type="math_round">
<value name="NUM">
<shadow type="math_number">
<field name="NUM">3.1</field>
</shadow>
</value>
</block>
<block type="math_on_list"></block>
<block type="math_modulo">
<value name="DIVIDEND">
<shadow type="math_number">
<field name="NUM">64</field>
</shadow>
</value>
<value name="DIVISOR">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
</block>
<block type="math_constrain">
<value name="VALUE">
<shadow type="math_number">
<field name="NUM">50</field>
</shadow>
</value>
<value name="LOW">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="HIGH">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>
<block type="math_random_int">
<value name="FROM">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="TO">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>
<block type="math_random_float"></block>
<block type="math_atan2">
<value name="X">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="Y">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>
</category>
<category name="Text" categorystyle="text_category">
<block type="text"></block>
<block type="text_multiline"></block>
<block type="text_join"></block>
<block type="text_append">
<value name="TEXT">
<shadow type="text"></shadow>
</value>
</block>
<block type="text_length">
<value name="VALUE">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_isEmpty">
<value name="VALUE">
<shadow type="text">
<field name="TEXT"></field>
</shadow>
</value>
</block>
<block type="text_indexOf">
<value name="VALUE">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
<value name="FIND">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_charAt">
<value name="VALUE">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
</block>
<block type="text_getSubstring">
<value name="STRING">
<block type="variables_get">
<field name="VAR">text</field>
</block>
</value>
</block>
<block type="text_changeCase">
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_trim">
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_count">
<value name="SUB">
<shadow type="text"></shadow>
</value>
<value name="TEXT">
<shadow type="text"></shadow>
</value>
</block>
<block type="text_replace">
<value name="FROM">
<shadow type="text"></shadow>
</value>
<value name="TO">
<shadow type="text"></shadow>
</value>
<value name="TEXT">
<shadow type="text"></shadow>
</value>
</block>
<block type="text_reverse">
<value name="TEXT">
<shadow type="text"></shadow>
</value>
</block>
<label text="Input/Output:" web-class="ioLabel"></label>
<block type="text_print">
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_prompt_ext">
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
</category>
<category name="Lists" categorystyle="list_category">
<block type="lists_create_with">
<mutation items="0"></mutation>
</block>
<block type="lists_create_with"></block>
<block type="lists_repeat">
<value name="NUM">
<shadow type="math_number">
<field name="NUM">5</field>
</shadow>
</value>
</block>
<block type="lists_length"></block>
<block type="lists_isEmpty"></block>
<block type="lists_indexOf">
<value name="VALUE">
<block type="variables_get">
<field name="VAR">list</field>
</block>
</value>
</block>
<block type="lists_getIndex">
<value name="VALUE">
<block type="variables_get">
<field name="VAR">list</field>
</block>
</value>
</block>
<block type="lists_setIndex">
<value name="LIST">
<block type="variables_get">
<field name="VAR">list</field>
</block>
</value>
</block>
<block type="lists_getSublist">
<value name="LIST">
<block type="variables_get">
<field name="VAR">list</field>
</block>
</value>
</block>
<block type="lists_split">
<value name="DELIM">
<shadow type="text">
<field name="TEXT">,</field>
</shadow>
</value>
</block>
<block type="lists_sort"></block>
<block type="lists_reverse"></block>
</category>
<category name="Colour" categorystyle="colour_category">
<block type="colour_picker"></block>
<block type="colour_random"></block>
<block type="colour_rgb">
<value name="RED">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="GREEN">
<shadow type="math_number">
<field name="NUM">50</field>
</shadow>
</value>
<value name="BLUE">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
</block>
<block type="colour_blend">
<value name="COLOUR1">
<shadow type="colour_picker">
<field name="COLOUR">#ff0000</field>
</shadow>
</value>
<value name="COLOUR2">
<shadow type="colour_picker">
<field name="COLOUR">#3333ff</field>
</shadow>
</value>
<value name="RATIO">
<shadow type="math_number">
<field name="NUM">0.5</field>
</shadow>
</value>
</block>
</category>
<sep></sep>
<category name="Variables" categorystyle="variable_category" custom="VARIABLE_DYNAMIC"></category>
<category name="Functions" categorystyle="procedure_category" custom="PROCEDURE"></category>
</xml>
</body>
</html>