UNPKG

vasille

Version:

The first Developer eXperience Orientated front-end framework (core library).

153 lines (152 loc) 4.44 kB
import { Listener } from "./listener.js"; /** * Model based on Array class * @extends Array * @implements IModel */ export class ArrayModel extends Array { /** * @param data {Array} input data */ constructor(data) { super(); this.passive = false; this.listener = new Listener(); if (data instanceof Array) { for (let i = 0; i < data.length; i++) { super.push(data[i]); } } } /* Array members */ /** * Calls Array.fill and notify about changes * @param value {*} value to fill with * @param start {?number} begin index * @param end {?number} end index */ fill(value, start, end) { this.passive = true; /* istanbul ignore else */ if (!start) { start = 0; } /* istanbul ignore else */ if (!end) { end = this.length; } for (let i = start; i < end; i++) { this.listener.emitRemoved(this[i], this[i]); this[i] = value; this.listener.emitAdded(value, value); } this.passive = false; return this; } /** * Calls Array.pop and notify about changes * @return {*} removed value */ pop() { this.passive = true; const v = super.pop(); /* istanbul ignore else */ if (v !== undefined) { this.listener.emitRemoved(v, v); } this.passive = false; return v; } /** * Calls Array.push and notify about changes * @param items {...*} values to push * @return {number} new length of array */ push(...items) { this.passive = true; items.forEach(item => { this.listener.emitAdded(item, item); super.push(item); }); this.passive = false; return this.length; } /** * Calls Array.shift and notify about changed * @return {*} the shifted value */ shift() { this.passive = true; const v = super.shift(); /* istanbul ignore else */ if (v !== undefined) { this.listener.emitRemoved(v, v); } this.passive = false; return v; } /** * Calls Array.splice and notify about changed * @param start {number} start index * @param deleteCount {?number} delete count * @param items {...*} * @return {ArrayModel} a pointer to this */ splice(start, deleteCount, ...items) { this.passive = true; start = Math.min(start, this.length); deleteCount = typeof deleteCount === "number" ? deleteCount : this.length - start; const before = this[start + deleteCount]; for (let i = 0; i < deleteCount; i++) { const index = start + deleteCount - i - 1; /* istanbul ignore else */ if (this[index] !== undefined) { this.listener.emitRemoved(this[index], this[index]); } } for (let i = 0; i < items.length; i++) { this.listener.emitAdded(before, items[i]); } this.passive = false; return new ArrayModel(super.splice(start, deleteCount, ...items)); } /** * Calls Array.unshift and notify about changed * @param items {...*} values to insert * @return {number} the length after prepend */ unshift(...items) { this.passive = true; for (let i = 0; i < items.length; i++) { this.listener.emitAdded(this[i], items[i]); } const r = super.unshift(...items); this.passive = false; return r; } replace(at, with_) { this.passive = true; this.listener.emitAdded(this[at], with_); this.listener.emitRemoved(this[at], this[at]); this[at] = with_; this.passive = false; return this; } destroy() { this.splice(0); } } export function proxyArrayModel(arr) { return new Proxy(arr, { set(target, p, newValue, receiver) { if (!arr.passive && typeof p === "string") { const index = parseInt(p); if (Number.isFinite(index)) { arr.replace(index, newValue); return true; } } return Reflect.set(target, p, newValue, receiver); }, }); }