relu-core
Version:
147 lines (128 loc) • 3.32 kB
JavaScript
var base = require("./base");
module.exports = function rpElement(array, index) {
if(array.elements && array.elements[index])
return array.elements[index].temporary();
var p = base();
p.constructor = rpElement;
p.index = index;
p.parent = array;
p._info = function() { return "[" + index + "]" };
p._actionsList = function() {
if(index < 0) return null;
var al = array._actionsList();
if(!al) return null;
return al.atPath([index]);
};
p._actionsTarget = function() {
if(index < 0) return null;
var at = array._actionsTarget();
if(!at) return null;
return at(index);
};
p._get = function() {
p.depend();
return p._getUndependend();
};
p._getUndependend = function() {
var a = array._getUndependend();
return getValue(a);
};
function getValue(a) {
if(index < 0) return undefined;
if(!Array.isArray(a)) return undefined;
if(a.length <= index) return undefined;
return a[index];
}
if(!array.elements)
array.elements = {};
array.elements[index] = p;
array.onUpdated(onUpdated, true);
array.onAdded(onAdded, true);
array.onRemoved(onRemoved, true);
array.onNested(onNested);
array.ref(p);
p.onceDisposed(function() {
if(index >= 0) disconnect();
p.index = index = -1;
});
p.isConst = function() {
return array.isConst();
};
p.writable = function() {
return array.writable();
};
function disconnect() {
array.removeUpdatedListener(onUpdated);
array.removeAddedListener(onAdded);
array.removeRemovedListener(onRemoved);
array.removeNestedListener(onNested);
if(array.elements[index] === p)
delete array.elements[index];
array.unref(p);
};
p.remove = function() {
if(index < 0) throw new Error("Item is already removed");
if(!Array.isArray(p.parent._getUndependend())) throw new Error("Parent is not an array");
if(index >= p.parent._getUndependend().length) throw new Error("Item is out of range (weird)");
array.spliceBefore(index, 1);
};
function onUpdated(newValue, oldValue) {
if(index < 0) return;
disconnect();
p.index = index = -1;
var old = getValue(oldValue);
if(old !== undefined) {
p._updated(undefined, old);
p._changed()
}
}
function onAdded(idx) {
if(index < 0) return;
if(idx <= index) {
if(array.elements[index] === p)
delete array.elements[index];
p.index = ++index;
array.elements[index] = p;
}
}
function onRemoved(idx, oldValue) {
if(index < 0) return;
if(idx < index) {
if(array.elements[index] === p)
delete array.elements[index];
p.index = --index;
array.elements[index] = p;
} else if(idx === index) {
disconnect();
p.index = index = -1;
var value = getValue(oldValue);
if(value !== undefined) {
p._updated(undefined, value);
p._changed();
}
}
}
function onNested(type, path, a, b) {
if(path[0] === index) {
if(path.length > 1)
p._nested(type, path.slice(1), a, b);
else {
switch(type) {
case "updated":
p._updated(a, b);
break;
case "added":
p._added(a, b);
break;
case "removed":
p._removed(a, b);
break;
case "changed":
p._changed();
break;
}
}
}
}
return p;
};