Merge branch 'develop' into rc/nov_2017

This commit is contained in:
Rachel Fenichel
2017-11-13 14:54:07 -08:00
96 changed files with 1430 additions and 1279 deletions
+5 -1
View File
@@ -2,9 +2,13 @@
*_uncompressed*.js
/msg/*
/core/css.js
/tests/blocks/*
/tests/compile/*
/tests/jsunit/*
/tests/generators/*
/tests/workspace_svg/*
/generators/*
/demos/*
/accessible/*
/appengine/*
/appengine/*
/externs/svg-externs.js
+48 -32
View File
@@ -1,57 +1,73 @@
Thanks for opening an issue for us! Before you open an issue, please check if a similar issue exists or has been closed before.
If you're asking a question about how to use Blockly in your application, please ask questions on the [mailing list](https://groups.google.com/forum/#!forum/blockly) instead of filing issues.
_Please delete the above section and the instructions in the sections below before submitting. If a section is not applicable, type "N/A" in that section._
<!--
- Thanks for opening an issue for us! Before you open an issue,
- please check if a similar issue exists or has been closed before.
-
- If you're asking a question about how to use Blockly in your application,
- please ask questions on the mailing list, instead of filing issues:
- https://groups.google.com/forum/#!forum/blockly
-->
### Problem statement
_Remove this hint: these checkboxes can be checked like this: [x]_
- [ ] Bug report
- [ ] Feature request
_What were you trying to do when you hit this bug? Or, what do you want to do with Blockly that your proposed feature would enable?_
<!-- TODO: Please describe the problem.
- Is it a bug report (something didn't work the way you expected),
- or a feature request (something new you think would improve Blockly)?
-->
### Expected Behavior
_Please describe what should happen. Include screenshots if applicable._
<!-- TODO: Please describe what should happen.
- Include screenshots if applicable.
-->
### Actual Behavior
_Describe what actually happens. Include screenshots if applicable._
<!-- TODO: Describe what actually happens.
- Include screenshots if applicable.
-->
### Steps to Reproduce
_Explain what someone needs to do in order to see what's described in *Actual behavior* above_
<!-- TODO: Explain what someone needs to do in order to see
- what's described in *Actual behavior* above
-->
1. Start by..
2. Next, do..
### Stack Traces
```
Please open up the console. If you see any Blockly-related errors, paste them here.
<!-- TODO: Please open up the console. If you see any Blockly-related errors,
- paste them between the quotes below.
-
- Ignore any instances of...
- "Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause()."
-->
Ignore any instances of "Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause()."
```
Replace with error stack trace.
```
### Operating System and Browser
_Remove this hint: these checkboxes can be checked like this: [x]_
<!-- TODO: If this issue is browser specific, uncomment the systems you have tested. -->
- [ ] Desktop:
- [ ] Chrome
- [ ] Firefox
- [ ] Safari
- [ ] Opera
- [ ] IE 10+
- [ ] IE 11
- [ ] EDGE
<!-- * Desktop Chrome -->
<!-- * Desktop Firefox -->
<!-- * Desktop Safari -->
<!-- * Desktop Opera -->
<!-- * Windows Internet Explorer 10 -->
<!-- * Windows Internet Explorer 11 -->
<!-- * Windows Edge -->
- [ ] Smartphone/Tablet/Chromebook (please complete the following information):
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
<!--
* Smartphone/Tablet/Chromebook (please complete the following information):
* Device: [e.g. iPhone6]
* OS: [e.g. iOS8.1]
* Browser [e.g. stock browser, safari]
* Version [e.g. 22]
-->
### Additional Information
_Anything else we should know?_
<!-- Anything else we should know? -->
+29 -21
View File
@@ -1,7 +1,12 @@
Thanks for submitting code to Blockly! Please fill out the following as part of your pull request so we can review your code more easily.
<!--
- Thanks for submitting code to Blockly! Please fill out the following as part of
- your pull request so we can review your code more easily.
-->
## The basics
<!-- TODO: Verify the following, checking each box with an 'x' between the brackets: [x] -->
- [ ] I branched from develop
- [ ] My pull request is against develop
- [ ] My code follows the [style guide](https://developers.google.com/blockly/guides/modify/web/style-guide)
@@ -9,37 +14,40 @@ Thanks for submitting code to Blockly! Please fill out the following as part of
## The details
### Resolves
_What Github issue does this resolve (please include link)?_
<!-- TODO: What Github issue does this resolve? Please include a link. -->
### Proposed Changes
_Describe what this Pull Request does. Include screenshots if applicable._
<!-- TODO: Describe what this Pull Request does. Include screenshots if applicable. -->
### Reason for Changes
_Explain why these changes should be made. Include screenshots if applicable._
<!--TODO: Explain why these changes should be made. Include screenshots if applicable. -->
### Test Coverage
_Please show how you have added tests to cover your changes, or tell us how you tested it and on which platforms. If it's plaform-agnostic you can delete these checkboxes._
<!-- TODO: Please show how you have added tests to cover your changes,
- or tell us how you tested it. For each systems you tested,
- uncomment the systems in the list below.
-->
Tested on:
_Remove this hint: these checkboxes can be checked like this: [x]_
- [ ] Desktop:
- [ ] Chrome
- [ ] Firefox
- [ ] Safari
- [ ] Opera
- [ ] IE 10+
- [ ] IE 11
- [ ] EDGE
<!-- * Desktop Chrome -->
<!-- * Desktop Firefox -->
<!-- * Desktop Safari -->
<!-- * Desktop Opera -->
<!-- * Windows Internet Explorer 10 -->
<!-- * Windows Internet Explorer 11 -->
<!-- * Windows Edge -->
<!--
* Smartphone/Tablet/Chromebook (please complete the following information):
* Device: [e.g. iPhone6]
* OS: [e.g. iOS8.1]
* Browser [e.g. stock browser, safari]
* Version [e.g. 22]
-->
- [ ] Smartphone/Tablet/Chromebook (please complete the following information):
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
### Additional Information
_Anything else we should know?_
<!-- Anything else we should know? -->
+3
View File
@@ -6,3 +6,6 @@ npm-debug.log
*.pyc
*.komodoproject
/nbproject/private/
tests/compile/main_compressed.js
tests/compile/*compiler*.jar
+5 -2
View File
@@ -15,16 +15,19 @@ matrix:
before_install:
- npm install google-closure-library
- npm install google-closure-compiler
- npm install webdriverio
# Symlink closure library
- ln -s $(npm root)/google-closure-library ../closure-library
before_script:
- export DISPLAY=:99.0
- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then ( scripts/setup_linux_env.sh ) fi
- if [ "${TRAVIS_OS_NAME}" == "osx" ]; then ( scripts/setup_osx_env.sh ) fi
- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then ( tests/scripts/setup_linux_env.sh ) fi
- if [ "${TRAVIS_OS_NAME}" == "osx" ]; then ( tests/scripts/setup_osx_env.sh ) fi
- sleep 2
script:
- set -x
- npm run lint
- npm test
- cd tests/compile; compile.sh; cd ..
+3 -3
View File
@@ -1390,7 +1390,7 @@ Blockly.Events.VarRename=function(a,b){a&&(Blockly.Events.VarRename.superClass_.
Blockly.Events.VarRename.prototype.fromJson=function(a){Blockly.Events.VarRename.superClass_.fromJson.call(this,a);this.oldName=a.oldName;this.newName=a.newName};Blockly.Events.VarRename.prototype.run=function(a){var b=this.getEventWorkspace_();a?b.renameVariableById(this.varId,this.newName):b.renameVariableById(this.varId,this.oldName)};
Blockly.Events.disableOrphans=function(a){if(a.type==Blockly.Events.MOVE||a.type==Blockly.Events.CREATE){Blockly.Events.disable();var b=Blockly.Workspace.getById(a.workspaceId);if(a=b.getBlockById(a.blockId))if(a.getParent()&&!a.getParent().disabled){b=a.getDescendants();a=0;for(var c;c=b[a];a++)c.setDisabled(!1)}else if((a.outputConnection||a.previousConnection)&&!b.isDragging()){do a.setDisabled(!0),a=a.getNextBlock();while(a)}Blockly.Events.enable()}};Blockly.Msg={};goog.getMsgOrig=goog.getMsg;goog.getMsg=function(a,b){var c=goog.getMsg.blocklyMsgMap[a];c&&(a=Blockly.Msg[c]);return goog.getMsgOrig(a,b)};goog.getMsg.blocklyMsgMap={Today:"TODAY"};Blockly.FieldTextInput=function(a,b){Blockly.FieldTextInput.superClass_.constructor.call(this,a,b)};goog.inherits(Blockly.FieldTextInput,Blockly.Field);Blockly.FieldTextInput.FONTSIZE=11;Blockly.FieldTextInput.htmlInput_=null;Blockly.FieldTextInput.prototype.CURSOR="text";Blockly.FieldTextInput.prototype.spellcheck_=!0;Blockly.FieldTextInput.prototype.dispose=function(){Blockly.WidgetDiv.hideIfOwner(this);Blockly.FieldTextInput.superClass_.dispose.call(this)};
Blockly.FieldTextInput.prototype.setValue=function(a){if(null!==a){if(this.sourceBlock_){var b=this.callValidator(a);null!==b&&(a=b)}Blockly.Field.prototype.setValue.call(this,a)}};Blockly.FieldTextInput.prototype.setText=function(a){null!==a&&(a=String(a),a!==this.text_&&(this.sourceBlock_&&Blockly.Events.isEnabled()&&Blockly.Events.fire(new Blockly.Events.BlockChange(this.sourceBlock_,"field",this.name,this.text_,a)),Blockly.Field.prototype.setText.call(this,a)))};
Blockly.FieldTextInput.prototype.setSpellcheck=function(a){this.spellcheck_=a};Blockly.FieldTextInput.prototype.showEditor_=function(a){this.workspace_=this.sourceBlock_.workspace;a=a||!1;!a&&(goog.userAgent.MOBILE||goog.userAgent.ANDROID||goog.userAgent.IPAD)?this.showPromptEditor_():this.showInlineEditor_(a)};Blockly.FieldTextInput.prototype.showPromptEditor_=function(){var a=this;Blockly.prompt(Blockly.Msg.CHANGE_VALUE_TITLE,this.text_,function(b){a.sourceBlock_&&(b=a.callValidator(b));a.setValue(b)})};
Blockly.FieldTextInput.prototype.setSpellcheck=function(a){this.spellcheck_=a};Blockly.FieldTextInput.prototype.showEditor_=function(a){this.workspace_=this.sourceBlock_.workspace;a=a||!1;!a&&(goog.userAgent.MOBILE||goog.userAgent.ANDROID||goog.userAgent.IPAD)?this.showPromptEditor_():this.showInlineEditor_(a)};Blockly.FieldTextInput.showPromptEditor_=function(){var a=this;Blockly.prompt(Blockly.Msg.CHANGE_VALUE_TITLE,this.text_,function(b){a.sourceBlock_&&(b=a.callValidator(b));a.setValue(b)})};
Blockly.FieldTextInput.prototype.showInlineEditor_=function(a){Blockly.WidgetDiv.show(this,this.sourceBlock_.RTL,this.widgetDispose_());var b=Blockly.WidgetDiv.DIV,c=goog.dom.createDom("INPUT","blocklyHtmlInput");c.setAttribute("spellcheck",this.spellcheck_);var d=Blockly.FieldTextInput.FONTSIZE*this.workspace_.scale+"pt";b.style.fontSize=d;c.style.fontSize=d;Blockly.FieldTextInput.htmlInput_=c;b.appendChild(c);c.value=c.defaultValue=this.text_;c.oldValue_=null;this.validate_();this.resizeEditor_();
a||(c.focus(),c.select());this.bindEvents_(c)};Blockly.FieldTextInput.prototype.bindEvents_=function(a){a.onKeyDownWrapper_=Blockly.bindEventWithChecks_(a,"keydown",this,this.onHtmlInputKeyDown_);a.onKeyUpWrapper_=Blockly.bindEventWithChecks_(a,"keyup",this,this.onHtmlInputChange_);a.onKeyPressWrapper_=Blockly.bindEventWithChecks_(a,"keypress",this,this.onHtmlInputChange_);a.onWorkspaceChangeWrapper_=this.resizeEditor_.bind(this);this.workspace_.addChangeListener(a.onWorkspaceChangeWrapper_)};
Blockly.FieldTextInput.prototype.unbindEvents_=function(a){Blockly.unbindEvent_(a.onKeyDownWrapper_);Blockly.unbindEvent_(a.onKeyUpWrapper_);Blockly.unbindEvent_(a.onKeyPressWrapper_);this.workspace_.removeChangeListener(a.onWorkspaceChangeWrapper_)};
@@ -1553,8 +1553,8 @@ Blockly.Css.CONTENT=[".blocklySvg {","background-color: #fff;","outline: none;",
"opacity: 0;","}",".blocklyMainWorkspaceScrollbar {","z-index: 20;","}",".blocklyFlyoutScrollbar {","z-index: 30;","}",".blocklyScrollbarHorizontal, .blocklyScrollbarVertical {","position: absolute;","outline: none;","}",".blocklyScrollbarBackground {","opacity: 0;","}",".blocklyScrollbarHandle {","fill: #ccc;","}",".blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,",".blocklyScrollbarHandle:hover {","fill: #bbb;","}",".blocklyZoom>image {","opacity: .4;","}",".blocklyZoom>image:hover {",
"opacity: .6;","}",".blocklyZoom>image:active {","opacity: .8;","}",".blocklyFlyout .blocklyScrollbarHandle {","fill: #bbb;","}",".blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,",".blocklyFlyout .blocklyScrollbarHandle:hover {","fill: #aaa;","}",".blocklyInvalidInput {","background: #faa;","}",".blocklyAngleCircle {","stroke: #444;","stroke-width: 1;","fill: #ddd;","fill-opacity: .8;","}",".blocklyAngleMarks {","stroke: #444;","stroke-width: 1;","}",".blocklyAngleGauge {",
"fill: #f88;","fill-opacity: .8;","}",".blocklyAngleLine {","stroke: #f00;","stroke-width: 2;","stroke-linecap: round;","pointer-events: none;","}",".blocklyContextMenu {","border-radius: 4px;","}",".blocklyDropdownMenu {","padding: 0 !important;","}",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-icon {","background: url(<<<PATH>>>/sprites.png) no-repeat -48px -16px !important;","}",".blocklyToolboxDiv {","background-color: #ddd;",
"overflow-x: visible;","overflow-y: auto;","position: absolute;","z-index: 70;","-webkit-tap-highlight-color: transparent;","}",".blocklyTreeRoot {","padding: 4px 0;","}",".blocklyTreeRoot:focus {","outline: none;","}",".blocklyTreeRow {","height: 22px;","line-height: 22px;","margin-bottom: 3px;","padding-right: 8px;","white-space: nowrap;","}",".blocklyHorizontalTree {","float: left;","margin: 1px 5px 8px 0;","}",".blocklyHorizontalTreeRtl {","float: right;","margin: 1px 0 8px 5px;","}",'.blocklyToolboxDiv[dir="RTL"] .blocklyTreeRow {',
"margin-left: 8px;","}",".blocklyTreeRow:not(.blocklyTreeSelected):hover {","background-color: #e4e4e4;","}",".blocklyTreeSeparator {","border-bottom: solid #e5e5e5 1px;","height: 0;","margin: 5px 0;","}",".blocklyTreeSeparatorHorizontal {","border-right: solid #e5e5e5 1px;","width: 0;","padding: 5px 0;","margin: 0 5px;","}",".blocklyTreeIcon {","background-image: url(<<<PATH>>>/sprites.png);","height: 16px;","vertical-align: middle;","width: 16px;","}",".blocklyTreeIconClosedLtr {","background-position: -32px -1px;",
"overflow-x: visible;","overflow-y: auto;","position: absolute;","z-index: 70;","}",".blocklyTreeRoot {","padding: 4px 0;","}",".blocklyTreeRoot:focus {","outline: none;","}",".blocklyTreeRow {","height: 22px;","line-height: 22px;","margin-bottom: 3px;","padding-right: 8px;","white-space: nowrap;","}",".blocklyHorizontalTree {","float: left;","margin: 1px 5px 8px 0;","}",".blocklyHorizontalTreeRtl {","float: right;","margin: 1px 0 8px 5px;","}",'.blocklyToolboxDiv[dir="RTL"] .blocklyTreeRow {',"margin-left: 8px;",
"}",".blocklyTreeRow:not(.blocklyTreeSelected):hover {","background-color: #e4e4e4;","}",".blocklyTreeSeparator {","border-bottom: solid #e5e5e5 1px;","height: 0;","margin: 5px 0;","}",".blocklyTreeSeparatorHorizontal {","border-right: solid #e5e5e5 1px;","width: 0;","padding: 5px 0;","margin: 0 5px;","}",".blocklyTreeIcon {","background-image: url(<<<PATH>>>/sprites.png);","height: 16px;","vertical-align: middle;","width: 16px;","}",".blocklyTreeIconClosedLtr {","background-position: -32px -1px;",
"}",".blocklyTreeIconClosedRtl {","background-position: 0px -1px;","}",".blocklyTreeIconOpen {","background-position: -16px -1px;","}",".blocklyTreeSelected>.blocklyTreeIconClosedLtr {","background-position: -32px -17px;","}",".blocklyTreeSelected>.blocklyTreeIconClosedRtl {","background-position: 0px -17px;","}",".blocklyTreeSelected>.blocklyTreeIconOpen {","background-position: -16px -17px;","}",".blocklyTreeIconNone,",".blocklyTreeSelected>.blocklyTreeIconNone {","background-position: -48px -1px;",
"}",".blocklyTreeLabel {","cursor: default;","font-family: sans-serif;","font-size: 16px;","padding: 0 3px;","vertical-align: middle;","}",".blocklyToolboxDelete .blocklyTreeLabel {",'cursor: url("<<<PATH>>>/handdelete.cur"), auto;',"}",".blocklyTreeSelected .blocklyTreeLabel {","color: #fff;","}",".blocklyWidgetDiv .goog-palette {","outline: none;","cursor: default;","}",".blocklyWidgetDiv .goog-palette-table {","border: 1px solid #666;","border-collapse: collapse;","}",".blocklyWidgetDiv .goog-palette-cell {",
"height: 13px;","width: 15px;","margin: 0;","border: 0;","text-align: center;","vertical-align: middle;","border-right: 1px solid #666;","font-size: 1px;","}",".blocklyWidgetDiv .goog-palette-colorswatch {","position: relative;","height: 13px;","width: 15px;","border: 1px solid #666;","}",".blocklyWidgetDiv .goog-palette-cell-hover .goog-palette-colorswatch {","border: 1px solid #FFF;","}",".blocklyWidgetDiv .goog-palette-cell-selected .goog-palette-colorswatch {","border: 1px solid #000;","color: #fff;",
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -1399,7 +1399,7 @@ Blockly.Events.VarRename=function(a,b){a&&(Blockly.Events.VarRename.superClass_.
Blockly.Events.VarRename.prototype.fromJson=function(a){Blockly.Events.VarRename.superClass_.fromJson.call(this,a);this.oldName=a.oldName;this.newName=a.newName};Blockly.Events.VarRename.prototype.run=function(a){var b=this.getEventWorkspace_();a?b.renameVariableById(this.varId,this.newName):b.renameVariableById(this.varId,this.oldName)};
Blockly.Events.disableOrphans=function(a){if(a.type==Blockly.Events.MOVE||a.type==Blockly.Events.CREATE){Blockly.Events.disable();var b=Blockly.Workspace.getById(a.workspaceId);if(a=b.getBlockById(a.blockId))if(a.getParent()&&!a.getParent().disabled){b=a.getDescendants();a=0;for(var c;c=b[a];a++)c.setDisabled(!1)}else if((a.outputConnection||a.previousConnection)&&!b.isDragging()){do a.setDisabled(!0),a=a.getNextBlock();while(a)}Blockly.Events.enable()}};Blockly.Msg={};goog.getMsgOrig=goog.getMsg;goog.getMsg=function(a,b){var c=goog.getMsg.blocklyMsgMap[a];c&&(a=Blockly.Msg[c]);return goog.getMsgOrig(a,b)};goog.getMsg.blocklyMsgMap={Today:"TODAY"};Blockly.FieldTextInput=function(a,b){Blockly.FieldTextInput.superClass_.constructor.call(this,a,b)};goog.inherits(Blockly.FieldTextInput,Blockly.Field);Blockly.FieldTextInput.FONTSIZE=11;Blockly.FieldTextInput.htmlInput_=null;Blockly.FieldTextInput.prototype.CURSOR="text";Blockly.FieldTextInput.prototype.spellcheck_=!0;Blockly.FieldTextInput.prototype.dispose=function(){Blockly.WidgetDiv.hideIfOwner(this);Blockly.FieldTextInput.superClass_.dispose.call(this)};
Blockly.FieldTextInput.prototype.setValue=function(a){if(null!==a){if(this.sourceBlock_){var b=this.callValidator(a);null!==b&&(a=b)}Blockly.Field.prototype.setValue.call(this,a)}};Blockly.FieldTextInput.prototype.setText=function(a){null!==a&&(a=String(a),a!==this.text_&&(this.sourceBlock_&&Blockly.Events.isEnabled()&&Blockly.Events.fire(new Blockly.Events.BlockChange(this.sourceBlock_,"field",this.name,this.text_,a)),Blockly.Field.prototype.setText.call(this,a)))};
Blockly.FieldTextInput.prototype.setSpellcheck=function(a){this.spellcheck_=a};Blockly.FieldTextInput.prototype.showEditor_=function(a){this.workspace_=this.sourceBlock_.workspace;a=a||!1;!a&&(goog.userAgent.MOBILE||goog.userAgent.ANDROID||goog.userAgent.IPAD)?this.showPromptEditor_():this.showInlineEditor_(a)};Blockly.FieldTextInput.prototype.showPromptEditor_=function(){var a=this;Blockly.prompt(Blockly.Msg.CHANGE_VALUE_TITLE,this.text_,function(b){a.sourceBlock_&&(b=a.callValidator(b));a.setValue(b)})};
Blockly.FieldTextInput.prototype.setSpellcheck=function(a){this.spellcheck_=a};Blockly.FieldTextInput.prototype.showEditor_=function(a){this.workspace_=this.sourceBlock_.workspace;a=a||!1;!a&&(goog.userAgent.MOBILE||goog.userAgent.ANDROID||goog.userAgent.IPAD)?this.showPromptEditor_():this.showInlineEditor_(a)};Blockly.FieldTextInput.showPromptEditor_=function(){var a=this;Blockly.prompt(Blockly.Msg.CHANGE_VALUE_TITLE,this.text_,function(b){a.sourceBlock_&&(b=a.callValidator(b));a.setValue(b)})};
Blockly.FieldTextInput.prototype.showInlineEditor_=function(a){Blockly.WidgetDiv.show(this,this.sourceBlock_.RTL,this.widgetDispose_());var b=Blockly.WidgetDiv.DIV,c=goog.dom.createDom("INPUT","blocklyHtmlInput");c.setAttribute("spellcheck",this.spellcheck_);var d=Blockly.FieldTextInput.FONTSIZE*this.workspace_.scale+"pt";b.style.fontSize=d;c.style.fontSize=d;Blockly.FieldTextInput.htmlInput_=c;b.appendChild(c);c.value=c.defaultValue=this.text_;c.oldValue_=null;this.validate_();this.resizeEditor_();
a||(c.focus(),c.select());this.bindEvents_(c)};Blockly.FieldTextInput.prototype.bindEvents_=function(a){a.onKeyDownWrapper_=Blockly.bindEventWithChecks_(a,"keydown",this,this.onHtmlInputKeyDown_);a.onKeyUpWrapper_=Blockly.bindEventWithChecks_(a,"keyup",this,this.onHtmlInputChange_);a.onKeyPressWrapper_=Blockly.bindEventWithChecks_(a,"keypress",this,this.onHtmlInputChange_);a.onWorkspaceChangeWrapper_=this.resizeEditor_.bind(this);this.workspace_.addChangeListener(a.onWorkspaceChangeWrapper_)};
Blockly.FieldTextInput.prototype.unbindEvents_=function(a){Blockly.unbindEvent_(a.onKeyDownWrapper_);Blockly.unbindEvent_(a.onKeyUpWrapper_);Blockly.unbindEvent_(a.onKeyPressWrapper_);this.workspace_.removeChangeListener(a.onWorkspaceChangeWrapper_)};
@@ -1562,8 +1562,8 @@ Blockly.Css.CONTENT=[".blocklySvg {","background-color: #fff;","outline: none;",
"opacity: 0;","}",".blocklyMainWorkspaceScrollbar {","z-index: 20;","}",".blocklyFlyoutScrollbar {","z-index: 30;","}",".blocklyScrollbarHorizontal, .blocklyScrollbarVertical {","position: absolute;","outline: none;","}",".blocklyScrollbarBackground {","opacity: 0;","}",".blocklyScrollbarHandle {","fill: #ccc;","}",".blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,",".blocklyScrollbarHandle:hover {","fill: #bbb;","}",".blocklyZoom>image {","opacity: .4;","}",".blocklyZoom>image:hover {",
"opacity: .6;","}",".blocklyZoom>image:active {","opacity: .8;","}",".blocklyFlyout .blocklyScrollbarHandle {","fill: #bbb;","}",".blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,",".blocklyFlyout .blocklyScrollbarHandle:hover {","fill: #aaa;","}",".blocklyInvalidInput {","background: #faa;","}",".blocklyAngleCircle {","stroke: #444;","stroke-width: 1;","fill: #ddd;","fill-opacity: .8;","}",".blocklyAngleMarks {","stroke: #444;","stroke-width: 1;","}",".blocklyAngleGauge {",
"fill: #f88;","fill-opacity: .8;","}",".blocklyAngleLine {","stroke: #f00;","stroke-width: 2;","stroke-linecap: round;","pointer-events: none;","}",".blocklyContextMenu {","border-radius: 4px;","}",".blocklyDropdownMenu {","padding: 0 !important;","}",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-icon {","background: url(<<<PATH>>>/sprites.png) no-repeat -48px -16px !important;","}",".blocklyToolboxDiv {","background-color: #ddd;",
"overflow-x: visible;","overflow-y: auto;","position: absolute;","z-index: 70;","-webkit-tap-highlight-color: transparent;","}",".blocklyTreeRoot {","padding: 4px 0;","}",".blocklyTreeRoot:focus {","outline: none;","}",".blocklyTreeRow {","height: 22px;","line-height: 22px;","margin-bottom: 3px;","padding-right: 8px;","white-space: nowrap;","}",".blocklyHorizontalTree {","float: left;","margin: 1px 5px 8px 0;","}",".blocklyHorizontalTreeRtl {","float: right;","margin: 1px 0 8px 5px;","}",'.blocklyToolboxDiv[dir="RTL"] .blocklyTreeRow {',
"margin-left: 8px;","}",".blocklyTreeRow:not(.blocklyTreeSelected):hover {","background-color: #e4e4e4;","}",".blocklyTreeSeparator {","border-bottom: solid #e5e5e5 1px;","height: 0;","margin: 5px 0;","}",".blocklyTreeSeparatorHorizontal {","border-right: solid #e5e5e5 1px;","width: 0;","padding: 5px 0;","margin: 0 5px;","}",".blocklyTreeIcon {","background-image: url(<<<PATH>>>/sprites.png);","height: 16px;","vertical-align: middle;","width: 16px;","}",".blocklyTreeIconClosedLtr {","background-position: -32px -1px;",
"overflow-x: visible;","overflow-y: auto;","position: absolute;","z-index: 70;","}",".blocklyTreeRoot {","padding: 4px 0;","}",".blocklyTreeRoot:focus {","outline: none;","}",".blocklyTreeRow {","height: 22px;","line-height: 22px;","margin-bottom: 3px;","padding-right: 8px;","white-space: nowrap;","}",".blocklyHorizontalTree {","float: left;","margin: 1px 5px 8px 0;","}",".blocklyHorizontalTreeRtl {","float: right;","margin: 1px 0 8px 5px;","}",'.blocklyToolboxDiv[dir="RTL"] .blocklyTreeRow {',"margin-left: 8px;",
"}",".blocklyTreeRow:not(.blocklyTreeSelected):hover {","background-color: #e4e4e4;","}",".blocklyTreeSeparator {","border-bottom: solid #e5e5e5 1px;","height: 0;","margin: 5px 0;","}",".blocklyTreeSeparatorHorizontal {","border-right: solid #e5e5e5 1px;","width: 0;","padding: 5px 0;","margin: 0 5px;","}",".blocklyTreeIcon {","background-image: url(<<<PATH>>>/sprites.png);","height: 16px;","vertical-align: middle;","width: 16px;","}",".blocklyTreeIconClosedLtr {","background-position: -32px -1px;",
"}",".blocklyTreeIconClosedRtl {","background-position: 0px -1px;","}",".blocklyTreeIconOpen {","background-position: -16px -1px;","}",".blocklyTreeSelected>.blocklyTreeIconClosedLtr {","background-position: -32px -17px;","}",".blocklyTreeSelected>.blocklyTreeIconClosedRtl {","background-position: 0px -17px;","}",".blocklyTreeSelected>.blocklyTreeIconOpen {","background-position: -16px -17px;","}",".blocklyTreeIconNone,",".blocklyTreeSelected>.blocklyTreeIconNone {","background-position: -48px -1px;",
"}",".blocklyTreeLabel {","cursor: default;","font-family: sans-serif;","font-size: 16px;","padding: 0 3px;","vertical-align: middle;","}",".blocklyToolboxDelete .blocklyTreeLabel {",'cursor: url("<<<PATH>>>/handdelete.cur"), auto;',"}",".blocklyTreeSelected .blocklyTreeLabel {","color: #fff;","}",".blocklyWidgetDiv .goog-palette {","outline: none;","cursor: default;","}",".blocklyWidgetDiv .goog-palette-table {","border: 1px solid #666;","border-collapse: collapse;","}",".blocklyWidgetDiv .goog-palette-cell {",
"height: 13px;","width: 15px;","margin: 0;","border: 0;","text-align: center;","vertical-align: middle;","border-right: 1px solid #666;","font-size: 1px;","}",".blocklyWidgetDiv .goog-palette-colorswatch {","position: relative;","height: 13px;","width: 15px;","border: 1px solid #666;","}",".blocklyWidgetDiv .goog-palette-cell-hover .goog-palette-colorswatch {","border: 1px solid #FFF;","}",".blocklyWidgetDiv .goog-palette-cell-selected .goog-palette-colorswatch {","border: 1px solid #000;","color: #fff;",
+102 -119
View File
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -107,7 +107,8 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT
// Block for blending two colours together.
{
"type": "colour_blend",
"message0": "%{BKY_COLOUR_BLEND_TITLE} %{BKY_COLOUR_BLEND_COLOUR1} %1 %{BKY_COLOUR_BLEND_COLOUR2} %2 %{BKY_COLOUR_BLEND_RATIO} %3",
"message0": "%{BKY_COLOUR_BLEND_TITLE} %{BKY_COLOUR_BLEND_COLOUR1} " +
"%1 %{BKY_COLOUR_BLEND_COLOUR2} %2 %{BKY_COLOUR_BLEND_RATIO} %3",
"args0": [
{
"type": "input_value",
+5 -5
View File
@@ -295,8 +295,8 @@ Blockly.Constants.Logic.TOOLTIPS_BY_OP = {
};
Blockly.Extensions.register('logic_op_tooltip',
Blockly.Extensions.buildTooltipForDropdown(
'OP', Blockly.Constants.Logic.TOOLTIPS_BY_OP));
Blockly.Extensions.buildTooltipForDropdown(
'OP', Blockly.Constants.Logic.TOOLTIPS_BY_OP));
/**
* Mutator methods added to controls_if blocks.
@@ -486,7 +486,7 @@ Blockly.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION = function() {
};
Blockly.Extensions.register('controls_if_tooltip',
Blockly.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION);
Blockly.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION);
/**
* Corrects the logic_compare dropdown label with respect to language direction.
@@ -574,7 +574,7 @@ Blockly.Constants.Logic.LOGIC_COMPARE_EXTENSION = function() {
};
Blockly.Extensions.register('logic_compare',
Blockly.Constants.Logic.LOGIC_COMPARE_EXTENSION);
Blockly.Constants.Logic.LOGIC_COMPARE_EXTENSION);
/**
* Adds type coordination between inputs and output.
@@ -619,4 +619,4 @@ Blockly.Constants.Logic.LOGIC_TERNARY_ONCHANGE_MIXIN = {
};
Blockly.Extensions.registerMixin('logic_ternary',
Blockly.Constants.Logic.LOGIC_TERNARY_ONCHANGE_MIXIN);
Blockly.Constants.Logic.LOGIC_TERNARY_ONCHANGE_MIXIN);
+11 -11
View File
@@ -227,8 +227,8 @@ Blockly.Constants.Loops.WHILE_UNTIL_TOOLTIPS = {
};
Blockly.Extensions.register('controls_whileUntil_tooltip',
Blockly.Extensions.buildTooltipForDropdown(
'MODE', Blockly.Constants.Loops.WHILE_UNTIL_TOOLTIPS));
Blockly.Extensions.buildTooltipForDropdown(
'MODE', Blockly.Constants.Loops.WHILE_UNTIL_TOOLTIPS));
/**
* Tooltips for the 'controls_flow_statements' block, keyed by FLOW value.
@@ -242,8 +242,8 @@ Blockly.Constants.Loops.BREAK_CONTINUE_TOOLTIPS = {
};
Blockly.Extensions.register('controls_flow_tooltip',
Blockly.Extensions.buildTooltipForDropdown(
'FLOW', Blockly.Constants.Loops.BREAK_CONTINUE_TOOLTIPS));
Blockly.Extensions.buildTooltipForDropdown(
'FLOW', Blockly.Constants.Loops.BREAK_CONTINUE_TOOLTIPS));
/**
* Mixin to add a context menu item to create a 'variables_get' block.
@@ -277,15 +277,15 @@ Blockly.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN = {
};
Blockly.Extensions.registerMixin('contextMenu_newGetVariableBlock',
Blockly.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN);
Blockly.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN);
Blockly.Extensions.register('controls_for_tooltip',
Blockly.Extensions.buildTooltipWithFieldValue(
Blockly.Msg.CONTROLS_FOR_TOOLTIP, 'VAR'));
Blockly.Extensions.buildTooltipWithFieldValue(
'%{BKY_CONTROLS_FOR_TOOLTIP}', 'VAR'));
Blockly.Extensions.register('controls_forEach_tooltip',
Blockly.Extensions.buildTooltipWithFieldValue(
Blockly.Msg.CONTROLS_FOREACH_TOOLTIP, 'VAR'));
Blockly.Extensions.buildTooltipWithFieldValue(
'%{BKY_CONTROLS_FOREACH_TOOLTIP}', 'VAR'));
/**
* This mixin adds a check to make sure the 'controls_flow_statements' block
@@ -295,7 +295,7 @@ Blockly.Extensions.register('controls_forEach_tooltip',
* @package
* @readonly
*/
Blockly.Constants.Loops.CONTROL_FLOW_CHECK_IN_LOOP_MIXIN = {
Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN = {
/**
* List of block types that are loops and thus do not need warnings.
* To add a new loop type add this to your code:
@@ -339,4 +339,4 @@ Blockly.Constants.Loops.CONTROL_FLOW_CHECK_IN_LOOP_MIXIN = {
};
Blockly.Extensions.registerMixin('controls_flow_in_loop_check',
Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN);
Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN);
+8 -8
View File
@@ -422,8 +422,8 @@ Blockly.Constants.Math.TOOLTIPS_BY_OP = {
};
Blockly.Extensions.register('math_op_tooltip',
Blockly.Extensions.buildTooltipForDropdown(
'OP', Blockly.Constants.Math.TOOLTIPS_BY_OP));
Blockly.Extensions.buildTooltipForDropdown(
'OP', Blockly.Constants.Math.TOOLTIPS_BY_OP));
/**
@@ -489,8 +489,8 @@ Blockly.Constants.Math.IS_DIVISIBLE_MUTATOR_EXTENSION = function() {
};
Blockly.Extensions.registerMutator('math_is_divisibleby_mutator',
Blockly.Constants.Math.IS_DIVISIBLEBY_MUTATOR_MIXIN,
Blockly.Constants.Math.IS_DIVISIBLE_MUTATOR_EXTENSION);
Blockly.Constants.Math.IS_DIVISIBLEBY_MUTATOR_MIXIN,
Blockly.Constants.Math.IS_DIVISIBLE_MUTATOR_EXTENSION);
/**
* Update the tooltip of 'math_change' block to reference the variable.
@@ -505,8 +505,8 @@ Blockly.Constants.Math.CHANGE_TOOLTIP_EXTENSION = function() {
};
Blockly.Extensions.register('math_change_tooltip',
Blockly.Extensions.buildTooltipWithFieldValue(
Blockly.Msg.MATH_CHANGE_TOOLTIP, 'VAR'));
Blockly.Extensions.buildTooltipWithFieldValue(
'%{BKY_MATH_CHANGE_TOOLTIP}', 'VAR'));
/**
* Mixin with mutator methods to support alternate output based if the
@@ -563,5 +563,5 @@ Blockly.Constants.Math.LIST_MODES_MUTATOR_EXTENSION = function() {
};
Blockly.Extensions.registerMutator('math_modes_of_list_mutator',
Blockly.Constants.Math.LIST_MODES_MUTATOR_MIXIN,
Blockly.Constants.Math.LIST_MODES_MUTATOR_EXTENSION);
Blockly.Constants.Math.LIST_MODES_MUTATOR_MIXIN,
Blockly.Constants.Math.LIST_MODES_MUTATOR_EXTENSION);
+61 -54
View File
@@ -188,8 +188,13 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT
"check": "String"
},
{
"type": "input_dummy",
"name": "AT"
"type": "field_dropdown",
"name": "WHERE",
"options": [["%{BKY_TEXT_CHARAT_FROM_START}", "FROM_START"],
["%{BKY_TEXT_CHARAT_FROM_END}", "FROM_END"],
["%{BKY_TEXT_CHARAT_FIRST}", "FIRST"],
["%{BKY_TEXT_CHARAT_LAST}", "LAST"],
["%{BKY_TEXT_CHARAT_RANDOM}", "RANDOM"]]
}
],
"output": "String",
@@ -562,17 +567,25 @@ Blockly.Blocks['text_reverse'] = {
*/
Blockly.Constants.Text.QUOTE_IMAGE_MIXIN = {
/**
* Image data URI of an LTR opening double quote (same as RTL closing couble quote).
* Image data URI of an LTR opening double quote (same as RTL closing double quote).
* @readonly
*/
QUOTE_IMAGE_LEFT_DATAURI:
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAn0lEQVQI1z3OMa5BURSF4f/cQhAKjUQhuQmFNwGJEUi0RKN5rU7FHKhpjEH3TEMtkdBSCY1EIv8r7nFX9e29V7EBAOvu7RPjwmWGH/VuF8CyN9/OAdvqIXYLvtRaNjx9mMTDyo+NjAN1HNcl9ZQ5oQMM3dgDUqDo1l8DzvwmtZN7mnD+PkmLa+4mhrxVA9fRowBWmVBhFy5gYEjKMfz9AylsaRRgGzvZAAAAAElFTkSuQmCC',
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAA' +
'n0lEQVQI1z3OMa5BURSF4f/cQhAKjUQhuQmFNwGJEUi0RKN5rU7FHKhpjEH3TEMtkdBSCY' +
'1EIv8r7nFX9e29V7EBAOvu7RPjwmWGH/VuF8CyN9/OAdvqIXYLvtRaNjx9mMTDyo+NjAN1' +
'HNcl9ZQ5oQMM3dgDUqDo1l8DzvwmtZN7mnD+PkmLa+4mhrxVA9fRowBWmVBhFy5gYEjKMf' +
'z9AylsaRRgGzvZAAAAAElFTkSuQmCC',
/**
* Image data URI of an LTR closing double quote (same as RTL opening couble quote).
* Image data URI of an LTR closing double quote (same as RTL opening double quote).
* @readonly
*/
QUOTE_IMAGE_RIGHT_DATAURI:
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAqUlEQVQI1z3KvUpCcRiA8ef9E4JNHhI0aFEacm1o0BsI0Slx8wa8gLauoDnoBhq7DcfWhggONDmJJgqCPA7neJ7p934EOOKOnM8Q7PDElo/4x4lFb2DmuUjcUzS3URnGib9qaPNbuXvBO3sGPHJDRG6fGVdMSeWDP2q99FQdFrz26Gu5Tq7dFMzUvbXy8KXeAj57cOklgA+u1B5AoslLtGIHQMaCVnwDnADZIFIrXsoXrgAAAABJRU5ErkJggg==',
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAA' +
'qUlEQVQI1z3KvUpCcRiA8ef9E4JNHhI0aFEacm1o0BsI0Slx8wa8gLauoDnoBhq7DcfWhg' +
'gONDmJJgqCPA7neJ7p934EOOKOnM8Q7PDElo/4x4lFb2DmuUjcUzS3URnGib9qaPNbuXvB' +
'O3sGPHJDRG6fGVdMSeWDP2q99FQdFrz26Gu5Tq7dFMzUvbXy8KXeAj57cOklgA+u1B5Aos' +
'lLtGIHQMaCVnwDnADZIFIrXsoXrgAAAABJRU5ErkJggg==',
/**
* Pixel width of QUOTE_IMAGE_LEFT_DATAURI and QUOTE_IMAGE_RIGHT_DATAURI.
* @readonly
@@ -587,6 +600,7 @@ Blockly.Constants.Text.QUOTE_IMAGE_MIXIN = {
/**
* Inserts appropriate quote images before and after the named field.
* @param {string} fieldName The name of the field to wrap with quotes.
* @this Blockly.Block
*/
quoteField_: function(fieldName) {
for (var i = 0, input; input = this.inputList[i]; i++) {
@@ -607,6 +621,7 @@ Blockly.Constants.Text.QUOTE_IMAGE_MIXIN = {
* @param {boolean} open If the image should be open quote (“ in LTR).
* Otherwise, a closing quote is used (” in LTR).
* @returns {!Blockly.FieldImage} The new field.
* @this Blockly.Block
*/
newQuote_: function(open) {
var isLeft = this.RTL? !open : open;
@@ -749,10 +764,10 @@ Blockly.Constants.Text.TEXT_JOIN_MUTATOR_MIXIN = {
Blockly.Constants.Text.TEXT_JOIN_EXTENSION = function() {
// Add the quote mixin for the itemCount_ = 0 case.
this.mixin(Blockly.Constants.Text.QUOTE_IMAGE_MIXIN);
// initialize the mutator values
// Initialize the mutator values.
this.itemCount_ = 2;
this.updateShape_();
// Configure the mutator ui
// Configure the mutator UI.
this.setMutator(new Blockly.Mutator(['text_create_join_item']));
};
@@ -814,7 +829,7 @@ Blockly.Constants.Text.TEXT_CHARAT_MUTATOR_MIXIN = {
*/
updateAt_: function(isAt) {
// Destroy old 'AT' and 'ORDINAL' inputs.
this.removeInput('AT');
this.removeInput('AT', true);
this.removeInput('ORDINAL', true);
// Create either a value 'AT' input or a dummy input.
if (isAt) {
@@ -823,71 +838,63 @@ Blockly.Constants.Text.TEXT_CHARAT_MUTATOR_MIXIN = {
this.appendDummyInput('ORDINAL')
.appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);
}
} else {
this.appendDummyInput('AT');
}
if (Blockly.Msg.TEXT_CHARAT_TAIL) {
this.removeInput('TAIL', true);
this.appendDummyInput('TAIL')
.appendField(Blockly.Msg.TEXT_CHARAT_TAIL);
}
var menu = new Blockly.FieldDropdown(this.WHERE_OPTIONS, function(value) {
var newAt = (value == 'FROM_START') || (value == 'FROM_END');
// The 'isAt' variable is available due to this function being a closure.
if (newAt != isAt) {
var block = this.sourceBlock_;
block.updateAt_(newAt);
// This menu has been destroyed and replaced. Update the replacement.
block.setFieldValue(value, 'WHERE');
return null;
}
return undefined;
});
this.getInput('AT').appendField(menu, 'WHERE');
this.isAt_ = isAt;
}
};
// Does the initial mutator update of text_charAt and adds the tooltip
Blockly.Constants.Text.TEXT_CHARAT_EXTENSION = function() {
this.WHERE_OPTIONS = [
[Blockly.Msg.TEXT_CHARAT_FROM_START, 'FROM_START'],
[Blockly.Msg.TEXT_CHARAT_FROM_END, 'FROM_END'],
[Blockly.Msg.TEXT_CHARAT_FIRST, 'FIRST'],
[Blockly.Msg.TEXT_CHARAT_LAST, 'LAST'],
[Blockly.Msg.TEXT_CHARAT_RANDOM, 'RANDOM']
];
this.updateAt_(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var where = thisBlock.getFieldValue('WHERE');
var tooltip = Blockly.Msg.TEXT_CHARAT_TOOLTIP;
if (where == 'FROM_START' || where == 'FROM_END') {
var msg = (where == 'FROM_START') ?
Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP :
Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP;
if (msg) {
tooltip += ' ' + msg.replace('%1',
thisBlock.workspace.options.oneBasedIndex ? '#1' : '#0');
}
var dropdown = this.getField('WHERE');
dropdown.setValidator(function(value) {
var newAt = (value == 'FROM_START') || (value == 'FROM_END');
if (newAt != this.isAt_) {
var block = this.sourceBlock_;
block.updateAt_(newAt);
// This menu has been destroyed and replaced. Update the replacement.
block.setFieldValue(value, 'WHERE');
return null;
}
return undefined;
});
this.updateAt_(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var where = thisBlock.getFieldValue('WHERE');
var tooltip = Blockly.Msg.TEXT_CHARAT_TOOLTIP;
if (where == 'FROM_START' || where == 'FROM_END') {
var msg = (where == 'FROM_START') ?
Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP :
Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP;
if (msg) {
tooltip += ' ' + msg.replace('%1',
thisBlock.workspace.options.oneBasedIndex ? '#1' : '#0');
}
return tooltip;
});
}
return tooltip;
});
};
Blockly.Extensions.register('text_indexOf_tooltip',
Blockly.Constants.Text.TEXT_INDEXOF_TOOLTIP_EXTENSION);
Blockly.Constants.Text.TEXT_INDEXOF_TOOLTIP_EXTENSION);
Blockly.Extensions.register('text_quotes',
Blockly.Constants.Text.TEXT_QUOTES_EXTENSION);
Blockly.Constants.Text.TEXT_QUOTES_EXTENSION);
Blockly.Extensions.register('text_append_tooltip',
Blockly.Constants.Text.TEXT_APPEND_TOOLTIP_EXTENSION);
Blockly.Constants.Text.TEXT_APPEND_TOOLTIP_EXTENSION);
Blockly.Extensions.registerMutator('text_join_mutator',
Blockly.Constants.Text.TEXT_JOIN_MUTATOR_MIXIN,
Blockly.Constants.Text.TEXT_JOIN_EXTENSION);
Blockly.Constants.Text.TEXT_JOIN_MUTATOR_MIXIN,
Blockly.Constants.Text.TEXT_JOIN_EXTENSION);
Blockly.Extensions.registerMutator('text_charAt_mutator',
Blockly.Constants.Text.TEXT_CHARAT_MUTATOR_MIXIN,
Blockly.Constants.Text.TEXT_CHARAT_EXTENSION);
Blockly.Constants.Text.TEXT_CHARAT_MUTATOR_MIXIN,
Blockly.Constants.Text.TEXT_CHARAT_EXTENSION);
+16 -60
View File
@@ -34,7 +34,7 @@
# The uncompressed file is a script that loads in each of Blockly's core files
# one by one. This takes much longer for a browser to load, but is useful
# when debugging code since line numbers are meaningful and variables haven't
# been renamed. The uncompressed file also allows for a faster developement
# been renamed. The uncompressed file also allows for a faster development
# cycle since there is no need to rebuild or recompile, just reload.
#
# The second pair are:
@@ -45,10 +45,11 @@
#
# This script also generates:
# blocks_compressed.js: The compressed Blockly language blocks.
# javascript_compressed.js: The compressed Javascript generator.
# javascript_compressed.js: The compressed JavaScript generator.
# python_compressed.js: The compressed Python generator.
# dart_compressed.js: The compressed Dart generator.
# php_compressed.js: The compressed PHP generator.
# lua_compressed.js: The compressed Lua generator.
# dart_compressed.js: The compressed Dart generator.
# msg/js/<LANG>.js for every language <LANG> defined in msg/js/<LANG>.json.
import sys
@@ -60,10 +61,9 @@ for arg in sys.argv[1:len(sys.argv)]:
if (arg != 'core' and
arg != 'accessible' and
arg != 'generators' and
arg != 'langfiles' and
arg != 'demo'):
raise Exception("Invalid argument: \"" + arg + "\". Usage: build.py <0 or more of accessible," +
" core, generators, langfiles, demo>")
arg != 'langfiles'):
raise Exception("Invalid argument: \"" + arg + "\". Usage: build.py "
"<0 or more of accessible, core, generators, langfiles>")
import errno, glob, httplib, json, os, re, subprocess, threading, urllib
@@ -212,49 +212,8 @@ class Gen_compressed(threading.Thread):
self.gen_generator("javascript")
self.gen_generator("python")
self.gen_generator("php")
self.gen_generator("dart")
self.gen_generator("lua")
if ('demo' in self.bundles):
self.gen_together()
def gen_together(self):
target_filename = os.path.join("demos", "fixed-advanced", "main_compressed.js")
# Define the parameters for the POST request.
params = [
("compilation_level", "ADVANCED_OPTIMIZATIONS"),
("use_closure_library", "true"),
("generate_exports", "true"),
("output_format", "json"),
("output_info", "compiled_code"),
("output_info", "warnings"),
("output_info", "errors"),
("output_info", "statistics"),
# debug options (to make the uglified code readable)
# ("formatting", "pretty_print"),
# ("formatting", "print_input_delimiter"),
# ("debug", "true"),
]
# Read in all the source files.
filenames = calcdeps.CalculateDependencies(self.search_paths,
[os.path.join("demos", "fixed-advanced", "main.js")])
filenames.sort() # Deterministic build.
for filename in filenames:
# Filter out the Closure files (the compiler will add them).
if filename.startswith(os.pardir + os.sep): # '../'
continue
f = open(filename)
params.append(("js_code", "".join(f.readlines())))
f.close()
externs = [os.path.join("externs", "svg-externs.js")]
for filename in externs:
f = open(filename)
params.append(("js_externs", "".join(f.readlines())))
f.close()
self.do_compile(params, target_filename, filenames, "")
self.gen_generator("dart")
def gen_core(self):
target_filename = "blockly_compressed.js"
@@ -403,7 +362,12 @@ class Gen_compressed(threading.Thread):
conn.close()
# Parse the JSON response.
json_data = json.loads(json_str)
try:
json_data = json.loads(json_str)
except ValueError:
print("ERROR: Could not parse JSON for %s. Raw data:" % target_filename)
print(json_str)
return
def file_lookup(name):
if not name.startswith("Input_"):
@@ -610,16 +574,8 @@ developers.google.com/blockly/guides/modify/web/closure""")
if ('accessible' in args):
Gen_uncompressed(full_search_paths, 'blockly_accessible_uncompressed.js').start()
if ('demo' in args):
all_search_paths = calcdeps.ExpandDirectories(
["accessible", "core", "blocks", os.path.join("demos", "fixed-advanced"), os.path.join("msg", "js"), os.path.join(os.path.pardir, "closure-library")])
all_search_paths.sort() # Deterministic build.
print("Compressing " + str(len(all_search_paths)) + " files...")
Gen_compressed(all_search_paths, args).start()
else:
# Compressed is limited by network and server speed.
Gen_compressed(full_search_paths, args).start()
# Compressed is limited by network and server speed.
Gen_compressed(full_search_paths, args).start()
# This is run locally in a separate thread
# defaultlangfiles checks for changes in the msg files, while manually asking
+20 -11
View File
@@ -48,7 +48,7 @@ goog.require('goog.string');
* @param {?string} prototypeName Name of the language object containing
* type-specific functions for this block.
* @param {string=} opt_id Optional ID. Use this ID if provided, otherwise
* create a new id.
* create a new ID.
* @constructor
*/
Blockly.Block = function(workspace, prototypeName, opt_id) {
@@ -261,7 +261,7 @@ Blockly.Block.prototype.dispose = function(healStack) {
/**
* Unplug this block from its superior block. If this block is a statement,
* optionally reconnect the block underneath with the block on top.
* @param {boolean} opt_healStack Disconnect child statement and reconnect
* @param {boolean=} opt_healStack Disconnect child statement and reconnect
* stack. Defaults to false.
*/
Blockly.Block.prototype.unplug = function(opt_healStack) {
@@ -293,10 +293,13 @@ Blockly.Block.prototype.unplug = function(opt_healStack) {
/**
* Returns all connections originating from this block.
* @param {boolean} all If true, return all connections even hidden ones.
* @return {!Array.<!Blockly.Connection>} Array of connections.
* @private
*/
Blockly.Block.prototype.getConnections_ = function() {
Blockly.Block.prototype.getConnections_ = function(
/* eslint-disable no-unused-vars */ all
/* eslint-enable no-unused-vars */) {
var myConnections = [];
if (this.outputConnection) {
myConnections.push(this.outputConnection);
@@ -608,7 +611,7 @@ Blockly.Block.prototype.getColour = function() {
*/
Blockly.Block.prototype.getHue = function() {
return this.hue_;
}
};
/**
* Change the colour of a block.
@@ -619,9 +622,9 @@ Blockly.Block.prototype.setColour = function(colour) {
if (!isNaN(hue) && 0 <= hue && hue <= 360) {
this.hue_ = hue;
this.colour_ = Blockly.hueToRgb(hue);
} else if (goog.isString(colour) && colour.match(/^#[0-9a-fA-F]{6}$/)) {
} else if (goog.isString(colour) && /^#[0-9a-fA-F]{6}$/.test(colour)) {
this.colour_ = colour;
// Only store hue if colour is set as a hue
// Only store hue if colour is set as a hue.
this.hue_ = null;
} else {
throw 'Invalid colour: ' + colour;
@@ -727,7 +730,7 @@ Blockly.Block.prototype.setFieldValue = function(newValue, name) {
/**
* Set whether this block can chain onto the bottom of another block.
* @param {boolean} newBoolean True if there can be a previous statement.
* @param {string|Array.<string>|null|undefined} opt_check Statement type or
* @param {(string|Array.<string>|null)=} opt_check Statement type or
* list of statement types. Null/undefined if any type could be connected.
*/
Blockly.Block.prototype.setPreviousStatement = function(newBoolean, opt_check) {
@@ -755,7 +758,7 @@ Blockly.Block.prototype.setPreviousStatement = function(newBoolean, opt_check) {
/**
* Set whether another block can chain onto the bottom of this block.
* @param {boolean} newBoolean True if there can be a next statement.
* @param {string|Array.<string>|null|undefined} opt_check Statement type or
* @param {(string|Array.<string>|null)=} opt_check Statement type or
* list of statement types. Null/undefined if any type could be connected.
*/
Blockly.Block.prototype.setNextStatement = function(newBoolean, opt_check) {
@@ -780,7 +783,7 @@ Blockly.Block.prototype.setNextStatement = function(newBoolean, opt_check) {
/**
* Set whether this block returns a value.
* @param {boolean} newBoolean True if there is an output.
* @param {string|Array.<string>|null|undefined} opt_check Returned type or list
* @param {(string|Array.<string>|null)=} opt_check Returned type or list
* of returned types. Null or undefined if any type could be returned
* (e.g. variable get).
*/
@@ -1423,8 +1426,12 @@ Blockly.Block.prototype.setCommentText = function(text) {
/**
* Set this block's warning text.
* @param {?string} text The text, or null to delete.
* @param {string=} opt_id An optional ID for the warning text to be able to
* maintain multiple warnings.
*/
Blockly.Block.prototype.setWarningText = function(/* text */) {
Blockly.Block.prototype.setWarningText = function(text,
/* eslint-disable no-unused-vars */ opt_id
/* eslint-enable no-unused-vars */) {
// NOP.
};
@@ -1432,7 +1439,9 @@ Blockly.Block.prototype.setWarningText = function(/* text */) {
* Give this block a mutator dialog.
* @param {Blockly.Mutator} mutator A mutator dialog instance or null to remove.
*/
Blockly.Block.prototype.setMutator = function(/* mutator */) {
Blockly.Block.prototype.setMutator = function(
/* eslint-disable no-unused-vars */ mutator
/* eslint-enable no-unused-vars */) {
// NOP.
};
+4 -4
View File
@@ -20,10 +20,10 @@
/**
* @fileoverview A class that manages a surface for dragging blocks. When a
* block drag is started, we move the block (and children) to a separate dom
* block drag is started, we move the block (and children) to a separate DOM
* element that we move around using translate3d. At the end of the drag, the
* blocks are put back in into the svg they came from. This helps performance by
* avoiding repainting the entire svg on every mouse move while dragging blocks.
* blocks are put back in into the SVG they came from. This helps performance by
* avoiding repainting the entire SVG on every mouse move while dragging blocks.
* @author picklesrus
*/
@@ -202,7 +202,7 @@ Blockly.BlockDragSurfaceSvg.prototype.getCurrentBlock = function() {
* element.
* If the block is being deleted it doesn't need to go back to the original
* surface, since it would be removed immediately during dispose.
* @param {Element} opt_newSurface Surface the dragging blocks should be moved
* @param {Element=} opt_newSurface Surface the dragging blocks should be moved
* to, or null if the blocks should be removed from this surface without
* being moved to a different surface.
*/
+9 -12
View File
@@ -326,9 +326,8 @@ Blockly.BlockSvg.prototype.render = function(opt_bubble) {
* @return {number} X-coordinate of the end of the field row (plus a gap).
* @private
*/
Blockly.BlockSvg.prototype.renderFields_ =
function(fieldList, cursorX, cursorY) {
/* eslint-disable indent */
Blockly.BlockSvg.prototype.renderFields_ = function(fieldList,
cursorX, cursorY) {
cursorY += Blockly.BlockSvg.INLINE_PADDING_Y;
if (this.RTL) {
cursorX = -cursorX;
@@ -356,7 +355,7 @@ Blockly.BlockSvg.prototype.renderFields_ =
}
}
return this.RTL ? -cursorX : cursorX;
}; /* eslint-enable indent */
};
/**
* Computes the height and widths for each row and field.
@@ -614,9 +613,8 @@ Blockly.BlockSvg.prototype.renderMoveConnections_ = function() {
* @param {number} rightEdge Minimum width of block.
* @private
*/
Blockly.BlockSvg.prototype.renderDrawTop_ =
function(steps, highlightSteps, rightEdge) {
/* eslint-disable indent */
Blockly.BlockSvg.prototype.renderDrawTop_ = function(steps,
highlightSteps, rightEdge) {
// Position the cursor at the top-left starting point.
if (this.squareTopLeftCorner_) {
steps.push('m 0,0');
@@ -651,7 +649,7 @@ Blockly.BlockSvg.prototype.renderDrawTop_ =
steps.push('H', rightEdge);
highlightSteps.push('H', rightEdge - 0.5);
this.width = rightEdge;
}; /* eslint-enable indent */
};
/**
* Render the right edge of the block.
@@ -916,9 +914,8 @@ Blockly.BlockSvg.prototype.renderDrawRight_ = function(steps, highlightSteps,
* @param {number} cursorY Height of block.
* @private
*/
Blockly.BlockSvg.prototype.renderDrawBottom_ =
function(steps, highlightSteps, cursorY) {
/* eslint-disable indent */
Blockly.BlockSvg.prototype.renderDrawBottom_ = function(steps,
highlightSteps, cursorY) {
this.height += cursorY + 1; // Add one for the shadow.
if (this.nextConnection) {
steps.push('H', (Blockly.BlockSvg.NOTCH_WIDTH + (this.RTL ? 0.5 : - 0.5)) +
@@ -954,7 +951,7 @@ Blockly.BlockSvg.prototype.renderDrawBottom_ =
'0.5,' + (cursorY - Blockly.BlockSvg.CORNER_RADIUS));
}
}
}; /* eslint-enable indent */
};
/**
* Render the left edge of the block.
+44 -79
View File
@@ -47,7 +47,7 @@ goog.require('goog.userAgent');
* @param {?string} prototypeName Name of the language object containing
* type-specific functions for this block.
* @param {string=} opt_id Optional ID. Use this ID if provided, otherwise
* create a new id.
* create a new ID.
* @extends {Blockly.Block}
* @constructor
*/
@@ -118,6 +118,14 @@ Blockly.BlockSvg.prototype.width = 0;
*/
Blockly.BlockSvg.prototype.dragStartXY_ = null;
/**
* Map from IDs for warnings text to PIDs of functions to apply them.
* Used to be able to maintain multiple warnings.
* @type {Object.<string, number>}
* @private
*/
Blockly.BlockSvg.prototype.warningTextDb_ = null;
/**
* Constant for identifying rows that are to be rendered inline.
* Don't collide with Blockly.INPUT_VALUE and friends.
@@ -244,7 +252,7 @@ Blockly.BlockSvg.prototype.setParent = function(newParent) {
// Move this block up the DOM. Keep track of x/y translations.
var xy = this.getRelativeToSurfaceXY();
this.workspace.getCanvas().appendChild(svgRoot);
svgRoot.setAttribute('transform', 'translate(' + xy.x + ',' + xy.y + ')');
svgRoot.setAttribute('transform', 'translate' + xy);
}
Blockly.Field.startCache();
@@ -375,7 +383,7 @@ Blockly.BlockSvg.prototype.moveDuringDrag = function(newLoc) {
if (this.useDragSurface_) {
this.workspace.blockDragSurface_.translateSurface(newLoc.x, newLoc.y);
} else {
this.svgGroup_.translate_ = 'translate(' + newLoc.x + ',' + newLoc.y + ')';
this.svgGroup_.translate_ = 'translate' + newLoc;
this.svgGroup_.setAttribute('transform',
this.svgGroup_.translate_ + this.svgGroup_.skew_);
}
@@ -526,7 +534,7 @@ Blockly.BlockSvg.prototype.tab = function(start, forward) {
/**
* Create an ordered list of all text fields and connected inputs.
* @return {!Array<!Blockly.FieldTextInput|!Blockly.Input>} The ordered list.
* @return {!Array.<!Blockly.FieldTextInput|!Blockly.Input>} The ordered list.
* @private
*/
Blockly.BlockSvg.prototype.createTabList_ = function() {
@@ -586,35 +594,10 @@ Blockly.BlockSvg.prototype.showContextMenu_ = function(e) {
var menuOptions = [];
if (this.isDeletable() && this.isMovable() && !block.isInFlyout) {
// Option to duplicate this block.
var duplicateOption = {
text: Blockly.Msg.DUPLICATE_BLOCK,
enabled: true,
callback: function() {
Blockly.duplicate_(block);
}
};
if (this.getDescendants().length > this.workspace.remainingCapacity()) {
duplicateOption.enabled = false;
}
menuOptions.push(duplicateOption);
menuOptions.push(Blockly.ContextMenu.blockDuplicateOption(block));
if (this.isEditable() && !this.collapsed_ &&
this.workspace.options.comments) {
// Option to add/remove a comment.
var commentOption = {enabled: !goog.userAgent.IE};
if (this.comment) {
commentOption.text = Blockly.Msg.REMOVE_COMMENT;
commentOption.callback = function() {
block.setCommentText(null);
};
} else {
commentOption.text = Blockly.Msg.ADD_COMMENT;
commentOption.callback = function() {
block.setCommentText('');
};
}
menuOptions.push(commentOption);
menuOptions.push(Blockly.ContextMenu.blockCommentOption(block));
}
// Option to make block inline.
@@ -669,35 +652,10 @@ Blockly.BlockSvg.prototype.showContextMenu_ = function(e) {
menuOptions.push(disableOption);
}
// Option to delete this block.
// Count the number of blocks that are nested in this block.
var descendantCount = this.getDescendants().length;
var nextBlock = this.getNextBlock();
if (nextBlock) {
// Blocks in the current stack would survive this block's deletion.
descendantCount -= nextBlock.getDescendants().length;
}
var deleteOption = {
text: descendantCount == 1 ? Blockly.Msg.DELETE_BLOCK :
Blockly.Msg.DELETE_X_BLOCKS.replace('%1', String(descendantCount)),
enabled: true,
callback: function() {
Blockly.Events.setGroup(true);
block.dispose(true, true);
Blockly.Events.setGroup(false);
}
};
menuOptions.push(deleteOption);
menuOptions.push(Blockly.ContextMenu.blockDeleteOption(block));
}
// Option to get help.
var url = goog.isFunction(this.helpUrl) ? this.helpUrl() : this.helpUrl;
var helpOption = {enabled: !!url};
helpOption.text = Blockly.Msg.HELP;
helpOption.callback = function() {
block.showHelp_();
};
menuOptions.push(helpOption);
menuOptions.push(Blockly.ContextMenu.blockHelpOption(block));
// Allow the block to add or modify menuOptions.
if (this.customContextMenu) {
@@ -848,6 +806,14 @@ Blockly.BlockSvg.prototype.dispose = function(healStack, animate) {
// Stop rerendering.
this.rendered = false;
// Clear pending warnings.
if (this.warningTextDb_) {
for (var n in this.warningTextDb_) {
clearTimeout(this.warningTextDb_[n]);
}
this.warningTextDb_ = null;
}
Blockly.Events.disable();
try {
var icons = this.getIcons();
@@ -1140,30 +1106,30 @@ Blockly.BlockSvg.prototype.setCommentText = function(text) {
* maintain multiple warnings.
*/
Blockly.BlockSvg.prototype.setWarningText = function(text, opt_id) {
if (!this.setWarningText.pid_) {
if (!this.warningTextDb_) {
// Create a database of warning PIDs.
// Only runs once per block (and only those with warnings).
this.setWarningText.pid_ = Object.create(null);
this.warningTextDb_ = Object.create(null);
}
var id = opt_id || '';
if (!id) {
// Kill all previous pending processes, this edit supersedes them all.
for (var n in this.setWarningText.pid_) {
clearTimeout(this.setWarningText.pid_[n]);
delete this.setWarningText.pid_[n];
for (var n in this.warningTextDb_) {
clearTimeout(this.warningTextDb_[n]);
delete this.warningTextDb_[n];
}
} else if (this.setWarningText.pid_[id]) {
} else if (this.warningTextDb_[id]) {
// Only queue up the latest change. Kill any earlier pending process.
clearTimeout(this.setWarningText.pid_[id]);
delete this.setWarningText.pid_[id];
clearTimeout(this.warningTextDb_[id]);
delete this.warningTextDb_[id];
}
if (this.workspace.isDragging()) {
// Don't change the warning text during a drag.
// Wait until the drag finishes.
var thisBlock = this;
this.setWarningText.pid_[id] = setTimeout(function() {
this.warningTextDb_[id] = setTimeout(function() {
if (thisBlock.workspace) { // Check block wasn't deleted.
delete thisBlock.setWarningText.pid_[id];
delete thisBlock.warningTextDb_[id];
thisBlock.setWarningText(text, id);
}
}, 100);
@@ -1194,7 +1160,7 @@ Blockly.BlockSvg.prototype.setWarningText = function(text, opt_id) {
}
this.warning.setText(/** @type {string} */ (text), id);
} else {
// Dispose all warnings if no id is given.
// Dispose all warnings if no ID is given.
if (this.warning && !id) {
this.warning.dispose();
changedState = true;
@@ -1311,8 +1277,8 @@ Blockly.BlockSvg.prototype.setColour = function(colour) {
/**
* Move this block to the front of the visible workspace.
* <g> tags do not respect z-index so svg renders them in the
* order that they are in the dom. By placing this block first within the
* <g> tags do not respect z-index so SVG renders them in the
* order that they are in the DOM. By placing this block first within the
* block group's <g>, it will render on top of any other blocks.
* @package
*/
@@ -1328,12 +1294,11 @@ Blockly.BlockSvg.prototype.bringToFront = function() {
/**
* Set whether this block can chain onto the bottom of another block.
* @param {boolean} newBoolean True if there can be a previous statement.
* @param {string|Array.<string>|null|undefined} opt_check Statement type or
* @param {(string|Array.<string>|null)=} opt_check Statement type or
* list of statement types. Null/undefined if any type could be connected.
*/
Blockly.BlockSvg.prototype.setPreviousStatement =
function(newBoolean, opt_check) {
/* eslint-disable indent */
Blockly.BlockSvg.prototype.setPreviousStatement = function(newBoolean,
opt_check) {
Blockly.BlockSvg.superClass_.setPreviousStatement.call(this, newBoolean,
opt_check);
@@ -1341,12 +1306,12 @@ Blockly.BlockSvg.prototype.setPreviousStatement =
this.render();
this.bumpNeighbours_();
}
}; /* eslint-enable indent */
};
/**
* Set whether another block can chain onto the bottom of this block.
* @param {boolean} newBoolean True if there can be a next statement.
* @param {string|Array.<string>|null|undefined} opt_check Statement type or
* @param {(string|Array.<string>|null)=} opt_check Statement type or
* list of statement types. Null/undefined if any type could be connected.
*/
Blockly.BlockSvg.prototype.setNextStatement = function(newBoolean, opt_check) {
@@ -1362,7 +1327,7 @@ Blockly.BlockSvg.prototype.setNextStatement = function(newBoolean, opt_check) {
/**
* Set whether this block returns a value.
* @param {boolean} newBoolean True if there is an output.
* @param {string|Array.<string>|null|undefined} opt_check Returned type or list
* @param {(string|Array.<string>|null)=} opt_check Returned type or list
* of returned types. Null or undefined if any type could be returned
* (e.g. variable get).
*/
@@ -1492,7 +1457,7 @@ Blockly.BlockSvg.prototype.bumpNeighbours_ = function() {
if (!this.workspace) {
return; // Deleted block.
}
if (Blockly.dragMode_ != Blockly.DRAG_NONE) {
if (this.workspace.isDragging()) {
return; // Don't bump blocks during a drag.
}
var rootBlock = this.getRootBlock();
+8 -5
View File
@@ -58,7 +58,10 @@ goog.require('goog.userAgent');
// Turn off debugging when compiled.
// Unused within the Blockly library, but used in Closure.
/* eslint-disable no-unused-vars */
var CLOSURE_DEFINES = {'goog.DEBUG': false};
/* eslint-enable no-unused-vars */
/**
* The main workspace most recently used.
@@ -395,14 +398,14 @@ Blockly.defineBlocksWithJsonArray = function(jsonArray) {
* Bind an event to a function call. When calling the function, verifies that
* it belongs to the touch stream that is currently being processed, and splits
* multitouch events into multiple events as needed.
* @param {!Node} node Node upon which to listen.
* @param {!EventTarget} node Node upon which to listen.
* @param {string} name Event name to listen to (e.g. 'mousedown').
* @param {Object} thisObject The value of 'this' in the function.
* @param {!Function} func Function to call when event is triggered.
* @param {boolean} opt_noCaptureIdentifier True if triggering on this event
* @param {boolean=} opt_noCaptureIdentifier True if triggering on this event
* should not block execution of other event handlers on this touch or other
* simultaneous touches.
* @param {boolean} opt_noPreventDefault True if triggering on this event
* @param {boolean=} opt_noPreventDefault True if triggering on this event
* should prevent the default handler. False by default. If
* opt_noPreventDefault is provided, opt_noCaptureIdentifier must also be
* provided.
@@ -461,7 +464,7 @@ Blockly.bindEventWithChecks_ = function(node, name, thisObject, func,
* simultaneous event processing.
* @deprecated in favor of bindEventWithChecks_, but preserved for external
* users.
* @param {!Node} node Node upon which to listen.
* @param {!EventTarget} node Node upon which to listen.
* @param {string} name Event name to listen to (e.g. 'mousedown').
* @param {Object} thisObject The value of 'this' in the function.
* @param {!Function} func Function to call when event is triggered.
@@ -528,7 +531,7 @@ Blockly.unbindEvent_ = function(bindData) {
* @return {boolean} True if number, false otherwise.
*/
Blockly.isNumber = function(str) {
return !!str.match(/^\s*-?\d+(\.\d+)?\s*$/);
return /^\s*-?\d+(\.\d+)?\s*$/.test(str);
};
// IE9 does not have a console. Create a stub to stop errors.
+1 -1
View File
@@ -32,6 +32,6 @@ goog.provide('Blockly.Blocks');
/*
* A mapping of block type names to block prototype objects.
* @type {!Object<string,Object>}
* @type {!Object.<string,Object>}
*/
Blockly.Blocks = new Object(null);
+12 -7
View File
@@ -70,19 +70,21 @@ Blockly.Comment.prototype.drawIcon_ = function(group) {
// Circle.
Blockly.utils.createSvgElement('circle',
{'class': 'blocklyIconShape', 'r': '8', 'cx': '8', 'cy': '8'},
group);
group);
// Can't use a real '?' text character since different browsers and operating
// systems render it differently.
// Body of question mark.
Blockly.utils.createSvgElement('path',
{'class': 'blocklyIconSymbol',
'd': 'm6.8,10h2c0.003,-0.617 0.271,-0.962 0.633,-1.266 2.875,-2.405 0.607,-5.534 -3.765,-3.874v1.7c3.12,-1.657 3.698,0.118 2.336,1.25 -1.201,0.998 -1.201,1.528 -1.204,2.19z'},
group);
'd': 'm6.8,10h2c0.003,-0.617 0.271,-0.962 0.633,-1.266 2.875,-2.405' +
'0.607,-5.534 -3.765,-3.874v1.7c3.12,-1.657 3.698,0.118 2.336,1.25' +
'-1.201,0.998 -1.201,1.528 -1.204,2.19z'},
group);
// Dot of question mark.
Blockly.utils.createSvgElement('rect',
{'class': 'blocklyIconSymbol',
'x': '6.8', 'y': '10.78', 'height': '2', 'width': '2'},
group);
'x': '6.8', 'y': '10.78', 'height': '2', 'width': '2'},
group);
};
/**
@@ -117,7 +119,9 @@ Blockly.Comment.prototype.createEditor_ = function() {
Blockly.bindEventWithChecks_(textarea, 'wheel', this, function(e) {
e.stopPropagation();
});
Blockly.bindEventWithChecks_(textarea, 'change', this, function(e) {
Blockly.bindEventWithChecks_(textarea, 'change', this, function(
/* eslint-disable no-unused-vars */ e
/* eslint-enable no-unused-vars */) {
if (this.text_ != textarea.value) {
Blockly.Events.fire(new Blockly.Events.BlockChange(
this.block_, 'comment', null, this.text_, textarea.value));
@@ -207,7 +211,8 @@ Blockly.Comment.prototype.setVisible = function(visible) {
* @param {!Event} e Mouse up event.
* @private
*/
Blockly.Comment.prototype.textareaFocus_ = function(e) {
Blockly.Comment.prototype.textareaFocus_ = function(
/* eslint-disable no-unused-vars */ e /* eslint-enable no-unused-vars */) {
// Ideally this would be hooked to the focus event for the comment.
// However doing so in Firefox swallows the cursor for unknown reasons.
// So this is hooked to mouseup instead. No big deal.
+96
View File
@@ -201,3 +201,99 @@ Blockly.ContextMenu.callbackFactory = function(block, xml) {
newBlock.select();
};
};
// Helper functions for creating context menu options.
/**
* Make a context menu option for deleting the current block.
* @param {!Blockly.BlockSvg} block The block where the right-click originated.
* @return {!Object} A menu option, containing text, enabled, and a callback.
* @package
*/
Blockly.ContextMenu.blockDeleteOption = function(block) {
// Option to delete this block but not blocks lower in the stack.
// Count the number of blocks that are nested in this block.
var descendantCount = block.getDescendants(true).length;
var nextBlock = block.getNextBlock();
if (nextBlock) {
// Blocks in the current stack would survive this block's deletion.
descendantCount -= nextBlock.getDescendants(true).length;
}
var deleteOption = {
text: descendantCount == 1 ? Blockly.Msg.DELETE_BLOCK :
Blockly.Msg.DELETE_X_BLOCKS.replace('%1', String(descendantCount)),
enabled: true,
callback: function() {
Blockly.Events.setGroup(true);
block.dispose(true, true);
Blockly.Events.setGroup(false);
}
};
return deleteOption;
};
/**
* Make a context menu option for showing help for the current block.
* @param {!Blockly.BlockSvg} block The block where the right-click originated.
* @return {!Object} A menu option, containing text, enabled, and a callback.
* @package
*/
Blockly.ContextMenu.blockHelpOption = function(block) {
var url = goog.isFunction(block.helpUrl) ? block.helpUrl() : block.helpUrl;
var helpOption = {
enabled: !!url,
text: Blockly.Msg.HELP,
callback: function() {
block.showHelp_();
}
};
return helpOption;
};
/**
* Make a context menu option for duplicating the current block.
* @param {!Blockly.BlockSvg} block The block where the right-click originated.
* @return {!Object} A menu option, containing text, enabled, and a callback.
* @package
*/
Blockly.ContextMenu.blockDuplicateOption = function(block) {
var enabled = true;
if (block.getDescendants().length > block.workspace.remainingCapacity()) {
enabled = false;
}
var duplicateOption = {
text: Blockly.Msg.DUPLICATE_BLOCK,
enabled: enabled,
callback: function() {
Blockly.duplicate_(block);
}
};
return duplicateOption;
};
/**
* Make a context menu option for adding or removing comments on the current
* block.
* @param {!Blockly.BlockSvg} block The block where the right-click originated.
* @return {!Object} A menu option, containing text, enabled, and a callback.
* @package
*/
Blockly.ContextMenu.blockCommentOption = function(block) {
var commentOption = {
enabled: !goog.userAgent.IE
};
// If there's already a comment, add an option to delete it.
if (block.comment) {
commentOption.text = Blockly.Msg.REMOVE_COMMENT;
commentOption.callback = function() {
block.setCommentText(null);
};
} else {
// If there's no comment, add an option to create a comment.
commentOption.text = Blockly.Msg.ADD_COMMENT;
commentOption.callback = function() {
block.setCommentText('');
};
}
return commentOption;
};
+6
View File
@@ -171,6 +171,12 @@ Blockly.DraggedConnectionManager.prototype.update = function(dxy, deleteArea) {
this.topBlock_.isDeletable();
this.wouldDeleteBlock_ = wouldDelete && !wouldConnect;
// Get rid of highlighting so we don't sent mixed messages.
if (wouldDelete && this.closestConnection_) {
this.closestConnection_.unhighlight();
this.closestConnection_ = null;
}
if (!this.wouldDeleteBlock_ && closestConnectionChanged &&
this.closestConnection_) {
this.addHighlighting_();
+60 -20
View File
@@ -42,7 +42,7 @@ goog.require('goog.math.Coordinate');
Blockly.Events.group_ = '';
/**
* Sets whether events should be added to the undo stack.
* Sets whether the next event should be added to the undo stack.
* @type {boolean}
*/
Blockly.Events.recordUndo = true;
@@ -201,10 +201,15 @@ Blockly.Events.filter = function(queueIn, forward) {
lastEvent.element == 'warningOpen')) {
// Merge click events.
lastEvent.newValue = event.newValue;
} else {
// Collision: newer events should merge into this event to maintain order
hash[key] = event;
mergedQueue.push(event);
}
}
}
queue = mergedQueue;
// Filter out any events that have become null due to merging.
queue = mergedQueue.filter(function(e) { return !e.isNull(); });
if (!forward) {
// Restore undo order.
queue.reverse();
@@ -305,7 +310,7 @@ Blockly.Events.fromJson = function(json, workspace) {
event = new Blockly.Events.Delete(null);
break;
case Blockly.Events.CHANGE:
event = new Blockly.Events.Change(null);
event = new Blockly.Events.Change(null, '', '', '', '');
break;
case Blockly.Events.MOVE:
event = new Blockly.Events.Move(null);
@@ -317,7 +322,7 @@ Blockly.Events.fromJson = function(json, workspace) {
event = new Blockly.Events.VarDelete(null);
break;
case Blockly.Events.VAR_RENAME:
event = new Blockly.Events.VarRename(null);
event = new Blockly.Events.VarRename(null, '');
break;
case Blockly.Events.UI:
event = new Blockly.Events.Ui(null);
@@ -336,11 +341,44 @@ Blockly.Events.fromJson = function(json, workspace) {
* @constructor
*/
Blockly.Events.Abstract = function(elem) {
/**
* The block id for the block this event pertains to, if appropriate for the
* event type.
* @type {string|undefined}
*/
this.blockId = undefined;
/**
* The variable id for the variable this event pertains to. Only set in
* VarCreate, VarDelete, and VarRename events.
* @type {string|undefined}
*/
this.varId = undefined;
/**
* The workspace identifier for this event.
* @type {string|undefined}
*/
this.workspaceId = undefined;
/**
* The event group id for the group this event belongs to. Groups define
* events that should be treated as an single action from the user's
* perspective, and should be undone together.
* @type {string}
*/
this.group = undefined;
/**
* Sets whether the event should be added to the undo stack.
* @type {boolean}
*/
this.recordUndo = undefined;
if (elem instanceof Blockly.Block) {
this.blockId = elem.id;
this.workspaceId = elem.workspace.id;
}
else if (elem instanceof Blockly.VariableModel){
} else if (elem instanceof Blockly.VariableModel) {
this.workspaceId = elem.workspace.id;
this.varId = elem.getId();
}
@@ -390,7 +428,9 @@ Blockly.Events.Abstract.prototype.isNull = function() {
* Run an event.
* @param {boolean} forward True if run forward, false if run backward (undo).
*/
Blockly.Events.Abstract.prototype.run = function(forward) {
Blockly.Events.Abstract.prototype.run = function(
/* eslint-disable no-unused-vars */ forward
/* eslint-enable no-unused-vars */) {
// Defined by subclasses.
};
@@ -482,7 +522,7 @@ Blockly.Events.Create.prototype.run = function(forward) {
block.dispose(false, false);
} else if (id == this.blockId) {
// Only complain about root-level block.
console.warn("Can't uncreate non-existant block: " + id);
console.warn("Can't uncreate non-existent block: " + id);
}
}
}
@@ -558,7 +598,7 @@ Blockly.Events.Delete.prototype.run = function(forward) {
block.dispose(false, false);
} else if (id == this.blockId) {
// Only complain about root-level block.
console.warn("Can't delete non-existant block: " + id);
console.warn("Can't delete non-existent block: " + id);
}
}
} else {
@@ -573,8 +613,8 @@ Blockly.Events.Delete.prototype.run = function(forward) {
* @param {Blockly.Block} block The changed block. Null for a blank event.
* @param {string} element One of 'field', 'comment', 'disabled', etc.
* @param {?string} name Name of input or field affected, or null.
* @param {string} oldValue Previous value of element.
* @param {string} newValue New value of element.
* @param {*} oldValue Previous value of element.
* @param {*} newValue New value of element.
* @extends {Blockly.Events.Abstract}
* @constructor
*/
@@ -595,8 +635,8 @@ goog.inherits(Blockly.Events.Change, Blockly.Events.Abstract);
* @param {Blockly.Block} block The changed block. Null for a blank event.
* @param {string} element One of 'field', 'comment', 'disabled', etc.
* @param {?string} name Name of input or field affected, or null.
* @param {string} oldValue Previous value of element.
* @param {string} newValue New value of element.
* @param {*} oldValue Previous value of element.
* @param {*} newValue New value of element.
* @extends {Blockly.Events.Abstract}
* @constructor
*/
@@ -649,7 +689,7 @@ Blockly.Events.Change.prototype.run = function(forward) {
var workspace = this.getEventWorkspace_();
var block = workspace.getBlockById(this.blockId);
if (!block) {
console.warn("Can't change non-existant block: " + this.blockId);
console.warn("Can't change non-existent block: " + this.blockId);
return;
}
if (block.mutator) {
@@ -666,7 +706,7 @@ Blockly.Events.Change.prototype.run = function(forward) {
field.callValidator(value);
field.setValue(value);
} else {
console.warn("Can't set non-existant field: " + this.name);
console.warn("Can't set non-existent field: " + this.name);
}
break;
case 'comment':
@@ -818,7 +858,7 @@ Blockly.Events.Move.prototype.run = function(forward) {
var workspace = this.getEventWorkspace_();
var block = workspace.getBlockById(this.blockId);
if (!block) {
console.warn("Can't move non-existant block: " + this.blockId);
console.warn("Can't move non-existent block: " + this.blockId);
return;
}
var parentId = forward ? this.newParentId : this.oldParentId;
@@ -828,7 +868,7 @@ Blockly.Events.Move.prototype.run = function(forward) {
if (parentId) {
parentBlock = workspace.getBlockById(parentId);
if (!parentBlock) {
console.warn("Can't connect to non-existant block: " + parentId);
console.warn("Can't connect to non-existent block: " + parentId);
return;
}
}
@@ -852,7 +892,7 @@ Blockly.Events.Move.prototype.run = function(forward) {
if (parentConnection) {
blockConnection.connect(parentConnection);
} else {
console.warn("Can't connect to non-existant input: " + inputName);
console.warn("Can't connect to non-existent input: " + inputName);
}
}
};
@@ -861,8 +901,8 @@ Blockly.Events.Move.prototype.run = function(forward) {
* Class for a UI event.
* @param {Blockly.Block} block The affected block.
* @param {string} element One of 'selected', 'comment', 'mutator', etc.
* @param {string} oldValue Previous value of element.
* @param {string} newValue New value of element.
* @param {*} oldValue Previous value of element.
* @param {*} newValue New value of element.
* @extends {Blockly.Events.Abstract}
* @constructor
*/
+67 -69
View File
@@ -83,8 +83,8 @@ Blockly.Extensions.registerMixin = function(name, mixinObj) {
* decompose are defined on the mixin.
* @param {string} name The name of this mutator extension.
* @param {!Object} mixinObj The values to mix in.
* @param {(function())=} opt_helperFn An optional function to apply after mixing
* in the object.
* @param {(function())=} opt_helperFn An optional function to apply after
* mixing in the object.
* @param {Array.<string>=} opt_blockList A list of blocks to appear in the
* flyout of the mutator dialog.
* @throws {Error} if the mutation is invalid or can't be applied to the block.
@@ -99,8 +99,8 @@ Blockly.Extensions.registerMutator = function(name, mixinObj, opt_helperFn,
Blockly.Extensions.checkHasFunction_(errorPrefix, mixinObj.mutationToDom,
'mutationToDom');
var hasMutatorDialog = Blockly.Extensions.checkMutatorDialog_(mixinObj,
errorPrefix);
var hasMutatorDialog =
Blockly.Extensions.checkMutatorDialog_(mixinObj, errorPrefix);
if (opt_helperFn && !goog.isFunction(opt_helperFn)) {
throw new Error('Extension "' + name + '" is not a function');
@@ -148,8 +148,8 @@ Blockly.Extensions.apply = function(name, block, isMutator) {
Blockly.Extensions.checkBlockHasMutatorProperties_(errorPrefix, block);
} else {
if (!Blockly.Extensions.mutatorPropertiesMatch_(mutatorProperties, block)) {
throw new Error('Error when applying extension "' + name +
'": mutation properties changed when applying a non-mutator extension.');
throw new Error('Error when applying extension "' + name + '": ' +
'mutation properties changed when applying a non-mutator extension.');
}
}
};
@@ -169,7 +169,7 @@ Blockly.Extensions.checkHasFunction_ = function(errorPrefix, func,
'missing required property "' + propertyName + '"');
} else if (typeof func != 'function') {
throw new Error(errorPrefix +
'" required property "' + propertyName + '" must be a function');
'" required property "' + propertyName + '" must be a function');
}
};
@@ -209,9 +209,9 @@ Blockly.Extensions.checkMutatorDialog_ = function(object, errorPrefix) {
var hasDecompose = object.decompose !== undefined;
if (hasCompose && hasDecompose) {
if (typeof object.compose !== 'function') {
if (typeof object.compose != 'function') {
throw new Error(errorPrefix + 'compose must be a function.');
} else if (typeof object.decompose !== 'function') {
} else if (typeof object.decompose != 'function') {
throw new Error(errorPrefix + 'decompose must be a function.');
}
return true;
@@ -232,11 +232,13 @@ Blockly.Extensions.checkMutatorDialog_ = function(object, errorPrefix) {
*/
Blockly.Extensions.checkBlockHasMutatorProperties_ = function(errorPrefix,
block) {
if (typeof block.domToMutation !== 'function') {
throw new Error(errorPrefix + 'Applying a mutator didn\'t add "domToMutation"');
if (typeof block.domToMutation != 'function') {
throw new Error(errorPrefix +
'Applying a mutator didn\'t add "domToMutation"');
}
if (typeof block.mutationToDom !== 'function') {
throw new Error(errorPrefix + 'Applying a mutator didn\'t add "mutationToDom"');
if (typeof block.mutationToDom != 'function') {
throw new Error(errorPrefix +
'Applying a mutator didn\'t add "mutationToDom"');
}
// A block with a mutator isn't required to have a mutation dialog, but
@@ -280,19 +282,16 @@ Blockly.Extensions.getMutatorProperties_ = function(block) {
* @private
*/
Blockly.Extensions.mutatorPropertiesMatch_ = function(oldProperties, block) {
var match = true;
var newProperties = Blockly.Extensions.getMutatorProperties_(block);
if (newProperties.length != oldProperties.length) {
match = false;
} else {
for (var i = 0; i < newProperties.length; i++) {
if (oldProperties[i] != newProperties[i]) {
match = false;
}
return false;
}
for (var i = 0; i < newProperties.length; i++) {
if (oldProperties[i] != newProperties[i]) {
return false;
}
}
return match;
return true;
};
/**
@@ -310,11 +309,12 @@ Blockly.Extensions.mutatorPropertiesMatch_ = function(oldProperties, block) {
* reported as warnings in the console, and are never fatal.
* @param {string} dropdownName The name of the field whose value is the key
* to the lookup table.
* @param {!Object<string, string>} lookupTable The table of field values to
* @param {!Object.<string, string>} lookupTable The table of field values to
* tooltip text.
* @return {Function} The extension function.
*/
Blockly.Extensions.buildTooltipForDropdown = function(dropdownName, lookupTable) {
Blockly.Extensions.buildTooltipForDropdown = function(dropdownName,
lookupTable) {
// List of block types already validated, to minimize duplicate warnings.
var blockTypesChecked = [];
@@ -322,10 +322,10 @@ Blockly.Extensions.buildTooltipForDropdown = function(dropdownName, lookupTable)
// Wait for load, in case Blockly.Msg is not yet populated.
// runAfterPageLoad() does not run in a Node.js environment due to lack of
// document object, in which case skip the validation.
if (document) { // Relies on document.readyState
if (document) { // Relies on document.readyState
Blockly.utils.runAfterPageLoad(function() {
for (var key in lookupTable) {
// Will print warnings is reference is missing.
// Will print warnings if reference is missing.
Blockly.utils.checkMessageReferences(lookupTable[key]);
}
});
@@ -338,7 +338,7 @@ Blockly.Extensions.buildTooltipForDropdown = function(dropdownName, lookupTable)
var extensionFn = function() {
if (this.type && blockTypesChecked.indexOf(this.type) === -1) {
Blockly.Extensions.checkDropdownOptionsInTable_(
this, dropdownName, lookupTable);
this, dropdownName, lookupTable);
blockTypesChecked.push(this.type);
}
@@ -347,7 +347,7 @@ Blockly.Extensions.buildTooltipForDropdown = function(dropdownName, lookupTable)
var tooltip = lookupTable[value];
if (tooltip == null) {
if (blockTypesChecked.indexOf(this.type) === -1) {
// Warn for missing values on generated tooltips
// Warn for missing values on generated tooltips.
var warning = 'No tooltip mapping for value ' + value +
' of field ' + dropdownName;
if (this.type != null) {
@@ -369,24 +369,24 @@ Blockly.Extensions.buildTooltipForDropdown = function(dropdownName, lookupTable)
* Emits console warnings when they are not.
* @param {!Blockly.Block} block The block containing the dropdown
* @param {string} dropdownName The name of the dropdown
* @param {!Object<string, string>} lookupTable The string lookup table
* @param {!Object.<string, string>} lookupTable The string lookup table
* @private
*/
Blockly.Extensions.checkDropdownOptionsInTable_ =
function(block, dropdownName, lookupTable) {
// Validate all dropdown options have values.
var dropdown = block.getField(dropdownName);
if (!dropdown.isOptionListDynamic()) {
var options = dropdown.getOptions();
for (var i = 0; i < options.length; ++i) {
var optionKey = options[i][1]; // label, then value
if (lookupTable[optionKey] == null) {
console.warn('No tooltip mapping for value ' + optionKey +
' of field ' + dropdownName + ' of block type ' + block.type);
}
Blockly.Extensions.checkDropdownOptionsInTable_ = function(block, dropdownName,
lookupTable) {
// Validate all dropdown options have values.
var dropdown = block.getField(dropdownName);
if (!dropdown.isOptionListDynamic()) {
var options = dropdown.getOptions();
for (var i = 0; i < options.length; ++i) {
var optionKey = options[i][1]; // label, then value
if (lookupTable[optionKey] == null) {
console.warn('No tooltip mapping for value ' + optionKey +
' of field ' + dropdownName + ' of block type ' + block.type);
}
}
};
}
};
/**
* Builds an extension function that will install a dynamic tooltip. The
@@ -397,31 +397,31 @@ Blockly.Extensions.checkDropdownOptionsInTable_ =
* @param {string} fieldName The field with the replacement value.
* @returns {Function} The extension function.
*/
Blockly.Extensions.buildTooltipWithFieldValue =
function(msgTemplate, fieldName) {
// Check the tooltip string messages for invalid references.
// Wait for load, in case Blockly.Msg is not yet populated.
// runAfterPageLoad() does not run in a Node.js environment due to lack of
// document object, in which case skip the validation.
if (document) { // Relies on document.readyState
Blockly.utils.runAfterPageLoad(function() {
// Will print warnings is reference is missing.
Blockly.utils.checkMessageReferences(msgTemplate);
});
}
Blockly.Extensions.buildTooltipWithFieldValue = function(msgTemplate,
fieldName) {
// Check the tooltip string messages for invalid references.
// Wait for load, in case Blockly.Msg is not yet populated.
// runAfterPageLoad() does not run in a Node.js environment due to lack of
// document object, in which case skip the validation.
if (document) { // Relies on document.readyState
Blockly.utils.runAfterPageLoad(function() {
// Will print warnings if reference is missing.
Blockly.utils.checkMessageReferences(msgTemplate);
});
}
/**
* The actual extension.
* @this {Blockly.Block}
*/
var extensionFn = function() {
this.setTooltip(function() {
return Blockly.utils.replaceMessageReferences(msgTemplate)
.replace('%1', this.getFieldValue(fieldName));
}.bind(this));
};
return extensionFn;
/**
* The actual extension.
* @this {Blockly.Block}
*/
var extensionFn = function() {
this.setTooltip(function() {
return Blockly.utils.replaceMessageReferences(msgTemplate)
.replace('%1', this.getFieldValue(fieldName));
}.bind(this));
};
return extensionFn;
};
/**
* Configures the tooltip to mimic the parent block when connected. Otherwise,
@@ -435,10 +435,8 @@ Blockly.Extensions.extensionParentTooltip_ = function() {
this.tooltipWhenNotConnected_ = this.tooltip;
this.setTooltip(function() {
var parent = this.getParent();
return (parent &&
parent.getInputsInline() &&
parent.tooltip) ||
this.tooltipWhenNotConnected_;
return (parent && parent.getInputsInline() && parent.tooltip) ||
this.tooltipWhenNotConnected_;
}.bind(this));
};
Blockly.Extensions.register('parent_tooltip_when_inline',
+6 -4
View File
@@ -146,7 +146,7 @@ Blockly.Field.prototype.init = function() {
'ry': 4,
'x': -Blockly.BlockSvg.SEP_SPACE_X / 2,
'y': 0,
'height': 16}, this.fieldGroup_, this.sourceBlock_.workspace);
'height': 16}, this.fieldGroup_);
/** @type {!Element} */
this.textElement_ = Blockly.utils.createSvgElement('text',
{'class': 'blocklyText', 'y': this.size_.height - 12.5},
@@ -527,7 +527,8 @@ Blockly.Field.prototype.setValue = function(newValue) {
* @param {!Event} e Mouse down event.
* @private
*/
Blockly.Field.prototype.onMouseDown_ = function(e) {
Blockly.Field.prototype.onMouseDown_ = function(
/* eslint-disable no-unused-vars */ e /* eslint-enable no-unused-vars */) {
if (!this.sourceBlock_ || !this.sourceBlock_.workspace) {
return;
}
@@ -537,13 +538,14 @@ Blockly.Field.prototype.onMouseDown_ = function(e) {
}
};
/**
* Change the tooltip text for this field.
* @param {string|!Element} newTip Text for tooltip or a parent element to
* link to for its tooltip.
*/
Blockly.Field.prototype.setTooltip = function(newTip) {
Blockly.Field.prototype.setTooltip = function(
/* eslint-disable no-unused-vars */ newTip
/* eslint-enable no-unused-vars */) {
// Non-abstract sub-classes may wish to implement this. See FieldLabel.
};
+11 -11
View File
@@ -112,13 +112,13 @@ Blockly.FieldAngle.prototype.render_ = function() {
// Update textElement.
this.textElement_.textContent = this.getDisplayText_();
// Insert degree symbol.
if (this.sourceBlock_.RTL) {
this.textElement_.insertBefore(this.symbol_, this.textElement_.firstChild);
} else {
this.textElement_.appendChild(this.symbol_);
}
this.textElement_.insertBefore(this.symbol_, this.textElement_.firstChild);
} else {
this.textElement_.appendChild(this.symbol_);
}
this.updateWidth();
};
@@ -174,11 +174,11 @@ Blockly.FieldAngle.prototype.showEditor_ = function() {
}, svg);
this.gauge_ = Blockly.utils.createSvgElement('path',
{'class': 'blocklyAngleGauge'}, svg);
this.line_ = Blockly.utils.createSvgElement('line',{
'x1': Blockly.FieldAngle.HALF,
'y1': Blockly.FieldAngle.HALF,
'class': 'blocklyAngleLine',
}, svg);
this.line_ = Blockly.utils.createSvgElement('line', {
'x1': Blockly.FieldAngle.HALF,
'y1': Blockly.FieldAngle.HALF,
'class': 'blocklyAngleLine'
}, svg);
// Draw markers around the edge.
for (var angle = 0; angle < 360; angle += 15) {
Blockly.utils.createSvgElement('line', {
@@ -317,4 +317,4 @@ Blockly.FieldAngle.prototype.classValidator = function(text) {
n -= 360;
}
return String(n);
};
};
+2 -2
View File
@@ -54,7 +54,7 @@ Blockly.FieldImage = function(src, width, height, opt_alt, opt_onClick) {
this.text_ = opt_alt || '';
this.setValue(src);
if (typeof opt_onClick === "function") {
if (typeof opt_onClick == 'function') {
this.clickHandler_ = opt_onClick;
}
};
@@ -188,7 +188,7 @@ Blockly.FieldImage.prototype.updateWidth = function() {
* call the handler.
*/
Blockly.FieldImage.prototype.showEditor_ = function() {
if (this.clickHandler_){
if (this.clickHandler_) {
this.clickHandler_(this);
}
};
+1
View File
@@ -29,6 +29,7 @@ goog.provide('Blockly.FieldNumber');
goog.require('Blockly.FieldTextInput');
goog.require('goog.math');
/**
* Class for an editable number field.
* @param {(string|number)=} opt_value The initial content of the field. The value
+9 -10
View File
@@ -258,7 +258,8 @@ Blockly.FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) {
* @param {!Event} e Keyboard event.
* @private
*/
Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(e) {
Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(
/* eslint-disable no-unused-vars */ e /* eslint-enable no-unused-vars */) {
var htmlInput = Blockly.FieldTextInput.htmlInput_;
// Update source block.
var text = htmlInput.value;
@@ -300,17 +301,15 @@ Blockly.FieldTextInput.prototype.validate_ = function() {
*/
Blockly.FieldTextInput.prototype.resizeEditor_ = function() {
var div = Blockly.WidgetDiv.DIV;
var bBox = this.fieldGroup_.getBBox();
div.style.width = bBox.width * this.workspace_.scale + 'px';
div.style.height = bBox.height * this.workspace_.scale + 'px';
var xy = this.getAbsoluteXY_();
var bBox = this.getScaledBBox_();
div.style.width = bBox.right - bBox.left + 'px';
div.style.height = bBox.bottom - bBox.top + 'px';
// In RTL mode block fields and LTR input fields the left edge moves,
// whereas the right edge is fixed. Reposition the editor.
if (this.sourceBlock_.RTL) {
var borderBBox = this.getScaledBBox_();
xy.x += borderBBox.width;
xy.x -= div.offsetWidth;
}
var x = this.sourceBlock_.RTL ? bBox.right - div.offsetWidth : bBox.left;
var xy = new goog.math.Coordinate(x, bBox.top);
// Shift by a few pixels to line up exactly.
xy.y += 1;
if (goog.userAgent.GECKO && Blockly.WidgetDiv.DIV.style.top) {
+8 -9
View File
@@ -41,8 +41,8 @@ goog.require('goog.string');
* a unique variable name will be generated.
* @param {Function=} opt_validator A function that is executed when a new
* option is selected. Its sole argument is the new option value.
* @param {Array.<string>} opt_variableTypes A list of the types of variables to
* include in the dropdown.
* @param {Array.<string>=} opt_variableTypes A list of the types of variables
* to include in the dropdown.
* @extends {Blockly.FieldDropdown}
* @constructor
*/
@@ -118,7 +118,7 @@ Blockly.FieldVariable.prototype.setValue = function(value) {
newText = variable.name;
}
// TODO(marisaleung): Remove name lookup after converting all Field Variable
// instances to use id instead of name.
// instances to use ID instead of name.
else if (variable = this.sourceBlock_.workspace.getVariable(value)) {
newValue = variable.getId();
}
@@ -181,7 +181,7 @@ Blockly.FieldVariable.dropdownCreate = function() {
var variables = workspace.getVariablesOfType(variableType);
variableModelList = variableModelList.concat(variables);
}
for (var i = 0; i < variableModelList.length; i++){
for (var i = 0; i < variableModelList.length; i++) {
if (createSelectedVariable &&
goog.string.caseInsensitiveEquals(variableModelList[i].name, name)) {
createSelectedVariable = false;
@@ -197,13 +197,13 @@ Blockly.FieldVariable.dropdownCreate = function() {
variableModelList.sort(Blockly.VariableModel.compareByName);
var options = [];
for (var i = 0; i < variableModelList.length; i++) {
// Set the uuid as the internal representation of the variable.
// Set the UUID as the internal representation of the variable.
options[i] = [variableModelList[i].name, variableModelList[i].getId()];
}
options.push([Blockly.Msg.RENAME_VARIABLE, Blockly.RENAME_VARIABLE_ID]);
if (Blockly.Msg.DELETE_VARIABLE) {
options.push([Blockly.Msg.DELETE_VARIABLE.replace('%1', name),
Blockly.DELETE_VARIABLE_ID]);
Blockly.DELETE_VARIABLE_ID]);
}
return options;
};
@@ -217,7 +217,7 @@ Blockly.FieldVariable.dropdownCreate = function() {
*/
Blockly.FieldVariable.prototype.onItemSelected = function(menu, menuItem) {
var id = menuItem.getValue();
// TODO(marisaleung): change setValue() to take in an id as the parameter.
// TODO(marisaleung): change setValue() to take in an ID as the parameter.
// Then remove itemText.
var itemText;
if (this.sourceBlock_ && this.sourceBlock_.workspace) {
@@ -226,8 +226,7 @@ Blockly.FieldVariable.prototype.onItemSelected = function(menu, menuItem) {
// If the item selected is a variable, set itemText to the variable name.
if (variable) {
itemText = variable.name;
}
else if (id == Blockly.RENAME_VARIABLE_ID) {
} else if (id == Blockly.RENAME_VARIABLE_ID) {
// Rename variable.
var currentName = this.getText();
variable = workspace.getVariable(currentName);
+17 -16
View File
@@ -75,12 +75,12 @@ Blockly.Flyout = function(workspaceOptions) {
this.eventWrappers_ = [];
/**
* List of background buttons that lurk behind each block to catch clicks
* List of background mats that lurk behind each block to catch clicks
* landing in the blocks' lakes and bays.
* @type {!Array.<!Element>}
* @private
*/
this.backgroundButtons_ = [];
this.mats_ = [];
/**
* List of visible buttons.
@@ -518,7 +518,7 @@ Blockly.Flyout.prototype.show = function(xmlList) {
};
/**
* Delete blocks and background buttons from a previous showing of the flyout.
* Delete blocks, mats and buttons from a previous showing of the flyout.
* @private
*/
Blockly.Flyout.prototype.clearOldBlocks_ = function() {
@@ -529,13 +529,15 @@ Blockly.Flyout.prototype.clearOldBlocks_ = function() {
block.dispose(false, false);
}
}
// Delete any background buttons from a previous showing.
for (var j = 0; j < this.backgroundButtons_.length; j++) {
var rect = this.backgroundButtons_[j];
if (rect) goog.dom.removeNode(rect);
// Delete any mats from a previous showing.
for (var j = 0; j < this.mats_.length; j++) {
var rect = this.mats_[j];
if (rect) {
goog.dom.removeNode(rect);
}
}
this.backgroundButtons_.length = 0;
this.mats_.length = 0;
// Delete any buttons from a previous showing.
for (var i = 0, button; button = this.buttons_[i]; i++) {
button.dispose();
}
@@ -547,7 +549,7 @@ Blockly.Flyout.prototype.clearOldBlocks_ = function() {
* @param {!Element} root The root node of the SVG group the block is in.
* @param {!Blockly.Block} block The block to add listeners for.
* @param {!Element} rect The invisible rectangle under the block that acts as
* a button for that block.
* a mat for that block.
* @private
*/
Blockly.Flyout.prototype.addBlockListeners_ = function(root, block, rect) {
@@ -652,8 +654,8 @@ Blockly.Flyout.prototype.initFlyoutButton_ = function(button, x, y) {
* @param {number} y The y position of the cursor during this layout pass.
* @param {!{height: number, width: number}} blockHW The height and width of the
* block.
* @param {number} index The index into the background buttons list where this
* rect should be placed.
* @param {number} index The index into the mats list where this rect should be
* placed.
* @return {!SVGElement} Newly created SVG element for the rectangle behind the
* block.
* @private
@@ -675,7 +677,7 @@ Blockly.Flyout.prototype.createRect_ = function(block, x, y, blockHW, index) {
this.workspace_.getCanvas().insertBefore(rect, block.getSvgRoot());
block.flyoutRect_ = rect;
this.backgroundButtons_[index] = rect;
this.mats_[index] = rect;
return rect;
};
@@ -725,14 +727,13 @@ Blockly.Flyout.prototype.filterForCapacity_ = function() {
};
/**
* Reflow blocks and their buttons.
* Reflow blocks and their mats.
*/
Blockly.Flyout.prototype.reflow = function() {
if (this.reflowWrapper_) {
this.workspace_.removeChangeListener(this.reflowWrapper_);
}
var blocks = this.workspace_.getTopBlocks(false);
this.reflowInternal_(blocks);
this.reflowInternal_();
if (this.reflowWrapper_) {
this.workspace_.addChangeListener(this.reflowWrapper_);
}
+15 -7
View File
@@ -145,17 +145,17 @@ Blockly.FlyoutButton.prototype.createDom = function() {
// Background rectangle.
var rect = Blockly.utils.createSvgElement('rect',
{'class': this.isLabel_ ?
'blocklyFlyoutLabelBackground' : 'blocklyFlyoutButtonBackground',
'rx': 4, 'ry': 4},
'blocklyFlyoutLabelBackground' : 'blocklyFlyoutButtonBackground',
'rx': 4, 'ry': 4},
this.svgGroup_);
var svgText = Blockly.utils.createSvgElement('text',
{'class': this.isLabel_ ? 'blocklyFlyoutLabelText' : 'blocklyText',
'x': 0, 'y': 0, 'text-anchor': 'middle'},
'x': 0, 'y': 0, 'text-anchor': 'middle'},
this.svgGroup_);
svgText.textContent = this.text_;
this.width = svgText.getComputedTextLength();
this.width = Blockly.Field.getCachedWidth(svgText);
this.height = 20; // Can't compute it :(
if (!this.isLabel_) {
@@ -185,12 +185,11 @@ Blockly.FlyoutButton.prototype.show = function() {
};
/**
* Update svg attributes to match internal state.
* Update SVG attributes to match internal state.
* @private
*/
Blockly.FlyoutButton.prototype.updateTransform_ = function() {
this.svgGroup_.setAttribute('transform',
'translate(' + this.position_.x + ',' + this.position_.y + ')');
this.svgGroup_.setAttribute('transform', 'translate' + this.position_);
};
/**
@@ -204,6 +203,15 @@ Blockly.FlyoutButton.prototype.moveTo = function(x, y) {
this.updateTransform_();
};
/**
* Location of the button.
* @return {!goog.math.Coordinate} x, y coordinates.
* @package
*/
Blockly.FlyoutButton.prototype.getPosition = function() {
return this.position_;
};
/**
* Get the button's target workspace.
* @return {!Blockly.WorkspaceSvg} The target workspace of the flyout where this
+3 -3
View File
@@ -351,14 +351,14 @@ Blockly.HorizontalFlyout.prototype.getClientRect = function() {
};
/**
* Compute height of flyout. Position button under each block.
* Compute height of flyout. Position mat under each block.
* For RTL: Lay out the blocks right-aligned.
* @param {!Array<!Blockly.Block>} blocks The blocks to reflow.
* @private
*/
Blockly.HorizontalFlyout.prototype.reflowInternal_ = function(blocks) {
Blockly.HorizontalFlyout.prototype.reflowInternal_ = function() {
this.workspace_.scale = this.targetWorkspace_.scale;
var flyoutHeight = 0;
var blocks = this.workspace_.getTopBlocks(false);
for (var i = 0, block; block = blocks[i]; i++) {
flyoutHeight = Math.max(flyoutHeight, block.getHeightWidth().height);
}
+16 -7
View File
@@ -188,7 +188,7 @@ Blockly.VerticalFlyout.prototype.setBackgroundPath_ = function(width, height) {
atRight ? this.CORNER_RADIUS : -this.CORNER_RADIUS,
this.CORNER_RADIUS);
// Bottom.
path.push('h', atRight ? width : -width);
path.push('h', atRight ? width : -width);
path.push('z');
this.svgBackground_.setAttribute('d', path.join(' '));
};
@@ -326,14 +326,14 @@ Blockly.VerticalFlyout.prototype.getClientRect = function() {
};
/**
* Compute width of flyout. Position button under each block.
* For RTL: Lay out the blocks right-aligned.
* @param {!Array<!Blockly.Block>} blocks The blocks to reflow.
* Compute width of flyout. Position mat under each block.
* For RTL: Lay out the blocks and buttons to be right-aligned.
* @private
*/
Blockly.VerticalFlyout.prototype.reflowInternal_ = function(blocks) {
Blockly.VerticalFlyout.prototype.reflowInternal_ = function() {
this.workspace_.scale = this.targetWorkspace_.scale;
var flyoutWidth = 0;
var blocks = this.workspace_.getTopBlocks(false);
for (var i = 0, block; block = blocks[i]; i++) {
var width = block.getHeightWidth().width;
if (block.outputConnection) {
@@ -353,14 +353,23 @@ Blockly.VerticalFlyout.prototype.reflowInternal_ = function(blocks) {
if (this.RTL) {
// With the flyoutWidth known, right-align the blocks.
var oldX = block.getRelativeToSurfaceXY().x;
var newX = flyoutWidth / this.workspace_.scale - this.MARGIN;
newX -= Blockly.BlockSvg.TAB_WIDTH;
var newX = flyoutWidth / this.workspace_.scale - this.MARGIN -
Blockly.BlockSvg.TAB_WIDTH;
block.moveBy(newX - oldX, 0);
}
if (block.flyoutRect_) {
this.moveRectToBlock_(block.flyoutRect_, block);
}
}
if (this.RTL) {
// With the flyoutWidth known, right-align the buttons.
for (var i = 0, button; button = this.buttons_[i]; i++) {
var y = button.getPosition().y;
var x = flyoutWidth - button.width - this.MARGIN -
Blockly.BlockSvg.TAB_WIDTH;
button.moveTo(x, y);
}
}
// Record the width for .getMetrics_ and .position.
this.width_ = flyoutWidth;
// Call this since it is possible the trash and zoom buttons need
+1 -1
View File
@@ -366,7 +366,7 @@ Blockly.Generator.prototype.provideFunction_ = function(desiredName, code) {
var oldCodeText;
while (oldCodeText != codeText) {
oldCodeText = codeText;
codeText = codeText.replace(/^(( )*) /gm, '$1\0');
codeText = codeText.replace(/^(( {2})*) {2}/gm, '$1\0');
}
codeText = codeText.replace(/\0/g, this.INDENT);
this.definitions_[desiredName] = codeText;
+2 -2
View File
@@ -246,7 +246,7 @@ Blockly.Gesture.prototype.updateFromEvent_ = function(e) {
var currentXY = new goog.math.Coordinate(e.clientX, e.clientY);
var changed = this.updateDragDelta_(currentXY);
// Exceeded the drag radius for the first time.
if (changed){
if (changed) {
this.updateIsDragging_();
Blockly.longStop_();
}
@@ -328,7 +328,7 @@ Blockly.Gesture.prototype.updateIsDraggingBlock_ = function() {
if (this.flyout_) {
this.isDraggingBlock_ = this.updateIsDraggingFromFlyout_();
} else if (this.targetBlock_.isMovable()){
} else if (this.targetBlock_.isMovable()) {
this.isDraggingBlock_ = true;
}
+1 -1
View File
@@ -121,7 +121,7 @@ Blockly.Grid.prototype.getSpacing = function() {
/**
* Get the id of the pattern element, which should be randomized to avoid
* conflicts with other Blockly instances on the page.
* @return {string} The pattern id.
* @return {string} The pattern ID.
* @package
*/
Blockly.Grid.prototype.getPatternId = function() {
+1 -1
View File
@@ -54,7 +54,7 @@ Blockly.inject = function(container, opt_options) {
throw 'Error: container is not in current document.';
}
var options = new Blockly.Options(opt_options || {});
var subContainer = goog.dom.createDom('div', 'injectionDiv');
var subContainer = goog.dom.createDom(goog.dom.TagName.DIV, 'injectionDiv');
container.appendChild(subContainer);
var svg = Blockly.createDom_(subContainer, options);
+1 -1
View File
@@ -101,7 +101,7 @@ Blockly.Input.prototype.insertFieldAt = function(index, field, opt_name) {
// Empty string, Null or undefined generates no field, unless field is named.
if (!field && !opt_name) {
return this;
return index;
}
// Generate a FieldLabel when given a plain text field.
if (goog.isString(field)) {
+1 -1
View File
@@ -42,7 +42,7 @@ goog.getMsgOrig = goog.getMsg;
* Overrides the default Closure function to check for a Blockly.Msg first.
* Used infrequently, only known case is TODAY button in date picker.
* @param {string} str Translatable string, places holders in the form {$foo}.
* @param {Object<string, string>=} opt_values Maps place holder name to value.
* @param {Object.<string, string>=} opt_values Maps place holder name to value.
* @return {string} message with placeholders filled.
* @suppress {duplicate}
*/
+7 -1
View File
@@ -73,7 +73,13 @@ Blockly.Mutator.prototype.drawIcon_ = function(group) {
// Gear teeth.
Blockly.utils.createSvgElement('path',
{'class': 'blocklyIconSymbol',
'd': 'm4.203,7.296 0,1.368 -0.92,0.677 -0.11,0.41 0.9,1.559 0.41,0.11 1.043,-0.457 1.187,0.683 0.127,1.134 0.3,0.3 1.8,0 0.3,-0.299 0.127,-1.138 1.185,-0.682 1.046,0.458 0.409,-0.11 0.9,-1.559 -0.11,-0.41 -0.92,-0.677 0,-1.366 0.92,-0.677 0.11,-0.41 -0.9,-1.559 -0.409,-0.109 -1.046,0.458 -1.185,-0.682 -0.127,-1.138 -0.3,-0.299 -1.8,0 -0.3,0.3 -0.126,1.135 -1.187,0.682 -1.043,-0.457 -0.41,0.11 -0.899,1.559 0.108,0.409z'},
'd': 'm4.203,7.296 0,1.368 -0.92,0.677 -0.11,0.41 0.9,1.559 0.41,' +
'0.11 1.043,-0.457 1.187,0.683 0.127,1.134 0.3,0.3 1.8,0 0.3,' +
'-0.299 0.127,-1.138 1.185,-0.682 1.046,0.458 0.409,-0.11 0.9,' +
'-1.559 -0.11,-0.41 -0.92,-0.677 0,-1.366 0.92,-0.677 0.11,' +
'-0.41 -0.9,-1.559 -0.409,-0.109 -1.046,0.458 -1.185,-0.682 ' +
'-0.127,-1.138 -0.3,-0.299 -1.8,0 -0.3,0.3 -0.126,1.135 -1.187,' +
'0.682 -1.043,-0.457 -0.41,0.11 -0.899,1.559 0.108,0.409z'},
group);
// Axle hole.
Blockly.utils.createSvgElement('circle',
+6 -5
View File
@@ -30,6 +30,7 @@ goog.provide('Blockly.ScrollbarPair');
goog.require('goog.dom');
goog.require('goog.events');
/**
* A note on units: most of the numbers that are in CSS pixels are scaled if the
* scrollbar is in a mutator.
@@ -189,7 +190,7 @@ Blockly.ScrollbarPair.prototype.getRatio_ = function(handlePosition, viewSize) {
* @param {!Blockly.Workspace} workspace Workspace to bind the scrollbar to.
* @param {boolean} horizontal True if horizontal, false if vertical.
* @param {boolean=} opt_pair True if scrollbar is part of a horiz/vert pair.
* @param {string} opt_class A class to be applied to this scrollbar.
* @param {string=} opt_class A class to be applied to this scrollbar.
* @constructor
*/
Blockly.Scrollbar = function(workspace, horizontal, opt_pair, opt_class) {
@@ -201,7 +202,7 @@ Blockly.Scrollbar = function(workspace, horizontal, opt_pair, opt_class) {
this.createDom_(opt_class);
/**
* The upper left corner of the scrollbar's svg group in CSS pixels relative
* The upper left corner of the scrollbar's SVG group in CSS pixels relative
* to the scrollbar's origin. This is usually relative to the injection div
* origin.
* @type {goog.math.Coordinate}
@@ -394,7 +395,7 @@ Blockly.ScrollbarPair.prototype.setContainerVisible = function(visible) {
};
/**
* Set the position of the scrollbar's svg group in CSS pixels relative to the
* Set the position of the scrollbar's SVG group in CSS pixels relative to the
* scrollbar's origin. This sets the scrollbar's location within the workspace.
* @param {number} x The new x coordinate.
* @param {number} y The new y coordinate.
@@ -591,7 +592,7 @@ Blockly.Scrollbar.prototype.resizeContentVertical = function(hostMetrics) {
/**
* Create all the DOM elements required for a scrollbar.
* The resulting widget is not sized.
* @param {string} opt_class A class to be applied to this scrollbar.
* @param {string=} opt_class A class to be applied to this scrollbar.
* @private
*/
Blockly.Scrollbar.prototype.createDom_ = function(opt_class) {
@@ -667,7 +668,7 @@ Blockly.Scrollbar.prototype.setVisible = function(visible) {
* Update visibility of scrollbar based on whether it thinks it should
* be visible and whether its containing workspace is visible.
* We cannot rely on the containing workspace being hidden to hide us
* because it is not necessarily our parent in the dom.
* because it is not necessarily our parent in the DOM.
*/
Blockly.Scrollbar.prototype.updateDisplay_ = function() {
var show = true;
+14 -10
View File
@@ -296,8 +296,9 @@ Blockly.Toolbox.prototype.populate_ = function(newTree) {
/**
* Sync trees of the toolbox.
* @param {!Node} treeIn DOM tree of blocks.
* @param {!Blockly.Toolbox.TreeControl} treeOut
* @param {string} pathToMedia
* @param {!Blockly.Toolbox.TreeControl} treeOut The TreeContorol object built
* from treeIn.
* @param {string} pathToMedia The path to the Blockly media directory.
* @return {Node} Tree node to open at startup (or null).
* @private
*/
@@ -331,12 +332,12 @@ Blockly.Toolbox.prototype.syncTrees_ = function(treeIn, treeOut, pathToMedia) {
// Decode the colour for any potential message references
// (eg. `%{BKY_MATH_HUE}`).
var colour = Blockly.utils.replaceMessageReferences(
childIn.getAttribute('colour'));
childIn.getAttribute('colour'));
if (goog.isString(colour)) {
if (colour.match(/^#[0-9a-fA-F]{6}$/)) {
if (/^#[0-9a-fA-F]{6}$/.test(colour)) {
childOut.hexColour = colour;
} else {
childOut.hexColour = Blockly.hueToRgb(colour);
childOut.hexColour = Blockly.hueToRgb(Number(colour));
}
this.hasColours_ = true;
} else {
@@ -388,7 +389,7 @@ Blockly.Toolbox.prototype.syncTrees_ = function(treeIn, treeOut, pathToMedia) {
/**
* Recursively add colours to this toolbox.
* @param {Blockly.Toolbox.TreeNode} opt_tree Starting point of tree.
* @param {Blockly.Toolbox.TreeNode=} opt_tree Starting point of tree.
* Defaults to the root node.
* @private
*/
@@ -629,7 +630,8 @@ Blockly.Toolbox.TreeNode.prototype.getExpandIconSafeHtml = function() {
* @param {!goog.events.BrowserEvent} e The browser event.
* @override
*/
Blockly.Toolbox.TreeNode.prototype.onClick_ = function(e) {
Blockly.Toolbox.TreeNode.prototype.onClick_ = function(
/* eslint-disable no-unused-vars */ e /* eslint-disable no-unused-vars */) {
// Expand icon.
if (this.hasChildren() && this.isUserCollapsible_) {
this.toggle();
@@ -648,7 +650,8 @@ Blockly.Toolbox.TreeNode.prototype.onClick_ = function(e) {
* @override
* @private
*/
Blockly.Toolbox.TreeNode.prototype.onMouseDown = function(e) {
Blockly.Toolbox.TreeNode.prototype.onMouseDown = function(
/* eslint-disable no-unused-vars */ e /* eslint-disable no-unused-vars */) {
// NOPE.
};
@@ -658,7 +661,8 @@ Blockly.Toolbox.TreeNode.prototype.onMouseDown = function(e) {
* @override
* @private
*/
Blockly.Toolbox.TreeNode.prototype.onDoubleClick_ = function(e) {
Blockly.Toolbox.TreeNode.prototype.onDoubleClick_ = function(
/* eslint-disable no-unused-vars */ e /* eslint-disable no-unused-vars */) {
// NOP.
};
@@ -695,6 +699,6 @@ Blockly.Toolbox.TreeNode.prototype.onKeyDown = function(e) {
* @extends {Blockly.Toolbox.TreeNode}
*/
Blockly.Toolbox.TreeSeparator = function(config) {
Blockly.Toolbox.TreeNode.call(this, null, '', config);
Blockly.Toolbox.TreeNode.call(this, null, goog.html.SafeHtml.EMPTY, config);
};
goog.inherits(Blockly.Toolbox.TreeSeparator, Blockly.Toolbox.TreeNode);
+5 -2
View File
@@ -184,7 +184,8 @@ Blockly.Tooltip.onMouseOver_ = function(e) {
* @param {!Event} e Mouse event.
* @private
*/
Blockly.Tooltip.onMouseOut_ = function(e) {
Blockly.Tooltip.onMouseOut_ = function(/* eslint-disable no-unused-vars */e
/* eslint-enable no-unused-vars */) {
if (Blockly.Tooltip.blocked_) {
// Someone doesn't want us to show tooltips.
return;
@@ -248,7 +249,9 @@ Blockly.Tooltip.hide = function() {
Blockly.Tooltip.DIV.style.display = 'none';
}
}
clearTimeout(Blockly.Tooltip.showPid_);
if (Blockly.Tooltip.showPid_) {
clearTimeout(Blockly.Tooltip.showPid_);
}
};
/**
+4 -3
View File
@@ -34,9 +34,10 @@ goog.require('goog.events');
goog.require('goog.events.BrowserFeature');
goog.require('goog.string');
/**
* Which touch events are we currently paying attention to?
* @type {DOMString}
* @type {?string}
* @private
*/
Blockly.Touch.touchIdentifier_ = null;
@@ -63,7 +64,7 @@ Blockly.longPid_ = 0;
/**
* Context menus on touch devices are activated using a long-press.
* Unfortunately the contextmenu touch event is currently (2015) only suported
* Unfortunately the contextmenu touch event is currently (2015) only supported
* by Chrome. This function is fired on any touchstart event, queues a task,
* which after about a second opens the context menu. The tasks is killed
* if the touch event terminates early.
@@ -154,7 +155,7 @@ Blockly.Touch.getTouchIdentifierFromEvent = function(e) {
Blockly.Touch.checkTouchIdentifier = function(e) {
var identifier = Blockly.Touch.getTouchIdentifierFromEvent(e);
// if (Blockly.touchIdentifier_ )is insufficient because android touch
// if (Blockly.touchIdentifier_ )is insufficient because Android touch
// identifiers may be zero.
if (Blockly.Touch.touchIdentifier_ != undefined &&
Blockly.Touch.touchIdentifier_ != null) {
+1
View File
@@ -30,6 +30,7 @@
**/
goog.provide('Blockly.utils.uiMenu');
/**
* Get the size of a rendered goog.ui.Menu.
* @param {!goog.ui.Menu} menu The menu to measure.
+29 -24
View File
@@ -44,8 +44,8 @@ goog.require('goog.userAgent');
* is not possible. To access the exported Blockly.Msg.Something it needs to be
* accessed through the exact name that was exported. Note, that all the exports
* are happening as the last thing in the generated js files, so they won't be
* accessible before javascript loads!
* @return {!Object<string, string>}
* accessible before JavaScript loads!
* @return {!Object.<string, string>} The message array.
* @private
*/
Blockly.utils.getMessageArray_ = function() {
@@ -208,10 +208,9 @@ Blockly.utils.getRelativeXY = function(element) {
Blockly.utils.getInjectionDivXY_ = function(element) {
var x = 0;
var y = 0;
var scale = 1;
while (element) {
var xy = Blockly.utils.getRelativeXY(element);
scale = Blockly.utils.getScale_(element);
var scale = Blockly.utils.getScale_(element);
x = (x * scale) + xy.x;
y = (y * scale) + xy.y;
var classes = element.getAttribute('class') || '';
@@ -286,11 +285,9 @@ Blockly.utils.getRelativeXY.XY_2D_REGEX_ =
* @param {string} name Element's tag name.
* @param {!Object} attrs Dictionary of attribute names and values.
* @param {Element} parent Optional parent on which to append the element.
* @param {Blockly.Workspace=} opt_workspace Optional workspace for access to
* context (scale...).
* @return {!SVGElement} Newly created SVG element.
*/
Blockly.utils.createSvgElement = function(name, attrs, parent /*, opt_workspace */) {
Blockly.utils.createSvgElement = function(name, attrs, parent) {
var e = /** @type {!SVGElement} */ (
document.createElementNS(Blockly.SVG_NS, name));
for (var key in attrs) {
@@ -328,7 +325,7 @@ Blockly.utils.isRightButton = function(e) {
* @param {!Event} e Mouse event.
* @param {!Element} svg SVG element.
* @param {SVGMatrix} matrix Inverted screen CTM to use.
* @return {!Object} Object with .x and .y properties.
* @return {!SVGPoint} Object with .x and .y properties.
*/
Blockly.utils.mouseToSvg = function(e, svg, matrix) {
var svgPoint = svg.createSVGPoint();
@@ -454,38 +451,45 @@ Blockly.utils.replaceMessageReferences = function(message) {
var interpolatedResult = Blockly.utils.tokenizeInterpolation_(message, false);
// When parseInterpolationTokens == false, interpolatedResult should be at
// most length 1.
return interpolatedResult.length ? interpolatedResult[0] : "";
return interpolatedResult.length ? interpolatedResult[0] : '';
};
/**
* Validates that any %{BKY_...} references in the message refer to keys of
* Validates that any %{MSG_KEY} references in the message refer to keys of
* the Blockly.Msg string table.
* @param {string} message Text which might contain string table references.
* @return {boolean} True if all message references have matching values.
* Otherwise, false.
*/
Blockly.utils.checkMessageReferences = function(message) {
var isValid = true; // True until a bad reference is found
var validSoFar = true;
var regex = /%{BKY_([a-zA-Z][a-zA-Z0-9_]*)}/g;
var msgTable = Blockly.utils.getMessageArray_();
// TODO(#1169): Implement support for other string tables, prefixes other than BKY_.
var regex = /%{(BKY_[A-Z][A-Z0-9_]*)}/gi;
var match = regex.exec(message);
while (match != null) {
while (match) {
var msgKey = match[1];
if (Blockly.utils.getMessageArray_()[msgKey] == null) {
console.log('WARNING: No message string for %{BKY_' + msgKey + '}.');
isValid = false;
msgKey = msgKey.toUpperCase();
if (msgKey.substr(0, 4) != 'BKY_') {
console.log('WARNING: Unsupported message table prefix in %{' + match[1] + '}.');
validSoFar = false; // Continue to report other errors.
} else if (msgTable[msgKey.substr(4)] == undefined) {
console.log('WARNING: No message string for %{' + match[1] + '}.');
validSoFar = false; // Continue to report other errors.
}
// Re-run on remainder of sting.
// Re-run on remainder of string.
message = message.substring(match.index + msgKey.length + 1);
match = regex.exec(message);
}
return isValid;
return validSoFar;
};
/**
* Internal implemention of the message reference and interpolation token
* Internal implementation of the message reference and interpolation token
* parsing used by tokenizeInterpolation() and replaceMessageReferences().
* @param {string} message Text which might contain string table references and
* interpolation tokens.
@@ -494,7 +498,8 @@ Blockly.utils.checkMessageReferences = function(message) {
* @return {!Array.<string|number>} Array of strings and numbers.
* @private
*/
Blockly.utils.tokenizeInterpolation_ = function(message, parseInterpolationTokens) {
Blockly.utils.tokenizeInterpolation_ = function(message,
parseInterpolationTokens) {
var tokens = [];
var chars = message.split('');
chars.push(''); // End marker.
@@ -502,7 +507,7 @@ Blockly.utils.tokenizeInterpolation_ = function(message, parseInterpolationToken
// 0 - Base case.
// 1 - % found.
// 2 - Digit found.
// 3 - Message ref found
// 3 - Message ref found.
var state = 0;
var buffer = [];
var number = null;
@@ -569,7 +574,8 @@ Blockly.utils.tokenizeInterpolation_ = function(message, parseInterpolationToken
if (goog.isString(rawValue)) {
// Attempt to dereference substrings, too, appending to the end.
Array.prototype.push.apply(tokens,
Blockly.utils.tokenizeInterpolation(rawValue));
Blockly.utils.tokenizeInterpolation_(
rawValue, parseInterpolationTokens));
} else if (parseInterpolationTokens) {
// When parsing interpolation tokens, numbers are special
// placeholders (%1, %2, etc). Make sure all other values are
@@ -640,7 +646,7 @@ Blockly.utils.genUid = function() {
* Legal characters for the unique ID. Should be all on a US keyboard.
* No characters that conflict with XML or JSON. Requests to remove additional
* 'problematic' characters from this soup will be denied. That's your failure
* to properly escape in your own environment. Issues #251, #625, #682.
* to properly escape in your own environment. Issues #251, #625, #682, #1304.
* @private
*/
Blockly.utils.genUid.soup_ = '!#$%()*+,-./:;=?@[]^_`{|}~' +
@@ -937,4 +943,3 @@ Blockly.utils.getViewportBBox = function() {
left: scrollOffset.x
};
};
+23 -21
View File
@@ -26,6 +26,7 @@
goog.provide('Blockly.VariableMap');
/**
* Class for a variable map. This contains a dictionary data structure with
* variable types as keys and lists of variables as values. The list of
@@ -33,12 +34,12 @@ goog.provide('Blockly.VariableMap');
* @param {!Blockly.Workspace} workspace The workspace this map belongs to.
* @constructor
*/
Blockly.VariableMap = function(workspace) {
Blockly.VariableMap = function(workspace) {
/**
* A map from variable type to list of variable names. The lists contain all
* of the named variables in the workspace, including variables
* that are not currently in use.
* @type {!Object<string, !Array.<Blockly.VariableModel>>}
* @type {!Object.<string, !Array.<Blockly.VariableModel>>}
* @private
*/
this.variableMap_ = {};
@@ -59,7 +60,7 @@ Blockly.VariableMap.prototype.clear = function() {
/**
* Rename the given variable by updating its name in the variable map.
* @param {?Blockly.VariableModel} variable Variable to rename.
* @param {Blockly.VariableModel} variable Variable to rename.
* @param {string} newName New variable name.
*/
Blockly.VariableMap.prototype.renameVariable = function(variable, newName) {
@@ -75,7 +76,7 @@ Blockly.VariableMap.prototype.renameVariable = function(variable, newName) {
if (variable) {
variableIndex = variableList.indexOf(variable);
}
if (newVariable){ // see if I can get rid of newVariable dependency
if (newVariable) { // see if I can get rid of newVariable dependency
newVariableIndex = variableList.indexOf(newVariable);
}
@@ -103,17 +104,18 @@ Blockly.VariableMap.prototype.renameVariable = function(variable, newName) {
};
/**
* Create a variable with a given name, optional type, and optional id.
* @param {!string} name The name of the variable. This must be unique across
* Create a variable with a given name, optional type, and optional ID.
* @param {string} name The name of the variable. This must be unique across
* variables and procedures.
* @param {?string} opt_type The type of the variable like 'int' or 'string'.
* @param {string=} opt_type The type of the variable like 'int' or 'string'.
* Does not need to be unique. Field_variable can filter variables based on
* their type. This will default to '' which is a specific type.
* @param {?string} opt_id The unique id of the variable. This will default to
* @param {string=} opt_id The unique ID of the variable. This will default to
* a UUID.
* @return {?Blockly.VariableModel} The newly created variable.
* @return {Blockly.VariableModel} The newly created variable.
*/
Blockly.VariableMap.prototype.createVariable = function(name, opt_type, opt_id) {
Blockly.VariableMap.prototype.createVariable = function(name,
opt_type, opt_id) {
var variable = this.getVariable(name);
if (variable) {
if (opt_type && variable.type != opt_type) {
@@ -122,11 +124,11 @@ Blockly.VariableMap.prototype.createVariable = function(name, opt_type, opt_id)
'type, "' + opt_type + '".');
}
if (opt_id && variable.getId() != opt_id) {
throw Error('Variable "' + name + '" is already in use and its id is "'
+ variable.getId() + '" which conflicts with the passed in ' +
throw Error('Variable "' + name + '" is already in use and its id is "' +
variable.getId() + '" which conflicts with the passed in ' +
'id, "' + opt_id + '".');
}
// The variable already exists and has the same id and type.
// The variable already exists and has the same ID and type.
return variable;
}
if (opt_id && this.getVariableById(opt_id)) {
@@ -148,7 +150,7 @@ Blockly.VariableMap.prototype.createVariable = function(name, opt_type, opt_id)
/**
* Delete a variable.
* @param {Blockly.VariableModel} variable Variable to delete.
* @param {!Blockly.VariableModel} variable Variable to delete.
*/
Blockly.VariableMap.prototype.deleteVariable = function(variable) {
var variableList = this.variableMap_[variable.type];
@@ -164,8 +166,8 @@ Blockly.VariableMap.prototype.deleteVariable = function(variable) {
/**
* Find the variable by the given name and return it. Return null if it is not
* found.
* @param {!string} name The name to check for.
* @return {?Blockly.VariableModel} The variable with the given name, or null if
* @param {string} name The name to check for.
* @return {Blockly.VariableModel} The variable with the given name, or null if
* it was not found.
*/
Blockly.VariableMap.prototype.getVariable = function(name) {
@@ -182,10 +184,10 @@ Blockly.VariableMap.prototype.getVariable = function(name) {
};
/**
* Find the variable by the given id and return it. Return null if it is not
* Find the variable by the given ID and return it. Return null if it is not
* found.
* @param {!string} id The id to check for.
* @return {?Blockly.VariableModel} The variable with the given id.
* @param {string} id The ID to check for.
* @return {Blockly.VariableModel} The variable with the given ID.
*/
Blockly.VariableMap.prototype.getVariableById = function(id) {
var keys = Object.keys(this.variableMap_);
@@ -204,7 +206,7 @@ Blockly.VariableMap.prototype.getVariableById = function(id) {
* Get a list containing all of the variables of a specified type. If type is
* null, return list of variables with empty string type.
* @param {?string} type Type of the variables to find.
* @return {Array.<Blockly.VariableModel>} The sought after variables of the
* @return {!Array.<!Blockly.VariableModel>} The sought after variables of the
* passed in type. An empty array if none are found.
*/
Blockly.VariableMap.prototype.getVariablesOfType = function(type) {
@@ -226,7 +228,7 @@ Blockly.VariableMap.prototype.getVariableTypes = function() {
/**
* Return all variables of all types.
* @return {!Array.<Blockly.VariableModel>} List of variable models.
* @return {!Array.<!Blockly.VariableModel>} List of variable models.
*/
Blockly.VariableMap.prototype.getAllVariables = function() {
var all_variables = [];
+4 -4
View File
@@ -31,14 +31,14 @@ goog.require('goog.string');
/**
* Class for a variable model.
* Holds information for the variable including name, id, and type.
* Holds information for the variable including name, ID, and type.
* @param {!Blockly.Workspace} workspace The variable's workspace.
* @param {!string} name The name of the variable. This must be unique across
* variables and procedures.
* @param {?string} opt_type The type of the variable like 'int' or 'string'.
* @param {string=} opt_type The type of the variable like 'int' or 'string'.
* Does not need to be unique. Field_variable can filter variables based on
* their type. This will default to '' which is a specific type.
* @param {?string} opt_id The unique id of the variable. This will default to
* @param {string=} opt_id The unique ID of the variable. This will default to
* a UUID.
* @see {Blockly.FieldVariable}
* @constructor
@@ -80,7 +80,7 @@ Blockly.VariableModel = function(workspace, name, opt_type, opt_id) {
};
/**
* @return {!string} The id for the variable.
* @return {!string} The ID for the variable.
*/
Blockly.VariableModel.prototype.getId = function() {
return this.id_;
+8 -8
View File
@@ -177,13 +177,13 @@ Blockly.Variables.flyoutCategoryBlocks = function(workspace) {
};
/**
* Return a new variable name that is not yet being used. This will try to
* generate single letter variable names in the range 'i' to 'z' to start with.
* If no unique name is located it will try 'i' to 'z', 'a' to 'h',
* then 'i2' to 'z2' etc. Skip 'l'.
* Return a new variable name that is not yet being used. This will try to
* generate single letter variable names in the range 'i' to 'z' to start with.
* If no unique name is located it will try 'i' to 'z', 'a' to 'h',
* then 'i2' to 'z2' etc. Skip 'l'.
* @param {!Blockly.Workspace} workspace The workspace to be unique in.
* @return {string} New variable name.
*/
* @return {string} New variable name.
*/
Blockly.Variables.generateUniqueName = function(workspace) {
var variableList = workspace.getAllVariables();
var newName = '';
@@ -232,7 +232,7 @@ Blockly.Variables.generateUniqueName = function(workspace) {
* @param {function(?string=)=} opt_callback A callback. It will
* be passed an acceptable new variable name, or null if change is to be
* aborted (cancel button), or undefined if an existing variable was chosen.
* @param {?string} opt_type The type of the variable like 'int', 'string', or
* @param {string=} opt_type The type of the variable like 'int', 'string', or
* ''. This will default to '', which is a specific type.
*/
Blockly.Variables.createVariable = function(workspace, opt_callback, opt_type) {
@@ -340,7 +340,7 @@ Blockly.Variables.generateVariableFieldXml_ = function(variableModel) {
// to be escaped to create valid XML.
var element = goog.dom.createDom('field');
element.setAttribute('name', 'VAR');
element.setAttribute('variableType', variableModel.type);
element.setAttribute('variabletype', variableModel.type);
element.setAttribute('id', variableModel.getId());
element.textContent = variableModel.name;
+3 -1
View File
@@ -139,7 +139,9 @@ Blockly.Warning.prototype.setVisible = function(visible) {
* @param {!Event} e Mouse up event.
* @private
*/
Blockly.Warning.prototype.bodyFocus_ = function(e) {
Blockly.Warning.prototype.bodyFocus_ = function(
/* eslint-disable no-unused-vars */ e /* eslint-enable no-unused-vars */) {
this.bubble_.promote_();
};
+24 -21
View File
@@ -34,7 +34,7 @@ goog.require('goog.math');
/**
* Class for a workspace. This is a data structure that contains blocks.
* There is no UI, and can be created headlessly.
* @param {Blockly.Options} opt_options Dictionary of options.
* @param {!Blockly.Options=} opt_options Dictionary of options.
* @constructor
*/
Blockly.Workspace = function(opt_options) {
@@ -217,8 +217,7 @@ Blockly.Workspace.prototype.updateVariableStore = function(clear) {
if (tempVar) {
varList.push({'name': tempVar.name, 'type': tempVar.type,
'id': tempVar.getId()});
}
else {
} else {
varList.push({'name': name, 'type': null, 'id': null});
// TODO(marisaleung): Use variable.type and variable.getId() once variable
// instances are storing more than just name.
@@ -241,7 +240,8 @@ Blockly.Workspace.prototype.updateVariableStore = function(clear) {
* @param {?Blockly.VariableModel} variable Variable to rename.
* @param {string} newName New variable name.
*/
Blockly.Workspace.prototype.renameVariableInternal_ = function(variable, newName) {
Blockly.Workspace.prototype.renameVariableInternal_ = function(
variable, newName) {
var newVariable = this.getVariable(newName);
var oldCase;
@@ -285,8 +285,8 @@ Blockly.Workspace.prototype.renameVariable = function(oldName, newName) {
/**
* Rename a variable by updating its name in the variable map. Identify the
* variable to rename with the given id.
* @param {string} id Id of the variable to rename.
* variable to rename with the given ID.
* @param {string} id ID of the variable to rename.
* @param {string} newName New variable name.
*/
Blockly.Workspace.prototype.renameVariableById = function(id, newName) {
@@ -295,13 +295,13 @@ Blockly.Workspace.prototype.renameVariableById = function(id, newName) {
};
/**
* Create a variable with a given name, optional type, and optional id.
* Create a variable with a given name, optional type, and optional ID.
* @param {!string} name The name of the variable. This must be unique across
* variables and procedures.
* @param {?string} opt_type The type of the variable like 'int' or 'string'.
* @param {string=} opt_type The type of the variable like 'int' or 'string'.
* Does not need to be unique. Field_variable can filter variables based on
* their type. This will default to '' which is a specific type.
* @param {?string} opt_id The unique id of the variable. This will default to
* @param {string=} opt_id The unique ID of the variable. This will default to
* a UUID.
* @return {?Blockly.VariableModel} The newly created variable.
*/
@@ -358,7 +358,8 @@ Blockly.Workspace.prototype.deleteVariable = function(name) {
if (uses.length > 1) {
// Confirm before deleting multiple blocks.
Blockly.confirm(
Blockly.Msg.DELETE_VARIABLE_CONFIRMATION.replace('%1', uses.length).
Blockly.Msg.DELETE_VARIABLE_CONFIRMATION.replace('%1',
String(uses.length)).
replace('%2', name),
function(ok) {
if (ok) {
@@ -372,23 +373,23 @@ Blockly.Workspace.prototype.deleteVariable = function(name) {
};
/**
* Delete a variables by the passed in id and all of its uses from this
* Delete a variables by the passed in ID and all of its uses from this
* workspace. May prompt the user for confirmation.
* @param {string} id Id of variable to delete.
* @param {string} id ID of variable to delete.
*/
Blockly.Workspace.prototype.deleteVariableById = function(id) {
var variable = this.getVariableById(id);
if (variable) {
this.deleteVariableInternal_(variable);
} else {
console.warn("Can't delete non-existant variable: " + id);
console.warn("Can't delete non-existent variable: " + id);
}
};
/**
* Deletes a variable and all of its uses from this workspace without asking the
* user for confirmation.
* @param {Blockly.VariableModel} variable Variable to delete.
* @param {!Blockly.VariableModel} variable Variable to delete.
* @private
*/
Blockly.Workspace.prototype.deleteVariableInternal_ = function(variable) {
@@ -409,7 +410,10 @@ Blockly.Workspace.prototype.deleteVariableInternal_ = function(variable) {
* not present.
* @deprecated April 2017
*/
Blockly.Workspace.prototype.variableIndexOf = function(name) {
Blockly.Workspace.prototype.variableIndexOf = function(
/* eslint-disable no-unused-vars */ name
/* eslint-enable no-unused-vars */) {
console.warn(
'Deprecated call to Blockly.Workspace.prototype.variableIndexOf');
return -1;
@@ -426,10 +430,10 @@ Blockly.Workspace.prototype.getVariable = function(name) {
};
/**
* Find the variable by the given id and return it. Return null if it is not
* Find the variable by the given ID and return it. Return null if it is not
* found.
* @param {!string} id The id to check for.
* @return {?Blockly.VariableModel} The variable with the given id.
* @param {!string} id The ID to check for.
* @return {?Blockly.VariableModel} The variable with the given ID.
*/
Blockly.Workspace.prototype.getVariableById = function(id) {
return this.variableMap_.getVariableById(id);
@@ -450,7 +454,7 @@ Blockly.Workspace.prototype.getWidth = function() {
* @param {?string} prototypeName Name of the language object containing
* type-specific functions for this block.
* @param {string=} opt_id Optional ID. Use this ID if provided, otherwise
* create a new id.
* create a new ID.
* @return {!Blockly.Block} The created block.
*/
Blockly.Workspace.prototype.newBlock = function(prototypeName, opt_id) {
@@ -496,8 +500,7 @@ Blockly.Workspace.prototype.undo = function(redo) {
for (var i = 0, event; event = events[i]; i++) {
event.run(redo);
}
}
finally {
} finally {
Blockly.Events.recordUndo = true;
}
};
+3 -2
View File
@@ -27,10 +27,12 @@
goog.provide('Blockly.WorkspaceAudio');
/**
* Class for loading, storing, and playing audio for a workspace.
* @param {Blockly.WorkspaceSvg} parentWorkspace The parent of the workspace
* this audio object belongs to, or null.
* @constructor
*/
Blockly.WorkspaceAudio = function(parentWorkspace) {
@@ -72,7 +74,6 @@ Blockly.WorkspaceAudio.prototype.dispose = function() {
* preference (i.e. increasing size). E.g. ['media/go.mp3', 'media/go.wav']
* Filenames include path from Blockly's root. File extensions matter.
* @param {string} name Name of sound.
* @package
*/
Blockly.WorkspaceAudio.prototype.load = function(filenames, name) {
if (!filenames.length) {
@@ -107,7 +108,7 @@ Blockly.WorkspaceAudio.prototype.load = function(filenames, name) {
Blockly.WorkspaceAudio.prototype.preload = function() {
for (var name in this.SOUNDS_) {
var sound = this.SOUNDS_[name];
sound.volume = .01;
sound.volume = 0.01;
sound.play();
sound.pause();
// iOS can only process one sound at a time. Trying to load more than one
+4 -4
View File
@@ -93,7 +93,7 @@ Blockly.WorkspaceDragSurfaceSvg.prototype.createDom = function() {
'xmlns:html': Blockly.HTML_NS,
'xmlns:xlink': 'http://www.w3.org/1999/xlink',
'version': '1.1',
'class': 'blocklyWsDragSurface blocklyOverflowVisible',
'class': 'blocklyWsDragSurface blocklyOverflowVisible'
}, null);
this.container_.appendChild(this.SVG_);
};
@@ -168,9 +168,9 @@ Blockly.WorkspaceDragSurfaceSvg.prototype.clearAndHide = function(newSurface) {
* @param {!Element} blockCanvas The block canvas <g> element from the workspace.
* @param {!Element} bubbleCanvas The <g> element that contains the bubbles.
* @param {?Element} previousSibling The element to insert the block canvas &
bubble canvas after when it goes back in the dom at the end of a drag.
* @param {number} width The width of the workspace svg element.
* @param {number} height The height of the workspace svg element.
bubble canvas after when it goes back in the DOM at the end of a drag.
* @param {number} width The width of the workspace SVG element.
* @param {number} height The height of the workspace SVG element.
* @param {number} scale The scale of the workspace being dragged.
* @package
*/
+21 -22
View File
@@ -245,7 +245,7 @@ Blockly.WorkspaceSvg.prototype.lastRecordedPageScroll_ = null;
/**
* Map from function names to callbacks, for deciding what to do when a button
* is clicked.
* @type {!Object<string, function(!Blockly.FlyoutButton)>}
* @type {!Object.<string, function(!Blockly.FlyoutButton)>}
* @private
*/
Blockly.WorkspaceSvg.prototype.flyoutButtonCallbacks_ = {};
@@ -253,7 +253,7 @@ Blockly.WorkspaceSvg.prototype.flyoutButtonCallbacks_ = {};
/**
* Map from function names to callbacks, for deciding what to do when a custom
* toolbox category is opened.
* @type {!Object<string, function(!Blockly.Workspace):!Array<!Element>>}
* @type {!Object.<string, function(!Blockly.Workspace):!Array.<!Element>>}
* @private
*/
Blockly.WorkspaceSvg.prototype.toolboxCategoryCallbacks_ = {};
@@ -370,10 +370,10 @@ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) {
}
/** @type {SVGElement} */
this.svgBlockCanvas_ = Blockly.utils.createSvgElement('g',
{'class': 'blocklyBlockCanvas'}, this.svgGroup_, this);
{'class': 'blocklyBlockCanvas'}, this.svgGroup_);
/** @type {SVGElement} */
this.svgBubbleCanvas_ = Blockly.utils.createSvgElement('g',
{'class': 'blocklyBubbleCanvas'}, this.svgGroup_, this);
{'class': 'blocklyBubbleCanvas'}, this.svgGroup_);
var bottom = Blockly.Scrollbar.scrollbarThickness;
if (this.options.hasTrashcan) {
bottom = this.addTrashcan_(bottom);
@@ -516,7 +516,7 @@ Blockly.WorkspaceSvg.prototype.addZoomControls_ = function(bottom) {
/**
* Add a flyout element in an element with the given tag name.
* @param {string} tagName What type of tag the flyout belongs in.
* @return {!Element} The element containing the flyout dom.
* @return {!Element} The element containing the flyout DOM.
* @private
*/
Blockly.WorkspaceSvg.prototype.addFlyout_ = function(tagName) {
@@ -623,8 +623,8 @@ Blockly.WorkspaceSvg.prototype.resize = function() {
* scroll position.
* @package
*/
Blockly.WorkspaceSvg.prototype.updateScreenCalculationsIfScrolled
= function() {
Blockly.WorkspaceSvg.prototype.updateScreenCalculationsIfScrolled =
function() {
/* eslint-disable indent */
var currScroll = goog.dom.getDocumentScroll();
if (!goog.math.Coordinate.equals(this.lastRecordedPageScroll_,
@@ -652,7 +652,7 @@ Blockly.WorkspaceSvg.prototype.getBubbleCanvas = function() {
/**
* Get the SVG element that contains this workspace.
* @return {!Element} SVG element.
* @return {Element} SVG element.
*/
Blockly.WorkspaceSvg.prototype.getParentSvg = function() {
if (this.cachedParentSvg_) {
@@ -664,7 +664,7 @@ Blockly.WorkspaceSvg.prototype.getParentSvg = function() {
this.cachedParentSvg_ = element;
return element;
}
element = element.parentNode;
element = element.parentElement;
}
return null;
};
@@ -691,7 +691,7 @@ Blockly.WorkspaceSvg.prototype.translate = function(x, y) {
/**
* Called at the end of a workspace drag to take the contents
* out of the drag surface and put them back into the workspace svg.
* out of the drag surface and put them back into the workspace SVG.
* Does nothing if the workspace drag surface is not enabled.
* @package
*/
@@ -705,8 +705,7 @@ Blockly.WorkspaceSvg.prototype.resetDragSurface = function() {
var trans = this.workspaceDragSurface_.getSurfaceTranslation();
this.workspaceDragSurface_.clearAndHide(this.svgGroup_);
var translation = 'translate(' + trans.x + ',' + trans.y + ') ' +
'scale(' + this.scale + ')';
var translation = 'translate' + trans + ' scale(' + this.scale + ')';
this.svgBlockCanvas_.setAttribute('transform', translation);
this.svgBubbleCanvas_.setAttribute('transform', translation);
};
@@ -737,8 +736,8 @@ Blockly.WorkspaceSvg.prototype.setupDragSurface = function() {
// Figure out where we want to put the canvas back. The order
// in the is important because things are layered.
var previousElement = this.svgBlockCanvas_.previousSibling;
var width = this.getParentSvg().getAttribute("width");
var height = this.getParentSvg().getAttribute("height");
var width = this.getParentSvg().getAttribute('width');
var height = this.getParentSvg().getAttribute('height');
var coord = Blockly.utils.getRelativeXY(this.svgBlockCanvas_);
this.workspaceDragSurface_.setContentsAndShow(this.svgBlockCanvas_,
this.svgBubbleCanvas_, previousElement, width, height, this.scale);
@@ -933,7 +932,7 @@ Blockly.WorkspaceSvg.prototype.renameVariable = function(oldName, newName) {
/**
* Rename a variable by updating its name in the variable map. Update the
* flyout to show the renamed variable immediately.
* @param {string} id Id of the variable to rename.
* @param {string} id ID of the variable to rename.
* @param {string} newName New variable name.
* @package
*/
@@ -954,9 +953,9 @@ Blockly.WorkspaceSvg.prototype.deleteVariable = function(name) {
};
/**
* Delete a variable by the passed in id. Update the flyout to show
* Delete a variable by the passed in ID. Update the flyout to show
* immediately that the variable is deleted.
* @param {string} id Id of variable to delete.
* @param {string} id ID of variable to delete.
* @package
*/
Blockly.WorkspaceSvg.prototype.deleteVariableById = function(id) {
@@ -971,7 +970,7 @@ Blockly.WorkspaceSvg.prototype.deleteVariableById = function(id) {
* @param {string=} opt_type The type of the variable like 'int' or 'string'.
* Does not need to be unique. Field_variable can filter variables based on
* their type. This will default to '' which is a specific type.
* @param {string=} opt_id The unique id of the variable. This will default to
* @param {string=} opt_id The unique ID of the variable. This will default to
* a UUID.
* @return {?Blockly.VariableModel} The newly created variable.
* @package
@@ -1064,7 +1063,7 @@ Blockly.WorkspaceSvg.prototype.moveDrag = function(e) {
* @return {boolean} True if currently dragging or scrolling.
*/
Blockly.WorkspaceSvg.prototype.isDragging = function() {
return this.currentGesture_ && this.currentGesture_.isDragging();
return this.currentGesture_ != null && this.currentGesture_.isDragging();
};
/**
@@ -1357,7 +1356,7 @@ Blockly.WorkspaceSvg.prototype.setBrowserFocus = function() {
try {
// Focus the workspace SVG - this is for Chrome and Firefox.
this.getParentSvg().focus();
} catch (e) {
} catch (e) {
// IE and Edge do not support focus on SVG elements. When that fails
// above, get the injectionDiv (the workspace's parent) and focus that
// instead. This doesn't work in Chrome.
@@ -1785,7 +1784,7 @@ Blockly.WorkspaceSvg.prototype.removeButtonCallback = function(key) {
* custom toolbox categories in this workspace. See the variable and procedure
* categories as an example.
* @param {string} key The name to use to look up this function.
* @param {function(!Blockly.Workspace):!Array<!Element>} func The function to
* @param {function(!Blockly.Workspace):!Array.<!Element>} func The function to
* call when the given toolbox category is opened.
*/
Blockly.WorkspaceSvg.prototype.registerToolboxCategoryCallback = function(key,
@@ -1799,7 +1798,7 @@ Blockly.WorkspaceSvg.prototype.registerToolboxCategoryCallback = function(key,
* Get the callback function associated with a given key, for populating
* custom toolbox categories in this workspace.
* @param {string} key The name to use to look up the function.
* @return {?function(!Blockly.Workspace):!Array<!Element>} The function
* @return {?function(!Blockly.Workspace):!Array.<!Element>} The function
* corresponding to the given key for this workspace, or null if no function
* is registered.
*/
+45 -49
View File
@@ -37,7 +37,7 @@ goog.require('goog.dom');
/**
* Encode a block tree as XML.
* @param {!Blockly.Workspace} workspace The workspace containing blocks.
* @param {boolean} opt_noId True if the encoder should skip the block ids.
* @param {boolean=} opt_noId True if the encoder should skip the block IDs.
* @return {!Element} XML document.
*/
Blockly.Xml.workspaceToDom = function(workspace, opt_noId) {
@@ -70,7 +70,7 @@ Blockly.Xml.variablesToDom = function(variableList) {
/**
* Encode a block subtree as XML with XY coordinates.
* @param {!Blockly.Block} block The root block to encode.
* @param {boolean} opt_noId True if the encoder should skip the block id.
* @param {boolean=} opt_noId True if the encoder should skip the block ID.
* @return {!Element} Tree of XML elements.
*/
Blockly.Xml.blockToDomWithXY = function(block, opt_noId) {
@@ -89,7 +89,7 @@ Blockly.Xml.blockToDomWithXY = function(block, opt_noId) {
/**
* Encode a block subtree as XML.
* @param {!Blockly.Block} block The root block to encode.
* @param {boolean} opt_noId True if the encoder should skip the block id.
* @param {boolean=} opt_noId True if the encoder should skip the block ID.
* @return {!Element} Tree of XML elements.
*/
Blockly.Xml.blockToDom = function(block, opt_noId) {
@@ -113,7 +113,7 @@ Blockly.Xml.blockToDom = function(block, opt_noId) {
var variable = block.workspace.getVariable(field.getValue());
if (variable) {
container.setAttribute('id', variable.getId());
container.setAttribute('variableType', variable.type);
container.setAttribute('variabletype', variable.type);
}
}
element.appendChild(container);
@@ -303,7 +303,7 @@ Blockly.Xml.textToDom = function(text) {
* Decode an XML DOM and create blocks on the workspace.
* @param {!Element} xml XML DOM.
* @param {!Blockly.Workspace} workspace The workspace.
* @return {Array.<string>} An array containing new block ids.
* @return {Array.<string>} An array containing new block IDs.
*/
Blockly.Xml.domToWorkspace = function(xml, workspace) {
if (xml instanceof Blockly.Workspace) {
@@ -317,7 +317,7 @@ Blockly.Xml.domToWorkspace = function(xml, workspace) {
if (workspace.RTL) {
width = workspace.getWidth();
}
var newBlockIds = []; // A list of block ids added by this call.
var newBlockIds = []; // A list of block IDs added by this call.
Blockly.Field.startCache();
// Safari 7.1.3 is known to provide node lists with extra references to
// children beyond the lists' length. Trust the length, do not use the
@@ -353,11 +353,10 @@ Blockly.Xml.domToWorkspace = function(xml, workspace) {
} else if (name == 'shadow') {
goog.asserts.fail('Shadow block cannot be a top-level block.');
variablesFirst = false;
} else if (name == 'variables') {
} else if (name == 'variables') {
if (variablesFirst) {
Blockly.Xml.domToVariables(xmlChild, workspace);
}
else {
} else {
throw Error('\'variables\' tag must exist once before block and ' +
'shadow tag elements in the workspace XML, but it was found in ' +
'another location.');
@@ -365,8 +364,7 @@ Blockly.Xml.domToWorkspace = function(xml, workspace) {
variablesFirst = false;
}
}
}
finally {
} finally {
if (!existingGroup) {
Blockly.Events.setGroup(false);
}
@@ -385,12 +383,12 @@ Blockly.Xml.domToWorkspace = function(xml, workspace) {
* blocks immediately below prior blocks, aligned by their starting edge.
* @param {!Element} xml The XML DOM.
* @param {!Blockly.Workspace} workspace The workspace to add to.
* @return {Array.<string>} An array containing new block ids.
* @return {Array.<string>} An array containing new block IDs.
*/
Blockly.Xml.appendDomToWorkspace = function(xml, workspace) {
var bbox; //bounding box of the current blocks
// first check if we have a workspaceSvg otherwise the block have no shape
// and the position does not matter
var bbox; // Bounding box of the current blocks.
// First check if we have a workspaceSvg, otherwise the blocks have no shape
// and the position does not matter.
if (workspace.hasOwnProperty('scale')) {
var savetab = Blockly.BlockSvg.TAB_WIDTH;
try {
@@ -400,22 +398,22 @@ Blockly.Xml.appendDomToWorkspace = function(xml, workspace) {
Blockly.BlockSvg.TAB_WIDTH = savetab;
}
}
// load the new blocks into the workspace and get the ids of the new blocks
// Load the new blocks into the workspace and get the IDs of the new blocks.
var newBlockIds = Blockly.Xml.domToWorkspace(xml,workspace);
if (bbox && bbox.height) { // check if any previous block
var offsetY = 0; // offset to add to y of the new block
if (bbox && bbox.height) { // check if any previous block
var offsetY = 0; // offset to add to y of the new block
var offsetX = 0;
var farY = bbox.y + bbox.height; //bottom position
var topX = bbox.x; // x of bounding box
// check position of the new blocks
var newX = Infinity; // x of top corner
var newY = Infinity; // y of top corner
var farY = bbox.y + bbox.height; // bottom position
var topX = bbox.x; // x of bounding box
// Check position of the new blocks.
var newX = Infinity; // x of top corner
var newY = Infinity; // y of top corner
for (var i = 0; i < newBlockIds.length; i++) {
var blockXY = workspace.getBlockById(newBlockIds[i]).getRelativeToSurfaceXY();
if (blockXY.y < newY) {
newY = blockXY.y;
}
if (blockXY.x < newX) { //if we align also on x
if (blockXY.x < newX) { // if we align also on x
newX = blockXY.x;
}
}
@@ -498,7 +496,7 @@ Blockly.Xml.domToVariables = function(xmlVariables, workspace) {
var id = xmlChild.getAttribute('id');
var name = xmlChild.textContent;
if (typeof(type) === undefined || type === null) {
if (type == null) {
throw Error('Variable with id, ' + id + ' is without a type');
}
workspace.createVariable(name, type, id);
@@ -530,21 +528,21 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
var input;
// Find any enclosed blocks or shadows in this tag.
var childBlockNode = null;
var childShadowNode = null;
var childBlockElement = null;
var childShadowElement = null;
for (var j = 0, grandchildNode; grandchildNode = xmlChild.childNodes[j];
j++) {
if (grandchildNode.nodeType == 1) {
if (grandchildNode.nodeName.toLowerCase() == 'block') {
childBlockNode = grandchildNode;
childBlockElement = /** @type {!Element} */ (grandchildNode);
} else if (grandchildNode.nodeName.toLowerCase() == 'shadow') {
childShadowNode = grandchildNode;
childShadowElement = /** @type {!Element} */ (grandchildNode);
}
}
}
// Use the shadow block if there is no child block.
if (!childBlockNode && childShadowNode) {
childBlockNode = childShadowNode;
if (!childBlockElement && childShadowElement) {
childBlockElement = childShadowElement;
}
var name = xmlChild.getAttribute('name');
@@ -589,21 +587,19 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
var text = xmlChild.textContent;
if (field instanceof Blockly.FieldVariable) {
// TODO (marisaleung): When we change setValue and getValue to
// interact with id's instead of names, update this so that we get
// the variable based on id instead of textContent.
var type = xmlChild.getAttribute('variableType') || '';
// interact with IDs instead of names, update this so that we get
// the variable based on ID instead of textContent.
var type = xmlChild.getAttribute('variabletype') || '';
var variable = workspace.getVariable(text);
if (!variable) {
variable = workspace.createVariable(text, type,
xmlChild.getAttribute(id));
}
if (typeof(type) !== undefined && type !== null) {
if (type !== variable.type) {
throw Error('Serialized variable type with id \'' +
variable.getId() + '\' had type ' + variable.type + ', and ' +
'does not match variable field that references it: ' +
Blockly.Xml.domToText(xmlChild) + '.');
}
if (type != null && type !== variable.type) {
throw Error('Serialized variable type with id \'' +
variable.getId() + '\' had type ' + variable.type + ', and ' +
'does not match variable field that references it: ' +
Blockly.Xml.domToText(xmlChild) + '.');
}
}
if (!field) {
@@ -621,11 +617,11 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
prototypeName);
break;
}
if (childShadowNode) {
input.connection.setShadowDom(childShadowNode);
if (childShadowElement) {
input.connection.setShadowDom(childShadowElement);
}
if (childBlockNode) {
blockChild = Blockly.Xml.domToBlockHeadless_(childBlockNode,
if (childBlockElement) {
blockChild = Blockly.Xml.domToBlockHeadless_(childBlockElement,
workspace);
if (blockChild.outputConnection) {
input.connection.connect(blockChild.outputConnection);
@@ -638,16 +634,16 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
}
break;
case 'next':
if (childShadowNode && block.nextConnection) {
block.nextConnection.setShadowDom(childShadowNode);
if (childShadowElement && block.nextConnection) {
block.nextConnection.setShadowDom(childShadowElement);
}
if (childBlockNode) {
if (childBlockElement) {
goog.asserts.assert(block.nextConnection,
'Next statement does not exist.');
// If there is more than one XML 'next' tag.
goog.asserts.assert(!block.nextConnection.isConnected(),
'Next statement is already connected.');
blockChild = Blockly.Xml.domToBlockHeadless_(childBlockNode,
blockChild = Blockly.Xml.domToBlockHeadless_(childBlockElement,
workspace);
goog.asserts.assert(blockChild.previousConnection,
'Next block does not have previous statement.');
+3 -3
View File
@@ -37,9 +37,9 @@ goog.require('goog.dom.xml');
/**
* Block Exporter Tools Class
* @constructor
*/
* Block Exporter Tools Class
* @constructor
*/
BlockExporterTools = function() {
// Create container for hidden workspace.
this.container = goog.dom.createDom('div', {
+4 -2
View File
@@ -387,13 +387,15 @@ Code.init = function() {
// TODO: Clean up the message files so this is done explicitly instead of
// through this for-loop.
for (var messageKey in MSG) {
if (goog.string.startsWith(messageKey, 'cat')) {
if (messageKey.indexOf('cat') == 0) {
Blockly.Msg[messageKey.toUpperCase()] = MSG[messageKey];
}
}
// Construct the toolbox XML.
// Construct the toolbox XML, replacing translated variable names.
var toolboxText = document.getElementById('toolbox').outerHTML;
toolboxText = toolboxText.replace(/(^|[^%]){(\w+)}/g,
function(m, p1, p2) {return p1 + MSG[p2];});
var toolboxXml = Blockly.Xml.textToDom(toolboxText);
Code.workspace = Blockly.inject('content_blocks',
-31
View File
@@ -1,31 +0,0 @@
/**
* @fileoverview Main file (entry point) for the advanced compilation demo.
*/
'use strict';
goog.provide('Demo');
// messages (in some language)
goog.require('Blockly.Msg.en');
// core
goog.require('Blockly');
// blocks
goog.require('Blockly.Constants.Colour');
goog.require('Blockly.Constants.Lists');
goog.require('Blockly.Constants.Logic');
goog.require('Blockly.Constants.Loops');
goog.require('Blockly.Constants.Math');
goog.require('Blockly.Blocks.procedures');
goog.require('Blockly.Constants.Text');
goog.require('Blockly.Constants.Variables');
Demo.init = function() {
Blockly.inject('blocklyDiv', {
'media': '../../media/',
'toolbox': document.getElementById('toolbox')
});
}
window.addEventListener('load', Demo.init);
+27 -28
View File
@@ -2,7 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<title>Blockly Demo: Minimap </title>
<title>Blockly Demo: Minimap</title>
<script src="../../blockly_compressed.js"></script>
<script src="../../blocks_compressed.js"></script>
<script src="../../msg/js/en.js"></script>
@@ -49,41 +49,40 @@
</xml>
<script>
// Inject master workspace.
var masterWorkspace = Blockly.inject('masterDiv', {
media: '../../media/',
scrollbars: true,
toolbox: document.getElementById('toolbox')
});
// Inject master workspace.
var masterWorkspace = Blockly.inject('masterDiv',{
media: '../../media/',
scrollbars: true,
toolbox: document.getElementById('toolbox')
});
// Inject workspace for minimap.
var minimapWorkspace = Blockly.inject('mapDiv',
{media: '../../media/',
readOnly: true,
zoom:
{controls: false,
wheel: true,
startScale: 0.1, //you can change this accorting to your needs.
maxScale: 0.1,
minScale: 0.01
}});
// Initilizing the minimap.
Minimap.init(masterWorkspace,minimapWorkspace);
// Inject workspace for minimap.
var minimapWorkspace = Blockly.inject('mapDiv', {
media: '../../media/',
readOnly: true,
zoom: {
controls: false,
wheel: true,
startScale: 0.1, // Change this according to your needs.
maxScale: 0.1,
minScale: 0.01
}
});
// Initialize the minimap.
Minimap.init(masterWorkspace,minimapWorkspace);
</script>
<style>
.minimap{
position:absolute;
position: absolute;
}
.mapDragger{
cursor: move;
fill:rgb(0,0,255);
stroke-width:0.5;
stroke:rgb(0,0,0);
fill-opacity:0.1;
}
fill: rgb(0,0,255);
stroke-width: .5;
stroke: rgb(0,0,0);
fill-opacity: .1;
}
</style>
</body>
+135 -127
View File
@@ -1,46 +1,46 @@
/**
* Blockly Demos: Code
*
* Copyright 2017 Google Inc.
* https://developers.google.com/blockly/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
* Blockly Demos: Minimap
*
* Copyright 2017 Google Inc.
* https://developers.google.com/blockly/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview JavaScript for Blockly's Minimap demo.
* @author karnpurohit@gmail.com (Karan Purohit)
*/
* @fileoverview JavaScript for Blockly's Minimap demo.
* @author karnpurohit@gmail.com (Karan Purohit)
*/
'use strict';
/**
* Creating a seperate namespace for minimap.
*/
* Creating a separate namespace for minimap.
*/
var Minimap = {};
/**
* Initilize the workspace and minimap.
* @param {Workspace} workspace The main workspace of the user.
* @param {Workspace} minimap The workspace that will be used as a minimap.
*/
Minimap.init = function(workspace, minimap){
* Initialize the workspace and minimap.
* @param {!Workspace} workspace The main workspace of the user.
* @param {!Workspace} minimap The workspace that will be used as a minimap.
*/
Minimap.init = function(workspace, minimap) {
this.workspace = workspace;
this.minimap = minimap;
//Adding scroll callback functionlity to vScroll and hScroll just for this demo.
//IMPORTANT: This should be changed when there is proper UI event handling
// api available and should be handled by workspace's event listeners.
this.workspace.scrollbar.vScroll.setHandlePosition = function(newPosition){
// Adding scroll callback functionality to vScroll and hScroll just for this demo.
// IMPORTANT: This should be changed when there is proper UI event handling
// API available and should be handled by workspace's event listeners.
this.workspace.scrollbar.vScroll.setHandlePosition = function(newPosition) {
this.handlePosition_ = newPosition;
this.svgHandle_.setAttribute(this.positionAttribute_, this.handlePosition_);
@@ -55,7 +55,7 @@ Minimap.init = function(workspace, minimap){
};
// Adding call back for horizontal scroll.
this.workspace.scrollbar.hScroll.setHandlePosition = function(newPosition){
this.workspace.scrollbar.hScroll.setHandlePosition = function(newPosition) {
this.handlePosition_ = newPosition;
this.svgHandle_.setAttribute(this.positionAttribute_, this.handlePosition_);
@@ -71,7 +71,7 @@ Minimap.init = function(workspace, minimap){
// Required to stop a positive feedback loop when user clicks minimap
// and the scroll changes, which inturn may change minimap.
// and the scroll changes, which in turn may change minimap.
this.disableScrollChange = false;
// Listen to events on the main workspace.
@@ -95,9 +95,9 @@ Minimap.init = function(workspace, minimap){
// Creating a rectangle in the minimap that represents current view.
Blockly.utils.createSvgElement('rect', {
'width':100,
'height':100,
'class':'mapDragger'
'width': 100,
'height': 100,
'class': 'mapDragger'
}, this.svg);
// Rectangle in the minimap that represents current view.
@@ -105,7 +105,7 @@ Minimap.init = function(workspace, minimap){
// Adding mouse events to the rectangle, to make it Draggable.
// Using Blockly.bindEvent_ to attach mouse/touch listeners.
Blockly.bindEvent_(this.mapDragger, "mousedown", null, Minimap.mousedown);
Blockly.bindEvent_(this.mapDragger, 'mousedown', null, Minimap.mousedown);
//When the window change, we need to resize the minimap window.
window.addEventListener('resize', Minimap.repositionMinimap);
@@ -113,20 +113,22 @@ Minimap.init = function(workspace, minimap){
// Mouse up event for the minimap.
this.svg.addEventListener('mouseup', Minimap.updateMapDragger);
//Boolen to check whether I am dragging the surface or not.
//Boolean to check whether I am dragging the surface or not.
this.isDragging = false;
};
Minimap.mousedown = function(e){
Minimap.mousedown = function(e) {
// Using Blockly.bindEvent_ to attach mouse/touch listeners.
Minimap.mouseMoveBindData = Blockly.bindEvent_(document,"mousemove", null, Minimap.mousemove);
Minimap.mouseUpBindData = Blockly.bindEvent_(document,"mouseup", null, Minimap.mouseup);
Minimap.mouseMoveBindData =
Blockly.bindEvent_(document, 'mousemove', null, Minimap.mousemove);
Minimap.mouseUpBindData =
Blockly.bindEvent_(document, 'mouseup', null, Minimap.mouseup);
Minimap.isDragging=true;
Minimap.isDragging = true;
e.stopPropagation();
};
Minimap.mouseup = function(e){
Minimap.mouseup = function(e) {
Minimap.isDragging = false;
// Removing listeners.
Blockly.unbindEvent_(Minimap.mouseUpBindData);
@@ -135,18 +137,18 @@ Minimap.mouseup = function(e){
e.stopPropagation();
};
Minimap.mousemove = function(e){
if(Minimap.isDragging){
Minimap.mousemove = function(e) {
if (Minimap.isDragging) {
Minimap.updateMapDragger(e);
e.stopPropagation();
}
};
/**
* Initilize the workspace and minimap.
* @param {Event} event Event that triggered in the main workspace.
*/
Minimap.mirrorEvent = function(event){
* Run non-UI events from the main workspace on the minimap.
* @param {!Event} event Event that triggered in the main workspace.
*/
Minimap.mirrorEvent = function(event) {
if (event.type == Blockly.Events.UI) {
return; // Don't mirror UI events.
}
@@ -161,146 +163,152 @@ Minimap.mirrorEvent = function(event){
};
/**
* Called when window is resized. Repositions the minimap overlay.
*/
Minimap.repositionMinimap = function(){
* Called when window is resized. Repositions the minimap overlay.
*/
Minimap.repositionMinimap = function() {
Minimap.rect = document.getElementById('mapDiv').getBoundingClientRect();
Minimap.svg.style.top = Minimap.rect.top + 'px';
Minimap.svg.style.left = Minimap.rect.left + 'px';
};
/**
* Updates the rectangle's height .
*/
Minimap.setDraggerHeight = function(){
* Updates the rectangle's height.
*/
Minimap.setDraggerHeight = function() {
var workspaceMetrics = Minimap.workspace.getMetrics();
var draggerHeight = (workspaceMetrics.viewHeight / Minimap.workspace.scale) * Minimap.minimap.scale;
var draggerHeight = (workspaceMetrics.viewHeight / Minimap.workspace.scale) *
Minimap.minimap.scale;
// It's zero when first block is placed.
if(draggerHeight == 0){
if (draggerHeight == 0) {
return;
}
Minimap.mapDragger.setAttribute("height", draggerHeight);
Minimap.mapDragger.setAttribute('height', draggerHeight);
};
/**
* Updates the rectangle's width.
*/
Minimap.setDraggerWidth = function(){
* Updates the rectangle's width.
*/
Minimap.setDraggerWidth = function() {
var workspaceMetrics = Minimap.workspace.getMetrics();
var draggerWidth = (workspaceMetrics.viewWidth / Minimap.workspace.scale) * Minimap.minimap.scale;
var draggerWidth = (workspaceMetrics.viewWidth / Minimap.workspace.scale) *
Minimap.minimap.scale;
// It's zero when first block is placed.
if(draggerWidth == 0){
if (draggerWidth == 0) {
return;
}
Minimap.mapDragger.setAttribute("width", draggerWidth);
Minimap.mapDragger.setAttribute('width', draggerWidth);
};
/**
* Updates the overall position of the viewport of the minimap by appropriately
* using translate functions.
*/
Minimap.scaleMinimap = function(){
* Updates the overall position of the viewport of the minimap by appropriately
* using translate functions.
*/
Minimap.scaleMinimap = function() {
var minimapBoundingBox = Minimap.minimap.getBlocksBoundingBox();
var workspaceBoundingBox = Minimap.workspace.getBlocksBoundingBox();
var workspaceMetrics = Minimap.workspace.getMetrics();
var minimapMetrics = Minimap.minimap.getMetrics();
//Scaling the mimimap such that all the blocks can be seen in the viewport.
//This padding is default because this is how to scrollbar(in main workspace) is implemented.
var topPadding = (workspaceMetrics.viewHeight) * Minimap.minimap.scale / (2 * Minimap.workspace.scale);
var sidePadding = (workspaceMetrics.viewWidth) * Minimap.minimap.scale / (2 * Minimap.workspace.scale);
// Scaling the mimimap such that all the blocks can be seen in the viewport.
// This padding is default because this is how to scrollbar(in main workspace)
// is implemented.
var topPadding = (workspaceMetrics.viewHeight) * Minimap.minimap.scale /
(2 * Minimap.workspace.scale);
var sidePadding = (workspaceMetrics.viewWidth) * Minimap.minimap.scale /
(2 * Minimap.workspace.scale);
// If actual padding is more than half view ports height, change it to actual padding.
if((workspaceBoundingBox.y * Minimap.workspace.scale - workspaceMetrics.contentTop)
* Minimap.minimap.scale / Minimap.workspace.scale > topPadding){
topPadding = (workspaceBoundingBox.y * Minimap.workspace.scale - workspaceMetrics.contentTop)
* Minimap.minimap.scale / Minimap.workspace.scale;
// If actual padding is more than half view ports height,
// change it to actual padding.
if ((workspaceBoundingBox.y * Minimap.workspace.scale -
workspaceMetrics.contentTop) *
Minimap.minimap.scale / Minimap.workspace.scale > topPadding) {
topPadding = (workspaceBoundingBox.y * Minimap.workspace.scale -
workspaceMetrics.contentTop) *
Minimap.minimap.scale / Minimap.workspace.scale;
}
// If actual padding is more than half view ports height, change it to actual padding.
if((workspaceBoundingBox.x * Minimap.workspace.scale - workspaceMetrics.contentLeft)
* Minimap.minimap.scale / Minimap.workspace.scale > sidePadding){
sidePadding = (workspaceBoundingBox.x * Minimap.workspace.scale - workspaceMetrics.contentLeft)
* Minimap.minimap.scale / Minimap.workspace.scale;
// If actual padding is more than half view ports height,
// change it to actual padding.
if ((workspaceBoundingBox.x * Minimap.workspace.scale -
workspaceMetrics.contentLeft) *
Minimap.minimap.scale / Minimap.workspace.scale > sidePadding) {
sidePadding = (workspaceBoundingBox.x * Minimap.workspace.scale -
workspaceMetrics.contentLeft) *
Minimap.minimap.scale / Minimap.workspace.scale;
}
var scalex = (minimapMetrics.viewWidth - 2 * sidePadding) / minimapBoundingBox.width;
var scaley = (minimapMetrics.viewHeight - 2 * topPadding) / minimapBoundingBox.height;
var scalex = (minimapMetrics.viewWidth - 2 * sidePadding) /
minimapBoundingBox.width;
var scaley = (minimapMetrics.viewHeight - 2 * topPadding) /
minimapBoundingBox.height;
Minimap.minimap.setScale(Math.min(scalex, scaley));
// Translating the minimap.
Minimap.minimap.translate( - minimapMetrics.contentLeft * Minimap.minimap.scale + sidePadding,
- minimapMetrics.contentTop * Minimap.minimap.scale + topPadding);
Minimap.minimap.translate(
-minimapMetrics.contentLeft * Minimap.minimap.scale + sidePadding,
-minimapMetrics.contentTop * Minimap.minimap.scale + topPadding);
};
/**
* Handles the onclick event on the minimapBoundingBox. Changes mapDraggers position.
* @param {Event} e Event from the mouse click.
*/
Minimap.updateMapDragger = function(e){
* Handles the onclick event on the minimapBoundingBox.
* Changes mapDraggers position.
* @param {!Event} e Event from the mouse click.
*/
Minimap.updateMapDragger = function(e) {
var y = e.clientY;
var x = e.clientX;
var draggerHeight = Minimap.mapDragger.getAttribute("height");
var draggerWidth = Minimap.mapDragger.getAttribute("width");
var draggerHeight = Minimap.mapDragger.getAttribute('height');
var draggerWidth = Minimap.mapDragger.getAttribute('width');
var finalY = y - Minimap.rect.top - draggerHeight / 2;
var finalX = x - Minimap.rect.left - draggerWidth / 2;
var maxValidY = (Minimap.workspace.getMetrics().contentHeight - Minimap.workspace.getMetrics().viewHeight)
* Minimap.minimap.scale;
var maxValidX = (Minimap.workspace.getMetrics().contentWidth - Minimap.workspace.getMetrics().viewWidth)
* Minimap.minimap.scale;
var maxValidY = (Minimap.workspace.getMetrics().contentHeight -
Minimap.workspace.getMetrics().viewHeight) * Minimap.minimap.scale;
var maxValidX = (Minimap.workspace.getMetrics().contentWidth -
Minimap.workspace.getMetrics().viewWidth) * Minimap.minimap.scale;
if(y + draggerHeight / 2 > Minimap.rect.bottom){
if (y + draggerHeight / 2 > Minimap.rect.bottom) {
finalY = Minimap.rect.bottom - Minimap.rect.top - draggerHeight;
}else if(y < Minimap.rect.top + draggerHeight / 2){
} else if (y < Minimap.rect.top + draggerHeight / 2) {
finalY = 0;
}
if(x + draggerWidth / 2 > Minimap.rect.right){
if (x + draggerWidth / 2 > Minimap.rect.right) {
finalX = Minimap.rect.right - Minimap.rect.left - draggerWidth;
}else if(x < Minimap.rect.left + draggerWidth / 2){
} else if (x < Minimap.rect.left + draggerWidth / 2) {
finalX = 0;
}
// Do not go below lower bound of scrollbar.
if(finalY > maxValidY){
if (finalY > maxValidY) {
finalY = maxValidY;
}
if(finalX > maxValidX){
if (finalX > maxValidX) {
finalX = maxValidX;
}
Minimap.mapDragger.setAttribute("y", finalY);
Minimap.mapDragger.setAttribute("x", finalX);
Minimap.mapDragger.setAttribute('y', finalY);
Minimap.mapDragger.setAttribute('x', finalX);
// Required, otherwise creates a feedback loop.
Minimap.disableScrollChange = true;
Minimap.workspace.scrollbar.vScroll.set((finalY * Minimap.workspace.scale) / Minimap.minimap.scale);
Minimap.workspace.scrollbar.hScroll.set((finalX * Minimap.workspace.scale) / Minimap.minimap.scale);
Minimap.workspace.scrollbar.vScroll.set((finalY * Minimap.workspace.scale) /
Minimap.minimap.scale);
Minimap.workspace.scrollbar.hScroll.set((finalX * Minimap.workspace.scale) /
Minimap.minimap.scale);
Minimap.disableScrollChange = false;
};
/**
* Handles the onclick event on the minimapBoundingBox, paramaters are passed by
* the event handler.
* @param {Float} position This is the absolute postion of the scrollbar.
* @param {boolean} horizontal Informs if the change event if for horizontal(true)
* scrollbar or vertical(false) scrollbar.
*/
Minimap.onScrollChange = function(position, horizontal){
if(Minimap.disableScrollChange){
return;
}
var newDraggerPosition = (position * Minimap.minimap.scale / Minimap.workspace.scale);
if(horizontal){
// Change the horizontal position of dragger.
Minimap.mapDragger.setAttribute("x", newDraggerPosition);
}
else{
// Change the vertical position of dragger.
Minimap.mapDragger.setAttribute("y", newDraggerPosition);
* Handles the onclick event on the minimapBoundingBox, parameters are passed by
* the event handler.
* @param {number} position This is the absolute position of the scrollbar.
* @param {boolean} horizontal Informs if the change event if for
* horizontal (true) or vertical (false) scrollbar.
*/
Minimap.onScrollChange = function(position, horizontal) {
if (!Minimap.disableScrollChange) {
Minimap.mapDragger.setAttribute(horizontal ? 'x' : 'y',
position * Minimap.minimap.scale / Minimap.workspace.scale);
}
};
+3 -3
View File
@@ -47,7 +47,7 @@ Blockly.Dart['procedures_defreturn'] = function(block) {
var returnValue = Blockly.Dart.valueToCode(block, 'RETURN',
Blockly.Dart.ORDER_NONE) || '';
if (returnValue) {
returnValue = ' return ' + returnValue + ';\n';
returnValue = Blockly.Dart.INDENT + 'return ' + returnValue + ';\n';
}
var returnType = returnValue ? 'dynamic' : 'void';
var args = [];
@@ -101,9 +101,9 @@ Blockly.Dart['procedures_ifreturn'] = function(block) {
if (block.hasReturnValue_) {
var value = Blockly.Dart.valueToCode(block, 'VALUE',
Blockly.Dart.ORDER_NONE) || 'null';
code += ' return ' + value + ';\n';
code += Blockly.Dart.INDENT + 'return ' + value + ';\n';
} else {
code += ' return;\n';
code += Blockly.Dart.INDENT + 'return;\n';
}
code += '}\n';
return code;
+3 -3
View File
@@ -47,7 +47,7 @@ Blockly.JavaScript['procedures_defreturn'] = function(block) {
var returnValue = Blockly.JavaScript.valueToCode(block, 'RETURN',
Blockly.JavaScript.ORDER_NONE) || '';
if (returnValue) {
returnValue = ' return ' + returnValue + ';\n';
returnValue = Blockly.JavaScript.INDENT + 'return ' + returnValue + ';\n';
}
var args = [];
for (var i = 0; i < block.arguments_.length; i++) {
@@ -101,9 +101,9 @@ Blockly.JavaScript['procedures_ifreturn'] = function(block) {
if (block.hasReturnValue_) {
var value = Blockly.JavaScript.valueToCode(block, 'VALUE',
Blockly.JavaScript.ORDER_NONE) || 'null';
code += ' return ' + value + ';\n';
code += Blockly.JavaScript.INDENT + 'return ' + value + ';\n';
} else {
code += ' return;\n';
code += Blockly.JavaScript.INDENT + 'return;\n';
}
code += '}\n';
return code;
+3 -3
View File
@@ -47,7 +47,7 @@ Blockly.Lua['procedures_defreturn'] = function(block) {
var returnValue = Blockly.Lua.valueToCode(block, 'RETURN',
Blockly.Lua.ORDER_NONE) || '';
if (returnValue) {
returnValue = ' return ' + returnValue + '\n';
returnValue = Blockly.Lua.INDENT + 'return ' + returnValue + '\n';
} else if (!branch) {
branch = '';
}
@@ -103,9 +103,9 @@ Blockly.Lua['procedures_ifreturn'] = function(block) {
if (block.hasReturnValue_) {
var value = Blockly.Lua.valueToCode(block, 'VALUE',
Blockly.Lua.ORDER_NONE) || 'nil';
code += ' return ' + value + '\n';
code += Blockly.Lua.INDENT + 'return ' + value + '\n';
} else {
code += ' return\n';
code += Blockly.Lua.INDENT + 'return\n';
}
code += 'end\n';
return code;
+4 -4
View File
@@ -43,7 +43,7 @@ Blockly.PHP['procedures_defreturn'] = function(block) {
Blockly.Variables.NAME_TYPE));
}
}
globals = globals.length ? ' global ' + globals.join(', ') + ';\n' : '';
globals = globals.length ? Blockly.PHP.INDENT + 'global ' + globals.join(', ') + ';\n' : '';
var funcName = Blockly.PHP.variableDB_.getName(
block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE);
@@ -61,7 +61,7 @@ Blockly.PHP['procedures_defreturn'] = function(block) {
var returnValue = Blockly.PHP.valueToCode(block, 'RETURN',
Blockly.PHP.ORDER_NONE) || '';
if (returnValue) {
returnValue = ' return ' + returnValue + ';\n';
returnValue = Blockly.PHP.INDENT + 'return ' + returnValue + ';\n';
}
var args = [];
for (var i = 0; i < block.arguments_.length; i++) {
@@ -115,9 +115,9 @@ Blockly.PHP['procedures_ifreturn'] = function(block) {
if (block.hasReturnValue_) {
var value = Blockly.PHP.valueToCode(block, 'VALUE',
Blockly.PHP.ORDER_NONE) || 'null';
code += ' return ' + value + ';\n';
code += Blockly.PHP.INDENT + 'return ' + value + ';\n';
} else {
code += ' return;\n';
code += Blockly.PHP.INDENT + 'return;\n';
}
code += '}\n';
return code;
+4 -4
View File
@@ -44,7 +44,7 @@ Blockly.Python['procedures_defreturn'] = function(block) {
Blockly.Variables.NAME_TYPE));
}
}
globals = globals.length ? ' global ' + globals.join(', ') + '\n' : '';
globals = globals.length ? Blockly.Python.INDENT + 'global ' + globals.join(', ') + '\n' : '';
var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'),
Blockly.Procedures.NAME_TYPE);
var branch = Blockly.Python.statementToCode(block, 'STACK');
@@ -61,7 +61,7 @@ Blockly.Python['procedures_defreturn'] = function(block) {
var returnValue = Blockly.Python.valueToCode(block, 'RETURN',
Blockly.Python.ORDER_NONE) || '';
if (returnValue) {
returnValue = ' return ' + returnValue + '\n';
returnValue = Blockly.Python.INDENT + 'return ' + returnValue + '\n';
} else if (!branch) {
branch = Blockly.Python.PASS;
}
@@ -117,9 +117,9 @@ Blockly.Python['procedures_ifreturn'] = function(block) {
if (block.hasReturnValue_) {
var value = Blockly.Python.valueToCode(block, 'VALUE',
Blockly.Python.ORDER_NONE) || 'None';
code += ' return ' + value + '\n';
code += Blockly.Python.INDENT + 'return ' + value + '\n';
} else {
code += ' return\n';
code += Blockly.Python.INDENT + 'return\n';
}
return code;
};
+1 -1
View File
@@ -140,7 +140,7 @@ goog.require('Blockly.Msg');
/** @export */ Blockly.Msg.LISTS_LENGTH_TITLE = "hirder %1";
/** @export */ Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Distreiñ hirder ul listenn.";
/** @export */ Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated
/** @export */ Blockly.Msg.LISTS_REPEAT_TITLE = "Krouiñ ul listenn gant an elfenn %1 arreet div wech";
/** @export */ Blockly.Msg.LISTS_REPEAT_TITLE = "Krouiñ ul listenn gant an elfenn %1 arreet %2 div wech";
/** @export */ Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Krouiñ ul listenn a c'hoarvez eus an dalvoudenn roet arreet an niver a wech meneget";
/** @export */ Blockly.Msg.LISTS_REVERSE_HELPURL = "https://github.com/google/blockly/wiki/Lists#reversing-a-list";
/** @export */ Blockly.Msg.LISTS_REVERSE_MESSAGE0 = "eilpennañ %1";
+1 -1
View File
@@ -39,7 +39,7 @@ goog.require('Blockly.Msg');
/** @export */ Blockly.Msg.CONTROLS_FOREACH_TITLE = "para cada item %1 na lista %2";
/** @export */ Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Para cada item numa lista, define a variável \"%1\" para o item e então faz algumas instruções.";
/** @export */ Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated
/** @export */ Blockly.Msg.CONTROLS_FOR_TITLE = "contar com %1 de %2 até %3 de %3 em %4";
/** @export */ Blockly.Msg.CONTROLS_FOR_TITLE = "contar com %1 de %2 até %3 por %4";
/** @export */ Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Faz com que a variável \"%1\" assuma os valores desde o número inicial até ao número final, contando de acordo com o intervalo especificado e executa os blocos especificados.";
/** @export */ Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Acrescente uma condição ao bloco se.";
/** @export */ Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Acrescente uma condição de excepação final para o bloco se.";
+1 -1
View File
@@ -247,7 +247,7 @@
"LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Ouzhpennañ, lemel pe adurzhiañ ar rannoù evit kefluniañ ar bloc'h listenn-mañ.",
"LISTS_CREATE_WITH_ITEM_TOOLTIP": "Ouzhpennañ un elfenn d'ar roll",
"LISTS_REPEAT_TOOLTIP": "Krouiñ ul listenn a c'hoarvez eus an dalvoudenn roet arreet an niver a wech meneget",
"LISTS_REPEAT_TITLE": "Krouiñ ul listenn gant an elfenn %1 arreet div wech",
"LISTS_REPEAT_TITLE": "Krouiñ ul listenn gant an elfenn %1 arreet %2 div wech",
"LISTS_LENGTH_TITLE": "hirder %1",
"LISTS_LENGTH_TOOLTIP": "Distreiñ hirder ul listenn.",
"LISTS_ISEMPTY_TITLE": "%1 zo goullo",
+1 -1
View File
@@ -67,7 +67,7 @@
"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Enquanto um valor for verdadeiro, então faça algumas instruções.",
"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Enquanto um valor for falso, então faça algumas instruções.",
"CONTROLS_FOR_TOOLTIP": "Faz com que a variável \"%1\" assuma os valores desde o número inicial até ao número final, contando de acordo com o intervalo especificado e executa os blocos especificados.",
"CONTROLS_FOR_TITLE": "contar com %1 de %2 até %3 de %3 em %4",
"CONTROLS_FOR_TITLE": "contar com %1 de %2 até %3 por %4",
"CONTROLS_FOREACH_TITLE": "para cada item %1 na lista %2",
"CONTROLS_FOREACH_TOOLTIP": "Para cada item numa lista, define a variável \"%1\" para o item e então faz algumas instruções.",
"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "sair do ciclo",
+5 -2
View File
@@ -17,8 +17,8 @@
"name": "Neil Fraser"
},
"scripts": {
"lint": "jshint .",
"pretest": "scripts/test_setup.sh",
"lint": "eslint .",
"pretest": "tests/scripts/test_setup.sh",
"test": "node tests/jsunit/test_runner.js"
},
"license": "Apache-2.0",
@@ -45,5 +45,8 @@
"npm": "^4.4.4",
"closure-library": "^1.43629075.2",
"webdriverio": "^4.6.2"
},
"devDependencies": {
"eslint": "2.9.0"
}
}
+34
View File
@@ -0,0 +1,34 @@
# Find the Closure Compiler.
if [ -f "$(npm root)/google-closure-compiler/compiler.jar" ]; then
# Travis test.
COMPILER="$(npm root)/google-closure-compiler/compiler.jar"
elif [ -f *compiler*.jar ]; then
# Manual test.
COMPILER="*compiler*.jar"
else
echo "ERROR: Closure Compiler not found."
echo "Download from this URL, and place jar file in current directory."
echo "https://dl.google.com/closure-compiler/compiler-latest.zip"
exit 1
fi
rm main_compressed.js 2> /dev/null
echo Compiling Blockly...
java -jar $COMPILER --js='main.js' \
--js='../../core/**.js' \
--js='../../blocks/**.js' \
--js='../../generators/**.js' \
--js='../../msg/js/**.js' \
--js='../../../closure-library/closure/goog/**.js' \
--js='../../../closure-library/third_party/closure/goog/**.js' \
--generate_exports \
--externs ../../externs/svg-externs.js \
--compilation_level ADVANCED_OPTIMIZATIONS \
--dependency_mode=STRICT --entry_point=Main \
--js_output_file main_compressed.js
if [ -s main_compressed.js ]; then
echo Compilation OK.
else
echo Compilation FAIL.
exit 1
fi
@@ -2,7 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<title>Blockly Demo: Fixed Blockly built with Closure Compiler&apos;s advanced optimizations</title>
<title>Blockly: Advanced Compilation Test</title>
<script src="main_compressed.js"></script>
<style>
body {
@@ -16,21 +16,16 @@
</style>
</head>
<body>
<h1>
<a href="https://developers.google.com/blockly/">Blockly</a> &gt;
<a href="../index.html">Demos</a> &gt;
Fixed Blockly built with Closure Compiler&apos;s advanced optimizations
</h1>
<h1>Blockly: Advanced Compilation Test</h1>
<p>
This is a simple demo of injecting Blockly into a fixed-sized 'div' element
from a Closure-compiled source code with advanced optimizations.
</p>
<p>To run this test manually, download
<a href="https://dl.google.com/closure-compiler/compiler-latest.zip">closure-compiler-vxxxxxxxx.jar</a>,
place it in this directory, then run compile.js from the command line.</p>
<p>&rarr; More info on <a href="https://developers.google.com/blockly/guides/configure-blockly/web/fixed-size">injecting fixed-sized Blockly</a>&hellip;</p>
<p>Measure the size of main_compressed.js (295kb as of October 2017), then reload
this page and see if Blockly works.</p>
<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>
<xml id="toolbox" style="display: none">
<block type="controls_if"></block>
<block type="logic_compare"></block>
@@ -40,6 +35,5 @@
<block type="text"></block>
<block type="text_print"></block>
</xml>
</body>
</html>
+17
View File
@@ -0,0 +1,17 @@
goog.provide('Main');
// Messages (in some language)
goog.require('Blockly.Msg.en');
// Core
goog.require('Blockly');
// Blocks
goog.require('Blockly.Constants.Logic');
goog.require('Blockly.Constants.Loops');
goog.require('Blockly.Constants.Math');
goog.require('Blockly.Constants.Text');
Main.init = function() {
Blockly.inject('blocklyDiv', {
'toolbox': document.getElementById('toolbox')
});
};
window.addEventListener('load', Main.init);
+1 -1
View File
@@ -304,4 +304,4 @@ function helper_createConnection(x, y, type, opt_shared_workspace,
conn.x_ = x;
conn.y_ = y;
return conn;
}
}
-76
View File
@@ -1,76 +0,0 @@
/**
* @license
* Blockly Tests
*
* Copyright 2016 Google Inc.
* https://developers.google.com/blockly/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
function test_DB_getNeighbours() {
var db = new Blockly.ConnectionDB();
// Search an empty list.
assertEquals(helper_getNeighbours(db, 10 /* x */, 10 /* y */, 100 /* radius */).length, 0);
// Set up some connections.
for (var i = 0; i < 10; i++) {
db.addConnection_(helper_createConnection(0, i, Blockly.PREVIOUS_STATEMENT));
}
// Test block belongs at beginning
var result = helper_getNeighbours(db, 0, 0, 4);
assertEquals(5, result.length);
for (i = 0; i < result.length; i++) {
assertNotEquals(result.indexOf(db[i]), -1); // contains
}
// Test block belongs at middle
result = helper_getNeighbours(db, 0, 4, 2);
assertEquals(5, result.length);
for (i = 0; i < result.length; i++) {
assertNotEquals(result.indexOf(db[i + 2]), -1); // contains
}
// Test block belongs at end
result = helper_getNeighbours(db, 0, 9, 4);
assertEquals(5, result.length);
for (i = 0; i < result.length; i++) {
assertNotEquals(result.indexOf(db[i + 5]), -1); // contains
}
// Test block has no neighbours due to being out of range in the x direction
result = helper_getNeighbours(db, 10, 9, 4);
assertEquals(result.length, 0);
// Test block has no neighbours due to being out of range in the y direction
result = helper_getNeighbours(db, 0, 19, 4);
assertEquals(result.length, 0);
// Test block has no neighbours due to being out of range diagonally
result = helper_getNeighbours(db, -2, -2, 2);
assertEquals(result.length, 0);
}
function helper_getNeighbours(db, x, y, radius) {
return db.getNeighbours(helper_createConnection(x, y, Blockly.NEXT_STATEMENT), radius);
}
function helper_createConnection(x, y, type) {
var conn = new Blockly.Connection({workspace: {}}, type);
conn.x_ = x;
conn.y_ = y;
return conn;
}
+48
View File
@@ -512,6 +512,48 @@ function test_events_mergeUi() {
eventTest_tearDownWithMockBlocks();
}
/**
* Tests that events that collide on a (event, block, workspace) tuple
* but cannot be merged do not get dropped during filtering.
*/
function test_events_stackclick() {
eventTest_setUpWithMockBlocks();
var block = workspace.newBlock('field_variable_test_block', '1');
var events = [
new Blockly.Events.Ui(block, 'click', undefined, undefined),
new Blockly.Events.Ui(block, 'stackclick', undefined, undefined)
];
var filteredEvents = Blockly.Events.filter(events, true);
// click and stackclick should both exist
assertEquals(2, filteredEvents.length);
assertEquals('click', filteredEvents[0].element);
assertEquals('stackclick', filteredEvents[1].element);
eventTest_tearDownWithMockBlocks();
}
/**
* Mutator composition could result in move events for blocks
* connected to the mutated block that were null operations. This
* leads to events in the undo/redo queue that do nothing, requiring
* an extra undo/redo to proceed to the next event. This test ensures
* that two move events that do get merged (disconnecting and
* reconnecting a block in response to a mutator change) are filtered
* from the queue.
*/
function test_events_filteraftermerge() {
eventTest_setUpWithMockBlocks();
var block = workspace.newBlock('field_variable_test_block', '1');
block.setParent(null);
var events = [];
helper_addMoveEventParent(events, block, null);
helper_addMoveEventParent(events, block, null);
var filteredEvents = Blockly.Events.filter(events, true);
// The two events should be merged, but because nothing has changed
// they will be filtered out.
assertEquals(0, filteredEvents.length);
eventTest_tearDownWithMockBlocks();
}
/**
* Helper function to simulate block move events.
*
@@ -525,3 +567,9 @@ function helper_addMoveEvent(events, block, newX, newY) {
block.xy_ = new goog.math.Coordinate(newX, newY);
events[events.length-1].recordNew();
}
function helper_addMoveEventParent(events, block, parent) {
events.push(new Blockly.Events.BlockMove(block));
block.setParent(parent);
events[events.length-1].recordNew();
}
+9 -9
View File
@@ -8,26 +8,26 @@
</head>
<body>
<script src="test_utilities.js"></script>
<script src="utils_test.js"></script>
<script src="connection_test.js"></script>
<script src="connection_db_test.js"></script>
<script src="extensions_test.js"></script>
<script src="connection_test.js"></script>
<script src="event_test.js"></script>
<script src="field_test.js"></script>
<script src="extensions_test.js"></script>
<script src="field_angle_test.js"></script>
<script src="field_number_test.js"></script>
<script src="field_test.js"></script>
<script src="field_variable_test.js"></script>
<script src="generator_test.js"></script>
<script src="gesture_test.js"></script>
<script src="input_test.js"></script>
<script src="json_test.js"></script>
<script src="names_test.js"></script>
<script src="procedures_test.js"></script>
<script src="utils_test.js"></script>
<script src="variable_map_test.js"></script>
<script src="variable_model_test.js"></script>
<script src="widget_div_test.js"></script>
<script src="workspace_test.js"></script>
<script src="workspace_undo_redo_test.js"></script>
<script src="xml_test.js"></script>
<script src="json_test.js"></script>
<script src="procedures_test.js"></script>
<script src="variable_model_test.js"></script>
<script src="variable_map_test.js"></script>
<script src="widget_div_test.js"></script>
</body>
</html>
+6 -6
View File
@@ -19,8 +19,8 @@
*/
/**
* @fileoverview Tests for Blockly.Input
*/
* @fileoverview Tests for Blockly.Input
*/
'use strict';
function test_appendField_simple() {
@@ -157,7 +157,7 @@ function test_insertFieldAt_prefix() {
var after = new Blockly.FieldLabel('after');
var prefix = new Blockly.FieldLabel('prefix');
var between = new Blockly.FieldLabel('between');
between.prefixField = prefix
between.prefixField = prefix;
input.appendField(before);
input.appendField(after);
@@ -175,7 +175,7 @@ function test_insertFieldAt_prefix() {
assertEquals(after, input.fieldRow[3]);
}
function test_insertFieldAt_prefix() {
function test_insertFieldAt_suffix() {
var ws = new Blockly.Workspace();
var block = new Blockly.Block(ws);
var input = new Blockly.Input(Blockly.DUMMY_INPUT, 'INPUT', block);
@@ -183,7 +183,7 @@ function test_insertFieldAt_prefix() {
var after = new Blockly.FieldLabel('after');
var suffix = new Blockly.FieldLabel('suffix');
var between = new Blockly.FieldLabel('between');
between.suffixField = suffix
between.suffixField = suffix;
input.appendField(before);
input.appendField(after);
@@ -199,4 +199,4 @@ function test_insertFieldAt_prefix() {
assertEquals(between, input.fieldRow[1]);
assertEquals(suffix, input.fieldRow[2]);
assertEquals(after, input.fieldRow[3]);
}
}
-1
View File
@@ -257,4 +257,3 @@ function test_json_dropdown_image() {
delete Blockly.Msg['ALTTEXT'];
}
}
-1
View File
@@ -80,4 +80,3 @@ function test_isNameUsed_True() {
assertTrue(result);
proceduresTest_tearDownWithMockBlocks();
}
+41 -25
View File
@@ -42,14 +42,14 @@ function test_addClass() {
assertEquals('Adding "three"', 'one two three', p.className);
}
function test_hasClass() {
var p = document.createElement('p');
p.className = ' one three two three ';
assertTrue('Has "one"', Blockly.utils.hasClass(p, 'one'));
assertTrue('Has "two"', Blockly.utils.hasClass(p, 'two'));
assertTrue('Has "three"', Blockly.utils.hasClass(p, 'three'));
assertFalse('Has no "four"', Blockly.utils.hasClass(p, 'four'));
assertFalse('Has no "t"', Blockly.utils.hasClass(p, 't'));
function test_hasClass() {
var p = document.createElement('p');
p.className = ' one three two three ';
assertTrue('Has "one"', Blockly.utils.hasClass(p, 'one'));
assertTrue('Has "two"', Blockly.utils.hasClass(p, 'two'));
assertTrue('Has "three"', Blockly.utils.hasClass(p, 'three'));
assertFalse('Has no "four"', Blockly.utils.hasClass(p, 'four'));
assertFalse('Has no "t"', Blockly.utils.hasClass(p, 't'));
}
function test_removeClass() {
@@ -128,19 +128,19 @@ function test_tokenizeInterpolation() {
tokens = Blockly.utils.tokenizeInterpolation('Hello');
assertArrayEquals('No interpolation', ['Hello'], tokens);
tokens = Blockly.utils.tokenizeInterpolation('Hello%World');
assertArrayEquals('Unescaped %.', ['Hello%World'], tokens);
tokens = Blockly.utils.tokenizeInterpolation('Hello%%World');
assertArrayEquals('Escaped %.', ['Hello%World'], tokens);
tokens = Blockly.utils.tokenizeInterpolation('Hello %1 World');
assertArrayEquals('Interpolation.', ['Hello ', 1, ' World'], tokens);
tokens = Blockly.utils.tokenizeInterpolation('%123Hello%456World%789');
assertArrayEquals('Interpolations.', [123, 'Hello', 456, 'World', 789], tokens);
tokens = Blockly.utils.tokenizeInterpolation('%%%x%%0%00%01%');
assertArrayEquals('Torture interpolations.', ['%%x%0', 0, 1, '%'], tokens);
@@ -192,22 +192,13 @@ function test_tokenizeInterpolation() {
function test_replaceMessageReferences() {
Blockly.Msg = Blockly.Msg || {};
Blockly.Msg.STRING_REF = 'test string';
Blockly.Msg.SUBREF = 'subref';
Blockly.Msg.STRING_REF_WITH_ARG = 'test %1 string';
Blockly.Msg.STRING_REF_WITH_SUBREF = 'test %{bky_subref} string';
var resultString = Blockly.utils.replaceMessageReferences('');
assertEquals('Empty string produces empty string', '', resultString);
resultString = Blockly.utils.replaceMessageReferences('%{bky_string_ref}');
assertEquals('Message ref dereferenced.', 'test string', resultString);
resultString = Blockly.utils.replaceMessageReferences('before %{bky_string_ref} after');
assertEquals('Message ref dereferenced.', 'before test string after', resultString);
resultString = Blockly.utils.replaceMessageReferences('%1');
assertEquals('Interpolation tokens ignored.', '%1', resultString);
resultString = Blockly.utils.replaceMessageReferences('%1 %2');
assertEquals('Interpolation tokens ignored.', '%1 %2', resultString);
resultString = Blockly.utils.replaceMessageReferences('before %1 after');
assertEquals('Interpolation tokens ignored.', 'before %1 after', resultString);
resultString = Blockly.utils.replaceMessageReferences('%%');
assertEquals('Escaped %', '%', resultString);
resultString = Blockly.utils.replaceMessageReferences('%%{bky_string_ref}');
@@ -215,4 +206,29 @@ function test_replaceMessageReferences() {
resultString = Blockly.utils.replaceMessageReferences('%a');
assertEquals('Unrecognized % escape code treated as literal', '%a', resultString);
resultString = Blockly.utils.replaceMessageReferences('%1');
assertEquals('Interpolation tokens ignored.', '%1', resultString);
resultString = Blockly.utils.replaceMessageReferences('%1 %2');
assertEquals('Interpolation tokens ignored.', '%1 %2', resultString);
resultString = Blockly.utils.replaceMessageReferences('before %1 after');
assertEquals('Interpolation tokens ignored.', 'before %1 after', resultString);
// Blockly.Msg.STRING_REF cases:
resultString = Blockly.utils.replaceMessageReferences('%{bky_string_ref}');
assertEquals('Message ref dereferenced.', 'test string', resultString);
resultString = Blockly.utils.replaceMessageReferences('before %{bky_string_ref} after');
assertEquals('Message ref dereferenced.', 'before test string after', resultString);
// Blockly.Msg.STRING_REF_WITH_ARG cases:
resultString = Blockly.utils.replaceMessageReferences('%{bky_string_ref_with_arg}');
assertEquals('Message ref dereferenced with argument preserved.', 'test %1 string', resultString);
resultString = Blockly.utils.replaceMessageReferences('before %{bky_string_ref_with_arg} after');
assertEquals('Message ref dereferenced with argument preserved.', 'before test %1 string after', resultString);
// Blockly.Msg.STRING_REF_WITH_SUBREF cases:
resultString = Blockly.utils.replaceMessageReferences('%{bky_string_ref_with_subref}');
assertEquals('Message ref and subref dereferenced.', 'test subref string', resultString);
resultString = Blockly.utils.replaceMessageReferences('before %{bky_string_ref_with_subref} after');
assertEquals('Message ref and subref dereferenced.', 'before test subref string after', resultString);
}
+2 -4
View File
@@ -131,8 +131,7 @@ function test_createVariableNullId() {
try {
variable_map.createVariable('name1', 'type1', null);
checkVariableValues(variable_map, 'name1', 'type1', '1');
}
finally {
} finally {
variableMapTest_tearDown();
}
}
@@ -143,8 +142,7 @@ function test_createVariableUndefinedId() {
try {
variable_map.createVariable('name1', 'type1', undefined);
checkVariableValues(variable_map, 'name1', 'type1', '1');
}
finally {
} finally {
variableMapTest_tearDown();
}
}
-1
View File
@@ -151,4 +151,3 @@ function test_widgetDiv_noXConflict_RTL() {
anchorBBox, widgetDiv_test_widgetSize, true /* rtl */);
assertEquals(anchorBBox.right - widgetDiv_test_widgetSize.width, calculated);
}
+9 -18
View File
@@ -66,8 +66,7 @@ function test_emptyWorkspace() {
assertEquals('Empty workspace (4).', 0, workspace.getTopBlocks(true).length);
assertEquals('Empty workspace (5).', 0, workspace.getTopBlocks(false).length);
assertEquals('Empty workspace (6).', 0, workspace.getAllBlocks().length);
}
finally {
} finally {
workspaceTest_tearDown();
}
}
@@ -187,8 +186,7 @@ function test_updateVariableStore_TrivialNoClear() {
workspace.updateVariableStore();
checkVariableValues(workspace, 'name1', 'type1', 'id1');
checkVariableValues(workspace, 'name2', 'type2', 'id2');
}
finally {
} finally {
workspaceTest_tearDown();
}
}
@@ -202,8 +200,7 @@ function test_updateVariableStore_NameNotInvariableMap_NoClear() {
try {
workspace.updateVariableStore();
checkVariableValues(workspace, 'name1', '', '1');
}
finally {
} finally {
workspaceTest_tearDown();
}
}
@@ -219,8 +216,7 @@ function test_updateVariableStore_ClearAndAllInUse() {
workspace.updateVariableStore(true);
checkVariableValues(workspace, 'name1', 'type1', 'id1');
checkVariableValues(workspace, 'name2', 'type2', 'id2');
}
finally {
} finally {
workspaceTest_tearDown();
}
}
@@ -237,8 +233,7 @@ function test_updateVariableStore_ClearAndOneInUse() {
checkVariableValues(workspace, 'name1', 'type1', 'id1');
var variabe = workspace.getVariable('name2');
assertNull(variable);
}
finally {
} finally {
workspaceTest_tearDown();
}
}
@@ -255,8 +250,7 @@ function test_addTopBlock_TrivialFlyoutIsTrue() {
try {
workspace.addTopBlock(block);
checkVariableValues(workspace, 'name1', '', '1');
}
finally {
} finally {
workspaceTest_tearDown();
}
}
@@ -274,8 +268,7 @@ function test_clear_Trivial() {
var varMapLength = Object.keys(workspace.variableMap_.variableMap_).length;
assertEquals(0, topBlocks_length);
assertEquals(0, varMapLength);
}
finally {
} finally {
workspaceTest_tearDown();
}
}
@@ -291,8 +284,7 @@ function test_clear_NoVariables() {
var varMapLength = Object.keys(workspace.variableMap_.variableMap_).length;
assertEquals(0, topBlocks_length);
assertEquals(0, varMapLength);
}
finally {
} finally {
workspaceTest_tearDown();
}
}
@@ -312,8 +304,7 @@ function test_renameVariable_NoBlocks() {
checkVariableValues(workspace, 'name2', '', '1');
var variable = workspace.getVariable(oldName);
assertNull(variable);
}
finally {
} finally {
workspaceTest_tearDown();
}
}
+31 -6
View File
@@ -67,7 +67,7 @@ function xmlTest_setUpWithMockBlocks() {
'name': 'VAR',
'variable': 'item'
}
],
]
}]);
}
@@ -91,7 +91,7 @@ function xmlTest_checkNonVariableField(fieldDom, name, text) {
assertEquals(text, fieldDom.textContent);
assertEquals(name, fieldDom.getAttribute('name'));
assertNull(fieldDom.getAttribute('id'));
assertNull(fieldDom.getAttribute('variableType'));
assertNull(fieldDom.getAttribute('variabletype'));
}
/**
@@ -104,7 +104,7 @@ function xmlTest_checkNonVariableField(fieldDom, name, text) {
*/
function xmlTest_checkVariableFieldDomValues(fieldDom, name, type, id, text) {
assertEquals(name, fieldDom.getAttribute('name'));
assertEquals(type, fieldDom.getAttribute('variableType'));
assertEquals(type, fieldDom.getAttribute('variabletype'));
assertEquals(id, fieldDom.getAttribute('id'));
assertEquals(text, fieldDom.textContent);
}
@@ -166,7 +166,7 @@ function test_domToWorkspace_VariablesAtTop() {
' <variable type="" id="id3">name3</variable>' +
' </variables>' +
' <block type="field_variable_test_block">' +
' <field name="VAR" id="id3" variableType="">name3</field>' +
' <field name="VAR" id="id3" variabletype="">name3</field>' +
' </block>' +
'</xml>');
Blockly.Xml.domToWorkspace(dom, workspace);
@@ -210,7 +210,7 @@ function test_domToWorkspace_VariablesAtTop_MissingType() {
' <variable id="id1">name1</variable>' +
' </variables>' +
' <block type="field_variable_test_block">' +
' <field name="VAR" id="id1" variableType="">name3</field>' +
' <field name="VAR" id="id1" variabletype="">name3</field>' +
' </block>' +
'</xml>');
Blockly.Xml.domToWorkspace(dom, workspace);
@@ -233,7 +233,7 @@ function test_domToWorkspace_VariablesAtTop_MismatchBlockType() {
' <variable type="type1" id="id1">name1</variable>' +
' </variables>' +
' <block type="field_variable_test_block">' +
' <field name="VAR" id="id1" variableType="">name1</field>' +
' <field name="VAR" id="id1" variabletype="">name1</field>' +
' </block>' +
'</xml>');
Blockly.Xml.domToWorkspace(dom, workspace);
@@ -364,3 +364,28 @@ function test_variablesToDom_noVariables() {
assertEquals(1, resultDom.children.length);
xmlTest_tearDown();
}
function test_variableFieldXml_caseSensitive() {
var id = 'testId';
var type = 'testType';
var name = 'testName';
var mockVariableModel = {
type: type,
name: name,
getId: function() {
return id;
}
};
var generatedXml = Blockly.Variables.generateVariableFieldXml_(mockVariableModel);
// The field contains this XML tag as a result of how we're generating this
// XML. This is not desirable, but the goal of this test is to make sure
// we're preserving case-sensitivity.
var xmlns = 'xmlns="http://www.w3.org/1999/xhtml"';
var goldenXml =
'<field ' + xmlns + ' name="VAR"' +
' variabletype="' + type + '"' +
' id="' + id + '">' + name + '</field>';
assertEquals(goldenXml, generatedXml);
}
@@ -11,13 +11,13 @@ function check_command {
fi
}
check_command scripts/get_geckdriver.sh
check_command tests/scripts/get_geckdriver.sh
sleep 5
check_command scripts/get_selenium.sh
check_command tests/scripts/get_selenium.sh
sleep 5
check_command scripts/get_chromedriver.sh
check_command tests/scripts/get_chromedriver.sh
sleep 10
check_command scripts/selenium_connect.sh
check_command tests/scripts/selenium_connect.sh
sleep 10
exit $EXIT_STATUS