UNPKG

4.74 kBJavaScriptView Raw
1var { DataView } = require('vis-data');
2
3/**
4 * @class Filter
5 *
6 * @param {DataGroup} dataGroup the data group
7 * @param {number} column The index of the column to be filtered
8 * @param {Graph3d} graph The graph
9 */
10function Filter (dataGroup, column, graph) {
11 this.dataGroup = dataGroup;
12 this.column = column;
13 this.graph = graph; // the parent graph
14
15 this.index = undefined;
16 this.value = undefined;
17
18 // read all distinct values and select the first one
19 this.values = dataGroup.getDistinctValues(this.column);
20
21 if (this.values.length > 0) {
22 this.selectValue(0);
23 }
24
25 // create an array with the filtered datapoints. this will be loaded afterwards
26 this.dataPoints = [];
27
28 this.loaded = false;
29 this.onLoadCallback = undefined;
30
31 if (graph.animationPreload) {
32 this.loaded = false;
33 this.loadInBackground();
34 }
35 else {
36 this.loaded = true;
37 }
38}
39
40
41/**
42 * Return the label
43 * @return {string} label
44 */
45Filter.prototype.isLoaded = function() {
46 return this.loaded;
47};
48
49
50/**
51 * Return the loaded progress
52 * @return {number} percentage between 0 and 100
53 */
54Filter.prototype.getLoadedProgress = function() {
55 var len = this.values.length;
56
57 var i = 0;
58 while (this.dataPoints[i]) {
59 i++;
60 }
61
62 return Math.round(i / len * 100);
63};
64
65
66/**
67 * Return the label
68 * @return {string} label
69 */
70Filter.prototype.getLabel = function() {
71 return this.graph.filterLabel;
72};
73
74
75/**
76 * Return the columnIndex of the filter
77 * @return {number} columnIndex
78 */
79Filter.prototype.getColumn = function() {
80 return this.column;
81};
82
83/**
84 * Return the currently selected value. Returns undefined if there is no selection
85 * @return {*} value
86 */
87Filter.prototype.getSelectedValue = function() {
88 if (this.index === undefined)
89 return undefined;
90
91 return this.values[this.index];
92};
93
94/**
95 * Retrieve all values of the filter
96 * @return {Array} values
97 */
98Filter.prototype.getValues = function() {
99 return this.values;
100};
101
102/**
103 * Retrieve one value of the filter
104 * @param {number} index
105 * @return {*} value
106 */
107Filter.prototype.getValue = function(index) {
108 if (index >= this.values.length)
109 throw new Error('Index out of range');
110
111 return this.values[index];
112};
113
114
115/**
116 * Retrieve the (filtered) dataPoints for the currently selected filter index
117 * @param {number} [index] (optional)
118 * @return {Array} dataPoints
119 */
120Filter.prototype._getDataPoints = function(index) {
121 if (index === undefined)
122 index = this.index;
123
124 if (index === undefined)
125 return [];
126
127 var dataPoints;
128 if (this.dataPoints[index]) {
129 dataPoints = this.dataPoints[index];
130 }
131 else {
132 var f = {};
133 f.column = this.column;
134 f.value = this.values[index];
135
136 var dataView = new DataView(this.dataGroup.getDataSet(), {filter: function (item) {return (item[f.column] == f.value);}}).get();
137 dataPoints = this.dataGroup._getDataPoints(dataView);
138
139 this.dataPoints[index] = dataPoints;
140 }
141
142 return dataPoints;
143};
144
145
146
147/**
148 * Set a callback function when the filter is fully loaded.
149 *
150 * @param {function} callback
151 */
152Filter.prototype.setOnLoadCallback = function(callback) {
153 this.onLoadCallback = callback;
154};
155
156
157/**
158 * Add a value to the list with available values for this filter
159 * No double entries will be created.
160 * @param {number} index
161 */
162Filter.prototype.selectValue = function(index) {
163 if (index >= this.values.length)
164 throw new Error('Index out of range');
165
166 this.index = index;
167 this.value = this.values[index];
168};
169
170/**
171 * Load all filtered rows in the background one by one
172 * Start this method without providing an index!
173 *
174 * @param {number} [index=0]
175 */
176Filter.prototype.loadInBackground = function(index) {
177 if (index === undefined)
178 index = 0;
179
180 var frame = this.graph.frame;
181
182 if (index < this.values.length) {
183 // create a progress box
184 if (frame.progress === undefined) {
185 frame.progress = document.createElement('DIV');
186 frame.progress.style.position = 'absolute';
187 frame.progress.style.color = 'gray';
188 frame.appendChild(frame.progress);
189 }
190 var progress = this.getLoadedProgress();
191 frame.progress.innerHTML = 'Loading animation... ' + progress + '%';
192 // TODO: this is no nice solution...
193 frame.progress.style.bottom = 60 + 'px'; // TODO: use height of slider
194 frame.progress.style.left = 10 + 'px';
195
196 var me = this;
197 setTimeout(function() {me.loadInBackground(index+1);}, 10);
198 this.loaded = false;
199 }
200 else {
201 this.loaded = true;
202
203 // remove the progress box
204 if (frame.progress !== undefined) {
205 frame.removeChild(frame.progress);
206 frame.progress = undefined;
207 }
208
209 if (this.onLoadCallback)
210 this.onLoadCallback();
211 }
212};
213
214module.exports = Filter;