relu-core
Version:
296 lines (264 loc) • 8.6 kB
JavaScript
var base = require("./base");
var variable = require("./variable");
var restricted = require("./restricted");
module.exports = function rpDelegated(d) {
var p = base();
p.constructor = rpDelegated;
p.origin = d;
d.onChanged(onDelegateChanged);
d.onUpdated(onDelegateUpdated);
d.onAdded(onDelegateAdded);
d.onRemoved(onDelegateRemoved);
d.ref(p);
var varWritable = {
set: function(v) {
this.v = v;
},
v: false
};
var writableRp = null;
var currentTargetElementListeners = [];
var currentTarget = d._getUndependend();
connect();
varWritable = variable(varWritable.v);
p._writable = restricted(varWritable).ref(p);
p.onceDisposed(function() {
disconnect();
d.removeChangedListener(onDelegateChanged);
d.removeUpdatedListener(onDelegateUpdated);
d.removeAddedListener(onDelegateAdded);
d.removeRemovedListener(onDelegateRemoved);
d.unref(p);
p._writable.unref(p);
});
p.isConst = function() {
if(!d.isConst()) return false;
if(!currentTarget) return true;
if(Array.isArray(currentTarget)) return currentTarget.every(function(item) {
return item.isConst();
});
return currentTarget.isConst();
};
p._get = function() {
p.depend();
return p._getUndependend();
};
var theArray;
if(Array.isArray(currentTarget)) {
theArray = currentTarget.map(function(item) {
return item._getUndependend();
});
}
p._getUndependend = function() {
if(!currentTarget) return undefined;
if(Array.isArray(currentTarget)) {
return theArray;
}
return currentTarget._getUndependend();
};
p._actionsList = function() {
if(!currentTarget) throw new Error("delegated has no target");
if(Array.isArray(currentTarget)) throw new Error("A delegated array is not writable");
return currentTarget._actionsList();
};
p._actionsTarget = function() {
if(!currentTarget) throw new Error("delegated has no target");
if(Array.isArray(currentTarget)) return function(idx) { return currentTarget[idx]._actionsTarget() };
return currentTarget._actionsTarget();
};
p._makeAttr = function(name, initial) {
return rpDelegated(d.computed(function(x) {
return x.attr(name, initial);
}));
};
var superElement = p._element;
p._element = function(x) {
if(!currentTarget) throw new Error("delegated has no target");
if(!Array.isArray(currentTarget))
return superElement.call(this, x);
return currentTarget[x];
};
var superProperty = p._property;
p._property = function(x) {
if(!currentTarget) throw new Error("delegated has no target");
if(!Array.isArray(currentTarget))
return superProperty.call(this, x);
throw new Error("Cannot get a property of delegated");
};
function disconnect(what, _writableRp, _currentTargetElementListeners) {
if(!what) {
what = currentTarget;
_writableRp = writableRp;
writableRp = null;
_currentTargetElementListeners = currentTargetElementListeners;
}
if(Array.isArray(what)) {
what.forEach(function(item, idx) {
item.removeUpdatedListener(_currentTargetElementListeners[idx].updated);
item.removeChangedListener(_currentTargetElementListeners[idx].changed);
item.removeAddedListener(_currentTargetElementListeners[idx].added);
item.removeRemovedListener(_currentTargetElementListeners[idx].removed);
item.removeNestedListener(_currentTargetElementListeners[idx].nested);
item.unref(p);
});
} else if(what) {
if(_writableRp && !_writableRp.isConst()) {
_writableRp.removeChangedListener(onWritableChanged);
_writableRp.unref(p);
_writableRp = null;
}
what.removeChangedListener(onChanged);
what.removeUpdatedListener(onUpdated);
what.removeAddedListener(onItemAdded);
what.removeRemovedListener(onItemRemoved);
what.removeNestedListener(onItemNested);
what.unref(p);
}
}
function connect() {
if(Array.isArray(currentTarget)) {
currentTargetElementListeners = [];
currentTarget.forEach(function(item) {
var l = {
target: item,
updated: onElementUpdated.bind(null, item),
changed: onElementChanged.bind(null, item),
added: onElementAdded.bind(null, item),
removed: onElementRemoved.bind(null, item),
nested: onElementNested.bind(null, item)
};
currentTargetElementListeners.push(l);
item.onUpdated(l.updated);
item.onChanged(l.changed);
item.onAdded(l.added);
item.onRemoved(l.removed);
item.onNested(l.nested);
item.ref(p);
});
varWritable.set(false);
} else if(currentTarget) {
var _writableRp = currentTarget.writable();
if(!_writableRp.isConst()) {
_writableRp.onChanged(onWritableChanged);
_writableRp.ref(p);
writableRp = _writableRp;
}
varWritable.set(_writableRp._getUndependend());
currentTarget.onChanged(onChanged);
currentTarget.onUpdated(onUpdated);
currentTarget.onAdded(onItemAdded);
currentTarget.onRemoved(onItemRemoved);
currentTarget.onNested(onItemNested);
currentTarget.ref(p);
} else {
varWritable.set(false);
}
}
function onDelegateUpdated(newTarget) {
if(newTarget === currentTarget) return;
var old = p._getUndependend();
var oldTarget = currentTarget;
var oldWritableRp = writableRp;
var oldCurrentTargetElementListeners = currentTargetElementListeners;
currentTarget = newTarget;
writableRp = null;
connect();
if(oldTarget) disconnect(oldTarget, oldWritableRp, oldCurrentTargetElementListeners);
if(Array.isArray(currentTarget)) {
theArray = currentTarget.map(function(item) {
return item._getUndependend();
});
}
var _value = p._getUndependend();
if(_value !== old) {
p._updated(_value, old);
}
}
function onDelegateAdded(idx, item) {
var l = {
target: item,
updated: onElementUpdated.bind(null, item),
changed: onElementChanged.bind(null, item),
added: onElementAdded.bind(null, item),
removed: onElementRemoved.bind(null, item),
nested: onElementNested.bind(null, item)
};
currentTargetElementListeners.splice(idx, 0, l);
item.onUpdated(l.updated);
item.onChanged(l.changed);
item.onAdded(l.added);
item.onRemoved(l.removed);
item.onNested(l.nested);
item.ref(p);
var value = item._getUndependend();
theArray.splice(idx, 0, value);
p._added(idx, value);
}
function onDelegateRemoved(idx, item) {
var target = currentTargetElementListeners[idx].target;
target.removeUpdatedListener(currentTargetElementListeners[idx].updated);
target.removeChangedListener(currentTargetElementListeners[idx].changed);
target.removeAddedListener(currentTargetElementListeners[idx].added);
target.removeRemovedListener(currentTargetElementListeners[idx].removed);
target.removeNestedListener(currentTargetElementListeners[idx].nested);
currentTargetElementListeners.splice(idx, 1);
var value = theArray.splice(idx, 1)[0];
p._removed(idx, value);
target.unref(p);
}
function onDelegateChanged() {
p._changed();
}
function onWritableChanged() {
if(!writableRp) return;
varWritable.set(writableRp._getUndependend());
}
function onElementUpdated(item, newValue, oldValue) {
currentTarget.forEach(function(_item, idx) {
if(_item !== item) return;
theArray[idx] = newValue;
p._nested("updated", [idx], newValue, oldValue);
});
}
function onElementChanged(item) {
currentTarget.forEach(function(_item, idx) {
if(_item !== item) return;
p._nested("changed", [idx]);
});
p._changedAtAtomicEnd();
}
function onElementAdded(item, idx2, element) {
currentTarget.forEach(function(_item, idx) {
if(_item !== item) return;
p._nested("added", [idx], idx2, element);
});
}
function onElementRemoved(item, idx2, element) {
currentTarget.forEach(function(_item, idx) {
if(_item !== item) return;
p._nested("removed", [idx], idx2, element);
});
}
function onElementNested(item, event, path, arg1, arg2) {
currentTarget.forEach(function(_item, idx) {
if(_item !== item) return;
p._nested(event, [idx].concat(path), arg1, arg2);
});
}
function onChanged() {
p._changedAtAtomicEnd();
}
function onUpdated(n, o) {
p._updated(n, o);
}
function onItemAdded(idx, item) {
p._added(idx, item);
}
function onItemRemoved(idx, item) {
p._removed(idx, item);
}
function onItemNested(event, path, arg1, arg2) {
p._nested(event, path, arg1, arg2);
}
return p;
};