simple-bound
Version:
A simple and customizable reactive data-binding library.
89 lines • 3.75 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const binding_1 = require("../binding");
const util_1 = require("../util");
const base_1 = require("./base");
/**
* Allows multiple full-object bindings.
* Stores bindings and binds objects together, providing the highest possible abstraction level for bindings.
*
* @extends {BaseBound<T>}
* @template T captures a type of proto object for later usage in binding type inference
*/
class Bound extends base_1.default {
/**
* Creates an instance of Bound using a proto object.
* @param proto used as an object prototype for the creation of boundObject and storage. Doesn't become bound itself.
* @param [plugins] to plug into the binding events. Do not work yet.
*/ //TODO: Bound plugins!
constructor(proto, plugins) {
super(proto, plugins);
this.storage = {};
const original = JSON.parse(JSON.stringify(proto));
for (const key in original) {
if (typeof original[key] === 'object') { // If the value is object - then treat it like another bound target
const bound = new Bound(original[key], (plugins || {})[key]);
this.boundObject[key] = bound.boundObject;
this.storage[key] = bound.storage;
}
else {
const binding = new binding_1.default(false, original[key], [(plugins || {})[key]]);
binding.addSubscriber(this.boundObject, key);
this.storage[key] = binding;
}
}
}
/**
* Binds an object to all other current subscribers
*
* @template U used to capture the bound object type. Must extends original template type.
* @param obj to bind
* @param [twoWay] whether the binding should be two-way
*/ //TODO: rework this function. It's a mess.
bind(obj, twoWay = true) {
const __bind = (_obj, _twoWay = true, path = '') => {
Object.defineProperty(_obj, '__bound__', {
value: util_1.fromPath(this.boundObject, path).__bound__,
writable: true
});
for (const key in util_1.fromPath(this.storage, path)) {
const nextPath = !path ? key : `${path}.${key}`;
const nextStorage = util_1.fromPath(this.storage, nextPath);
const nextValue = _obj[key];
if (nextStorage instanceof binding_1.default) {
nextStorage.addSubscriber(_obj, key, _twoWay ? 'master' : 'slave');
}
else {
__bind(nextValue, _twoWay, nextPath);
}
}
};
__bind(obj, twoWay);
return this;
}
/**
* Unbinds an object and destroys all of its listeners
*
* @param obj reference of object to be unbound
*/
unbind(obj) {
const __unbind = (_obj, path = '') => {
_obj.__bound__ = undefined;
for (const key in util_1.fromPath(this.storage, path)) {
const nextPath = !path ? key : `${path}.${key}`;
const nextStorage = util_1.fromPath(this.storage, nextPath);
const nextValue = _obj[key];
if (nextStorage instanceof binding_1.default) {
nextStorage.removeSubscriber(_obj, key);
}
else {
_obj[key] = __unbind(nextValue, nextPath);
}
}
return JSON.parse(JSON.stringify(_obj));
};
return __unbind(obj);
}
}
exports.default = Bound;
//# sourceMappingURL=bound.js.map