mirror of
https://github.com/google/blockly.git
synced 2026-01-08 09:30:06 +01:00
Porting math.js blocks to JSON (#846)
Moving all `math.js` definitions into a single JSON array, complete with i18n syntax for all messages, dropdowns, and tooltips. Adding Blockly.Extensions.buildTooltipForDropdown(..) to facilitate the creation and error-checking of tooltips that update based on the value of a dropdown. Now warn on raw string in JSON 'extensions'.
This commit is contained in:
committed by
GitHub
parent
46316c7cea
commit
7b0275cd70
@@ -21,9 +21,9 @@
|
||||
/**
|
||||
* @fileoverview Colour blocks for Blockly.
|
||||
*
|
||||
* This file is scraped to extract .json file definitions. The array passed to
|
||||
* defineBlocksWithJsonArray(..) must be strict JSON: double quotes only, no
|
||||
* outside references, no functions, no trailing commasa, etc. The one
|
||||
* This file is scraped to extract a .json file of block definitions. The array
|
||||
* passed to defineBlocksWithJsonArray(..) must be strict JSON: double quotes
|
||||
* only, no outside references, no functions, no trailing commas, etc. The one
|
||||
* exception is end-of-line comments, which the scraper will remove.
|
||||
* @author fraser@google.com (Neil Fraser)
|
||||
*/
|
||||
@@ -128,4 +128,4 @@ Blockly.defineBlocksWithJsonArray([
|
||||
"helpUrl": "%{BKY_COLOUR_BLEND_HELPURL}",
|
||||
"tooltip": "%{BKY_COLOUR_BLEND_TOOLTIP}"
|
||||
}
|
||||
]); // End of defineBlocksWithJsonArray(...) DO NOT DELETE
|
||||
]); // End of defineBlocksWithJsonArray(...) (Do not delete this comment.)
|
||||
|
||||
811
blocks/math.js
811
blocks/math.js
@@ -20,6 +20,11 @@
|
||||
|
||||
/**
|
||||
* @fileoverview Math blocks for Blockly.
|
||||
*
|
||||
* This file is scraped to extract a .json file of block definitions. The array
|
||||
* passed to defineBlocksWithJsonArray(..) must be strict JSON: double quotes
|
||||
* only, no outside references, no functions, no trailing commas, etc. The one
|
||||
* exception is end-of-line comments, which the scraper will remove.
|
||||
* @author q.neutron@gmail.com (Quynh Neutron)
|
||||
*/
|
||||
'use strict';
|
||||
@@ -31,6 +36,7 @@ goog.require('Blockly.Blocks');
|
||||
|
||||
/**
|
||||
* Common HSV hue for all blocks in this category.
|
||||
* Should be the same as Blockly.Msg.MATH_HUE
|
||||
*/
|
||||
Blockly.Blocks.math.HUE = 230;
|
||||
|
||||
@@ -49,216 +55,371 @@ Blockly.defineBlocksWithJsonArray([
|
||||
"helpUrl": "%{BKY_MATH_NUMBER_HELPURL}",
|
||||
"tooltip": "%{BKY_MATH_NUMBER_TOOLTIP}",
|
||||
"extensions": ["parent_tooltip_when_inline"]
|
||||
}
|
||||
]);
|
||||
|
||||
Blockly.Blocks['math_arithmetic'] = {
|
||||
/**
|
||||
* Block for basic arithmetic operator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": "%1 %2 %3",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "A",
|
||||
"check": "Number"
|
||||
},
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "OP",
|
||||
"options":
|
||||
[[Blockly.Msg.MATH_ADDITION_SYMBOL, 'ADD'],
|
||||
[Blockly.Msg.MATH_SUBTRACTION_SYMBOL, 'MINUS'],
|
||||
[Blockly.Msg.MATH_MULTIPLICATION_SYMBOL, 'MULTIPLY'],
|
||||
[Blockly.Msg.MATH_DIVISION_SYMBOL, 'DIVIDE'],
|
||||
[Blockly.Msg.MATH_POWER_SYMBOL, 'POWER']]
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "B",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"inputsInline": true,
|
||||
"output": "Number",
|
||||
"colour": Blockly.Blocks.math.HUE,
|
||||
"helpUrl": Blockly.Msg.MATH_ARITHMETIC_HELPURL
|
||||
});
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
var thisBlock = this;
|
||||
this.setTooltip(function() {
|
||||
var mode = thisBlock.getFieldValue('OP');
|
||||
var TOOLTIPS = {
|
||||
'ADD': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD,
|
||||
'MINUS': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS,
|
||||
'MULTIPLY': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY,
|
||||
'DIVIDE': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE,
|
||||
'POWER': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER
|
||||
};
|
||||
return TOOLTIPS[mode];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_single'] = {
|
||||
/**
|
||||
* Block for advanced math operators with single operand.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": "%1 %2",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "OP",
|
||||
"options": [
|
||||
[Blockly.Msg.MATH_SINGLE_OP_ROOT, 'ROOT'],
|
||||
[Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE, 'ABS'],
|
||||
['-', 'NEG'],
|
||||
['ln', 'LN'],
|
||||
['log10', 'LOG10'],
|
||||
['e^', 'EXP'],
|
||||
['10^', 'POW10']
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "NUM",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"output": "Number",
|
||||
"colour": Blockly.Blocks.math.HUE,
|
||||
"helpUrl": Blockly.Msg.MATH_SINGLE_HELPURL
|
||||
});
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
var thisBlock = this;
|
||||
this.setTooltip(function() {
|
||||
var mode = thisBlock.getFieldValue('OP');
|
||||
var TOOLTIPS = {
|
||||
'ROOT': Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT,
|
||||
'ABS': Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS,
|
||||
'NEG': Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG,
|
||||
'LN': Blockly.Msg.MATH_SINGLE_TOOLTIP_LN,
|
||||
'LOG10': Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10,
|
||||
'EXP': Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP,
|
||||
'POW10': Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10
|
||||
};
|
||||
return TOOLTIPS[mode];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_trig'] = {
|
||||
/**
|
||||
* Block for trigonometry operators.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": "%1 %2",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "OP",
|
||||
"options": [
|
||||
[Blockly.Msg.MATH_TRIG_SIN, 'SIN'],
|
||||
[Blockly.Msg.MATH_TRIG_COS, 'COS'],
|
||||
[Blockly.Msg.MATH_TRIG_TAN, 'TAN'],
|
||||
[Blockly.Msg.MATH_TRIG_ASIN, 'ASIN'],
|
||||
[Blockly.Msg.MATH_TRIG_ACOS, 'ACOS'],
|
||||
[Blockly.Msg.MATH_TRIG_ATAN, 'ATAN']
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "NUM",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"output": "Number",
|
||||
"colour": Blockly.Blocks.math.HUE,
|
||||
"helpUrl": Blockly.Msg.MATH_TRIG_HELPURL
|
||||
});
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
var thisBlock = this;
|
||||
this.setTooltip(function() {
|
||||
var mode = thisBlock.getFieldValue('OP');
|
||||
var TOOLTIPS = {
|
||||
'SIN': Blockly.Msg.MATH_TRIG_TOOLTIP_SIN,
|
||||
'COS': Blockly.Msg.MATH_TRIG_TOOLTIP_COS,
|
||||
'TAN': Blockly.Msg.MATH_TRIG_TOOLTIP_TAN,
|
||||
'ASIN': Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN,
|
||||
'ACOS': Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS,
|
||||
'ATAN': Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN
|
||||
};
|
||||
return TOOLTIPS[mode];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_constant'] = {
|
||||
/**
|
||||
* Block for constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": "%1",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "CONSTANT",
|
||||
"options": [
|
||||
['\u03c0', 'PI'],
|
||||
['e', 'E'],
|
||||
['\u03c6', 'GOLDEN_RATIO'],
|
||||
['sqrt(2)', 'SQRT2'],
|
||||
['sqrt(\u00bd)', 'SQRT1_2'],
|
||||
['\u221e', 'INFINITY']
|
||||
]
|
||||
}
|
||||
],
|
||||
"output": "Number",
|
||||
"colour": Blockly.Blocks.math.HUE,
|
||||
"tooltip": Blockly.Msg.MATH_CONSTANT_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.MATH_CONSTANT_HELPURL
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_number_property'] = {
|
||||
/**
|
||||
* Block for checking if a number is even, odd, prime, whole, positive,
|
||||
* negative or if it is divisible by certain number.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var PROPERTIES =
|
||||
[[Blockly.Msg.MATH_IS_EVEN, 'EVEN'],
|
||||
[Blockly.Msg.MATH_IS_ODD, 'ODD'],
|
||||
[Blockly.Msg.MATH_IS_PRIME, 'PRIME'],
|
||||
[Blockly.Msg.MATH_IS_WHOLE, 'WHOLE'],
|
||||
[Blockly.Msg.MATH_IS_POSITIVE, 'POSITIVE'],
|
||||
[Blockly.Msg.MATH_IS_NEGATIVE, 'NEGATIVE'],
|
||||
[Blockly.Msg.MATH_IS_DIVISIBLE_BY, 'DIVISIBLE_BY']];
|
||||
this.setColour(Blockly.Blocks.math.HUE);
|
||||
this.appendValueInput('NUMBER_TO_CHECK')
|
||||
.setCheck('Number');
|
||||
var dropdown = new Blockly.FieldDropdown(PROPERTIES, function(option) {
|
||||
var divisorInput = (option == 'DIVISIBLE_BY');
|
||||
this.sourceBlock_.updateShape_(divisorInput);
|
||||
});
|
||||
this.appendDummyInput()
|
||||
.appendField(dropdown, 'PROPERTY');
|
||||
this.setInputsInline(true);
|
||||
this.setOutput(true, 'Boolean');
|
||||
this.setTooltip(Blockly.Msg.MATH_IS_TOOLTIP);
|
||||
},
|
||||
|
||||
// Block for basic arithmetic operator.
|
||||
{
|
||||
"type": "math_arithmetic",
|
||||
"message0": "%1 %2 %3",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "A",
|
||||
"check": "Number"
|
||||
},
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "OP",
|
||||
"options": [
|
||||
["%{BKY_MATH_ADDITION_SYMBOL}", "ADD"],
|
||||
["%{BKY_MATH_SUBTRACTION_SYMBOL}", "MINUS"],
|
||||
["%{BKY_MATH_MULTIPLICATION_SYMBOL}", "MULTIPLY"],
|
||||
["%{BKY_MATH_DIVISION_SYMBOL}", "DIVIDE"],
|
||||
["%{BKY_MATH_POWER_SYMBOL}", "POWER"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "B",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"inputsInline": true,
|
||||
"output": "Number",
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"helpUrl": "%{BKY_MATH_ARITHMETIC_HELPURL}",
|
||||
"extensions": ["math_op_tooltip"]
|
||||
},
|
||||
|
||||
// Block for advanced math operators with single operand.
|
||||
{
|
||||
"type": "math_single",
|
||||
"message0": "%1 %2",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "OP",
|
||||
"options": [
|
||||
["%{BKY_MATH_SINGLE_OP_ROOT}", 'ROOT'],
|
||||
["%{BKY_MATH_SINGLE_OP_ABSOLUTE}", 'ABS'],
|
||||
['-', 'NEG'],
|
||||
['ln', 'LN'],
|
||||
['log10', 'LOG10'],
|
||||
['e^', 'EXP'],
|
||||
['10^', 'POW10']
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "NUM",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"output": "Number",
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"helpUrl": "%{BKY_MATH_SINGLE_HELPURL}",
|
||||
"extensions": ["math_op_tooltip"]
|
||||
},
|
||||
|
||||
// Block for trigonometry operators.
|
||||
{
|
||||
"type": "math_trig",
|
||||
"message0": "%1 %2",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "OP",
|
||||
"options": [
|
||||
["%{BKY_MATH_TRIG_SIN}", "SIN"],
|
||||
["%{BKY_MATH_TRIG_COS}", "COS"],
|
||||
["%{BKY_MATH_TRIG_TAN}", "TAN"],
|
||||
["%{BKY_MATH_TRIG_ASIN}", "ASIN"],
|
||||
["%{BKY_MATH_TRIG_ACOS}", "ACOS"],
|
||||
["%{BKY_MATH_TRIG_ATAN}", "ATAN"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "NUM",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"output": "Number",
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"helpUrl": "%{BKY_MATH_TRIG_HELPURL}",
|
||||
"extensions": ["math_op_tooltip"]
|
||||
},
|
||||
|
||||
// Block for constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY.
|
||||
{
|
||||
"type": "math_constant",
|
||||
"message0": "%1",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "CONSTANT",
|
||||
"options": [
|
||||
["\u03c0", "PI"],
|
||||
["e", "E"],
|
||||
["\u03c6", "GOLDEN_RATIO"],
|
||||
["sqrt(2)", "SQRT2"],
|
||||
["sqrt(\u00bd)", "SQRT1_2"],
|
||||
["\u221e", "INFINITY"]
|
||||
]
|
||||
}
|
||||
],
|
||||
"output": "Number",
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"tooltip": "%{BKY_MATH_CONSTANT_TOOLTIP}",
|
||||
"helpUrl": "%{BKY_MATH_CONSTANT_HELPURL}"
|
||||
},
|
||||
|
||||
// Block for checking if a number is even, odd, prime, whole, positive,
|
||||
// negative or if it is divisible by certain number.
|
||||
{
|
||||
"type": "math_number_property",
|
||||
"message0": "%1 %2",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "NUMBER_TO_CHECK",
|
||||
"check": "Number"
|
||||
},
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "PROPERTY",
|
||||
"options": [
|
||||
["%{BKY_MATH_IS_EVEN}", "EVEN"],
|
||||
["%{BKY_MATH_IS_ODD}", "ODD"],
|
||||
["%{BKY_MATH_IS_PRIME}", "PRIME"],
|
||||
["%{BKY_MATH_IS_WHOLE}", "WHOLE"],
|
||||
["%{BKY_MATH_IS_POSITIVE}", "POSITIVE"],
|
||||
["%{BKY_MATH_IS_NEGATIVE}", "NEGATIVE"],
|
||||
["%{BKY_MATH_IS_DIVISIBLE_BY}", "DIVISIBLE_BY"]
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputsInline": true,
|
||||
"output": "Boolean",
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"tooltip": "%{BKY_MATH_IS_TOOLTIP}",
|
||||
"extensions": ["math_is_divisibleby_mutator"]
|
||||
},
|
||||
|
||||
// Block for adding to a variable in place.
|
||||
{
|
||||
"type": "math_change",
|
||||
"message0": "%{BKY_MATH_CHANGE_TITLE}",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_variable",
|
||||
"name": "VAR",
|
||||
"variable": "%{BKY_MATH_CHANGE_TITLE_ITEM}"
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "DELTA",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"previousStatement": null,
|
||||
"nextStatement": null,
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"helpUrl": "%{BKY_MATH_CHANGE_HELPURL}",
|
||||
"extensions": ["math_change_tooltip"]
|
||||
},
|
||||
|
||||
// Block for rounding functions.
|
||||
{
|
||||
"type": "math_round",
|
||||
"message0": "%1 %2",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "OP",
|
||||
"options": [
|
||||
["%{BKY_MATH_ROUND_OPERATOR_ROUND}", "ROUND"],
|
||||
["%{BKY_MATH_ROUND_OPERATOR_ROUNDUP}", "ROUNDUP"],
|
||||
["%{BKY_MATH_ROUND_OPERATOR_ROUNDDOWN}", "ROUNDDOWN"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "NUM",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"output": "Number",
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"helpUrl": "%{BKY_MATH_ROUND_HELPURL}",
|
||||
"tooltip": "%{BKY_MATH_ROUND_TOOLTIP}"
|
||||
},
|
||||
|
||||
// Block for evaluating a list of numbers to return sum, average, min, max,
|
||||
// etc. Some functions also work on text (min, max, mode, median).
|
||||
{
|
||||
"type": "math_on_list",
|
||||
"message0": "%1 %2",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "OP",
|
||||
"options": [
|
||||
["%{BKY_MATH_ONLIST_OPERATOR_SUM}", "SUM"],
|
||||
["%{BKY_MATH_ONLIST_OPERATOR_MIN}", "MIN"],
|
||||
["%{BKY_MATH_ONLIST_OPERATOR_MAX}", "MAX"],
|
||||
["%{BKY_MATH_ONLIST_OPERATOR_AVERAGE}", "AVERAGE"],
|
||||
["%{BKY_MATH_ONLIST_OPERATOR_MEDIAN}", "MEDIAN"],
|
||||
["%{BKY_MATH_ONLIST_OPERATOR_MODE}", "MODE"],
|
||||
["%{BKY_MATH_ONLIST_OPERATOR_STD_DEV}", "STD_DEV"],
|
||||
["%{BKY_MATH_ONLIST_OPERATOR_RANDOM}", "RANDOM"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "LIST",
|
||||
"check": "Array"
|
||||
}
|
||||
],
|
||||
"output": "Number",
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"helpUrl": "%{BKY_MATH_ONLIST_HELPURL}",
|
||||
"extensions": ["math_op_tooltip", "math_modes_of_list_mutator"]
|
||||
},
|
||||
|
||||
// Block for remainder of a division.
|
||||
{
|
||||
"type": "math_modulo",
|
||||
"message0": "%{BKY_MATH_MODULO_TITLE}",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "DIVIDEND",
|
||||
"check": "Number"
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "DIVISOR",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"inputsInline": true,
|
||||
"output": "Number",
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"tooltip": "%{BKY_MATH_MODULO_TOOLTIP}",
|
||||
"helpUrl": "%{BKY_MATH_MODULO_HELPURL}"
|
||||
},
|
||||
|
||||
// Block for constraining a number between two limits.
|
||||
{
|
||||
"type": "math_constrain",
|
||||
"message0": "%{BKY_MATH_CONSTRAIN_TITLE}",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "VALUE",
|
||||
"check": "Number"
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "LOW",
|
||||
"check": "Number"
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "HIGH",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"inputsInline": true,
|
||||
"output": "Number",
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"tooltip": "%{BKY_MATH_CONSTRAIN_TOOLTIP}",
|
||||
"helpUrl": "%{BKY_MATH_CONSTRAIN_HELPURL}"
|
||||
},
|
||||
|
||||
// Block for random integer between [X] and [Y].
|
||||
{
|
||||
"type": "math_random_int",
|
||||
"message0": "%{BKY_MATH_RANDOM_INT_TITLE}",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "FROM",
|
||||
"check": "Number"
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "TO",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"inputsInline": true,
|
||||
"output": "Number",
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"tooltip": "%{BKY_MATH_RANDOM_INT_TOOLTIP}",
|
||||
"helpUrl": "%{BKY_MATH_RANDOM_INT_HELPURL}"
|
||||
},
|
||||
|
||||
// Block for random integer between [X] and [Y].
|
||||
{
|
||||
"type": "math_random_float",
|
||||
"message0": "%{BKY_MATH_RANDOM_FLOAT_TITLE_RANDOM}",
|
||||
"output": "Number",
|
||||
"colour": "%{BKY_MATH_HUE}",
|
||||
"tooltip": "%{BKY_MATH_RANDOM_FLOAT_TOOLTIP}",
|
||||
"helpUrl": "%{BKY_MATH_RANDOM_FLOAT_HELPURL}"
|
||||
}
|
||||
]); // End of defineBlocksWithJsonArray(...) (Do not delete this comment.)
|
||||
|
||||
/**
|
||||
* Mapping of math block OP value to tooltip message for blocks
|
||||
* math_arithmetic, math_simple, math_trig, and math_on_lists.
|
||||
*
|
||||
* Messages are not dereferenced here in order to capture possible language
|
||||
* changes.
|
||||
*/
|
||||
Blockly.Blocks.math.TOOLTIPS_BY_OP_ = {
|
||||
// math_arithmetic
|
||||
'ADD': '%{BKY_MATH_ARITHMETIC_TOOLTIP_ADD}',
|
||||
'MINUS': '%{BKY_MATH_ARITHMETIC_TOOLTIP_MINUS}',
|
||||
'MULTIPLY': '%{BKY_MATH_ARITHMETIC_TOOLTIP_MULTIPLY}',
|
||||
'DIVIDE': '%{BKY_MATH_ARITHMETIC_TOOLTIP_DIVIDE}',
|
||||
'POWER': '%{BKY_MATH_ARITHMETIC_TOOLTIP_POWER}',
|
||||
|
||||
// math_simple
|
||||
'ROOT': '%{BKY_MATH_SINGLE_TOOLTIP_ROOT}',
|
||||
'ABS': '%{BKY_MATH_SINGLE_TOOLTIP_ABS}',
|
||||
'NEG': '%{BKY_MATH_SINGLE_TOOLTIP_NEG}',
|
||||
'LN': '%{BKY_MATH_SINGLE_TOOLTIP_LN}',
|
||||
'LOG10': '%{BKY_MATH_SINGLE_TOOLTIP_LOG10}',
|
||||
'EXP': '%{BKY_MATH_SINGLE_TOOLTIP_EXP}',
|
||||
'POW10': '%{BKY_MATH_SINGLE_TOOLTIP_POW10}',
|
||||
|
||||
// math_trig
|
||||
'SIN': '%{BKY_MATH_TRIG_TOOLTIP_SIN}',
|
||||
'COS': '%{BKY_MATH_TRIG_TOOLTIP_COS}',
|
||||
'TAN': '%{BKY_MATH_TRIG_TOOLTIP_TAN}',
|
||||
'ASIN': '%{BKY_MATH_TRIG_TOOLTIP_ASIN}',
|
||||
'ACOS': '%{BKY_MATH_TRIG_TOOLTIP_ACOS}',
|
||||
'ATAN': '%{BKY_MATH_TRIG_TOOLTIP_ATAN}',
|
||||
|
||||
// math_on_lists
|
||||
'SUM': '%{BKY_MATH_ONLIST_TOOLTIP_SUM}',
|
||||
'MIN': '%{BKY_MATH_ONLIST_TOOLTIP_MIN}',
|
||||
'MAX': '%{BKY_MATH_ONLIST_TOOLTIP_MAX}',
|
||||
'AVERAGE': '%{BKY_MATH_ONLIST_TOOLTIP_AVERAGE}',
|
||||
'MEDIAN': '%{BKY_MATH_ONLIST_TOOLTIP_MEDIAN}',
|
||||
'MODE': '%{BKY_MATH_ONLIST_TOOLTIP_MODE}',
|
||||
'STD_DEV': '%{BKY_MATH_ONLIST_TOOLTIP_STD_DEV}',
|
||||
'RANDOM': '%{BKY_MATH_ONLIST_TOOLTIP_RANDOM}',
|
||||
};
|
||||
Blockly.Extensions.register("math_op_tooltip",
|
||||
Blockly.Extensions.buildTooltipForDropdown(
|
||||
'OP', Blockly.Blocks.math.TOOLTIPS_BY_OP_));
|
||||
|
||||
|
||||
Blockly.Blocks.math.IS_DIVISIBLEBY_MUTATOR_MIXIN_ = {
|
||||
/**
|
||||
* Create XML to represent whether the 'divisorInput' should be present.
|
||||
* @return {Element} XML storage element.
|
||||
@@ -299,114 +460,34 @@ Blockly.Blocks['math_number_property'] = {
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_change'] = {
|
||||
Blockly.Extensions.register("math_is_divisibleby_mutator",
|
||||
/**
|
||||
* Block for adding to a variable in place.
|
||||
* @this Blockly.Block
|
||||
* Update shape (add/remove divisor input) based on whether property is
|
||||
* "divisble by".
|
||||
* @this {Blockly.Block}
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": Blockly.Msg.MATH_CHANGE_TITLE,
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_variable",
|
||||
"name": "VAR",
|
||||
"variable": Blockly.Msg.MATH_CHANGE_TITLE_ITEM
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "DELTA",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"previousStatement": null,
|
||||
"nextStatement": null,
|
||||
"colour": Blockly.Blocks.variables.HUE,
|
||||
"helpUrl": Blockly.Msg.MATH_CHANGE_HELPURL
|
||||
function() {
|
||||
goog.mixin(this, Blockly.Blocks.math.IS_DIVISIBLEBY_MUTATOR_MIXIN_);
|
||||
this.getField('PROPERTY').setValidator(function(option) {
|
||||
var divisorInput = (option == 'DIVISIBLE_BY');
|
||||
this.sourceBlock_.updateShape_(divisorInput);
|
||||
});
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
});
|
||||
|
||||
Blockly.Extensions.register("math_change_tooltip",
|
||||
/**
|
||||
* Update tooltip with named variable.
|
||||
* @this {Blockly.Block}
|
||||
*/
|
||||
function() {
|
||||
var thisBlock = this;
|
||||
this.setTooltip(function() {
|
||||
return Blockly.Msg.MATH_CHANGE_TOOLTIP.replace('%1',
|
||||
thisBlock.getFieldValue('VAR'));
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
Blockly.Blocks['math_round'] = {
|
||||
/**
|
||||
* Block for rounding functions.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": "%1 %2",
|
||||
"args0": [
|
||||
{
|
||||
"type": "field_dropdown",
|
||||
"name": "OP",
|
||||
"options": [
|
||||
[Blockly.Msg.MATH_ROUND_OPERATOR_ROUND, 'ROUND'],
|
||||
[Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP, 'ROUNDUP'],
|
||||
[Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN, 'ROUNDDOWN']
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "NUM",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"output": "Number",
|
||||
"colour": Blockly.Blocks.math.HUE,
|
||||
"tooltip": Blockly.Msg.MATH_ROUND_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.MATH_ROUND_HELPURL
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_on_list'] = {
|
||||
/**
|
||||
* Block for evaluating a list of numbers to return sum, average, min, max,
|
||||
* etc. Some functions also work on text (min, max, mode, median).
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.MATH_ONLIST_OPERATOR_SUM, 'SUM'],
|
||||
[Blockly.Msg.MATH_ONLIST_OPERATOR_MIN, 'MIN'],
|
||||
[Blockly.Msg.MATH_ONLIST_OPERATOR_MAX, 'MAX'],
|
||||
[Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE, 'AVERAGE'],
|
||||
[Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN, 'MEDIAN'],
|
||||
[Blockly.Msg.MATH_ONLIST_OPERATOR_MODE, 'MODE'],
|
||||
[Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV, 'STD_DEV'],
|
||||
[Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM, 'RANDOM']];
|
||||
// Assign 'this' to a variable for use in the closures below.
|
||||
var thisBlock = this;
|
||||
this.setHelpUrl(Blockly.Msg.MATH_ONLIST_HELPURL);
|
||||
this.setColour(Blockly.Blocks.math.HUE);
|
||||
this.setOutput(true, 'Number');
|
||||
var dropdown = new Blockly.FieldDropdown(OPERATORS, function(newOp) {
|
||||
thisBlock.updateType_(newOp);
|
||||
});
|
||||
this.appendValueInput('LIST')
|
||||
.setCheck('Array')
|
||||
.appendField(dropdown, 'OP');
|
||||
this.setTooltip(function() {
|
||||
var mode = thisBlock.getFieldValue('OP');
|
||||
var TOOLTIPS = {
|
||||
'SUM': Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM,
|
||||
'MIN': Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN,
|
||||
'MAX': Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX,
|
||||
'AVERAGE': Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE,
|
||||
'MEDIAN': Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN,
|
||||
'MODE': Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE,
|
||||
'STD_DEV': Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV,
|
||||
'RANDOM': Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM
|
||||
};
|
||||
return TOOLTIPS[mode];
|
||||
});
|
||||
},
|
||||
Blockly.Blocks.math.LIST_MODES_MUTATOR_MIXIN_ = {
|
||||
/**
|
||||
* Modify this block to have the correct output type.
|
||||
* @param {string} newOp Either 'MODE' or some op than returns a number.
|
||||
@@ -439,111 +520,15 @@ Blockly.Blocks['math_on_list'] = {
|
||||
this.updateType_(xmlElement.getAttribute('op'));
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_modulo'] = {
|
||||
Blockly.Extensions.register("math_modes_of_list_mutator",
|
||||
/**
|
||||
* Block for remainder of a division.
|
||||
* @this Blockly.Block
|
||||
* Update output type based on whether the operator is "mode".
|
||||
* @this {Blockly.Block}
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": Blockly.Msg.MATH_MODULO_TITLE,
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "DIVIDEND",
|
||||
"check": "Number"
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "DIVISOR",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"inputsInline": true,
|
||||
"output": "Number",
|
||||
"colour": Blockly.Blocks.math.HUE,
|
||||
"tooltip": Blockly.Msg.MATH_MODULO_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.MATH_MODULO_HELPURL
|
||||
function() {
|
||||
var thisBlock = this;
|
||||
goog.mixin(this, Blockly.Blocks.math.LIST_MODES_MUTATOR_MIXIN_);
|
||||
this.getField('OP').setValidator(function(newOp) {
|
||||
thisBlock.updateType_(newOp);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_constrain'] = {
|
||||
/**
|
||||
* Block for constraining a number between two limits.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": Blockly.Msg.MATH_CONSTRAIN_TITLE,
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "VALUE",
|
||||
"check": "Number"
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "LOW",
|
||||
"check": "Number"
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "HIGH",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"inputsInline": true,
|
||||
"output": "Number",
|
||||
"colour": Blockly.Blocks.math.HUE,
|
||||
"tooltip": Blockly.Msg.MATH_CONSTRAIN_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.MATH_CONSTRAIN_HELPURL
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_random_int'] = {
|
||||
/**
|
||||
* Block for random integer between [X] and [Y].
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": Blockly.Msg.MATH_RANDOM_INT_TITLE,
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "FROM",
|
||||
"check": "Number"
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "TO",
|
||||
"check": "Number"
|
||||
}
|
||||
],
|
||||
"inputsInline": true,
|
||||
"output": "Number",
|
||||
"colour": Blockly.Blocks.math.HUE,
|
||||
"tooltip": Blockly.Msg.MATH_RANDOM_INT_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.MATH_RANDOM_INT_HELPURL
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_random_float'] = {
|
||||
/**
|
||||
* Block for random fraction between 0 and 1.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.jsonInit({
|
||||
"message0": Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM,
|
||||
"output": "Number",
|
||||
"colour": Blockly.Blocks.math.HUE,
|
||||
"tooltip": Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP,
|
||||
"helpUrl": Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1024,6 +1024,11 @@ Blockly.Block.prototype.jsonInit = function(json) {
|
||||
var localizedValue = Blockly.utils.replaceMessageReferences(rawValue);
|
||||
this.setHelpUrl(localizedValue);
|
||||
}
|
||||
if (goog.isString(json['extensions'])) {
|
||||
console.warn('JSON attribute \'extensions\' should be an array of ' +
|
||||
'strings. Found raw string in JSON for \'' + json['type'] + '\' block.');
|
||||
json['extensions'] = [json['extensions']]; // Correct and continue.
|
||||
}
|
||||
if (Array.isArray(json['extensions'])) {
|
||||
var extensionNames = json['extensions'];
|
||||
for (var i = 0; i < extensionNames.length; ++i) {
|
||||
|
||||
@@ -74,6 +74,82 @@ Blockly.Extensions.apply = function(name, block) {
|
||||
extensionFn.apply(block);
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds an extension function that will map a dropdown value to a tooltip string.
|
||||
* Tooltip strings will be passed through Blockly.utils.checkMessageReferences(..)
|
||||
* immediately and Blockly.utils.replaceMessageReferences(..) at display time.
|
||||
* @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
|
||||
* tooltip text.
|
||||
* @return {Function} The extension function.
|
||||
*/
|
||||
Blockly.Extensions.buildTooltipForDropdown = function(dropdownName, lookupTable) {
|
||||
// List of block types already validated, to minimize duplicate warnings.
|
||||
var blockTypesChecked = [];
|
||||
|
||||
// Validate message strings early.
|
||||
for (var key in lookupTable) {
|
||||
Blockly.utils.checkMessageReferences(lookupTable[key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual extension.
|
||||
* @this {Blockly.Block}
|
||||
*/
|
||||
return function() {
|
||||
var thisBlock = this;
|
||||
|
||||
if (this.type && !blockTypesChecked.includes(this.type)) {
|
||||
Blockly.Extensions.checkDropdownOptionsInTable_(
|
||||
this, dropdownName, lookupTable);
|
||||
blockTypesChecked.push(this.type);
|
||||
}
|
||||
|
||||
this.setTooltip(function() {
|
||||
var value = thisBlock.getFieldValue(dropdownName);
|
||||
var tooltip = lookupTable[value];
|
||||
if (tooltip == null) {
|
||||
if (!blockTypesChecked.includes(thisBlock.type)) {
|
||||
// Warn for missing values on generated tooltips
|
||||
var warning = 'No tooltip mapping for value ' + value +
|
||||
' of field ' + dropdownName;
|
||||
if (thisBlock.type != null) {
|
||||
warning += (' of block type ' + thisBlock.type);
|
||||
}
|
||||
console.warn(warning + '.');
|
||||
}
|
||||
} else {
|
||||
tooltip = Blockly.utils.replaceMessageReferences(tooltip);
|
||||
}
|
||||
return tooltip;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks all options keys are present in the provided string lookup table.
|
||||
* 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
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Configures the tooltip to mimic the parent block when connected. Otherwise,
|
||||
* uses the tooltip text at the time this extension is initialized. This takes
|
||||
|
||||
@@ -52,7 +52,7 @@ goog.require('goog.userAgent');
|
||||
Blockly.FieldDropdown = function(menuGenerator, opt_validator) {
|
||||
this.menuGenerator_ = menuGenerator;
|
||||
this.trimOptions_();
|
||||
var firstTuple = this.getOptions_()[0];
|
||||
var firstTuple = this.getOptions()[0];
|
||||
|
||||
// Call parent's constructor.
|
||||
Blockly.FieldDropdown.superClass_.constructor.call(this, firstTuple[1],
|
||||
@@ -138,7 +138,7 @@ Blockly.FieldDropdown.prototype.showEditor_ = function() {
|
||||
|
||||
var menu = new goog.ui.Menu();
|
||||
menu.setRightToLeft(this.sourceBlock_.RTL);
|
||||
var options = this.getOptions_();
|
||||
var options = this.getOptions();
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
var content = options[i][0]; // Human-readable text or image.
|
||||
var value = options[i][1]; // Language-neutral value.
|
||||
@@ -230,7 +230,7 @@ Blockly.FieldDropdown.prototype.onItemSelected = function(menu, menuItem) {
|
||||
if (value !== null) {
|
||||
this.setValue(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Factor out common words in statically defined options.
|
||||
@@ -288,13 +288,19 @@ Blockly.FieldDropdown.prototype.trimOptions_ = function() {
|
||||
this.menuGenerator_ = newOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the option list is generated by a function. Otherwise false.
|
||||
*/
|
||||
Blockly.FieldDropdown.prototype.isOptionListDynamic = function() {
|
||||
return goog.isFunction(this.menuGenerator_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a list of the options for this dropdown.
|
||||
* @return {!Array.<!Array>} Array of option tuples:
|
||||
* (human-readable text or image, language-neutral name).
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldDropdown.prototype.getOptions_ = function() {
|
||||
Blockly.FieldDropdown.prototype.getOptions = function() {
|
||||
if (goog.isFunction(this.menuGenerator_)) {
|
||||
return this.menuGenerator_.call(this);
|
||||
}
|
||||
@@ -323,7 +329,7 @@ Blockly.FieldDropdown.prototype.setValue = function(newValue) {
|
||||
}
|
||||
this.value_ = newValue;
|
||||
// Look up and display the human-readable text.
|
||||
var options = this.getOptions_();
|
||||
var options = this.getOptions();
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
// Options are tuples of human-readable text and language-neutral values.
|
||||
if (options[i][1] == newValue) {
|
||||
|
||||
@@ -84,15 +84,15 @@ Blockly.utils.removeClass = function(element, className) {
|
||||
/**
|
||||
* Checks if an element has the specified CSS class.
|
||||
* Similar to Closure's goog.dom.classes.has, except it handles SVG elements.
|
||||
* @param {!Element} element DOM element to check.
|
||||
* @param {string} className Name of class to check.
|
||||
* @return {boolean} True if class exists, false otherwise.
|
||||
* @private
|
||||
*/
|
||||
Blockly.utils.hasClass = function(element, className) {
|
||||
var classes = element.getAttribute('class');
|
||||
return (' ' + classes + ' ').indexOf(' ' + className + ' ') != -1;
|
||||
};
|
||||
* @param {!Element} element DOM element to check.
|
||||
* @param {string} className Name of class to check.
|
||||
* @return {boolean} True if class exists, false otherwise.
|
||||
* @private
|
||||
*/
|
||||
Blockly.utils.hasClass = function(element, className) {
|
||||
var classes = element.getAttribute('class');
|
||||
return (' ' + classes + ' ').indexOf(' ' + className + ' ') != -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Don't do anything for this event, just halt propagation.
|
||||
@@ -144,7 +144,7 @@ Blockly.utils.getRelativeXY = function(element) {
|
||||
}
|
||||
}
|
||||
|
||||
// Then check for style = transform: translate(...) or translate3d(...)
|
||||
// Then check for style = transform: translate(...) or translate3d(...)
|
||||
var style = element.getAttribute('style');
|
||||
if (style && style.indexOf('translate') > -1) {
|
||||
var styleComponents = style.match(Blockly.utils.getRelativeXY.XY_2D_REGEX_);
|
||||
@@ -164,7 +164,7 @@ Blockly.utils.getRelativeXY = function(element) {
|
||||
|
||||
/**
|
||||
* Return the coordinates of the top-left corner of this element relative to
|
||||
* the div blockly was injected into.
|
||||
* the div blockly was injected into.
|
||||
* @param {!Element} element SVG element to find the coordinates of. If this is
|
||||
* not a child of the div blockly was injected into, the behaviour is
|
||||
* undefined.
|
||||
@@ -185,7 +185,7 @@ Blockly.utils.getInjectionDivXY_ = function(element) {
|
||||
}
|
||||
element = element.parentNode;
|
||||
}
|
||||
return new goog.math.Coordinate(x, y);
|
||||
return new goog.math.Coordinate(x, y);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -195,9 +195,9 @@ Blockly.utils.getInjectionDivXY_ = function(element) {
|
||||
* @private
|
||||
*/
|
||||
Blockly.utils.getScale_ = function(element) {
|
||||
var scale = 1;
|
||||
var scale = 1;
|
||||
var transform = element.getAttribute('transform');
|
||||
if (transform) {
|
||||
if (transform) {
|
||||
var transformComponents =
|
||||
transform.match(Blockly.utils.getScale_.REGEXP_);
|
||||
if (transformComponents && transformComponents[0]) {
|
||||
@@ -315,7 +315,7 @@ Blockly.utils.shortestStringLength = function(array) {
|
||||
if (!array.length) {
|
||||
return 0;
|
||||
}
|
||||
return array.reduce(function (a, b) {
|
||||
return array.reduce(function(a, b) {
|
||||
return a.length < b.length ? a : b;
|
||||
}).length;
|
||||
};
|
||||
@@ -402,7 +402,7 @@ Blockly.utils.commonWordSuffix = function(array, opt_shortest) {
|
||||
*/
|
||||
Blockly.utils.tokenizeInterpolation = function(message) {
|
||||
return Blockly.utils.tokenizeInterpolation_(message, true);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Replaces string table references in a message string. For example,
|
||||
@@ -416,7 +416,34 @@ Blockly.utils.replaceMessageReferences = function(message) {
|
||||
// When parseInterpolationTokens == false, interpolatedResult should be at
|
||||
// most length 1.
|
||||
return interpolatedResult.length ? interpolatedResult[0] : "";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates that any %{BKY_...} 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 regex = /%{BKY_([a-zA-Z][a-zA-Z0-9_]*)}/g;
|
||||
var match = regex.exec(message);
|
||||
while (match != null) {
|
||||
var msgKey = match[1];
|
||||
if (Blockly.Msg[msgKey] == null) {
|
||||
console.log('WARNING: No message string for %{BKY_' + msgKey + '}.');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
// Re-run on remainder of sting.
|
||||
message = message.substring(match.index + msgKey.length + 1);
|
||||
match = regex.exec(message);
|
||||
}
|
||||
|
||||
return isValid;
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal implemention of the message reference and interpolation token
|
||||
|
||||
Reference in New Issue
Block a user