1.Google Blockly概述以及入门

一.什么是Blockly

(1)概述:

  • Blockly是一种可视化编程工具,是众多可视化编程工具的鼻祖。
  • 2012年6月,Google发布的完全可视化的编程语言Goole Blockly。
  • Blockly代码块由类似于积木的图形对象构成,只需要拖拖拽拽就可以实现程序的功能。

(2)详述:

  • 一种基于网页的可视化是程序:
    • Google Blockly是基于网页的可视化编程库,用户可以离线或者在线进行编程操作。
  • 多种开发语言环境库:
    • Blockly代码块可以通过自带的语言转换工具箱转换成JavaScript、Python、PHP、Lua、Dart等多种语言。
  • 开源的自定义编程环境:
    • 用户可以自己定义Blockly代码块放入Blockly的工具箱中,用于以后使用。

(3)Blockly的使用流程图:

  • 我们可以使用Blockly的工具箱编写Blockly代码块实现程序功能,然后使用语言转换器转换为需要的语言。
  • 我们也可以自定义Blockly代码块生成工具放入工具箱和语言转换器中,用于以后使用。

二.Blockly的编程环境

(1)Blockly有在线和离线版本

  • 在线版本网址: https://developers.google.cn/blockly
  • 离线版本下载网址:https://github.com/google/blockly
    • 下载后在demos目录下,使用浏览器打开index.html即可。

(2)Blockly在线版本

(3)Blockly离线版本

  • 离线Blockly的一些demo例子:

    •  Fixed Blockly :固定大小的Blockly块的工作空间,不会随浏览器大小变化而变化。
    •  Resizable Blockly :可变大小的Blockly块的工作空间,会随浏览器大小变化而变化。
    •  Defining the Toolbox :Blockly自定义的工具箱
    •  Maximum Block Limit :限制Blockly块的个数,不能超过指定Blockly个数。
    •  Generate JavaScript :生成JavaScript代码
    •  Headless :将xml代码生成其他的语言的代码
    •  JS Interpreter :展示使用Blockly代码块生成JavaScript代码并可以单步执行
    •  Graph :通过数学公式在坐标系中生成图形
    •  RTL :从右到左显示Blockly块(对于阿拉伯语和希伯来语使用)
    •  Custom Dialogs :自定义实现覆盖浏览器对话框
    •  Custom Fields :自定义字段
    •    Cloud Storage :云存储在App Engine
    •   Mirrored Blockly  :展示两个同步的Blockly工作区,左侧主工作区变化,右侧从工作区也发生变化。
    •  Accessible Blockly : 屏幕阅读无障碍访问版本
    •  Plane :支持35种语言
    •  Code Editor :将Blocky程序导出成JavaScript,Python,PHP,Lua,Dart或XML
    •  Blockly Developer Tools :使用Blockly构建自定义的代码块并设置到工作箱。

三.Blockly的功能模块

工具箱中有8个主要模块: blockly-master>demos>code>index.html 中可以查看源码

运行index.html结果:(右上角可以修改语言类型为简体中文)

主要为大家讲解三个文件 blockly_compressed.js , blocks_compressed.js , javascript_compressed.js 

(1)  blocks_compressed.js :定义了Blockly工具箱中的所有可用Blockly块,仅仅是Blockly.Blocks的内容。

以下:讲解loops(循环)模块程序代码

  • 其中 Blockly.defineBlocksWithJsonArray([{...},{...},{...},...]) :用于定义某一个工具,例如循环工具所有Blockly块。
  • 每一个 {...} 都包含一个循环模块的Blockly块:6个循环模块
    • controls_repeat_ext
    • controls_repeat
    • controls_whileUntil
    • controls_for
    • controls_forEach
    • controls_flow_statements
  1 Blockly.Blocks.loops = {};
  2 Blockly.Constants.Loops = {};
  3 Blockly.Constants.Loops.HUE = 120;
  4 Blockly.defineBlocksWithJsonArray([{
  5     type: "controls_repeat_ext",
  6     message0: "%{BKY_CONTROLS_REPEAT_TITLE}",
  7     args0: [{
  8         type: "input_value",
  9         name: "TIMES",
 10         check: "Number"
 11     }],
 12     message1: "%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",
 13     args1: [{
 14         type: "input_statement",
 15         name: "DO"
 16     }],
 17     previousStatement: null,
 18     nextStatement: null,
 19     style: "loop_blocks",
 20     tooltip: "%{BKY_CONTROLS_REPEAT_TOOLTIP}",
 21     helpUrl: "%{BKY_CONTROLS_REPEAT_HELPURL}"
 22 }, {
 23     type: "controls_repeat",
 24     message0: "%{BKY_CONTROLS_REPEAT_TITLE}",
 25     args0: [{
 26         type: "field_number",
 27         name: "TIMES",
 28         value: 10,
 29         min: 0,
 30         precision: 1
 31     }],
 32     message1: "%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",
 33     args1: [{
 34         type: "input_statement",
 35         name: "DO"
 36     }],
 37     previousStatement: null,
 38     nextStatement: null,
 39     style: "loop_blocks",
 40     tooltip: "%{BKY_CONTROLS_REPEAT_TOOLTIP}",
 41     helpUrl: "%{BKY_CONTROLS_REPEAT_HELPURL}"
 42 }, {
 43     type: "controls_whileUntil",
 44     message0: "%1 %2",
 45     args0: [{
 46         type: "field_dropdown",
 47         name: "MODE",
 48         options: [
 49             ["%{BKY_CONTROLS_WHILEUNTIL_OPERATOR_WHILE}", "WHILE"],
 50             ["%{BKY_CONTROLS_WHILEUNTIL_OPERATOR_UNTIL}", "UNTIL"]
 51         ]
 52     }, {
 53         type: "input_value",
 54         name: "BOOL",
 55         check: "Boolean"
 56     }],
 57     message1: "%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",
 58     args1: [{
 59         type: "input_statement",
 60         name: "DO"
 61     }],
 62     previousStatement: null,
 63     nextStatement: null,
 64     style: "loop_blocks",
 65     helpUrl: "%{BKY_CONTROLS_WHILEUNTIL_HELPURL}",
 66     extensions: ["controls_whileUntil_tooltip"]
 67 }, {
 68     type: "controls_for",
 69     message0: "%{BKY_CONTROLS_FOR_TITLE}",
 70     args0: [{
 71         type: "field_variable",
 72         name: "VAR",
 73         variable: null
 74     }, {
 75         type: "input_value",
 76         name: "FROM",
 77         check: "Number",
 78         align: "RIGHT"
 79     }, {
 80         type: "input_value",
 81         name: "TO",
 82         check: "Number",
 83         align: "RIGHT"
 84     }, {
 85         type: "input_value",
 86         name: "BY",
 87         check: "Number",
 88         align: "RIGHT"
 89     }],
 90     message1: "%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",
 91     args1: [{
 92         type: "input_statement",
 93         name: "DO"
 94     }],
 95     inputsInline: !0,
 96     previousStatement: null,
 97     nextStatement: null,
 98     style: "loop_blocks",
 99     helpUrl: "%{BKY_CONTROLS_FOR_HELPURL}",
100     extensions: ["contextMenu_newGetVariableBlock", "controls_for_tooltip"]
101 }, {
102     type: "controls_forEach",
103     message0: "%{BKY_CONTROLS_FOREACH_TITLE}",
104     args0: [{
105         type: "field_variable",
106         name: "VAR",
107         variable: null
108     }, {
109         type: "input_value",
110         name: "LIST",
111         check: "Array"
112     }],
113     message1: "%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",
114     args1: [{
115         type: "input_statement",
116         name: "DO"
117     }],
118     previousStatement: null,
119     nextStatement: null,
120     style: "loop_blocks",
121     helpUrl: "%{BKY_CONTROLS_FOREACH_HELPURL}",
122     extensions: ["contextMenu_newGetVariableBlock", "controls_forEach_tooltip"]
123 }, {
124     type: "controls_flow_statements",
125     message0: "%1",
126     args0: [{
127         type: "field_dropdown",
128         name: "FLOW",
129         options: [
130             ["%{BKY_CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK}", "BREAK"],
131             ["%{BKY_CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE}", "CONTINUE"]
132         ]
133     }],
134     previousStatement: null,
135     style: "loop_blocks",
136     helpUrl: "%{BKY_CONTROLS_FLOW_STATEMENTS_HELPURL}",
137     extensions: ["controls_flow_tooltip", "controls_flow_in_loop_check"]
138 }]);
139 Blockly.Constants.Loops.WHILE_UNTIL_TOOLTIPS = {
140     WHILE: "%{BKY_CONTROLS_WHILEUNTIL_TOOLTIP_WHILE}",
141     UNTIL: "%{BKY_CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL}"
142 };
143 Blockly.Extensions.register("controls_whileUntil_tooltip", Blockly.Extensions.buildTooltipForDropdown("MODE", Blockly.Constants.Loops.WHILE_UNTIL_TOOLTIPS));
144 Blockly.Constants.Loops.BREAK_CONTINUE_TOOLTIPS = {
145     BREAK: "%{BKY_CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK}",
146     CONTINUE: "%{BKY_CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE}"
147 };
148 Blockly.Extensions.register("controls_flow_tooltip", Blockly.Extensions.buildTooltipForDropdown("FLOW", Blockly.Constants.Loops.BREAK_CONTINUE_TOOLTIPS));
149 Blockly.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN = {
150     customContextMenu: function (a) {
151         if (!this.isInFlyout) {
152             var b = this.getField("VAR").getVariable(),
153                 c = b.name;
154             if (!this.isCollapsed() && null != c) {
155                 var d = {
156                     enabled: !0
157                 };
158                 d.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace("%1", c);
159                 b = Blockly.Variables.generateVariableFieldDom(b);
160                 c = Blockly.utils.xml.createElement("block");
161                 c.setAttribute("type", "variables_get");
162                 c.appendChild(b);
163                 d.callback = Blockly.ContextMenu.callbackFactory(this, c);
164                 a.push(d)
165             }
166         }
167     }
168 };
169 Blockly.Extensions.registerMixin("contextMenu_newGetVariableBlock", Blockly.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN);
170 Blockly.Extensions.register("controls_for_tooltip", Blockly.Extensions.buildTooltipWithFieldText("%{BKY_CONTROLS_FOR_TOOLTIP}", "VAR"));
171 Blockly.Extensions.register("controls_forEach_tooltip", Blockly.Extensions.buildTooltipWithFieldText("%{BKY_CONTROLS_FOREACH_TOOLTIP}", "VAR"));
172 Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN = {
173     LOOP_TYPES: ["controls_repeat", "controls_repeat_ext", "controls_forEach", "controls_for", "controls_whileUntil"],
174     suppressPrefixSuffix: !0,
175     getSurroundLoop: function (a) {
176         do {
177             if (-1 != Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.LOOP_TYPES.indexOf(a.type)) return a;
178             a = a.getSurroundParent()
179         } while (a);
180         return null
181     },
182     onchange: function (a) {
183         this.workspace.isDragging && !this.workspace.isDragging() && (Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.getSurroundLoop(this) ?
184             (this.setWarningText(null), this.isInFlyout || this.setEnabled(!0)) : (this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING), this.isInFlyout || this.getInheritedDisabled() || this.setEnabled(!1)))
185     }
186 };
187 Blockly.Extensions.registerMixin("controls_flow_in_loop_check", Blockly.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN);
View Code

抽取定义的一段代码: controls_for 循环功能模块

分析:一个message对应一个args,args中是一个数组里面嵌套多个对象,一个对象中主要有type表示类型,name表示名称。

 1 {
 2     type: "controls_for",
 3     message0: "%{BKY_CONTROLS_FOR_TITLE}",
 4     args0: [{
 5         type: "field_variable",
 6         name: "VAR",
 7         variable: null
 8     }, {
 9         type: "input_value",
10         name: "FROM",
11         check: "Number",
12         align: "RIGHT"
13     }, {
14         type: "input_value",
15         name: "TO",
16         check: "Number",
17         align: "RIGHT"
18     }, {
19         type: "input_value",
20         name: "BY",
21         check: "Number",
22         align: "RIGHT"
23     }],
24     message1: "%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",
25     args1: [{
26         type: "input_statement",
27         name: "DO"
28     }],
29     inputsInline: !0,
30     previousStatement: null,
31     nextStatement: null,
32     style: "loop_blocks",
33     helpUrl: "%{BKY_CONTROLS_FOR_HELPURL}",
34     extensions: ["contextMenu_newGetVariableBlock", "controls_for_tooltip"]
35 }

在html中的代码:

我们根据值以及类型进行赋值

 1 <block type="controls_for">
 2     <field name="VAR">i</field>
 3     <value name="FROM">
 4         <block type="math_number">
 5             <field name="NUM">1</field>
 6         </block>
 7     </value>
 8     <value name="TO">
 9         <block type="math_number">
10             <field name="NUM">10</field>
11         </block>
12     </value>
13     <value name="BY">
14         <block type="math_number">
15             <field name="NUM">1</field>
16         </block>
17     </value>
18 </block>

显示的样式:

 

(2) javascript_compressed.js :主要是将定义好的Blocks的工具箱创建出来的程序解析成JavaScript代码。

以下截取一小段:主要将Blocks的list解析为JavaScript的Array。

  1 Blockly.JavaScript.lists = {};
  2 Blockly.JavaScript.lists_create_empty = function (a) {
  3     return ["[]", Blockly.JavaScript.ORDER_ATOMIC]
  4 };
  5 Blockly.JavaScript.lists_create_with = function (a) {
  6     for (var b = Array(a.itemCount_), c = 0; c < a.itemCount_; c++) b[c] = Blockly.JavaScript.valueToCode(a, "ADD" + c, Blockly.JavaScript.ORDER_COMMA) || "null";
  7     return ["[" + b.join(", ") + "]", Blockly.JavaScript.ORDER_ATOMIC]
  8 };
  9 Blockly.JavaScript.lists_repeat = function (a) {
 10     var b = Blockly.JavaScript.provideFunction_("listsRepeat", ["function " + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + "(value, n) {", "  var array = [];", "  for (var i = 0; i < n; i++) {", "    array[i] = value;", "  }", "  return array;", "}"]),
 11         c = Blockly.JavaScript.valueToCode(a, "ITEM", Blockly.JavaScript.ORDER_COMMA) || "null";
 12     a = Blockly.JavaScript.valueToCode(a, "NUM", Blockly.JavaScript.ORDER_COMMA) || "0";
 13     return [b + "(" + c + ", " + a + ")", Blockly.JavaScript.ORDER_FUNCTION_CALL]
 14 };
 15 Blockly.JavaScript.lists_length = function (a) {
 16     return [(Blockly.JavaScript.valueToCode(a, "VALUE", Blockly.JavaScript.ORDER_MEMBER) || "[]") + ".length", Blockly.JavaScript.ORDER_MEMBER]
 17 };
 18 Blockly.JavaScript.lists_isEmpty = function (a) {
 19     return ["!" + (Blockly.JavaScript.valueToCode(a, "VALUE", Blockly.JavaScript.ORDER_MEMBER) || "[]") + ".length", Blockly.JavaScript.ORDER_LOGICAL_NOT]
 20 };
 21 Blockly.JavaScript.lists_indexOf = function (a) {
 22     var b = "FIRST" == a.getFieldValue("END") ? "indexOf" : "lastIndexOf",
 23         c = Blockly.JavaScript.valueToCode(a, "FIND", Blockly.JavaScript.ORDER_NONE) || "''";
 24     b = (Blockly.JavaScript.valueToCode(a, "VALUE", Blockly.JavaScript.ORDER_MEMBER) || "[]") + "." + b + "(" + c + ")";
 25     return a.workspace.options.oneBasedIndex ? [b + " + 1", Blockly.JavaScript.ORDER_ADDITION] : [b, Blockly.JavaScript.ORDER_FUNCTION_CALL]
 26 };
 27 Blockly.JavaScript.lists_getIndex = function (a) {
 28     var b = a.getFieldValue("MODE") || "GET",
 29         c = a.getFieldValue("WHERE") || "FROM_START",
 30         d = Blockly.JavaScript.valueToCode(a, "VALUE", "RANDOM" == c ? Blockly.JavaScript.ORDER_COMMA : Blockly.JavaScript.ORDER_MEMBER) || "[]";
 31     switch (c) {
 32         case "FIRST":
 33             if ("GET" == b) return [d + "[0]", Blockly.JavaScript.ORDER_MEMBER];
 34             if ("GET_REMOVE" == b) return [d + ".shift()", Blockly.JavaScript.ORDER_MEMBER];
 35             if ("REMOVE" == b) return d + ".shift();\n";
 36             break;
 37         case "LAST":
 38             if ("GET" == b) return [d + ".slice(-1)[0]", Blockly.JavaScript.ORDER_MEMBER];
 39             if ("GET_REMOVE" == b) return [d + ".pop()", Blockly.JavaScript.ORDER_MEMBER];
 40             if ("REMOVE" == b) return d + ".pop();\n";
 41             break;
 42         case "FROM_START":
 43             a = Blockly.JavaScript.getAdjusted(a, "AT");
 44             if ("GET" == b) return [d + "[" + a + "]", Blockly.JavaScript.ORDER_MEMBER];
 45             if ("GET_REMOVE" == b) return [d + ".splice(" + a + ", 1)[0]", Blockly.JavaScript.ORDER_FUNCTION_CALL];
 46             if ("REMOVE" == b) return d + ".splice(" + a + ", 1);\n";
 47             break;
 48         case "FROM_END":
 49             a = Blockly.JavaScript.getAdjusted(a, "AT", 1, !0);
 50             if ("GET" == b) return [d + ".slice(" + a + ")[0]", Blockly.JavaScript.ORDER_FUNCTION_CALL];
 51             if ("GET_REMOVE" == b) return [d + ".splice(" + a + ", 1)[0]", Blockly.JavaScript.ORDER_FUNCTION_CALL];
 52             if ("REMOVE" == b) return d + ".splice(" + a + ", 1);";
 53             break;
 54         case "RANDOM":
 55             d = Blockly.JavaScript.provideFunction_("listsGetRandomItem", ["function " + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + "(list, remove) {", "  var x = Math.floor(Math.random() * list.length);", "  if (remove) {", "    return list.splice(x, 1)[0];", "  } else {", "    return list[x];", "  }", "}"]) + "(" + d + ", " + ("GET" != b) + ")";
 56             if ("GET" == b || "GET_REMOVE" == b) return [d,
 57                 Blockly.JavaScript.ORDER_FUNCTION_CALL
 58             ];
 59             if ("REMOVE" == b) return d + ";\n"
 60     }
 61     throw Error("Unhandled combination (lists_getIndex).");
 62 };
 63 Blockly.JavaScript.lists_setIndex = function (a) {
 64     function b() {
 65         if (c.match(/^\w+$/)) return "";
 66         var a = Blockly.JavaScript.variableDB_.getDistinctName("tmpList", Blockly.Variables.NAME_TYPE),
 67             b = "var " + a + " = " + c + ";\n";
 68         c = a;
 69         return b
 70     }
 71     var c = Blockly.JavaScript.valueToCode(a, "LIST", Blockly.JavaScript.ORDER_MEMBER) || "[]",
 72         d = a.getFieldValue("MODE") || "GET",
 73         e = a.getFieldValue("WHERE") || "FROM_START",
 74         f = Blockly.JavaScript.valueToCode(a, "TO", Blockly.JavaScript.ORDER_ASSIGNMENT) || "null";
 75     switch (e) {
 76         case "FIRST":
 77             if ("SET" == d) return c +
 78                 "[0] = " + f + ";\n";
 79             if ("INSERT" == d) return c + ".unshift(" + f + ");\n";
 80             break;
 81         case "LAST":
 82             if ("SET" == d) return a = b(), a + (c + "[" + c + ".length - 1] = " + f + ";\n");
 83             if ("INSERT" == d) return c + ".push(" + f + ");\n";
 84             break;
 85         case "FROM_START":
 86             e = Blockly.JavaScript.getAdjusted(a, "AT");
 87             if ("SET" == d) return c + "[" + e + "] = " + f + ";\n";
 88             if ("INSERT" == d) return c + ".splice(" + e + ", 0, " + f + ");\n";
 89             break;
 90         case "FROM_END":
 91             e = Blockly.JavaScript.getAdjusted(a, "AT", 1, !1, Blockly.JavaScript.ORDER_SUBTRACTION);
 92             a = b();
 93             if ("SET" == d) return a + (c + "[" + c + ".length - " + e +
 94                 "] = " + f + ";\n");
 95             if ("INSERT" == d) return a + (c + ".splice(" + c + ".length - " + e + ", 0, " + f + ");\n");
 96             break;
 97         case "RANDOM":
 98             a = b();
 99             e = Blockly.JavaScript.variableDB_.getDistinctName("tmpX", Blockly.Variables.NAME_TYPE);
100             a += "var " + e + " = Math.floor(Math.random() * " + c + ".length);\n";
101             if ("SET" == d) return a + (c + "[" + e + "] = " + f + ";\n");
102             if ("INSERT" == d) return a + (c + ".splice(" + e + ", 0, " + f + ");\n")
103     }
104     throw Error("Unhandled combination (lists_setIndex).");
105 };
106 Blockly.JavaScript.lists.getIndex_ = function (a, b, c) {
107     return "FIRST" == b ? "0" : "FROM_END" == b ? a + ".length - 1 - " + c : "LAST" == b ? a + ".length - 1" : c
108 };
109 Blockly.JavaScript.lists_getSublist = function (a) {
110     var b = Blockly.JavaScript.valueToCode(a, "LIST", Blockly.JavaScript.ORDER_MEMBER) || "[]",
111         c = a.getFieldValue("WHERE1"),
112         d = a.getFieldValue("WHERE2");
113     if ("FIRST" == c && "LAST" == d) b += ".slice(0)";
114     else if (b.match(/^\w+$/) || "FROM_END" != c && "FROM_START" == d) {
115         switch (c) {
116             case "FROM_START":
117                 var e = Blockly.JavaScript.getAdjusted(a, "AT1");
118                 break;
119             case "FROM_END":
120                 e = Blockly.JavaScript.getAdjusted(a, "AT1", 1, !1, Blockly.JavaScript.ORDER_SUBTRACTION);
121                 e = b + ".length - " + e;
122                 break;
123             case "FIRST":
124                 e =
125                     "0";
126                 break;
127             default:
128                 throw Error("Unhandled option (lists_getSublist).");
129         }
130         switch (d) {
131             case "FROM_START":
132                 a = Blockly.JavaScript.getAdjusted(a, "AT2", 1);
133                 break;
134             case "FROM_END":
135                 a = Blockly.JavaScript.getAdjusted(a, "AT2", 0, !1, Blockly.JavaScript.ORDER_SUBTRACTION);
136                 a = b + ".length - " + a;
137                 break;
138             case "LAST":
139                 a = b + ".length";
140                 break;
141             default:
142                 throw Error("Unhandled option (lists_getSublist).");
143         }
144         b = b + ".slice(" + e + ", " + a + ")"
145     } else {
146         e = Blockly.JavaScript.getAdjusted(a, "AT1");
147         a = Blockly.JavaScript.getAdjusted(a, "AT2");
148         var f = Blockly.JavaScript.lists.getIndex_,
149             g = {
150                 FIRST: "First",
151                 LAST: "Last",
152                 FROM_START: "FromStart",
153                 FROM_END: "FromEnd"
154             };
155         b = Blockly.JavaScript.provideFunction_("subsequence" + g[c] + g[d], ["function " + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + "(sequence" + ("FROM_END" == c || "FROM_START" == c ? ", at1" : "") + ("FROM_END" == d || "FROM_START" == d ? ", at2" : "") + ") {", "  var start = " + f("sequence", c, "at1") + ";", "  var end = " + f("sequence", d, "at2") + " + 1;", "  return sequence.slice(start, end);", "}"]) + "(" + b + ("FROM_END" == c || "FROM_START" == c ? ", " + e : "") + ("FROM_END" == d || "FROM_START" ==
156             d ? ", " + a : "") + ")"
157     }
158     return [b, Blockly.JavaScript.ORDER_FUNCTION_CALL]
159 };
160 Blockly.JavaScript.lists_sort = function (a) {
161     var b = Blockly.JavaScript.valueToCode(a, "LIST", Blockly.JavaScript.ORDER_FUNCTION_CALL) || "[]",
162         c = "1" === a.getFieldValue("DIRECTION") ? 1 : -1;
163     a = a.getFieldValue("TYPE");
164     var d = Blockly.JavaScript.provideFunction_("listsGetSortCompare", ["function " + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + "(type, direction) {", "  var compareFuncs = {", '    "NUMERIC": function(a, b) {', "        return Number(a) - Number(b); },", '    "TEXT": function(a, b) {', "        return a.toString() > b.toString() ? 1 : -1; },",
165         '    "IGNORE_CASE": function(a, b) {', "        return a.toString().toLowerCase() > b.toString().toLowerCase() ? 1 : -1; },", "  };", "  var compare = compareFuncs[type];", "  return function(a, b) { return compare(a, b) * direction; }", "}"
166     ]);
167     return [b + ".slice().sort(" + d + '("' + a + '", ' + c + "))", Blockly.JavaScript.ORDER_FUNCTION_CALL]
168 };
169 Blockly.JavaScript.lists_split = function (a) {
170     var b = Blockly.JavaScript.valueToCode(a, "INPUT", Blockly.JavaScript.ORDER_MEMBER),
171         c = Blockly.JavaScript.valueToCode(a, "DELIM", Blockly.JavaScript.ORDER_NONE) || "''";
172     a = a.getFieldValue("MODE");
173     if ("SPLIT" == a) b || (b = "''"), a = "split";
174     else if ("JOIN" == a) b || (b = "[]"), a = "join";
175     else throw Error("Unknown mode: " + a);
176     return [b + "." + a + "(" + c + ")", Blockly.JavaScript.ORDER_FUNCTION_CALL]
177 };
178 Blockly.JavaScript.lists_reverse = function (a) {
179     return [(Blockly.JavaScript.valueToCode(a, "LIST", Blockly.JavaScript.ORDER_FUNCTION_CALL) || "[]") + ".slice().reverse()", Blockly.JavaScript.ORDER_FUNCTION_CALL]
180 };
View Code

(3) blockly_compressed.js :提供了整体框架以及配套设施,拥有大量API函数供使用。

posted @ 2019-11-29 13:05  All_just_for_fun  阅读(4186)  评论(0编辑  收藏  举报