@oat-sa/tao-core-ui 1.58.1 → 1.58.2

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 (233) hide show
  1. package/dist/actionbar.js +386 -395
  2. package/dist/adder.js +21 -19
  3. package/dist/animable/absorbable/absorbable.js +204 -213
  4. package/dist/animable/absorbable/css/absorb.css +1 -0
  5. package/dist/animable/absorbable/css/absorb.css.map +1 -1
  6. package/dist/animable/pulsable/pulsable.js +168 -177
  7. package/dist/autocomplete/css/autocomplete.css +1 -0
  8. package/dist/autocomplete/css/autocomplete.css.map +1 -1
  9. package/dist/autocomplete.js +68 -66
  10. package/dist/badge/badge.js +188 -197
  11. package/dist/badge/css/badge.css +1 -0
  12. package/dist/badge/css/badge.css.map +1 -1
  13. package/dist/breadcrumbs.js +275 -284
  14. package/dist/btngrouper.js +5 -5
  15. package/dist/bulkActionPopup.js +490 -495
  16. package/dist/button.js +283 -291
  17. package/dist/cascadingComboBox.js +249 -258
  18. package/dist/ckeditor/ckConfigurator.js +26 -19
  19. package/dist/ckeditor/dtdHandler.js +11 -9
  20. package/dist/class/selector.js +441 -450
  21. package/dist/component/resizable.js +1 -1
  22. package/dist/component/windowed.js +285 -294
  23. package/dist/component.js +419 -428
  24. package/dist/contextualPopup.js +417 -426
  25. package/dist/dashboard.js +300 -309
  26. package/dist/datalist.js +753 -762
  27. package/dist/datatable/filterStrategy/multiple.js +1 -1
  28. package/dist/datatable/filterStrategy/single.js +1 -1
  29. package/dist/datatable.js +1527 -1550
  30. package/dist/dateRange/dateRange.js +393 -402
  31. package/dist/datetime/picker.js +665 -672
  32. package/dist/deleter.js +368 -377
  33. package/dist/destination/selector.js +286 -295
  34. package/dist/dialog/alert.js +3 -3
  35. package/dist/dialog/confirm.js +1 -1
  36. package/dist/dialog/confirmDelete.js +216 -225
  37. package/dist/dialog.js +650 -654
  38. package/dist/disabler.js +8 -8
  39. package/dist/documentViewer/providers/pdfViewer/fallback/viewer.js +166 -175
  40. package/dist/documentViewer/providers/pdfViewer/pdfjs/findBar.js +518 -527
  41. package/dist/documentViewer/providers/pdfViewer/pdfjs/pageView.js +380 -389
  42. package/dist/documentViewer/providers/pdfViewer/pdfjs/searchEngine.js +539 -548
  43. package/dist/documentViewer/providers/pdfViewer/pdfjs/viewer.js +369 -378
  44. package/dist/documentViewer/providers/pdfViewer.js +184 -193
  45. package/dist/documentViewer.js +292 -301
  46. package/dist/dropdown.js +383 -392
  47. package/dist/durationer.js +5 -5
  48. package/dist/dynamicComponent.js +597 -598
  49. package/dist/feedback.js +356 -362
  50. package/dist/figure/FigureStateActive.js +117 -108
  51. package/dist/filesender.js +2 -2
  52. package/dist/filter.js +230 -239
  53. package/dist/form/dropdownForm.js +355 -357
  54. package/dist/form/form.js +919 -690
  55. package/dist/form/simpleForm.js +1 -1
  56. package/dist/form/validator/renderer.js +233 -235
  57. package/dist/form/validator/validator.js +257 -189
  58. package/dist/form/widget/definitions.js +1 -1
  59. package/dist/form/widget/providers/checkBox.js +254 -259
  60. package/dist/form/widget/providers/comboBox.js +187 -192
  61. package/dist/form/widget/providers/default.js +8 -9
  62. package/dist/form/widget/providers/hidden.js +170 -179
  63. package/dist/form/widget/providers/hiddenBox.js +262 -267
  64. package/dist/form/widget/providers/radioBox.js +216 -225
  65. package/dist/form/widget/providers/textArea.js +187 -196
  66. package/dist/form/widget/providers/textBox.js +2 -3
  67. package/dist/form/widget/widget.js +473 -475
  68. package/dist/formValidator/formValidator.js +1 -1
  69. package/dist/formValidator/highlighters/message.js +1 -1
  70. package/dist/generis/form/form.js +314 -323
  71. package/dist/generis/validator/validator.js +209 -218
  72. package/dist/generis/widget/checkBox/checkBox.js +218 -227
  73. package/dist/generis/widget/comboBox/comboBox.js +179 -188
  74. package/dist/generis/widget/hiddenBox/hiddenBox.js +220 -229
  75. package/dist/generis/widget/textBox/textBox.js +169 -178
  76. package/dist/generis/widget/widget.js +246 -255
  77. package/dist/groupedComboBox.js +222 -231
  78. package/dist/groupvalidator.js +2 -2
  79. package/dist/highlighter.js +967 -958
  80. package/dist/image/ImgStateActive/helper.js +7 -5
  81. package/dist/image/ImgStateActive/initHelper.js +49 -43
  82. package/dist/image/ImgStateActive/initMediaEditor.js +24 -20
  83. package/dist/image/ImgStateActive/mediaSizer.js +14 -12
  84. package/dist/image/ImgStateActive.js +72 -70
  85. package/dist/incrementer.js +6 -6
  86. package/dist/inplacer.js +6 -6
  87. package/dist/itemButtonList/css/item-button-list.css +1 -0
  88. package/dist/itemButtonList/css/item-button-list.css.map +1 -1
  89. package/dist/itemButtonList.js +439 -435
  90. package/dist/keyNavigation/navigableDomElement.js +51 -38
  91. package/dist/keyNavigation/navigator.js +85 -70
  92. package/dist/listbox.js +460 -469
  93. package/dist/liststyler.js +8 -8
  94. package/dist/loadingButton/loadingButton.js +209 -218
  95. package/dist/lock.js +476 -485
  96. package/dist/login/login.js +475 -484
  97. package/dist/maths/calculator/basicCalculator.js +235 -244
  98. package/dist/maths/calculator/calculatorComponent.js +3 -3
  99. package/dist/maths/calculator/core/board.js +772 -781
  100. package/dist/maths/calculator/core/expression.js +476 -485
  101. package/dist/maths/calculator/core/labels.js +228 -237
  102. package/dist/maths/calculator/core/tokenizer.js +1 -1
  103. package/dist/maths/calculator/core/tokens.js +163 -170
  104. package/dist/maths/calculator/plugins/keyboard/templateKeyboard/templateKeyboard.js +244 -253
  105. package/dist/maths/calculator/plugins/screen/simpleScreen/simpleScreen.js +279 -288
  106. package/dist/maths/calculator/scientificCalculator.js +327 -336
  107. package/dist/mediaEditor/mediaEditorComponent.js +238 -245
  108. package/dist/mediaEditor/plugins/mediaAlignment/helper.js +7 -7
  109. package/dist/mediaEditor/plugins/mediaAlignment/mediaAlignmentComponent.js +229 -235
  110. package/dist/mediaEditor/plugins/mediaDimension/mediaDimensionComponent.js +580 -589
  111. package/dist/mediaplayer/players/html5.js +666 -675
  112. package/dist/mediaplayer/players/youtube.js +419 -424
  113. package/dist/mediaplayer/support.js +11 -10
  114. package/dist/mediaplayer/utils/reminder.js +14 -13
  115. package/dist/mediaplayer/utils/timeObserver.js +10 -11
  116. package/dist/mediaplayer/youtubeManager.js +164 -145
  117. package/dist/mediaplayer.js +1565 -1520
  118. package/dist/mediasizer.js +669 -678
  119. package/dist/modal.js +10 -17
  120. package/dist/pageSizeSelector.js +219 -228
  121. package/dist/pagination/providers/pages.js +280 -289
  122. package/dist/pagination/providers/simple.js +192 -201
  123. package/dist/previewer.js +30 -30
  124. package/dist/progressbar.js +4 -4
  125. package/dist/report.js +347 -356
  126. package/dist/resource/filters.js +271 -280
  127. package/dist/resource/list.js +1264 -1273
  128. package/dist/resource/selector.js +865 -874
  129. package/dist/resource/tree.js +1483 -1492
  130. package/dist/resourcemgr/fileBrowser.js +564 -569
  131. package/dist/resourcemgr/filePreview.js +16 -16
  132. package/dist/resourcemgr/fileSelector.js +515 -524
  133. package/dist/resourcemgr/util/updatePermissions.js +2 -2
  134. package/dist/resourcemgr.js +306 -315
  135. package/dist/searchModal/advancedSearch.js +796 -767
  136. package/dist/searchModal.js +114 -91
  137. package/dist/switch/switch.js +298 -307
  138. package/dist/tabs.js +598 -575
  139. package/dist/taskQueue/status.js +312 -321
  140. package/dist/taskQueue/table.js +375 -384
  141. package/dist/taskQueue/taskQueueModel.js +488 -472
  142. package/dist/taskQueueButton/taskable.js +264 -273
  143. package/dist/taskQueueButton/treeButton.js +189 -198
  144. package/dist/themeLoader.js +24 -23
  145. package/dist/themes.js +1 -1
  146. package/dist/toggler.js +3 -3
  147. package/dist/tooltip.js +295 -304
  148. package/dist/transformer.js +2 -2
  149. package/dist/tristateCheckboxGroup.js +311 -320
  150. package/dist/uploader.js +687 -696
  151. package/dist/validator/Report.js +1 -1
  152. package/dist/validator/Validator.js +3 -3
  153. package/dist/validator/validators.js +9 -9
  154. package/dist/validator.js +240 -230
  155. package/dist/waitForMedia.js +1 -1
  156. package/package.json +3 -3
  157. package/src/animable/absorbable/css/absorb.css +1 -0
  158. package/src/animable/absorbable/css/absorb.css.map +1 -1
  159. package/src/autocomplete/css/autocomplete.css +1 -0
  160. package/src/autocomplete/css/autocomplete.css.map +1 -1
  161. package/src/badge/css/badge.css +1 -0
  162. package/src/badge/css/badge.css.map +1 -1
  163. package/src/ckeditor/ckConfigurator.js +4 -0
  164. package/src/itemButtonList/css/item-button-list.css +1 -0
  165. package/src/itemButtonList/css/item-button-list.css.map +1 -1
  166. package/src/.DS_Store +0 -0
  167. package/src/css/basic.css +0 -7826
  168. package/src/css/basic.css.map +0 -1
  169. package/src/css/ckeditor/skins/tao/css/dialog.css +0 -950
  170. package/src/css/ckeditor/skins/tao/css/dialog.css.map +0 -1
  171. package/src/css/ckeditor/skins/tao/css/editor.css +0 -1850
  172. package/src/css/ckeditor/skins/tao/css/editor.css.map +0 -1
  173. package/src/scss/.DS_Store +0 -0
  174. package/src/scss/basic.scss +0 -16
  175. package/src/scss/ckeditor/skins/tao/scss/dialog.scss +0 -763
  176. package/src/scss/ckeditor/skins/tao/scss/editor.scss +0 -111
  177. package/src/scss/ckeditor/skins/tao/scss/inc/_ck-icons.scss +0 -59
  178. package/src/scss/ckeditor/skins/tao/scss/inc/_colorpanel.scss +0 -118
  179. package/src/scss/ckeditor/skins/tao/scss/inc/_elementspath.scss +0 -69
  180. package/src/scss/ckeditor/skins/tao/scss/inc/_mainui.scss +0 -194
  181. package/src/scss/ckeditor/skins/tao/scss/inc/_menu.scss +0 -181
  182. package/src/scss/ckeditor/skins/tao/scss/inc/_panel.scss +0 -200
  183. package/src/scss/ckeditor/skins/tao/scss/inc/_presets.scss +0 -32
  184. package/src/scss/ckeditor/skins/tao/scss/inc/_reset.scss +0 -101
  185. package/src/scss/ckeditor/skins/tao/scss/inc/_richcombo.scss +0 -213
  186. package/src/scss/ckeditor/skins/tao/scss/inc/_tao.scss +0 -59
  187. package/src/scss/ckeditor/skins/tao/scss/inc/_toolbar.scss +0 -301
  188. package/src/scss/font/source-sans-pro/source-sans-pro-italic.eot +0 -0
  189. package/src/scss/font/source-sans-pro/source-sans-pro-italic.eot.b64 +0 -1
  190. package/src/scss/font/source-sans-pro/source-sans-pro-italic.woff +0 -0
  191. package/src/scss/font/source-sans-pro/source-sans-pro-italic.woff.b64 +0 -1
  192. package/src/scss/font/source-sans-pro/source-sans-pro-regular.eot +0 -0
  193. package/src/scss/font/source-sans-pro/source-sans-pro-regular.eot.b64 +0 -1
  194. package/src/scss/font/source-sans-pro/source-sans-pro-regular.woff +0 -0
  195. package/src/scss/font/source-sans-pro/source-sans-pro-regular.woff.b64 +0 -1
  196. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.eot +0 -0
  197. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.eot.b64 +0 -1
  198. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.woff +0 -0
  199. package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.woff.b64 +0 -1
  200. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.eot +0 -0
  201. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.eot.b64 +0 -1
  202. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.woff +0 -0
  203. package/src/scss/font/source-sans-pro/source-sans-pro-semibold.woff.b64 +0 -1
  204. package/src/scss/font/tao/tao.eot +0 -0
  205. package/src/scss/font/tao/tao.svg +0 -235
  206. package/src/scss/font/tao/tao.ttf +0 -0
  207. package/src/scss/font/tao/tao.woff +0 -0
  208. package/src/scss/inc/_base.scss +0 -496
  209. package/src/scss/inc/_bootstrap.scss +0 -6
  210. package/src/scss/inc/_buttons.scss +0 -114
  211. package/src/scss/inc/_colors.scss +0 -88
  212. package/src/scss/inc/_feedback.scss +0 -150
  213. package/src/scss/inc/_flex-grid.scss +0 -15
  214. package/src/scss/inc/_fonts.scss +0 -4
  215. package/src/scss/inc/_forms.scss +0 -827
  216. package/src/scss/inc/_functions.scss +0 -283
  217. package/src/scss/inc/_grid.scss +0 -66
  218. package/src/scss/inc/_jquery.nouislider.scss +0 -254
  219. package/src/scss/inc/_normalize.scss +0 -528
  220. package/src/scss/inc/_report.scss +0 -68
  221. package/src/scss/inc/_secondary-properties.scss +0 -89
  222. package/src/scss/inc/_select2.scss +0 -634
  223. package/src/scss/inc/_toolbars.scss +0 -155
  224. package/src/scss/inc/_tooltip.scss +0 -312
  225. package/src/scss/inc/_variables.scss +0 -21
  226. package/src/scss/inc/base/_highlight.scss +0 -5
  227. package/src/scss/inc/base/_list-style.scss +0 -59
  228. package/src/scss/inc/base/_svg.scss +0 -3
  229. package/src/scss/inc/base/_table.scss +0 -63
  230. package/src/scss/inc/fonts/_source-sans-pro.scss +0 -29
  231. package/src/scss/inc/fonts/_tao-icon-classes.scss +0 -226
  232. package/src/scss/inc/fonts/_tao-icon-def.scss +0 -12
  233. package/src/scss/inc/fonts/_tao-icon-vars.scss +0 -240
@@ -1,956 +1,947 @@
1
1
  define(['lodash', 'i18n', 'core/collections', 'ui/component', 'ui/maths/calculator/core/areaBroker', 'ui/maths/calculator/core/terms', 'ui/maths/calculator/core/tokens', 'ui/maths/calculator/core/expression', 'ui/maths/calculator/core/tokenizer', 'util/mathsEvaluator', 'handlebars', 'lib/dompurify/purify'], function (_, __, collections, componentFactory, areaBrokerFactory, registeredTerms, tokensHelper, expressionHelper, tokenizerFactory, mathsEvaluatorFactory, Handlebars, DOMPurify) { 'use strict';
2
2
 
3
- _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
4
- __ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
5
- collections = collections && Object.prototype.hasOwnProperty.call(collections, 'default') ? collections['default'] : collections;
6
- componentFactory = componentFactory && Object.prototype.hasOwnProperty.call(componentFactory, 'default') ? componentFactory['default'] : componentFactory;
7
- areaBrokerFactory = areaBrokerFactory && Object.prototype.hasOwnProperty.call(areaBrokerFactory, 'default') ? areaBrokerFactory['default'] : areaBrokerFactory;
8
- registeredTerms = registeredTerms && Object.prototype.hasOwnProperty.call(registeredTerms, 'default') ? registeredTerms['default'] : registeredTerms;
9
- tokensHelper = tokensHelper && Object.prototype.hasOwnProperty.call(tokensHelper, 'default') ? tokensHelper['default'] : tokensHelper;
10
- expressionHelper = expressionHelper && Object.prototype.hasOwnProperty.call(expressionHelper, 'default') ? expressionHelper['default'] : expressionHelper;
11
- tokenizerFactory = tokenizerFactory && Object.prototype.hasOwnProperty.call(tokenizerFactory, 'default') ? tokenizerFactory['default'] : tokenizerFactory;
12
- mathsEvaluatorFactory = mathsEvaluatorFactory && Object.prototype.hasOwnProperty.call(mathsEvaluatorFactory, 'default') ? mathsEvaluatorFactory['default'] : mathsEvaluatorFactory;
13
- Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
14
- DOMPurify = DOMPurify && Object.prototype.hasOwnProperty.call(DOMPurify, 'default') ? DOMPurify['default'] : DOMPurify;
15
-
3
+ _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
4
+ __ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
5
+ collections = collections && Object.prototype.hasOwnProperty.call(collections, 'default') ? collections['default'] : collections;
6
+ componentFactory = componentFactory && Object.prototype.hasOwnProperty.call(componentFactory, 'default') ? componentFactory['default'] : componentFactory;
7
+ areaBrokerFactory = areaBrokerFactory && Object.prototype.hasOwnProperty.call(areaBrokerFactory, 'default') ? areaBrokerFactory['default'] : areaBrokerFactory;
8
+ registeredTerms = registeredTerms && Object.prototype.hasOwnProperty.call(registeredTerms, 'default') ? registeredTerms['default'] : registeredTerms;
9
+ tokensHelper = tokensHelper && Object.prototype.hasOwnProperty.call(tokensHelper, 'default') ? tokensHelper['default'] : tokensHelper;
10
+ expressionHelper = expressionHelper && Object.prototype.hasOwnProperty.call(expressionHelper, 'default') ? expressionHelper['default'] : expressionHelper;
11
+ tokenizerFactory = tokenizerFactory && Object.prototype.hasOwnProperty.call(tokenizerFactory, 'default') ? tokenizerFactory['default'] : tokenizerFactory;
12
+ mathsEvaluatorFactory = mathsEvaluatorFactory && Object.prototype.hasOwnProperty.call(mathsEvaluatorFactory, 'default') ? mathsEvaluatorFactory['default'] : mathsEvaluatorFactory;
13
+ Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
14
+ DOMPurify = DOMPurify && Object.prototype.hasOwnProperty.call(DOMPurify, 'default') ? DOMPurify['default'] : DOMPurify;
15
+
16
+ function _typeof(obj) {
17
+ "@babel/helpers - typeof";
18
+
19
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
20
+ return typeof obj;
21
+ } : function (obj) {
22
+ return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
23
+ }, _typeof(obj);
24
+ }
25
+
26
+ function Helpers0 (hb) {
27
+ //register a i18n helper
28
+ hb.registerHelper('__', function (key) {
29
+ return __(key);
30
+ });
16
31
  /**
17
- * This program is free software; you can redistribute it and/or
18
- * modify it under the terms of the GNU General Public License
19
- * as published by the Free Software Foundation; under version 2
20
- * of the License (non-upgradable).
21
- *
22
- * This program is distributed in the hope that it will be useful,
23
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
- * GNU General Public License for more details.
26
- *
27
- * You should have received a copy of the GNU General Public License
28
- * along with this program; if not, write to the Free Software
29
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30
- *
31
- * Copyright (c) 2013-2019 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
32
- *
32
+ * Register dompurify helper
33
33
  *
34
+ * https://github.com/cure53/DOMPurify
35
+ * with config SAFE_FOR_TEMPLATES: true
36
+ * to make output safe for template systems
34
37
  */
35
- function Helpers0 (hb) {
36
- //register a i18n helper
37
- hb.registerHelper('__', function (key) {
38
- return __(key);
39
- });
40
- /**
41
- * Register dompurify helper
42
- *
43
- * https://github.com/cure53/DOMPurify
44
- * with config SAFE_FOR_TEMPLATES: true
45
- * to make output safe for template systems
46
- */
47
-
48
- hb.registerHelper('dompurify', function (context) {
49
- return DOMPurify.sanitize(context);
50
- });
51
- /**
52
- * Register join helper
53
- *
54
- * Example :
55
- * var values = {a:v1, b:v2, c:v3};
56
- * Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
57
- * Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
58
- */
59
-
60
- hb.registerHelper('join', function (arr, keyValueGlue, fragmentGlue, wrapper) {
61
- var fragments = [];
62
- keyValueGlue = typeof keyValueGlue === 'string' ? keyValueGlue : undefined;
63
- fragmentGlue = typeof fragmentGlue === 'string' ? fragmentGlue : ' ';
64
- wrapper = typeof wrapper === 'string' ? wrapper : '"';
65
-
66
- _.forIn(arr, function (value, key) {
67
- var fragment = '';
68
-
69
- if (value !== null || value !== undefined) {
70
- if (typeof value === 'boolean') {
71
- value = value ? 'true' : 'false';
72
- } else if (typeof value === 'object') {
73
- value = _.values(value).join(' ');
74
- }
75
- } else {
76
- value = '';
77
- }
78
-
79
- if (keyValueGlue !== undefined) {
80
- fragment += key + keyValueGlue;
81
- }
82
38
 
83
- fragment += wrapper + value + wrapper;
84
- fragments.push(fragment);
85
- });
39
+ hb.registerHelper('dompurify', function (context) {
40
+ return DOMPurify.sanitize(context);
41
+ });
42
+ /**
43
+ * Register join helper
44
+ *
45
+ * Example :
46
+ * var values = {a:v1, b:v2, c:v3};
47
+ * Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
48
+ * Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
49
+ */
86
50
 
87
- return fragments.join(fragmentGlue);
88
- }); //register a classic "for loop" helper
89
- //it also adds a local variable "i" as the index in each iteration loop
51
+ hb.registerHelper('join', function (arr, keyValueGlue, fragmentGlue, wrapper) {
52
+ var fragments = [];
53
+ keyValueGlue = typeof keyValueGlue === 'string' ? keyValueGlue : undefined;
54
+ fragmentGlue = typeof fragmentGlue === 'string' ? fragmentGlue : ' ';
55
+ wrapper = typeof wrapper === 'string' ? wrapper : '"';
90
56
 
91
- hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
92
- var ret = '';
93
- startIndex = parseInt(startIndex);
94
- stopIndex = parseInt(stopIndex);
95
- increment = parseInt(increment);
57
+ _.forIn(arr, function (value, key) {
58
+ var fragment = '';
96
59
 
97
- for (var i = startIndex; i < stopIndex; i += increment) {
98
- ret += options.fn(_.extend({}, this, {
99
- i: i
100
- }));
101
- }
102
-
103
- return ret;
104
- });
105
- hb.registerHelper('equal', function (var1, var2, options) {
106
- if (var1 == var2) {
107
- return options.fn(this);
60
+ if (value !== null || value !== undefined) {
61
+ if (typeof value === 'boolean') {
62
+ value = value ? 'true' : 'false';
63
+ } else if (_typeof(value) === 'object') {
64
+ value = _.values(value).join(' ');
65
+ }
108
66
  } else {
109
- return options.inverse(this);
67
+ value = '';
110
68
  }
111
- }); // register a "get property" helper
112
- // it gets the named property from the provided context
113
-
114
- hb.registerHelper('property', function (name, context) {
115
- return context[name] || '';
116
- }); // register an 'includes' helper
117
- // it checks if value is in array
118
69
 
119
- hb.registerHelper('includes', function (haystack, needle, options) {
120
- if (_.contains(haystack, needle)) {
121
- return options.fn(this);
70
+ if (keyValueGlue !== undefined) {
71
+ fragment += key + keyValueGlue;
122
72
  }
73
+
74
+ fragment += wrapper + value + wrapper;
75
+ fragments.push(fragment);
123
76
  });
124
- }
125
77
 
126
- if (!Helpers0.__initialized) {
127
- Helpers0(Handlebars);
128
- Helpers0.__initialized = true;
129
- }
130
- var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
131
- this.compilerInfo = [4,'>= 1.0.0'];
132
- helpers = this.merge(helpers, Handlebars.helpers);
78
+ return fragments.join(fragmentGlue);
79
+ }); //register a classic "for loop" helper
80
+ //it also adds a local variable "i" as the index in each iteration loop
81
+
82
+ hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
83
+ var ret = '';
84
+ startIndex = parseInt(startIndex);
85
+ stopIndex = parseInt(stopIndex);
86
+ increment = parseInt(increment);
87
+
88
+ for (var i = startIndex; i < stopIndex; i += increment) {
89
+ ret += options.fn(_.extend({}, this, {
90
+ i: i
91
+ }));
92
+ }
93
+
94
+ return ret;
95
+ });
96
+ hb.registerHelper('equal', function (var1, var2, options) {
97
+ if (var1 == var2) {
98
+ return options.fn(this);
99
+ } else {
100
+ return options.inverse(this);
101
+ }
102
+ }); // register a "get property" helper
103
+ // it gets the named property from the provided context
104
+
105
+ hb.registerHelper('property', function (name, context) {
106
+ return context[name] || '';
107
+ }); // register an 'includes' helper
108
+ // it checks if value is in array
109
+
110
+ hb.registerHelper('includes', function (haystack, needle, options) {
111
+ if (_.contains(haystack, needle)) {
112
+ return options.fn(this);
113
+ }
114
+ });
115
+ }
116
+
117
+ if (!Helpers0.__initialized) {
118
+ Helpers0(Handlebars);
119
+ Helpers0.__initialized = true;
120
+ }
121
+ var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
122
+ this.compilerInfo = [4,'>= 1.0.0'];
123
+ helpers = this.merge(helpers, Handlebars.helpers);
124
+
125
+
126
+ return "<div class=\"calculator\">\n <div class=\"screen\"></div>\n <div class=\"input\"></div>\n <div class=\"keyboard\"></div>\n</div>";
127
+ });
128
+ function boardTpl(data, options, asString) {
129
+ var html = Template(data, options);
130
+ return (asString || true) ? html : $(html);
131
+ }
132
+
133
+ /**
134
+ * This program is free software; you can redistribute it and/or
135
+ * modify it under the terms of the GNU General Public License
136
+ * as published by the Free Software Foundation; under version 2
137
+ * of the License (non-upgradable).
138
+ *
139
+ * This program is distributed in the hope that it will be useful,
140
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
141
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
142
+ * GNU General Public License for more details.
143
+ *
144
+ * You should have received a copy of the GNU General Public License
145
+ * along with this program; if not, write to the Free Software
146
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
147
+ *
148
+ * Copyright (c) 2018-2019 Open Assessment Technologies SA ;
149
+ */
150
+ /**
151
+ * Default config values
152
+ * @type {Object}
153
+ */
154
+
155
+ var defaultConfig = {
156
+ expression: '',
157
+ position: 0
158
+ };
159
+ /**
160
+ * Name of the variable that contains the last result
161
+ * @type {String}
162
+ */
163
+
164
+ var lastResultVariableName = registeredTerms.ANS.value;
165
+ /**
166
+ * Regex that matches the prefixed function operators
167
+ * @type {RegExp}
168
+ */
169
+
170
+ var rePrefixedTerm = /^@[a-zA-Z_]\w*$/;
171
+ /**
172
+ * The internal namespace for built-in events listeners
173
+ * @type {String}
174
+ */
175
+
176
+ var ns = 'calculator';
177
+ /**
178
+ * Build the basic UI for a calculator
179
+ * @param {jQuery|HTMLElement|String} $container
180
+ * @param {Function[]} pluginFactories
181
+ * @param {Object} [config]
182
+ * @param {String} [config.expression=''] - The initial expression
183
+ * @param {Number} [config.position=0] - The initial position in the expression
184
+ * @param {Object} [config.maths] - Optional config for the maths evaluator (@see util/mathsEvaluator)
185
+ * @param {Object} [config.plugins] - Optional config for each plugins
186
+ * @returns {calculator}
187
+ */
188
+
189
+ function calculatorBoardFactory($container, pluginFactories, config) {
190
+ /**
191
+ * Maths expression parser.
192
+ * @type {Function}
193
+ */
194
+ var mathsEvaluator;
195
+ /**
196
+ * Keep the area broker instance
197
+ * @see ui/maths/calculator/areaBroker
198
+ */
133
199
 
200
+ var areaBroker;
201
+ /**
202
+ * @type {Object} the registered plugins
203
+ */
134
204
 
135
- return "<div class=\"calculator\">\n <div class=\"screen\"></div>\n <div class=\"input\"></div>\n <div class=\"keyboard\"></div>\n</div>";
136
- });
137
- function boardTpl(data, options, asString) {
138
- var html = Template(data, options);
139
- return (asString || true) ? html : $(html);
140
- }
205
+ var plugins = {};
206
+ /**
207
+ * The current expression
208
+ * @type {String}
209
+ */
141
210
 
211
+ var expression = '';
142
212
  /**
143
- * This program is free software; you can redistribute it and/or
144
- * modify it under the terms of the GNU General Public License
145
- * as published by the Free Software Foundation; under version 2
146
- * of the License (non-upgradable).
147
- *
148
- * This program is distributed in the hope that it will be useful,
149
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
150
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
151
- * GNU General Public License for more details.
152
- *
153
- * You should have received a copy of the GNU General Public License
154
- * along with this program; if not, write to the Free Software
155
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
156
- *
157
- * Copyright (c) 2018-2019 Open Assessment Technologies SA ;
213
+ * A list of variables that can be used in the expression
214
+ * @type {Map}
158
215
  */
216
+
217
+ var variables = new collections.Map();
159
218
  /**
160
- * Default config values
161
- * @type {Object}
219
+ * A list of registered commands that can be used inside the calculator
220
+ * @type {Map}
162
221
  */
163
222
 
164
- var defaultConfig = {
165
- expression: '',
166
- position: 0
167
- };
223
+ var commands = new collections.Map();
168
224
  /**
169
- * Name of the variable that contains the last result
170
- * @type {String}
225
+ * The current position in the current expression (i.e. the position of the caret)
226
+ * @type {Number}
171
227
  */
172
228
 
173
- var lastResultVariableName = registeredTerms.ANS.value;
229
+ var position = 0;
174
230
  /**
175
- * Regex that matches the prefixed function operators
176
- * @type {RegExp}
231
+ * The tokenizer utilized to split down the expression
232
+ * @type {calculatorTokenizer}
177
233
  */
178
234
 
179
- var rePrefixedTerm = /^@[a-zA-Z_]\w*$/;
235
+ var tokenizer = tokenizerFactory();
180
236
  /**
181
- * The internal namespace for built-in events listeners
182
- * @type {String}
237
+ * The list of tokens extracted from the expression
238
+ * @type {Array|null}
183
239
  */
184
240
 
185
- var ns = 'calculator';
241
+ var tokens = null;
186
242
  /**
187
- * Build the basic UI for a calculator
188
- * @param {jQuery|HTMLElement|String} $container
189
- * @param {Function[]} pluginFactories
190
- * @param {Object} [config]
191
- * @param {String} [config.expression=''] - The initial expression
192
- * @param {Number} [config.position=0] - The initial position in the expression
193
- * @param {Object} [config.maths] - Optional config for the maths evaluator (@see util/mathsEvaluator)
194
- * @param {Object} [config.plugins] - Optional config for each plugins
195
- * @returns {calculator}
243
+ *
244
+ * @type {Object}
196
245
  */
197
246
 
198
- function calculatorBoardFactory($container, pluginFactories, config) {
247
+ var calculatorApi = {
199
248
  /**
200
- * Maths expression parser.
201
- * @type {Function}
249
+ * Returns the current expression
250
+ * @returns {String}
202
251
  */
203
- var mathsEvaluator;
252
+ getExpression: function getExpression() {
253
+ return expression;
254
+ },
255
+
204
256
  /**
205
- * Keep the area broker instance
206
- * @see ui/maths/calculator/areaBroker
257
+ * Changes the current expression
258
+ * @param {String} expr
259
+ * @returns {calculator}
260
+ * @fires expressionchange after the expression has been changed
207
261
  */
262
+ setExpression: function setExpression(expr) {
263
+ expression = String(expr || '');
264
+ tokens = null;
265
+ /**
266
+ * @event expressionchange
267
+ * @param {String} expression
268
+ */
269
+
270
+ this.trigger('expressionchange', expression);
271
+ return this;
272
+ },
208
273
 
209
- var areaBroker;
210
274
  /**
211
- * @type {Object} the registered plugins
275
+ * Gets the current position inside the expression
276
+ * @returns {Number}
212
277
  */
278
+ getPosition: function getPosition() {
279
+ return position;
280
+ },
213
281
 
214
- var plugins = {};
215
282
  /**
216
- * The current expression
217
- * @type {String}
283
+ * Sets the current position inside the expression
284
+ * @param {Number|String} pos
285
+ * @returns {calculator}
286
+ * @fires positionchange after the position has been changed
218
287
  */
288
+ setPosition: function setPosition(pos) {
289
+ position = Math.max(0, Math.min(parseInt(pos, 10) || 0, expression.length));
290
+ /**
291
+ * @event positionchange
292
+ * @param {Number} position
293
+ */
294
+
295
+ this.trigger('positionchange', position);
296
+ return this;
297
+ },
219
298
 
220
- var expression = '';
221
299
  /**
222
- * A list of variables that can be used in the expression
223
- * @type {Map}
300
+ * Gets the tokens from the current expression
301
+ * @returns {token[]}
224
302
  */
303
+ getTokens: function getTokens() {
304
+ if (tokens === null) {
305
+ tokens = tokenizer.tokenize(expression);
306
+ }
307
+
308
+ return tokens;
309
+ },
225
310
 
226
- var variables = new collections.Map();
227
311
  /**
228
- * A list of registered commands that can be used inside the calculator
229
- * @type {Map}
312
+ * Gets the token at the current position from the current expression
313
+ * @returns {token|null} Returns the token at the current position, or null if none
230
314
  */
315
+ getToken: function getToken() {
316
+ var tokensList = this.getTokens();
317
+ var index = this.getTokenIndex();
318
+ return tokensList[index] || null;
319
+ },
231
320
 
232
- var commands = new collections.Map();
233
321
  /**
234
- * The current position in the current expression (i.e. the position of the caret)
235
- * @type {Number}
322
+ * Gets token index from the current position in the expression.
323
+ * @returns {Number} Returns the index of the token at the current position.
236
324
  */
325
+ getTokenIndex: function getTokenIndex() {
326
+ var index = 0;
327
+
328
+ _.forEach(this.getTokens(), function (token, idx) {
329
+ if (position >= token.offset) {
330
+ index = idx;
331
+ }
332
+ });
333
+
334
+ return index;
335
+ },
237
336
 
238
- var position = 0;
239
337
  /**
240
- * The tokenizer utilized to split down the expression
241
- * @type {calculatorTokenizer}
338
+ * Gets access to the tokenizer
339
+ * @returns {calculatorTokenizer}
242
340
  */
341
+ getTokenizer: function getTokenizer() {
342
+ return tokenizer;
343
+ },
243
344
 
244
- var tokenizer = tokenizerFactory();
245
345
  /**
246
- * The list of tokens extracted from the expression
247
- * @type {Array|null}
346
+ * Gets a variable defined for the expression.
347
+ * @param {String} name - The variable name
348
+ * @returns {mathsExpression} The value. Can be another expression.
248
349
  */
350
+ getVariable: function getVariable(name) {
351
+ return variables.get(name);
352
+ },
249
353
 
250
- var tokens = null;
251
354
  /**
252
- *
253
- * @type {Object}
355
+ * Checks if a variable is registered
356
+ * @param {String} name
357
+ * @returns {Boolean}
254
358
  */
359
+ hasVariable: function hasVariable(name) {
360
+ return variables.has(name);
361
+ },
255
362
 
256
- var calculatorApi = {
257
- /**
258
- * Returns the current expression
259
- * @returns {String}
260
- */
261
- getExpression: function getExpression() {
262
- return expression;
263
- },
363
+ /**
364
+ * Sets a variable that can be used by the expression.
365
+ * @param {String} name - The variable name
366
+ * @param {String|Number|mathsExpression} value - The value. Can be another expression.
367
+ * @returns {calculator}
368
+ * @fires variableadd after the variable has been set
369
+ */
370
+ setVariable: function setVariable(name, value) {
371
+ var errValue;
372
+
373
+ try {
374
+ value = mathsEvaluator(value);
375
+ } catch (err) {
376
+ errValue = value && value.expression || value;
377
+ value = mathsEvaluator('0');
378
+ value.expression = errValue;
379
+ }
264
380
 
381
+ variables.set(name, value);
265
382
  /**
266
- * Changes the current expression
267
- * @param {String} expr
268
- * @returns {calculator}
269
- * @fires expressionchange after the expression has been changed
383
+ * @event variableadd
384
+ * @param {String} name
385
+ * @param {String} value
270
386
  */
271
- setExpression: function setExpression(expr) {
272
- expression = String(expr || '');
273
- tokens = null;
274
- /**
275
- * @event expressionchange
276
- * @param {String} expression
277
- */
278
387
 
279
- this.trigger('expressionchange', expression);
280
- return this;
281
- },
388
+ this.trigger('variableadd', name, value);
389
+ return this;
390
+ },
282
391
 
392
+ /**
393
+ * Deletes a variable defined for the expression.
394
+ * @param {String} name - The variable name
395
+ * @returns {calculator}
396
+ * @fires variabledelete after the variable has been deleted
397
+ */
398
+ deleteVariable: function deleteVariable(name) {
399
+ variables.delete(name);
283
400
  /**
284
- * Gets the current position inside the expression
285
- * @returns {Number}
401
+ * @event variabledelete
402
+ * @param {String} name
286
403
  */
287
- getPosition: function getPosition() {
288
- return position;
289
- },
290
404
 
291
- /**
292
- * Sets the current position inside the expression
293
- * @param {Number|String} pos
294
- * @returns {calculator}
295
- * @fires positionchange after the position has been changed
296
- */
297
- setPosition: function setPosition(pos) {
298
- position = Math.max(0, Math.min(parseInt(pos, 10) || 0, expression.length));
299
- /**
300
- * @event positionchange
301
- * @param {Number} position
302
- */
405
+ this.trigger('variabledelete', name);
406
+ return this;
407
+ },
303
408
 
304
- this.trigger('positionchange', position);
305
- return this;
306
- },
409
+ /**
410
+ * Gets the list of variables defined for the expression.
411
+ * @returns {Object} The list of defined variables.
412
+ */
413
+ getVariables: function getVariables() {
414
+ var defs = {};
415
+ variables.forEach(function (value, name) {
416
+ defs[name] = value;
417
+ });
418
+ return defs;
419
+ },
307
420
 
308
- /**
309
- * Gets the tokens from the current expression
310
- * @returns {token[]}
311
- */
312
- getTokens: function getTokens() {
313
- if (tokens === null) {
314
- tokens = tokenizer.tokenize(expression);
315
- }
421
+ /**
422
+ * Sets a list of variables that can be used by the expression.
423
+ * @param {Object} defs - A list variables to set.
424
+ * @returns {calculator}
425
+ * @fires variableadd after each variable has been set
426
+ */
427
+ setVariables: function setVariables(defs) {
428
+ var self = this;
316
429
 
317
- return tokens;
318
- },
430
+ _.forEach(defs, function (value, name) {
431
+ self.setVariable(name, value);
432
+ });
319
433
 
320
- /**
321
- * Gets the token at the current position from the current expression
322
- * @returns {token|null} Returns the token at the current position, or null if none
323
- */
324
- getToken: function getToken() {
325
- var tokensList = this.getTokens();
326
- var index = this.getTokenIndex();
327
- return tokensList[index] || null;
328
- },
434
+ return this;
435
+ },
329
436
 
437
+ /**
438
+ * Deletes all variables defined for the expression.
439
+ * @returns {calculator}
440
+ * @fires variabledelete after the variables has been deleted
441
+ */
442
+ deleteVariables: function deleteVariables() {
443
+ variables.clear();
330
444
  /**
331
- * Gets token index from the current position in the expression.
332
- * @returns {Number} Returns the index of the token at the current position.
445
+ * @event variabledelete
446
+ * @param {null} name
333
447
  */
334
- getTokenIndex: function getTokenIndex() {
335
- var index = 0;
336
448
 
337
- _.forEach(this.getTokens(), function (token, idx) {
338
- if (position >= token.offset) {
339
- index = idx;
340
- }
341
- });
449
+ this.trigger('variabledelete', null);
450
+ this.setLastResult('0');
451
+ return this;
452
+ },
342
453
 
343
- return index;
344
- },
454
+ /**
455
+ * Sets the value of the last result
456
+ * @param {String|Number|mathsExpression} [result='0']
457
+ * @returns {calculator}
458
+ */
459
+ setLastResult: function setLastResult(result) {
460
+ if (!result || expressionHelper.containsError(result)) {
461
+ result = '0';
462
+ }
345
463
 
346
- /**
347
- * Gets access to the tokenizer
348
- * @returns {calculatorTokenizer}
349
- */
350
- getTokenizer: function getTokenizer() {
351
- return tokenizer;
352
- },
464
+ this.setVariable(lastResultVariableName, result);
465
+ return this;
466
+ },
353
467
 
354
- /**
355
- * Gets a variable defined for the expression.
356
- * @param {String} name - The variable name
357
- * @returns {mathsExpression} The value. Can be another expression.
358
- */
359
- getVariable: function getVariable(name) {
360
- return variables.get(name);
361
- },
468
+ /**
469
+ * Gets the value of the last result
470
+ * @returns {mathsExpression}
471
+ */
472
+ getLastResult: function getLastResult() {
473
+ return this.getVariable(lastResultVariableName);
474
+ },
362
475
 
476
+ /**
477
+ * Registers a command
478
+ * @param {String} name
479
+ * @param {String} [label]
480
+ * @param {String} [description]
481
+ * @returns {calculator}
482
+ * @fires commandadd after the command has been set
483
+ */
484
+ setCommand: function setCommand(name, label, description) {
485
+ commands.set(name, {
486
+ name: name,
487
+ label: label,
488
+ description: description
489
+ });
363
490
  /**
364
- * Checks if a variable is registered
491
+ * @event commandadd
365
492
  * @param {String} name
366
- * @returns {Boolean}
367
493
  */
368
- hasVariable: function hasVariable(name) {
369
- return variables.has(name);
370
- },
371
494
 
372
- /**
373
- * Sets a variable that can be used by the expression.
374
- * @param {String} name - The variable name
375
- * @param {String|Number|mathsExpression} value - The value. Can be another expression.
376
- * @returns {calculator}
377
- * @fires variableadd after the variable has been set
378
- */
379
- setVariable: function setVariable(name, value) {
380
- var errValue;
381
-
382
- try {
383
- value = mathsEvaluator(value);
384
- } catch (err) {
385
- errValue = value && value.expression || value;
386
- value = mathsEvaluator('0');
387
- value.expression = errValue;
388
- }
495
+ this.trigger('commandadd', name);
496
+ return this;
497
+ },
389
498
 
390
- variables.set(name, value);
391
- /**
392
- * @event variableadd
393
- * @param {String} name
394
- * @param {String} value
395
- */
396
-
397
- this.trigger('variableadd', name, value);
398
- return this;
399
- },
400
-
401
- /**
402
- * Deletes a variable defined for the expression.
403
- * @param {String} name - The variable name
404
- * @returns {calculator}
405
- * @fires variabledelete after the variable has been deleted
406
- */
407
- deleteVariable: function deleteVariable(name) {
408
- variables.delete(name);
409
- /**
410
- * @event variabledelete
411
- * @param {String} name
412
- */
499
+ /**
500
+ * Gets the definition of a registered command
501
+ * @returns {Object} The registered command
502
+ */
503
+ getCommand: function getCommand(name) {
504
+ return commands.get(name);
505
+ },
413
506
 
414
- this.trigger('variabledelete', name);
415
- return this;
416
- },
507
+ /**
508
+ * Gets the list of registered commands
509
+ * @returns {Object} The list of registered commands
510
+ */
511
+ getCommands: function getCommands() {
512
+ var defs = {};
513
+ commands.forEach(function (value, name) {
514
+ defs[name] = value;
515
+ });
516
+ return defs;
517
+ },
417
518
 
418
- /**
419
- * Gets the list of variables defined for the expression.
420
- * @returns {Object} The list of defined variables.
421
- */
422
- getVariables: function getVariables() {
423
- var defs = {};
424
- variables.forEach(function (value, name) {
425
- defs[name] = value;
426
- });
427
- return defs;
428
- },
519
+ /**
520
+ * Checks if a command is registered
521
+ * @param {String} name
522
+ * @returns {Boolean}
523
+ */
524
+ hasCommand: function hasCommand(name) {
525
+ return commands.has(name);
526
+ },
429
527
 
528
+ /**
529
+ * Delete a registered command
530
+ * @param {String} name
531
+ * @returns {calculator}
532
+ * @fires commanddelete after the command has been deleted
533
+ */
534
+ deleteCommand: function deleteCommand(name) {
535
+ commands.delete(name);
430
536
  /**
431
- * Sets a list of variables that can be used by the expression.
432
- * @param {Object} defs - A list variables to set.
433
- * @returns {calculator}
434
- * @fires variableadd after each variable has been set
537
+ * @event commanddelete
538
+ * @param {String} name
435
539
  */
436
- setVariables: function setVariables(defs) {
437
- var self = this;
438
540
 
439
- _.forEach(defs, function (value, name) {
440
- self.setVariable(name, value);
441
- });
541
+ this.trigger('commanddelete', name);
542
+ return this;
543
+ },
442
544
 
443
- return this;
444
- },
545
+ /**
546
+ * Inserts a term in the expression at the current position
547
+ * @param {String} name - The name of the term to insert
548
+ * @param {Object} term - The definition of the term to insert
549
+ * @returns {calculator}
550
+ * @fires termerror if the term to add is invalid
551
+ * @fires termadd when the term has been added
552
+ * @fires termadd-<name> when the term has been added
553
+ */
554
+ addTerm: function addTerm(name, term) {
555
+ var tokensList = this.getTokens();
556
+ var index = this.getTokenIndex();
557
+ var currentToken = tokensList[index];
558
+ var nextToken = tokensList[index + 1];
559
+ var isIdentifier, needsSpace, value; // checks if the aforementioned token requires space around
560
+
561
+ function tokenNeedsSpace(token) {
562
+ return tokensHelper.isIdentifier(token) || isIdentifier && !tokensHelper.isSeparator(token);
563
+ }
445
564
 
446
- /**
447
- * Deletes all variables defined for the expression.
448
- * @returns {calculator}
449
- * @fires variabledelete after the variables has been deleted
450
- */
451
- deleteVariables: function deleteVariables() {
452
- variables.clear();
565
+ if (!_.isPlainObject(term) || 'undefined' === typeof term.value) {
453
566
  /**
454
- * @event variabledelete
455
- * @param {null} name
567
+ * @event termerror
568
+ * @param {TypeError} err
456
569
  */
570
+ return this.trigger('termerror', new TypeError('Invalid term: ' + name));
571
+ }
457
572
 
458
- this.trigger('variabledelete', null);
459
- this.setLastResult('0');
460
- return this;
461
- },
462
-
463
- /**
464
- * Sets the value of the last result
465
- * @param {String|Number|mathsExpression} [result='0']
466
- * @returns {calculator}
467
- */
468
- setLastResult: function setLastResult(result) {
469
- if (!result || expressionHelper.containsError(result)) {
470
- result = '0';
471
- }
472
-
473
- this.setVariable(lastResultVariableName, result);
474
- return this;
475
- },
573
+ value = term.value; // will replace the current term if:
574
+ // - it is a 0, and the term to add is not an operator nor a dot
575
+ // - it is the last result, and the term to add is not an operator
476
576
 
477
- /**
478
- * Gets the value of the last result
479
- * @returns {mathsExpression}
480
- */
481
- getLastResult: function getLastResult() {
482
- return this.getVariable(lastResultVariableName);
483
- },
577
+ if (!tokensHelper.isOperator(term.type) && !rePrefixedTerm.test(term.value) && tokensList.length === 1 && (currentToken.type === 'NUM0' && name !== 'DOT' || currentToken.type === 'ANS')) {
578
+ this.replace(value);
579
+ } else {
580
+ // simply add the term, with potentially spaces around
581
+ if (expression && !tokensHelper.isSeparator(term.type)) {
582
+ isIdentifier = tokensHelper.isIdentifier(term.type);
583
+ needsSpace = tokenNeedsSpace(currentToken); // prepend space when either the term to add or the previous term is an identifier
484
584
 
485
- /**
486
- * Registers a command
487
- * @param {String} name
488
- * @param {String} [label]
489
- * @param {String} [description]
490
- * @returns {calculator}
491
- * @fires commandadd after the command has been set
492
- */
493
- setCommand: function setCommand(name, label, description) {
494
- commands.set(name, {
495
- name: name,
496
- label: label,
497
- description: description
498
- });
499
- /**
500
- * @event commandadd
501
- * @param {String} name
502
- */
585
+ if (position && needsSpace) {
586
+ value = ' ' + value;
587
+ } // append space when either the term to add or the next term is an identifier
503
588
 
504
- this.trigger('commandadd', name);
505
- return this;
506
- },
507
589
 
508
- /**
509
- * Gets the definition of a registered command
510
- * @returns {Object} The registered command
511
- */
512
- getCommand: function getCommand(name) {
513
- return commands.get(name);
514
- },
590
+ if (!position && needsSpace || position < expression.length && tokenNeedsSpace(nextToken)) {
591
+ value += ' ';
592
+ }
593
+ }
515
594
 
595
+ this.insert(value);
596
+ }
516
597
  /**
517
- * Gets the list of registered commands
518
- * @returns {Object} The list of registered commands
598
+ * @event termadd
599
+ * @param {String} name - The name of the added term
600
+ * @param {Object} term - The descriptor of the added term
519
601
  */
520
- getCommands: function getCommands() {
521
- var defs = {};
522
- commands.forEach(function (value, name) {
523
- defs[name] = value;
524
- });
525
- return defs;
526
- },
527
602
 
528
- /**
529
- * Checks if a command is registered
530
- * @param {String} name
531
- * @returns {Boolean}
532
- */
533
- hasCommand: function hasCommand(name) {
534
- return commands.has(name);
535
- },
536
603
 
604
+ this.trigger('termadd', name, term);
537
605
  /**
538
- * Delete a registered command
539
- * @param {String} name
540
- * @returns {calculator}
541
- * @fires commanddelete after the command has been deleted
606
+ * @event termadd-<name>
607
+ * @param {Object} term - The descriptor of the added term
542
608
  */
543
- deleteCommand: function deleteCommand(name) {
544
- commands.delete(name);
545
- /**
546
- * @event commanddelete
547
- * @param {String} name
548
- */
549
609
 
550
- this.trigger('commanddelete', name);
551
- return this;
552
- },
610
+ this.trigger('termadd-' + name, term);
611
+ return this;
612
+ },
553
613
 
554
- /**
555
- * Inserts a term in the expression at the current position
556
- * @param {String} name - The name of the term to insert
557
- * @param {Object} term - The definition of the term to insert
558
- * @returns {calculator}
559
- * @fires termerror if the term to add is invalid
560
- * @fires termadd when the term has been added
561
- * @fires termadd-<name> when the term has been added
562
- */
563
- addTerm: function addTerm(name, term) {
564
- var tokensList = this.getTokens();
565
- var index = this.getTokenIndex();
566
- var currentToken = tokensList[index];
567
- var nextToken = tokensList[index + 1];
568
- var isIdentifier, needsSpace, value; // checks if the aforementioned token requires space around
569
-
570
- function tokenNeedsSpace(token) {
571
- return tokensHelper.isIdentifier(token) || isIdentifier && !tokensHelper.isSeparator(token);
572
- }
614
+ /**
615
+ * Inserts a term in the expression at the current position
616
+ * @param {String} name - The name of the term to insert
617
+ * @returns {calculator}
618
+ * @fires termerror if the term to add is invalid
619
+ * @fires termadd when the term has been added
620
+ */
621
+ useTerm: function useTerm(name) {
622
+ var term;
573
623
 
574
- if (!_.isPlainObject(term) || 'undefined' === typeof term.value) {
575
- /**
576
- * @event termerror
577
- * @param {TypeError} err
578
- */
579
- return this.trigger('termerror', new TypeError('Invalid term: ' + name));
580
- }
624
+ if (rePrefixedTerm.test(name)) {
625
+ name = name.substring(1);
626
+ term = _.clone(registeredTerms[name]);
627
+ term.value = '@' + term.value;
628
+ } else {
629
+ term = registeredTerms[name];
630
+ }
581
631
 
582
- value = term.value; // will replace the current term if:
583
- // - it is a 0, and the term to add is not an operator nor a dot
584
- // - it is the last result, and the term to add is not an operator
632
+ if ('undefined' === typeof term) {
633
+ /**
634
+ * @event termerror
635
+ * @param {TypeError} err
636
+ */
637
+ return this.trigger('termerror', new TypeError('Invalid term: ' + name));
638
+ }
585
639
 
586
- if (!tokensHelper.isOperator(term.type) && !rePrefixedTerm.test(term.value) && tokensList.length === 1 && (currentToken.type === 'NUM0' && name !== 'DOT' || currentToken.type === 'ANS')) {
587
- this.replace(value);
588
- } else {
589
- // simply add the term, with potentially spaces around
590
- if (expression && !tokensHelper.isSeparator(term.type)) {
591
- isIdentifier = tokensHelper.isIdentifier(term.type);
592
- needsSpace = tokenNeedsSpace(currentToken); // prepend space when either the term to add or the previous term is an identifier
640
+ return this.addTerm(name, term);
641
+ },
593
642
 
594
- if (position && needsSpace) {
595
- value = ' ' + value;
596
- } // append space when either the term to add or the next term is an identifier
643
+ /**
644
+ * Inserts a list of terms in the expression at the current position
645
+ * @param {String|String[]} names - The names of the terms to insert.
646
+ * Could be either an array of names or a list separated by spaces.
647
+ * @returns {calculator}
648
+ * @fires termerror if a term to add is invalid
649
+ * @fires termadd when a term has been added
650
+ */
651
+ useTerms: function useTerms(names) {
652
+ if ('string' === typeof names) {
653
+ names = names.split(/\s+/);
654
+ }
597
655
 
656
+ _.forEach(names, this.useTerm.bind(this));
598
657
 
599
- if (!position && needsSpace || position < expression.length && tokenNeedsSpace(nextToken)) {
600
- value += ' ';
601
- }
602
- }
658
+ return this;
659
+ },
603
660
 
604
- this.insert(value);
605
- }
661
+ /**
662
+ * Inserts a variable as a term in the expression at the current position
663
+ * @param {String} name - The name of the variable to insert
664
+ * @returns {calculator}
665
+ * @fires termerror if the term to add is invalid
666
+ * @fires termadd when the term has been added
667
+ */
668
+ useVariable: function useVariable(name) {
669
+ if (!variables.has(name)) {
606
670
  /**
607
- * @event termadd
608
- * @param {String} name - The name of the added term
609
- * @param {Object} term - The descriptor of the added term
671
+ * @event termerror
672
+ * @param {TypeError} err
610
673
  */
674
+ return this.trigger('termerror', new TypeError('Invalid variable: ' + name));
675
+ }
611
676
 
677
+ return this.addTerm('VAR_' + name.toUpperCase(), {
678
+ label: name,
679
+ value: name,
680
+ type: 'variable',
681
+ description: __('Variable %s', name)
682
+ });
683
+ },
612
684
 
613
- this.trigger('termadd', name, term);
685
+ /**
686
+ * Calls a command
687
+ * @param {String} name - The name of the called command
688
+ * @param {*} ... - additional params for the command
689
+ * @returns {calculator}
690
+ * @fires command with the name and the parameters of the command
691
+ * @fires command-<name> with the parameters of the command
692
+ * @fires commanderror if the command is invalid
693
+ */
694
+ useCommand: function useCommand(name) {
695
+ if (!commands.has(name)) {
614
696
  /**
615
- * @event termadd-<name>
616
- * @param {Object} term - The descriptor of the added term
697
+ * @event commanderror
698
+ * @param {TypeError} err
617
699
  */
618
-
619
- this.trigger('termadd-' + name, term);
620
- return this;
621
- },
622
-
700
+ return this.trigger('commanderror', new TypeError('Invalid command: ' + name));
701
+ }
623
702
  /**
624
- * Inserts a term in the expression at the current position
625
- * @param {String} name - The name of the term to insert
626
- * @returns {calculator}
627
- * @fires termerror if the term to add is invalid
628
- * @fires termadd when the term has been added
703
+ * @event command
704
+ * @param {String} name - The name of the called command
705
+ * @param {*} ... - additional params for the command
629
706
  */
630
- useTerm: function useTerm(name) {
631
- var term;
632
707
 
633
- if (rePrefixedTerm.test(name)) {
634
- name = name.substring(1);
635
- term = _.clone(registeredTerms[name]);
636
- term.value = '@' + term.value;
637
- } else {
638
- term = registeredTerms[name];
639
- }
640
-
641
- if ('undefined' === typeof term) {
642
- /**
643
- * @event termerror
644
- * @param {TypeError} err
645
- */
646
- return this.trigger('termerror', new TypeError('Invalid term: ' + name));
647
- }
648
-
649
- return this.addTerm(name, term);
650
- },
651
708
 
709
+ this.trigger.apply(this, ['command'].concat([].slice.call(arguments)));
652
710
  /**
653
- * Inserts a list of terms in the expression at the current position
654
- * @param {String|String[]} names - The names of the terms to insert.
655
- * Could be either an array of names or a list separated by spaces.
656
- * @returns {calculator}
657
- * @fires termerror if a term to add is invalid
658
- * @fires termadd when a term has been added
711
+ * @event command-<name>
712
+ * @param {*} ... - additional params for the command
659
713
  */
660
- useTerms: function useTerms(names) {
661
- if ('string' === typeof names) {
662
- names = names.split(/\s+/);
663
- }
664
714
 
665
- _.forEach(names, this.useTerm.bind(this));
666
-
667
- return this;
668
- },
715
+ this.trigger.apply(this, ['command-' + name].concat([].slice.call(arguments, 1)));
716
+ return this;
717
+ },
669
718
 
719
+ /**
720
+ * Replaces the expression and move the cursor at the end.
721
+ * @param {String} newExpression - The new expression to set
722
+ * @param {Number|String} [newPosition=newExpression.length] - The new position to set
723
+ * @returns {calculator}
724
+ * @fires replace after the expression has been replaced
725
+ */
726
+ replace: function replace(newExpression, newPosition) {
727
+ var oldExpression = expression;
728
+ var oldPosition = position;
729
+ this.setExpression(newExpression).setPosition('undefined' !== typeof newPosition ? newPosition : expression.length);
670
730
  /**
671
- * Inserts a variable as a term in the expression at the current position
672
- * @param {String} name - The name of the variable to insert
673
- * @returns {calculator}
674
- * @fires termerror if the term to add is invalid
675
- * @fires termadd when the term has been added
731
+ * @event replace
732
+ * @param {String} expression - the replaced expression
733
+ * @param {Number} position - the replaced position
676
734
  */
677
- useVariable: function useVariable(name) {
678
- if (!variables.has(name)) {
679
- /**
680
- * @event termerror
681
- * @param {TypeError} err
682
- */
683
- return this.trigger('termerror', new TypeError('Invalid variable: ' + name));
684
- }
685
735
 
686
- return this.addTerm('VAR_' + name.toUpperCase(), {
687
- label: name,
688
- value: name,
689
- type: 'variable',
690
- description: __('Variable %s', name)
691
- });
692
- },
736
+ this.trigger('replace', oldExpression, oldPosition);
737
+ return this;
738
+ },
693
739
 
740
+ /**
741
+ * Inserts a sub-expression in the current expression and move the cursor.
742
+ * @param {String} subExpression - The sub-expression to insert
743
+ * @returns {calculator}
744
+ * @fires insert after the expression has been inserted
745
+ */
746
+ insert: function insert(subExpression) {
747
+ var oldExpression = expression;
748
+ var oldPosition = position;
749
+ this.setExpression(expression.substr(0, position) + subExpression + expression.substr(position)).setPosition(position + subExpression.length);
694
750
  /**
695
- * Calls a command
696
- * @param {String} name - The name of the called command
697
- * @param {*} ... - additional params for the command
698
- * @returns {calculator}
699
- * @fires command with the name and the parameters of the command
700
- * @fires command-<name> with the parameters of the command
701
- * @fires commanderror if the command is invalid
751
+ * @event insert
752
+ * @param {String} expression - the replaced expression
753
+ * @param {Number} position - the replaced position
702
754
  */
703
- useCommand: function useCommand(name) {
704
- if (!commands.has(name)) {
705
- /**
706
- * @event commanderror
707
- * @param {TypeError} err
708
- */
709
- return this.trigger('commanderror', new TypeError('Invalid command: ' + name));
710
- }
711
- /**
712
- * @event command
713
- * @param {String} name - The name of the called command
714
- * @param {*} ... - additional params for the command
715
- */
716
-
717
-
718
- this.trigger.apply(this, ['command'].concat([].slice.call(arguments)));
719
- /**
720
- * @event command-<name>
721
- * @param {*} ... - additional params for the command
722
- */
723
755
 
724
- this.trigger.apply(this, ['command-' + name].concat([].slice.call(arguments, 1)));
725
- return this;
726
- },
756
+ this.trigger('insert', oldExpression, oldPosition);
757
+ return this;
758
+ },
727
759
 
760
+ /**
761
+ * Clears the expression
762
+ * @returns {calculator}
763
+ * @fires clear after the expression has been cleared
764
+ */
765
+ clear: function clear() {
766
+ this.setExpression('').setPosition(0);
728
767
  /**
729
- * Replaces the expression and move the cursor at the end.
730
- * @param {String} newExpression - The new expression to set
731
- * @param {Number|String} [newPosition=newExpression.length] - The new position to set
732
- * @returns {calculator}
733
- * @fires replace after the expression has been replaced
768
+ * @event clear
734
769
  */
735
- replace: function replace(newExpression, newPosition) {
736
- var oldExpression = expression;
737
- var oldPosition = position;
738
- this.setExpression(newExpression).setPosition('undefined' !== typeof newPosition ? newPosition : expression.length);
739
- /**
740
- * @event replace
741
- * @param {String} expression - the replaced expression
742
- * @param {Number} position - the replaced position
743
- */
744
770
 
745
- this.trigger('replace', oldExpression, oldPosition);
746
- return this;
747
- },
771
+ this.trigger('clear');
772
+ return this;
773
+ },
748
774
 
749
- /**
750
- * Inserts a sub-expression in the current expression and move the cursor.
751
- * @param {String} subExpression - The sub-expression to insert
752
- * @returns {calculator}
753
- * @fires insert after the expression has been inserted
754
- */
755
- insert: function insert(subExpression) {
756
- var oldExpression = expression;
757
- var oldPosition = position;
758
- this.setExpression(expression.substr(0, position) + subExpression + expression.substr(position)).setPosition(position + subExpression.length);
775
+ /**
776
+ * Evaluates the current expression
777
+ * @returns {mathsExpression|null}
778
+ * @fires evaluate when the expression has been evaluated
779
+ * @fires syntaxerror when the expression contains an error
780
+ */
781
+ evaluate: function evaluate() {
782
+ var result = null;
783
+
784
+ try {
785
+ if (expression.trim()) {
786
+ result = mathsEvaluator(expression, _.mapValues(this.getVariables(), 'result'));
787
+ } else {
788
+ result = mathsEvaluator('0');
789
+ }
759
790
  /**
760
- * @event insert
761
- * @param {String} expression - the replaced expression
762
- * @param {Number} position - the replaced position
791
+ * @event evaluate
792
+ * @param {mathsExpression} result
763
793
  */
764
794
 
765
- this.trigger('insert', oldExpression, oldPosition);
766
- return this;
767
- },
768
795
 
769
- /**
770
- * Clears the expression
771
- * @returns {calculator}
772
- * @fires clear after the expression has been cleared
773
- */
774
- clear: function clear() {
775
- this.setExpression('').setPosition(0);
796
+ this.trigger('evaluate', result);
797
+ } catch (e) {
776
798
  /**
777
- * @event clear
799
+ * @event syntaxerror
800
+ * @param {Error} err
778
801
  */
802
+ this.trigger('syntaxerror', e);
803
+ }
779
804
 
780
- this.trigger('clear');
781
- return this;
782
- },
783
-
784
- /**
785
- * Evaluates the current expression
786
- * @returns {mathsExpression|null}
787
- * @fires evaluate when the expression has been evaluated
788
- * @fires syntaxerror when the expression contains an error
789
- */
790
- evaluate: function evaluate() {
791
- var result = null;
792
-
793
- try {
794
- if (expression.trim()) {
795
- result = mathsEvaluator(expression, _.mapValues(this.getVariables(), 'result'));
796
- } else {
797
- result = mathsEvaluator('0');
798
- }
799
- /**
800
- * @event evaluate
801
- * @param {mathsExpression} result
802
- */
803
-
804
-
805
- this.trigger('evaluate', result);
806
- } catch (e) {
807
- /**
808
- * @event syntaxerror
809
- * @param {Error} err
810
- */
811
- this.trigger('syntaxerror', e);
812
- }
813
-
814
- return result;
815
- },
816
-
817
- /**
818
- * Runs a method in all plugins
819
- *
820
- * @param {String} method - the method to run
821
- * @returns {Promise} once that resolve when all plugins are done
822
- */
823
- runPlugins: function runPlugins(method) {
824
- var execStack = [];
825
-
826
- _.forEach(plugins, function (plugin) {
827
- if (_.isFunction(plugin[method])) {
828
- execStack.push(plugin[method]());
829
- }
830
- });
831
-
832
- return Promise.all(execStack);
833
- },
834
-
835
- /**
836
- * Gets the calculator plugins
837
- * @returns {Array} the plugins
838
- */
839
- getPlugins: function getPlugins() {
840
- return _.toArray(plugins);
841
- },
805
+ return result;
806
+ },
842
807
 
843
- /**
844
- * Gets a plugin
845
- * @param {String} name - the plugin name
846
- * @returns {plugin} the plugin
847
- */
848
- getPlugin: function getPlugin(name) {
849
- return plugins[name];
850
- },
808
+ /**
809
+ * Runs a method in all plugins
810
+ *
811
+ * @param {String} method - the method to run
812
+ * @returns {Promise} once that resolve when all plugins are done
813
+ */
814
+ runPlugins: function runPlugins(method) {
815
+ var execStack = [];
851
816
 
852
- /**
853
- * Gets access to the areaBroker
854
- * @returns {areaBroker}
855
- */
856
- getAreaBroker: function getAreaBroker() {
857
- return areaBroker;
858
- },
817
+ _.forEach(plugins, function (plugin) {
818
+ if (_.isFunction(plugin[method])) {
819
+ execStack.push(plugin[method]());
820
+ }
821
+ });
859
822
 
860
- /**
861
- * Setups the maths evaluator
862
- * @returns {calculator}
863
- */
864
- setupMathsEvaluator: function setupMathsEvaluator() {
865
- mathsEvaluator = mathsEvaluatorFactory(this.getConfig().maths);
866
- return this;
867
- },
823
+ return Promise.all(execStack);
824
+ },
868
825
 
869
- /**
870
- * Gets access to the mathsEvaluator
871
- * @returns {Function}
872
- */
873
- getMathsEvaluator: function getMathsEvaluator() {
874
- return mathsEvaluator;
875
- }
876
- };
877
826
  /**
878
- * @typedef {component} calculator
827
+ * Gets the calculator plugins
828
+ * @returns {Array} the plugins
879
829
  */
830
+ getPlugins: function getPlugins() {
831
+ return _.toArray(plugins);
832
+ },
880
833
 
881
- var calculator = componentFactory(calculatorApi, defaultConfig).setTemplate(boardTpl).before('init', function () {
882
- this.setupMathsEvaluator();
883
- this.setLastResult('0');
884
-
885
- if (this.config.expression) {
886
- this.setExpression(this.config.expression);
887
- }
834
+ /**
835
+ * Gets a plugin
836
+ * @param {String} name - the plugin name
837
+ * @returns {plugin} the plugin
838
+ */
839
+ getPlugin: function getPlugin(name) {
840
+ return plugins[name];
841
+ },
888
842
 
889
- if (this.config.position) {
890
- this.setPosition(this.config.position);
891
- } // built-in commands
843
+ /**
844
+ * Gets access to the areaBroker
845
+ * @returns {areaBroker}
846
+ */
847
+ getAreaBroker: function getAreaBroker() {
848
+ return areaBroker;
849
+ },
892
850
 
851
+ /**
852
+ * Setups the maths evaluator
853
+ * @returns {calculator}
854
+ */
855
+ setupMathsEvaluator: function setupMathsEvaluator() {
856
+ mathsEvaluator = mathsEvaluatorFactory(this.getConfig().maths);
857
+ return this;
858
+ },
893
859
 
894
- this.setCommand('clear', __('Clear'), __('Clear expression')).setCommand('clearAll', __('Clear All'), __('Clear all data')).setCommand('execute', __('Execute'), __('Compute the expression')).setCommand('var', __('Variable'), __('Use a variable')).setCommand('term', __('Term'), __('Use a term')).on('command-term', this.useTerms.bind(this)).on('command-var', this.useVariable.bind(this)).on('command-execute', this.evaluate.bind(this)).on('command-clearAll', this.deleteVariables.bind(this)).on('command-clear command-clearAll', this.clear.bind(this));
895
- }).after('evaluate', function (result) {
896
- this.setLastResult(result);
897
- }).after('init', function () {
898
- this.render($container);
899
- }).before('render', function () {
900
- var self = this;
901
- var pluginsConfig = this.getConfig().plugins || {};
902
- var $element = this.getElement();
903
- areaBroker = areaBrokerFactory($element, {
904
- screen: $element.find('.screen'),
905
- // where the expressions and their result are rendered
906
- input: $element.find('.input'),
907
- // where the expressions are input
908
- keyboard: $element.find('.keyboard') // the keyboard area that should provide a way to interact with the calculator
860
+ /**
861
+ * Gets access to the mathsEvaluator
862
+ * @returns {Function}
863
+ */
864
+ getMathsEvaluator: function getMathsEvaluator() {
865
+ return mathsEvaluator;
866
+ }
867
+ };
868
+ /**
869
+ * @typedef {component} calculator
870
+ */
909
871
 
910
- });
872
+ var calculator = componentFactory(calculatorApi, defaultConfig).setTemplate(boardTpl).before('init', function () {
873
+ this.setupMathsEvaluator();
874
+ this.setLastResult('0');
875
+
876
+ if (this.config.expression) {
877
+ this.setExpression(this.config.expression);
878
+ }
879
+
880
+ if (this.config.position) {
881
+ this.setPosition(this.config.position);
882
+ } // built-in commands
883
+
884
+
885
+ this.setCommand('clear', __('Clear'), __('Clear expression')).setCommand('clearAll', __('Clear All'), __('Clear all data')).setCommand('execute', __('Execute'), __('Compute the expression')).setCommand('var', __('Variable'), __('Use a variable')).setCommand('term', __('Term'), __('Use a term')).on('command-term', this.useTerms.bind(this)).on('command-var', this.useVariable.bind(this)).on('command-execute', this.evaluate.bind(this)).on('command-clearAll', this.deleteVariables.bind(this)).on('command-clear command-clearAll', this.clear.bind(this));
886
+ }).after('evaluate', function (result) {
887
+ this.setLastResult(result);
888
+ }).after('init', function () {
889
+ this.render($container);
890
+ }).before('render', function () {
891
+ var self = this;
892
+ var pluginsConfig = this.getConfig().plugins || {};
893
+ var $element = this.getElement();
894
+ areaBroker = areaBrokerFactory($element, {
895
+ screen: $element.find('.screen'),
896
+ // where the expressions and their result are rendered
897
+ input: $element.find('.input'),
898
+ // where the expressions are input
899
+ keyboard: $element.find('.keyboard') // the keyboard area that should provide a way to interact with the calculator
911
900
 
912
- _.forEach(pluginFactories, function (pluginFactory) {
913
- var plugin = pluginFactory(self, self.getAreaBroker());
914
- var pluginName = plugin.getName();
901
+ });
915
902
 
916
- if (pluginsConfig[pluginName]) {
917
- plugin.setConfig(pluginsConfig[pluginName]);
918
- }
903
+ _.forEach(pluginFactories, function (pluginFactory) {
904
+ var plugin = pluginFactory(self, self.getAreaBroker());
905
+ var pluginName = plugin.getName();
919
906
 
920
- plugins[plugin.getName()] = plugin;
921
- });
907
+ if (pluginsConfig[pluginName]) {
908
+ plugin.setConfig(pluginsConfig[pluginName]);
909
+ }
922
910
 
923
- return this.runPlugins('install').then(function () {
924
- return self.runPlugins('init');
925
- }).then(function () {
926
- return self.runPlugins('render');
927
- }).then(function () {
928
- /**
929
- * @event ready
930
- */
931
- self.trigger('ready');
932
- }).catch(function (err) {
933
- self.trigger('error', err);
934
- });
935
- }).on('destroy', function () {
936
- var self = this;
937
- return this.runPlugins('destroy').then(function () {
938
- self.off('.' + ns);
939
- tokenizer = null;
940
- areaBroker = null;
941
- mathsEvaluator = null;
942
- variables.clear();
943
- plugins = {};
944
- });
911
+ plugins[plugin.getName()] = plugin;
945
912
  });
946
913
 
947
- _.defer(function () {
948
- calculator.init(config);
914
+ return this.runPlugins('install').then(function () {
915
+ return self.runPlugins('init');
916
+ }).then(function () {
917
+ return self.runPlugins('render');
918
+ }).then(function () {
919
+ /**
920
+ * @event ready
921
+ */
922
+ self.trigger('ready');
923
+ }).catch(function (err) {
924
+ self.trigger('error', err);
949
925
  });
926
+ }).on('destroy', function () {
927
+ var self = this;
928
+ return this.runPlugins('destroy').then(function () {
929
+ self.off('.' + ns);
930
+ tokenizer = null;
931
+ areaBroker = null;
932
+ mathsEvaluator = null;
933
+ variables.clear();
934
+ plugins = {};
935
+ });
936
+ });
937
+
938
+ _.defer(function () {
939
+ calculator.init(config);
940
+ });
950
941
 
951
- return calculator;
952
- }
942
+ return calculator;
943
+ }
953
944
 
954
- return calculatorBoardFactory;
945
+ return calculatorBoardFactory;
955
946
 
956
947
  });