ixbrl-viewer 1.4.1__py3-none-any.whl → 1.4.86__py3-none-any.whl
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.
- iXBRLViewerPlugin/__init__.py +231 -127
- iXBRLViewerPlugin/_version.py +33 -3
- iXBRLViewerPlugin/constants.py +96 -2
- iXBRLViewerPlugin/featureConfig.py +8 -1
- iXBRLViewerPlugin/iXBRLViewer.py +356 -214
- iXBRLViewerPlugin/plugin.py +12 -0
- iXBRLViewerPlugin/ui.py +81 -50
- iXBRLViewerPlugin/viewer/dist/ixbrlviewer.js +1 -1
- iXBRLViewerPlugin/viewer/dist/ixbrlviewer.js.LICENSE.txt +12 -5
- iXBRLViewerPlugin/viewer/i18next-parser.config.js +1 -1
- iXBRLViewerPlugin/viewer/src/data/utr.json +1244 -0
- iXBRLViewerPlugin/viewer/src/html/fact-details.html +69 -38
- iXBRLViewerPlugin/viewer/src/html/footer-logo.html +4 -0
- iXBRLViewerPlugin/viewer/src/html/footnote-details.html +2 -2
- iXBRLViewerPlugin/viewer/src/html/inspector.html +352 -197
- iXBRLViewerPlugin/viewer/src/i18n/cy/balancetypes.json +1 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/scale.json +16 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/datatypes.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/labelroles.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/scale.json +16 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/translation.json +73 -23
- iXBRLViewerPlugin/viewer/src/i18n/es/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/datatypes.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/scale.json +16 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/translation.json +87 -37
- iXBRLViewerPlugin/viewer/src/i18n/fr/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/icons/calculator.svg +13 -0
- iXBRLViewerPlugin/viewer/src/icons/circle-cross.svg +11 -0
- iXBRLViewerPlugin/viewer/src/icons/circle-tick.svg +11 -0
- iXBRLViewerPlugin/viewer/src/icons/dark-mode.svg +4 -0
- iXBRLViewerPlugin/viewer/src/icons/dimension.svg +1 -5
- iXBRLViewerPlugin/viewer/src/icons/member.svg +2 -5
- iXBRLViewerPlugin/viewer/src/icons/multi-tag.svg +10 -0
- iXBRLViewerPlugin/viewer/src/img/arelle-dark.svg +179 -0
- iXBRLViewerPlugin/viewer/src/img/inline-viewer-dark.svg +59 -0
- iXBRLViewerPlugin/viewer/src/js/accordian.js +5 -4
- iXBRLViewerPlugin/viewer/src/js/aspect.js +29 -10
- iXBRLViewerPlugin/viewer/src/js/aspect.test.js +40 -31
- iXBRLViewerPlugin/viewer/src/js/balance.js +14 -0
- iXBRLViewerPlugin/viewer/src/js/calculation.js +213 -0
- iXBRLViewerPlugin/viewer/src/js/calculation.test.js +306 -0
- iXBRLViewerPlugin/viewer/src/js/calculationInspector.js +187 -0
- iXBRLViewerPlugin/viewer/src/js/chart.js +26 -24
- iXBRLViewerPlugin/viewer/src/js/chart.test.js +10 -9
- iXBRLViewerPlugin/viewer/src/js/concept.js +37 -4
- iXBRLViewerPlugin/viewer/src/js/concept.test.js +30 -6
- iXBRLViewerPlugin/viewer/src/js/datatype.js +20 -0
- iXBRLViewerPlugin/viewer/src/js/datatype.test.js +62 -0
- iXBRLViewerPlugin/viewer/src/js/dialog.js +6 -4
- iXBRLViewerPlugin/viewer/src/js/docOrderIndex.js +7 -7
- iXBRLViewerPlugin/viewer/src/js/fact.js +156 -59
- iXBRLViewerPlugin/viewer/src/js/fact.test.js +160 -29
- iXBRLViewerPlugin/viewer/src/js/factset.js +64 -15
- iXBRLViewerPlugin/viewer/src/js/factset.test.js +102 -31
- iXBRLViewerPlugin/viewer/src/js/footnote.js +8 -2
- iXBRLViewerPlugin/viewer/src/js/index.js +11 -3
- iXBRLViewerPlugin/viewer/src/js/inspector.js +747 -221
- iXBRLViewerPlugin/viewer/src/js/inspector.test.js +143 -25
- iXBRLViewerPlugin/viewer/src/js/interval.js +70 -0
- iXBRLViewerPlugin/viewer/src/js/interval.test.js +153 -0
- iXBRLViewerPlugin/viewer/src/js/ixbrlviewer.js +391 -262
- iXBRLViewerPlugin/viewer/src/js/ixbrlviewer.test.js +134 -20
- iXBRLViewerPlugin/viewer/src/js/ixnode.js +1 -1
- iXBRLViewerPlugin/viewer/src/js/menu.js +25 -7
- iXBRLViewerPlugin/viewer/src/js/number-matcher.js +7 -3
- iXBRLViewerPlugin/viewer/src/js/number-matcher.test.js +4 -0
- iXBRLViewerPlugin/viewer/src/js/outline.js +34 -13
- iXBRLViewerPlugin/viewer/src/js/outline.test.js +97 -91
- iXBRLViewerPlugin/viewer/src/js/period.js +0 -1
- iXBRLViewerPlugin/viewer/src/js/report.js +260 -351
- iXBRLViewerPlugin/viewer/src/js/report.test.js +95 -27
- iXBRLViewerPlugin/viewer/src/js/reportset.js +264 -0
- iXBRLViewerPlugin/viewer/src/js/reportset.test.js +357 -0
- iXBRLViewerPlugin/viewer/src/js/search.js +72 -38
- iXBRLViewerPlugin/viewer/src/js/search.test.js +184 -84
- iXBRLViewerPlugin/viewer/src/js/summary.js +34 -8
- iXBRLViewerPlugin/viewer/src/js/summary.test.js +69 -25
- iXBRLViewerPlugin/viewer/src/js/tableExport.js +9 -9
- iXBRLViewerPlugin/viewer/src/js/taxonomynamer.js +34 -0
- iXBRLViewerPlugin/viewer/src/js/taxonomynamer.test.js +32 -0
- iXBRLViewerPlugin/viewer/src/js/test-utils.js +46 -0
- iXBRLViewerPlugin/viewer/src/js/theme.js +50 -0
- iXBRLViewerPlugin/viewer/src/js/unit.js +90 -32
- iXBRLViewerPlugin/viewer/src/js/unit.test.js +62 -25
- iXBRLViewerPlugin/viewer/src/js/util.js +94 -0
- iXBRLViewerPlugin/viewer/src/js/util.test.js +33 -1
- iXBRLViewerPlugin/viewer/src/js/utr.js +27 -0
- iXBRLViewerPlugin/viewer/src/js/viewer.js +205 -181
- iXBRLViewerPlugin/viewer/src/js/viewerOptions.js +0 -2
- iXBRLViewerPlugin/viewer/src/less/accordian.less +10 -6
- iXBRLViewerPlugin/viewer/src/less/block-list.less +16 -5
- iXBRLViewerPlugin/viewer/src/less/calculation-inspector.less +83 -0
- iXBRLViewerPlugin/viewer/src/less/chart.less +8 -5
- iXBRLViewerPlugin/viewer/src/less/colours-dark-mode.less +40 -0
- iXBRLViewerPlugin/viewer/src/less/colours.less +32 -20
- iXBRLViewerPlugin/viewer/src/less/common.less +3 -3
- iXBRLViewerPlugin/viewer/src/less/components.less +6 -4
- iXBRLViewerPlugin/viewer/src/less/core.less +2 -0
- iXBRLViewerPlugin/viewer/src/less/dialog.less +21 -14
- iXBRLViewerPlugin/viewer/src/less/form-controls.less +33 -11
- iXBRLViewerPlugin/viewer/src/less/inspector.less +1045 -726
- iXBRLViewerPlugin/viewer/src/less/loader.less +2 -2
- iXBRLViewerPlugin/viewer/src/less/menu.less +33 -15
- iXBRLViewerPlugin/viewer/src/less/summary.less +16 -6
- iXBRLViewerPlugin/viewer/src/less/tabs.less +9 -9
- iXBRLViewerPlugin/viewer/src/less/text-block-viewer.less +2 -0
- iXBRLViewerPlugin/viewer/src/less/text-mixins.less +2 -1
- iXBRLViewerPlugin/viewer/src/less/validation-report.less +2 -3
- iXBRLViewerPlugin/viewer/src/less/viewer.less +105 -74
- iXBRLViewerPlugin/viewer/webpack.common.js +19 -9
- iXBRLViewerPlugin/xhtmlserialize.py +59 -45
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/METADATA +181 -50
- ixbrl_viewer-1.4.86.dist-info/RECORD +217 -0
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/WHEEL +1 -1
- ixbrl_viewer-1.4.1.dist-info/LICENSE → ixbrl_viewer-1.4.86.dist-info/licenses/LICENSE.md +8 -14
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/top_level.txt +0 -1
- iXBRLViewerPlugin/viewer/src/js/calculations.js +0 -111
- iXBRLViewerPlugin/viewer/src/js/interact.min.js +0 -6
- ixbrl_viewer-1.4.1.dist-info/RECORD +0 -155
- tests/__init__.py +0 -0
- tests/puppeteer/framework/core_elements.js +0 -117
- tests/puppeteer/framework/page_objects/doc_frame.js +0 -105
- tests/puppeteer/framework/page_objects/fact_details_panel.js +0 -80
- tests/puppeteer/framework/page_objects/search_panel.js +0 -76
- tests/puppeteer/framework/page_objects/toolbar.js +0 -18
- tests/puppeteer/framework/utils.js +0 -3
- tests/puppeteer/framework/viewer_page.js +0 -103
- tests/puppeteer/puppeteer_test_run_via_intellij.jpg +0 -0
- tests/puppeteer/test_filings/filing_documents_smoke_test.zip +0 -0
- tests/puppeteer/test_filings/highlights.zip +0 -0
- tests/puppeteer/tests/fact_properties.test.js +0 -78
- tests/puppeteer/tests/highlight.test.js +0 -186
- tests/puppeteer/tests/search.test.js +0 -86
- tests/puppeteer/tools/generate.sh +0 -15
- tests/unit_tests/__init__.py +0 -0
- tests/unit_tests/iXBRLViewerPlugin/__init__.py +0 -0
- tests/unit_tests/iXBRLViewerPlugin/mock_arelle.py +0 -39
- tests/unit_tests/iXBRLViewerPlugin/test_iXBRLViewer.py +0 -641
- tests/unit_tests/iXBRLViewerPlugin/test_xhtmlserialize.py +0 -310
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/entry_points.txt +0 -0
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info/licenses}/NOTICE +0 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// Copyright 2021 Workiva Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
import $ from 'jquery';
|
|
16
|
+
import i18next from 'i18next';
|
|
17
|
+
|
|
18
|
+
import { Dialog } from './dialog.js';
|
|
19
|
+
import { ResolvedCalc11Calculation } from './calculation.js';
|
|
20
|
+
|
|
21
|
+
export class CalculationInspector extends Dialog {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(".dialog.calculation-inspector");
|
|
24
|
+
this.addButton("Dismiss", true);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
duplicateFactIcons(factset) {
|
|
28
|
+
const icons = $("<td></td>").addClass("icons");
|
|
29
|
+
if (factset.size() > 1 && !factset.completeDuplicates()) {
|
|
30
|
+
if (factset.isConsistent()) {
|
|
31
|
+
icons.append(
|
|
32
|
+
$("<span></span>")
|
|
33
|
+
.addClass("duplicate-facts")
|
|
34
|
+
.attr("title", i18next.t('calculation.consistent-duplicate-facts-present', {nfacts: factset.size()}))
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
icons.append(
|
|
39
|
+
$("<span></span>")
|
|
40
|
+
.addClass("duplicate-facts")
|
|
41
|
+
.attr("title", i18next.t('calculation.inconsistent-duplicate-facts-present', {nfacts: factset.size()}))
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return icons;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
populateCalc11Table(resolvedCalculation, table) {
|
|
49
|
+
table.addClass("calc11");
|
|
50
|
+
const tbody = table.find("tbody");
|
|
51
|
+
let hasIcons = false;
|
|
52
|
+
for (const row of resolvedCalculation.rows) {
|
|
53
|
+
let factText = "";
|
|
54
|
+
let minText = "";
|
|
55
|
+
let maxText = "";
|
|
56
|
+
|
|
57
|
+
if (!row.facts.isEmpty()) {
|
|
58
|
+
let f = row.facts.items()[0];
|
|
59
|
+
const reportedInterval = row.facts.valueIntersection();
|
|
60
|
+
if (reportedInterval === undefined) {
|
|
61
|
+
factText = "n/a";
|
|
62
|
+
minText = "n/a";
|
|
63
|
+
maxText = "n/a";
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
factText = f.readableValue(reportedInterval.midpoint().toNumber());
|
|
67
|
+
const contributionInterval = row.contributionInterval();
|
|
68
|
+
minText = f.readableValue(contributionInterval.a.toNumber());
|
|
69
|
+
maxText = f.readableValue(contributionInterval.b.toNumber());
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const icons = this.duplicateFactIcons(row.facts);
|
|
73
|
+
hasIcons = hasIcons || icons.find("span").length > 0;
|
|
74
|
+
$("<tr></tr>")
|
|
75
|
+
.append($("<td></td>").addClass("weight").text(row.weightSign))
|
|
76
|
+
.append($("<td></td>").text(row.concept.label()).addClass("line-item"))
|
|
77
|
+
.append($("<td></td>").addClass("figure").text(factText))
|
|
78
|
+
.append(icons)
|
|
79
|
+
.append($("<td></td>").addClass("figure").text(minText))
|
|
80
|
+
.append($("<td></td>").addClass("figure").text(maxText))
|
|
81
|
+
.appendTo(tbody);
|
|
82
|
+
}
|
|
83
|
+
const fact = resolvedCalculation.totalFact;
|
|
84
|
+
const cvi = resolvedCalculation.calculatedTotalInterval();
|
|
85
|
+
$("<tr></tr>").addClass("total")
|
|
86
|
+
.append($("<td></td>"))
|
|
87
|
+
.append($("<td></td>").text(`${fact.concept().label()} (${i18next.t('calculation.calculated-total')})`).addClass("line-item"))
|
|
88
|
+
.append($("<td></td>").text(cvi === undefined ? 'n/a' : fact.readableValue(cvi.midpoint().toNumber())).addClass("figure"))
|
|
89
|
+
.append($("<td></td>").addClass("icons"))
|
|
90
|
+
.append($("<td></td>").text(cvi === undefined ? 'n/a' : fact.readableValue(cvi.a.toNumber())).addClass("figure"))
|
|
91
|
+
.append($("<td></td>").text(cvi === undefined ? 'n/a' : fact.readableValue(cvi.b.toNumber())).addClass("figure"))
|
|
92
|
+
.appendTo(tbody);
|
|
93
|
+
|
|
94
|
+
const tvi = resolvedCalculation.totalFactSet.valueIntersection();
|
|
95
|
+
const icons = this.duplicateFactIcons(resolvedCalculation.totalFactSet);
|
|
96
|
+
$("<tr></tr>")
|
|
97
|
+
.append($("<td></td>"))
|
|
98
|
+
.append($("<td></td>").text(`${fact.concept().label()} (${i18next.t('calculation.reported-total')})`).addClass("line-item"))
|
|
99
|
+
.append($("<td></td>").text(tvi === undefined ? 'n/a' : fact.readableValue(tvi.midpoint().toNumber())).addClass("figure"))
|
|
100
|
+
.append(icons)
|
|
101
|
+
.append($("<td></td>").text(tvi === undefined ? 'n/a' : fact.readableValue(tvi.a.toNumber())).addClass("figure"))
|
|
102
|
+
.append($("<td></td>").text(tvi === undefined ? 'n/a' : fact.readableValue(tvi.b.toNumber())).addClass("figure"))
|
|
103
|
+
.appendTo(tbody);
|
|
104
|
+
if (hasIcons) {
|
|
105
|
+
table.addClass("has-icons");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
populateLegacyCalcTable(resolvedCalculation, table) {
|
|
110
|
+
table.removeClass("calc11");
|
|
111
|
+
const tbody = table.find("tbody");
|
|
112
|
+
let hasIcons = false;
|
|
113
|
+
for (const row of resolvedCalculation.rows) {
|
|
114
|
+
let factText = "";
|
|
115
|
+
|
|
116
|
+
if (!row.facts.isEmpty()) {
|
|
117
|
+
let f = row.facts.items()[0];
|
|
118
|
+
const reportedInterval = row.facts.valueIntersection();
|
|
119
|
+
if (reportedInterval === undefined) {
|
|
120
|
+
factText = "Inconsistent duplicates";
|
|
121
|
+
}
|
|
122
|
+
else if (!row.facts.completeDuplicates()) {
|
|
123
|
+
factText = "Duplicate facts";
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
factText = f.readableValue();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const icons = this.duplicateFactIcons(row.facts);
|
|
130
|
+
hasIcons = hasIcons || icons.find("span").length > 0;
|
|
131
|
+
$("<tr></tr>")
|
|
132
|
+
.append($("<td></td>").addClass("weight").text(row.weightSign))
|
|
133
|
+
.append($("<td></td>").text(row.concept.label()).addClass("line-item"))
|
|
134
|
+
.append($("<td></td>").addClass("figure").text(factText))
|
|
135
|
+
.append(icons)
|
|
136
|
+
.appendTo(tbody);
|
|
137
|
+
}
|
|
138
|
+
const fact = resolvedCalculation.totalFact;
|
|
139
|
+
const ct = resolvedCalculation.calculatedTotal();
|
|
140
|
+
$("<tr></tr>").addClass("total")
|
|
141
|
+
.append($("<td></td>"))
|
|
142
|
+
.append($("<td></td>").text(`${fact.concept().label()} (${i18next.t('calculation.calculated-total')})`).addClass("line-item"))
|
|
143
|
+
.append($("<td></td>").text(fact.readableValue(ct)).addClass("figure"))
|
|
144
|
+
.append($("<td></td>").addClass("icons"))
|
|
145
|
+
.appendTo(tbody);
|
|
146
|
+
|
|
147
|
+
$("<tr></tr>")
|
|
148
|
+
.append($("<td></td>"))
|
|
149
|
+
.append($("<td></td>").text(`${fact.concept().label()} (${i18next.t('calculation.reported-total')})`).addClass("line-item"))
|
|
150
|
+
.append($("<td></td>").text(fact.readableValue()).addClass("figure"))
|
|
151
|
+
.append($("<td></td>").addClass("icons"))
|
|
152
|
+
.appendTo(tbody);
|
|
153
|
+
if (hasIcons) {
|
|
154
|
+
table.addClass("has-icons");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
displayCalculation(resolvedCalculation) {
|
|
159
|
+
const table = this.node.find("table.calculation-trace");
|
|
160
|
+
const tbody = table.find("tbody");
|
|
161
|
+
// We remove the padding on the icons column (used to indicate
|
|
162
|
+
// duplicate facts) if it is empty to avoid an unsightly gap
|
|
163
|
+
tbody.empty();
|
|
164
|
+
table.removeClass("has-icons");
|
|
165
|
+
if (resolvedCalculation instanceof ResolvedCalc11Calculation) {
|
|
166
|
+
this.populateCalc11Table(resolvedCalculation, table);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
this.populateLegacyCalcTable(resolvedCalculation, table);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
const messageCell = table.find("td.status");
|
|
174
|
+
messageCell.removeClass("inconsistent").removeClass("consistent").removeClass("unchecked");
|
|
175
|
+
if (resolvedCalculation.unchecked()) {
|
|
176
|
+
messageCell.addClass("unchecked").find(".message").text(i18next.t('calculation.does-not-bind'));
|
|
177
|
+
}
|
|
178
|
+
else if (resolvedCalculation.isConsistent()) {
|
|
179
|
+
messageCell.addClass("consistent").find(".message").text(i18next.t('factDetails.calculationIsConsistent'));
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
messageCell.addClass("inconsistent").find(".message").text(i18next.t('factDetails.calculationIsInconsistent'));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
// See COPYRIGHT.md for copyright information
|
|
2
2
|
|
|
3
3
|
import $ from 'jquery';
|
|
4
|
-
import Chart from 'chart.js';
|
|
4
|
+
import { BarController, BarElement, CategoryScale, Chart, LinearScale } from 'chart.js';
|
|
5
5
|
import { AspectSet } from './aspect.js';
|
|
6
6
|
import { wrapLabel } from "./util.js";
|
|
7
7
|
import { Dialog } from './dialog.js';
|
|
8
|
+
import { getVariable } from './theme.js';
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
export class IXBRLChart extends Dialog {
|
|
10
12
|
constructor() {
|
|
11
13
|
super(".dialog.chart");
|
|
14
|
+
this.dataSetColours = [
|
|
15
|
+
getVariable('--colour-primary'),
|
|
16
|
+
getVariable('--colour-secondary'),
|
|
17
|
+
getVariable('--colour-warning'),
|
|
18
|
+
]
|
|
12
19
|
}
|
|
13
20
|
|
|
14
21
|
_multiplierDescription(m) {
|
|
@@ -32,11 +39,7 @@ export class IXBRLChart extends Dialog {
|
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
dataSetColour(i) {
|
|
35
|
-
return [
|
|
36
|
-
'#66cc00',
|
|
37
|
-
'#0094ff',
|
|
38
|
-
'#fbad17'
|
|
39
|
-
][i];
|
|
42
|
+
return this.dataSetColours[i];
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
addAspect(a) {
|
|
@@ -76,7 +79,7 @@ export class IXBRLChart extends Dialog {
|
|
|
76
79
|
covered[dims[1]] = null;
|
|
77
80
|
}
|
|
78
81
|
|
|
79
|
-
const facts = fact.report
|
|
82
|
+
const facts = fact.report.deduplicate(fact.report.getAlignedFacts(fact, covered));
|
|
80
83
|
|
|
81
84
|
/* Get the unique aspect values along each dimension. This is to ensure
|
|
82
85
|
* that we assign facts to datasets consistently (we have one dataset per value
|
|
@@ -97,7 +100,7 @@ export class IXBRLChart extends Dialog {
|
|
|
97
100
|
const uv2 = set2av.uniqueValues();
|
|
98
101
|
|
|
99
102
|
const scale = this._chooseMultiplier(facts);
|
|
100
|
-
const yLabel = fact.
|
|
103
|
+
const yLabel = fact.unitLabel() + " " + this._multiplierDescription(scale);
|
|
101
104
|
const labels = [];
|
|
102
105
|
|
|
103
106
|
const dataSets = [];
|
|
@@ -123,7 +126,7 @@ export class IXBRLChart extends Dialog {
|
|
|
123
126
|
if (dims[1]) {
|
|
124
127
|
covered[dims[1]] = uv2[j].value();
|
|
125
128
|
}
|
|
126
|
-
const dp = fact.report
|
|
129
|
+
const dp = fact.report.getAlignedFacts(fact, covered);
|
|
127
130
|
if (dp.length > 0) {
|
|
128
131
|
dataSets[j].data[i] = dp[0].value()/(10**scale);
|
|
129
132
|
}
|
|
@@ -139,13 +142,13 @@ export class IXBRLChart extends Dialog {
|
|
|
139
142
|
for (const av of fact.aspects()) {
|
|
140
143
|
/* Don't show concept in list of additional aspects */
|
|
141
144
|
if (av.name() != 'c') {
|
|
142
|
-
const a = $("<
|
|
145
|
+
const a = $("<button>")
|
|
143
146
|
.addClass("other-aspect")
|
|
144
147
|
.appendTo($(".other-aspects",c));
|
|
145
148
|
if (dims.includes(av.name())) {
|
|
146
149
|
a.addClass("selected")
|
|
147
150
|
.text(av.label() + ": *")
|
|
148
|
-
.click(
|
|
151
|
+
.on("click", () => this.removeAspect(av.name()));
|
|
149
152
|
}
|
|
150
153
|
else {
|
|
151
154
|
if (av.name() != 'u') {
|
|
@@ -154,7 +157,7 @@ export class IXBRLChart extends Dialog {
|
|
|
154
157
|
a.text(av.label() + ": " + av.valueLabel());
|
|
155
158
|
if (dims.length < 2) {
|
|
156
159
|
a.addClass("addable")
|
|
157
|
-
.click(
|
|
160
|
+
.on("click", () => this.addAspect(av.name()));
|
|
158
161
|
}
|
|
159
162
|
}
|
|
160
163
|
}
|
|
@@ -173,6 +176,7 @@ export class IXBRLChart extends Dialog {
|
|
|
173
176
|
this.setChartSize();
|
|
174
177
|
|
|
175
178
|
const ctx = $("canvas", c);
|
|
179
|
+
Chart.register(BarController, BarElement, CategoryScale, LinearScale);
|
|
176
180
|
const chart = new Chart(ctx, {
|
|
177
181
|
type: "bar",
|
|
178
182
|
data: {
|
|
@@ -183,29 +187,27 @@ export class IXBRLChart extends Dialog {
|
|
|
183
187
|
responsive: true,
|
|
184
188
|
maintainAspectRatio: false,
|
|
185
189
|
scales: {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
},
|
|
190
|
-
scaleLabel: {
|
|
190
|
+
y: {
|
|
191
|
+
beginAtZero: true,
|
|
192
|
+
title: {
|
|
191
193
|
display: true,
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
xAxes: [{
|
|
194
|
+
text: yLabel,
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
x: {
|
|
197
198
|
ticks: {
|
|
198
199
|
autoSkip: false
|
|
199
200
|
}
|
|
200
|
-
}
|
|
201
|
+
}
|
|
201
202
|
}
|
|
202
203
|
|
|
203
204
|
}
|
|
204
205
|
});
|
|
205
|
-
$(window).resize(
|
|
206
|
+
$(window).on("resize", () => {
|
|
206
207
|
this.setChartSize();
|
|
207
208
|
chart.resize();
|
|
208
209
|
});
|
|
210
|
+
$(".other-aspect", c).get(0)?.focus();
|
|
209
211
|
}
|
|
210
212
|
|
|
211
213
|
setChartSize() {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// See COPYRIGHT.md for copyright information
|
|
2
2
|
|
|
3
|
-
import { Fact } from "./fact.js";
|
|
4
3
|
import { IXBRLChart } from "./chart.js";
|
|
5
|
-
import {
|
|
4
|
+
import { ReportSet } from "./reportset.js";
|
|
6
5
|
import { TestInspector } from "./test-utils.js";
|
|
6
|
+
import { NAMESPACE_ISO4217 } from "./util";
|
|
7
7
|
|
|
8
8
|
var testReportData = {
|
|
9
9
|
"prefixes": {
|
|
10
10
|
"eg": "http://www.example.com",
|
|
11
|
-
"iso4217":
|
|
11
|
+
"iso4217": NAMESPACE_ISO4217,
|
|
12
12
|
"e": "http://example.com/entity",
|
|
13
13
|
},
|
|
14
14
|
"concepts": {
|
|
@@ -74,21 +74,22 @@ var testReportData = {
|
|
|
74
74
|
|
|
75
75
|
function testReport(facts, ixData) {
|
|
76
76
|
// Deep copy of standing data
|
|
77
|
-
|
|
77
|
+
const data = JSON.parse(JSON.stringify(testReportData));
|
|
78
78
|
data.facts = facts;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return
|
|
79
|
+
const reportSet = new ReportSet(data);
|
|
80
|
+
reportSet.setIXNodeMap(ixData);
|
|
81
|
+
return reportSet;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
function testFact(factData, ixData) {
|
|
85
85
|
factData.a = factData.a || {};
|
|
86
86
|
factData.a.c = factData.a.c || 'eg:Concept1';
|
|
87
87
|
ixData = ixData || {};
|
|
88
|
-
|
|
88
|
+
const reportSet = testReport({"f1": factData}, {"f1": ixData });
|
|
89
|
+
return reportSet.getItemById("0-f1");
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
|
|
92
|
+
const insp = new TestInspector();
|
|
92
93
|
beforeAll(() => {
|
|
93
94
|
return insp.i18nInit();
|
|
94
95
|
});
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
// See COPYRIGHT.md for copyright information
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { DataType } from "./datatype.js";
|
|
4
|
+
import { Balance } from "./balance.js";
|
|
4
5
|
|
|
5
6
|
export class Concept {
|
|
6
7
|
constructor(report, name) {
|
|
7
|
-
|
|
8
|
+
const c = report.concepts()[name];
|
|
9
|
+
this.hasDefinition = (c !== undefined);
|
|
10
|
+
this._c = c ?? {};
|
|
11
|
+
this.name = name;
|
|
12
|
+
this.report = report;
|
|
8
13
|
}
|
|
9
14
|
|
|
10
15
|
/*
|
|
@@ -22,6 +27,18 @@ export class Concept {
|
|
|
22
27
|
}
|
|
23
28
|
}
|
|
24
29
|
|
|
30
|
+
labels() {
|
|
31
|
+
if (!this._c.labels) {
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
const lang = this.report.reportSet.viewerOptions.language;
|
|
35
|
+
return Object.fromEntries(
|
|
36
|
+
Object.entries(this._c.labels)
|
|
37
|
+
.map(([role, labels]) => [role, labels[lang]])
|
|
38
|
+
.filter(([role, label]) => label !== undefined)
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
25
42
|
references() {
|
|
26
43
|
if (!this._c.r) {
|
|
27
44
|
return [];
|
|
@@ -48,7 +65,11 @@ export class Concept {
|
|
|
48
65
|
}
|
|
49
66
|
|
|
50
67
|
isEnumeration() {
|
|
51
|
-
return Boolean(this._c.e);
|
|
68
|
+
return Boolean(this._c && this._c.e);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
label() {
|
|
72
|
+
return this.report.getLabelOrName(this.name);
|
|
52
73
|
}
|
|
53
74
|
|
|
54
75
|
isTextBlock() {
|
|
@@ -56,6 +77,18 @@ export class Concept {
|
|
|
56
77
|
}
|
|
57
78
|
|
|
58
79
|
typedDomainElement() {
|
|
59
|
-
return this._c.td
|
|
80
|
+
return this._c.td;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
dataType() {
|
|
84
|
+
if (this._c.dt !== undefined) {
|
|
85
|
+
return new DataType(this.report, this._c.dt);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
balance() {
|
|
90
|
+
if (this._c.b !== undefined) {
|
|
91
|
+
return new Balance(this._c.b);
|
|
92
|
+
}
|
|
60
93
|
}
|
|
61
94
|
}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
// See COPYRIGHT.md for copyright information
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { ReportSet } from "./reportset.js";
|
|
4
|
+
import { NAMESPACE_ISO4217 } from "./util";
|
|
5
|
+
import { TestInspector } from "./test-utils.js";
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
const insp = new TestInspector();
|
|
8
|
+
beforeAll(() => {
|
|
9
|
+
insp.i18nInit();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const testReportData = {
|
|
6
13
|
"prefixes": {
|
|
7
14
|
"eg": "http://www.example.com",
|
|
8
|
-
"iso4217":
|
|
15
|
+
"iso4217": NAMESPACE_ISO4217,
|
|
9
16
|
"e": "http://example.com/entity",
|
|
10
17
|
},
|
|
11
18
|
"concepts": {
|
|
@@ -14,14 +21,16 @@ var testReportData = {
|
|
|
14
21
|
"std": {
|
|
15
22
|
"en": "English label"
|
|
16
23
|
}
|
|
17
|
-
}
|
|
24
|
+
},
|
|
25
|
+
"b": "debit"
|
|
18
26
|
},
|
|
19
27
|
"eg:Concept2": {
|
|
20
28
|
"labels": {
|
|
21
29
|
"std": {
|
|
22
30
|
"en": "English label for concept two"
|
|
23
31
|
}
|
|
24
|
-
}
|
|
32
|
+
},
|
|
33
|
+
"b": "credit"
|
|
25
34
|
},
|
|
26
35
|
"eg:Concept3": {
|
|
27
36
|
"labels": {
|
|
@@ -48,7 +57,9 @@ var testReportData = {
|
|
|
48
57
|
};
|
|
49
58
|
|
|
50
59
|
describe("Concept references", () => {
|
|
51
|
-
|
|
60
|
+
const rs = new ReportSet(testReportData);
|
|
61
|
+
rs._initialize();
|
|
62
|
+
const r = rs.reports[0];
|
|
52
63
|
test("Absent reference", () => {
|
|
53
64
|
var c1 = r.getConcept("eg:Concept1");
|
|
54
65
|
expect(c1.referenceValuesAsString()).toEqual("");
|
|
@@ -83,3 +94,16 @@ describe("Concept references", () => {
|
|
|
83
94
|
]);
|
|
84
95
|
});
|
|
85
96
|
});
|
|
97
|
+
|
|
98
|
+
describe("Balance types", () => {
|
|
99
|
+
test("Debit/Credit", () => {
|
|
100
|
+
const rs = new ReportSet(testReportData);
|
|
101
|
+
rs._initialize();
|
|
102
|
+
const r = rs.reports[0];
|
|
103
|
+
expect(r.getConcept("eg:Concept1").balance().balance).toBe("debit");
|
|
104
|
+
expect(r.getConcept("eg:Concept1").balance().label()).toBe("Debit");
|
|
105
|
+
expect(r.getConcept("eg:Concept2").balance().balance).toBe("credit");
|
|
106
|
+
expect(r.getConcept("eg:Concept2").balance().label()).toBe("Credit");
|
|
107
|
+
expect(r.getConcept("eg:Concept3").balance()).toBeUndefined();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// See COPYRIGHT.md for copyright information
|
|
2
|
+
|
|
3
|
+
import i18next from 'i18next';
|
|
4
|
+
import { NAMESPACE_XBRLI } from "./util.js";
|
|
5
|
+
|
|
6
|
+
export class DataType {
|
|
7
|
+
constructor(report, name) {
|
|
8
|
+
this.name = name;
|
|
9
|
+
this.report = report;
|
|
10
|
+
this.qname = report.qname(name);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
label() {
|
|
14
|
+
if (this.qname.namespace == NAMESPACE_XBRLI) {
|
|
15
|
+
return i18next.t(`dataTypes:${this.qname.localname}`, {defaultValue: this.qname.qname});
|
|
16
|
+
}
|
|
17
|
+
return this.report.reportSet.taxonomyNamer.convertQName(this.qname);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// See COPYRIGHT.md for copyright information
|
|
2
|
+
|
|
3
|
+
import { ReportSet } from "./reportset.js";
|
|
4
|
+
import { NAMESPACE_ISO4217, NAMESPACE_XBRLI } from "./util";
|
|
5
|
+
import { TestInspector } from "./test-utils.js";
|
|
6
|
+
|
|
7
|
+
const testReportData = {
|
|
8
|
+
"prefixes": {
|
|
9
|
+
"eg": "http://www.example.com",
|
|
10
|
+
"iso4217": NAMESPACE_ISO4217,
|
|
11
|
+
"xbrli": NAMESPACE_XBRLI,
|
|
12
|
+
"e": "http://example.com/entity",
|
|
13
|
+
},
|
|
14
|
+
"concepts": {
|
|
15
|
+
},
|
|
16
|
+
"facts": {
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function testReport(concept) {
|
|
21
|
+
// Deep copy of standing data
|
|
22
|
+
const data = JSON.parse(JSON.stringify(testReportData));
|
|
23
|
+
data.concepts["eg:concept"] = concept;
|
|
24
|
+
const reportSet = new ReportSet(data);
|
|
25
|
+
reportSet.setIXNodeMap({});
|
|
26
|
+
return reportSet.reports[0];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const insp = new TestInspector();
|
|
30
|
+
beforeAll(() => {
|
|
31
|
+
insp.i18nInit();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("Data types", () => {
|
|
35
|
+
test("Monetary", () => {
|
|
36
|
+
const r1 = testReport({ "dt": "xbrli:monetaryItemType" });
|
|
37
|
+
expect(r1.getConcept("eg:concept").dataType().label()).toBe("Monetary");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("String", () => {
|
|
41
|
+
const r1 = testReport({ "dt": "xbrli:stringItemType" });
|
|
42
|
+
expect(r1.getConcept("eg:concept").dataType().label()).toBe("String");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("Unknown xbrli", () => {
|
|
46
|
+
const r1 = testReport({ "dt": "xbrli:unknown" });
|
|
47
|
+
expect(r1.getConcept("eg:concept").dataType().label()).toBe("xbrli:unknown");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("Custom", () => {
|
|
51
|
+
const r1 = testReport({ "dt": "eg:stringItemType" });
|
|
52
|
+
expect(r1.getConcept("eg:concept").dataType().label()).toBe("eg:stringItemType");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("No datatype", () => {
|
|
56
|
+
const r1 = testReport({});
|
|
57
|
+
expect(r1.getConcept("eg:concept").dataType()).toBeUndefined();
|
|
58
|
+
});
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
@@ -6,9 +6,9 @@ export class Dialog {
|
|
|
6
6
|
constructor(selector) {
|
|
7
7
|
this.node = $("#dialog-templates").find(selector).clone().appendTo("#ixv #dialog-container");
|
|
8
8
|
|
|
9
|
-
$('.close', this.node).click(
|
|
10
|
-
$(document).
|
|
11
|
-
if (e.
|
|
9
|
+
$('.close', this.node).on("click", () => this.close());
|
|
10
|
+
$(document).on("keyup", (e) => {
|
|
11
|
+
if (e.which === 27) {
|
|
12
12
|
this.close();
|
|
13
13
|
}
|
|
14
14
|
});
|
|
@@ -28,11 +28,13 @@ export class Dialog {
|
|
|
28
28
|
|
|
29
29
|
close() {
|
|
30
30
|
$('.dialog-mask').hide();
|
|
31
|
-
this.node.
|
|
31
|
+
this.node.get(0).close();
|
|
32
|
+
this.node.remove();
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
show() {
|
|
35
36
|
$('.dialog-mask').show();
|
|
37
|
+
this.node.get(0).showModal();
|
|
36
38
|
this.node.show();
|
|
37
39
|
}
|
|
38
40
|
}
|
|
@@ -5,21 +5,21 @@ export class DocOrderIndex {
|
|
|
5
5
|
this.index = [];
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
addItem(
|
|
9
|
-
this.index.push({
|
|
8
|
+
addItem(vuid, docIndex) {
|
|
9
|
+
this.index.push({vuid: vuid, docIndex: docIndex});
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
getAdjacentItem(
|
|
13
|
-
const currentIndex = this.index.findIndex(n => n.
|
|
12
|
+
getAdjacentItem(vuid, offset) {
|
|
13
|
+
const currentIndex = this.index.findIndex(n => n.vuid === vuid);
|
|
14
14
|
const l = this.index.length;
|
|
15
|
-
return this.index[(currentIndex + offset + l) % l].
|
|
15
|
+
return this.index[(currentIndex + offset + l) % l].vuid;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
getFirstInDocument(docIndex) {
|
|
19
|
-
return this.index.filter(n => n.docIndex
|
|
19
|
+
return this.index.filter(n => n.docIndex === docIndex)[0].vuid;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
getLastInDocument(docIndex) {
|
|
23
|
-
return this.index.filter(n => n.docIndex
|
|
23
|
+
return this.index.filter(n => n.docIndex === docIndex).at(-1).vuid;
|
|
24
24
|
}
|
|
25
25
|
}
|