mirror of
https://github.com/scratchfoundation/scratch-blocks.git
synced 2025-08-28 22:10:31 -04:00
Replaces calls to window.alert(), window.confirm(), and window.prompt() with Blockly.alert(), Blockly.confirm(), and Blockly.prompt(). These are designed to allow app developers to replace the dialogs with versions that match their own open app, possibly avoiding modal browser dialogs. They each take a callback, so the developer has the opportunity to implement non-modal behavior.
This commit is contained in:
parent
13c5d9b3dd
commit
8f3b4bcb5e
8 changed files with 567 additions and 56 deletions
|
@ -338,6 +338,42 @@ Blockly.getMainWorkspace = function() {
|
|||
return Blockly.mainWorkspace;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper to window.alert() that app developers may override to
|
||||
* provide alternatives to the modal browser window.
|
||||
* @param {string} message The message to display to the user.
|
||||
* @param {function()=} opt_callback The callback when the alert is dismissed.
|
||||
*/
|
||||
Blockly.alert = function(message, opt_callback) {
|
||||
window.alert(message);
|
||||
if (opt_callback) {
|
||||
opt_callback();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper to window.confirm() that app developers may override to
|
||||
* provide alternatives to the modal browser window.
|
||||
* @param {string} message The message to display to the user.
|
||||
* @param {!function(boolean)} callback The callback for handling user response.
|
||||
*/
|
||||
Blockly.confirm = function(message, callback) {
|
||||
callback(window.confirm(message));
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper to window.prompt() that app developers may override to provide
|
||||
* alternatives to the modal browser window. Built-in browser prompts are
|
||||
* often used for better text input experience on mobile device. We strongly
|
||||
* recommend testing mobile when overriding this.
|
||||
* @param {string} message The message to display to the user.
|
||||
* @param {string} defaultValue The value to initialize the prompt with.
|
||||
* @param {!function(string)} callback The callback for handling user reponse.
|
||||
*/
|
||||
Blockly.prompt = function(message, defaultValue, callback) {
|
||||
callback(window.prompt(message, defaultValue));
|
||||
};
|
||||
|
||||
// IE9 does not have a console. Create a stub to stop errors.
|
||||
if (!goog.global['console']) {
|
||||
goog.global['console'] = {
|
||||
|
|
|
@ -130,7 +130,7 @@ Blockly.FieldAngle.prototype.showEditor_ = function() {
|
|||
Blockly.FieldAngle.superClass_.showEditor_.call(this, noFocus);
|
||||
var div = Blockly.WidgetDiv.DIV;
|
||||
if (!div.firstChild) {
|
||||
// Mobile interface uses window.prompt.
|
||||
// Mobile interface uses Blockly.prompt.
|
||||
return;
|
||||
}
|
||||
// Build the SVG DOM.
|
||||
|
|
|
@ -114,11 +114,14 @@ Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput) {
|
|||
if (!quietInput && (goog.userAgent.MOBILE || goog.userAgent.ANDROID ||
|
||||
goog.userAgent.IPAD)) {
|
||||
// Mobile browsers have issues with in-line textareas (focus & keyboards).
|
||||
var newValue = window.prompt(Blockly.Msg.CHANGE_VALUE_TITLE, this.text_);
|
||||
if (this.sourceBlock_) {
|
||||
newValue = this.callValidator(newValue);
|
||||
}
|
||||
this.setValue(newValue);
|
||||
var fieldText = this;
|
||||
Blockly.prompt(Blockly.Msg.CHANGE_VALUE_TITLE, this.text_,
|
||||
function(newValue) {
|
||||
if (fieldText.sourceBlock_) {
|
||||
newValue = fieldText.callValidator(newValue);
|
||||
}
|
||||
fieldText.setValue(newValue);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -227,47 +227,57 @@ Blockly.Variables.generateUniqueName = function(workspace) {
|
|||
* Create a new variable on the given workspace.
|
||||
* @param {!Blockly.Workspace} workspace The workspace on which to create the
|
||||
* variable.
|
||||
* @return {null|undefined|string} An acceptable new variable name, or null if
|
||||
* change is to be aborted (cancel button), or undefined if an existing
|
||||
* variable was chosen.
|
||||
* @param {function(null|undefined|string)=} opt_callback A callback. It will
|
||||
* return an acceptable new variable name, or null if change is to be
|
||||
* aborted (cancel button), or undefined if an existing variable was chosen.
|
||||
*/
|
||||
Blockly.Variables.createVariable = function(workspace) {
|
||||
while (true) {
|
||||
var text = Blockly.Variables.promptName(Blockly.Msg.NEW_VARIABLE_TITLE, '');
|
||||
if (text) {
|
||||
if (workspace.variableIndexOf(text) != -1) {
|
||||
window.alert(Blockly.Msg.VARIABLE_ALREADY_EXISTS.replace('%1',
|
||||
text.toLowerCase()));
|
||||
} else {
|
||||
workspace.createVariable(text);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
text = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return text;
|
||||
Blockly.Variables.createVariable = function(workspace, opt_callback) {
|
||||
var promptAndCheckWithAlert = function(defaultName) {
|
||||
Blockly.Variables.promptName(Blockly.Msg.NEW_VARIABLE_TITLE, defaultName,
|
||||
function(text) {
|
||||
if (text) {
|
||||
if (workspace.variableIndexOf(text) != -1) {
|
||||
Blockly.alert(Blockly.Msg.VARIABLE_ALREADY_EXISTS.replace('%1',
|
||||
text.toLowerCase()),
|
||||
function() {
|
||||
promptAndCheckWithAlert(text); // Recurse
|
||||
});
|
||||
} else {
|
||||
workspace.createVariable(text);
|
||||
if (opt_callback) {
|
||||
opt_callback(text);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// User canceled prompt without a value.
|
||||
if (opt_callback) {
|
||||
opt_callback(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
promptAndCheckWithAlert('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Prompt the user for a new variable name.
|
||||
* @param {string} promptText The string of the prompt.
|
||||
* @param {string} defaultText The default value to show in the prompt's field.
|
||||
* @return {?string} The new variable name, or null if the user picked
|
||||
* something illegal.
|
||||
* @param {function(?string)} callback A callback. It will return the new
|
||||
* variable name, or null if the user picked something illegal.
|
||||
*/
|
||||
Blockly.Variables.promptName = function(promptText, defaultText) {
|
||||
var newVar = window.prompt(promptText, defaultText);
|
||||
// Merge runs of whitespace. Strip leading and trailing whitespace.
|
||||
// Beyond this, all names are legal.
|
||||
if (newVar) {
|
||||
newVar = newVar.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, '');
|
||||
if (newVar == Blockly.Msg.RENAME_VARIABLE ||
|
||||
newVar == Blockly.Msg.NEW_VARIABLE) {
|
||||
// Ok, not ALL names are legal...
|
||||
newVar = null;
|
||||
Blockly.Variables.promptName = function(promptText, defaultText, callback) {
|
||||
Blockly.prompt(promptText, defaultText, function(newVar) {
|
||||
// Merge runs of whitespace. Strip leading and trailing whitespace.
|
||||
// Beyond this, all names are legal.
|
||||
if (newVar) {
|
||||
newVar = newVar.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, '');
|
||||
if (newVar == Blockly.Msg.RENAME_VARIABLE ||
|
||||
newVar == Blockly.Msg.NEW_VARIABLE) {
|
||||
// Ok, not ALL names are legal...
|
||||
newVar = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newVar;
|
||||
callback(newVar);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -316,26 +316,29 @@ Blockly.Workspace.prototype.deleteVariable = function(name) {
|
|||
if (block.type == 'procedures_defnoreturn' ||
|
||||
block.type == 'procedures_defreturn') {
|
||||
var procedureName = block.getFieldValue('NAME');
|
||||
window.alert(
|
||||
Blockly.alert(
|
||||
Blockly.Msg.CANNOT_DELETE_VARIABLE_PROCEDURE.replace('%1', name).
|
||||
replace('%2', procedureName));
|
||||
replace('%2', procedureName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
var ok = window.confirm(
|
||||
var workspace = this;
|
||||
Blockly.confirm(
|
||||
Blockly.Msg.DELETE_VARIABLE_CONFIRMATION.replace('%1', uses.length).
|
||||
replace('%2', name));
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
replace('%2', name),
|
||||
function(ok) {
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
Blockly.Events.setGroup(true);
|
||||
for (var i = 0; i < uses.length; i++) {
|
||||
uses[i].dispose(true, false);
|
||||
Blockly.Events.setGroup(true);
|
||||
for (var i = 0; i < uses.length; i++) {
|
||||
uses[i].dispose(true, false);
|
||||
}
|
||||
Blockly.Events.setGroup(false);
|
||||
workspace.variableList.splice(variableIndex, 1);
|
||||
});
|
||||
}
|
||||
Blockly.Events.setGroup(false);
|
||||
this.variableList.splice(variableIndex, 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -985,10 +985,16 @@ Blockly.WorkspaceSvg.prototype.showContextMenu_ = function(e) {
|
|||
Blockly.Msg.DELETE_X_BLOCKS.replace('%1', String(deleteList.length)),
|
||||
enabled: deleteList.length > 0,
|
||||
callback: function() {
|
||||
if (deleteList.length < 2 ||
|
||||
window.confirm(Blockly.Msg.DELETE_ALL_BLOCKS.replace('%1',
|
||||
String(deleteList.length)))) {
|
||||
if (deleteList.length < 2 ) {
|
||||
deleteNext();
|
||||
} else {
|
||||
Blockly.confirm(Blockly.Msg.DELETE_ALL_BLOCKS.
|
||||
replace('%1',String(deleteList.length)),
|
||||
function(ok) {
|
||||
if (ok) {
|
||||
deleteNext();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
101
demos/custom-dialogs/custom-dialog.js
Normal file
101
demos/custom-dialogs/custom-dialog.js
Normal file
|
@ -0,0 +1,101 @@
|
|||
/** Override Blockly.alert() with custom implementation. */
|
||||
Blockly.alert = function(message, callback) {
|
||||
showDialog('Alert', message, {
|
||||
okay: callback
|
||||
});
|
||||
}
|
||||
|
||||
/** Override Blockly.confirm() with custom implementation. */
|
||||
Blockly.confirm = function(message, callback) {
|
||||
showDialog('Confirm', message, {
|
||||
showOkay: true,
|
||||
okay: function() {
|
||||
callback(true)
|
||||
},
|
||||
showCancel: true,
|
||||
cancel: function() {
|
||||
callback(false)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Override Blockly.prompt() with custom implementation. */
|
||||
Blockly.prompt = function(message, defaultValue, callback) {
|
||||
showDialog('Prompt', message, {
|
||||
showInput: true,
|
||||
showOkay: true,
|
||||
okay: function() {
|
||||
callback(dialogInput.value)
|
||||
},
|
||||
showCancel: true,
|
||||
cancel: function() {
|
||||
callback(null)
|
||||
}
|
||||
});
|
||||
dialogInput.value = defaultValue
|
||||
}
|
||||
|
||||
// Implementation details below...
|
||||
var backdropDiv, dialogDiv, dialogInput
|
||||
|
||||
function hideDialog() {
|
||||
backdropDiv.style.display = 'none'
|
||||
dialogDiv.style.display = 'none'
|
||||
}
|
||||
|
||||
function showDialog(title, message, options) {
|
||||
if (!backdropDiv) {
|
||||
// Generate HTML
|
||||
var body = document.getElementsByTagName('body')[0]
|
||||
backdropDiv = document.createElement('div')
|
||||
backdropDiv.setAttribute('id', 'backdrop')
|
||||
body.appendChild(backdropDiv)
|
||||
|
||||
dialogDiv = document.createElement('div')
|
||||
dialogDiv.setAttribute('id', 'dialog')
|
||||
backdropDiv.appendChild(dialogDiv)
|
||||
dialogDiv.onclick = function(event) {
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
}
|
||||
backdropDiv.style.display = 'block'
|
||||
dialogDiv.style.display = 'block'
|
||||
|
||||
dialogDiv.innerHTML = '<div id="dialogTitle"><strong>' + title + '</strong></div>'
|
||||
+ '<p>' + message + '</p>'
|
||||
+ (options.showInput? '<div><input id="dialogInput"></div>' : '')
|
||||
+ '<div class="buttons">'
|
||||
+ (options.showCancel ? '<button id="dialogCancel">Cancel</button>': '')
|
||||
+ (options.showOkay ? '<button id="dialogOkay">OK</button>': '')
|
||||
+ '</div>'
|
||||
dialogInput = document.getElementById('dialogInput')
|
||||
|
||||
document.getElementById('dialogOkay').onclick = function(event) {
|
||||
hideDialog()
|
||||
if (options.okay) {
|
||||
options.okay()
|
||||
}
|
||||
event.stopPropagation()
|
||||
}
|
||||
document.getElementById('dialogCancel').onclick = function(event) {
|
||||
hideDialog()
|
||||
if (options.cancel) {
|
||||
options.cancel()
|
||||
}
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
backdropDiv.onclick = function(event) {
|
||||
hideDialog()
|
||||
if (options.cancel) {
|
||||
options.cancel();
|
||||
} else if (options.okay) {
|
||||
options.okay();
|
||||
}
|
||||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
352
demos/custom-dialogs/index.html
Normal file
352
demos/custom-dialogs/index.html
Normal file
|
@ -0,0 +1,352 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Blockly Demo: Custom Dialog</title>
|
||||
<script src="../../blockly_compressed.js"></script>
|
||||
<script src="../../blocks_compressed.js"></script>
|
||||
<script src="../../msg/js/en.js"></script>
|
||||
<style>
|
||||
body {
|
||||
background-color: #fff;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
h1 {
|
||||
font-weight: normal;
|
||||
font-size: 140%;
|
||||
}
|
||||
#backdrop {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
#dialog {
|
||||
background-color: white;
|
||||
width: 400px;
|
||||
margin: 20px auto 0;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1><a href="https://developers.google.com/blockly/">Blockly</a> >
|
||||
<a href="../index.html">Demos</a> > Custom Dialog</h1>
|
||||
|
||||
<p>This is a simple demo of replacing modal browser dialogs with HTML.</p>
|
||||
|
||||
<p>Try creating new variables, creating variables with names already in
|
||||
use, or deleting multiple blocks on the workspace.
|
||||
</p>
|
||||
|
||||
<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>
|
||||
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Logic" colour="210">
|
||||
<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" colour="120">
|
||||
<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" colour="230">
|
||||
<block type="math_number" gap="32"></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>
|
||||
</category>
|
||||
<category name="Text" colour="160">
|
||||
<block type="text"></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_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" colour="260">
|
||||
<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>
|
||||
</category>
|
||||
<category name="Colour" colour="20">
|
||||
<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" colour="330" custom="VARIABLE"></category>
|
||||
<category name="Functions" colour="290" custom="PROCEDURE"></category>
|
||||
</xml>
|
||||
|
||||
<script>
|
||||
var workspace = Blockly.inject('blocklyDiv',
|
||||
{media: '../../media/',
|
||||
toolbox: document.getElementById('toolbox')});
|
||||
</script>
|
||||
<script src="custom-dialog.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue