@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.
- package/dist/actionbar.js +386 -395
- package/dist/adder.js +21 -19
- package/dist/animable/absorbable/absorbable.js +204 -213
- package/dist/animable/absorbable/css/absorb.css +1 -0
- package/dist/animable/absorbable/css/absorb.css.map +1 -1
- package/dist/animable/pulsable/pulsable.js +168 -177
- package/dist/autocomplete/css/autocomplete.css +1 -0
- package/dist/autocomplete/css/autocomplete.css.map +1 -1
- package/dist/autocomplete.js +68 -66
- package/dist/badge/badge.js +188 -197
- package/dist/badge/css/badge.css +1 -0
- package/dist/badge/css/badge.css.map +1 -1
- package/dist/breadcrumbs.js +275 -284
- package/dist/btngrouper.js +5 -5
- package/dist/bulkActionPopup.js +490 -495
- package/dist/button.js +283 -291
- package/dist/cascadingComboBox.js +249 -258
- package/dist/ckeditor/ckConfigurator.js +26 -19
- package/dist/ckeditor/dtdHandler.js +11 -9
- package/dist/class/selector.js +441 -450
- package/dist/component/resizable.js +1 -1
- package/dist/component/windowed.js +285 -294
- package/dist/component.js +419 -428
- package/dist/contextualPopup.js +417 -426
- package/dist/dashboard.js +300 -309
- package/dist/datalist.js +753 -762
- package/dist/datatable/filterStrategy/multiple.js +1 -1
- package/dist/datatable/filterStrategy/single.js +1 -1
- package/dist/datatable.js +1527 -1550
- package/dist/dateRange/dateRange.js +393 -402
- package/dist/datetime/picker.js +665 -672
- package/dist/deleter.js +368 -377
- package/dist/destination/selector.js +286 -295
- package/dist/dialog/alert.js +3 -3
- package/dist/dialog/confirm.js +1 -1
- package/dist/dialog/confirmDelete.js +216 -225
- package/dist/dialog.js +650 -654
- package/dist/disabler.js +8 -8
- package/dist/documentViewer/providers/pdfViewer/fallback/viewer.js +166 -175
- package/dist/documentViewer/providers/pdfViewer/pdfjs/findBar.js +518 -527
- package/dist/documentViewer/providers/pdfViewer/pdfjs/pageView.js +380 -389
- package/dist/documentViewer/providers/pdfViewer/pdfjs/searchEngine.js +539 -548
- package/dist/documentViewer/providers/pdfViewer/pdfjs/viewer.js +369 -378
- package/dist/documentViewer/providers/pdfViewer.js +184 -193
- package/dist/documentViewer.js +292 -301
- package/dist/dropdown.js +383 -392
- package/dist/durationer.js +5 -5
- package/dist/dynamicComponent.js +597 -598
- package/dist/feedback.js +356 -362
- package/dist/figure/FigureStateActive.js +117 -108
- package/dist/filesender.js +2 -2
- package/dist/filter.js +230 -239
- package/dist/form/dropdownForm.js +355 -357
- package/dist/form/form.js +919 -690
- package/dist/form/simpleForm.js +1 -1
- package/dist/form/validator/renderer.js +233 -235
- package/dist/form/validator/validator.js +257 -189
- package/dist/form/widget/definitions.js +1 -1
- package/dist/form/widget/providers/checkBox.js +254 -259
- package/dist/form/widget/providers/comboBox.js +187 -192
- package/dist/form/widget/providers/default.js +8 -9
- package/dist/form/widget/providers/hidden.js +170 -179
- package/dist/form/widget/providers/hiddenBox.js +262 -267
- package/dist/form/widget/providers/radioBox.js +216 -225
- package/dist/form/widget/providers/textArea.js +187 -196
- package/dist/form/widget/providers/textBox.js +2 -3
- package/dist/form/widget/widget.js +473 -475
- package/dist/formValidator/formValidator.js +1 -1
- package/dist/formValidator/highlighters/message.js +1 -1
- package/dist/generis/form/form.js +314 -323
- package/dist/generis/validator/validator.js +209 -218
- package/dist/generis/widget/checkBox/checkBox.js +218 -227
- package/dist/generis/widget/comboBox/comboBox.js +179 -188
- package/dist/generis/widget/hiddenBox/hiddenBox.js +220 -229
- package/dist/generis/widget/textBox/textBox.js +169 -178
- package/dist/generis/widget/widget.js +246 -255
- package/dist/groupedComboBox.js +222 -231
- package/dist/groupvalidator.js +2 -2
- package/dist/highlighter.js +967 -958
- package/dist/image/ImgStateActive/helper.js +7 -5
- package/dist/image/ImgStateActive/initHelper.js +49 -43
- package/dist/image/ImgStateActive/initMediaEditor.js +24 -20
- package/dist/image/ImgStateActive/mediaSizer.js +14 -12
- package/dist/image/ImgStateActive.js +72 -70
- package/dist/incrementer.js +6 -6
- package/dist/inplacer.js +6 -6
- package/dist/itemButtonList/css/item-button-list.css +1 -0
- package/dist/itemButtonList/css/item-button-list.css.map +1 -1
- package/dist/itemButtonList.js +439 -435
- package/dist/keyNavigation/navigableDomElement.js +51 -38
- package/dist/keyNavigation/navigator.js +85 -70
- package/dist/listbox.js +460 -469
- package/dist/liststyler.js +8 -8
- package/dist/loadingButton/loadingButton.js +209 -218
- package/dist/lock.js +476 -485
- package/dist/login/login.js +475 -484
- package/dist/maths/calculator/basicCalculator.js +235 -244
- package/dist/maths/calculator/calculatorComponent.js +3 -3
- package/dist/maths/calculator/core/board.js +772 -781
- package/dist/maths/calculator/core/expression.js +476 -485
- package/dist/maths/calculator/core/labels.js +228 -237
- package/dist/maths/calculator/core/tokenizer.js +1 -1
- package/dist/maths/calculator/core/tokens.js +163 -170
- package/dist/maths/calculator/plugins/keyboard/templateKeyboard/templateKeyboard.js +244 -253
- package/dist/maths/calculator/plugins/screen/simpleScreen/simpleScreen.js +279 -288
- package/dist/maths/calculator/scientificCalculator.js +327 -336
- package/dist/mediaEditor/mediaEditorComponent.js +238 -245
- package/dist/mediaEditor/plugins/mediaAlignment/helper.js +7 -7
- package/dist/mediaEditor/plugins/mediaAlignment/mediaAlignmentComponent.js +229 -235
- package/dist/mediaEditor/plugins/mediaDimension/mediaDimensionComponent.js +580 -589
- package/dist/mediaplayer/players/html5.js +666 -675
- package/dist/mediaplayer/players/youtube.js +419 -424
- package/dist/mediaplayer/support.js +11 -10
- package/dist/mediaplayer/utils/reminder.js +14 -13
- package/dist/mediaplayer/utils/timeObserver.js +10 -11
- package/dist/mediaplayer/youtubeManager.js +164 -145
- package/dist/mediaplayer.js +1565 -1520
- package/dist/mediasizer.js +669 -678
- package/dist/modal.js +10 -17
- package/dist/pageSizeSelector.js +219 -228
- package/dist/pagination/providers/pages.js +280 -289
- package/dist/pagination/providers/simple.js +192 -201
- package/dist/previewer.js +30 -30
- package/dist/progressbar.js +4 -4
- package/dist/report.js +347 -356
- package/dist/resource/filters.js +271 -280
- package/dist/resource/list.js +1264 -1273
- package/dist/resource/selector.js +865 -874
- package/dist/resource/tree.js +1483 -1492
- package/dist/resourcemgr/fileBrowser.js +564 -569
- package/dist/resourcemgr/filePreview.js +16 -16
- package/dist/resourcemgr/fileSelector.js +515 -524
- package/dist/resourcemgr/util/updatePermissions.js +2 -2
- package/dist/resourcemgr.js +306 -315
- package/dist/searchModal/advancedSearch.js +796 -767
- package/dist/searchModal.js +114 -91
- package/dist/switch/switch.js +298 -307
- package/dist/tabs.js +598 -575
- package/dist/taskQueue/status.js +312 -321
- package/dist/taskQueue/table.js +375 -384
- package/dist/taskQueue/taskQueueModel.js +488 -472
- package/dist/taskQueueButton/taskable.js +264 -273
- package/dist/taskQueueButton/treeButton.js +189 -198
- package/dist/themeLoader.js +24 -23
- package/dist/themes.js +1 -1
- package/dist/toggler.js +3 -3
- package/dist/tooltip.js +295 -304
- package/dist/transformer.js +2 -2
- package/dist/tristateCheckboxGroup.js +311 -320
- package/dist/uploader.js +687 -696
- package/dist/validator/Report.js +1 -1
- package/dist/validator/Validator.js +3 -3
- package/dist/validator/validators.js +9 -9
- package/dist/validator.js +240 -230
- package/dist/waitForMedia.js +1 -1
- package/package.json +3 -3
- package/src/animable/absorbable/css/absorb.css +1 -0
- package/src/animable/absorbable/css/absorb.css.map +1 -1
- package/src/autocomplete/css/autocomplete.css +1 -0
- package/src/autocomplete/css/autocomplete.css.map +1 -1
- package/src/badge/css/badge.css +1 -0
- package/src/badge/css/badge.css.map +1 -1
- package/src/ckeditor/ckConfigurator.js +4 -0
- package/src/itemButtonList/css/item-button-list.css +1 -0
- package/src/itemButtonList/css/item-button-list.css.map +1 -1
- package/src/.DS_Store +0 -0
- package/src/css/basic.css +0 -7826
- package/src/css/basic.css.map +0 -1
- package/src/css/ckeditor/skins/tao/css/dialog.css +0 -950
- package/src/css/ckeditor/skins/tao/css/dialog.css.map +0 -1
- package/src/css/ckeditor/skins/tao/css/editor.css +0 -1850
- package/src/css/ckeditor/skins/tao/css/editor.css.map +0 -1
- package/src/scss/.DS_Store +0 -0
- package/src/scss/basic.scss +0 -16
- package/src/scss/ckeditor/skins/tao/scss/dialog.scss +0 -763
- package/src/scss/ckeditor/skins/tao/scss/editor.scss +0 -111
- package/src/scss/ckeditor/skins/tao/scss/inc/_ck-icons.scss +0 -59
- package/src/scss/ckeditor/skins/tao/scss/inc/_colorpanel.scss +0 -118
- package/src/scss/ckeditor/skins/tao/scss/inc/_elementspath.scss +0 -69
- package/src/scss/ckeditor/skins/tao/scss/inc/_mainui.scss +0 -194
- package/src/scss/ckeditor/skins/tao/scss/inc/_menu.scss +0 -181
- package/src/scss/ckeditor/skins/tao/scss/inc/_panel.scss +0 -200
- package/src/scss/ckeditor/skins/tao/scss/inc/_presets.scss +0 -32
- package/src/scss/ckeditor/skins/tao/scss/inc/_reset.scss +0 -101
- package/src/scss/ckeditor/skins/tao/scss/inc/_richcombo.scss +0 -213
- package/src/scss/ckeditor/skins/tao/scss/inc/_tao.scss +0 -59
- package/src/scss/ckeditor/skins/tao/scss/inc/_toolbar.scss +0 -301
- package/src/scss/font/source-sans-pro/source-sans-pro-italic.eot +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-italic.eot.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-italic.woff +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-italic.woff.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-regular.eot +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-regular.eot.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-regular.woff +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-regular.woff.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.eot +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.eot.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.woff +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold-italic.woff.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold.eot +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold.eot.b64 +0 -1
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold.woff +0 -0
- package/src/scss/font/source-sans-pro/source-sans-pro-semibold.woff.b64 +0 -1
- package/src/scss/font/tao/tao.eot +0 -0
- package/src/scss/font/tao/tao.svg +0 -235
- package/src/scss/font/tao/tao.ttf +0 -0
- package/src/scss/font/tao/tao.woff +0 -0
- package/src/scss/inc/_base.scss +0 -496
- package/src/scss/inc/_bootstrap.scss +0 -6
- package/src/scss/inc/_buttons.scss +0 -114
- package/src/scss/inc/_colors.scss +0 -88
- package/src/scss/inc/_feedback.scss +0 -150
- package/src/scss/inc/_flex-grid.scss +0 -15
- package/src/scss/inc/_fonts.scss +0 -4
- package/src/scss/inc/_forms.scss +0 -827
- package/src/scss/inc/_functions.scss +0 -283
- package/src/scss/inc/_grid.scss +0 -66
- package/src/scss/inc/_jquery.nouislider.scss +0 -254
- package/src/scss/inc/_normalize.scss +0 -528
- package/src/scss/inc/_report.scss +0 -68
- package/src/scss/inc/_secondary-properties.scss +0 -89
- package/src/scss/inc/_select2.scss +0 -634
- package/src/scss/inc/_toolbars.scss +0 -155
- package/src/scss/inc/_tooltip.scss +0 -312
- package/src/scss/inc/_variables.scss +0 -21
- package/src/scss/inc/base/_highlight.scss +0 -5
- package/src/scss/inc/base/_list-style.scss +0 -59
- package/src/scss/inc/base/_svg.scss +0 -3
- package/src/scss/inc/base/_table.scss +0 -63
- package/src/scss/inc/fonts/_source-sans-pro.scss +0 -29
- package/src/scss/inc/fonts/_tao-icon-classes.scss +0 -226
- package/src/scss/inc/fonts/_tao-icon-def.scss +0 -12
- 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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
84
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
92
|
-
var
|
|
93
|
-
startIndex = parseInt(startIndex);
|
|
94
|
-
stopIndex = parseInt(stopIndex);
|
|
95
|
-
increment = parseInt(increment);
|
|
57
|
+
_.forIn(arr, function (value, key) {
|
|
58
|
+
var fragment = '';
|
|
96
59
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
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
|
-
|
|
120
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
205
|
+
var plugins = {};
|
|
206
|
+
/**
|
|
207
|
+
* The current expression
|
|
208
|
+
* @type {String}
|
|
209
|
+
*/
|
|
141
210
|
|
|
211
|
+
var expression = '';
|
|
142
212
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
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
|
-
*
|
|
161
|
-
* @type {
|
|
219
|
+
* A list of registered commands that can be used inside the calculator
|
|
220
|
+
* @type {Map}
|
|
162
221
|
*/
|
|
163
222
|
|
|
164
|
-
var
|
|
165
|
-
expression: '',
|
|
166
|
-
position: 0
|
|
167
|
-
};
|
|
223
|
+
var commands = new collections.Map();
|
|
168
224
|
/**
|
|
169
|
-
*
|
|
170
|
-
* @type {
|
|
225
|
+
* The current position in the current expression (i.e. the position of the caret)
|
|
226
|
+
* @type {Number}
|
|
171
227
|
*/
|
|
172
228
|
|
|
173
|
-
var
|
|
229
|
+
var position = 0;
|
|
174
230
|
/**
|
|
175
|
-
*
|
|
176
|
-
* @type {
|
|
231
|
+
* The tokenizer utilized to split down the expression
|
|
232
|
+
* @type {calculatorTokenizer}
|
|
177
233
|
*/
|
|
178
234
|
|
|
179
|
-
var
|
|
235
|
+
var tokenizer = tokenizerFactory();
|
|
180
236
|
/**
|
|
181
|
-
* The
|
|
182
|
-
* @type {
|
|
237
|
+
* The list of tokens extracted from the expression
|
|
238
|
+
* @type {Array|null}
|
|
183
239
|
*/
|
|
184
240
|
|
|
185
|
-
var
|
|
241
|
+
var tokens = null;
|
|
186
242
|
/**
|
|
187
|
-
*
|
|
188
|
-
* @
|
|
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
|
-
|
|
247
|
+
var calculatorApi = {
|
|
199
248
|
/**
|
|
200
|
-
*
|
|
201
|
-
* @
|
|
249
|
+
* Returns the current expression
|
|
250
|
+
* @returns {String}
|
|
202
251
|
*/
|
|
203
|
-
|
|
252
|
+
getExpression: function getExpression() {
|
|
253
|
+
return expression;
|
|
254
|
+
},
|
|
255
|
+
|
|
204
256
|
/**
|
|
205
|
-
*
|
|
206
|
-
* @
|
|
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
|
-
*
|
|
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
|
-
*
|
|
217
|
-
* @
|
|
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
|
-
*
|
|
223
|
-
* @
|
|
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
|
-
*
|
|
229
|
-
* @
|
|
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
|
-
*
|
|
235
|
-
* @
|
|
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
|
-
*
|
|
241
|
-
* @
|
|
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
|
-
*
|
|
247
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
-
*
|
|
267
|
-
* @param {String}
|
|
268
|
-
* @
|
|
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
|
-
|
|
280
|
-
|
|
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
|
-
*
|
|
285
|
-
* @
|
|
401
|
+
* @event variabledelete
|
|
402
|
+
* @param {String} name
|
|
286
403
|
*/
|
|
287
|
-
getPosition: function getPosition() {
|
|
288
|
-
return position;
|
|
289
|
-
},
|
|
290
404
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
|
|
305
|
-
|
|
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
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
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
|
-
|
|
318
|
-
|
|
430
|
+
_.forEach(defs, function (value, name) {
|
|
431
|
+
self.setVariable(name, value);
|
|
432
|
+
});
|
|
319
433
|
|
|
320
|
-
|
|
321
|
-
|
|
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
|
-
*
|
|
332
|
-
* @
|
|
445
|
+
* @event variabledelete
|
|
446
|
+
* @param {null} name
|
|
333
447
|
*/
|
|
334
|
-
getTokenIndex: function getTokenIndex() {
|
|
335
|
-
var index = 0;
|
|
336
448
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
});
|
|
449
|
+
this.trigger('variabledelete', null);
|
|
450
|
+
this.setLastResult('0');
|
|
451
|
+
return this;
|
|
452
|
+
},
|
|
342
453
|
|
|
343
|
-
|
|
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
|
-
|
|
348
|
-
|
|
349
|
-
*/
|
|
350
|
-
getTokenizer: function getTokenizer() {
|
|
351
|
-
return tokenizer;
|
|
352
|
-
},
|
|
464
|
+
this.setVariable(lastResultVariableName, result);
|
|
465
|
+
return this;
|
|
466
|
+
},
|
|
353
467
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
374
|
-
|
|
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
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
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
|
-
|
|
415
|
-
|
|
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
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
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
|
-
*
|
|
432
|
-
* @param {
|
|
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
|
-
|
|
440
|
-
|
|
441
|
-
|
|
541
|
+
this.trigger('commanddelete', name);
|
|
542
|
+
return this;
|
|
543
|
+
},
|
|
442
544
|
|
|
443
|
-
|
|
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
|
|
455
|
-
* @param {
|
|
567
|
+
* @event termerror
|
|
568
|
+
* @param {TypeError} err
|
|
456
569
|
*/
|
|
570
|
+
return this.trigger('termerror', new TypeError('Invalid term: ' + name));
|
|
571
|
+
}
|
|
457
572
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
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
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
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
|
-
|
|
487
|
-
|
|
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
|
-
|
|
510
|
-
|
|
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
|
-
*
|
|
518
|
-
* @
|
|
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
|
-
*
|
|
539
|
-
* @param {
|
|
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
|
-
|
|
551
|
-
|
|
552
|
-
|
|
610
|
+
this.trigger('termadd-' + name, term);
|
|
611
|
+
return this;
|
|
612
|
+
},
|
|
553
613
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
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
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
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
|
-
|
|
583
|
-
|
|
584
|
-
|
|
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
|
-
|
|
587
|
-
|
|
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
|
-
|
|
595
|
-
|
|
596
|
-
|
|
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
|
-
|
|
600
|
-
|
|
601
|
-
}
|
|
602
|
-
}
|
|
658
|
+
return this;
|
|
659
|
+
},
|
|
603
660
|
|
|
604
|
-
|
|
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
|
|
608
|
-
* @param {
|
|
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
|
-
|
|
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
|
|
616
|
-
* @param {
|
|
697
|
+
* @event commanderror
|
|
698
|
+
* @param {TypeError} err
|
|
617
699
|
*/
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
return this;
|
|
621
|
-
},
|
|
622
|
-
|
|
700
|
+
return this.trigger('commanderror', new TypeError('Invalid command: ' + name));
|
|
701
|
+
}
|
|
623
702
|
/**
|
|
624
|
-
*
|
|
625
|
-
* @param {String} name - The name of the
|
|
626
|
-
* @
|
|
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
|
-
*
|
|
654
|
-
* @param {
|
|
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
|
-
|
|
666
|
-
|
|
667
|
-
|
|
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
|
-
*
|
|
672
|
-
* @param {String}
|
|
673
|
-
* @
|
|
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
|
-
|
|
687
|
-
|
|
688
|
-
|
|
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
|
-
*
|
|
696
|
-
* @param {String}
|
|
697
|
-
* @param {
|
|
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
|
-
|
|
725
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
746
|
-
|
|
747
|
-
|
|
771
|
+
this.trigger('clear');
|
|
772
|
+
return this;
|
|
773
|
+
},
|
|
748
774
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
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
|
|
761
|
-
* @param {
|
|
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
|
-
|
|
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
|
|
799
|
+
* @event syntaxerror
|
|
800
|
+
* @param {Error} err
|
|
778
801
|
*/
|
|
802
|
+
this.trigger('syntaxerror', e);
|
|
803
|
+
}
|
|
779
804
|
|
|
780
|
-
|
|
781
|
-
|
|
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
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
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
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
827
|
+
* Gets the calculator plugins
|
|
828
|
+
* @returns {Array} the plugins
|
|
879
829
|
*/
|
|
830
|
+
getPlugins: function getPlugins() {
|
|
831
|
+
return _.toArray(plugins);
|
|
832
|
+
},
|
|
880
833
|
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
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
|
-
|
|
890
|
-
|
|
891
|
-
|
|
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
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
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
|
-
|
|
913
|
-
var plugin = pluginFactory(self, self.getAreaBroker());
|
|
914
|
-
var pluginName = plugin.getName();
|
|
901
|
+
});
|
|
915
902
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
903
|
+
_.forEach(pluginFactories, function (pluginFactory) {
|
|
904
|
+
var plugin = pluginFactory(self, self.getAreaBroker());
|
|
905
|
+
var pluginName = plugin.getName();
|
|
919
906
|
|
|
920
|
-
|
|
921
|
-
|
|
907
|
+
if (pluginsConfig[pluginName]) {
|
|
908
|
+
plugin.setConfig(pluginsConfig[pluginName]);
|
|
909
|
+
}
|
|
922
910
|
|
|
923
|
-
|
|
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
|
-
|
|
948
|
-
|
|
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
|
-
|
|
952
|
-
|
|
942
|
+
return calculator;
|
|
943
|
+
}
|
|
953
944
|
|
|
954
|
-
|
|
945
|
+
return calculatorBoardFactory;
|
|
955
946
|
|
|
956
947
|
});
|