blockly 7.20211209.4 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/blockly.d.ts +18963 -18432
  2. package/blockly.min.js +5 -4
  3. package/blockly_compressed.js +4 -3
  4. package/blockly_compressed.js.map +1 -1
  5. package/blocks/blocks.js +47 -0
  6. package/blocks/colour.js +13 -3
  7. package/blocks/lists.js +22 -13
  8. package/blocks/logic.js +13 -3
  9. package/blocks/loops.js +24 -11
  10. package/blocks/math.js +12 -3
  11. package/blocks/procedures.js +45 -32
  12. package/blocks/text.js +22 -13
  13. package/blocks/variables.js +14 -3
  14. package/blocks/variables_dynamic.js +13 -3
  15. package/blocks_compressed.js +1 -1
  16. package/blocks_compressed.js.map +1 -1
  17. package/core/block.js +1869 -1814
  18. package/core/block_drag_surface.js +201 -200
  19. package/core/block_dragger.js +377 -373
  20. package/core/block_svg.js +1593 -1479
  21. package/core/blockly.js +8 -22
  22. package/core/blocks.js +9 -2
  23. package/core/browser_events.js +22 -5
  24. package/core/bubble.js +841 -797
  25. package/core/bubble_dragger.js +213 -206
  26. package/core/bump_objects.js +2 -2
  27. package/core/clipboard.js +9 -9
  28. package/core/comment.js +353 -332
  29. package/core/common.js +46 -17
  30. package/core/component_manager.js +181 -174
  31. package/core/config.js +87 -0
  32. package/core/connection.js +595 -584
  33. package/core/connection_checker.js +242 -244
  34. package/core/connection_db.js +235 -230
  35. package/core/contextmenu.js +9 -6
  36. package/core/contextmenu_items.js +1 -2
  37. package/core/contextmenu_registry.js +93 -89
  38. package/core/css.js +474 -474
  39. package/core/delete_area.js +45 -42
  40. package/core/drag_target.js +57 -56
  41. package/core/dropdowndiv.js +153 -163
  42. package/core/events/events.js +2 -2
  43. package/core/events/events_abstract.js +89 -77
  44. package/core/events/events_block_base.js +37 -36
  45. package/core/events/events_block_change.js +130 -124
  46. package/core/events/events_block_create.js +73 -71
  47. package/core/events/events_block_delete.js +84 -82
  48. package/core/events/events_block_drag.js +50 -49
  49. package/core/events/events_block_move.js +147 -140
  50. package/core/events/events_bubble_open.js +51 -50
  51. package/core/events/events_click.js +48 -44
  52. package/core/events/events_comment_base.js +72 -69
  53. package/core/events/events_comment_change.js +63 -61
  54. package/core/events/events_comment_create.js +44 -42
  55. package/core/events/events_comment_delete.js +42 -40
  56. package/core/events/events_comment_move.js +106 -104
  57. package/core/events/events_marker_move.js +65 -64
  58. package/core/events/events_selected.js +46 -45
  59. package/core/events/events_theme_change.js +36 -35
  60. package/core/events/events_toolbox_item_select.js +46 -45
  61. package/core/events/events_trashcan_open.js +37 -36
  62. package/core/events/events_ui.js +47 -46
  63. package/core/events/events_ui_base.js +30 -29
  64. package/core/events/events_var_base.js +37 -36
  65. package/core/events/events_var_create.js +50 -48
  66. package/core/events/events_var_delete.js +50 -48
  67. package/core/events/events_var_rename.js +51 -49
  68. package/core/events/events_viewport.js +66 -65
  69. package/core/events/utils.js +29 -14
  70. package/core/events/workspace_events.js +49 -55
  71. package/core/extensions.js +4 -3
  72. package/core/field.js +1061 -997
  73. package/core/field_angle.js +462 -442
  74. package/core/field_checkbox.js +194 -182
  75. package/core/field_colour.js +519 -505
  76. package/core/field_dropdown.js +617 -598
  77. package/core/field_image.js +229 -220
  78. package/core/field_label.js +102 -91
  79. package/core/field_label_serializable.js +42 -41
  80. package/core/field_multilineinput.js +372 -358
  81. package/core/field_number.js +272 -253
  82. package/core/field_textinput.js +499 -467
  83. package/core/field_variable.js +458 -420
  84. package/core/flyout_base.js +1005 -952
  85. package/core/flyout_button.js +277 -260
  86. package/core/flyout_horizontal.js +304 -302
  87. package/core/flyout_metrics_manager.js +64 -64
  88. package/core/flyout_vertical.js +306 -300
  89. package/core/generator.js +459 -446
  90. package/core/gesture.js +829 -813
  91. package/core/grid.js +166 -163
  92. package/core/icon.js +168 -159
  93. package/core/inject.js +7 -5
  94. package/core/input.js +257 -248
  95. package/core/insertion_marker_manager.js +655 -624
  96. package/core/internal_constants.js +0 -129
  97. package/core/keyboard_nav/ast_node.js +605 -596
  98. package/core/keyboard_nav/basic_cursor.js +166 -165
  99. package/core/keyboard_nav/cursor.js +99 -97
  100. package/core/keyboard_nav/marker.js +83 -79
  101. package/core/keyboard_nav/tab_navigate_cursor.js +18 -23
  102. package/core/marker_manager.js +153 -141
  103. package/core/menu.js +377 -372
  104. package/core/menuitem.js +223 -217
  105. package/core/metrics_manager.js +403 -390
  106. package/core/mutator.js +468 -437
  107. package/core/names.js +229 -188
  108. package/core/options.js +290 -284
  109. package/core/procedures.js +29 -17
  110. package/core/registry.js +19 -16
  111. package/core/rendered_connection.js +482 -463
  112. package/core/renderers/common/block_rendering.js +9 -3
  113. package/core/renderers/common/constants.js +1119 -1112
  114. package/core/renderers/common/debug.js +14 -0
  115. package/core/renderers/common/debugger.js +338 -316
  116. package/core/renderers/common/drawer.js +380 -370
  117. package/core/renderers/common/i_path_object.js +2 -2
  118. package/core/renderers/common/info.js +626 -618
  119. package/core/renderers/common/marker_svg.js +579 -541
  120. package/core/renderers/common/path_object.js +203 -200
  121. package/core/renderers/common/renderer.js +220 -218
  122. package/core/renderers/geras/constants.js +36 -36
  123. package/core/renderers/geras/drawer.js +155 -147
  124. package/core/renderers/geras/highlight_constants.js +244 -238
  125. package/core/renderers/geras/highlighter.js +231 -179
  126. package/core/renderers/geras/info.js +392 -369
  127. package/core/renderers/geras/measurables/inline_input.js +25 -19
  128. package/core/renderers/geras/measurables/statement_input.js +23 -17
  129. package/core/renderers/geras/path_object.js +106 -121
  130. package/core/renderers/geras/renderer.js +96 -98
  131. package/core/renderers/measurables/base.js +30 -18
  132. package/core/renderers/measurables/bottom_row.js +83 -80
  133. package/core/renderers/measurables/connection.js +22 -15
  134. package/core/renderers/measurables/external_value_input.js +35 -22
  135. package/core/renderers/measurables/field.js +35 -20
  136. package/core/renderers/measurables/hat.js +18 -13
  137. package/core/renderers/measurables/icon.js +24 -17
  138. package/core/renderers/measurables/in_row_spacer.js +15 -13
  139. package/core/renderers/measurables/inline_input.js +43 -33
  140. package/core/renderers/measurables/input_connection.js +41 -28
  141. package/core/renderers/measurables/input_row.js +50 -44
  142. package/core/renderers/measurables/jagged_edge.js +14 -12
  143. package/core/renderers/measurables/next_connection.js +16 -14
  144. package/core/renderers/measurables/output_connection.js +26 -20
  145. package/core/renderers/measurables/previous_connection.js +16 -15
  146. package/core/renderers/measurables/round_corner.js +20 -18
  147. package/core/renderers/measurables/row.js +184 -168
  148. package/core/renderers/measurables/spacer_row.js +38 -23
  149. package/core/renderers/measurables/square_corner.js +18 -16
  150. package/core/renderers/measurables/statement_input.js +23 -20
  151. package/core/renderers/measurables/top_row.js +88 -85
  152. package/core/renderers/minimalist/constants.js +8 -7
  153. package/core/renderers/minimalist/drawer.js +11 -10
  154. package/core/renderers/minimalist/info.js +18 -18
  155. package/core/renderers/minimalist/renderer.js +40 -39
  156. package/core/renderers/thrasos/info.js +258 -248
  157. package/core/renderers/thrasos/renderer.js +20 -20
  158. package/core/renderers/zelos/constants.js +898 -873
  159. package/core/renderers/zelos/drawer.js +186 -169
  160. package/core/renderers/zelos/info.js +502 -479
  161. package/core/renderers/zelos/marker_svg.js +129 -115
  162. package/core/renderers/zelos/measurables/bottom_row.js +31 -30
  163. package/core/renderers/zelos/measurables/inputs.js +22 -21
  164. package/core/renderers/zelos/measurables/row_elements.js +14 -13
  165. package/core/renderers/zelos/measurables/top_row.js +34 -33
  166. package/core/renderers/zelos/path_object.js +181 -180
  167. package/core/renderers/zelos/renderer.js +91 -92
  168. package/core/scrollbar.js +759 -713
  169. package/core/scrollbar_pair.js +250 -245
  170. package/core/serialization/blocks.js +26 -10
  171. package/core/serialization/workspaces.js +3 -2
  172. package/core/shortcut_registry.js +286 -277
  173. package/core/sprites.js +31 -0
  174. package/core/theme.js +135 -141
  175. package/core/theme_manager.js +147 -143
  176. package/core/toolbox/category.js +602 -576
  177. package/core/toolbox/collapsible_category.js +226 -227
  178. package/core/toolbox/separator.js +70 -61
  179. package/core/toolbox/toolbox.js +934 -927
  180. package/core/toolbox/toolbox_item.js +115 -99
  181. package/core/tooltip.js +108 -35
  182. package/core/touch.js +8 -3
  183. package/core/touch_gesture.js +254 -251
  184. package/core/trashcan.js +606 -595
  185. package/core/utils/coordinate.js +97 -95
  186. package/core/utils/dom.js +2 -2
  187. package/core/utils/global.js +2 -0
  188. package/core/utils/rect.js +41 -37
  189. package/core/utils/sentinel.js +25 -0
  190. package/core/utils/size.js +30 -27
  191. package/core/utils/svg.js +18 -16
  192. package/core/variable_map.js +325 -341
  193. package/core/variable_model.js +55 -54
  194. package/core/variables.js +9 -2
  195. package/core/variables_dynamic.js +3 -1
  196. package/core/warning.js +126 -120
  197. package/core/widgetdiv.js +4 -4
  198. package/core/workspace.js +685 -664
  199. package/core/workspace_audio.js +124 -118
  200. package/core/workspace_comment.js +308 -298
  201. package/core/workspace_comment_svg.js +1029 -951
  202. package/core/workspace_drag_surface_svg.js +147 -140
  203. package/core/workspace_dragger.js +70 -71
  204. package/core/workspace_svg.js +2322 -2297
  205. package/core/xml.js +30 -20
  206. package/core/zoom_controls.js +431 -439
  207. package/generators/dart/colour.js +56 -64
  208. package/generators/dart/lists.js +61 -50
  209. package/generators/dart/math.js +160 -148
  210. package/generators/dart/text.js +83 -61
  211. package/generators/javascript/colour.js +37 -34
  212. package/generators/javascript/lists.js +50 -43
  213. package/generators/javascript/math.js +123 -139
  214. package/generators/javascript/text.js +67 -81
  215. package/generators/lua/colour.js +25 -23
  216. package/generators/lua/lists.js +97 -69
  217. package/generators/lua/logic.js +1 -2
  218. package/generators/lua/math.js +182 -144
  219. package/generators/lua/text.js +116 -99
  220. package/generators/php/colour.js +38 -32
  221. package/generators/php/lists.js +109 -89
  222. package/generators/php/math.js +90 -81
  223. package/generators/php/text.js +63 -61
  224. package/generators/python/colour.js +18 -18
  225. package/generators/python/lists.js +38 -30
  226. package/generators/python/loops.js +12 -8
  227. package/generators/python/math.js +104 -106
  228. package/generators/python/text.js +34 -30
  229. package/msg/smn.js +436 -0
  230. package/package.json +7 -6
  231. package/blocks/all.js +0 -23
@@ -17,304 +17,323 @@ goog.module('Blockly.FieldNumber');
17
17
 
18
18
  const aria = goog.require('Blockly.utils.aria');
19
19
  const fieldRegistry = goog.require('Blockly.fieldRegistry');
20
- const object = goog.require('Blockly.utils.object');
20
+ const {Field} = goog.require('Blockly.Field');
21
21
  const {FieldTextInput} = goog.require('Blockly.FieldTextInput');
22
+ /* eslint-disable-next-line no-unused-vars */
23
+ const {Sentinel} = goog.requireType('Blockly.utils.Sentinel');
22
24
 
23
25
 
24
26
  /**
25
27
  * Class for an editable number field.
26
- * @param {string|number=} opt_value The initial value of the field. Should cast
27
- * to a number. Defaults to 0.
28
- * @param {?(string|number)=} opt_min Minimum value.
29
- * @param {?(string|number)=} opt_max Maximum value.
30
- * @param {?(string|number)=} opt_precision Precision for value.
31
- * @param {?Function=} opt_validator A function that is called to validate
32
- * changes to the field's value. Takes in a number & returns a validated
33
- * number, or null to abort the change.
34
- * @param {Object=} opt_config A map of options used to configure the field.
35
- * See the [field creation documentation]{@link
36
- * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/number#creation}
37
- * for a list of properties this parameter supports.
38
28
  * @extends {FieldTextInput}
39
- * @constructor
40
29
  * @alias Blockly.FieldNumber
41
30
  */
42
- const FieldNumber = function(
43
- opt_value, opt_min, opt_max, opt_precision, opt_validator, opt_config) {
31
+ class FieldNumber extends FieldTextInput {
44
32
  /**
45
- * The minimum value this number field can contain.
46
- * @type {number}
47
- * @protected
33
+ * @param {(string|number|!Sentinel)=} opt_value The initial value of
34
+ * the field. Should cast to a number. Defaults to 0.
35
+ * Also accepts Field.SKIP_SETUP if you wish to skip setup (only used by
36
+ * subclasses that want to handle configuration and setting the field
37
+ * value after their own constructors have run).
38
+ * @param {?(string|number)=} opt_min Minimum value. Will only be used if
39
+ * opt_config is not provided.
40
+ * @param {?(string|number)=} opt_max Maximum value. Will only be used if
41
+ * opt_config is not provided.
42
+ * @param {?(string|number)=} opt_precision Precision for value. Will only be
43
+ * used if opt_config is not provided.
44
+ * @param {?Function=} opt_validator A function that is called to validate
45
+ * changes to the field's value. Takes in a number & returns a validated
46
+ * number, or null to abort the change.
47
+ * @param {Object=} opt_config A map of options used to configure the field.
48
+ * See the [field creation documentation]{@link
49
+ * https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/number#creation}
50
+ * for a list of properties this parameter supports.
48
51
  */
49
- this.min_ = -Infinity;
52
+ constructor(
53
+ opt_value, opt_min, opt_max, opt_precision, opt_validator, opt_config) {
54
+ // Pass SENTINEL so that we can define properties before value validation.
55
+ super(Field.SKIP_SETUP);
56
+
57
+ /**
58
+ * The minimum value this number field can contain.
59
+ * @type {number}
60
+ * @protected
61
+ */
62
+ this.min_ = -Infinity;
63
+
64
+ /**
65
+ * The maximum value this number field can contain.
66
+ * @type {number}
67
+ * @protected
68
+ */
69
+ this.max_ = Infinity;
70
+
71
+ /**
72
+ * The multiple to which this fields value is rounded.
73
+ * @type {number}
74
+ * @protected
75
+ */
76
+ this.precision_ = 0;
77
+
78
+ /**
79
+ * The number of decimal places to allow, or null to allow any number of
80
+ * decimal digits.
81
+ * @type {?number}
82
+ * @private
83
+ */
84
+ this.decimalPlaces_ = null;
85
+
86
+ /**
87
+ * Serializable fields are saved by the serializer, non-serializable fields
88
+ * are not. Editable fields should also be serializable.
89
+ * @type {boolean}
90
+ */
91
+ this.SERIALIZABLE = true;
92
+
93
+ if (opt_value === Field.SKIP_SETUP) return;
94
+ if (opt_config) {
95
+ this.configure_(opt_config);
96
+ } else {
97
+ this.setConstraints(opt_min, opt_max, opt_precision);
98
+ }
99
+ this.setValue(opt_value);
100
+ if (opt_validator) this.setValidator(opt_validator);
101
+ }
50
102
 
51
103
  /**
52
- * The maximum value this number field can contain.
53
- * @type {number}
104
+ * Configure the field based on the given map of options.
105
+ * @param {!Object} config A map of options to configure the field based on.
54
106
  * @protected
107
+ * @override
55
108
  */
56
- this.max_ = Infinity;
109
+ configure_(config) {
110
+ super.configure_(config);
111
+ this.setMinInternal_(config['min']);
112
+ this.setMaxInternal_(config['max']);
113
+ this.setPrecisionInternal_(config['precision']);
114
+ }
57
115
 
58
116
  /**
59
- * The multiple to which this fields value is rounded.
60
- * @type {number}
61
- * @protected
117
+ * Set the maximum, minimum and precision constraints on this field.
118
+ * Any of these properties may be undefined or NaN to be disabled.
119
+ * Setting precision (usually a power of 10) enforces a minimum step between
120
+ * values. That is, the user's value will rounded to the closest multiple of
121
+ * precision. The least significant digit place is inferred from the
122
+ * precision. Integers values can be enforces by choosing an integer
123
+ * precision.
124
+ * @param {?(number|string|undefined)} min Minimum value.
125
+ * @param {?(number|string|undefined)} max Maximum value.
126
+ * @param {?(number|string|undefined)} precision Precision for value.
62
127
  */
63
- this.precision_ = 0;
128
+ setConstraints(min, max, precision) {
129
+ this.setMinInternal_(min);
130
+ this.setMaxInternal_(max);
131
+ this.setPrecisionInternal_(precision);
132
+ this.setValue(this.getValue());
133
+ }
64
134
 
65
135
  /**
66
- * The number of decimal places to allow, or null to allow any number of
67
- * decimal digits.
68
- * @type {?number}
69
- * @private
136
+ * Sets the minimum value this field can contain. Updates the value to
137
+ * reflect.
138
+ * @param {?(number|string|undefined)} min Minimum value.
70
139
  */
71
- this.decimalPlaces_ = null;
72
-
73
- FieldNumber.superClass_.constructor.call(
74
- this, opt_value, opt_validator, opt_config);
75
-
76
- if (!opt_config) { // Only do one kind of configuration or the other.
77
- this.setConstraints(opt_min, opt_max, opt_precision);
140
+ setMin(min) {
141
+ this.setMinInternal_(min);
142
+ this.setValue(this.getValue());
78
143
  }
79
- };
80
- object.inherits(FieldNumber, FieldTextInput);
81
-
82
- /**
83
- * The default value for this field.
84
- * @type {*}
85
- * @protected
86
- */
87
- FieldNumber.prototype.DEFAULT_VALUE = 0;
88
-
89
- /**
90
- * Construct a FieldNumber from a JSON arg object.
91
- * @param {!Object} options A JSON object with options (value, min, max, and
92
- * precision).
93
- * @return {!FieldNumber} The new field instance.
94
- * @package
95
- * @nocollapse
96
- */
97
- FieldNumber.fromJson = function(options) {
98
- // `this` might be a subclass of FieldNumber if that class doesn't override
99
- // the static fromJson method.
100
- return new this(
101
- options['value'], undefined, undefined, undefined, undefined, options);
102
- };
103
144
 
104
- /**
105
- * Serializable fields are saved by the XML renderer, non-serializable fields
106
- * are not. Editable fields should also be serializable.
107
- * @type {boolean}
108
- */
109
- FieldNumber.prototype.SERIALIZABLE = true;
110
-
111
- /**
112
- * Configure the field based on the given map of options.
113
- * @param {!Object} config A map of options to configure the field based on.
114
- * @protected
115
- * @override
116
- */
117
- FieldNumber.prototype.configure_ = function(config) {
118
- FieldNumber.superClass_.configure_.call(this, config);
119
- this.setMinInternal_(config['min']);
120
- this.setMaxInternal_(config['max']);
121
- this.setPrecisionInternal_(config['precision']);
122
- };
145
+ /**
146
+ * Sets the minimum value this field can contain. Called internally to avoid
147
+ * value updates.
148
+ * @param {?(number|string|undefined)} min Minimum value.
149
+ * @private
150
+ */
151
+ setMinInternal_(min) {
152
+ if (min == null) {
153
+ this.min_ = -Infinity;
154
+ } else {
155
+ min = Number(min);
156
+ if (!isNaN(min)) {
157
+ this.min_ = min;
158
+ }
159
+ }
160
+ }
123
161
 
124
- /**
125
- * Set the maximum, minimum and precision constraints on this field.
126
- * Any of these properties may be undefined or NaN to be disabled.
127
- * Setting precision (usually a power of 10) enforces a minimum step between
128
- * values. That is, the user's value will rounded to the closest multiple of
129
- * precision. The least significant digit place is inferred from the precision.
130
- * Integers values can be enforces by choosing an integer precision.
131
- * @param {?(number|string|undefined)} min Minimum value.
132
- * @param {?(number|string|undefined)} max Maximum value.
133
- * @param {?(number|string|undefined)} precision Precision for value.
134
- */
135
- FieldNumber.prototype.setConstraints = function(min, max, precision) {
136
- this.setMinInternal_(min);
137
- this.setMaxInternal_(max);
138
- this.setPrecisionInternal_(precision);
139
- this.setValue(this.getValue());
140
- };
162
+ /**
163
+ * Returns the current minimum value this field can contain. Default is
164
+ * -Infinity.
165
+ * @return {number} The current minimum value this field can contain.
166
+ */
167
+ getMin() {
168
+ return this.min_;
169
+ }
141
170
 
142
- /**
143
- * Sets the minimum value this field can contain. Updates the value to reflect.
144
- * @param {?(number|string|undefined)} min Minimum value.
145
- */
146
- FieldNumber.prototype.setMin = function(min) {
147
- this.setMinInternal_(min);
148
- this.setValue(this.getValue());
149
- };
171
+ /**
172
+ * Sets the maximum value this field can contain. Updates the value to
173
+ * reflect.
174
+ * @param {?(number|string|undefined)} max Maximum value.
175
+ */
176
+ setMax(max) {
177
+ this.setMaxInternal_(max);
178
+ this.setValue(this.getValue());
179
+ }
150
180
 
151
- /**
152
- * Sets the minimum value this field can contain. Called internally to avoid
153
- * value updates.
154
- * @param {?(number|string|undefined)} min Minimum value.
155
- * @private
156
- */
157
- FieldNumber.prototype.setMinInternal_ = function(min) {
158
- if (min == null) {
159
- this.min_ = -Infinity;
160
- } else {
161
- min = Number(min);
162
- if (!isNaN(min)) {
163
- this.min_ = min;
181
+ /**
182
+ * Sets the maximum value this field can contain. Called internally to avoid
183
+ * value updates.
184
+ * @param {?(number|string|undefined)} max Maximum value.
185
+ * @private
186
+ */
187
+ setMaxInternal_(max) {
188
+ if (max == null) {
189
+ this.max_ = Infinity;
190
+ } else {
191
+ max = Number(max);
192
+ if (!isNaN(max)) {
193
+ this.max_ = max;
194
+ }
164
195
  }
165
196
  }
166
- };
167
197
 
168
- /**
169
- * Returns the current minimum value this field can contain. Default is
170
- * -Infinity.
171
- * @return {number} The current minimum value this field can contain.
172
- */
173
- FieldNumber.prototype.getMin = function() {
174
- return this.min_;
175
- };
198
+ /**
199
+ * Returns the current maximum value this field can contain. Default is
200
+ * Infinity.
201
+ * @return {number} The current maximum value this field can contain.
202
+ */
203
+ getMax() {
204
+ return this.max_;
205
+ }
176
206
 
177
- /**
178
- * Sets the maximum value this field can contain. Updates the value to reflect.
179
- * @param {?(number|string|undefined)} max Maximum value.
180
- */
181
- FieldNumber.prototype.setMax = function(max) {
182
- this.setMaxInternal_(max);
183
- this.setValue(this.getValue());
184
- };
207
+ /**
208
+ * Sets the precision of this field's value, i.e. the number to which the
209
+ * value is rounded. Updates the field to reflect.
210
+ * @param {?(number|string|undefined)} precision The number to which the
211
+ * field's value is rounded.
212
+ */
213
+ setPrecision(precision) {
214
+ this.setPrecisionInternal_(precision);
215
+ this.setValue(this.getValue());
216
+ }
185
217
 
186
- /**
187
- * Sets the maximum value this field can contain. Called internally to avoid
188
- * value updates.
189
- * @param {?(number|string|undefined)} max Maximum value.
190
- * @private
191
- */
192
- FieldNumber.prototype.setMaxInternal_ = function(max) {
193
- if (max == null) {
194
- this.max_ = Infinity;
195
- } else {
196
- max = Number(max);
197
- if (!isNaN(max)) {
198
- this.max_ = max;
218
+ /**
219
+ * Sets the precision of this field's value. Called internally to avoid
220
+ * value updates.
221
+ * @param {?(number|string|undefined)} precision The number to which the
222
+ * field's value is rounded.
223
+ * @private
224
+ */
225
+ setPrecisionInternal_(precision) {
226
+ this.precision_ = Number(precision) || 0;
227
+ let precisionString = String(this.precision_);
228
+ if (precisionString.indexOf('e') !== -1) {
229
+ // String() is fast. But it turns .0000001 into '1e-7'.
230
+ // Use the much slower toLocaleString to access all the digits.
231
+ precisionString =
232
+ this.precision_.toLocaleString('en-US', {maximumFractionDigits: 20});
233
+ }
234
+ const decimalIndex = precisionString.indexOf('.');
235
+ if (decimalIndex === -1) {
236
+ // If the precision is 0 (float) allow any number of decimals,
237
+ // otherwise allow none.
238
+ this.decimalPlaces_ = precision ? 0 : null;
239
+ } else {
240
+ this.decimalPlaces_ = precisionString.length - decimalIndex - 1;
199
241
  }
200
242
  }
201
- };
202
243
 
203
- /**
204
- * Returns the current maximum value this field can contain. Default is
205
- * Infinity.
206
- * @return {number} The current maximum value this field can contain.
207
- */
208
- FieldNumber.prototype.getMax = function() {
209
- return this.max_;
210
- };
244
+ /**
245
+ * Returns the current precision of this field. The precision being the
246
+ * number to which the field's value is rounded. A precision of 0 means that
247
+ * the value is not rounded.
248
+ * @return {number} The number to which this field's value is rounded.
249
+ */
250
+ getPrecision() {
251
+ return this.precision_;
252
+ }
211
253
 
212
- /**
213
- * Sets the precision of this field's value, i.e. the number to which the
214
- * value is rounded. Updates the field to reflect.
215
- * @param {?(number|string|undefined)} precision The number to which the
216
- * field's value is rounded.
217
- */
218
- FieldNumber.prototype.setPrecision = function(precision) {
219
- this.setPrecisionInternal_(precision);
220
- this.setValue(this.getValue());
221
- };
254
+ /**
255
+ * Ensure that the input value is a valid number (must fulfill the
256
+ * constraints placed on the field).
257
+ * @param {*=} opt_newValue The input value.
258
+ * @return {?number} A valid number, or null if invalid.
259
+ * @protected
260
+ * @override
261
+ */
262
+ doClassValidation_(opt_newValue) {
263
+ if (opt_newValue === null) {
264
+ return null;
265
+ }
266
+ // Clean up text.
267
+ let newValue = String(opt_newValue);
268
+ // TODO: Handle cases like 'ten', '1.203,14', etc.
269
+ // 'O' is sometimes mistaken for '0' by inexperienced users.
270
+ newValue = newValue.replace(/O/ig, '0');
271
+ // Strip out thousands separators.
272
+ newValue = newValue.replace(/,/g, '');
273
+ // Ignore case of 'Infinity'.
274
+ newValue = newValue.replace(/infinity/i, 'Infinity');
222
275
 
223
- /**
224
- * Sets the precision of this field's value. Called internally to avoid
225
- * value updates.
226
- * @param {?(number|string|undefined)} precision The number to which the
227
- * field's value is rounded.
228
- * @private
229
- */
230
- FieldNumber.prototype.setPrecisionInternal_ = function(precision) {
231
- this.precision_ = Number(precision) || 0;
232
- let precisionString = String(this.precision_);
233
- if (precisionString.indexOf('e') !== -1) {
234
- // String() is fast. But it turns .0000001 into '1e-7'.
235
- // Use the much slower toLocaleString to access all the digits.
236
- precisionString =
237
- this.precision_.toLocaleString('en-US', {maximumFractionDigits: 20});
238
- }
239
- const decimalIndex = precisionString.indexOf('.');
240
- if (decimalIndex === -1) {
241
- // If the precision is 0 (float) allow any number of decimals,
242
- // otherwise allow none.
243
- this.decimalPlaces_ = precision ? 0 : null;
244
- } else {
245
- this.decimalPlaces_ = precisionString.length - decimalIndex - 1;
276
+ // Clean up number.
277
+ let n = Number(newValue || 0);
278
+ if (isNaN(n)) {
279
+ // Invalid number.
280
+ return null;
281
+ }
282
+ // Get the value in range.
283
+ n = Math.min(Math.max(n, this.min_), this.max_);
284
+ // Round to nearest multiple of precision.
285
+ if (this.precision_ && isFinite(n)) {
286
+ n = Math.round(n / this.precision_) * this.precision_;
287
+ }
288
+ // Clean up floating point errors.
289
+ if (this.decimalPlaces_ !== null) {
290
+ n = Number(n.toFixed(this.decimalPlaces_));
291
+ }
292
+ return n;
246
293
  }
247
- };
248
294
 
249
- /**
250
- * Returns the current precision of this field. The precision being the
251
- * number to which the field's value is rounded. A precision of 0 means that
252
- * the value is not rounded.
253
- * @return {number} The number to which this field's value is rounded.
254
- */
255
- FieldNumber.prototype.getPrecision = function() {
256
- return this.precision_;
257
- };
295
+ /**
296
+ * Create the number input editor widget.
297
+ * @return {!HTMLElement} The newly created number input editor.
298
+ * @protected
299
+ * @override
300
+ */
301
+ widgetCreate_() {
302
+ const htmlInput = super.widgetCreate_();
258
303
 
259
- /**
260
- * Ensure that the input value is a valid number (must fulfill the
261
- * constraints placed on the field).
262
- * @param {*=} opt_newValue The input value.
263
- * @return {?number} A valid number, or null if invalid.
264
- * @protected
265
- * @override
266
- */
267
- FieldNumber.prototype.doClassValidation_ = function(opt_newValue) {
268
- if (opt_newValue === null) {
269
- return null;
304
+ // Set the accessibility state
305
+ if (this.min_ > -Infinity) {
306
+ aria.setState(htmlInput, aria.State.VALUEMIN, this.min_);
307
+ }
308
+ if (this.max_ < Infinity) {
309
+ aria.setState(htmlInput, aria.State.VALUEMAX, this.max_);
310
+ }
311
+ return htmlInput;
270
312
  }
271
- // Clean up text.
272
- let newValue = String(opt_newValue);
273
- // TODO: Handle cases like 'ten', '1.203,14', etc.
274
- // 'O' is sometimes mistaken for '0' by inexperienced users.
275
- newValue = newValue.replace(/O/ig, '0');
276
- // Strip out thousands separators.
277
- newValue = newValue.replace(/,/g, '');
278
- // Ignore case of 'Infinity'.
279
- newValue = newValue.replace(/infinity/i, 'Infinity');
280
313
 
281
- // Clean up number.
282
- let n = Number(newValue || 0);
283
- if (isNaN(n)) {
284
- // Invalid number.
285
- return null;
286
- }
287
- // Get the value in range.
288
- n = Math.min(Math.max(n, this.min_), this.max_);
289
- // Round to nearest multiple of precision.
290
- if (this.precision_ && isFinite(n)) {
291
- n = Math.round(n / this.precision_) * this.precision_;
292
- }
293
- // Clean up floating point errors.
294
- if (this.decimalPlaces_ !== null) {
295
- n = Number(n.toFixed(this.decimalPlaces_));
314
+ /**
315
+ * Construct a FieldNumber from a JSON arg object.
316
+ * @param {!Object} options A JSON object with options (value, min, max, and
317
+ * precision).
318
+ * @return {!FieldNumber} The new field instance.
319
+ * @package
320
+ * @nocollapse
321
+ * @override
322
+ */
323
+ static fromJson(options) {
324
+ // `this` might be a subclass of FieldNumber if that class doesn't override
325
+ // the static fromJson method.
326
+ return new this(
327
+ options['value'], undefined, undefined, undefined, undefined, options);
296
328
  }
297
- return n;
298
- };
329
+ }
299
330
 
300
331
  /**
301
- * Create the number input editor widget.
302
- * @return {!HTMLElement} The newly created number input editor.
332
+ * The default value for this field.
333
+ * @type {*}
303
334
  * @protected
304
- * @override
305
335
  */
306
- FieldNumber.prototype.widgetCreate_ = function() {
307
- const htmlInput = FieldNumber.superClass_.widgetCreate_.call(this);
308
-
309
- // Set the accessibility state
310
- if (this.min_ > -Infinity) {
311
- aria.setState(htmlInput, aria.State.VALUEMIN, this.min_);
312
- }
313
- if (this.max_ < Infinity) {
314
- aria.setState(htmlInput, aria.State.VALUEMAX, this.max_);
315
- }
316
- return htmlInput;
317
- };
336
+ FieldNumber.prototype.DEFAULT_VALUE = 0;
318
337
 
319
338
  fieldRegistry.register('field_number', FieldNumber);
320
339