mirror of
https://github.com/google/blockly.git
synced 2026-01-07 17:10:11 +01:00
Porting wiki pages from Google Code.
18
Alternatives.md
Normal file
18
Alternatives.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# A growing family
|
||||
|
||||
Blockly is one of a growing number of visual programming environments. Many of these languages have roots at MIT, leading to a similar look and feel across different products. Blockly was influenced by [App Inventor](http://www.appinventor.mit.edu/), which in turn was influenced by [Scratch](http://scratch.mit.edu/), which in turn was influenced by [StarLogo](http://education.mit.edu/projects/starlogo-tng).
|
||||
|
||||
# Blockly's distinguishing features
|
||||
|
||||
Blockly was designed with the following requirements:
|
||||
* Execute in a web-browser. No downloads or plugins needed.
|
||||
* Exportable code. Users can extract their programs as JavaScript, Python, Dart or other language so that when they outgrow Blockly they can keep learning.
|
||||
* Open source. Everything about Blockly is open: you can fork it, hack it, and use it in your own websites.
|
||||
* Highly capable. With the ability to calculate standard deviation using a single block, Blockly is not a toy.
|
||||
|
||||
Equally important is a negative characteristic:
|
||||
* Blockly in itself is not an educational platform. Blockly is an editor that may be used as part of an educational platform, or as part of a business suite, or as part of a gaming system, etc.
|
||||
|
||||
# Alternatives
|
||||
|
||||
Wikipedia currently lists about a hundred [visual programming environments](https://en.wikipedia.org/wiki/Visual_programming_language). Please check them out before choosing one. Visual programming environments are still evolving quickly and as a community we are still learning what works and what doesn't.
|
||||
10
And_Or.md
Normal file
10
And_Or.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# The **And Or** Block
|
||||
|
||||
To access the **And Or** Block, click **Logic**.
|
||||
|
||||
| **Option** | **Description** |
|
||||
|:-----------|:----------------|
|
||||
| **and** | Place this between two blocks to make the program do something whenever both conditions exist at the same time. Example: In the Maze program, you might want your player to move forward whenever there are walls on both sides. To do this, use **wall to the right?** and **wall to the left?**.|
|
||||
| **or** |Place this between two blocks when you want the program to do something whenever at least one of the conditions exist.|
|
||||
|
||||
**Note**: The **And Or** block fits with blocks that it might not be useful with. For example, it fits with the **True** block.
|
||||
5
BlockTemplates.md
Normal file
5
BlockTemplates.md
Normal file
@@ -0,0 +1,5 @@
|
||||
**This describes work in progress. Use of this functionality is not yet recommended.**
|
||||
|
||||
# Introduction
|
||||
|
||||
[Creating new blocks in JavaScript](https://code.google.com/p/blockly/wiki/Tutorial_CreateYourFirstBlock) can be repetitive and error-prone, especially if the blocks have [mutators](https://code.google.com/p/blockly/wiki/CreatingMutators). The purpose of the block template system is to enable new blocks to be added with less work and worry.
|
||||
11
BlocklyModes.md
Normal file
11
BlocklyModes.md
Normal file
@@ -0,0 +1,11 @@
|
||||
Blockly has two modes: simple and advanced.
|
||||
|
||||
Simple mode has a fixed toolbox with a small number of blocks, no scrollbars, and usually no trashcan:
|
||||
https://blockly-demo.appspot.com/static/demos/fixed/index.html
|
||||
|
||||
Advanced mode has flyout toolboxes organized by category, an infinite scrolling workspace, and usually a trashcan:
|
||||
https://blockly-demo.appspot.com/static/demos/toolbox/index.html
|
||||
|
||||
These two modes are mutually incompatible. Consider what happens when one drags a block to the toolbox. In one mode the block is deleted. In the other mode the workspace grows to the left. A scrolling workspace next to a fixed toolbox would be bad.
|
||||
|
||||
The determining factor for the existence of a scrolling workspace is whether there are categories in the toolbox. See the second link, above.
|
||||
80
CachingArguments.md
Normal file
80
CachingArguments.md
Normal file
@@ -0,0 +1,80 @@
|
||||
**[Creating Custom Blocks](wiki/CustomBlocks): [Generating Code](wiki/GeneratingCode): Caching Arguments**
|
||||
|
||||
# Caching Arguments
|
||||
|
||||
When generating code from blocks one often finds the need to use the returned value of a sub-block more than once. Consider a value block that finds and returns the last element of a list. The block itself would have one input (a list), and would return a value (the last element). Here is the generator for JavaScript:
|
||||
```
|
||||
var code = arg0 + '[' + arg0 + '.length - 1]';
|
||||
```
|
||||
If ` arg0 ` is a variable name, this generator returns perfectly acceptable JavaScript:
|
||||
```
|
||||
aList[aList.length - 1]
|
||||
```
|
||||
However, this generator may have unintended behaviour if ` arg0 ` were a function call. Consider the following code:
|
||||
```
|
||||
randomList()[randomList().length - 1]
|
||||
```
|
||||
The two returned values might be of different lengths, resulting in an out of range condition. Additionally, if the function call has side-effects, then calling it twice could be undesirable.
|
||||
|
||||
There are two solutions to this problem. Statement blocks should use temporary variables. Value blocks should use utility functions.
|
||||
|
||||
## Temporary Variables
|
||||
|
||||
The simplest solution is to assign the offending input to a temporary variable. Care must be taken that this variable does not accidentally collide with an existing variable. The following code shows an example of a temporary variable in a statement block which alerts the last element of a list.
|
||||
```
|
||||
var listVar = Blockly.JavaScript.variableDB_.getDistinctName(
|
||||
'temp_list', Blockly.Variables.NAME_TYPE);
|
||||
var code = 'var ' + listVar + ' = ' + arg0 + ';\n';
|
||||
code += 'alert(' + listVar + '[' + listVar + '.length - 1]);\n';
|
||||
```
|
||||
The ` getDistinctName ` call takes an argument of the desired variable name ("temp\_list") and will return an non-colliding name to use (possibly "temp\_list2").
|
||||
|
||||
The downside of temporary variables is that if the offending input was already a variable, then one generates redundant code:
|
||||
```
|
||||
var temp_list = foo;
|
||||
alert(temp_list[temp_list.length - 1]);
|
||||
```
|
||||
To produce cleaner code, check to see if the offending input is a simple literal, and generate code accordingly:
|
||||
```
|
||||
if (argument0.match(/^\w+$/)) {
|
||||
var code = 'alert(' + arg0 + '[' + arg0 + '.length - 1]);\n';
|
||||
} else {
|
||||
var listVar = Blockly.JavaScript.variableDB_.getDistinctName(
|
||||
'temp_list', Blockly.Variables.NAME_TYPE);
|
||||
var code = 'var ' + listVar + ' = ' + arg0 + ';\n';
|
||||
code += 'alert(' + listVar + '[' + listVar + '.length - 1]);\n';
|
||||
}
|
||||
```
|
||||
|
||||
See ` Blockly.JavaScript.controls_forEach ` for a working example of temporary variables.
|
||||
|
||||
Temporary variables work well in statement blocks (in this case an alert) where the generated code may span multiple lines. However they are unworkable in value blocks which must be on a single line. For value blocks one must use a utility function instead of temporary variables.
|
||||
|
||||
## Utility Functions
|
||||
|
||||
Defining a utility function is a powerful way to create blocks that operate at a higher level than the underlying language. Utility functions are not generated unless they are used, and they are only generated once regardless of the number of times they are used. The following example includes inline comments.
|
||||
|
||||
```
|
||||
// Only define a utility function if it hasn't already been defined.
|
||||
// The 'definitions_' property of the generator stores all the utility functions.
|
||||
if (!Blockly.JavaScript.definitions_['list_lastElement']) {
|
||||
// Obtain a non-colliding function name.
|
||||
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
|
||||
'list_lastElement', Blockly.Generator.NAME_TYPE);
|
||||
// Save this name in a place that can be accessed by all blocks of this type.
|
||||
Blockly.JavaScript.list_lastElement.utilityFunction = functionName;
|
||||
// Build the function line by line. Ensure that the name is dynamic.
|
||||
var func = [];
|
||||
func.push('function ' + functionName + '(aList) {');
|
||||
func.push(' // Return the last element of a list.');
|
||||
func.push(' return aList[aList.length - 1];');
|
||||
func.push('}');
|
||||
// Add the completed function to the code generator.
|
||||
Blockly.JavaScript.definitions_['list_lastElement'] = func.join('\n');
|
||||
}
|
||||
// Generate the function call for this block.
|
||||
var code = Blockly.JavaScript.list_lastElement.utilityFunction + '(' + arg0 + ')';
|
||||
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
|
||||
```
|
||||
|
||||
See ` Blockly.JavaScript.text_endString ` for a working example of a utility function.
|
||||
21
Closure.md
Normal file
21
Closure.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Introduction
|
||||
|
||||
Did you just get this error message?
|
||||
|
||||

|
||||
|
||||
If so, then you are probably attempting to run the uncompiled version of Blockly and you are missing the dependency on [Closure Library](https://developers.google.com/closure/library/).
|
||||
|
||||
## Getting Closure
|
||||
|
||||
Getting Closure is quick and easy. Use Subversion to checkout a copy from [Closure's repository](https://code.google.com/p/closure-library/source/checkout):
|
||||
|
||||
```
|
||||
svn checkout https://github.com/google/closure-library/trunk closure-library-read-only
|
||||
```
|
||||
|
||||
Once you have the Closure files, place them next to Blocky's root directory and ensure that the directory is named ` closure-library-read-only `. This is the directory structure you want:
|
||||
|
||||

|
||||
|
||||
That's it. Blockly should now work in uncompiled mode.
|
||||
79
CloudStorageWithAppEngine.md
Normal file
79
CloudStorageWithAppEngine.md
Normal file
@@ -0,0 +1,79 @@
|
||||
**[Installation](wiki/Installation): Cloud Storage**
|
||||
|
||||
# Introduction
|
||||
|
||||
If your application is hosted on App Engine, a cloud storage service is available that allows users to save, load, share, and publish their programs.
|
||||
|
||||
_Note that the [RealtimeCollaboration](wiki/RealtimeCollaboration) feature provides an alternate way to save, load, share, and publish programs. It does, however, currently require users to have a Google Account._
|
||||
|
||||
## Setting up App Engine
|
||||
|
||||
The first step is to get your own copy of Blockly running on App Engine.
|
||||
|
||||
1. Download and install the [Python SDK](https://developers.google.com/appengine/downloads).
|
||||
1. Log into [Google App Engine](https://appengine.google.com/) and create an application.
|
||||
1. Edit ` appengine/app.yaml ` and change the application ID from ` blockly-demo ` to the application name you created in the previous step.
|
||||
1. Copy (or soft-link) the following files and directories into ` appengine/static/ `:
|
||||
* ` apps/ `
|
||||
* ` demos/ `
|
||||
* ` msg/ `
|
||||
* ` media/ `
|
||||
* ` tests/ `
|
||||
* ` *_compressed.js `
|
||||
1. Optional: If you'd like to use ` blockly_uncompressed.js ` on the server, also copy that into ` appengine/static/ ` and copy ` closure-library-read-only/ ` into the parent directory, ` appengine/ `.
|
||||
1. Optional: If you'd like to run the Blockly Playground, you'll have to add links for the ` blocks `, ` core `, ` generators `, and ` tests ` directories, as well as the files in step 5.
|
||||
1. Run the Google App Engine Launcher from the GUI, add your ` appengine ` directory as an existing application, and press the "Deploy" button. If you prefer to use the command line, run: ` appcfg.py --oauth2 update appengine/ `.
|
||||
|
||||
Once Blockly is uploaded you can point a browser to the URL you created in step 2. You should see a list of demos, including the cloud storage demo.
|
||||
|
||||
## Talking to the Cloud
|
||||
|
||||
Examine the source of the [storage demo](https://blockly-demo.appspot.com/static/demos/storage/index.html) at [demos/storage/index.html](https://code.google.com/p/blockly/source/browse/trunk/demos/storage/index.html) and note the following features. First, there is a script include that loads the cloud storage API:
|
||||
|
||||
```
|
||||
<script type="text/javascript" src="/storage.js"></script>
|
||||
```
|
||||
|
||||
There are also these message definitions, which you should modify as desired:
|
||||
```
|
||||
BlocklyStorage.HTTPREQUEST_ERROR = 'There was a problem with the request.\n';
|
||||
BlocklyStorage.LINK_ALERT = 'Share your blocks with this link:\n\n%1';
|
||||
BlocklyStorage.HASH_ERROR = 'Sorry, "%1" doesn\'t correspond with any saved Blockly file.';
|
||||
BlocklyStorage.XML_ERROR = 'Could not load your saved file.\n'+
|
||||
'Perhaps it was created with a different version of Blockly?';
|
||||
```
|
||||
Translations into other languages can be found at [apps/json](https://code.google.com/p/blockly/source/browse/#svn%2Ftrunk%2Fapps%2Fjson).
|
||||
|
||||
Saving the current blocks is a single call to ` BlocklyStorage.link() `:
|
||||
|
||||
```
|
||||
<button onclick="BlocklyStorage.link()">Save Blocks</button>
|
||||
```
|
||||
|
||||
To restore saved blocks on page load, just call ` BlocklyStorage.retrieveXml ` with the URL's hash after Blockly has been injected:
|
||||
|
||||
```
|
||||
if ('BlocklyStorage' in window && window.location.hash.length > 1) {
|
||||
BlocklyStorage.retrieveXml(window.location.hash.substring(1));
|
||||
}
|
||||
```
|
||||
|
||||
## Local Storage
|
||||
|
||||
The ` storage.js ` API also offers the ability to save a single set of blocks in the browser's local storage. This may be implemented instead of cloud storage, or in addition with cloud storage (though in the latter case one has to be careful of both types of storage attempting to restore at once).
|
||||
|
||||
To restore blocks from local storage, call ` BlocklyStorage.restoreBlocks ` in a timeout right after Blockly has been injected.
|
||||
|
||||
```
|
||||
window.setTimeout(BlocklyStorage.restoreBlocks, 0);
|
||||
```
|
||||
|
||||
To automatically backup the blocks into local storage when the user leaves the page, call ` BlocklyStorage.backupOnUnload ` and it will register an event listener on the page's unload event.
|
||||
|
||||
```
|
||||
BlocklyStorage.backupOnUnload();
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
Here is [a live demo](https://blockly-demo.appspot.com/static/demos/storage/index.html) of cloud storage.
|
||||
48
Colour.md
Normal file
48
Colour.md
Normal file
@@ -0,0 +1,48 @@
|
||||
(TODO: Add table of contents.)
|
||||
|
||||
# Introduction
|
||||
|
||||
Blockly users can choose, create, and blend colours. Colours are primarily used in [the turtle graphics application](https://blockly-demo.appspot.com/static/apps/turtle/index.html) but are also available in [the coding application](https://blockly-demo.appspot.com/static/apps/code/index.html). Note that we use the British spelling of "colour".
|
||||
|
||||
# Blocks
|
||||
## Picking a colour from a palette
|
||||
|
||||
The simplest way to get a colour is with the **colour picker**. It appears as a red rounded rectangle. When the user clicks on it, a palette of colours pops open, from which the user can choose the desired colour by again clicking.
|
||||
|
||||

|
||||
|
||||
## Creating a colour from red, green, and blue components
|
||||
|
||||
The **colour with** block allows the user to specify the desired percent of red, green, and blue. This block builds a colour with the maximum amounts of red and blue and no green (making purple):
|
||||
|
||||

|
||||
|
||||
Note that we use [a range from 0 to 100 (inclusive) for each component](http://www.december.com/html/spec/colorper.html), not the less intuitive range of 0 to 255 generally used by programmers and graphic designers.
|
||||
|
||||
The ability to specify colours with changing numbers allows some beautiful turtle graphic applications, such as [this contest winner](https://plus.google.com/105063463762828771517/posts/HzzPaimTLwu) (see code):
|
||||
|
||||
## Generating a random colour
|
||||
|
||||
The **random colour** block generates colours at random.
|
||||
|
||||

|
||||
|
||||
Specifically, each of the red, green, and blue components is a number from 0 to 255 (inclusive), with equal likelihood.
|
||||
|
||||
## Blending colours
|
||||
|
||||
Unlike traditional turtle graphics systems, Blockly provides a means for blending two colours, as though one were blending two different colours of paint. The following block provides the colour that would be obtained by mixing equal amounts of red paint (actually, [red light](http://www.newton.dep.anl.gov/askasci/gen99/gen99557.htm)) and yellow paint:
|
||||
|
||||

|
||||
|
||||
If the ratio were 0, the result would have no red and all yellow. If the ratio were 1, the result would be all red and no yellow.
|
||||
|
||||
# Technical details
|
||||
|
||||
Blockly colours are represented as text of the form "#rrggbb" where "rr", "gg", and "bb" represent the red, green, and blue components, respectively, in the hexadecimal range 00 to ff. Since colours are usually passed to the "set colour" block in the turtle graphics application, most users are never aware of this, but it is exposed by the following program:
|
||||
|
||||

|
||||
|
||||
which prints "#ff0000".
|
||||
|
||||
Note that [blending light is different from blending pigments](http://www.newton.dep.anl.gov/askasci/gen99/gen99557.htm). Blending red, green, and blue light in equal ratios yields white light, while blending red, green, and blue paint yields a muddy colour.
|
||||
76
ContributingCode.md
Normal file
76
ContributingCode.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Introduction
|
||||
|
||||
Blockly welcomes your contributions. Want to translate Blockly into a new language? Want to fix a bug that's annoying you? Want to write an application that uses Blockly?
|
||||
|
||||
The only rule is that all code committed by anyone must be reviewed and approved by one other contributor.
|
||||
|
||||
## First-time contributor
|
||||
|
||||
Just use Subversion to pull down a copy of Blockly's source from the repository:
|
||||
```
|
||||
svn checkout http://blockly.googlecode.com/svn/trunk/ blockly
|
||||
```
|
||||
Windows users may wish to use [Tortise SVN](http://tortoisesvn.tigris.org/).
|
||||
|
||||
Make your changes, then send us the resulting patch:
|
||||
```
|
||||
svn diff
|
||||
```
|
||||
Post the patch in a bug, or on the newsgroup, or email it to one of us.
|
||||
|
||||
If it is good, and you want to do more, we will add you as a contributor.
|
||||
|
||||
## As a contributor
|
||||
|
||||
Once you are a Blockly contributor we encourage you to [install depot\_tools](http://dev.chromium.org/developers/how-tos/install-depot-tools) that streamline the process of getting reviews done. Then you can set up your working directory:
|
||||
|
||||
```
|
||||
mkdir blockly
|
||||
cd blockly
|
||||
gclient config --name trunk https://blockly.googlecode.com/svn/trunk
|
||||
gclient sync
|
||||
```
|
||||
|
||||
First time before running 'gclient sync', you may need run the command:
|
||||
```
|
||||
svn ls https://blockly.googlecode.com/svn/trunk
|
||||
```
|
||||
|
||||
and type 'p' to accept Server certificate (p)ermanently to access the https resource.
|
||||
|
||||
[Install Closure library](https://code.google.com/p/blockly/wiki/Closure).
|
||||
|
||||
### Update the code
|
||||
|
||||
```
|
||||
cd blockly
|
||||
gclient sync
|
||||
```
|
||||
|
||||
### Submitting a code review
|
||||
|
||||
* Do some work.
|
||||
* cd trunk
|
||||
* ` gcl change `
|
||||
* [Run tests](wiki/UnitTesting).
|
||||
* ` gcl upload xxxx `
|
||||
* Go to the url on codereview.appspot.com returned by ` gcl upload `.
|
||||
* Click on "Publish+Mail Comments", fill in the reviewer field, and send.
|
||||
* Get "LGTM" (Looks Good To Me) from reviewer.
|
||||
* ` gclient sync `
|
||||
* [Run tests](wiki/UnitTesting).
|
||||
* ` gcl commit xxxx `
|
||||
|
||||
### Branching
|
||||
|
||||
To include branches in your client, create it with:
|
||||
|
||||
```
|
||||
gclient config --name blockly https://blockly.googlecode.com/svn
|
||||
```
|
||||
|
||||
To merge in changes from the main branch, run the following from the subdirectory for the branch (e.g., ` branches/i18n `):
|
||||
|
||||
```
|
||||
svn merge https://blockly.googlecode.com/svn/trunk
|
||||
```
|
||||
82
CreatingMessageDescriptions.md
Normal file
82
CreatingMessageDescriptions.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Introduction
|
||||
|
||||
In order to translate the Blockly language, we need to add descriptions for every piece of text currently displayed in English. There are 343 such messages, which are too many for the core Blockly team to mark up themselves. We are looking for volunteers who are experienced with Blockly to help add descriptions to these messages.
|
||||
|
||||
# Background
|
||||
|
||||
Please read [The Blockly Language](https://translatewiki.net/wiki/Translating:Blockly#The_Blockly_Language) within [the Blockly translation instructions](https://translatewiki.net/wiki/Translating:Blockly#The_Blockly_Language) on Translatewiki. This describes each of the types of text that appear in the language file:
|
||||
* block text
|
||||
* block input text
|
||||
* tooltip
|
||||
* context menu
|
||||
* url
|
||||
* dropdown choice
|
||||
* prompt
|
||||
* button
|
||||
It is possible that there are other types I have not yet categorized.
|
||||
|
||||
# Examples
|
||||
|
||||
I have written descriptions for 43 messages. See https://code.google.com/p/blockly/source/browse/branches/i18n/language/en/messages.js.
|
||||
|
||||
The general format is:
|
||||
```
|
||||
/** @desc <TYPE OF TEXT> - <DESCRIPTION OF TEXT FOR TRANSLATOR> */
|
||||
Blockly.<MESSAGE NAME> = goog.getMsg("<ENGLISH TEXT OF MESSAGE>");
|
||||
```
|
||||
|
||||
For example, the following definition of MSG\_DUPLICATE\_BLOCK indicates that the English-language text "Duplicate" appears on a "context menu" and that the user selects it in order to "make a duplicate of the selected block".
|
||||
|
||||
```
|
||||
/** @desc context menu - make a duplicate of the selected block */
|
||||
Blockly.MSG_DUPLICATE_BLOCK = goog.getMsg("Duplicate");
|
||||
```
|
||||
|
||||
Descriptions can contain [wikitext](https://www.mediawiki.org/wiki/Help:Formatting), which will be properly displayed to the translator. Specifically, you can include links to further information, as in this example:
|
||||
|
||||
```
|
||||
/** @desc tooltip - how if statements work (see [https://code.google.com/p/blockly/wiki/If_Then]) */
|
||||
Blockly.LANG_CONTROLS_IF_TOOLTIP_1 = goog.getMsg("If a value is true, then do some blocks");
|
||||
```
|
||||
|
||||
Descriptions may also contain bold text, indicated by pairs of 3 single quotes, to show how a word might be used in a sentence:
|
||||
|
||||
```
|
||||
/** @desc block text - if (as in: '''if''' there is a path to the right, turn right). */
|
||||
Blockly.LANG_CONTROLS_IF_MSG_IF = goog.getMsg("if");
|
||||
```
|
||||
|
||||
Descriptions may not include double quotes(").
|
||||
|
||||
# Sections
|
||||
|
||||
| **Name** | **# messages** | **corresponding source code** | **author** | **status** |
|
||||
|:---------|:---------------|:------------------------------|:-----------|:-----------|
|
||||
| context menus | 12 | [block.js](https://code.google.com/p/blockly/source/browse/trunk/core/block.js) | Ellen | done |
|
||||
| variable renaming| 5 | [variables.js](https://code.google.com/p/blockly/source/browse/trunk/core/variables.js) | Ellen | done |
|
||||
| colour | 16 | [colours.js](https://code.google.com/p/blockly/source/browse/trunk/language/common/colour.js) | Ellen | done |
|
||||
| controls: if | 15 | [control.js](https://code.google.com/p/blockly/source/browse/trunk/language/common/control.js) | Ellen | done |
|
||||
| controls: repeat, while | 11 | [control.js](https://code.google.com/p/blockly/source/browse/trunk/language/common/control.js) | -- | -- |
|
||||
| controls: for, foreach, control flow | 19 | [control.js](https://code.google.com/p/blockly/source/browse/trunk/language/common/control.js) | -- | -- |
|
||||
| logic | 27 | [logic.js](https://code.google.com/p/blockly/source/browse/trunk/language/common/logic.js) | -- | -- |
|
||||
| math | 77 | [math.js](https://code.google.com/p/blockly/source/browse/trunk/language/common/math.js) | -- | -- |
|
||||
| text | 56 | [text.js](https://code.google.com/p/blockly/source/browse/trunk/language/common/text.js) | -- | -- |
|
||||
| lists | 70 | [lists.js](https://code.google.com/p/blockly/source/browse/trunk/language/common/lists.js) | -- | -- |
|
||||
| variables | 10 | [variables.js](https://code.google.com/p/blockly/source/browse/trunk/language/common/variables.js) | Alexandros | in progress |
|
||||
| procedures | 24 | [procedures.js](https://code.google.com/p/blockly/source/browse/trunk/language/common/procedures.js) | -- | -- |
|
||||
|
||||
# Steps
|
||||
|
||||
To volunteer:
|
||||
1. Visit and read through the file [messages.js](https://code.google.com/p/blockly/source/browse/branches/i18n/language/en/messages.js) to see how descriptions are written.
|
||||
1. Decide on a section you would like to volunteer for.
|
||||
1. Write descriptions for a few of the messages.
|
||||
1. Post a message to the [Blockly discussion group](https://groups.google.com/forum/?fromgroups#!forum/blockly) (or send it directly to me) with the above information and how long the work would take you.
|
||||
|
||||
Tips for translating messages:
|
||||
* If you're not sure how the message is used, play around with the [code application](https://blockly-demo.appspot.com/static/apps/code/index.html) and/or view the source code.
|
||||
* If a message consists of two (or more) strings joined by a plus sign, please combine them into a single string.
|
||||
* You can make additions to [the Blockly translation instructions](https://translatewiki.net/wiki/Translating:Blockly#The_Blockly_Language).
|
||||
* If you run into trouble, ask for help.
|
||||
|
||||
Also feel free to suggest improvements to the descriptions I wrote.
|
||||
31
CustomBlocks.md
Normal file
31
CustomBlocks.md
Normal file
@@ -0,0 +1,31 @@
|
||||
This document is aimed at developers who wish to create new blocks within Blockly. It is assumed that one has a local copy of Blockly which one can edit, one is generally familiar with Blockly's usage, and one has a basic understanding of JavaScript or some similar language.
|
||||
|
||||
# Introduction
|
||||
|
||||
Blockly comes with a large number of pre-defined blocks. Everything from mathematical functions to looping structures. However, in order to interface with an external application, one must create custom blocks to form an API. For example, when creating a drawing program, one might need to create a "_draw circle of radius R_" block.
|
||||
|
||||
In most cases the easiest approach is to just find a really similar block which already exists, copy it, and modify it as needed. The following documentation is for those who need more help. If all else fails, post in the [support newsgroup](https://groups.google.com/group/blockly).
|
||||
|
||||
## Define Block
|
||||
|
||||
The first step is to create a block; specifying its shape, labels, and connection points. This is done in the ` language/ ` directory.
|
||||
|
||||
→ More info on [Defining Blocks](wiki/DefiningBlocks)...
|
||||
|
||||
Advanced blocks may dynamically change their shape in response to the user or other factors.
|
||||
|
||||
→ More info on [Creating Mutators](wiki/CreatingMutators)...
|
||||
|
||||
## Code Generation
|
||||
|
||||
The second step is to create the generator code to export the new block to a programming language (such as JavaScript, Python, or Dart). This is done in the ` generators/ ` directory.
|
||||
|
||||
→ More info on [Generating Code](wiki/GeneratingCode)...
|
||||
|
||||
To generate code that is both clean and correct, one must be mindful of the order of operations list for the given language.
|
||||
|
||||
→ More info on [Operator Precedence](wiki/OperatorPrecedence)...
|
||||
|
||||
Creating more complicated blocks requires the use of temporary variables and/or utility functions. This is particularly true when an input is used twice and needs to be cached.
|
||||
|
||||
→ More info on [Caching Arguments](wiki/CachingArguments)...
|
||||
287
DefiningBlocks.md
Normal file
287
DefiningBlocks.md
Normal file
@@ -0,0 +1,287 @@
|
||||
**[Creating Custom Blocks](wiki/CustomBlocks): Defining Blocks**
|
||||
|
||||
Note that much of block creation can be done through the Blockly GUI using [Block Factory](https://blockly-demo.appspot.com/static/apps/blockfactory/index.html) instead of manually creating the code given below.
|
||||
|
||||
# Defining a Block
|
||||
|
||||
Go to the ` blocks/ ` directory. Assuming your block(s) don't fit in the existing categories, create a new JavaScript file. This new JavaScript file needs to be included in the list of ` <script ...> ` tags in the editor's HTML file.
|
||||
|
||||
A typical block definition looks like this:
|
||||
```
|
||||
Blockly.Blocks['text_length'] = {
|
||||
init: function() {
|
||||
this.setHelpUrl('http://www.w3schools.com/jsref/jsref_length_string.asp');
|
||||
this.setColour(160);
|
||||
this.appendValueInput('VALUE')
|
||||
.setCheck('String')
|
||||
.appendField('length');
|
||||
this.setOutput(true, 'Number');
|
||||
this.setTooltip('Returns number of letters in the provided text.');
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
* ` text_length ` is the name of the block. Since all blocks share the same namespace, it is good to use a name made up of your category (in this case ` text `) followed by your block's function (in this case ` length `).
|
||||
* ` init ` is a function which defines the look and feel of the block.
|
||||
|
||||
## Init Function
|
||||
|
||||
The ` init ` function creates the block's shape. In the context of this function the keyword ` this ` is the actual block being created. There are several functions commonly used in an ` init ` function:
|
||||
|
||||
* [setHelpUrl](wiki/#setHelpUrl)
|
||||
* [setColour](wiki/#setColour)
|
||||
* [setOutput](wiki/#setOutput)
|
||||
* [setPreviousStatement](wiki/#setPreviousStatement)
|
||||
* [setNextStatement](wiki/#setNextStatement)
|
||||
* [appendDummyInput, appendValueInput, appendStatementInput ](wiki/#appendDummyInput,_appendValueInput,_appendStatementInput)
|
||||
* [setCheck](wiki/#setCheck)
|
||||
* [setAlign](wiki/#setAlign)
|
||||
* [appendField](wiki/#appendField)
|
||||
* [setInputsInline](wiki/#setInputsInline)
|
||||
* [setTooltip](wiki/#setTooltip)
|
||||
* [setMutator](wiki/#setMutator)
|
||||
* [setDeletable](wiki/#setDeletable)
|
||||
* [setEditable](wiki/#setEditable)
|
||||
* [setMovable](wiki/#setMovable)
|
||||
|
||||
### setHelpUrl
|
||||
|
||||
```
|
||||
this.setHelpUrl('http://www.w3schools.com/jsref/jsref_length_string.asp');
|
||||
```
|
||||
|
||||
The URL of the page which should open when the user right-clicks on the block and chooses help. If this value is ` null ` then the menu will be greyed out. Advanced blocks may specify a function (instead of a static string) which returns a URL string, thus allowing for dynamic help.
|
||||
|
||||
### setColour
|
||||
|
||||
```
|
||||
this.setColour(160);
|
||||
```
|
||||
Blockly uses a [Hue-Saturation-Value](https://en.wikipedia.org/wiki/HSL_and_HSV) (HSV) colour model. Saturation and Value are hard-coded into Blockly, whereas the Hue is defined on each block. This ensures that developers have the freedom to choose from a wide range of colours, while still guaranteeing that all the blocks will fit together visually. It also allows the entire Blockly look and feel to be made brighter (for children) or more depressing (for businesses) by simply adjusting the two hard-coded Saturation and Value constants.
|
||||
|
||||

|
||||
|
||||
To find a good colour, visit this [HSV picker](http://www.rapidtables.com/web/color/color-picker.htm), enter Blockly's Saturation and Value constants (the defaults are 45% and 65% respectively), then slide the Hue as desired. Use this Hue value as the argument to the ` this.setColour ` function. Note the British spelling. Failure to set the colour results in a black block.
|
||||
|
||||
### setOutput
|
||||
|
||||
```
|
||||
this.setOutput(true, 'Number');
|
||||
```
|
||||
|
||||

|
||||
|
||||
Value blocks (as opposed to statements) need an output tab. Blocks with an output tab may not also have a previous statement notch.
|
||||
|
||||
This function also defines the expected value type that this block will output. A block that outputs a number will refuse to connect to a block that inputs a string (e.g. ` length(123) ` does not make sense). Use a short descriptive string, such as ` "Boolean" `, ` "Number" `, ` "String" `, or ` "Array" `.
|
||||
|
||||
In the event that the block could return more than one type of value, use an array of types (e.g. ` ["Number", "Date"] `). If the block could return any type of value (such as a variable's getter block), use ` null ` as the value.
|
||||
|
||||
### setPreviousStatement
|
||||
|
||||
```
|
||||
this.setPreviousStatement(true);
|
||||
```
|
||||
|
||||

|
||||
|
||||
Creates a notch at the top of the block, so that it may be plugged into a stack of statements. Normally combined with ` setNextStatement ` (see below). Blocks with a previous statement notch may not also have an output tab.
|
||||
|
||||
Optionally (and not typically), this function can take a second argument to limit the types of statements this block may be connected to.
|
||||
|
||||
### setNextStatement
|
||||
|
||||
```
|
||||
this.setNextStatement(true);
|
||||
```
|
||||
|
||||

|
||||
|
||||
Creates a notch at the bottom of the block, so that other statements may be stacked below it. Unless this block terminates flow (e.g. break, return, or end), this is normally combined with ` setPreviousStatement ` (see above).
|
||||
|
||||
Optionally (and not typically), this function can take a second argument to limit the types of statements this block may be connected to.
|
||||
|
||||
### appendDummyInput, appendValueInput, appendStatementInput
|
||||
|
||||
```
|
||||
this.appendDummyInput()
|
||||
.appendField('for each')
|
||||
.appendField('item')
|
||||
.appendField(new Blockly.FieldVariable());
|
||||
this.appendValueInput('LIST')
|
||||
.setCheck('Array')
|
||||
.setAlign(Blockly.ALIGN_RIGHT)
|
||||
.appendField('in list');
|
||||
this.appendStatementInput('DO')
|
||||
.appendField('do');
|
||||
```
|
||||
|
||||

|
||||
|
||||
Each block has a list of input rows. There are three types of inputs:
|
||||
|
||||
* ` appendDummyInput ` - Not an connector, just a row for fields.
|
||||
* ` appendValueInput ` - A socket in which to plug a value block.
|
||||
* ` appendStatementInput ` - A notch for a stack of statement blocks.
|
||||
|
||||
All three types are demonstrated in the "for each" block above.
|
||||
|
||||
The value and statement functions take a string that specifies the language-neutral name of the input. These names allow inputs to be reordered in different languages; for instance in one language a block might say "get (X) from (Y)" whereas in another language the same block might say "from (Y) get (X)". The block's code generator can use the names to find input "Y" regardless of where it is located in the block.
|
||||
|
||||
Dummy inputs generally do not require names and may be called without argument.
|
||||
|
||||
Once an input is created and appended to the block, it may be configured using 'method chaining'[[?](https://en.wikipedia.org/wiki/Method_chaining)]. There are three functions that are used for configuring inputs.
|
||||
|
||||
#### setCheck
|
||||
|
||||
```
|
||||
input.setCheck(Number);
|
||||
```
|
||||
|
||||
This optional function is used for type-checking of connected inputs. If given an argument of null, then this input may be connected to any block. See [setOutput](wiki/#setOutput) for details on the expected values.
|
||||
|
||||
#### setAlign
|
||||
|
||||
```
|
||||
input.setAlign(Blockly.ALIGN_RIGHT);
|
||||
```
|
||||
|
||||
This optional function is used to align the fields (see below). There are three self-descriptive values which may be passed as an argument to this function: ` Blockly.ALIGN_LEFT `, ` Blockly.ALIGN_RIGHT `, and ` Blockly.ALIGN_CENTRE `. Note the British spelling of 'centre'. Left alignment is the default.
|
||||
|
||||
When designing blocks for RTL (Arabic and Hebrew), left and right are reversed. Thus ` Blockly.ALIGN_RIGHT ` would align fields to the left.
|
||||
|
||||
#### appendField
|
||||
|
||||
Once an input has been created and appended to a block with ` appendInput `, one may optionally append any number of fields to the input. These fields are often used as labels to describe what each input is for. There are many different types of fields.
|
||||
|
||||
```
|
||||
input.appendField('hello');
|
||||
```
|
||||
|
||||

|
||||
|
||||
An input row can contain any number of field elements. The simplest field element is text. Blockly's convention is to use all lowercase text, with the exception of proper names (e.g. Google, SQL).
|
||||
|
||||
```
|
||||
var textInput = new Blockly.FieldTextInput('Neil');
|
||||
input.appendField(textInput, 'NAME');
|
||||
```
|
||||
|
||||

|
||||
|
||||
Another field element is a text input. First, create the field, then append it to the input row. Since the code generators will eventually need to access the data in this field element, be sure to give it a name (in this case ` 'NAME' `). This name is never seen by the user and should be consistent across all human language versions of the block.
|
||||
|
||||
Optionally, the ` FieldTextInput ` constructor can also take a second argument which becomes the validation function or change handler. See ` math_number ` for an example of where the user's input is rewritten.
|
||||
|
||||
```
|
||||
var dropdown = new Blockly.FieldDropdown([['world', 'WORLD'], ['computer', 'CPU']]);
|
||||
input.appendField(dropdown, 'MODE');
|
||||
```
|
||||
|
||||

|
||||
|
||||
Another field element is a drop-down menu. Just like the text input field, the drop-down menu is created separately, then appended to the input row. The ` FieldDropdown ` object is created with a list of menu options, or with a generator function.
|
||||
|
||||
→ More info on [Drop-down Menus](wiki/DropDown)...
|
||||
|
||||
```
|
||||
var variable = new Blockly.FieldVariable('item');
|
||||
input.appendField(variable, 'VAR');
|
||||
```
|
||||
|
||||

|
||||
|
||||
Another field element is a variable selection menu. The ` FieldVariable ` object is created with the default variable name to use (in this case ` 'item' `). If this name is omitted, the variable will be a new unique variable (e.g. ` 'i' `, ` 'j' `, ` 'k' `...).
|
||||
|
||||
```
|
||||
var checkbox = new Blockly.FieldCheckbox('TRUE');
|
||||
input.appendField(checkbox, 'TOGGLE');
|
||||
```
|
||||
|
||||

|
||||
|
||||
Another field element is a checkbox. The ` FieldCheckbox ` object is created with an initial state, either ` 'TRUE' ` or ` 'FALSE' `.
|
||||
|
||||
Optionally, the ` FieldCheckbox ` constructor can also take a second argument which becomes the validation function or change handler.
|
||||
|
||||
```
|
||||
var colour = new Blockly.FieldColour('#ff0000');
|
||||
input.appendField(colour, 'COLOUR');
|
||||
```
|
||||
|
||||

|
||||
|
||||
Another field element is a colour picker. The ` FieldColour ` object is created with an initial colour, in hexadecimal ` '#rrggbb' ` format. Note the British spelling.
|
||||
|
||||
Optionally, the ` FieldColour ` constructor can also take a second argument which becomes the validation function or change handler.
|
||||
|
||||
```
|
||||
var image = new Blockly.FieldImage('http://www.gstatic.com/codesite/ph/images/star_on.gif', 15, 15, '*');
|
||||
input.appendField(image);
|
||||
```
|
||||
|
||||

|
||||
|
||||
Another field element is a static image. The ` FieldImage ` object is created with the image URL and the desired height and width. The image will be scaled to within the specified dimensions, while preserving the aspect ratio. The block will expand as needed to accommodate the image. An optional fourth argument specifies the alternate text for use when the block is collapsed.
|
||||
|
||||
If the image is being served locally on a relative URL, use ` Blockly.pathToBlockly ` to specify Blockly's root directory.
|
||||
|
||||
### setInputsInline
|
||||
|
||||
```
|
||||
this.setInputsInline(true);
|
||||
```
|
||||
|
||||

|
||||
|
||||
Value and variable inputs are by default each on separate lines (as shown on the left). By setting inputs inline, one can create a more compact block (as shown on the right).
|
||||
|
||||
Use inline inputs when a block is likely going to have small inputs such as numbers. The user can toggle this option through the context menu.
|
||||
|
||||
### setTooltip
|
||||
|
||||
```
|
||||
this.setTooltip('Returns number of letters in the provided text.');
|
||||
```
|
||||
|
||||
Tooltips offer instant help when the user hovers their mouse over the block. Longer strings should include line breaks (` \n `) since the text does not wrap automatically.
|
||||
|
||||
Tooltips may also be defined as a function instead of a static string. This allows for dynamic help. See ` math_arithmetic ` for an example of a tooltip that changes depending on which dropdown option has been chosen.
|
||||
|
||||
### setMutator
|
||||
|
||||
```
|
||||
this.setMutator(new Blockly.Mutator(['controls_if_elseif', 'controls_if_else']));
|
||||
```
|
||||
|
||||

|
||||
|
||||
Mutators allow advanced blocks to change shape, most notably as a result of users opening a dialog to add, remove or rearrange components. Creating a mutator is not trivial and is the subject of a separate page: [Creating Mutators](wiki/CreatingMutators).
|
||||
|
||||
### setDeletable
|
||||
|
||||
```
|
||||
this.setDeletable(false);
|
||||
```
|
||||
|
||||
When set to false, the user will not be able to delete this block from the workspace. If this attribute is not set, the default is true.
|
||||
|
||||
### setEditable
|
||||
|
||||
```
|
||||
this.setEditable(false);
|
||||
```
|
||||
|
||||
When set to false, the user will not be able to change the block's inputs. If this attribute is not set, the default is true.
|
||||
|
||||
### setMovable
|
||||
|
||||
```
|
||||
this.setMovable(false);
|
||||
```
|
||||
|
||||
When set to false, the user will not be able to move the block within the workspace. This position can be set at initialization. If this attribute is not set, the default is true.
|
||||
|
||||
**Please send any questions you have to the [support group](https://groups.google.com/forum/#!forum/blockly), not as a comment to this page.**
|
||||
32
DropDown.md
Normal file
32
DropDown.md
Normal file
@@ -0,0 +1,32 @@
|
||||
**[Creating Custom Blocks](wiki/CustomBlocks): [Defining Blocks](wiki/DefiningBlocks): Drop-down Menus**
|
||||
|
||||
Drop-down menus can be somewhat complicated field elements used in creating blocks.
|
||||
|
||||
## Language Neutrality
|
||||
|
||||
```
|
||||
input.appendField('hello');
|
||||
var dropdown = new Blockly.FieldDropdown([['world', 'WORLD'], ['computer', 'CPU']]);
|
||||
input.appendField(dropdown, 'MODE');
|
||||
```
|
||||
|
||||

|
||||
|
||||
The ` FieldDropdown ` object is created with a list of menu options. Each option is made up of two strings. The first is the human-readable text to display. The second is a string constant which is used when saving the option to XML. This separation allows a dropdown menu's setting to be preserved between languages. For instance an English (` en/ `) version of a block may define ` [['left', 'LEFT'], ['right', 'RIGHT']] ` while a German (` de/ `) version of the same block would define ` [['links', 'LEFT'], ['rechts', 'RIGHT']] `.
|
||||
|
||||
## Prefix/Suffix Matching
|
||||
|
||||
If all the menu options of a ` FieldDropdown ` object share common prefix and/or suffix words, these words are automatically factored out and inserted as static text. For example, the same "hello world" code above could be rewritten like this:
|
||||
|
||||
```
|
||||
var dropdown = new Blockly.FieldDropdown([['hello world', 'WORLD'], ['hello computer', 'CPU']]);
|
||||
input.appendField(dropdown, 'MODE');
|
||||
```
|
||||
|
||||
One advantage of this approach is that the block is easier for to translate into other languages. The earlier code has the strings ` 'hello' `, ` 'world' `, and ` 'computer' `, whereas the revised code has the strings ` 'hello world' ` and ` 'hello computer' `. Translators have a much easier time translating phrases than words in isolation.
|
||||
|
||||
Another advantage of this approach is that word order often changes between languages. Imagine a language that used ` 'world hello' ` and ` 'computer hello' `. The suffix matching algorithm will detect the common ` 'hello' ` and display it after the drop-down.
|
||||
|
||||
However, sometimes the prefix/suffix matching fails. There are some cases where two words should always go together and the prefix should not be factored out. For example ` 'drive red car' ` and ` 'drive red truck' ` should arguably only have ` 'drive' ` factored out, not ` 'drive red' `. The Unicode non-breaking space ` '\u00A0' ` may be used in place of a regular space to suppress the prefix/suffix matcher. Thus the above example can be fixed with ` 'drive red\u00A0car' ` and ` 'drive red\u00A0truck' `.
|
||||
|
||||
Another place where prefix/suffix matching fails is in languages that do not separate individual words with spaces. Chinese is a good example. The string
|
||||
24
FAQs.md
Normal file
24
FAQs.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# FAQs for Blockly Users
|
||||
|
||||
**What is Blockly?**
|
||||
|
||||
A new programming language made up of "blocks" that look like jigsaw puzzle pieces.
|
||||
|
||||
|
||||
**What do I use Blockly for?**
|
||||
|
||||
First, a programmer needs to integrate Blockly with a web application, like Gmail or Google Docs, that you already use. Then you can use Blockly to write simple programs like macros and scripts that work with the web application.
|
||||
|
||||
For example, in Gmail, you can use Blockly to create email filters that do things like, "If Bob emails me three times in less than an hour, and each email contains the word 'deadline', delete all his emails except the first one."
|
||||
|
||||
|
||||
**How do I write a program with Blockly?**
|
||||
|
||||
You click a block to place it in your workspace, then right-click the block to select the options you want, and then drag and drop blocks together to make a program.
|
||||
|
||||
|
||||
**The program I wrote doesn't make any sense!**
|
||||
|
||||
Blockly lets you put together blocks almost any way you want - even if your program won't work. Blockly keeps you from making some kinds of mistakes, like programming syntax errors, but it can't prevent you from making mistakes like telling a program to, "Divide 'hello' by seven."
|
||||
|
||||
If you know the basics of software programming, you can use Blockly to write useful programs that do cool things. And if you don't know how to program, playing around with Blockly can help you learn.
|
||||
44
Future.md
Normal file
44
Future.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Introduction
|
||||
|
||||
Blockly is in active development with changes landing every day. We are aware of many deficiencies and are working hard to address them. Many of Blockly's features come from volunteer developers, so please feel free to dig into the code and send us contributions.
|
||||
|
||||
# Running Everywhere
|
||||
|
||||
It is important that everyone be able to use Blockly. That means running in as many environments as possible:
|
||||
|
||||
* [Translating Blockly](wiki/Translation) (or just some demo apps) into your language is extremely helpful. Less that 5% of the world [speaks English](https://en.wikipedia.org/wiki/List_of_languages_by_number_of_native_speakers) natively. Help us reach the billions of people who are missing out.
|
||||
* Touch screen support (for Android and iOS tablets in particular) is critical. Currently Blockly kinda-sorta works, but we need to do much better.
|
||||
* Good support for IE 10 and IE 9 (IE 8 is assumed to be a lost cause). The Google developers do not have easy access to Windows computers, so any help to improve IE is appreciated.
|
||||
|
||||
# New Blocks
|
||||
|
||||
Different applications need different blocks. There are a few types of blocks that are repeatedly requested:
|
||||
|
||||
* Text split, List join. Split text into a list based on a delimiter, join a list into a text based on a separator.
|
||||
* List sort. Choice of alphabetic, numeric, case-insensitive, and length modes. Ascending or descending order.
|
||||
* 2D grids. Arrays of arrays are clumsy and hard to visualize. A new category of blocks that deals with grid data (spreadsheets) is needed. Most of the existing list blocks would have grid equivalents.
|
||||
* Multi-line strings. A block with a text area one can type paragraphs into. Also useful would be a character picker widget that allows one to select Unicode characters.
|
||||
* Date/Time selection. A calendar picker (similar to the existing colour picker) would allow users to choose dates and times easily.
|
||||
|
||||
# Improved UI
|
||||
|
||||
Blockly is designed to be clean and simple. We don't want to add clutter. But there are many ways that the UI may be improved:
|
||||
|
||||
* Multi-block selection. Hold shift to click many blocks, for group moves, collapsing, disabling or deleting.
|
||||
* Cursor control for accessibility. Many users don't have good mouse-skills due to disabilities. Adding keyboard shortcuts to manipulate Blockly would enable these users to participate. The same shortcuts would also benefit power programmers.
|
||||
* Trash can contents. Clicking on the trash can should bring up a bubble that contains everything that has been deleted. These blocks may be dragged out of the trash and back into the workspace.
|
||||
* Improved variable rename dialog. Shows a preview of how many variables are going to be renamed, warns of collisions, etc.
|
||||
|
||||
# Scalability
|
||||
|
||||
Writing large programs in most visual programming environments is cumbersome. There are many interesting problems in allowing one to write large programs (many are challenging enough to produce publishable academic papers or dissertations if you feel so inclined). The Blockly team is _currently_ focused on small educational applications, which means nobody is currently pursuing these:
|
||||
|
||||
* Zooming in and out like Google Maps. This is more than just scaling the workspace, details need to appear and disappear appropriately.
|
||||
* Multiple workspaces. Break a large program into pieces, with parts in different tabs?
|
||||
* Variable scope. Currently all variables are global, except for function arguments. Large programs need some sort of scope.
|
||||
* Debugging hooks. Being able to run a program, step forwards and backwards, inspect variables, set break points.
|
||||
* Search. Find functions, callers, variables, and other code searching activities. Likewise, a search and replace feature would allow for easier maintenance of code.
|
||||
* Libraries. How does one bundle code into a reusable, publishable module that other programs may include and depend on?
|
||||
* Collaboration. Blockly was designed from the beginning to integrate well with the [Google Drive SDK](https://developers.google.com/drive/realtime/). This would allow real-time multi-user collaborative editing.
|
||||
|
||||
But most important of all, grab a copy of Blockly, integrate it with your apps, and see how your users like it. We love to see Blockly out in the real world -- from teaching programming to students, to controlling heavy machinery in a factory.
|
||||
43
GeneratingCode.md
Normal file
43
GeneratingCode.md
Normal file
@@ -0,0 +1,43 @@
|
||||
**[Creating Custom Blocks](wiki/CustomBlocks): Generating Code**
|
||||
|
||||
# Generating Code
|
||||
|
||||
First, go to the ` generators/ ` directory and choose the subdirectory that corresponds to the language you want to generate (JavaScript, Python, Dart, etc).
|
||||
|
||||
Assuming your block(s) don't fit in the existing categories, create a new JavaScript file. This new JavaScript file needs to be included in the list of ` <script ...> ` tags in the editor's HTML file.
|
||||
|
||||
A typical block's code generator looks like this:
|
||||
```
|
||||
Blockly.JavaScript['text_indexOf'] = function(block) {
|
||||
// Search the text for a substring.
|
||||
var operator = block.getFieldValue('END') == 'FIRST' ? 'indexOf' : 'lastIndexOf';
|
||||
var argument0 = Blockly.JavaScript.valueToCode(block, 'FIND',
|
||||
Blockly.JavaScript.ORDER_NONE) || '\'\'';
|
||||
var argument1 = Blockly.JavaScript.valueToCode(block, 'VALUE',
|
||||
Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
|
||||
var code = argument1 + '.' + operator + '(' + argument0 + ') + 1';
|
||||
return [code, Blockly.JavaScript.ORDER_MEMBER];
|
||||
};
|
||||
```
|
||||
|
||||
## Collecting the Arguments
|
||||
|
||||
The first task for any block's code generator is to collect all the arguments and field data. There are several functions commonly used for this task:
|
||||
|
||||
* [getFieldValue](wiki/#getFieldValue)
|
||||
* [valueToCode](wiki/#valueToCode)
|
||||
* [statementToCode](wiki/#statementToCode)
|
||||
|
||||
### getFieldValue
|
||||
|
||||
```
|
||||
block.getFieldValue('END')
|
||||
```
|
||||
|
||||
This function returns the value from a field of the specified name.
|
||||
|
||||
* In the case of a text field, this function returns the typed text. E.g. "Hello World".
|
||||
|
||||
* In the case of a dropdown, this function returns the language-neutral text associated with the selected option. An English block might have a dropdown with the word "first" selected, whereas the same dropdown in German would display "erste". Code generators should not have to know all possible human languages, thus the ` getFieldValue ` function will return the language-neutral text that was specified when the dropdown was created.
|
||||
|
||||
* In the case of a variable dropdown, this function returns the user-facing name of a variable dropdown. It is important to note that this name is not necessarily the same as the variable name used in the generated code. For example, a variable name of "` for `" is legal in Blockly, but would collide with a reserved word in most languages and thus would be renamed to "` for2 `". Likewise, an Arabic variable name of "
|
||||
65
IfElse.md
Normal file
65
IfElse.md
Normal file
@@ -0,0 +1,65 @@
|
||||
(TODO: Add table of contents.)
|
||||
|
||||
# Introduction
|
||||
|
||||
Conditional statements are central to computer programming. They make it possible to express statements like:
|
||||
* If there is a path to the left, turn left.
|
||||
* If score = 100, print "Well done!".
|
||||
|
||||
See [additional information about conditional statements](https://en.wikipedia.org/wiki/Conditional_(programming)).
|
||||
|
||||
# Blocks
|
||||
|
||||
## If blocks
|
||||
|
||||
The simplest conditional statement is an **if** block, as shown:
|
||||
|
||||

|
||||
|
||||
When run, this will compare the value of the variable **x** to 100. If it is larger, "What a big number!" will be printed. Otherwise, nothing happens.
|
||||
|
||||
## If-Else blocks
|
||||
|
||||
It is also possible to specify that something should happen if the condition is _not_ true, as shown in this example:
|
||||
|
||||

|
||||
|
||||
As with the previous block, "What a big number!" will be printed if **x** > 100; otherwise, "That's not very big." will be printed.
|
||||
|
||||
An **if** block may have zero or one **else** sections but not more than one.
|
||||
|
||||
## If-Else-If blocks
|
||||
|
||||
It is also possible to test multiple conditions with a single **if** block by adding **else if** clauses:
|
||||
|
||||

|
||||
|
||||
The block first checks if **x** > 100, printing "What a big number!" if it is. If it is not, it goes on to check if **x** = 42. If so, it prints "That's my lucky number." Otherwise, nothing happens.
|
||||
|
||||
An **if** block may have any number of **else if** sections. Conditions are evaluated top to bottom until one is satisfied, or until no more conditions are left.
|
||||
|
||||
## If-Else-If-Else blocks
|
||||
|
||||
As shown here, **if** blocks may have both **else if** and **else** sections:
|
||||
|
||||

|
||||
|
||||
The **else** section guarantees that some action is performed, even if none of the prior conditions are true.
|
||||
|
||||
An **else** section may occur after any number of **else if** sections, including zero.
|
||||
|
||||
# Block Modification
|
||||
|
||||
Only the plain **if** block appears on the toolbar:
|
||||
|
||||

|
||||
|
||||
To add **else if** and **else** clauses, the user needs to click on the plus sign, which opens a new window:
|
||||
|
||||

|
||||
|
||||
The user can then drag **else if** and **else** clauses into the **if** block, as well as reordering and removing them. When finished, the user should click on the minus sign, which closes the window, as shown here:
|
||||
|
||||

|
||||
|
||||
Note that the shapes of the blocks allows any number of **else if** subblocks to be added but only up to one **else** block.
|
||||
56
InjectingFixedSize.md
Normal file
56
InjectingFixedSize.md
Normal file
@@ -0,0 +1,56 @@
|
||||
**[Installation](wiki/Installation): Injecting Fixed-sized Blockly**
|
||||
|
||||
# Introduction
|
||||
|
||||
The simplest way to put Blockly into a webpage is to inject it into an empty 'div' tag. There are two major limitations of this approach:
|
||||
|
||||
* One can't have more than one instance of Blockly on the same page.
|
||||
* Blockly cannot easily reflow as the window resizes.
|
||||
|
||||
Both of these issues may be solved by [injecting Blockly into an iframe](wiki/InjectingResizable).
|
||||
|
||||
## Injection
|
||||
|
||||
If neither of the above limitations are a concern, include the core Blockly script and the core blocks set. Note that the path may vary, depending on where your page is in relation to Blockly:
|
||||
|
||||
```
|
||||
<script type="text/javascript" src="blockly_compressed.js"></script>
|
||||
<script type="text/javascript" src="blocks_compressed.js"></script>
|
||||
```
|
||||
|
||||
Then include the messages for the user's language (in this case English):
|
||||
|
||||
```
|
||||
<script type="text/javascript" src="msg/js/en.js"></script>
|
||||
```
|
||||
|
||||
Add an empty div to the page and set its size:
|
||||
|
||||
```
|
||||
<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>
|
||||
```
|
||||
|
||||
Add the structure of the toolbox (see [Defining the Toolbox](wiki/Toolbox) for more information):
|
||||
|
||||
```
|
||||
<xml id="toolbox" style="display: none">
|
||||
<block type="controls_if"></block>
|
||||
<block type="controls_repeat_ext"></block>
|
||||
<block type="logic_compare"></block>
|
||||
<block type="math_number"></block>
|
||||
<block type="math_arithmetic"></block>
|
||||
<block type="text"></block>
|
||||
<block type="text_print"></block>
|
||||
</xml>
|
||||
```
|
||||
|
||||
Finally, call the following to inject Blockly into an empty div. Set 'path' to be the relative path from your web page to Blockly's root directory. This is used by Blockly so that media such as the trash can and the sounds may be loaded.
|
||||
|
||||
```
|
||||
<script type="text/javascript">
|
||||
Blockly.inject(document.getElementById('blocklyDiv'),
|
||||
{path: './', toolbox: document.getElementById('toolbox')});
|
||||
</script>
|
||||
```
|
||||
|
||||
Test the page in a browser. You should see Blockly's editor filling the div, with four block categories in the toolbox. Here is [a live demo](https://blockly-demo.appspot.com/static/demos/fixed/index.html).
|
||||
75
Installation.md
Normal file
75
Installation.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Introduction
|
||||
|
||||
Blockly is designed to easily install into your web application. Users drag blocks around, Blockly generates code, your application does something with that code. From your application's point of view Blockly is just a textarea in which the user types syntactically perfect JavaScript, Python, Dart, or other language.
|
||||
|
||||
Blockly is 100% client-side, requiring no support from the server (unless one wants to use the cloud-storage or realtime collaboration features). There are no 3rd party dependencies (unless one wants to recompile the core). Everything is open source.
|
||||
|
||||
If you do not need to modify the code, you can use our public server at https://blockly-demo.appspot.com. Installation is only recommended for developers who wish to modify or add source code.
|
||||
|
||||
## Get the Code
|
||||
|
||||
First, download the source code. Use [Subversion](http://subversion.apache.org/) to pull a copy of Blockly off of Google Code:
|
||||
|
||||
```
|
||||
svn checkout http://blockly.googlecode.com/svn/trunk/ blockly
|
||||
```
|
||||
|
||||
Once you have the code, point your browser at ` apps/maze/index.html ` and test out the maze app. Verify that clicking "Run Program" will make the man move forward.
|
||||
|
||||
## Injecting Blockly
|
||||
|
||||
With your installation of Blockly verified as working, inject Blockly into a web page using either a fixed-size ` div ` or a resizable ` iframe `.
|
||||
|
||||
→ More info on [injecting fixed-sized Blockly](wiki/InjectingFixedSize)...
|
||||
|
||||
→ More info on [injecting resizable Blockly](wiki/InjectingResizable)...
|
||||
|
||||
## Configuration
|
||||
|
||||
The ` Blockly.inject ` line contains as its second argument a dictionary of name-value pairs. These are used for configuration. The following options are supported:
|
||||
| ` collapse: ` | boolean | Allows blocks to be collapsed or expanded. Defaults to ` true ` if the toolbox has categories, ` false ` otherwise. |
|
||||
|:--------------|:--------|:---------------------------------------------------------------------------------------------------------------------|
|
||||
| ` comments: ` | boolean | Allows blocks to have comments. Defaults to ` true ` if the toolbox has categories, ` false ` otherwise. |
|
||||
| ` disable: ` | boolean | Allows blocks to be disabled. Defaults to ` true ` if the toolbox has categories, ` false ` otherwise. |
|
||||
| ` maxBlocks: ` | number | Maximum number of blocks that may be created. Useful for student exercises. Defaults to ` Infinity `. |
|
||||
| ` path: ` | string | Path from page (or frame) to the Blockly root directory. Defaults to ` "./" `. |
|
||||
| ` readOnly: ` | boolean | If ` true `, prevent the user from editing. Supresses the toolbox and trashcan. Defaults to ` false `. |
|
||||
| ` rtl: ` | boolean | If ` true `, mirror the editor for Arabic or Hebrew locales. See [RTL demo](https://blockly-demo.appspot.com/static/demos/rtl/index.html). Defaults to ` false `. |
|
||||
| ` scrollbars: ` | boolean | If ` false `, supress scrollbars that appear if the toolbox has categories. Defaults to ` true `. |
|
||||
| ` sound: ` | boolean | If ` false `, don't play sounds (e.g. click and delete). Defaults to ` true `. |
|
||||
| ` toolbox: ` | XML nodes or string | Tree structure of categories and blocks available to the user. See [Defining the Toolbox](wiki/Toolbox) for more information. |
|
||||
| ` trashcan: ` | boolean | Displays or hides the trashcan. Defaults to ` true ` if the toolbox has categories, ` false ` otherwise. |
|
||||
|
||||
Blockly's library of blocks is highly configurable. The blocks shown to the user can be customized so that users only see blocks that are relevant to the task. Browse the ` blocks/ ` directory for block categories that you want to include. The categories and blocks shown in the toolbox (the side menu) is specified using an [XML tree](wiki/Toolbox).
|
||||
|
||||
Additionally, custom blocks need to be built to call your web application's API. An example is the [Maze application](https://blockly-demo.appspot.com/static/apps/maze/index.html) which has custom blocks for movement. More info on [Creating custom blocks](wiki/CustomBlocks)...
|
||||
|
||||
## Language Generators
|
||||
|
||||
Blockly is not a programming language, one cannot 'run' a Blockly program. Instead, Blockly can translate the user's program into JavaScript, Python, Dart, or some other language.
|
||||
|
||||
→ More info on [Language Generators](wiki/LanguageGenerators)...
|
||||
|
||||
## Importing and Exporting Blocks
|
||||
|
||||
If your application needs to save and store the user's blocks and restore them at a later visit, use this call for export to XML:
|
||||
|
||||
```
|
||||
var xml = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace);
|
||||
var xml_text = Blockly.Xml.domToText(xml);
|
||||
```
|
||||
|
||||
This will produce a minimal (but ugly) string containing the XML for the user's blocks. If one wishes to obtain a more readable (but larger) string, use ` Blockly.Xml.domToPrettyText ` instead.
|
||||
|
||||
Restoring from an XML string to blocks is just as simple:
|
||||
|
||||
```
|
||||
var xml = Blockly.Xml.textToDom(xml_text);
|
||||
Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml);
|
||||
```
|
||||
|
||||
## Cloud Storage
|
||||
|
||||
Blockly comes with an optional cloud-storage feature. It enables users to save, load, share, and publish their programs. If your project is hosted on App Engine you can take advantage of this service.
|
||||
|
||||
→ More info on [Cloud Storage](wiki/CloudStorageWithAppEngine)...
|
||||
104
JSInterpreter.md
Normal file
104
JSInterpreter.md
Normal file
@@ -0,0 +1,104 @@
|
||||
**[Installation](wiki/Installation): [Language Generators](wiki/LanguageGenerators): JavaScript Interpreter**
|
||||
|
||||
## Eval is Evil
|
||||
|
||||
The quickest way to run your user's blocks is to generate JavaScript, then push the resulting code through the browser's ` eval() ` function. This works very well for many simple applications. The [Language Generators](wiki/LanguageGenerators) page describes how to do this, along with a couple of hacks such as how to deal with infinite loops and how not to collide with existing variables.
|
||||
|
||||
However, if you are serious about running the user's blocks properly, then the [JS Interpreter](https://github.com/NeilFraser/JS-Interpreter) is the way to go. This project is separate from Blockly, but was specifically written for Blockly.
|
||||
|
||||
* Execute code at any speed.
|
||||
* Pause/resume/step-through execution.
|
||||
* Highlight blocks as they execute.
|
||||
* Completely isolated from browser's JS.
|
||||
|
||||
## Run the Interpreter
|
||||
|
||||
First, download the JS Interpreter from GitHub and add it to your page:
|
||||
|
||||
```
|
||||
<script type="text/javascript" src="acorn_interpreter.js"></script>
|
||||
```
|
||||
|
||||
The simplest method of calling it is to generate the JavaScript, create the interpreter, and run the code:
|
||||
|
||||
```
|
||||
var code = Blockly.JavaScript.workspaceToCode();
|
||||
var myInterpreter = new Interpreter(code);
|
||||
myInterpreter.run();
|
||||
```
|
||||
|
||||
## Step the Interpreter
|
||||
|
||||
In order to execute the code slower, or in a more controlled manner, replace the call to ` run ` with a loop that steps (in this case one step every 10ms):
|
||||
|
||||
```
|
||||
function nextStep() {
|
||||
if (myInterpreter.step()) {
|
||||
window.setTimeout(nextStep, 10);
|
||||
}
|
||||
}
|
||||
nextStep();
|
||||
```
|
||||
|
||||
Note that each step is not a line or a block, it is a semantic unit in JavaScript, which may be extremely fine-grained.
|
||||
|
||||
## Add an API
|
||||
|
||||
The JS Interpreter is a sandbox that is completely isolated from the browser. Any blocks that perform actions with the outside world require an API added to the interpreter. For a full description, see the documentation for the JS Interpreter. But to start with, here is the API needed to support the alert and prompt blocks:
|
||||
|
||||
```
|
||||
function initApi(interpreter, scope) {
|
||||
// Add an API function for the alert() block.
|
||||
var wrapper = function(text) {
|
||||
text = text ? text.toString() : '';
|
||||
return interpreter.createPrimitive(alert(text));
|
||||
};
|
||||
interpreter.setProperty(scope, 'alert',
|
||||
interpreter.createNativeFunction(wrapper));
|
||||
|
||||
// Add an API function for the prompt() block.
|
||||
wrapper = function(text) {
|
||||
text = text ? text.toString() : '';
|
||||
return interpreter.createPrimitive(prompt(text));
|
||||
};
|
||||
interpreter.setProperty(scope, 'prompt',
|
||||
interpreter.createNativeFunction(wrapper));
|
||||
}
|
||||
```
|
||||
|
||||
Then modify your interpreter initialization to pass in the initApi function:
|
||||
|
||||
```
|
||||
var myInterpreter = new Interpreter(code, initApi);
|
||||
```
|
||||
|
||||
The alert and prompt blocks are the only two blocks in the default set of blocks that require a custom API for the interpreter.
|
||||
|
||||
## Highlight Blocks
|
||||
|
||||
Some applications that use Blockly will want to highlight the currently executing block as the code runs. This may be done on a statement-by-statement level by setting ` STATEMENT_PREFIX ` prior to generating the JavaScript code:
|
||||
|
||||
```
|
||||
Blockly.JavaScript.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
|
||||
Blockly.JavaScript.addReservedWords('highlightBlock');
|
||||
```
|
||||
|
||||
This results in the statement ` highlight('123'); ` being added to before every statement, where ` 123 ` is the serial number of the block to be highlighted. Then create the API for the highlighting function:
|
||||
|
||||
```
|
||||
function initApi(interpreter, scope) {
|
||||
// Add an API function for highlighting blocks.
|
||||
var wrapper = function(id) {
|
||||
id = id ? id.toString() : '';
|
||||
return interpreter.createPrimitive(Blockly.mainWorkspace.highlightBlock(id));
|
||||
};
|
||||
interpreter.setProperty(scope, 'highlightBlock',
|
||||
interpreter.createNativeFunction(wrapper));
|
||||
}
|
||||
```
|
||||
|
||||
More sophisticated applications might wish to repeatedly execute steps without pause until a highlight command is reached, then pause. This strategy simulates line-by-line execution. The example below uses this approach.
|
||||
|
||||
## Example
|
||||
|
||||
Here is [a live demo](https://blockly-demo.appspot.com/static/demos/interpreter/index.html) of interpreting JavaScript step by step.
|
||||
57
Klingon.md
Normal file
57
Klingon.md
Normal file
@@ -0,0 +1,57 @@
|
||||
On 1 April 2014 we released a
|
||||
[Klingon translation of Blockly](https://blockly-demo.appspot.com/static/apps/code/index.html?lang=tlh#ortpyd).
|
||||
Klingon is an unusual choice for a translation, and on this page we wanted to
|
||||
give some context on the hows and whys, as well as how you can help.
|
||||
|
||||
## Why?
|
||||
|
||||
Blockly has been translated into over 40 languages, including RTL languages such
|
||||
as Arabic and Hebrew. We feel that it is important that novice programmers are
|
||||
able to learn the fundamentals of programming in their own language, before
|
||||
making the transition to conventional English-based programming languages.
|
||||
|
||||
Klingon is a real language in every sense of the word. It is not just a
|
||||
collection of made-up words thrown together for a movie. Instead, it has been
|
||||
crafted by linguists over the course of decades. The Klingon language has a
|
||||
complicated grammar that is completely unique.
|
||||
|
||||
Consider word order. English follows the Subject-Verb-Object order ("The cat
|
||||
eats the food."). Hungarian follows the Object-Subject-Verb order ("The food
|
||||
the cat eats."). Hebrew follows the Verb-Subject-Object order ("Eats the cat
|
||||
the food."). Klingon is the most bizarre, with Object-Verb-Subject order ("The
|
||||
food eats the cat."). Supporting Klingon is the ultimate test of Blockly's
|
||||
flexibility. Block inputs need to be reordered, suffix groups need to be added,
|
||||
rules for plurals need to be rethought. Infrastructure improvements made during
|
||||
the course of translating to Klingon help us support all languages.
|
||||
|
||||
## Who?
|
||||
|
||||
The number of Google employees who are fluent in Klingon is larger than one
|
||||
might expect (and we are hiring). Google's Klingon language group maintains
|
||||
a style guide for terminology so that different applications use a consistent
|
||||
vocabulary.
|
||||
|
||||
We are always pleased when volunteers come forward to contribute new
|
||||
translations or corrections -- whether for Klingon, or other languages.
|
||||
|
||||
## How?
|
||||
|
||||
Most of [Blockly's translations](wiki/Translation) are done by volunteers using
|
||||
Translatewiki. Unfortunately, Klingon is not in their language matrix.
|
||||
As a result, Klingon contributors need to edit two files manually:
|
||||
|
||||
https://code.google.com/p/blockly/source/browse/trunk/msg/json/tlh.json
|
||||
|
||||
and
|
||||
|
||||
https://code.google.com/p/blockly/source/browse/trunk/apps/json/tlh.json
|
||||
|
||||
See the ` en.json ` files in each directory for the English phrases (including
|
||||
those not yet translated to Klingon), and the ` qqq.json ` files for descriptions.
|
||||
We actively do not want tooltip messages or help URLs translated since they
|
||||
offer useful context for those new to Klingon.
|
||||
|
||||
All phrases _must_ be manually translated. Bing Translate produces such
|
||||
translations as ` "Library" -> "be'nI''a'wI', Datu'" ` which actually means
|
||||
` "discover my big sister" `.
|
||||
Clearly this would be an inadvisable phrase to use in a Klingon environment.
|
||||
202
Lists.md
Normal file
202
Lists.md
Normal file
@@ -0,0 +1,202 @@
|
||||
(TODO: Add table of contents.)
|
||||
|
||||
# Introduction
|
||||
|
||||
As in everyday speech, a Blockly list is an ordered collection of items, such as a "to do" list or a shopping list. Items in a list may be of any type, and the same value may appear more than once in a list.
|
||||
|
||||
# List Creation
|
||||
|
||||
## create empty list
|
||||
|
||||
The simplest list is the empty list, which is created with the **create empty list** block:
|
||||
|
||||

|
||||
|
||||
## create list with
|
||||
|
||||
### basic usage
|
||||
The **create list with** block allows the user to specify the initial values in a new list. In this example, a list of words is being created and placed in a variable named **letters**:
|
||||
|
||||

|
||||
|
||||
For this document, we'll denote this list as ["alpha", "beta", "gamma"], and we will refer below to the variables defined in this section.
|
||||
|
||||
This shows the creation of a list of numbers:
|
||||
|
||||

|
||||
|
||||
This creates a list of colours:
|
||||
|
||||

|
||||
|
||||
It is less common, but possible, to create a list with values of different types:
|
||||
|
||||

|
||||
|
||||
### changing number of inputs
|
||||
|
||||
To change the number of inputs, click on the plus ("+") icon. This opens a new window:
|
||||
|
||||

|
||||
|
||||
You can then drag **item** sublocks from the left side of the window into the **if** block on the right side to add a new input, as shown:
|
||||
|
||||

|
||||
|
||||
While the new item was added at the bottom in this example, it can be added anywhere. Similarly, unwanted **item** subblocks can be dragged off the **if** block to the left.
|
||||
|
||||
|
||||
## create list with item
|
||||
|
||||
The **create list with item** block lets you create a list that has the specified number of copies of an item. For example, the following blocks set the variable **words** to the list containing ["very", "very", "very"].
|
||||
|
||||

|
||||
|
||||
# Checking a List's Length
|
||||
|
||||
## is empty
|
||||
|
||||
The value of an **is empty** block is **true** if its input is the empty list and **false** if it is anything else (including a non-list). IS THIS TRUE? The value of the following blocks would be **false** because the variable **colours** is not empty: it has three items.
|
||||
|
||||

|
||||
|
||||
Note the similarity to the ["is empty" block for text](https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text).
|
||||
|
||||
## length of
|
||||
|
||||
The value of the **length of** block is the number of elements in the list used as an input. For example, the value of the following blocks would be 3 because colour has three items.
|
||||
|
||||

|
||||
|
||||
Note that the **length of** block tells you how many items are in the list, not how many _different_ items are in it. For example, the following has the value 3, even though **words** consists of three copies of the same text (["very", "very", "very"]).
|
||||
|
||||

|
||||
|
||||
Note the similarity to the ["length of" block for text](https://code.google.com/p/blockly/wiki/Text#Text_length).
|
||||
|
||||
# Finding Items in a List
|
||||
|
||||
These blocks find the position of an item in a list. For example, the following has a value of 1 because the first appearance of "very" is as the beginning of the **words** list (["very", "very", "very"]).
|
||||
|
||||

|
||||
|
||||
The result of the following is 3 because the last appearance of "very" in **words** is in position 3.
|
||||
|
||||

|
||||
|
||||
If the item is nowhere in the list, the result is in the value 0, as in this example:
|
||||
|
||||

|
||||
|
||||
These blocks are analogous to [the ones for finding letters in text](https://code.google.com/p/blockly/wiki/Text#Finding_text).
|
||||
|
||||
# Getting Items from a List
|
||||
|
||||
## Getting a single item
|
||||
|
||||
Recall the definition of the list **colours**:
|
||||
|
||||

|
||||
|
||||
The following block gets the color <font color='blue'>blue</font> because it is the second element in the list (counting from the beginning on the left):
|
||||
|
||||

|
||||
|
||||
This gets <font color='green'>green</font> because it is the second element counting from the right end:
|
||||

|
||||
|
||||
This gets the first element, <font color='red'>red</font>:
|
||||
|
||||

|
||||
|
||||
This gets the last element, <font color='orange'>yellow</font>:
|
||||
|
||||

|
||||
|
||||
This randomly selects an item from the list, returning any of <font color='red'>red</font>, <font color='blue'>blue</font>, <font color='green'>green</font>, or <font color='orange'>yellow</font> with equal likelihood.
|
||||
|
||||

|
||||
|
||||
### Getting and removing an item
|
||||
|
||||
A dropdown menu on the **in list ... get** block changes it to **in list ... get and remove**, which provides the same otuput but also modifies the original list:
|
||||
|
||||

|
||||
|
||||
This example sets the variable **first letter** to "alpha" and leaves **letters** as: ["beta", "gamma"].
|
||||
|
||||

|
||||
|
||||
### Removing an item
|
||||
|
||||
Selecting "remove" on the dropdown causes the plug on the left of the block to disappear:
|
||||
|
||||

|
||||
|
||||
This removes the first item from **letters**.
|
||||
|
||||
## Getting a sublist
|
||||
|
||||
The **in list ... get sublist** block is similar to the **in list ... get** block except that it extracts a sublist, rather than an individual item. There are several options for how the start and end of the sublist can be specified:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
A few languages (notably Hungarian) require text following the right socket (hole). This is referred to as a "tail" message.
|
||||
|
||||
In this example, a new list **first letters** is created. This new list has two elements: ["alpha", "beta"].
|
||||
|
||||

|
||||
|
||||
Note that this block does not modify the original list.
|
||||
|
||||
# Adding Items to a List
|
||||
|
||||
## in list ... set
|
||||
|
||||
The **in list ... set** block replaces the item at a specified location in a list with a different item.
|
||||
|
||||

|
||||
|
||||
For the meaning of each of the dropdown options, see the [previous section](wiki/Lists#Getting_Items_from_a_List).
|
||||
|
||||
The following example does two things:
|
||||
1. The list **words** is created with 3 items: ["very", "very", "very"].
|
||||
1. The third item in the list is replaced by "good". The new value of **words** is ["very", "very", "good"].
|
||||
|
||||

|
||||
|
||||
## in list ... insert at
|
||||
|
||||
The **in list ... insert at** block is obtained by using the dropdown menu on the **in list ... set** block:
|
||||
|
||||

|
||||
|
||||
It inserts a new item into the list at the specified location, before the item previously at that location. The following example (built on an earlier one) does three things:
|
||||
|
||||
1. The list **words** is created with 3 items: ["very", "very", "very"].
|
||||
1. The third item in the list is replaced by "good". The new value of **words** is ["very", "very", "good"].
|
||||
1. The word "you're" is inserted at the beginning of the list. The final value of **words** is ["You're", "very", "very", "good"].
|
||||
|
||||

|
||||
|
||||
# Related Blocks
|
||||
|
||||
## Printing a list
|
||||
|
||||
The [print block](wiki/Text#Printing_text) in the Text category can print lists. The result of the following program is the shown alert box:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Doing something for each item in a list
|
||||
|
||||
The [for-each block](wiki/Loops#for_each) in the Control category performs an operation on every item in a list. For example, these blocks individually print each item in the list:
|
||||
|
||||

|
||||
|
||||
This does not remove the items from the original list.
|
||||
|
||||
See also the examples of the [loop termination blocks](wiki/Loops#Loop_Termination_Blocks).
|
||||
48
Logic.md
Normal file
48
Logic.md
Normal file
@@ -0,0 +1,48 @@
|
||||
(TODO: Add table of contents.)
|
||||
|
||||
# Introduction
|
||||
|
||||
[Boolean algebra](https://en.wikipedia.org/wiki/Boolean_algebra) is a mathematical system that has two values:
|
||||
* **true**
|
||||
* **false**
|
||||
|
||||
Boolean values (also called _conditions_) are used in these control block, which contain examples::
|
||||
* [conditional blocks](wiki/IfElse)
|
||||
* [repeat blocks](wiki/Loops#repeat)
|
||||
|
||||
One of the many examples from those pages is:
|
||||
|
||||

|
||||
|
||||
If the value of the variable **x** is greater than 100, the condition is **true**, and the text "What a big number!" is printed. If the value of **x** is not greater than 100, the condition is **false**, and "That's not very big." is printed.
|
||||
|
||||
Boolean values can also be stored in variables and passed to procedures, the same as number, text, and list values.
|
||||
|
||||
# Blocks
|
||||
|
||||
If a block expects a Boolean value as an input, it interprets an absent input as **false**. An example is provided below. Non-Boolean values cannot be directly plugged in where Boolean values are expected, although it is possible (but inadvisable) to store a non-Boolean value in a variable, then plug that into the input. Neither of these practices are recommended, and their behavior could change in future versions of Blockly.
|
||||
|
||||
## Values
|
||||
|
||||
A single block, with a dropdown specifying either **true** or **false**, can be used to get a boolean value:
|
||||
|
||||

|
||||
|
||||
## not
|
||||
|
||||
The **not** block converts its Boolean input into its opposite. For example, the result of:
|
||||
|
||||

|
||||
|
||||
is false.
|
||||
|
||||
As mentioned above, if no input is provided, a value of **true** is assumed, so the following block produces the value **false**:
|
||||
|
||||

|
||||
|
||||
Leaving an input empty is not recommended, however.
|
||||
|
||||
## comparisons
|
||||
|
||||
|
||||
## logical operations
|
||||
70
Loops.md
Normal file
70
Loops.md
Normal file
@@ -0,0 +1,70 @@
|
||||
(TODO: Add table of contents.)
|
||||
|
||||
# Introduction and Terminology
|
||||
|
||||
The **Control** category holds blocks that control whether other blocks placed in their **body** are run. (For example, in the below "repeat" block, the body contains the "print" block and its input.) There are two types of control blocks: [IfElse](wiki/IfElse) (described on their own page) and these, which control how many times the body is run and, in some cases, the value of a variable used within the body. These structures are called **loops** since the body is repeated (possibly) multiple times, reminiscent of a rope containing loops. Each pass through the loop is called an **iteration**. (How about our using the term "pass"?) For more information, see https://en.wikipedia.org/wiki/Control_flow#Loops.
|
||||
|
||||
# Blocks for Loop Creation
|
||||
|
||||
## repeat
|
||||
|
||||
The simplest "repeat" block runs the code in its body the specified number of times. For example, the following block will print "Hello!" ten times.
|
||||
|
||||

|
||||
|
||||
### repeat while
|
||||
|
||||
Imagine a game in which a player rolls a die and adds up all of the values rolled as long as the total is less than 30. The following blocks implement that game:
|
||||
|
||||
1. A variable named **total** gets an initial value of 0.
|
||||
1. The loop begins with a check that **total** is less than 30. If so, the blocks in the body are run.
|
||||
1. A random number in the range 1 to 6 is generated (simulating a die roll) and stored in a variable named **roll**.
|
||||
1. The number rolled is printed.
|
||||
1. The variable **total** gets increased by **roll**.
|
||||
1. The end of the loop having been reached, control goes back to step 2.
|
||||
|
||||

|
||||
|
||||
When the loop completes, any subsequent blocks (not shown) would be run. In our example, the loop would end after some number of random numbers in the range 1 to 6 had been printed, and the variable **total** would hold the sum of these numbers, which would be guaranteed to be at least 30.
|
||||
|
||||
For more information, see https://en.wikipedia.org/wiki/While_loop.
|
||||
|
||||
### repeat until
|
||||
|
||||
"Repeat while" loops repeat their bodies _while_ some condition is true. Repeat-until loops are similar except that they repeat their bodies _until_ some condition is true. The following blocks are equivalent to the previous example because the loop contains until **total** is greater than or equal to 30.
|
||||
|
||||

|
||||
|
||||
## count with
|
||||
|
||||
The **count with** block (called a [for loop](https://en.wikipedia.org/wiki/For_loop) in most programming languages) advances a variable from the first value to the second value by the increment amount (third value), running the body once for each value. For example, the following program prints the numbers 1, 3, and 5.
|
||||
|
||||

|
||||
|
||||
As shown by the two following loops, each of which prints the numbers 5, 3, and 1, the first input may be larger than the second. The behavior is the same whether the increment amount (third value) is positive or negative.
|
||||
|
||||

|
||||
|
||||
## for each
|
||||
|
||||
The **for each** block (see https://en.wikipedia.org/wiki/Foreach) is similar, except instead of giving the loop variable values in a numeric sequence, it uses the values from a list in turn. The following program prints each element of the list: "alpha", "beta", "gamma".
|
||||
|
||||

|
||||
|
||||
# Loop Termination Blocks
|
||||
|
||||
Most loops run until the terminating condition (in the case of **repeat** blocks) is met or until all values have been taken by the loop variable (in the case of **count with** and **for each** loops). Two rarely needed but occasionally useful blocks provide additional means for controlling loop behavior. Although the below examples are for **for each** loops, they can be used with any type of loop.
|
||||
|
||||
## continue with next iteration
|
||||
|
||||
The **continue with next iteration** (called [continue](https://en.wikipedia.org/wiki/Control_flow#Continuation_with_next_iteration) in most programming languages) causes the remaining code in the body to be skipped and for the next iteration (pass) of the loop to begin.
|
||||
|
||||
The following program prints "alpha" on the first iteration of the loop. On the second iteration, the **continue with next iteration** block is run, skipping the printing of "beta". On the final iteration, "gamma" is printed.
|
||||
|
||||

|
||||
|
||||
## break out of loop
|
||||
|
||||
The **break out of loop** block provides [an early exit from a loop](https://en.wikipedia.org/wiki/Control_flow#Early_exit_from_loops). The following program prints "alpha" on the first iteration and "breaks out" of the loop on the second iteration when the loop variable is equal to "beta". The third item in the list is never reached.
|
||||
|
||||

|
||||
84
OperatorPrecedence.md
Normal file
84
OperatorPrecedence.md
Normal file
@@ -0,0 +1,84 @@
|
||||
**[Creating Custom Blocks](wiki/CustomBlocks): [Generating Code](wiki/GeneratingCode): Operator Precedence**
|
||||
|
||||
Code generators are used to convert Blockly's programs into JavaScript, Python, Dart, etc. The most challenging issue when writing a code generator for a new block is handling the order of operations so that the resulting code executes as intended.
|
||||
|
||||
# Bad Parentheses
|
||||
|
||||
Consider the following assembly of blocks.
|
||||
|
||||

|
||||
|
||||
If the generators were not aware of operator precedence, the resulting JavaScript code would be:
|
||||
```
|
||||
alert(2 * 3 + 4);
|
||||
```
|
||||
This is obviously incorrect, since the multiplication operator rips apart the addition, grabbing the '3' for itself. One solution is to wrap the result of every value block in parentheses:
|
||||
```
|
||||
alert(((2) * ((3) + (4)));
|
||||
```
|
||||
This solution works perfectly, but it results in extremely messy code with large numbers of redundant parentheses. For some use cases this is not an issue. If human eyes are never going to see the generated code, then this is acceptable. However, Blockly is often used as an educational tool to introduce programming, a use case which relies on generating human-readable code.
|
||||
|
||||
# Good Parentheses
|
||||
|
||||
To generate correct code without an unreasonable number of parentheses, each language generator is provided with an ordered list of precedences. Here is the list for JavaScript:
|
||||
|
||||
```
|
||||
Blockly.JavaScript.ORDER_ATOMIC = 0; // 0 "" ...
|
||||
Blockly.JavaScript.ORDER_MEMBER = 1; // . []
|
||||
Blockly.JavaScript.ORDER_NEW = 1; // new
|
||||
Blockly.JavaScript.ORDER_FUNCTION_CALL = 2; // ()
|
||||
Blockly.JavaScript.ORDER_INCREMENT = 3; // ++
|
||||
Blockly.JavaScript.ORDER_DECREMENT = 3; // --
|
||||
Blockly.JavaScript.ORDER_LOGICAL_NOT = 4; // !
|
||||
Blockly.JavaScript.ORDER_BITWISE_NOT = 4; // ~
|
||||
Blockly.JavaScript.ORDER_UNARY_PLUS = 4; // +
|
||||
Blockly.JavaScript.ORDER_UNARY_NEGATION = 4; // -
|
||||
Blockly.JavaScript.ORDER_TYPEOF = 4; // typeof
|
||||
Blockly.JavaScript.ORDER_VOID = 4; // void
|
||||
Blockly.JavaScript.ORDER_DELETE = 4; // delete
|
||||
Blockly.JavaScript.ORDER_MULTIPLICATION = 5; // *
|
||||
Blockly.JavaScript.ORDER_DIVISION = 5; // /
|
||||
Blockly.JavaScript.ORDER_MODULUS = 5; // %
|
||||
Blockly.JavaScript.ORDER_ADDITION = 6; // +
|
||||
Blockly.JavaScript.ORDER_SUBTRACTION = 6; // -
|
||||
Blockly.JavaScript.ORDER_BITWISE_SHIFT = 7; // << >> >>>
|
||||
Blockly.JavaScript.ORDER_RELATIONAL = 8; // < <= > >=
|
||||
Blockly.JavaScript.ORDER_IN = 8; // in
|
||||
Blockly.JavaScript.ORDER_INSTANCEOF = 8; // instanceof
|
||||
Blockly.JavaScript.ORDER_EQUALITY = 9; // == != === !==
|
||||
Blockly.JavaScript.ORDER_BITWISE_AND = 10; // &
|
||||
Blockly.JavaScript.ORDER_BITWISE_XOR = 11; // ^
|
||||
Blockly.JavaScript.ORDER_BITWISE_OR = 12; // |
|
||||
Blockly.JavaScript.ORDER_LOGICAL_AND = 13; // &&
|
||||
Blockly.JavaScript.ORDER_LOGICAL_OR = 14; // ||
|
||||
Blockly.JavaScript.ORDER_CONDITIONAL = 15; // ?:
|
||||
Blockly.JavaScript.ORDER_ASSIGNMENT = 16; // = += -= *= /= %= <<= >>= ...
|
||||
Blockly.JavaScript.ORDER_COMMA = 17; // ,
|
||||
Blockly.JavaScript.ORDER_NONE = 99; // (...)
|
||||
```
|
||||
|
||||
The bulk of this list is taken directly from JavaScript's [language spec](https://developer.mozilla.org/en/JavaScript/Reference/Operators/Operator_Precedence), with ` ORDER_ATOMIC ` added to the start and ` ORDER_NONE ` added to the end.
|
||||
|
||||
Applying these orders occurs in two places within each block's generator. The first place is when fetching generated code from a connected value block. In this case we pass the constant which represents the maximum binding strength of any operators adjacent to the sub-block's generated code. For example:
|
||||
```
|
||||
var arg0 = Blockly.JavaScript.valueToCode(this, 'NUM1', Blockly.JavaScript.ORDER_DIVISION);
|
||||
```
|
||||
The second place is when returning generated code from a value block. In this case we pass the constant which represents the minimum binding strength of any operators in the block's generated code. For example:
|
||||
```
|
||||
return [arg0 + ' / ' + arg1, Blockly.JavaScript.ORDER_DIVISION];
|
||||
```
|
||||
|
||||
If the order value returned by the sub-block is weaker than or equal to the order value for the order argument of the parent block, then the ` valueToCode ` function will automatically wrap the contents of the sub-block's code in parentheses to prevent it from being ripped apart by the parent block's code.
|
||||
|
||||
Below are some more examples. In each case the block has one connected sub-block which is represented as 'X' (the contents of 'X' is unknown and doesn't matter). The second column lists the strongest operator which might split 'X'. The third column lists the weakest operator in the final code for the block.
|
||||
|
||||
| **Generated Code** | **Max strength against X** | **Min strength of block** |
|
||||
|:-------------------|:---------------------------|:--------------------------|
|
||||
| ` X + 1 ` | ` ORDER_ADDITION ` | ` ORDER_ADDITION ` |
|
||||
| ` Math.sqrt(X) ` | ` ORDER_NONE ` | ` ORDER_MEMBER ` |
|
||||
| ` !X && false ` | ` ORDER_LOGICAL_NOT ` | ` ORDER_LOGICAL_AND ` |
|
||||
| ` foo[X % 60] ` | ` ORDER_MODULUS ` | ` ORDER_MEMBER ` |
|
||||
|
||||
# Math is hard
|
||||
|
||||
Still don't understand? No problem. Just use ` ORDER_ATOMIC ` as the order on every call to ` valueToCode `, and use ` ORDER_NONE ` as the order for the final return statement on every value block. The resulting code will be infested with needless parentheses, but is guaranteed to be correct.
|
||||
44
RealtimeCollaboration.md
Normal file
44
RealtimeCollaboration.md
Normal file
@@ -0,0 +1,44 @@
|
||||
### Introduction
|
||||
The Blockly library supports realtime collaboration of Blockly programs similar to realtime collaboration of documents in Google Drive, i.e. multiple users can edit the same program at the same time, with all the users seeing each others changes in real time.
|
||||
|
||||
Using Blockly's realtime collaboration feature will provide your users with a sharable link which they can send to a friend or colleague. That link contain the ID of a 'document' which is saved in Google Drive and stores the Blockly program that is being edited. Note that this implies that using Blockly's realtime collaboration feature also provides for persistent storage of a Blockly program (as an alternative to the mechanism described in [CloudStorageWithAppEngine](wiki/CloudStorageWithAppEngine)) and therefore is useful even if you don't necessarily care about realtime collaboration. Also note that another benefit of using the realtime collaboration feature will be the ability to 'undo' and 'redo' editing operations. 'Undo' and 'redo' are not currently supported due to a bug (in Blockly code) but hopefully that will soon be fixed.
|
||||
|
||||
Blockly's realtime collaboration is built using [Google Drive's Realtime API](https://developers.google.com/drive/realtime/): a service provided by Google that enables 3rd party developers to incorporate realtime collaboration into their own web applications.
|
||||
|
||||
> _Note that Google Drive's Realtime API currently requires users to have (or create) Google Accounts, so please consider that when deciding to enable realtime collaboration into your app._
|
||||
|
||||
By default realtime collaboration is currently disabled in Blockly. This wiki page tells you how to enable it. Note that these instructions are for the developer using Blockly for their web application, not for the end user.
|
||||
|
||||
There are two major steps to take in order to enable realtime collaboration in Blockly. One is to [put the appropriate code in your application](wiki/#Code_to_enable_realtime_collaboration). The other is to use the [Google Developer Console](https://cloud.google.com/console/project) to [register your application](wiki/Registering_with_the_Google_Developer_Console) to use Google Drive's Realtime API.
|
||||
|
||||
### Code to enable realtime collaboration
|
||||
To enable realtime collaboration in your application's code add a 'realtime: true' option to your Blockly.inject() method call. There are also a set of 'realtimeOptions: ...' that you can add, as well. Here, for example, is the code in for this in [playground.html](https://code.google.com/p/blockly/source/browse/trunk/tests/playground.html) in the Blockly Playground application (which is part of the standard Blockly test codebase):
|
||||
|
||||
```
|
||||
function start() {
|
||||
var toolbox = document.getElementById('toolbox');
|
||||
Blockly.inject(document.getElementById('blocklyDiv'),
|
||||
{rtl: rtl, path: '../', toolbox: toolbox, realtime: true,
|
||||
realtimeOptions:
|
||||
{clientId: 'YOUR CLIENT ID GOES HERE',
|
||||
chatbox: {elementId: 'chatbox'},
|
||||
collabElementId: 'collaborators'}});
|
||||
if (Blockly.Realtime.isEnabled()) {
|
||||
enableRealtimeSpecificUi();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The clientId string (i.e 'YOUR CLIENT ID GOES HERE') needs to be replaced by the Client ID that you will obtain when registering your application in the Google Developers Console. That ID should look something like ` '12345678901.apps.googlecontent.com' `
|
||||
|
||||
The 'chatbox' option is used if you want to have a collaborative chat in you app. Within that option you must specify an 'elementId' suboption which tells the realtime code the id of a textarea that is defined in your app and which will be used for the chat. You can also specify the initial text to be placed in your chatbox by adding an 'initText' suboption. If you don't specify an 'initText' it will default to the value of Blockly.Msg.CHAT, which has the value _'Chat with your collaborator by typing in this box!'_ for english users but can be localized.
|
||||
|
||||
The 'collabElementId' option is used if you want to view thumbnail images (with alt/hover text containing the users' name) of all the users (with available profiles that are accessible to the user) currently collaborating on a particular Blockly-based program. The value of the 'collabElementId' option should be the id of a div in your application where the thumbnails will be placed. See the [playground.html](https://code.google.com/p/blockly/source/browse/trunk/tests/playground.html) for an example of this.
|
||||
|
||||
### Registering with the Google Developer Console
|
||||
To register your application with the Google Developers Console, please use the instructions that can be found in the [activation section of the Google Drive Realtime API Quickstart documentation](https://developers.google.com/drive/realtime/realtime-quickstart#step_1_activate_the_drive_api).
|
||||
|
||||
### Example
|
||||
Here's [a simple live demo](https://blockly-realtime-collab.appspot.com/static/demos/realtime/index.html) of Blockly realtime collaboration in action. For something more extensive, here's [a live demo of the Blockly Playground](https://blockly-realtime-collab.appspot.com/static/tests/playground.html) enabled for realtime collaboration.
|
||||
|
||||
The first time you view them you may need to click the 'You must authorize' button.
|
||||
149
Text.md
Normal file
149
Text.md
Normal file
@@ -0,0 +1,149 @@
|
||||
(TODO: Add table of contents.)
|
||||
|
||||
# Introduction
|
||||
|
||||
Examples of pieces of text are:
|
||||
* "thing #1"
|
||||
* "March 12, 2010"
|
||||
* "" (the empty text)
|
||||
Text can contain letters (which may be lower-case or upper-case), numbers, punctuation marks, other symbols, and blank spaces between words. (The non-Blockly term for all of these different types of text is [character](https://en.wikipedia.org/wiki/Character_(computing)).)
|
||||
|
||||
# Blocks
|
||||
|
||||
## Text creation
|
||||
The following block creates the piece of text "hello" and stores it in the variable named ` greeting `.
|
||||
|
||||

|
||||
|
||||
The **create text with** block combines (concatenates) the value of the ` greeting ` variable and the new text "world" to create the text "helloworld". Note that there is no space between them, since none was in either original text.
|
||||
|
||||

|
||||
|
||||
To increase the number of text inputs, click on the plus sign, which changes the view to:
|
||||
|
||||

|
||||
|
||||
Additional inputs are added by dragging an "item" block from the gray toolbox on the left into the "join" block.
|
||||
|
||||
## Text modification
|
||||
|
||||
The **to...append text** block adds the given text to the specified variable. In this case, it changes the value of the variable ` greeting ` from "hello" to "hello, there!"
|
||||
|
||||

|
||||
|
||||
|
||||
## Text length
|
||||
|
||||
The **length of** blocks count the number of letters, numbers, etc., in each text. The length of "We're #1!" is 9, and the length of the empty text is 0.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Checking for empty text
|
||||
The **is empty** block checks whether the given text is empty (has length 0). The result is **true** in the first case and **false** in the second.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Finding text
|
||||
|
||||
These blocks can be used to check whether a piece of text is in another piece of text and, if so, where it appears. For example, this asks for the first occurrence of "e" in "hello". The result is 2.
|
||||
|
||||

|
||||
|
||||
This asks for the _last_ occurrence of "e" in "hello", which, is also 2.
|
||||
|
||||

|
||||
|
||||
Whether **first** or **last** is selected, this block will give the result 0, since "hello" does not contain "z".
|
||||
|
||||

|
||||
|
||||
## Extracting text
|
||||
|
||||
### Extracting a single character
|
||||
|
||||
This gets "b", the second letter in "abcde":
|
||||
|
||||

|
||||
|
||||
This gets "d", the second _to last_ letter in "abcde":
|
||||
|
||||

|
||||
|
||||
This gets "a", the first letter in "abcde":
|
||||
|
||||

|
||||
|
||||
This gets "e", the last letter in "abcde":
|
||||
|
||||

|
||||
|
||||
This gets any of the 5 letters in "abcde" with equal probability:
|
||||
|
||||

|
||||
|
||||
None of these modify the text on which the extraction is performed.
|
||||
|
||||
### Extracting a region of text
|
||||
|
||||
The **in text...get substring** block allows a region of text to be extracted, starting with either:
|
||||
* letter #
|
||||
* letter # from end
|
||||
* the first letter
|
||||
and ending with:
|
||||
* letter #
|
||||
* letter # from end
|
||||
* the last letter
|
||||
|
||||
In the following example, "abc" is extracted.
|
||||
|
||||

|
||||
|
||||
## Adjusting text case
|
||||
|
||||
This block creates a version of the input text that is either:
|
||||
* UPPER CASE (all letters upper-case)
|
||||
* Title Case (first letters upper-case, other letters lower-case)
|
||||
* lower case
|
||||
|
||||
The result of the following block is "HELLO".
|
||||
|
||||

|
||||
|
||||
Non-alphabetic characters are not affected. Note that this block on text in languages without case, such as Chinese.
|
||||
|
||||
## Trimming (removing) spaces
|
||||
|
||||
The following block removes space characters from:
|
||||
* the beginning of the text
|
||||
* the end of the text
|
||||
* both sides of the text
|
||||
|
||||
The result of the following block is "hi there". (Spaces in the middle of the text are not affected.)
|
||||
|
||||

|
||||
|
||||
## Printing text
|
||||
|
||||
The **print** block causes the input value to be displayed in a pop-up window, as shown:
|
||||
|
||||

|
||||
|
||||
If the code is exported as JavaScript, Python, or Dart, it will be printed to the console (screen). In no case is it sent to the printer, as the name might suggest.
|
||||
|
||||
## Getting input from the user
|
||||
|
||||
The following block creates a pop-up window that prompts the user to enter a name. The result is stored in the variable **name**:
|
||||
|
||||

|
||||
|
||||
This is what the current version of the pop-up window looks like:
|
||||
|
||||

|
||||
|
||||
There is also a version of the block for getting a number from the user:
|
||||
|
||||

|
||||
158
Toolbox.md
Normal file
158
Toolbox.md
Normal file
@@ -0,0 +1,158 @@
|
||||
**[Installation](wiki/Installation): Defining the Toolbox**
|
||||
|
||||
# Introduction
|
||||
|
||||
The toolbox is the side menu from whence the user may create new blocks.
|
||||
The structure of the toolbox is specified with XML, which may be either a tree
|
||||
of nodes, or a string representation. This XML is passed to Blockly when it is
|
||||
injected into the page.
|
||||
|
||||
Here is a minimal example, using a tree of nodes:
|
||||
|
||||
```
|
||||
<xml id="toolbox" style="display: none">
|
||||
<block type="controls_if"></block>
|
||||
<block type="controls_whileUntil"></block>
|
||||
</xml>
|
||||
<script type="text/javascript">
|
||||
Blockly.inject(document.getElementById('blocklyDiv'),
|
||||
{path: './', toolbox: document.getElementById('toolbox')});
|
||||
</script>
|
||||
```
|
||||
|
||||
Here is the same example, using a string representation:
|
||||
|
||||
```
|
||||
<script type="text/javascript">
|
||||
var toolbox = '<xml>';
|
||||
toolbox += ' <block type="controls_if"></block>';
|
||||
toolbox += ' <block type="controls_whileUntil"></block>';
|
||||
toolbox += '</xml>';
|
||||
Blockly.inject(document.getElementById('blocklyDiv'),
|
||||
{path: './', toolbox: toolbox});
|
||||
</script>
|
||||
```
|
||||
|
||||
## No Categories
|
||||
|
||||
If there are a small number of blocks, then they may be displayed without any
|
||||
categories. In this mode all the available blocks are shown in the toolbox,
|
||||
there are no scrollbars on the main workspace, and the trashcan is not needed.
|
||||
|
||||
|
||||
## Categories
|
||||
|
||||
The blocks in the toolbox may be organized in categories. Here are two
|
||||
categories ('Control' and 'Logic'), each of which contain three blocks:
|
||||
|
||||
```
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Control">
|
||||
<block type="controls_if"></block>
|
||||
<block type="controls_whileUntil"></block>
|
||||
</category>
|
||||
<category name="Logic">
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_boolean"></block>
|
||||
</category>
|
||||
</xml>
|
||||
```
|
||||
|
||||
There are two categories that have special behaviours. Variable and procedure
|
||||
categories are defined with no contents, but with a ` 'custom' ` property of
|
||||
` 'VARIABLE' ` or ` 'PROCEDURE' ` respectively. These categories will be populated
|
||||
automatically with the appropriate blocks.
|
||||
|
||||
```
|
||||
<category name="Variables" custom="VARIABLE"></category>
|
||||
<category name="Functions" custom="PROCEDURE"></category>
|
||||
```
|
||||
|
||||
## Tree of Categories
|
||||
|
||||
Categories may be nested within other categories. Here are two top-level
|
||||
categories ('Core' and 'Custom'), each of which contain two sub-categories,
|
||||
each of which contain blocks:
|
||||
|
||||
```
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Core">
|
||||
<category name="Control">
|
||||
<block type="controls_if"></block>
|
||||
<block type="controls_whileUntil"></block>
|
||||
</category>
|
||||
<category name="Logic">
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_boolean"></block>
|
||||
</category>
|
||||
</category>
|
||||
<category name="Custom">
|
||||
<block type="start"></block>
|
||||
<category name="Move">
|
||||
<block type="move_forward"></block>
|
||||
<block type="move_backward"></block>
|
||||
</category>
|
||||
<category name="Turn">
|
||||
<block type="turn_left"></block>
|
||||
<block type="turn_right"></block>
|
||||
</category>
|
||||
</category>
|
||||
</xml>
|
||||
```
|
||||
|
||||
Note that it is possible for a category to contain both sub-categories and blocks.
|
||||
In the above example, 'Custom' has two sub-categories ('Move' and 'Turn'), as well
|
||||
as a block of its own ('start').
|
||||
|
||||
## Block Groups
|
||||
|
||||
The XML may contain groups of blocks, or customized blocks. Here are three blocks:
|
||||
1. A simple ` logic_boolean ` block.
|
||||
1. A ` math_number ` block that has been modified to display the number 42 instead of the default of 0.
|
||||
1. A ` controls_for ` block that has two ` math_number ` blocks that appear connected to it.
|
||||
|
||||
```
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Blocks">
|
||||
<block type="logic_boolean"></block>
|
||||
<block type="math_number">
|
||||
<field name="NUM">42</field>
|
||||
</block>
|
||||
<block type="controls_for">
|
||||
<value name="FROM">
|
||||
<block type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="TO">
|
||||
<block type="math_number">
|
||||
<field name="NUM">10</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
</category>
|
||||
</xml>
|
||||
```
|
||||
|
||||
The XML for these groups or customized blocks is the same as Blockly's XML save format.
|
||||
Thus, the easiest way to construct the XML for such blocks is to use the
|
||||
[Code application](https://blockly-demo.appspot.com/static/apps/code/en.html) to
|
||||
build the blocks, then switch to the XML tab and copy the result.
|
||||
|
||||
## Changing the Toolbox
|
||||
|
||||
The application may change the blocks available in the toolbox at any time with a single function call:
|
||||
```
|
||||
Blockly.updateToolbox(newTree);
|
||||
```
|
||||
|
||||
As was the case during initial configuration, ` newTree ` may either be a tree of nodes, or a string representation. The only restriction is that the mode cannot be changed; that is if there were categories in the initially-defined toolbox then the new toolbox must also have categories (though the categories may change). Likewise, if the initially-defined toolbox did not have any categories, then the new toolbox may not have any categories.
|
||||
|
||||
Be aware that at this time updating the toolbar causes some minor UI resets:
|
||||
* In a toolbox with categories, the flyout will close if it was open.
|
||||
* In a toolbox without categories, any fields changed by the user (such as a dropdown) will revert to the default.
|
||||
* Any toolbox so long that it extends beyond the page will have its scrollbar jump to the top.
|
||||
|
||||
Here is [a live demo](https://blockly-demo.appspot.com/static/demos/toolbox/index.html) of a tree with categories and block groups.
|
||||
33
Translation.md
Normal file
33
Translation.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Introduction
|
||||
|
||||
Our goal is for Blockly to be available in as many languages as possible, so students don't have to struggle with English at the same time as they're learning computer science concepts.
|
||||
|
||||
|
||||
# Using Blockly
|
||||
|
||||
If you're not already a Blockly user, try it out. Some good starting places are:
|
||||
* [Puzzle](https://blockly-demo.appspot.com/blockly/apps/puzzle/index.html) (to learn the Blockly user interface)
|
||||
* [Maze](https://blockly-demo.appspot.com/blockly/apps/maze/index.html)
|
||||
* [Code](https://blockly-demo.appspot.com/blockly/apps/code/index.html) (meant for experienced programmers)
|
||||
|
||||
# Translatewiki
|
||||
|
||||
All of Blockly's translations are handled by [translatewiki.net](http://translatewiki.net).
|
||||
|
||||
## Creating an account at Translatewiki
|
||||
|
||||
Use the [Getting started wizard](http://translatewiki.net/w/i.php?title=Special:UserLogin&returnto=Special%3AFirstSteps&type=signup). Steps are:
|
||||
1. Creating an account.
|
||||
1. Configuring your preferences. You may specify any languages at this step.
|
||||
1. Creating your user page. You must specify (at least) "I have a moderate command of" "English" to do translations for Blockly. You should also specify at least one other language that you are able to do translations into.
|
||||
1. Request translator permissions. Write a brief introduction, ideally information to give the reviewer reason to believe you're a genuine translator and not a vandal. For example, if you have already contributed translations to Blockly, link to the translated file and point out that it contains your name (assuming it does). Here are the [maze translations](https://code.google.com/p/blockly/source/browse/#svn%2Ftrunk%2Fapps%2Fmaze). Press "Send request". You then need to wait to be manually approved, which can take anywhere from a few minutes to a couple of hours (longest during nighttime in Central Europe). **You probably will not be notified that you were approved; just give it a try a little later.**
|
||||
|
||||
Optionally, personalize your user page. You can do this by clicking on your user name, which is shown on the top of the page once you have logged in. Once on your user page, the easiest way to modify it is by clicking on the "Edit with form" tab near the top of the page.
|
||||
|
||||
## Reading about Blockly translation
|
||||
|
||||
Visit [Translating:Blockly](http://translatewiki.net/wiki/Translating:Blockly), which has detailed information for translators. Please contact us with any questions. You can leave a comment on this page or use the translatewiki interface to give feedback.
|
||||
|
||||
## Start translating
|
||||
|
||||
Start translating by clicking on the "Translate this project" link at the top of [Translating:Blockly](http://translatewiki.net/wiki/Translating:Blockly) or going directly to http://translatewiki.net/w/i.php?title=Special:Translate&group=out-blockly-0-all. You may have to click on "English" in the phrase "Translate to English" toward the upper right to change to your language.
|
||||
310
TranslationForDevelopers.md
Normal file
310
TranslationForDevelopers.md
Normal file
@@ -0,0 +1,310 @@
|
||||
This document provides what developers should know about Blockly translations. Translators should read [this document](https://code.google.com/p/blockly/wiki/Translation) instead.
|
||||
|
||||
(TODO: Add table of contents.)
|
||||
|
||||
# Introduction
|
||||
|
||||
Internationalization (i18n) is one of Blockly's top priorities. See, for example, [CS in VN](https://neil.fraser.name/news/2013/03/16/). Blockly supports right-to-left and left-to-right scripts, and the [Puzzle application](https://blockly-demo.appspot.com/static/apps/puzzle/index.html) has been translated into over 50 languages. We look forward to getting all of Blockly translated into that many languages.
|
||||
|
||||
# TranslateWiki
|
||||
We use [TranslateWiki](http://www.translatewiki.net) as our translation console and translator community. We provide them with the following files:
|
||||
* **qqq.json**, mapping message names to _message documentation_ (information for translators).
|
||||
* **en.json**, mapping message names to the English-language text. Note that we use Canadian English.
|
||||
* **_LANG_.json**, mapping message names to the appropriate language text. Messages that have not been translated to the given language will not be present in this file.
|
||||
_LANG_ is (loosely) an [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag), such as "de" for German or "pt-br" for Brazilian Portuguese. See this [incomplete list of languages supported by translatewiki](https://translatewiki.net/wiki/Special:SupportedLanguages).
|
||||
|
||||
TranslateWiki gives us _LANG_.json files and sometimes a modified ` qqq.json ` files with improved messages. All files are transferred through our repository, to which TranslateWiki has access. Our
|
||||
contact is Siebrand Mazeland.
|
||||
|
||||
# Applications and Tutorials
|
||||
|
||||
The Blockly applications and tutorials (henceforth referred to as "apps") are built with "Soy", also known as [Google Closure templates](https://developers.google.com/closure/templates/), which has [translation tools](https://developers.google.com/closure/templates/docs/translation). Specifically, all messages appear in files whose name ends with the "soy" extension. Messages used by multiple apps are defined in [apps/common.soy](https://code.google.com/p/blockly/source/browse/trunk/apps/common.soy), and have the prefix "Apps." Messages used by only a single app are defined in that app's template.soy file, such as [apps/maze/template.soy](https://code.google.com/p/blockly/source/browse/trunk/apps/maze/template.soy) and prefixed with the name of the application, such as "Maze.".
|
||||
|
||||
## The msg tag
|
||||
Here is an example of a message definition:
|
||||
|
||||
```
|
||||
{msg meaning="Maze.moveForward"
|
||||
desc="block text - Imperative or infinitive of a verb for a person moving
|
||||
(walking) in the direction he/she is facing."}
|
||||
move forward
|
||||
{/msg}
|
||||
```
|
||||
|
||||
Notes:
|
||||
* The key is defined through the "meaning" attribute: "Maze.moveForward".
|
||||
* The message documentation for the translator is defined through the "desc" attribute. This appears as the value in the qqq.json file.
|
||||
* The English language text appears between the "msg" start and end tags. This appears as the value in the en.json file.
|
||||
|
||||
A left brace or right brace can be included in an attribute value by using double braces to introduce and close the "msg" tags and writing "{lb}" [brace](wiki/left) for "{" or "{rb}" for "}", as in this definition:
|
||||
|
||||
```
|
||||
{{msg meaning="Puzzle.country1Language"
|
||||
desc="The English language.{lb}{lb}Identical|English{rb}{rb}"}}
|
||||
English
|
||||
{{/msg}}
|
||||
```
|
||||
(The TranslateWiki "Identical" tag is shrouded in mystery. It was added to a Blockly file by a TranslateWiki wizard, and I was told not to worry about why.)
|
||||
|
||||
## Placement of the msg tag
|
||||
|
||||
### Messages used only once within a template
|
||||
|
||||
If a message is used only once and the use is within the template, it can be defined where it is used:
|
||||
|
||||
```
|
||||
<button class="notext"
|
||||
title="{msg meaning="Apps.codeTooltip"
|
||||
desc="tooltip (pop-up help) for button; pressing the button causes a program in the
|
||||
JavaScript computer language to be displayed, based on the program created by the user."}
|
||||
See generated JavaScript code.
|
||||
{/msg}"
|
||||
onclick="BlocklyApps.showCode(this);">
|
||||
<img src="../../media/1x1.gif" class="code icon21">
|
||||
</button>
|
||||
```
|
||||
|
||||
|
||||
### Messages referenced from JavaScript files
|
||||
If a message is used by a JavaScript file, such as maze.js or blocks.js, it must be declared within a span:
|
||||
|
||||
```
|
||||
<span id="Maze_moveForward">
|
||||
{msg meaning="Maze.moveForward"
|
||||
desc="block text - Imperative or infinitive of a verb for a person moving
|
||||
(walking) in the direction he/she is facing."}
|
||||
move forward
|
||||
{/msg}
|
||||
</span>
|
||||
```
|
||||
By convention, the id of the span is the same as the "meaning" key but replaces periods with underscores. The message is referenced from code through the method ` BlocklyApps.getMsg() `, as in the example below from [apps/maze/blocks.js](https://code.google.com/p/blockly/source/browse/trunk/apps/maze/blocks.js):
|
||||
|
||||
```
|
||||
Blockly.Blocks['maze_moveForward'] = {
|
||||
// Block for moving forward. [A portion of the following code is omitted.]
|
||||
init: function() {
|
||||
this.setColour(290);
|
||||
this.appendDummyInput()
|
||||
.appendField(BlocklyApps.getMsg('Maze_moveForward'));
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Messages used multiple times
|
||||
If a message is used multiple times within one or multiple template files, all "msg" tags should have the same "meaning" attribute and enclosed text, but only one should have the real description as the "desc" attribute. The others should have "IBID" (case-insensitive).
|
||||
|
||||
If a message is used in more than one app, it should be defined within a span in [apps/common.soy](https://code.google.com/p/blockly/source/browse/trunk/apps/common.soy), and its meaning should be prefixed with "Apps.". For example, common.soy includes:
|
||||
|
||||
```
|
||||
<span id="blocklyMessage">
|
||||
{msg meaning="Apps.blocklyMessage"
|
||||
desc="The project name. If readers of your language would know approximately how to pronounce 'Blockly',
|
||||
leave unchanged. Otherwise, include a transliteration in parentheses, such as the Russian:
|
||||
'Blockly (\u0411\u043bo\u043a\u043b\u0438)'."}
|
||||
Blockly
|
||||
{/msg}
|
||||
</span>
|
||||
```
|
||||
|
||||
Here is a sample use from [apps/turtle/template.soy](https://code.google.com/p/blockly/source/browse/trunk/apps/turtle/template.soy):
|
||||
```
|
||||
<a href="../index.html">{msg meaning="Apps.blocklyMessage" desc="IBID"}Blockly{/msg}</a>
|
||||
```
|
||||
|
||||
## Build process
|
||||
|
||||
### Building a single app in English
|
||||
|
||||
Every app's template.soy file contains a comment near the top describing how to rebuild its English-language message file (apps/` * `/generated/en.js). For example, this command appears at the top of [apps/turtle/template.soy](https://code.google.com/p/blockly/source/browse/trunk/apps/turtle/template.soy):
|
||||
|
||||
```
|
||||
java -jar ../_soy/SoyToJsSrcCompiler.jar --outputPathFormat generated/en.js --srcs ../common.soy,template.soy
|
||||
```
|
||||
|
||||
When run in the apps/turtle directory, this rebuilds [apps/turtle/generated/en.js](https://code.google.com/p/blockly/source/browse/trunk/apps/turtle/generated/en.js).
|
||||
|
||||
Emacs users might want to add the following to their .emacs file to automatically regenerate the appropriate en.js file whenever a template.soy file is saved:
|
||||
```
|
||||
(add-hook 'after-save-hook
|
||||
(lambda ()
|
||||
(if (string-match "^template.soy\\(<.*>\\)?$" (buffer-name))
|
||||
(shell-command "java -jar ../_soy/SoyToJsSrcCompiler.jar --outputPathFormat generated/en.js --srcs ../common.soy,template.soy"))))
|
||||
```
|
||||
Of course, if you have a different path to ` _soy ` or wish to generate "en\_us.js" instead of "en.js", you will need to change the command.
|
||||
|
||||
|
||||
### Doing a full build
|
||||
|
||||
Before checking in code, developers should do a full i18n build by following the instructions in comments at the top of [apps/common.soy](https://code.google.com/p/blockly/source/browse/trunk/apps/common.soy). The below diagram shows the build process. It is followed by a description of each step.
|
||||
|
||||

|
||||
|
||||
#### SoyMsgExtractor.jar
|
||||
|
||||
<font color='orange'>SoyMsgExtractor.jar</font> extracts the messages from the template files into ` extracted_msgs.xlf `. For example, this message:
|
||||
|
||||
```
|
||||
{msg meaning="Maze.moveForward"
|
||||
desc="block text - Imperative or infinitive of a verb for a person moving
|
||||
(walking) in the direction he/she is facing."}
|
||||
move forward
|
||||
{/msg}
|
||||
```
|
||||
|
||||
becomes:
|
||||
|
||||
```
|
||||
<trans-unit id="4138774728570944645" datatype="html">
|
||||
<source>move forward</source>
|
||||
<note priority="1" from="description">block text - Imperative or infinitive of a verb for a person moving
|
||||
(walking) in the direction he/she is facing.</note>
|
||||
<note priority="1" from="meaning">Maze.moveForward</note>
|
||||
</trans-unit>
|
||||
```
|
||||
|
||||
The ` id ` is some sort of hash value that changes whenever the message description changes.
|
||||
|
||||
#### xliff\_to\_json.py
|
||||
|
||||
The script <font color='magenta'><a href='https://code.google.com/p/blockly/source/browse/trunk/i18n/xliff_to_json.py'>xliff_to_json.py</a></font> takes ` extracted_msgs.xlf ` as input and generates three JSON files that use message "meanings" (such as `Maze.moveForward') as keys:
|
||||
* [qqq.json](https://code.google.com/p/blockly/source/browse/trunk/apps/json/qqq.json), where the values are the message documentation (translator instructions).
|
||||
* [en.json](https://code.google.com/p/blockly/source/browse/trunk/apps/json/en.json), where the values are the English-language messages (e.g., "move forward").
|
||||
* [keys.json](https://code.google.com/p/blockly/source/browse/trunk/apps/json/keys.json), where the values are ` id `s from ` extracted_msgs.xlf `, such as "4138774728570944645".
|
||||
|
||||
Note that these do not change the other languages' json files, which were generated by <font color='blue'>translatewiki</font>. These files are automatically picked up by Siebrand Mazeland at translatewiki, who periodically checks in updated qqq.json and other languages' JSON files as blockly@translatewiki.net.
|
||||
|
||||
#### json\_to\_js.py
|
||||
|
||||
Finally, the script <font color='red'>json_to_js.py</font> uses the JSON files and template files to generate JavaScript files for each app-language combination, such as [apps/maze/generated/es.js](https://code.google.com/p/blockly/source/browse/trunk/apps/maze/generated/es.js), the Spanish translation of the maze application.
|
||||
|
||||
## Translation status
|
||||
|
||||
The status of the translations can be found at "https://translatewiki.net/w/i.php?title=Special%3AMessageGroupStats&x=D&group=out-blockly-apps&suppressempty=1".
|
||||
|
||||
To see how complete each application is, run the following from the ` apps/ ` directory:
|
||||
```
|
||||
../i18n/status.py json/*.json --html > status.html
|
||||
```
|
||||
View the resulting file in a browser. Additional options can be seen with:
|
||||
```
|
||||
../i18n/status.py --help
|
||||
```
|
||||
|
||||
# The Blockly Language
|
||||
|
||||
"The Blockly language" or "core Blockly" refers to the blocks that are defined in [blocks/](http://code.google.com/p/blockly/source/browse/#svn%2Ftrunk%2Fblocks) and are independent of (although used by) the apps. These include blocks for:
|
||||
* control flow (such as if and if-else)
|
||||
* loops
|
||||
* mathematical and logical functions and values
|
||||
* functions on text and on lists
|
||||
* creating and using functions and variables
|
||||
In this context of "the core Blockly language", "core" does _not_ refer to the directory [core/](http://code.google.com/p/blockly/source/browse/#svn%2Ftrunk%2Fcore), which contains Blockly's low-level base, which is not directly visible to users.
|
||||
|
||||
Because the core Blockly language may be used by developers who do not use Closure or Soy, and because the messages are only referenced from JavaScript, we use a different pipeline than described above for messages for applications and tutorials.
|
||||
|
||||
## messages.js
|
||||
|
||||
### definitions and descriptions
|
||||
|
||||
Messages are defined in the file [msg/messages.js](https://code.google.com/p/blockly/source/browse/trunk/msg/messages.js) using the following format:
|
||||
```
|
||||
/// <DESCRIPTION>
|
||||
Blockly.Msg.<KEY> = '<TEXT>';
|
||||
```
|
||||
Descriptions may be multiple lines, each of which is preceded by three slashes (` /// `). The key and English-language text must be on a single line, and the text must be delimited by single quotation marks immediately followed by a semicolon.
|
||||
|
||||
Here is a sample definition:
|
||||
```
|
||||
/// dropdown - This finds the most common numbers ([https://en.wikipedia.org/wiki/Mode_(statistics) modes])
|
||||
/// in a list. For example, the modes of the list {1, 3, 9, 3, 9} are {3, 9}.
|
||||
Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = 'modes of list';
|
||||
```
|
||||
|
||||
By convention, descriptions start with one of the terms listed in https://translatewiki.net/wiki/Translating:Blockly#Messages_associated_with_blocks. It is followed by a hyphen and a message description starting with a capital letter and ending with a period.
|
||||
|
||||
The use of [MediaWiki markup](http://www.mediawiki.org/wiki/Help:Formatting) is encouraged, including external links to this Blockly wiki, Wikipedia, and saved programs illustrating the use of a block. Files may be [uploaded to translatewiki](https://translatewiki.net/wiki/Special:Upload) and referenced as shown in the following example:
|
||||
```
|
||||
/// block text - Title of blocks allowing users to find text. See
|
||||
/// [https://code.google.com/p/blockly/wiki/Text#Finding_text
|
||||
/// https://code.google.com/p/blockly/wiki/Text#Finding_text].
|
||||
/// [[File:Blockly-find-text.png]]
|
||||
Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = 'in text';
|
||||
```
|
||||
This causes the picture to be displayed in-line for the translator.
|
||||
|
||||
Developers are encouraged to read through [msg/messages.js](https://code.google.com/p/blockly/source/browse/trunk/msg/messages.js) and to use the [Translation](wiki/Translation) interface before creating their own messages.
|
||||
|
||||
### synonyms
|
||||
|
||||
In some cases, one message is defined to be equal to another, as in:
|
||||
|
||||
```
|
||||
Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;
|
||||
```
|
||||
|
||||
This says that the default name of the variable in the "text append" block is the same as the general default variable. The format must be exactly as shown. It is not possible to include any other code on the line, such as concatenating two messages.
|
||||
|
||||
These synonyms exist either for historical reasons (they used to have different values) or to facilitate making them different in the future.
|
||||
|
||||
Synonym definitions may appear anywhere in ` messages.js ` after the right-hand value has been defined.
|
||||
|
||||
## Message interpolation
|
||||
|
||||
Ideally, translators should be given sentences, rather than bits of pieces of text to be concatenated with data. This can sometimes be provided through message interpolation, as in this example:
|
||||
|
||||

|
||||
```
|
||||
/// block title - Title of [https://code.google.com/p/blockly/wiki/Loops#count_with count with] blocks.
|
||||
Blockly.Msg.CONTROLS_FOR_INPUT_WITH = 'count with';
|
||||
|
||||
/// block text - Starting with a (usually lower) number in a range (%1),
|
||||
/// ending with a (usually higher) number in a range (%2), and counting the
|
||||
/// iterations by a number of steps (%3). As in
|
||||
/// [https://code.google.com/p/blockly/wiki/Loops#count_with
|
||||
/// https://code.google.com/p/blockly/wiki/Loops#count_with].
|
||||
Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = 'from %1 to %2 by %3';
|
||||
```
|
||||
The relevant part of the definition of the 'controls\_for' block in blocks/loops.js is:
|
||||
```
|
||||
this.appendDummyInput()
|
||||
.appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH)
|
||||
.appendField(new Blockly.FieldVariable(null), 'VAR');
|
||||
this.interpolateMsg(Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY,
|
||||
['FROM', 'Number', Blockly.ALIGN_RIGHT],
|
||||
['TO', 'Number', Blockly.ALIGN_RIGHT],
|
||||
['BY', 'Number', Blockly.ALIGN_RIGHT],
|
||||
Blockly.ALIGN_RIGHT);
|
||||
```
|
||||
The %1, %2, and %3 are placeholders respectively for the 'FROM', 'TO', and 'BY' numbers.
|
||||
|
||||
Note that the two messages could not have been combined into a single one because interpolation only supports sockets, not dropdowns, text fields, number fields, etc.
|
||||
|
||||
## Build process
|
||||
|
||||
Building consists of two steps: (1) generating JSON files and (2) generating JS files. They are built automatically by the main [build.py script](https://code.google.com/p/blockly/source/browse/trunk/build.py) but can also be built by executing the following two scripts.
|
||||
|
||||
### Generating JSON files
|
||||
|
||||
Translatewiki requires [en.json](https://code.google.com/p/blockly/source/browse/trunk/msg/json/en.json) and [qqq.json](https://code.google.com/p/blockly/source/browse/trunk/msg/json/qqq.json). We also require a file [synonyms.json](https://code.google.com/p/blockly/source/browse/trunk/msg/json/synonyms.json), to keep track of synonymous messages. These three files are generated by running the following command from the ` msg/ ` directory:
|
||||
```
|
||||
../i18n/js_to_json.py
|
||||
```
|
||||
The script [js\_to\_json.py](https://code.google.com/p/blockly/source/browse/trunk/i18n/js_to_json.py) contains the regular expressions matching lines in ` messages.js `, in case any question arises about syntax.
|
||||
|
||||
### Generating JavaScript files
|
||||
|
||||
The JSON files produced in the previous step, as well as any obtained from translatewiki are used by the following script:
|
||||
```
|
||||
../i18n/create_messages.py json/*.json
|
||||
```
|
||||
This populates the directory [msg/js/](https://code.google.com/p/blockly/source/browse/#svn%2Ftrunk%2Fmsg%2Fjs).
|
||||
Any messages not defined in a language's .json file will have the original English-language text, as shown by this excerpt from zh-tw.js:
|
||||
```
|
||||
Blockly.Msg.CHANGE_VALUE_TITLE = "修改值:";
|
||||
Blockly.Msg.COLLAPSE_ALL = "Collapse Blocks"; // untranslated
|
||||
```
|
||||
The comment "untranslated" is added automatically by [create\_messages.py](https://code.google.com/p/blockly/source/browse/trunk/i18n/create_messages.py).
|
||||
|
||||
## Translation status
|
||||
|
||||
The status of the translations can be found at "https://translatewiki.net/w/i.php?title=Special%3AMessageGroupStats&x=D&group=out-blockly-core&suppressempty=1".
|
||||
15
True_False.md
Normal file
15
True_False.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# The **True False** Block
|
||||
|
||||
To access the **True False** Block, click **Logic**.
|
||||
|
||||
| **Option** | **Description** |
|
||||
|:-----------|:----------------|
|
||||
| **true** | Useful when combined with another block, like the **Repeat** block, to tell the program to do something whenever a condition is true.|
|
||||
| **false** |Useful when combined with another block, like the **Repeat** block, to tell the program to do something whenever a condition is true.|
|
||||
|
||||
**Tip**: Combine the **True False** block with the [Repeat](wiki/Repeat) block to write statements like:
|
||||
|
||||
* **Repeat while** true.
|
||||
* **Repeat until** false.
|
||||
|
||||
**Note**: The **True False** block fits with other blocks, like the **And Or** block, that it might not be useful with.
|
||||
18
UnitTesting.md
Normal file
18
UnitTesting.md
Normal file
@@ -0,0 +1,18 @@
|
||||
After changing or adding code, you should run existing unit tests and consider writing more.
|
||||
|
||||
# Running unit tests
|
||||
1. Load ` tests/generators/index.html ` in a browser.
|
||||
1. Choose the relevant part of the system to test from the drop-down menu, and click "Load". Blocks should appear in the workspace.
|
||||
1. Click on "JavaScript".
|
||||
1. Copy and run the generated code in a JavaScript console. If the output ends with "OK", the test has passed.
|
||||
1. Click on "Python".
|
||||
1. Copy and run the generated code in a Python interpreter. If the output ends with "OK", the test has passed.
|
||||
1. Click on "Dart".
|
||||
1. Copy and run the generated code in a Dart interpreter. If the output ends with "OK", the test has passed.
|
||||
|
||||
# Modifying or creating unit tests
|
||||
1. Load ` tests/generators/index.html ` in a browser.
|
||||
1. Choose the relevant part of the system from the drop-down menu, and click "Load". Blocks should appear in the workspace.
|
||||
1. Make any changes or additions to the blocks.
|
||||
1. Click on "XML".
|
||||
1. Copy the generated XML into the appropriate file in ` tests/generators/ `.
|
||||
49
Variables.md
Normal file
49
Variables.md
Normal file
@@ -0,0 +1,49 @@
|
||||
(TODO: Add table of contents.)
|
||||
|
||||
# Introduction
|
||||
|
||||
We use the term _variable_ the same as it is used in mathematics and in other programming languages: a named value that can be changed (varies). Variables can be created in several different ways.
|
||||
* Every [count with](https://code.google.com/p/blockly/wiki/Loops#count_with) and [for each](https://code.google.com/p/blockly/wiki/Loops#for_each) block uses a variable and defines its values. These values can only be used within the block. A traditional computer science term for these are [loop variables](https://en.wikipedia.org/wiki/Loop_variable).
|
||||
* User-defined functions (also known as "procedures") can define inputs, which creates variables that can be used only within the function. These are traditionally called "[parameters](https://en.wikipedia.org/wiki/Parameter)" or "arguments".
|
||||
* Users may create variables at any time through the "set" block. These are traditionally called "[global variables](https://en.wikipedia.org/wiki/Global_variables)".
|
||||
Blockly does not support [local variables](https://en.wikipedia.org/wiki/Local_variable).
|
||||
|
||||
|
||||
## Default names
|
||||
|
||||
While users can choose any name for a variable, core Blockly provides a default name, "item", as shown in the below picture. Some applications provide other default values, such as "value", also shown below.
|
||||
|
||||
## Dropdown menu
|
||||
|
||||
Clicking on a variable's dropdown symbol (triangle) gives the following menu:
|
||||
|
||||

|
||||
|
||||
The menu provides the following options.
|
||||
* the names of all variables defined in the program.
|
||||
* "Rename variable...", which changes the name of this variable wherever it appears in the program. Selecting this opens a small window that prompts the user for the new name with the text: "Rename all %1 variables to:", where %1 is replaced by the old name (here "item").
|
||||
* "New variable...", which enables the user to enter a new name for the variable, without replacing or changing variables with the old name (here "item"). Selecting this opens a small window that prompts the user for the new name with the text "New variable name:".
|
||||
|
||||
# Blocks
|
||||
|
||||
## Set
|
||||
|
||||
The **set** block assigns a value to a variable, creating the variable if it doesn't already exist. For example, this sets the value of the variable named "age" to 12.
|
||||
|
||||

|
||||
|
||||
## Get
|
||||
|
||||
The **get** block provides the value stored in a variable, without changing it.
|
||||
|
||||

|
||||
|
||||
It is possible, but a bad idea, to write a program in which a **get** appears without a corresponding **set**.
|
||||
|
||||
# Example
|
||||
|
||||
Consider the following example code:
|
||||
|
||||

|
||||
|
||||
The first row of blocks creates a variable named "age" and sets its initial value to the number 12. The second row of blocks gets the value 12, adds 1 to it, and stores the sum (13) into the variable. The final row displays the message: "Happy birthday! You are now 13"
|
||||
Reference in New Issue
Block a user