UNPKG

11.9 kBJavaScriptView Raw
1/**
2 * ag-grid - Advanced Data Grid / Data Table supporting Javascript / React / AngularJS / Web Components
3 * @version v18.1.2
4 * @link http://www.ag-grid.com/
5 * @license MIT
6 */
7"use strict";
8var __extends = (this && this.__extends) || (function () {
9 var extendStatics = Object.setPrototypeOf ||
10 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
11 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
12 return function (d, b) {
13 extendStatics(d, b);
14 function __() { this.constructor = d; }
15 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
16 };
17})();
18Object.defineProperty(exports, "__esModule", { value: true });
19var utils_1 = require("../../utils");
20var beanStub_1 = require("../../context/beanStub");
21var rowNodeBlock_1 = require("./rowNodeBlock");
22var RowNodeCache = (function (_super) {
23 __extends(RowNodeCache, _super);
24 function RowNodeCache(cacheParams) {
25 var _this = _super.call(this) || this;
26 _this.maxRowFound = false;
27 _this.blocks = {};
28 _this.blockCount = 0;
29 _this.virtualRowCount = cacheParams.initialRowCount;
30 _this.cacheParams = cacheParams;
31 return _this;
32 }
33 RowNodeCache.prototype.destroy = function () {
34 var _this = this;
35 _super.prototype.destroy.call(this);
36 this.forEachBlockInOrder(function (block) { return _this.destroyBlock(block); });
37 };
38 RowNodeCache.prototype.init = function () {
39 var _this = this;
40 this.active = true;
41 this.addDestroyFunc(function () { return _this.active = false; });
42 };
43 RowNodeCache.prototype.isActive = function () {
44 return this.active;
45 };
46 RowNodeCache.prototype.getVirtualRowCount = function () {
47 return this.virtualRowCount;
48 };
49 RowNodeCache.prototype.hack_setVirtualRowCount = function (virtualRowCount) {
50 this.virtualRowCount = virtualRowCount;
51 };
52 RowNodeCache.prototype.isMaxRowFound = function () {
53 return this.maxRowFound;
54 };
55 // listener on EVENT_LOAD_COMPLETE
56 RowNodeCache.prototype.onPageLoaded = function (event) {
57 this.cacheParams.rowNodeBlockLoader.loadComplete();
58 this.checkBlockToLoad();
59 // if we are not active, then we ignore all events, otherwise we could end up getting the
60 // grid to refresh even though we are no longer the active cache
61 if (!this.isActive()) {
62 return;
63 }
64 this.logger.log("onPageLoaded: page = " + event.page.getBlockNumber() + ", lastRow = " + event.lastRow);
65 if (event.success) {
66 this.checkVirtualRowCount(event.page, event.lastRow);
67 }
68 };
69 RowNodeCache.prototype.purgeBlocksIfNeeded = function (blockToExclude) {
70 var _this = this;
71 // no purge if user didn't give maxBlocksInCache
72 if (utils_1.Utils.missing(this.cacheParams.maxBlocksInCache)) {
73 return;
74 }
75 // no purge if block count is less than max allowed
76 if (this.blockCount <= this.cacheParams.maxBlocksInCache) {
77 return;
78 }
79 // put all candidate blocks into a list for sorting
80 var blocksForPurging = [];
81 this.forEachBlockInOrder(function (block) {
82 // we exclude checking for the page just created, as this has yet to be accessed and hence
83 // the lastAccessed stamp will not be updated for the first time yet
84 if (block === blockToExclude) {
85 return;
86 }
87 blocksForPurging.push(block);
88 });
89 // note: need to verify that this sorts items in the right order
90 blocksForPurging.sort(function (a, b) { return b.getLastAccessed() - a.getLastAccessed(); });
91 // we remove (maxBlocksInCache - 1) as we already excluded the 'just created' page.
92 // in other words, after the splice operation below, we have taken out the blocks
93 // we want to keep, which means we are left with blocks that we can potentially purge
94 var blocksToKeep = this.cacheParams.maxBlocksInCache - 1;
95 blocksForPurging.splice(0, blocksToKeep);
96 // try and purge each block
97 blocksForPurging.forEach(function (block) {
98 // we never purge blocks if they are open, as purging them would mess up with
99 // our indexes, it would be very messy to restore the purged block to it's
100 // previous state if it had open children (and what if open children of open
101 // children, jeeeesus, just thinking about it freaks me out) so best is have a
102 // rule, if block is open, we never purge.
103 if (block.isAnyNodeOpen(_this.virtualRowCount)) {
104 return;
105 }
106 // at this point, block is not needed, and no open nodes, so burn baby burn
107 _this.removeBlockFromCache(block);
108 });
109 };
110 RowNodeCache.prototype.postCreateBlock = function (newBlock) {
111 newBlock.addEventListener(rowNodeBlock_1.RowNodeBlock.EVENT_LOAD_COMPLETE, this.onPageLoaded.bind(this));
112 this.setBlock(newBlock.getBlockNumber(), newBlock);
113 this.purgeBlocksIfNeeded(newBlock);
114 this.checkBlockToLoad();
115 };
116 RowNodeCache.prototype.removeBlockFromCache = function (blockToRemove) {
117 if (!blockToRemove) {
118 return;
119 }
120 this.destroyBlock(blockToRemove);
121 // we do not want to remove the 'loaded' event listener, as the
122 // concurrent loads count needs to be updated when the load is complete
123 // if the purged page is in loading state
124 };
125 // gets called after: 1) block loaded 2) block created 3) cache refresh
126 RowNodeCache.prototype.checkBlockToLoad = function () {
127 this.cacheParams.rowNodeBlockLoader.checkBlockToLoad();
128 };
129 RowNodeCache.prototype.checkVirtualRowCount = function (block, lastRow) {
130 // if client provided a last row, we always use it, as it could change between server calls
131 // if user deleted data and then called refresh on the grid.
132 if (typeof lastRow === 'number' && lastRow >= 0) {
133 this.virtualRowCount = lastRow;
134 this.maxRowFound = true;
135 this.onCacheUpdated();
136 }
137 else if (!this.maxRowFound) {
138 // otherwise, see if we need to add some virtual rows
139 var lastRowIndex = (block.getBlockNumber() + 1) * this.cacheParams.blockSize;
140 var lastRowIndexPlusOverflow = lastRowIndex + this.cacheParams.overflowSize;
141 if (this.virtualRowCount < lastRowIndexPlusOverflow) {
142 this.virtualRowCount = lastRowIndexPlusOverflow;
143 this.onCacheUpdated();
144 }
145 else if (this.cacheParams.dynamicRowHeight) {
146 // the only other time is if dynamic row height, as loading rows
147 // will change the height of the block, given the height of the rows
148 // is only known after the row is loaded.
149 this.onCacheUpdated();
150 }
151 }
152 };
153 RowNodeCache.prototype.setVirtualRowCount = function (rowCount, maxRowFound) {
154 this.virtualRowCount = rowCount;
155 // if undefined is passed, we do not set this value, if one of {true,false}
156 // is passed, we do set the value.
157 if (utils_1.Utils.exists(maxRowFound)) {
158 this.maxRowFound = maxRowFound;
159 }
160 // if we are still searching, then the row count must not end at the end
161 // of a particular page, otherwise the searching will not pop into the
162 // next page
163 if (!this.maxRowFound) {
164 if (this.virtualRowCount % this.cacheParams.blockSize === 0) {
165 this.virtualRowCount++;
166 }
167 }
168 this.onCacheUpdated();
169 };
170 RowNodeCache.prototype.forEachNodeDeep = function (callback, sequence) {
171 var _this = this;
172 this.forEachBlockInOrder(function (block) {
173 block.forEachNodeDeep(callback, sequence, _this.virtualRowCount);
174 });
175 };
176 RowNodeCache.prototype.forEachBlockInOrder = function (callback) {
177 var ids = this.getBlockIdsSorted();
178 this.forEachBlockId(ids, callback);
179 };
180 RowNodeCache.prototype.forEachBlockInReverseOrder = function (callback) {
181 var ids = this.getBlockIdsSorted().reverse();
182 this.forEachBlockId(ids, callback);
183 };
184 RowNodeCache.prototype.forEachBlockId = function (ids, callback) {
185 var _this = this;
186 ids.forEach(function (id) {
187 var block = _this.blocks[id];
188 callback(block, id);
189 });
190 };
191 RowNodeCache.prototype.getBlockIdsSorted = function () {
192 // get all page id's as NUMBERS (not strings, as we need to sort as numbers) and in descending order
193 var numberComparator = function (a, b) { return a - b; }; // default comparator for array is string comparison
194 var blockIds = Object.keys(this.blocks).map(function (idStr) { return parseInt(idStr); }).sort(numberComparator);
195 return blockIds;
196 };
197 RowNodeCache.prototype.getBlock = function (blockId) {
198 return this.blocks[blockId];
199 };
200 RowNodeCache.prototype.setBlock = function (id, block) {
201 this.blocks[id] = block;
202 this.blockCount++;
203 this.cacheParams.rowNodeBlockLoader.addBlock(block);
204 };
205 RowNodeCache.prototype.destroyBlock = function (block) {
206 delete this.blocks[block.getBlockNumber()];
207 block.destroy();
208 this.blockCount--;
209 this.cacheParams.rowNodeBlockLoader.removeBlock(block);
210 };
211 // gets called 1) row count changed 2) cache purged 3) items inserted
212 RowNodeCache.prototype.onCacheUpdated = function () {
213 if (this.isActive()) {
214 // this results in both row models (infinite and server side) firing ModelUpdated,
215 // however server side row model also updates the row indexes first
216 var event_1 = {
217 type: RowNodeCache.EVENT_CACHE_UPDATED
218 };
219 this.dispatchEvent(event_1);
220 }
221 };
222 RowNodeCache.prototype.purgeCache = function () {
223 var _this = this;
224 this.forEachBlockInOrder(function (block) { return _this.removeBlockFromCache(block); });
225 this.onCacheUpdated();
226 };
227 RowNodeCache.prototype.getRowNodesInRange = function (firstInRange, lastInRange) {
228 var _this = this;
229 var result = [];
230 var lastBlockId = -1;
231 var inActiveRange = false;
232 var numberSequence = new utils_1.NumberSequence();
233 // if only one node passed, we start the selection at the top
234 if (utils_1.Utils.missing(firstInRange)) {
235 inActiveRange = true;
236 }
237 var foundGapInSelection = false;
238 this.forEachBlockInOrder(function (block, id) {
239 if (foundGapInSelection)
240 return;
241 if (inActiveRange && (lastBlockId + 1 !== id)) {
242 foundGapInSelection = true;
243 return;
244 }
245 lastBlockId = id;
246 block.forEachNodeShallow(function (rowNode) {
247 var hitFirstOrLast = rowNode === firstInRange || rowNode === lastInRange;
248 if (inActiveRange || hitFirstOrLast) {
249 result.push(rowNode);
250 }
251 if (hitFirstOrLast) {
252 inActiveRange = !inActiveRange;
253 }
254 }, numberSequence, _this.virtualRowCount);
255 });
256 // inActiveRange will be still true if we never hit the second rowNode
257 var invalidRange = foundGapInSelection || inActiveRange;
258 return invalidRange ? [] : result;
259 };
260 RowNodeCache.EVENT_CACHE_UPDATED = 'cacheUpdated';
261 return RowNodeCache;
262}(beanStub_1.BeanStub));
263exports.RowNodeCache = RowNodeCache;