@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,597 +1,588 @@
|
|
|
1
1
|
define(['lodash', 'ui/maths/calculator/core/terms', 'ui/maths/calculator/core/tokens', 'ui/maths/calculator/core/tokenizer', 'handlebars', 'i18n', 'lib/dompurify/purify'], function (_, registeredTerms, tokensHelper, tokenizerFactory, Handlebars, __, DOMPurify) { 'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
_ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
|
|
4
|
+
registeredTerms = registeredTerms && Object.prototype.hasOwnProperty.call(registeredTerms, 'default') ? registeredTerms['default'] : registeredTerms;
|
|
5
|
+
tokensHelper = tokensHelper && Object.prototype.hasOwnProperty.call(tokensHelper, 'default') ? tokensHelper['default'] : tokensHelper;
|
|
6
|
+
tokenizerFactory = tokenizerFactory && Object.prototype.hasOwnProperty.call(tokenizerFactory, 'default') ? tokenizerFactory['default'] : tokenizerFactory;
|
|
7
|
+
Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
|
|
8
|
+
__ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
|
|
9
|
+
DOMPurify = DOMPurify && Object.prototype.hasOwnProperty.call(DOMPurify, 'default') ? DOMPurify['default'] : DOMPurify;
|
|
10
|
+
|
|
11
|
+
function _typeof(obj) {
|
|
12
|
+
"@babel/helpers - typeof";
|
|
13
|
+
|
|
14
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
|
|
15
|
+
return typeof obj;
|
|
16
|
+
} : function (obj) {
|
|
17
|
+
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
18
|
+
}, _typeof(obj);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function Helpers0 (hb) {
|
|
22
|
+
//register a i18n helper
|
|
23
|
+
hb.registerHelper('__', function (key) {
|
|
24
|
+
return __(key);
|
|
25
|
+
});
|
|
11
26
|
/**
|
|
12
|
-
*
|
|
13
|
-
* modify it under the terms of the GNU General Public License
|
|
14
|
-
* as published by the Free Software Foundation; under version 2
|
|
15
|
-
* of the License (non-upgradable).
|
|
16
|
-
*
|
|
17
|
-
* This program is distributed in the hope that it will be useful,
|
|
18
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
19
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
20
|
-
* GNU General Public License for more details.
|
|
21
|
-
*
|
|
22
|
-
* You should have received a copy of the GNU General Public License
|
|
23
|
-
* along with this program; if not, write to the Free Software
|
|
24
|
-
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
25
|
-
*
|
|
26
|
-
* Copyright (c) 2013-2019 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
|
|
27
|
-
*
|
|
27
|
+
* Register dompurify helper
|
|
28
28
|
*
|
|
29
|
+
* https://github.com/cure53/DOMPurify
|
|
30
|
+
* with config SAFE_FOR_TEMPLATES: true
|
|
31
|
+
* to make output safe for template systems
|
|
29
32
|
*/
|
|
30
|
-
function Helpers0 (hb) {
|
|
31
|
-
//register a i18n helper
|
|
32
|
-
hb.registerHelper('__', function (key) {
|
|
33
|
-
return __(key);
|
|
34
|
-
});
|
|
35
|
-
/**
|
|
36
|
-
* Register dompurify helper
|
|
37
|
-
*
|
|
38
|
-
* https://github.com/cure53/DOMPurify
|
|
39
|
-
* with config SAFE_FOR_TEMPLATES: true
|
|
40
|
-
* to make output safe for template systems
|
|
41
|
-
*/
|
|
42
|
-
|
|
43
|
-
hb.registerHelper('dompurify', function (context) {
|
|
44
|
-
return DOMPurify.sanitize(context);
|
|
45
|
-
});
|
|
46
|
-
/**
|
|
47
|
-
* Register join helper
|
|
48
|
-
*
|
|
49
|
-
* Example :
|
|
50
|
-
* var values = {a:v1, b:v2, c:v3};
|
|
51
|
-
* Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
|
|
52
|
-
* Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
|
|
53
|
-
*/
|
|
54
33
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
34
|
+
hb.registerHelper('dompurify', function (context) {
|
|
35
|
+
return DOMPurify.sanitize(context);
|
|
36
|
+
});
|
|
37
|
+
/**
|
|
38
|
+
* Register join helper
|
|
39
|
+
*
|
|
40
|
+
* Example :
|
|
41
|
+
* var values = {a:v1, b:v2, c:v3};
|
|
42
|
+
* Using {{{join attributes '=' ' ' '"'}}} will return : a="v1" b="v2" c="v3"
|
|
43
|
+
* Using {{{join values null ' or ' '*'}}} will return : *v1* or *v2* or *v3*
|
|
44
|
+
*/
|
|
60
45
|
|
|
61
|
-
|
|
62
|
-
|
|
46
|
+
hb.registerHelper('join', function (arr, keyValueGlue, fragmentGlue, wrapper) {
|
|
47
|
+
var fragments = [];
|
|
48
|
+
keyValueGlue = typeof keyValueGlue === 'string' ? keyValueGlue : undefined;
|
|
49
|
+
fragmentGlue = typeof fragmentGlue === 'string' ? fragmentGlue : ' ';
|
|
50
|
+
wrapper = typeof wrapper === 'string' ? wrapper : '"';
|
|
63
51
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
value = value ? 'true' : 'false';
|
|
67
|
-
} else if (typeof value === 'object') {
|
|
68
|
-
value = _.values(value).join(' ');
|
|
69
|
-
}
|
|
70
|
-
} else {
|
|
71
|
-
value = '';
|
|
72
|
-
}
|
|
52
|
+
_.forIn(arr, function (value, key) {
|
|
53
|
+
var fragment = '';
|
|
73
54
|
|
|
74
|
-
|
|
75
|
-
|
|
55
|
+
if (value !== null || value !== undefined) {
|
|
56
|
+
if (typeof value === 'boolean') {
|
|
57
|
+
value = value ? 'true' : 'false';
|
|
58
|
+
} else if (_typeof(value) === 'object') {
|
|
59
|
+
value = _.values(value).join(' ');
|
|
76
60
|
}
|
|
61
|
+
} else {
|
|
62
|
+
value = '';
|
|
63
|
+
}
|
|
77
64
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
return fragments.join(fragmentGlue);
|
|
83
|
-
}); //register a classic "for loop" helper
|
|
84
|
-
//it also adds a local variable "i" as the index in each iteration loop
|
|
85
|
-
|
|
86
|
-
hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
|
|
87
|
-
var ret = '';
|
|
88
|
-
startIndex = parseInt(startIndex);
|
|
89
|
-
stopIndex = parseInt(stopIndex);
|
|
90
|
-
increment = parseInt(increment);
|
|
91
|
-
|
|
92
|
-
for (var i = startIndex; i < stopIndex; i += increment) {
|
|
93
|
-
ret += options.fn(_.extend({}, this, {
|
|
94
|
-
i: i
|
|
95
|
-
}));
|
|
65
|
+
if (keyValueGlue !== undefined) {
|
|
66
|
+
fragment += key + keyValueGlue;
|
|
96
67
|
}
|
|
97
68
|
|
|
98
|
-
|
|
69
|
+
fragment += wrapper + value + wrapper;
|
|
70
|
+
fragments.push(fragment);
|
|
99
71
|
});
|
|
100
|
-
hb.registerHelper('equal', function (var1, var2, options) {
|
|
101
|
-
if (var1 == var2) {
|
|
102
|
-
return options.fn(this);
|
|
103
|
-
} else {
|
|
104
|
-
return options.inverse(this);
|
|
105
|
-
}
|
|
106
|
-
}); // register a "get property" helper
|
|
107
|
-
// it gets the named property from the provided context
|
|
108
72
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
// it checks if value is in array
|
|
73
|
+
return fragments.join(fragmentGlue);
|
|
74
|
+
}); //register a classic "for loop" helper
|
|
75
|
+
//it also adds a local variable "i" as the index in each iteration loop
|
|
113
76
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
77
|
+
hb.registerHelper('for', function (startIndex, stopIndex, increment, options) {
|
|
78
|
+
var ret = '';
|
|
79
|
+
startIndex = parseInt(startIndex);
|
|
80
|
+
stopIndex = parseInt(stopIndex);
|
|
81
|
+
increment = parseInt(increment);
|
|
120
82
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
|
|
126
|
-
this.compilerInfo = [4,'>= 1.0.0'];
|
|
127
|
-
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
|
|
128
|
-
var stack1, self=this, functionType="function", escapeExpression=this.escapeExpression;
|
|
129
|
-
|
|
130
|
-
function program1(depth0,data) {
|
|
131
|
-
|
|
132
|
-
var buffer = "", stack1, helper;
|
|
133
|
-
stack1 = helpers.each.call(depth0, (depth0 && depth0.startExponent), {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data});
|
|
134
|
-
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
135
|
-
buffer += "<span class=\"term term-";
|
|
136
|
-
if (helper = helpers.type) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
137
|
-
else { helper = (depth0 && depth0.type); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
138
|
-
buffer += escapeExpression(stack1);
|
|
139
|
-
stack1 = helpers['if'].call(depth0, (depth0 && depth0.elide), {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
|
|
140
|
-
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
141
|
-
buffer += "\" data-value=\"";
|
|
142
|
-
if (helper = helpers.value) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
143
|
-
else { helper = (depth0 && depth0.value); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
144
|
-
buffer += escapeExpression(stack1)
|
|
145
|
-
+ "\" data-token=\"";
|
|
146
|
-
if (helper = helpers.token) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
147
|
-
else { helper = (depth0 && depth0.token); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
148
|
-
buffer += escapeExpression(stack1)
|
|
149
|
-
+ "\" data-type=\"";
|
|
150
|
-
if (helper = helpers.type) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
151
|
-
else { helper = (depth0 && depth0.type); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
152
|
-
buffer += escapeExpression(stack1)
|
|
153
|
-
+ "\">";
|
|
154
|
-
if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
155
|
-
else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
156
|
-
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
157
|
-
buffer += "</span>";
|
|
158
|
-
stack1 = helpers.each.call(depth0, (depth0 && depth0.endExponent), {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data});
|
|
159
|
-
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
160
|
-
return buffer;
|
|
161
|
-
}
|
|
162
|
-
function program2(depth0,data) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return "<sup>";
|
|
83
|
+
for (var i = startIndex; i < stopIndex; i += increment) {
|
|
84
|
+
ret += options.fn(_.extend({}, this, {
|
|
85
|
+
i: i
|
|
86
|
+
}));
|
|
166
87
|
}
|
|
167
88
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
89
|
+
return ret;
|
|
90
|
+
});
|
|
91
|
+
hb.registerHelper('equal', function (var1, var2, options) {
|
|
92
|
+
if (var1 == var2) {
|
|
93
|
+
return options.fn(this);
|
|
94
|
+
} else {
|
|
95
|
+
return options.inverse(this);
|
|
172
96
|
}
|
|
97
|
+
}); // register a "get property" helper
|
|
98
|
+
// it gets the named property from the provided context
|
|
173
99
|
|
|
174
|
-
function
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
100
|
+
hb.registerHelper('property', function (name, context) {
|
|
101
|
+
return context[name] || '';
|
|
102
|
+
}); // register an 'includes' helper
|
|
103
|
+
// it checks if value is in array
|
|
104
|
+
|
|
105
|
+
hb.registerHelper('includes', function (haystack, needle, options) {
|
|
106
|
+
if (_.contains(haystack, needle)) {
|
|
107
|
+
return options.fn(this);
|
|
178
108
|
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!Helpers0.__initialized) {
|
|
113
|
+
Helpers0(Handlebars);
|
|
114
|
+
Helpers0.__initialized = true;
|
|
115
|
+
}
|
|
116
|
+
var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
|
|
117
|
+
this.compilerInfo = [4,'>= 1.0.0'];
|
|
118
|
+
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
|
|
119
|
+
var stack1, self=this, functionType="function", escapeExpression=this.escapeExpression;
|
|
120
|
+
|
|
121
|
+
function program1(depth0,data) {
|
|
122
|
+
|
|
123
|
+
var buffer = "", stack1, helper;
|
|
124
|
+
stack1 = helpers.each.call(depth0, (depth0 && depth0.startExponent), {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data});
|
|
125
|
+
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
126
|
+
buffer += "<span class=\"term term-";
|
|
127
|
+
if (helper = helpers.type) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
128
|
+
else { helper = (depth0 && depth0.type); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
129
|
+
buffer += escapeExpression(stack1);
|
|
130
|
+
stack1 = helpers['if'].call(depth0, (depth0 && depth0.elide), {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
|
|
131
|
+
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
132
|
+
buffer += "\" data-value=\"";
|
|
133
|
+
if (helper = helpers.value) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
134
|
+
else { helper = (depth0 && depth0.value); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
135
|
+
buffer += escapeExpression(stack1)
|
|
136
|
+
+ "\" data-token=\"";
|
|
137
|
+
if (helper = helpers.token) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
138
|
+
else { helper = (depth0 && depth0.token); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
139
|
+
buffer += escapeExpression(stack1)
|
|
140
|
+
+ "\" data-type=\"";
|
|
141
|
+
if (helper = helpers.type) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
142
|
+
else { helper = (depth0 && depth0.type); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
143
|
+
buffer += escapeExpression(stack1)
|
|
144
|
+
+ "\">";
|
|
145
|
+
if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
|
|
146
|
+
else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
|
|
147
|
+
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
148
|
+
buffer += "</span>";
|
|
149
|
+
stack1 = helpers.each.call(depth0, (depth0 && depth0.endExponent), {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data});
|
|
150
|
+
if(stack1 || stack1 === 0) { buffer += stack1; }
|
|
151
|
+
return buffer;
|
|
152
|
+
}
|
|
153
|
+
function program2(depth0,data) {
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
return "<sup>";
|
|
157
|
+
}
|
|
179
158
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
function termsTpl(data, options, asString) {
|
|
185
|
-
var html = Template(data, options);
|
|
186
|
-
return (asString || true) ? html : $(html);
|
|
159
|
+
function program4(depth0,data) {
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
return " term-elide";
|
|
187
163
|
}
|
|
188
164
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
*
|
|
195
|
-
* This program is distributed in the hope that it will be useful,
|
|
196
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
197
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
198
|
-
* GNU General Public License for more details.
|
|
199
|
-
*
|
|
200
|
-
* You should have received a copy of the GNU General Public License
|
|
201
|
-
* along with this program; if not, write to the Free Software
|
|
202
|
-
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
203
|
-
*
|
|
204
|
-
* Copyright (c) 2019 Open Assessment Technologies SA ;
|
|
205
|
-
*/
|
|
206
|
-
/**
|
|
207
|
-
* @typedef {term} renderTerm - Represents a renderable tokenizable term
|
|
208
|
-
* @property {Array} startExponent - List of exponent starts (will produce exponent notation for the term)
|
|
209
|
-
* @property {Array} endExponent - List of exponent ends (will finish exponent notation for the term)
|
|
210
|
-
* @property {Boolean} prefixed - Tells if the term is prefixed (i.e. function treated as binary operator)
|
|
211
|
-
* @property {Boolean} elide - Allows to hide the term when operands exist on each side
|
|
212
|
-
*/
|
|
165
|
+
function program6(depth0,data) {
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
return "</sup>";
|
|
169
|
+
}
|
|
213
170
|
|
|
171
|
+
stack1 = helpers.each.call(depth0, depth0, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
|
|
172
|
+
if(stack1 || stack1 === 0) { return stack1; }
|
|
173
|
+
else { return ''; }
|
|
174
|
+
});
|
|
175
|
+
function termsTpl(data, options, asString) {
|
|
176
|
+
var html = Template(data, options);
|
|
177
|
+
return (asString || true) ? html : $(html);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* This program is free software; you can redistribute it and/or
|
|
182
|
+
* modify it under the terms of the GNU General Public License
|
|
183
|
+
* as published by the Free Software Foundation; under version 2
|
|
184
|
+
* of the License (non-upgradable).
|
|
185
|
+
*
|
|
186
|
+
* This program is distributed in the hope that it will be useful,
|
|
187
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
188
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
189
|
+
* GNU General Public License for more details.
|
|
190
|
+
*
|
|
191
|
+
* You should have received a copy of the GNU General Public License
|
|
192
|
+
* along with this program; if not, write to the Free Software
|
|
193
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
194
|
+
*
|
|
195
|
+
* Copyright (c) 2019 Open Assessment Technologies SA ;
|
|
196
|
+
*/
|
|
197
|
+
/**
|
|
198
|
+
* @typedef {term} renderTerm - Represents a renderable tokenizable term
|
|
199
|
+
* @property {Array} startExponent - List of exponent starts (will produce exponent notation for the term)
|
|
200
|
+
* @property {Array} endExponent - List of exponent ends (will finish exponent notation for the term)
|
|
201
|
+
* @property {Boolean} prefixed - Tells if the term is prefixed (i.e. function treated as binary operator)
|
|
202
|
+
* @property {Boolean} elide - Allows to hide the term when operands exist on each side
|
|
203
|
+
*/
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Name of the variable that contains the last result
|
|
207
|
+
* @type {String}
|
|
208
|
+
*/
|
|
209
|
+
|
|
210
|
+
var lastResultVariableName = registeredTerms.ANS.value;
|
|
211
|
+
/**
|
|
212
|
+
* Regex that matches the prefixed function operators
|
|
213
|
+
* @type {RegExp}
|
|
214
|
+
*/
|
|
215
|
+
|
|
216
|
+
var rePrefixedTerm = /^@[a-zA-Z_]\w*$/;
|
|
217
|
+
/**
|
|
218
|
+
* Regex that matches the usual error tokens in a result
|
|
219
|
+
* @type {RegExp}
|
|
220
|
+
*/
|
|
221
|
+
|
|
222
|
+
var reErrorValue = /(NaN|[+-]?Infinity)/;
|
|
223
|
+
/**
|
|
224
|
+
* Regex that matches the last result variable
|
|
225
|
+
* @type {RegExp}
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
var reAnsVar = new RegExp('\\b' + lastResultVariableName + '\\b', 'g');
|
|
229
|
+
/**
|
|
230
|
+
* List of tokens representing sign or sum
|
|
231
|
+
* @type {String[]}
|
|
232
|
+
*/
|
|
233
|
+
|
|
234
|
+
var signOperators = ['NEG', 'POS', 'SUB', 'ADD'];
|
|
235
|
+
/**
|
|
236
|
+
* List of tokens representing sub exponent parts to continue
|
|
237
|
+
* @type {String[]}
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
var continueExponent = ['POW', 'NTHRT'];
|
|
241
|
+
/**
|
|
242
|
+
* Default number of significant digits used to round displayed variables
|
|
243
|
+
* @type {Number}
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
var defaultDecimalDigits = 5;
|
|
247
|
+
/**
|
|
248
|
+
* List of helpers that apply on expression
|
|
249
|
+
* @type {Object}
|
|
250
|
+
*/
|
|
251
|
+
|
|
252
|
+
var expressionHelper = {
|
|
214
253
|
/**
|
|
215
|
-
*
|
|
216
|
-
* @
|
|
254
|
+
* Checks if an expression contains an error token
|
|
255
|
+
* @param {String|Number|Object} expression
|
|
256
|
+
* @returns {Boolean}
|
|
217
257
|
*/
|
|
258
|
+
containsError: function containsError(expression) {
|
|
259
|
+
return reErrorValue.test(tokensHelper.stringValue(expression));
|
|
260
|
+
},
|
|
218
261
|
|
|
219
|
-
var lastResultVariableName = registeredTerms.ANS.value;
|
|
220
262
|
/**
|
|
221
|
-
*
|
|
222
|
-
* @
|
|
263
|
+
* Replace the last result variable by a particular value in an expression
|
|
264
|
+
* @param {String|Number|Object} expression
|
|
265
|
+
* @param {String|Number|Object} value
|
|
266
|
+
* @returns {String}
|
|
223
267
|
*/
|
|
268
|
+
replaceLastResult: function replaceLastResult(expression, value) {
|
|
269
|
+
return tokensHelper.stringValue(expression).replace(reAnsVar, tokensHelper.stringValue(value || '0'));
|
|
270
|
+
},
|
|
224
271
|
|
|
225
|
-
var rePrefixedTerm = /^@[a-zA-Z_]\w*$/;
|
|
226
272
|
/**
|
|
227
|
-
*
|
|
228
|
-
* @
|
|
273
|
+
* Rounds the value of a variable
|
|
274
|
+
* @param {Object} variable
|
|
275
|
+
* @param {Number} [decimalDigits=5]
|
|
276
|
+
* @returns {String}
|
|
229
277
|
*/
|
|
278
|
+
roundVariable: function roundVariable(variable, decimalDigits) {
|
|
279
|
+
var resultString = tokensHelper.stringValue(variable);
|
|
280
|
+
var fullString = resultString;
|
|
281
|
+
var value = variable && variable.result;
|
|
282
|
+
decimalDigits = decimalDigits || defaultDecimalDigits;
|
|
283
|
+
|
|
284
|
+
if ('undefined' !== typeof value) {
|
|
285
|
+
if (value.toExponential && resultString.indexOf(registeredTerms.EXP10.value) > 0) {
|
|
286
|
+
resultString = value.toExponential(decimalDigits).toString();
|
|
287
|
+
} else if (value.toDecimalPlaces && resultString.indexOf(registeredTerms.DOT.value) > 0) {
|
|
288
|
+
resultString = value.toDecimalPlaces(decimalDigits).toString();
|
|
289
|
+
}
|
|
230
290
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
291
|
+
if (resultString.length < fullString.length) {
|
|
292
|
+
resultString += registeredTerms.ELLIPSIS.value;
|
|
293
|
+
} else {
|
|
294
|
+
resultString = fullString;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
236
297
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
* List of tokens representing sign or sum
|
|
240
|
-
* @type {String[]}
|
|
241
|
-
*/
|
|
298
|
+
return resultString;
|
|
299
|
+
},
|
|
242
300
|
|
|
243
|
-
var signOperators = ['NEG', 'POS', 'SUB', 'ADD'];
|
|
244
301
|
/**
|
|
245
|
-
*
|
|
246
|
-
* @
|
|
302
|
+
* Rounds the value of the last result variable
|
|
303
|
+
* @param {Object} variables
|
|
304
|
+
* @param {Number} [decimalDigits=5]
|
|
305
|
+
* @returns {Object}
|
|
247
306
|
*/
|
|
307
|
+
roundLastResultVariable: function roundLastResultVariable(variables, decimalDigits) {
|
|
308
|
+
if (variables && 'undefined' !== typeof variables[lastResultVariableName]) {
|
|
309
|
+
variables[lastResultVariableName] = expressionHelper.roundVariable(variables[lastResultVariableName], decimalDigits);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return variables;
|
|
313
|
+
},
|
|
248
314
|
|
|
249
|
-
var continueExponent = ['POW', 'NTHRT'];
|
|
250
315
|
/**
|
|
251
|
-
*
|
|
252
|
-
* @
|
|
316
|
+
* Replace sign operators by a proper symbol
|
|
317
|
+
* @param {String|Number|Object} expression
|
|
318
|
+
* @returns {String}
|
|
253
319
|
*/
|
|
320
|
+
renderSign: function renderSign(expression) {
|
|
321
|
+
return tokensHelper.stringValue(expression).replace(registeredTerms.SUB.value, registeredTerms.NEG.label).replace(registeredTerms.ADD.value, registeredTerms.POS.label);
|
|
322
|
+
},
|
|
254
323
|
|
|
255
|
-
var defaultDecimalDigits = 5;
|
|
256
324
|
/**
|
|
257
|
-
*
|
|
258
|
-
* @
|
|
325
|
+
* Renders an expression into a HTML string, using the display label of each extracted token .
|
|
326
|
+
* @param {String|Number|Object|token[]} expression
|
|
327
|
+
* @param {Object} [variables]
|
|
328
|
+
* @param {calculatorTokenizer} [tokenizer]
|
|
329
|
+
* @returns {String}
|
|
259
330
|
*/
|
|
260
|
-
|
|
261
|
-
|
|
331
|
+
render: function render(expression, variables, tokenizer) {
|
|
332
|
+
var tokens = expression;
|
|
333
|
+
var exponents = [];
|
|
334
|
+
var terms = [];
|
|
335
|
+
var previous;
|
|
262
336
|
/**
|
|
263
|
-
*
|
|
264
|
-
* @param {
|
|
265
|
-
* @
|
|
337
|
+
* Transform an operator to a sign
|
|
338
|
+
* @param {renderTerm} term
|
|
339
|
+
* @param {String} token
|
|
266
340
|
*/
|
|
267
|
-
containsError: function containsError(expression) {
|
|
268
|
-
return reErrorValue.test(tokensHelper.stringValue(expression));
|
|
269
|
-
},
|
|
270
341
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
* @returns {String}
|
|
276
|
-
*/
|
|
277
|
-
replaceLastResult: function replaceLastResult(expression, value) {
|
|
278
|
-
return tokensHelper.stringValue(expression).replace(reAnsVar, tokensHelper.stringValue(value || '0'));
|
|
279
|
-
},
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Rounds the value of a variable
|
|
283
|
-
* @param {Object} variable
|
|
284
|
-
* @param {Number} [decimalDigits=5]
|
|
285
|
-
* @returns {String}
|
|
286
|
-
*/
|
|
287
|
-
roundVariable: function roundVariable(variable, decimalDigits) {
|
|
288
|
-
var resultString = tokensHelper.stringValue(variable);
|
|
289
|
-
var fullString = resultString;
|
|
290
|
-
var value = variable && variable.result;
|
|
291
|
-
decimalDigits = decimalDigits || defaultDecimalDigits;
|
|
292
|
-
|
|
293
|
-
if ('undefined' !== typeof value) {
|
|
294
|
-
if (value.toExponential && resultString.indexOf(registeredTerms.EXP10.value) > 0) {
|
|
295
|
-
resultString = value.toExponential(decimalDigits).toString();
|
|
296
|
-
} else if (value.toDecimalPlaces && resultString.indexOf(registeredTerms.DOT.value) > 0) {
|
|
297
|
-
resultString = value.toDecimalPlaces(decimalDigits).toString();
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (resultString.length < fullString.length) {
|
|
301
|
-
resultString += registeredTerms.ELLIPSIS.value;
|
|
302
|
-
} else {
|
|
303
|
-
resultString = fullString;
|
|
304
|
-
}
|
|
342
|
+
function toSignOperator(term, token) {
|
|
343
|
+
if (!previous || tokensHelper.isModifier(previous.type) || previous.token === 'LPAR' || previous.token === 'EXP10') {
|
|
344
|
+
term.label = registeredTerms[token].label;
|
|
345
|
+
term.token = token;
|
|
305
346
|
}
|
|
347
|
+
} // the expression might be already tokenized, if not we need to tokenize it
|
|
306
348
|
|
|
307
|
-
return resultString;
|
|
308
|
-
},
|
|
309
349
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
* @returns {Object}
|
|
315
|
-
*/
|
|
316
|
-
roundLastResultVariable: function roundLastResultVariable(variables, decimalDigits) {
|
|
317
|
-
if (variables && 'undefined' !== typeof variables[lastResultVariableName]) {
|
|
318
|
-
variables[lastResultVariableName] = expressionHelper.roundVariable(variables[lastResultVariableName], decimalDigits);
|
|
350
|
+
if (!_.isArray(expression)) {
|
|
351
|
+
// we need a valid tokenizer, so if none is provided we must build one
|
|
352
|
+
if (!tokenizer || !tokenizer.tokenize) {
|
|
353
|
+
tokenizer = tokenizerFactory();
|
|
319
354
|
}
|
|
320
355
|
|
|
321
|
-
|
|
322
|
-
}
|
|
356
|
+
tokens = tokenizer.tokenize(expression);
|
|
357
|
+
}
|
|
323
358
|
|
|
324
|
-
|
|
325
|
-
* Replace sign operators by a proper symbol
|
|
326
|
-
* @param {String|Number|Object} expression
|
|
327
|
-
* @returns {String}
|
|
328
|
-
*/
|
|
329
|
-
renderSign: function renderSign(expression) {
|
|
330
|
-
return tokensHelper.stringValue(expression).replace(registeredTerms.SUB.value, registeredTerms.NEG.label).replace(registeredTerms.ADD.value, registeredTerms.POS.label);
|
|
331
|
-
},
|
|
359
|
+
variables = variables || {}; // each token needs to be translated into a displayable term
|
|
332
360
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
* @param {String|Number|Object|token[]} expression
|
|
336
|
-
* @param {Object} [variables]
|
|
337
|
-
* @param {calculatorTokenizer} [tokenizer]
|
|
338
|
-
* @returns {String}
|
|
339
|
-
*/
|
|
340
|
-
render: function render(expression, variables, tokenizer) {
|
|
341
|
-
var tokens = expression;
|
|
342
|
-
var exponents = [];
|
|
343
|
-
var terms = [];
|
|
344
|
-
var previous;
|
|
361
|
+
_.forEach(tokens, function (token, index) {
|
|
362
|
+
var registeredTerm = registeredTerms[token.type];
|
|
345
363
|
/**
|
|
346
|
-
*
|
|
347
|
-
* @param {renderTerm} term
|
|
348
|
-
* @param {String} token
|
|
364
|
+
* @type {renderTerm}
|
|
349
365
|
*/
|
|
350
366
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
367
|
+
var term = {
|
|
368
|
+
type: token.type,
|
|
369
|
+
token: token.type,
|
|
370
|
+
value: token.value,
|
|
371
|
+
label: token.value,
|
|
372
|
+
description: token.value,
|
|
373
|
+
exponent: null,
|
|
374
|
+
startExponent: [],
|
|
375
|
+
endExponent: [],
|
|
376
|
+
prefixed: rePrefixedTerm.test(token.value),
|
|
377
|
+
elide: false
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
if (registeredTerm) {
|
|
381
|
+
_.merge(term, registeredTerm); // always display the actual value of the last result variable
|
|
382
|
+
// also takes care of the value's sign
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
if (term.value === lastResultVariableName && 'undefined' !== typeof variables[term.value]) {
|
|
386
|
+
term.label = expressionHelper.render(variables[term.value], variables, tokenizer);
|
|
355
387
|
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
tokenizer = tokenizerFactory();
|
|
388
|
+
} else if (term.token === 'term') {
|
|
389
|
+
// unspecified token can be a variable
|
|
390
|
+
if ('undefined' !== typeof variables[term.value]) {
|
|
391
|
+
term.type = 'variable';
|
|
392
|
+
} else {
|
|
393
|
+
term.type = 'unknown';
|
|
363
394
|
}
|
|
395
|
+
} // take care of the value's sign
|
|
364
396
|
|
|
365
|
-
tokens = tokenizer.tokenize(expression);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
variables = variables || {}; // each token needs to be translated into a displayable term
|
|
369
|
-
|
|
370
|
-
_.forEach(tokens, function (token, index) {
|
|
371
|
-
var registeredTerm = registeredTerms[token.type];
|
|
372
|
-
/**
|
|
373
|
-
* @type {renderTerm}
|
|
374
|
-
*/
|
|
375
|
-
|
|
376
|
-
var term = {
|
|
377
|
-
type: token.type,
|
|
378
|
-
token: token.type,
|
|
379
|
-
value: token.value,
|
|
380
|
-
label: token.value,
|
|
381
|
-
description: token.value,
|
|
382
|
-
exponent: null,
|
|
383
|
-
startExponent: [],
|
|
384
|
-
endExponent: [],
|
|
385
|
-
prefixed: rePrefixedTerm.test(token.value),
|
|
386
|
-
elide: false
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
if (registeredTerm) {
|
|
390
|
-
_.merge(term, registeredTerm); // always display the actual value of the last result variable
|
|
391
|
-
// also takes care of the value's sign
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if (term.value === lastResultVariableName && 'undefined' !== typeof variables[term.value]) {
|
|
395
|
-
term.label = expressionHelper.render(variables[term.value], variables, tokenizer);
|
|
396
|
-
}
|
|
397
|
-
} else if (term.token === 'term') {
|
|
398
|
-
// unspecified token can be a variable
|
|
399
|
-
if ('undefined' !== typeof variables[term.value]) {
|
|
400
|
-
term.type = 'variable';
|
|
401
|
-
} else {
|
|
402
|
-
term.type = 'unknown';
|
|
403
|
-
}
|
|
404
|
-
} // take care of the value's sign
|
|
405
397
|
|
|
398
|
+
if (term.token === 'SUB') {
|
|
399
|
+
toSignOperator(term, 'NEG');
|
|
400
|
+
} else if (term.token === 'ADD') {
|
|
401
|
+
toSignOperator(term, 'POS');
|
|
402
|
+
}
|
|
406
403
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
} else if (term.token === 'ADD') {
|
|
410
|
-
toSignOperator(term, 'POS');
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
terms.push(term); // exponents will be processed in a second pass
|
|
414
|
-
// for now we just need to keep track of the position
|
|
404
|
+
terms.push(term); // exponents will be processed in a second pass
|
|
405
|
+
// for now we just need to keep track of the position
|
|
415
406
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
407
|
+
if (term.exponent) {
|
|
408
|
+
exponents.push(index);
|
|
409
|
+
}
|
|
419
410
|
|
|
420
|
-
|
|
421
|
-
|
|
411
|
+
previous = term;
|
|
412
|
+
}); // if any exponent has been discovered, we need to process them now
|
|
422
413
|
|
|
423
414
|
|
|
424
|
-
|
|
425
|
-
|
|
415
|
+
_.forEach(exponents, function (index) {
|
|
416
|
+
var term = terms[index];
|
|
426
417
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
418
|
+
if (term.exponent === 'left' && index > 0) {
|
|
419
|
+
exponentOnTheLeft(index, terms);
|
|
420
|
+
} else if (term.exponent === 'right' && index < terms.length - 1) {
|
|
421
|
+
exponentOnTheRight(index, terms);
|
|
422
|
+
}
|
|
423
|
+
});
|
|
433
424
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
425
|
+
return termsTpl(terms);
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
/**
|
|
429
|
+
* Search for the full operand on the left, then tag the edges with exponent flags
|
|
430
|
+
* @param {Number} index
|
|
431
|
+
* @param {renderTerm[]} terms
|
|
432
|
+
*/
|
|
433
|
+
|
|
434
|
+
function exponentOnTheLeft(index, terms) {
|
|
435
|
+
var parenthesis = 0;
|
|
436
|
+
var next = terms[index];
|
|
437
|
+
var term = terms[--index];
|
|
437
438
|
/**
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
* @param {renderTerm[]} terms
|
|
439
|
+
* Simply moves the cursor to the next term to examine.
|
|
440
|
+
* Here the move is made from the right to the left.
|
|
441
441
|
*/
|
|
442
442
|
|
|
443
|
-
function
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* Simply moves the cursor to the next term to examine.
|
|
449
|
-
* Here the move is made from the right to the left.
|
|
450
|
-
*/
|
|
443
|
+
function nextTerm() {
|
|
444
|
+
next = term;
|
|
445
|
+
term = terms[--index];
|
|
446
|
+
} // only take care of actual operand value or sub expression (starting from the right)
|
|
451
447
|
|
|
452
|
-
function nextTerm() {
|
|
453
|
-
next = term;
|
|
454
|
-
term = terms[--index];
|
|
455
|
-
} // only take care of actual operand value or sub expression (starting from the right)
|
|
456
448
|
|
|
449
|
+
if (term && (tokensHelper.isOperand(term.type) || term.token === 'RPAR')) {
|
|
450
|
+
term.endExponent.push(term.endExponent.length);
|
|
457
451
|
|
|
458
|
-
if (term
|
|
459
|
-
|
|
452
|
+
if (term.token === 'RPAR') {
|
|
453
|
+
// closing parenthesis, we need to find the opening parenthesis
|
|
454
|
+
parenthesis++;
|
|
460
455
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
parenthesis++;
|
|
464
|
-
|
|
465
|
-
while (index > 0 && parenthesis > 0) {
|
|
466
|
-
nextTerm();
|
|
456
|
+
while (index > 0 && parenthesis > 0) {
|
|
457
|
+
nextTerm();
|
|
467
458
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
} // a function could be attached to the sub expression, if so we must keep the link
|
|
474
|
-
// however, the prefixed functions are particular as they act as a binary operators,
|
|
475
|
-
// and therefore are not considered as function here
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
if (index > 0 && tokensHelper.isFunction(terms[index - 1]) && !terms[index - 1].prefixed) {
|
|
479
|
-
nextTerm();
|
|
459
|
+
if (term.token === 'RPAR') {
|
|
460
|
+
parenthesis++;
|
|
461
|
+
} else if (term.token === 'LPAR') {
|
|
462
|
+
parenthesis--;
|
|
480
463
|
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
nextTerm();
|
|
485
|
-
} // if the end of the chain has been overflown, we must step back one token
|
|
464
|
+
} // a function could be attached to the sub expression, if so we must keep the link
|
|
465
|
+
// however, the prefixed functions are particular as they act as a binary operators,
|
|
466
|
+
// and therefore are not considered as function here
|
|
486
467
|
|
|
487
468
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
}
|
|
469
|
+
if (index > 0 && tokensHelper.isFunction(terms[index - 1]) && !terms[index - 1].prefixed) {
|
|
470
|
+
nextTerm();
|
|
491
471
|
}
|
|
472
|
+
} else if (tokensHelper.isDigit(term.type)) {
|
|
473
|
+
// chain of digits should be treated as a single operand
|
|
474
|
+
while (index && tokensHelper.isDigit(term.type)) {
|
|
475
|
+
nextTerm();
|
|
476
|
+
} // if the end of the chain has been overflown, we must step back one token
|
|
492
477
|
|
|
493
|
-
|
|
478
|
+
|
|
479
|
+
if (!tokensHelper.isDigit(term.type)) {
|
|
480
|
+
term = next;
|
|
481
|
+
}
|
|
494
482
|
}
|
|
483
|
+
|
|
484
|
+
term.startExponent.push(term.startExponent.length);
|
|
495
485
|
}
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Search for the full operand on the right, then tag the edges with exponent flags
|
|
489
|
+
* @param {Number} index
|
|
490
|
+
* @param {renderTerm[]} terms
|
|
491
|
+
*/
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
function exponentOnTheRight(index, terms) {
|
|
495
|
+
var last = terms.length - 1;
|
|
496
|
+
var parenthesis = 0;
|
|
497
|
+
var startAt = index;
|
|
498
|
+
var previous = terms[index];
|
|
499
|
+
var term = terms[++index];
|
|
500
|
+
var shouldContinue;
|
|
496
501
|
/**
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
* @param {renderTerm[]} terms
|
|
502
|
+
* Simply moves the cursor to the next term to examine.
|
|
503
|
+
* Here the move is made from the left to the right.
|
|
500
504
|
*/
|
|
501
505
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
/**
|
|
511
|
-
* Simply moves the cursor to the next term to examine.
|
|
512
|
-
* Here the move is made from the left to the right.
|
|
513
|
-
*/
|
|
514
|
-
|
|
515
|
-
function nextTerm() {
|
|
516
|
-
previous = term;
|
|
517
|
-
term = terms[++index];
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* Simply moves back the cursor to the previous term.
|
|
521
|
-
* Here the move is made from the right to the left.
|
|
522
|
-
*/
|
|
506
|
+
function nextTerm() {
|
|
507
|
+
previous = term;
|
|
508
|
+
term = terms[++index];
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Simply moves back the cursor to the previous term.
|
|
512
|
+
* Here the move is made from the right to the left.
|
|
513
|
+
*/
|
|
523
514
|
|
|
524
515
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
516
|
+
function previousTerm() {
|
|
517
|
+
term = previous;
|
|
518
|
+
previous = terms[--index];
|
|
519
|
+
} // only take care of actual operand value or sub expression (starting from the left)
|
|
529
520
|
|
|
530
521
|
|
|
531
|
-
|
|
532
|
-
|
|
522
|
+
if (term && (tokensHelper.isOperand(term.type) || term.token === 'LPAR' || signOperators.indexOf(term.token) >= 0)) {
|
|
523
|
+
term.startExponent.push(term.startExponent.length); // we use an internal loop as exponents could be chained
|
|
533
524
|
|
|
534
|
-
|
|
535
|
-
|
|
525
|
+
do {
|
|
526
|
+
shouldContinue = false; // functions are attached to an operand, and this link should be kept
|
|
536
527
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
528
|
+
while (index < last && (tokensHelper.isFunction(term.type) || signOperators.indexOf(term.token) >= 0)) {
|
|
529
|
+
nextTerm();
|
|
530
|
+
} // if the end has been reached, step back one token
|
|
540
531
|
|
|
541
532
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
533
|
+
if (!term) {
|
|
534
|
+
previousTerm();
|
|
535
|
+
}
|
|
545
536
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
537
|
+
if (term.token === 'LPAR') {
|
|
538
|
+
// opening parenthesis, we need to find the closing parenthesis
|
|
539
|
+
parenthesis++;
|
|
549
540
|
|
|
550
|
-
|
|
551
|
-
|
|
541
|
+
while (index < last && parenthesis > 0) {
|
|
542
|
+
nextTerm();
|
|
552
543
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
}
|
|
544
|
+
if (term.token === 'LPAR') {
|
|
545
|
+
parenthesis++;
|
|
546
|
+
} else if (term.token === 'RPAR') {
|
|
547
|
+
parenthesis--;
|
|
558
548
|
}
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
549
|
+
}
|
|
550
|
+
} else if (tokensHelper.isDigit(term.type)) {
|
|
551
|
+
// chain of digits should be treated as a single operand
|
|
552
|
+
while (index < last && tokensHelper.isDigit(term.type)) {
|
|
553
|
+
nextTerm();
|
|
554
|
+
} // if the end of the chain has been overflown, we must step back one token
|
|
564
555
|
|
|
565
556
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
557
|
+
if (!term || !tokensHelper.isDigit(term.type)) {
|
|
558
|
+
previousTerm();
|
|
559
|
+
}
|
|
560
|
+
} // factorial is a special case, as the operator can be placed either on the right or on the left
|
|
561
|
+
// in any case it should be attached to its operand
|
|
571
562
|
|
|
572
563
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
564
|
+
while (index < last && terms[index + 1].token === 'FAC') {
|
|
565
|
+
nextTerm();
|
|
566
|
+
} // sometimes a sub exponent continues the chain and should be part of the expression to put in exponent
|
|
576
567
|
|
|
577
568
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
569
|
+
if (index < last && continueExponent.indexOf(terms[index + 1].token) >= 0) {
|
|
570
|
+
// the next term should be ignored as we already know it is an exponent operator
|
|
571
|
+
// then the term after have to be set as the current one
|
|
572
|
+
nextTerm();
|
|
573
|
+
nextTerm();
|
|
574
|
+
shouldContinue = true;
|
|
575
|
+
}
|
|
576
|
+
} while (shouldContinue);
|
|
586
577
|
|
|
587
|
-
|
|
578
|
+
term.endExponent.push(term.endExponent.length); // elide the operator if operands are complete
|
|
588
579
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
}
|
|
580
|
+
if (startAt > 0 && startAt < last && terms[startAt].token === 'POW' && terms[startAt + 1].startExponent.length) {
|
|
581
|
+
terms[startAt].elide = true;
|
|
592
582
|
}
|
|
593
583
|
}
|
|
584
|
+
}
|
|
594
585
|
|
|
595
|
-
|
|
586
|
+
return expressionHelper;
|
|
596
587
|
|
|
597
588
|
});
|