lively.lang_array-projection.js
/**
* Accessor to sub-ranges of arrays. This is used, for example, for rendering
* large lists or tables in which only a part of the items should be used for
* processing or rendering.
*
* An array projection provides convenient access and
* can apply operations to sub-ranges.
* @module lively.lang/array-projection
*/
/**
* Create a projection.
*
* ```
* arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 1)
* => { array: [/.../], from: 1, to: 5 }
* ```
*/
function create (array, length, optStartIndex) {
let startIndex = optStartIndex || 0;
if (startIndex + length > array.length) { startIndex -= startIndex + length - array.length; }
return { array, from: startIndex, to: startIndex + length };
}
/**
* Convert a projection back to an array.
*/
function toArray (projection) {
return projection.array.slice(projection.from, projection.to);
}
/**
* Maps index from original Array to projection.
*
* ```
* var proj = arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 3);
* arrayProjection.originalToProjectedIndex(proj, 1) => null
* arrayProjection.originalToProjectedIndex(proj, 3) => 0
* arrayProjection.originalToProjectedIndex(proj, 5) => 2
* ```
*/
function originalToProjectedIndex (projection, index) {
return index < projection.from || index >= projection.to
? null : index - projection.from;
}
/**
* Inverse to `originalToProjectedIndex`.
* ```
* var proj = arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 3);
* projectedToOriginalIndex(proj, 1) => 4
* ```
*/
function projectedToOriginalIndex (projection, index) {
if (index < 0 || index > projection.to - projection.from) return null;
return projection.from + index;
}
/**
* Computes how the projection needs to shift minimally (think "scroll"
* down or up) so that index becomes "visible" in projection.
* ```
* var proj = arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 3);
* arrayProjection.transformToIncludeIndex(proj, 1)
* => { array: [/.../], from: 1, to: 5 }
* ```
*/
function transformToIncludeIndex (projection, index) {
if (!(index in projection.array)) return null;
let delta = 0;
if (index < projection.from) delta = -projection.from + index;
if (index >= projection.to) delta = index - projection.to + 1;
if (delta === 0) return projection;
return create(
projection.array,
projection.to - projection.from,
projection.from + delta);
}
export {
create,
toArray,
originalToProjectedIndex,
projectedToOriginalIndex,
transformToIncludeIndex
};