@nativescript/core
Version:
A JavaScript library providing an easy to use api for interacting with iOS and Android platform APIs.
133 lines • 4.3 kB
JavaScript
import { Observable } from '../observable';
import { ChangeType } from '../observable-array';
/**
* Advanced array like class that helps loading items on demand.
*/
export class VirtualArray extends Observable {
constructor(length = 0) {
super();
this._length = length;
this._cache = {};
this._requestedIndexes = [];
this._loadedIndexes = [];
}
/**
* Gets or sets length for the virtual array.
*/
get length() {
return this._length;
}
set length(value) {
if (this._length !== value) {
const index = this._length;
const count = value - this._length;
this._length = value;
this.notify({
eventName: ChangeType.Change,
object: this,
action: count > 0 ? ChangeType.Add : ChangeType.Delete,
index: index,
removed: new Array(count < 0 ? Math.abs(count) : 0),
addedCount: count > 0 ? count : 0,
});
}
}
get loadSize() {
return this._loadSize;
}
set loadSize(value) {
this._loadSize = value;
}
getItem(index) {
const item = this._cache[index];
if (item === undefined) {
if (index >= 0 && index < this.length && this._requestedIndexes.indexOf(index) < 0 && this._loadedIndexes.indexOf(index) < 0) {
this.requestItems(index);
}
}
return item;
}
setItem(index, value) {
if (this._cache[index] !== value) {
this.load(index, [value]);
}
}
/**
* Loads items from an array starting at index.
*/
load(index, items) {
for (let i = 0; i < items.length; i++) {
const itemIndex = index + i;
this._cache[itemIndex] = items[i];
this._requestedIndexes.splice(this._requestedIndexes.indexOf(itemIndex), 1);
if (this._loadedIndexes.indexOf(itemIndex) < 0) {
this._loadedIndexes.push(itemIndex);
}
}
// Remove requested but never loaded indexes.
if (this._requestedIndexes.length > 0) {
for (let i = 0; i < this.loadSize - items.length; i++) {
this._requestedIndexes.splice(this._requestedIndexes.indexOf(index + i), 1);
}
}
this.notify({
eventName: ChangeType.Change,
object: this,
action: ChangeType.Update,
index: index,
removed: new Array(items.length),
addedCount: items.length,
});
}
requestItems(index) {
const indexesToLoad = [];
const pageIndex = this._loadSize > 0 ? this._loadSize * Math.floor(index / this._loadSize) : index;
let count = 0;
let start = -1;
for (let i = 0; i < this.loadSize; i++) {
const itemIndex = pageIndex + i;
if (itemIndex >= this._length) {
break;
}
if (this._loadedIndexes.indexOf(itemIndex) < 0) {
if (start < 0) {
start = itemIndex;
}
indexesToLoad.push(itemIndex);
if (this._requestedIndexes.indexOf(itemIndex) < 0) {
this._requestedIndexes.push(itemIndex);
}
count++;
}
else {
if (count > 0) {
this.notify({
eventName: VirtualArray.itemsLoadingEvent,
object: this,
index: start,
count: count,
});
}
start = -1;
count = 0;
}
}
if (start >= 0 && count > 0) {
this.notify({
eventName: VirtualArray.itemsLoadingEvent,
object: this,
index: start,
count: count,
});
}
}
}
/**
* String value used when hooking to change event.
*/
VirtualArray.changeEvent = ChangeType.Change;
/**
* String value used when hooking to itemsLoading event.
*/
VirtualArray.itemsLoadingEvent = 'itemsLoading';
//# sourceMappingURL=index.js.map