@oat-sa/tao-core-ui 1.67.0 → 2.0.0

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 (239) hide show
  1. package/README.md +17 -16
  2. package/dist/animable/absorbable/css/absorb.css +25 -29
  3. package/dist/animable/absorbable/css/absorb.css.map +1 -1
  4. package/dist/animable/pulsable/css/pulse.css +20 -23
  5. package/dist/animable/pulsable/css/pulse.css.map +1 -1
  6. package/dist/autocomplete/css/autocomplete.css +20 -21
  7. package/dist/autocomplete/css/autocomplete.css.map +1 -1
  8. package/dist/badge/css/badge.css +67 -79
  9. package/dist/badge/css/badge.css.map +1 -1
  10. package/dist/breadcrumbs/css/breadcrumbs.css +54 -61
  11. package/dist/breadcrumbs/css/breadcrumbs.css.map +1 -1
  12. package/dist/bulkActionPopup/css/bulkActionPopup.css +27 -42
  13. package/dist/bulkActionPopup/css/bulkActionPopup.css.map +1 -1
  14. package/dist/calculator/css/calculator.css +91 -112
  15. package/dist/calculator/css/calculator.css.map +1 -1
  16. package/dist/class/css/selector.css +83 -97
  17. package/dist/class/css/selector.css.map +1 -1
  18. package/dist/component/css/components.css +351 -406
  19. package/dist/component/css/components.css.map +1 -1
  20. package/dist/component/css/windowComponent.css +19 -28
  21. package/dist/component/css/windowComponent.css.map +1 -1
  22. package/dist/contextualPopup/css/contextualPopup.css +42 -55
  23. package/dist/contextualPopup/css/contextualPopup.css.map +1 -1
  24. package/dist/dashboard/css/dashboard.css +43 -57
  25. package/dist/dashboard/css/dashboard.css.map +1 -1
  26. package/dist/datalist/css/datalist.css +63 -88
  27. package/dist/datalist/css/datalist.css.map +1 -1
  28. package/dist/datatable/css/datatable.css +84 -113
  29. package/dist/datatable/css/datatable.css.map +1 -1
  30. package/dist/dateRange/css/dateRange.css +1 -2
  31. package/dist/dateRange/css/dateRange.css.map +1 -1
  32. package/dist/datetime/css/picker.css +71 -103
  33. package/dist/datetime/css/picker.css.map +1 -1
  34. package/dist/destination/css/selector.css +17 -24
  35. package/dist/destination/css/selector.css.map +1 -1
  36. package/dist/documentViewer/css/documentViewer.css +137 -162
  37. package/dist/documentViewer/css/documentViewer.css.map +1 -1
  38. package/dist/dropdown/css/dropdown.css +55 -72
  39. package/dist/dropdown/css/dropdown.css.map +1 -1
  40. package/dist/dynamicComponent/css/dynamicComponent.css +78 -91
  41. package/dist/dynamicComponent/css/dynamicComponent.css.map +1 -1
  42. package/dist/form/css/dropdownForm.css +36 -45
  43. package/dist/form/css/dropdownForm.css.map +1 -1
  44. package/dist/form/css/form.css +12 -16
  45. package/dist/form/css/form.css.map +1 -1
  46. package/dist/form/validator/css/validator.css +5 -7
  47. package/dist/form/validator/css/validator.css.map +1 -1
  48. package/dist/form/widget/css/widget.css +26 -34
  49. package/dist/form/widget/css/widget.css.map +1 -1
  50. package/dist/generis/form/css/form.css +14 -18
  51. package/dist/generis/form/css/form.css.map +1 -1
  52. package/dist/generis/validator/css/validator.css +5 -7
  53. package/dist/generis/validator/css/validator.css.map +1 -1
  54. package/dist/generis/widget/css/widget.css +29 -38
  55. package/dist/generis/widget/css/widget.css.map +1 -1
  56. package/dist/itemButtonList/css/item-button-list.css +135 -172
  57. package/dist/itemButtonList/css/item-button-list.css.map +1 -1
  58. package/dist/listbox/css/listbox.css +64 -84
  59. package/dist/listbox/css/listbox.css.map +1 -1
  60. package/dist/loadingButton/css/button.css +20 -29
  61. package/dist/loadingButton/css/button.css.map +1 -1
  62. package/dist/maths/calculator/basicCalculator.js +4 -4
  63. package/dist/maths/calculator/calculatorComponent.js +22 -25
  64. package/dist/maths/calculator/core/board.js +12327 -720
  65. package/dist/maths/calculator/core/labels.js +7918 -138
  66. package/dist/maths/calculator/core/plugin.js +4 -5
  67. package/dist/maths/calculator/css/calculator.css +224 -270
  68. package/dist/maths/calculator/css/calculator.css.map +1 -1
  69. package/dist/maths/calculator/defaultCalculator.js +10 -6
  70. package/dist/maths/calculator/plugins/keyboard/templateKeyboard/templateKeyboard.js +23 -25
  71. package/dist/maths/calculator/plugins/screen/simpleScreen/simpleScreen.js +7973 -194
  72. package/dist/maths/calculator/scientificCalculator.js +7 -12
  73. package/dist/mediaplayer/css/player.css +281 -370
  74. package/dist/mediaplayer/css/player.css.map +1 -1
  75. package/dist/pagination/css/pagination.css +38 -49
  76. package/dist/pagination/css/pagination.css.map +1 -1
  77. package/dist/propertySelector/css/propertySelector.css +34 -44
  78. package/dist/propertySelector/css/propertySelector.css.map +1 -1
  79. package/dist/resource/css/selector.css +400 -490
  80. package/dist/resource/css/selector.css.map +1 -1
  81. package/dist/resourcemgr/css/resourcemgr.css +192 -237
  82. package/dist/resourcemgr/css/resourcemgr.css.map +1 -1
  83. package/dist/searchModal/css/advancedSearch.css +92 -121
  84. package/dist/searchModal/css/advancedSearch.css.map +1 -1
  85. package/dist/searchModal/css/searchModal.css +261 -333
  86. package/dist/searchModal/css/searchModal.css.map +1 -1
  87. package/dist/switch/css/switch.css +36 -47
  88. package/dist/switch/css/switch.css.map +1 -1
  89. package/dist/tabs/css/tabs.css +32 -40
  90. package/dist/tabs/css/tabs.css.map +1 -1
  91. package/dist/taskQueue/css/taskQueue.css +17 -27
  92. package/dist/taskQueue/css/taskQueue.css.map +1 -1
  93. package/dist/taskQueueButton/css/taskable.css +1 -2
  94. package/dist/taskQueueButton/css/taskable.css.map +1 -1
  95. package/dist/taskQueueButton/css/treeButton.css +20 -26
  96. package/dist/taskQueueButton/css/treeButton.css.map +1 -1
  97. package/dist/tristateCheckboxGroup/css/tristateCheckboxGroup.css +3 -5
  98. package/dist/tristateCheckboxGroup/css/tristateCheckboxGroup.css.map +1 -1
  99. package/dist/waitingDialog/css/waitingDialog.css +18 -23
  100. package/dist/waitingDialog/css/waitingDialog.css.map +1 -1
  101. package/package.json +20 -24
  102. package/scss/inc/_base.scss +9 -8
  103. package/scss/inc/_flex-grid.scss +1 -1
  104. package/scss/inc/_forms.scss +5 -5
  105. package/scss/inc/_functions.scss +8 -8
  106. package/scss/inc/fonts/_tao-icon-classes.scss +230 -230
  107. package/src/animable/absorbable/css/absorb.css +25 -29
  108. package/src/animable/absorbable/css/absorb.css.map +1 -1
  109. package/src/animable/pulsable/css/pulse.css +20 -23
  110. package/src/animable/pulsable/css/pulse.css.map +1 -1
  111. package/src/autocomplete/css/autocomplete.css +20 -21
  112. package/src/autocomplete/css/autocomplete.css.map +1 -1
  113. package/src/badge/css/badge.css +67 -79
  114. package/src/badge/css/badge.css.map +1 -1
  115. package/src/breadcrumbs/css/breadcrumbs.css +54 -61
  116. package/src/breadcrumbs/css/breadcrumbs.css.map +1 -1
  117. package/src/bulkActionPopup/css/bulkActionPopup.css +27 -42
  118. package/src/bulkActionPopup/css/bulkActionPopup.css.map +1 -1
  119. package/src/calculator/css/calculator.css +91 -112
  120. package/src/calculator/css/calculator.css.map +1 -1
  121. package/src/calculator/scss/calculator.scss +1 -1
  122. package/src/class/css/selector.css +83 -97
  123. package/src/class/css/selector.css.map +1 -1
  124. package/src/component/css/components.css +351 -406
  125. package/src/component/css/components.css.map +1 -1
  126. package/src/component/css/windowComponent.css +19 -28
  127. package/src/component/css/windowComponent.css.map +1 -1
  128. package/src/contextualPopup/css/contextualPopup.css +42 -55
  129. package/src/contextualPopup/css/contextualPopup.css.map +1 -1
  130. package/src/css/basic.css +4000 -4374
  131. package/src/css/basic.css.map +1 -1
  132. package/src/dashboard/css/dashboard.css +43 -57
  133. package/src/dashboard/css/dashboard.css.map +1 -1
  134. package/src/datalist/css/datalist.css +63 -88
  135. package/src/datalist/css/datalist.css.map +1 -1
  136. package/src/datatable/css/datatable.css +84 -113
  137. package/src/datatable/css/datatable.css.map +1 -1
  138. package/src/dateRange/css/dateRange.css +1 -2
  139. package/src/dateRange/css/dateRange.css.map +1 -1
  140. package/src/datetime/css/picker.css +71 -103
  141. package/src/datetime/css/picker.css.map +1 -1
  142. package/src/destination/css/selector.css +17 -24
  143. package/src/destination/css/selector.css.map +1 -1
  144. package/src/documentViewer/css/documentViewer.css +137 -162
  145. package/src/documentViewer/css/documentViewer.css.map +1 -1
  146. package/src/dropdown/css/dropdown.css +55 -72
  147. package/src/dropdown/css/dropdown.css.map +1 -1
  148. package/src/dynamicComponent/css/dynamicComponent.css +78 -91
  149. package/src/dynamicComponent/css/dynamicComponent.css.map +1 -1
  150. package/src/form/css/dropdownForm.css +36 -45
  151. package/src/form/css/dropdownForm.css.map +1 -1
  152. package/src/form/css/form.css +12 -16
  153. package/src/form/css/form.css.map +1 -1
  154. package/src/form/validator/css/validator.css +5 -7
  155. package/src/form/validator/css/validator.css.map +1 -1
  156. package/src/form/widget/css/widget.css +26 -34
  157. package/src/form/widget/css/widget.css.map +1 -1
  158. package/src/generis/form/css/form.css +14 -18
  159. package/src/generis/form/css/form.css.map +1 -1
  160. package/src/generis/validator/css/validator.css +5 -7
  161. package/src/generis/validator/css/validator.css.map +1 -1
  162. package/src/generis/widget/css/widget.css +29 -38
  163. package/src/generis/widget/css/widget.css.map +1 -1
  164. package/src/itemButtonList/css/item-button-list.css +135 -172
  165. package/src/itemButtonList/css/item-button-list.css.map +1 -1
  166. package/src/listbox/css/listbox.css +64 -84
  167. package/src/listbox/css/listbox.css.map +1 -1
  168. package/src/listbox/scss/listbox.scss +8 -8
  169. package/src/loadingButton/css/button.css +20 -29
  170. package/src/loadingButton/css/button.css.map +1 -1
  171. package/src/maths/calculator/basicCalculator.js +1 -4
  172. package/src/maths/calculator/calculatorComponent.js +49 -60
  173. package/src/maths/calculator/core/board.js +372 -493
  174. package/src/maths/calculator/core/labels.js +46 -48
  175. package/src/maths/calculator/core/plugin.js +3 -5
  176. package/src/maths/calculator/core/tpl/terms.tpl +7 -1
  177. package/src/maths/calculator/css/calculator.css +224 -270
  178. package/src/maths/calculator/css/calculator.css.map +1 -1
  179. package/src/maths/calculator/defaultCalculator.js +7 -9
  180. package/src/maths/calculator/plugins/keyboard/templateKeyboard/defaultTemplate.tpl +3 -3
  181. package/src/maths/calculator/plugins/keyboard/templateKeyboard/templateKeyboard.js +17 -20
  182. package/src/maths/calculator/plugins/screen/simpleScreen/simpleScreen.js +102 -108
  183. package/src/maths/calculator/scientificCalculator.js +2 -10
  184. package/src/maths/calculator/scss/calculator.scss +20 -7
  185. package/src/maths/calculator/tpl/basicKeyboard.tpl +3 -3
  186. package/src/maths/calculator/tpl/scientificKeyboard.tpl +4 -4
  187. package/src/mediaplayer/css/player.css +281 -370
  188. package/src/mediaplayer/css/player.css.map +1 -1
  189. package/src/pagination/css/pagination.css +38 -49
  190. package/src/pagination/css/pagination.css.map +1 -1
  191. package/src/propertySelector/css/propertySelector.css +34 -44
  192. package/src/propertySelector/css/propertySelector.css.map +1 -1
  193. package/src/resource/css/selector.css +400 -490
  194. package/src/resource/css/selector.css.map +1 -1
  195. package/src/resourcemgr/css/resourcemgr.css +192 -237
  196. package/src/resourcemgr/css/resourcemgr.css.map +1 -1
  197. package/src/searchModal/css/advancedSearch.css +92 -121
  198. package/src/searchModal/css/advancedSearch.css.map +1 -1
  199. package/src/searchModal/css/searchModal.css +261 -333
  200. package/src/searchModal/css/searchModal.css.map +1 -1
  201. package/src/searchModal/scss/searchModal.scss +1 -1
  202. package/src/switch/css/switch.css +36 -47
  203. package/src/switch/css/switch.css.map +1 -1
  204. package/src/tabs/css/tabs.css +32 -40
  205. package/src/tabs/css/tabs.css.map +1 -1
  206. package/src/taskQueue/css/taskQueue.css +17 -27
  207. package/src/taskQueue/css/taskQueue.css.map +1 -1
  208. package/src/taskQueueButton/css/taskable.css +1 -2
  209. package/src/taskQueueButton/css/taskable.css.map +1 -1
  210. package/src/taskQueueButton/css/treeButton.css +20 -26
  211. package/src/taskQueueButton/css/treeButton.css.map +1 -1
  212. package/src/tristateCheckboxGroup/css/tristateCheckboxGroup.css +3 -5
  213. package/src/tristateCheckboxGroup/css/tristateCheckboxGroup.css.map +1 -1
  214. package/src/waitingDialog/css/waitingDialog.css +18 -23
  215. package/src/waitingDialog/css/waitingDialog.css.map +1 -1
  216. package/dist/maths/calculator/core/areaBroker.js +0 -43
  217. package/dist/maths/calculator/core/expression.js +0 -463
  218. package/dist/maths/calculator/core/terms.js +0 -456
  219. package/dist/maths/calculator/core/tokenizer.js +0 -229
  220. package/dist/maths/calculator/core/tokens.js +0 -167
  221. package/dist/maths/calculator/plugins/core/degrad.js +0 -71
  222. package/dist/maths/calculator/plugins/core/history.js +0 -149
  223. package/dist/maths/calculator/plugins/core/remind.js +0 -76
  224. package/dist/maths/calculator/plugins/core/stepNavigation.js +0 -148
  225. package/dist/maths/calculator/plugins/modifiers/pow10.js +0 -136
  226. package/dist/maths/calculator/plugins/modifiers/sign.js +0 -314
  227. package/dist/maths/calculator/pluginsLoader.js +0 -47
  228. package/src/maths/calculator/core/areaBroker.js +0 -38
  229. package/src/maths/calculator/core/expression.js +0 -430
  230. package/src/maths/calculator/core/terms.js +0 -459
  231. package/src/maths/calculator/core/tokenizer.js +0 -245
  232. package/src/maths/calculator/core/tokens.js +0 -178
  233. package/src/maths/calculator/plugins/core/degrad.js +0 -90
  234. package/src/maths/calculator/plugins/core/history.js +0 -166
  235. package/src/maths/calculator/plugins/core/remind.js +0 -96
  236. package/src/maths/calculator/plugins/core/stepNavigation.js +0 -175
  237. package/src/maths/calculator/plugins/modifiers/pow10.js +0 -143
  238. package/src/maths/calculator/plugins/modifiers/sign.js +0 -339
  239. package/src/maths/calculator/pluginsLoader.js +0 -46
@@ -13,145 +13,127 @@
13
13
  * along with this program; if not, write to the Free Software
14
14
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15
15
  *
16
- * Copyright (c) 2018-2019 Open Assessment Technologies SA ;
16
+ * Copyright (c) 2018-2023 Open Assessment Technologies SA ;
17
17
  */
18
18
  /**
19
19
  * Defines the base component that will host the calculator UI and link it to the engine.
20
- * @author Jean-Sébastien Conan <jean-sebastien@taotesting.com>
21
20
  */
22
21
 
23
- import _ from 'lodash';
24
- import __ from 'i18n';
25
-
26
- import collections from 'core/collections';
22
+ import Handlebars from 'handlebars';
23
+ import { engineFactory, historyPlugin, defaultDecimalDigits, expressionHelper } from '@oat-sa/tao-calculator/dist';
24
+ import areaBrokerFactory from 'ui/areaBroker';
27
25
  import componentFactory from 'ui/component';
28
- import areaBrokerFactory from 'ui/maths/calculator/core/areaBroker';
29
- import registeredTerms from 'ui/maths/calculator/core/terms';
30
- import tokensHelper from 'ui/maths/calculator/core/tokens';
31
- import expressionHelper from 'ui/maths/calculator/core/expression';
32
- import tokenizerFactory from 'ui/maths/calculator/core/tokenizer';
33
- import mathsEvaluatorFactory from 'util/mathsEvaluator';
34
26
  import boardTpl from 'ui/maths/calculator/core/tpl/board';
27
+ import termsTpl from 'ui/maths/calculator/core/tpl/terms';
28
+
29
+ Handlebars.registerHelper('isArray', Array.isArray);
30
+ Handlebars.registerPartial('ui-maths-terms', termsTpl);
35
31
 
36
32
  /**
37
33
  * Default config values
38
34
  * @type {Object}
39
35
  */
40
- var defaultConfig = {
36
+ const defaultConfig = {
41
37
  expression: '',
42
38
  position: 0
43
39
  };
44
40
 
45
41
  /**
46
- * Name of the variable that contains the last result
47
- * @type {String}
48
- */
49
- var lastResultVariableName = registeredTerms.ANS.value;
50
-
51
- /**
52
- * Regex that matches the prefixed function operators
53
- * @type {RegExp}
42
+ * The list of areas that should be provided by the calculator.
43
+ * @type {string[]}
54
44
  */
55
- var rePrefixedTerm = /^@[a-zA-Z_]\w*$/;
45
+ const calculatorAreas = [
46
+ 'screen', // where the expressions and their result are rendered
47
+ 'input', // where the expressions are input
48
+ 'keyboard' // the keyboard area that should provide a way to interact with the calculator
49
+ ];
56
50
 
57
51
  /**
58
- * The internal namespace for built-in events listeners
59
- * @type {String}
52
+ * Creates a calculator instance.
53
+ * @param {object} config
54
+ * @param {string} [config.expression=''] - The current expression.
55
+ * @param {number} [config.position=0] - The current position in the expression (i.e. the position of the caret).
56
+ * @param {boolean} [config.instant=false] - Whether the calculator should be in instant mode or not.
57
+ * @param {boolean} [config.corrector=true] - Whether the calculator should be in corrector mode or not.
58
+ * @param {object} [config.variables] - An optional list of variables.
59
+ * @param {object} [config.commands] - An optional list of commands.
60
+ * @param {object} [config.maths] - An optional config for the maths evaluator (@see mathsEvaluator).
61
+ * @returns {calculator}
60
62
  */
61
- var ns = 'calculator';
63
+ function calculatorFactory({
64
+ expression = '',
65
+ position = 0,
66
+ instant = false,
67
+ corrector = true,
68
+ variables = {},
69
+ commands = {},
70
+ maths = {}
71
+ } = {}) {
72
+ const plugins = { history: historyPlugin };
73
+ return engineFactory({ expression, position, instant, corrector, variables, commands, maths, plugins });
74
+ }
62
75
 
63
76
  /**
64
77
  * Build the basic UI for a calculator
65
- * @param {jQuery|HTMLElement|String} $container
66
- * @param {Function[]} pluginFactories
67
- * @param {Object} [config]
68
- * @param {String} [config.expression=''] - The initial expression
69
- * @param {Number} [config.position=0] - The initial position in the expression
70
- * @param {Object} [config.maths] - Optional config for the maths evaluator (@see util/mathsEvaluator)
71
- * @param {Object} [config.plugins] - Optional config for each plugins
78
+ * @param {jQuery|HTMLElement|string} $container
79
+ * @param {function[]} pluginFactories
80
+ * @param {object} [config]
81
+ * @param {string} [config.expression=''] - The initial expression
82
+ * @param {number} [config.position=0] - The initial position in the expression
83
+ * @param {boolean} [config.instant=false] - Whether the calculator should be in instant mode or not.
84
+ * @param {boolean} [config.corrector=true] - Whether the calculator should be in corrector mode or not.
85
+ * @param {object} [config.variables] - An optional list of variables.
86
+ * @param {object} [config.commands] - An optional list of commands.
87
+ * @param {object} [config.maths] - Optional config for the maths evaluator (@see util/mathsEvaluator)
88
+ * @param {object} [config.plugins] - Optional config for each plugins
72
89
  * @returns {calculator}
73
90
  */
74
91
  function calculatorBoardFactory($container, pluginFactories, config) {
75
92
  /**
76
- * Maths expression parser.
77
- * @type {Function}
78
- */
79
- var mathsEvaluator;
80
-
81
- /**
82
- * Keep the area broker instance
83
- * @see ui/maths/calculator/areaBroker
84
- */
85
- var areaBroker;
86
-
87
- /**
88
- * @type {Object} the registered plugins
89
- */
90
- var plugins = {};
91
-
92
- /**
93
- * The current expression
94
- * @type {String}
95
- */
96
- var expression = '';
97
-
98
- /**
99
- * A list of variables that can be used in the expression
100
- * @type {Map}
101
- */
102
- var variables = new collections.Map();
103
-
104
- /**
105
- * A list of registered commands that can be used inside the calculator
106
- * @type {Map}
93
+ * @type {calculator} The calculator engine.
107
94
  */
108
- var commands = new collections.Map();
95
+ const calculator = calculatorFactory(config);
109
96
 
110
97
  /**
111
- * The current position in the current expression (i.e. the position of the caret)
112
- * @type {Number}
98
+ * @type {Map} The registered plugins
113
99
  */
114
- var position = 0;
100
+ const plugins = new Map();
115
101
 
116
102
  /**
117
- * The tokenizer utilized to split down the expression
118
- * @type {calculatorTokenizer}
119
- */
120
- var tokenizer = tokenizerFactory();
121
-
122
- /**
123
- * The list of tokens extracted from the expression
124
- * @type {Array|null}
103
+ * Keep the area broker instance
104
+ * @see ui/maths/calculator/areaBroker
125
105
  */
126
- var tokens = null;
106
+ let areaBroker;
127
107
 
128
108
  /**
129
- *
109
+ * The component API.
130
110
  * @type {Object}
131
111
  */
132
- var calculatorApi = {
112
+ const calculatorApi = {
113
+ /**
114
+ * Gets the calculator's engine
115
+ * @returns {calculator}
116
+ */
117
+ getCalculator() {
118
+ return calculator;
119
+ },
120
+
133
121
  /**
134
122
  * Returns the current expression
135
123
  * @returns {String}
136
124
  */
137
- getExpression: function getExpression() {
138
- return expression;
125
+ getExpression() {
126
+ return calculator.getExpression();
139
127
  },
140
128
 
141
129
  /**
142
130
  * Changes the current expression
143
- * @param {String} expr
131
+ * @param {String} expression
144
132
  * @returns {calculator}
145
133
  * @fires expressionchange after the expression has been changed
146
134
  */
147
- setExpression: function setExpression(expr) {
148
- expression = String(expr || '');
149
- tokens = null;
150
- /**
151
- * @event expressionchange
152
- * @param {String} expression
153
- */
154
- this.trigger('expressionchange', expression);
135
+ setExpression(expression) {
136
+ calculator.setExpression(expression);
155
137
  return this;
156
138
  },
157
139
 
@@ -159,23 +141,18 @@ function calculatorBoardFactory($container, pluginFactories, config) {
159
141
  * Gets the current position inside the expression
160
142
  * @returns {Number}
161
143
  */
162
- getPosition: function getPosition() {
163
- return position;
144
+ getPosition() {
145
+ return calculator.getPosition();
164
146
  },
165
147
 
166
148
  /**
167
149
  * Sets the current position inside the expression
168
- * @param {Number|String} pos
150
+ * @param {Number|String} position
169
151
  * @returns {calculator}
170
152
  * @fires positionchange after the position has been changed
171
153
  */
172
- setPosition: function setPosition(pos) {
173
- position = Math.max(0, Math.min(parseInt(pos, 10) || 0, expression.length));
174
- /**
175
- * @event positionchange
176
- * @param {Number} position
177
- */
178
- this.trigger('positionchange', position);
154
+ setPosition(position) {
155
+ calculator.setPosition(position);
179
156
  return this;
180
157
  },
181
158
 
@@ -183,43 +160,32 @@ function calculatorBoardFactory($container, pluginFactories, config) {
183
160
  * Gets the tokens from the current expression
184
161
  * @returns {token[]}
185
162
  */
186
- getTokens: function getTokens() {
187
- if (tokens === null) {
188
- tokens = tokenizer.tokenize(expression);
189
- }
190
- return tokens;
163
+ getTokens() {
164
+ return calculator.getTokens();
191
165
  },
192
166
 
193
167
  /**
194
168
  * Gets the token at the current position from the current expression
195
169
  * @returns {token|null} Returns the token at the current position, or null if none
196
170
  */
197
- getToken: function getToken() {
198
- var tokensList = this.getTokens();
199
- var index = this.getTokenIndex();
200
- return tokensList[index] || null;
171
+ getToken() {
172
+ return calculator.getToken();
201
173
  },
202
174
 
203
175
  /**
204
176
  * Gets token index from the current position in the expression.
205
177
  * @returns {Number} Returns the index of the token at the current position.
206
178
  */
207
- getTokenIndex: function getTokenIndex() {
208
- var index = 0;
209
- _.forEach(this.getTokens(), function(token, idx) {
210
- if (position >= token.offset) {
211
- index = idx;
212
- }
213
- });
214
- return index;
179
+ getTokenIndex() {
180
+ return calculator.getTokenIndex();
215
181
  },
216
182
 
217
183
  /**
218
184
  * Gets access to the tokenizer
219
185
  * @returns {calculatorTokenizer}
220
186
  */
221
- getTokenizer: function getTokenizer() {
222
- return tokenizer;
187
+ getTokenizer() {
188
+ return calculator.getTokenizer();
223
189
  },
224
190
 
225
191
  /**
@@ -227,8 +193,8 @@ function calculatorBoardFactory($container, pluginFactories, config) {
227
193
  * @param {String} name - The variable name
228
194
  * @returns {mathsExpression} The value. Can be another expression.
229
195
  */
230
- getVariable: function getVariable(name) {
231
- return variables.get(name);
196
+ getVariable(name) {
197
+ return calculator.getVariable(name);
232
198
  },
233
199
 
234
200
  /**
@@ -236,8 +202,8 @@ function calculatorBoardFactory($container, pluginFactories, config) {
236
202
  * @param {String} name
237
203
  * @returns {Boolean}
238
204
  */
239
- hasVariable: function hasVariable(name) {
240
- return variables.has(name);
205
+ hasVariable(name) {
206
+ return calculator.hasVariable(name);
241
207
  },
242
208
 
243
209
  /**
@@ -247,22 +213,8 @@ function calculatorBoardFactory($container, pluginFactories, config) {
247
213
  * @returns {calculator}
248
214
  * @fires variableadd after the variable has been set
249
215
  */
250
- setVariable: function setVariable(name, value) {
251
- var errValue;
252
- try {
253
- value = mathsEvaluator(value);
254
- } catch (err) {
255
- errValue = (value && value.expression) || value;
256
- value = mathsEvaluator('0');
257
- value.expression = errValue;
258
- }
259
- variables.set(name, value);
260
- /**
261
- * @event variableadd
262
- * @param {String} name
263
- * @param {String} value
264
- */
265
- this.trigger('variableadd', name, value);
216
+ setVariable(name, value) {
217
+ calculator.setVariable(name, value);
266
218
  return this;
267
219
  },
268
220
 
@@ -272,13 +224,8 @@ function calculatorBoardFactory($container, pluginFactories, config) {
272
224
  * @returns {calculator}
273
225
  * @fires variabledelete after the variable has been deleted
274
226
  */
275
- deleteVariable: function deleteVariable(name) {
276
- variables.delete(name);
277
- /**
278
- * @event variabledelete
279
- * @param {String} name
280
- */
281
- this.trigger('variabledelete', name);
227
+ deleteVariable(name) {
228
+ calculator.deleteVariable(name);
282
229
  return this;
283
230
  },
284
231
 
@@ -286,12 +233,8 @@ function calculatorBoardFactory($container, pluginFactories, config) {
286
233
  * Gets the list of variables defined for the expression.
287
234
  * @returns {Object} The list of defined variables.
288
235
  */
289
- getVariables: function getVariables() {
290
- var defs = {};
291
- variables.forEach(function(value, name) {
292
- defs[name] = value;
293
- });
294
- return defs;
236
+ getVariables() {
237
+ return calculator.getAllVariables();
295
238
  },
296
239
 
297
240
  /**
@@ -300,11 +243,8 @@ function calculatorBoardFactory($container, pluginFactories, config) {
300
243
  * @returns {calculator}
301
244
  * @fires variableadd after each variable has been set
302
245
  */
303
- setVariables: function setVariables(defs) {
304
- var self = this;
305
- _.forEach(defs, function(value, name) {
306
- self.setVariable(name, value);
307
- });
246
+ setVariables(defs) {
247
+ calculator.setVariableList(defs);
308
248
  return this;
309
249
  },
310
250
 
@@ -313,14 +253,8 @@ function calculatorBoardFactory($container, pluginFactories, config) {
313
253
  * @returns {calculator}
314
254
  * @fires variabledelete after the variables has been deleted
315
255
  */
316
- deleteVariables: function deleteVariables() {
317
- variables.clear();
318
- /**
319
- * @event variabledelete
320
- * @param {null} name
321
- */
322
- this.trigger('variabledelete', null);
323
- this.setLastResult('0');
256
+ deleteVariables() {
257
+ calculator.clearVariables();
324
258
  return this;
325
259
  },
326
260
 
@@ -329,11 +263,8 @@ function calculatorBoardFactory($container, pluginFactories, config) {
329
263
  * @param {String|Number|mathsExpression} [result='0']
330
264
  * @returns {calculator}
331
265
  */
332
- setLastResult: function setLastResult(result) {
333
- if (!result || expressionHelper.containsError(result)) {
334
- result = '0';
335
- }
336
- this.setVariable(lastResultVariableName, result);
266
+ setLastResult(result) {
267
+ calculator.setLastResult(result);
337
268
  return this;
338
269
  },
339
270
 
@@ -341,29 +272,19 @@ function calculatorBoardFactory($container, pluginFactories, config) {
341
272
  * Gets the value of the last result
342
273
  * @returns {mathsExpression}
343
274
  */
344
- getLastResult: function getLastResult() {
345
- return this.getVariable(lastResultVariableName);
275
+ getLastResult() {
276
+ return calculator.getLastResult();
346
277
  },
347
278
 
348
279
  /**
349
280
  * Registers a command
350
- * @param {String} name
351
- * @param {String} [label]
352
- * @param {String} [description]
281
+ * @param {string} name
282
+ * @param {function} action
353
283
  * @returns {calculator}
354
284
  * @fires commandadd after the command has been set
355
285
  */
356
- setCommand: function setCommand(name, label, description) {
357
- commands.set(name, {
358
- name: name,
359
- label: label,
360
- description: description
361
- });
362
- /**
363
- * @event commandadd
364
- * @param {String} name
365
- */
366
- this.trigger('commandadd', name);
286
+ setCommand(name, action) {
287
+ calculator.setCommand(name, action);
367
288
  return this;
368
289
  },
369
290
 
@@ -371,20 +292,16 @@ function calculatorBoardFactory($container, pluginFactories, config) {
371
292
  * Gets the definition of a registered command
372
293
  * @returns {Object} The registered command
373
294
  */
374
- getCommand: function getCommand(name) {
375
- return commands.get(name);
295
+ getCommand(name) {
296
+ return calculator.getCommand(name);
376
297
  },
377
298
 
378
299
  /**
379
300
  * Gets the list of registered commands
380
301
  * @returns {Object} The list of registered commands
381
302
  */
382
- getCommands: function getCommands() {
383
- var defs = {};
384
- commands.forEach(function(value, name) {
385
- defs[name] = value;
386
- });
387
- return defs;
303
+ getCommands() {
304
+ return calculator.getAllCommands();
388
305
  },
389
306
 
390
307
  /**
@@ -392,8 +309,8 @@ function calculatorBoardFactory($container, pluginFactories, config) {
392
309
  * @param {String} name
393
310
  * @returns {Boolean}
394
311
  */
395
- hasCommand: function hasCommand(name) {
396
- return commands.has(name);
312
+ hasCommand(name) {
313
+ return calculator.hasCommand(name);
397
314
  },
398
315
 
399
316
  /**
@@ -402,119 +319,21 @@ function calculatorBoardFactory($container, pluginFactories, config) {
402
319
  * @returns {calculator}
403
320
  * @fires commanddelete after the command has been deleted
404
321
  */
405
- deleteCommand: function deleteCommand(name) {
406
- commands.delete(name);
407
- /**
408
- * @event commanddelete
409
- * @param {String} name
410
- */
411
- this.trigger('commanddelete', name);
322
+ deleteCommand(name) {
323
+ calculator.deleteCommand(name);
412
324
  return this;
413
325
  },
414
326
 
415
327
  /**
416
328
  * Inserts a term in the expression at the current position
417
329
  * @param {String} name - The name of the term to insert
418
- * @param {Object} term - The definition of the term to insert
419
330
  * @returns {calculator}
420
- * @fires termerror if the term to add is invalid
421
- * @fires termadd when the term has been added
422
- * @fires termadd-<name> when the term has been added
423
- */
424
- addTerm: function addTerm(name, term) {
425
- var tokensList = this.getTokens();
426
- var index = this.getTokenIndex();
427
- var currentToken = tokensList[index];
428
- var nextToken = tokensList[index + 1];
429
- var isIdentifier, needsSpace, value;
430
-
431
- // checks if the aforementioned token requires space around
432
- function tokenNeedsSpace(token) {
433
- return tokensHelper.isIdentifier(token) || (isIdentifier && !tokensHelper.isSeparator(token));
434
- }
435
-
436
- if (!_.isPlainObject(term) || 'undefined' === typeof term.value) {
437
- /**
438
- * @event termerror
439
- * @param {TypeError} err
440
- */
441
- return this.trigger('termerror', new TypeError('Invalid term: ' + name));
442
- }
443
-
444
- value = term.value;
445
-
446
- // will replace the current term if:
447
- // - it is a 0, and the term to add is not an operator nor a dot
448
- // - it is the last result, and the term to add is not an operator
449
- if (
450
- !tokensHelper.isOperator(term.type) &&
451
- !rePrefixedTerm.test(term.value) &&
452
- tokensList.length === 1 &&
453
- ((currentToken.type === 'NUM0' && name !== 'DOT') || currentToken.type === 'ANS')
454
- ) {
455
- this.replace(value);
456
- } else {
457
- // simply add the term, with potentially spaces around
458
- if (expression && !tokensHelper.isSeparator(term.type)) {
459
- isIdentifier = tokensHelper.isIdentifier(term.type);
460
- needsSpace = tokenNeedsSpace(currentToken);
461
-
462
- // prepend space when either the term to add or the previous term is an identifier
463
- if (position && needsSpace) {
464
- value = ' ' + value;
465
- }
466
-
467
- // append space when either the term to add or the next term is an identifier
468
- if ((!position && needsSpace) || (position < expression.length && tokenNeedsSpace(nextToken))) {
469
- value += ' ';
470
- }
471
- }
472
-
473
- this.insert(value);
474
- }
475
-
476
- /**
477
- * @event termadd
478
- * @param {String} name - The name of the added term
479
- * @param {Object} term - The descriptor of the added term
480
- */
481
- this.trigger('termadd', name, term);
482
-
483
- /**
484
- * @event termadd-<name>
485
- * @param {Object} term - The descriptor of the added term
486
- */
487
- this.trigger('termadd-' + name, term);
488
-
489
- return this;
490
- },
491
-
492
- /**
493
- * Inserts a term in the expression at the current position
494
- * @param {String} name - The name of the term to insert
495
- * @returns {calculator}
496
- * @fires termerror if the term to add is invalid
331
+ * @fires error if the term to add is invalid
497
332
  * @fires termadd when the term has been added
498
333
  */
499
- useTerm: function useTerm(name) {
500
- var term;
501
- if (rePrefixedTerm.test(name)) {
502
- name = name.substring(1);
503
- term = _.clone(registeredTerms[name]);
504
- term.value = '@' + term.value;
505
- } else {
506
- term = registeredTerms[name];
507
- }
508
-
509
- if ('undefined' === typeof term) {
510
- /**
511
- * @event termerror
512
- * @param {TypeError} err
513
- */
514
- return this.trigger('termerror', new TypeError('Invalid term: ' + name));
515
- }
516
-
517
- return this.addTerm(name, term);
334
+ useTerm(name) {
335
+ calculator.insertTerm(name);
336
+ return this;
518
337
  },
519
338
 
520
339
  /**
@@ -522,16 +341,11 @@ function calculatorBoardFactory($container, pluginFactories, config) {
522
341
  * @param {String|String[]} names - The names of the terms to insert.
523
342
  * Could be either an array of names or a list separated by spaces.
524
343
  * @returns {calculator}
525
- * @fires termerror if a term to add is invalid
344
+ * @fires error if the term to add is invalid
526
345
  * @fires termadd when a term has been added
527
346
  */
528
- useTerms: function useTerms(names) {
529
- if ('string' === typeof names) {
530
- names = names.split(/\s+/);
531
- }
532
-
533
- _.forEach(names, this.useTerm.bind(this));
534
-
347
+ useTerms(names) {
348
+ calculator.insertTermList(names);
535
349
  return this;
536
350
  },
537
351
 
@@ -539,106 +353,48 @@ function calculatorBoardFactory($container, pluginFactories, config) {
539
353
  * Inserts a variable as a term in the expression at the current position
540
354
  * @param {String} name - The name of the variable to insert
541
355
  * @returns {calculator}
542
- * @fires termerror if the term to add is invalid
356
+ * @fires error if the term to add is invalid
543
357
  * @fires termadd when the term has been added
544
358
  */
545
- useVariable: function useVariable(name) {
546
- if (!variables.has(name)) {
547
- /**
548
- * @event termerror
549
- * @param {TypeError} err
550
- */
551
- return this.trigger('termerror', new TypeError('Invalid variable: ' + name));
552
- }
553
-
554
- return this.addTerm('VAR_' + name.toUpperCase(), {
555
- label: name,
556
- value: name,
557
- type: 'variable',
558
- description: __('Variable %s', name)
559
- });
359
+ useVariable(name) {
360
+ calculator.insertVariable(name);
361
+ return this;
560
362
  },
561
363
 
562
364
  /**
563
365
  * Calls a command
564
366
  * @param {String} name - The name of the called command
565
- * @param {*} ... - additional params for the command
367
+ * @param {...*} args - additional params for the command
566
368
  * @returns {calculator}
567
369
  * @fires command with the name and the parameters of the command
568
370
  * @fires command-<name> with the parameters of the command
569
- * @fires commanderror if the command is invalid
570
- */
571
- useCommand: function useCommand(name) {
572
- if (!commands.has(name)) {
573
- /**
574
- * @event commanderror
575
- * @param {TypeError} err
576
- */
577
- return this.trigger('commanderror', new TypeError('Invalid command: ' + name));
578
- }
579
-
580
- /**
581
- * @event command
582
- * @param {String} name - The name of the called command
583
- * @param {*} ... - additional params for the command
584
- */
585
- this.trigger.apply(this, ['command'].concat([].slice.call(arguments)));
586
-
587
- /**
588
- * @event command-<name>
589
- * @param {*} ... - additional params for the command
590
- */
591
- this.trigger.apply(this, ['command-' + name].concat([].slice.call(arguments, 1)));
592
-
371
+ * @fires error if the command is invalid
372
+ */
373
+ useCommand(name, ...args) {
374
+ calculator.invoke(name, ...args);
593
375
  return this;
594
376
  },
595
377
 
596
378
  /**
597
379
  * Replaces the expression and move the cursor at the end.
598
- * @param {String} newExpression - The new expression to set
599
- * @param {Number|String} [newPosition=newExpression.length] - The new position to set
380
+ * @param {String} expression - The new expression to set
381
+ * @param {Number|String} [position=newExpression.length] - The new position to set
600
382
  * @returns {calculator}
601
383
  * @fires replace after the expression has been replaced
602
384
  */
603
- replace: function replace(newExpression, newPosition) {
604
- var oldExpression = expression;
605
- var oldPosition = position;
606
-
607
- this.setExpression(newExpression).setPosition(
608
- 'undefined' !== typeof newPosition ? newPosition : expression.length
609
- );
610
-
611
- /**
612
- * @event replace
613
- * @param {String} expression - the replaced expression
614
- * @param {Number} position - the replaced position
615
- */
616
- this.trigger('replace', oldExpression, oldPosition);
617
-
385
+ replace(expression, position) {
386
+ calculator.replace(expression, position);
618
387
  return this;
619
388
  },
620
389
 
621
390
  /**
622
391
  * Inserts a sub-expression in the current expression and move the cursor.
623
- * @param {String} subExpression - The sub-expression to insert
392
+ * @param {String} expression - The sub-expression to insert
624
393
  * @returns {calculator}
625
394
  * @fires insert after the expression has been inserted
626
395
  */
627
- insert: function insert(subExpression) {
628
- var oldExpression = expression;
629
- var oldPosition = position;
630
-
631
- this.setExpression(
632
- expression.substr(0, position) + subExpression + expression.substr(position)
633
- ).setPosition(position + subExpression.length);
634
-
635
- /**
636
- * @event insert
637
- * @param {String} expression - the replaced expression
638
- * @param {Number} position - the replaced position
639
- */
640
- this.trigger('insert', oldExpression, oldPosition);
641
-
396
+ insert(expression) {
397
+ calculator.insert(expression);
642
398
  return this;
643
399
  },
644
400
 
@@ -647,14 +403,8 @@ function calculatorBoardFactory($container, pluginFactories, config) {
647
403
  * @returns {calculator}
648
404
  * @fires clear after the expression has been cleared
649
405
  */
650
- clear: function clear() {
651
- this.setExpression('').setPosition(0);
652
-
653
- /**
654
- * @event clear
655
- */
656
- this.trigger('clear');
657
-
406
+ clear() {
407
+ calculator.clear();
658
408
  return this;
659
409
  },
660
410
 
@@ -662,30 +412,26 @@ function calculatorBoardFactory($container, pluginFactories, config) {
662
412
  * Evaluates the current expression
663
413
  * @returns {mathsExpression|null}
664
414
  * @fires evaluate when the expression has been evaluated
415
+ * @fires result when the result is available
665
416
  * @fires syntaxerror when the expression contains an error
666
417
  */
667
- evaluate: function evaluate() {
668
- var result = null;
669
- try {
670
- if (expression.trim()) {
671
- result = mathsEvaluator(expression, _.mapValues(this.getVariables(), 'result'));
672
- } else {
673
- result = mathsEvaluator('0');
674
- }
418
+ evaluate() {
419
+ return calculator.evaluate();
420
+ },
675
421
 
676
- /**
677
- * @event evaluate
678
- * @param {mathsExpression} result
679
- */
680
- this.trigger('evaluate', result);
681
- } catch (e) {
682
- /**
683
- * @event syntaxerror
684
- * @param {Error} err
685
- */
686
- this.trigger('syntaxerror', e);
687
- }
688
- return result;
422
+ /**
423
+ * Renders the expression into a string
424
+ * @param {string|object|token[]} expression
425
+ * @param {number} decimals - The number of decimals to present after the dot in the last result variable.
426
+ * @returns {string}
427
+ */
428
+ renderExpression(expression = null, decimals = defaultDecimalDigits) {
429
+ const tokens = expression === null ? calculator.getTokens() : expression;
430
+ const variables = expressionHelper.roundAllVariables(calculator.getAllVariables(), decimals);
431
+ const renderedTerms = expressionHelper.nestExponents(
432
+ expressionHelper.render(tokens, variables, calculator.getTokenizer())
433
+ );
434
+ return termsTpl(renderedTerms);
689
435
  },
690
436
 
691
437
  /**
@@ -694,11 +440,11 @@ function calculatorBoardFactory($container, pluginFactories, config) {
694
440
  * @param {String} method - the method to run
695
441
  * @returns {Promise} once that resolve when all plugins are done
696
442
  */
697
- runPlugins: function runPlugins(method) {
698
- var execStack = [];
443
+ runPlugins(method) {
444
+ const execStack = [];
699
445
 
700
- _.forEach(plugins, function(plugin) {
701
- if (_.isFunction(plugin[method])) {
446
+ plugins.forEach(plugin => {
447
+ if ('function' === typeof plugin[method]) {
702
448
  execStack.push(plugin[method]());
703
449
  }
704
450
  });
@@ -708,10 +454,10 @@ function calculatorBoardFactory($container, pluginFactories, config) {
708
454
 
709
455
  /**
710
456
  * Gets the calculator plugins
711
- * @returns {Array} the plugins
457
+ * @returns {plugin[]} the plugins
712
458
  */
713
- getPlugins: function getPlugins() {
714
- return _.toArray(plugins);
459
+ getPlugins() {
460
+ return [...plugins.values()];
715
461
  },
716
462
 
717
463
  /**
@@ -719,15 +465,15 @@ function calculatorBoardFactory($container, pluginFactories, config) {
719
465
  * @param {String} name - the plugin name
720
466
  * @returns {plugin} the plugin
721
467
  */
722
- getPlugin: function getPlugin(name) {
723
- return plugins[name];
468
+ getPlugin(name) {
469
+ return plugins.get(name);
724
470
  },
725
471
 
726
472
  /**
727
473
  * Gets access to the areaBroker
728
474
  * @returns {areaBroker}
729
475
  */
730
- getAreaBroker: function getAreaBroker() {
476
+ getAreaBroker() {
731
477
  return areaBroker;
732
478
  },
733
479
 
@@ -735,107 +481,240 @@ function calculatorBoardFactory($container, pluginFactories, config) {
735
481
  * Setups the maths evaluator
736
482
  * @returns {calculator}
737
483
  */
738
- setupMathsEvaluator: function setupMathsEvaluator() {
739
- mathsEvaluator = mathsEvaluatorFactory(this.getConfig().maths);
484
+ setupMathsEvaluator() {
485
+ calculator.configureMathsEvaluator(this.getConfig().maths);
740
486
  return this;
741
487
  },
742
488
 
743
489
  /**
744
490
  * Gets access to the mathsEvaluator
745
- * @returns {Function}
491
+ * @returns {function}
492
+ */
493
+ getMathsEvaluator() {
494
+ return calculator.getMathsEvaluator();
495
+ },
496
+
497
+ /**
498
+ * Sync the component state with the calculator state.
499
+ * @returns {calculator}
746
500
  */
747
- getMathsEvaluator: function getMathsEvaluator() {
748
- return mathsEvaluator;
501
+ syncCalculatorState() {
502
+ const degree = calculator.isDegreeMode();
503
+ this.setState('degree', degree);
504
+ this.setState('radian', !degree);
505
+ return this;
749
506
  }
750
507
  };
751
508
 
752
509
  /**
753
- * @typedef {component} calculator
510
+ * The calculator component
511
+ * @type {component}
754
512
  */
755
- var calculator = componentFactory(calculatorApi, defaultConfig)
513
+ const calculatorComponent = componentFactory(calculatorApi, defaultConfig)
756
514
  .setTemplate(boardTpl)
757
- .before('init', function() {
758
- this.setupMathsEvaluator();
759
- this.setLastResult('0');
760
- if (this.config.expression) {
761
- this.setExpression(this.config.expression);
762
- }
763
- if (this.config.position) {
764
- this.setPosition(this.config.position);
765
- }
766
-
767
- // built-in commands
768
- this.setCommand('clear', __('Clear'), __('Clear expression'))
769
- .setCommand('clearAll', __('Clear All'), __('Clear all data'))
770
- .setCommand('execute', __('Execute'), __('Compute the expression'))
771
- .setCommand('var', __('Variable'), __('Use a variable'))
772
- .setCommand('term', __('Term'), __('Use a term'))
773
- .on('command-term', this.useTerms.bind(this))
774
- .on('command-var', this.useVariable.bind(this))
775
- .on('command-execute', this.evaluate.bind(this))
776
- .on('command-clearAll', this.deleteVariables.bind(this))
777
- .on('command-clear command-clearAll', this.clear.bind(this));
778
- })
779
- .after('evaluate', function(result) {
780
- this.setLastResult(result);
515
+ .before('init', function beforeInit() {
516
+ calculator
517
+ .configureMathsEvaluator(this.config.maths)
518
+ .on('configure', () => this.syncCalculatorState())
519
+ .on('expression', expression => this.trigger('expressionchange', expression))
520
+ .on('position', position => this.trigger('positionchange', position))
521
+ .on('variableadd', (name, value) => this.trigger('variableadd', name, value))
522
+ .on('variabledelete', name => this.trigger('variabledelete', name))
523
+ .on('variableclear', () => this.trigger('variableclear'))
524
+ .on('commandadd', name => this.trigger('commandadd', name))
525
+ .on('commanddelete', name => this.trigger('commanddelete', name))
526
+ .on('term', (name, term) => {
527
+ this.trigger('termadd', name, term);
528
+ this.trigger(`termadd-${name}`, term);
529
+ })
530
+ .on('command', (name, ...args) => {
531
+ this.trigger('command', name, ...args);
532
+ this.trigger(`command-${name}`, ...args);
533
+ })
534
+ .on('replace', (expression, position) => this.trigger('replace', expression, position))
535
+ .on('insert', (expression, position) => this.trigger('insert', expression, position))
536
+ .on('clear', () => this.trigger('clear'))
537
+ .on('reset', () => this.trigger('reset'))
538
+ .on('correct', () => this.trigger('correct'))
539
+ .on('evaluate', result => this.trigger('evaluate', result))
540
+ .on('result', result => this.trigger('result', result))
541
+ .on('syntaxerror', error => this.trigger('syntaxerror', error))
542
+ .on('error', error => this.trigger('error', error));
781
543
  })
782
- .after('init', function() {
544
+ .after('init', function afterInit() {
783
545
  this.render($container);
784
546
  })
785
- .before('render', function() {
786
- var self = this;
787
- var pluginsConfig = this.getConfig().plugins || {};
788
- var $element = this.getElement();
789
-
790
- areaBroker = areaBrokerFactory($element, {
547
+ .before('render', function onRender() {
548
+ const $element = this.getElement();
549
+ areaBroker = areaBrokerFactory(calculatorAreas, $element, {
791
550
  screen: $element.find('.screen'), // where the expressions and their result are rendered
792
551
  input: $element.find('.input'), // where the expressions are input
793
552
  keyboard: $element.find('.keyboard') // the keyboard area that should provide a way to interact with the calculator
794
553
  });
795
554
 
796
- _.forEach(pluginFactories, function(pluginFactory) {
797
- var plugin = pluginFactory(self, self.getAreaBroker());
798
- var pluginName = plugin.getName();
799
- if (pluginsConfig[pluginName]) {
800
- plugin.setConfig(pluginsConfig[pluginName]);
801
- }
802
- plugins[plugin.getName()] = plugin;
803
- });
555
+ const pluginsConfig = this.getConfig().plugins || {};
556
+ if (Array.isArray(pluginFactories)) {
557
+ pluginFactories.forEach(pluginFactory => {
558
+ const plugin = pluginFactory(this, this.getAreaBroker());
559
+ const pluginName = plugin.getName();
560
+ if (pluginsConfig[pluginName]) {
561
+ plugin.setConfig(pluginsConfig[pluginName]);
562
+ }
563
+ plugins.set(plugin.getName(), plugin);
564
+ });
565
+ }
566
+
567
+ this.syncCalculatorState();
804
568
 
805
569
  return this.runPlugins('install')
806
- .then(function() {
807
- return self.runPlugins('init');
808
- })
809
- .then(function() {
810
- return self.runPlugins('render');
811
- })
812
- .then(function() {
813
- /**
814
- * @event ready
815
- */
816
- self.trigger('ready');
817
- })
818
- .catch(function(err) {
819
- self.trigger('error', err);
820
- });
570
+ .then(() => this.runPlugins('init'))
571
+ .then(() => this.runPlugins('render'))
572
+ .then(() => this.trigger('ready'))
573
+ .catch(err => this.trigger('error', err));
821
574
  })
822
- .on('destroy', function() {
823
- var self = this;
824
- return this.runPlugins('destroy').then(function() {
825
- self.off('.' + ns);
826
- tokenizer = null;
575
+ .on('destroy', function onDestroy() {
576
+ return this.runPlugins('destroy').then(() => {
577
+ plugins.clear();
578
+ calculator.off();
579
+ this.removeAllListeners();
827
580
  areaBroker = null;
828
- mathsEvaluator = null;
829
- variables.clear();
830
- plugins = {};
831
581
  });
832
582
  });
833
583
 
834
- _.defer(function() {
835
- calculator.init(config);
836
- });
584
+ setTimeout(() => calculatorComponent.init(config), 0);
837
585
 
838
- return calculator;
586
+ return calculatorComponent;
839
587
  }
840
588
 
841
589
  export default calculatorBoardFactory;
590
+
591
+ /**
592
+ * Notifies the expression has changed.
593
+ * @event expressionchange
594
+ * @param {string} expression - The new expression.
595
+ */
596
+
597
+ /**
598
+ * Notifies the position inside the expression has changed.
599
+ * @event positionchange
600
+ * @param {number} position - The new position.
601
+ */
602
+
603
+ /**
604
+ * Notifies a variable has been added.
605
+ * @event variableadd
606
+ * @param {string} name - The name of the new variable.
607
+ * @param {string} value - The value of the new variable.
608
+ */
609
+
610
+ /**
611
+ * Notifies a variable has been removed.
612
+ * @event variabledelete
613
+ * @param {string} name - The name of the removed variable.
614
+ */
615
+
616
+ /**
617
+ * Notifies all variables have been removed.
618
+ * @event variableclear
619
+ */
620
+
621
+ /**
622
+ * Notifies a command has been registered.
623
+ * @event commandadd
624
+ * @param {string} name - The name of the new command.
625
+ */
626
+
627
+ /**
628
+ * Notifies a command has been removed.
629
+ * @event commanddelete
630
+ * @param {string} name - The name of the removed command.
631
+ */
632
+
633
+ /**
634
+ * Notifies a command has been invoked.
635
+ * @event command
636
+ * @param {string} name - The name of the called command
637
+ * @param {...*} args - Additional params for the command
638
+ */
639
+
640
+ /**
641
+ * Notifies a particular command has been invoked.
642
+ * @event command-<name>
643
+ * @param {...*} args - Additional params for the command
644
+ */
645
+
646
+ /**
647
+ * Notifies a term has been added to the expression.
648
+ * @event termadd
649
+ * @param {string} name - The name of the added term
650
+ * @param {term} term - The descriptor of the added term
651
+ */
652
+
653
+ /**
654
+ * Notifies the expression has been replaced.
655
+ * @event replace
656
+ * @param {string} expression - The replaced expression
657
+ * @param {number} position - The replaced position
658
+ */
659
+
660
+ /**
661
+ * Notifies a sub-expression has been inserted.
662
+ * @event insert
663
+ * @param {string} expression - The replaced expression
664
+ * @param {number} position - The replaced position
665
+ */
666
+
667
+ /**
668
+ * Notifies the expression has been cleared.
669
+ * @event clear
670
+ */
671
+
672
+ /**
673
+ * Notifies the calculator has been reset.
674
+ * @event reset
675
+ */
676
+
677
+ /**
678
+ * Notifies the expression has been corrected.
679
+ * @event correct
680
+ */
681
+
682
+ /**
683
+ * Notifies the expression has been evaluated.
684
+ * @event evaluate
685
+ * @param {mathsExpression} result - The result of the expression.
686
+ */
687
+
688
+ /**
689
+ * Notifies the result is available.
690
+ * @event result
691
+ * @param {mathsExpression} result - The result of the expression.
692
+ */
693
+
694
+ /**
695
+ * Notifies the expression has a syntax error.
696
+ * @event syntaxerror
697
+ * @param {Error} err - The error object.
698
+ */
699
+
700
+ /**
701
+ * Notifies an error occurred.
702
+ * @event error
703
+ * @param {Error} err - The error object.
704
+ */
705
+
706
+ /**
707
+ * @typedef {import('@oat-sa/tao-calculator/src/core/terms.js').term} term
708
+ */
709
+
710
+ /**
711
+ * @typedef {import('@oat-sa/tao-calculator/src/core/tokenizer.js').token} token
712
+ */
713
+
714
+ /**
715
+ * @typedef {import('@oat-sa/tao-calculator/src/core/mathsEvaluator.js').mathsExpression} mathsExpression
716
+ */
717
+
718
+ /**
719
+ * @typedef {import('@oat-sa/tao-calculator/src/core/expression.js').renderTerm} renderTerm
720
+ */