hedera-web/js/vn/object.js

260 lines
5.2 KiB
JavaScript
Raw Normal View History

2016-09-26 09:28:47 +00:00
/**
2022-05-30 01:30:33 +00:00
* The main base class. Manages the signal system. Objects based on this class
* can be instantiated declaratively using XML.
2022-05-26 06:08:31 +00:00
*/
2022-06-06 16:02:17 +00:00
module.exports = class VnObject {
2022-05-30 01:30:33 +00:00
/**
* Tag to be used when the class instance is defined via XML. All classes
* must define this attribute, even if it is not used.
*/
2022-06-06 16:02:17 +00:00
static Tag = 'vn-object';
2022-05-30 01:30:33 +00:00
/**
* Class public properties.
*/
2022-06-06 16:02:17 +00:00
static Properties = {};
2022-05-30 01:30:33 +00:00
/*
2022-06-06 16:02:17 +00:00
* Reference count.
*/
_refCount = 1;
2022-05-30 01:30:33 +00:00
/*
2022-06-06 16:02:17 +00:00
* Signal handlers data.
*/
_thisArg = null;
2022-05-30 01:30:33 +00:00
/**
* Initializes the object and sets all properties passed to the class
* constructor.
*
* @param {Object} props The properties passed to the contructor
*/
2022-06-06 16:02:17 +00:00
constructor(props) {
this.setProperties(props);
}
initialize(props) {
2022-05-28 15:49:46 +00:00
this.setProperties(props);
}
2022-05-30 01:30:33 +00:00
/**
* Sets a group of object properties.
*
* @param {Object} props Properties
*/
2022-06-06 16:02:17 +00:00
setProperties(props) {
for (var prop in props)
this[prop] = props[prop];
}
2022-05-30 01:30:33 +00:00
/**
* Increases the object reference count.
*/
2022-06-06 16:02:17 +00:00
ref() {
2015-11-09 08:14:33 +00:00
this._refCount++;
return this;
}
2022-05-30 01:30:33 +00:00
/**
* Decreases the object reference count.
*/
2022-06-06 16:02:17 +00:00
unref() {
2015-11-09 08:14:33 +00:00
this._refCount--;
2015-11-09 08:14:33 +00:00
if (this._refCount === 0)
2022-05-28 15:49:46 +00:00
this._destroy();
}
2022-05-30 01:30:33 +00:00
/**
* Called from @Vn.Builder when it finds a custom tag as a child of the
* element.
*
* @param {Vn.Scope} scope The scope instance
* @param {Node} node The custom tag child nodes
*/
2022-06-06 16:02:17 +00:00
loadXml() {}
2022-05-30 01:30:33 +00:00
/**
* Called from @Vn.Builder when it finds a a child tag that isn't
* associated to any property.
*
* @param {Object} child The child object instance
*/
2022-06-06 16:02:17 +00:00
appendChild() {}
/**
* Conects a signal with a function.
*
2022-05-30 01:30:33 +00:00
* @param {string} id The signal identifier
* @param {function} callback The callback
* @param {Object} instance The instance
2022-05-26 06:08:31 +00:00
*/
2022-06-06 16:02:17 +00:00
on(id, callback, instance) {
2022-05-28 15:49:46 +00:00
if (!(callback instanceof Function)) {
console.warn('Vn.Object: Invalid callback for signal \'%s\'', id);
2015-07-17 14:34:42 +00:00
return;
2015-11-09 08:14:33 +00:00
}
2022-05-28 15:49:46 +00:00
this._signalInit();
2022-05-30 01:30:33 +00:00
var callbacks = this._thisArg.signals[id];
2015-11-09 08:14:33 +00:00
if (!callbacks)
2022-05-30 01:30:33 +00:00
callbacks = this._thisArg.signals[id] = [];
2022-05-28 15:49:46 +00:00
callbacks.push({
2022-05-30 01:30:33 +00:00
blocked: false
,callback: callback
,instance: instance
});
}
/**
* Locks/Unlocks a signal emission to the specified object.
*
2022-05-30 01:30:33 +00:00
* @param {string} id The signal identifier
* @param {function} callback The callback
* @param {boolean} block %true for lock the signal, %false for unlock
2022-05-26 06:08:31 +00:00
*/
2022-06-06 16:02:17 +00:00
blockSignal(id, callback, block, instance) {
2022-05-30 01:30:33 +00:00
if (!this._thisArg)
2015-11-09 08:14:33 +00:00
return;
2022-05-30 01:30:33 +00:00
var callbacks = this._thisArg.signals[id];
if (!callbacks)
return;
for (var i = 0; i < callbacks.length; i++)
if (callbacks[i].callback == callback
&& callbacks[i].instance == instance)
callbacks[i].blocked = block;
}
/**
2022-05-30 01:30:33 +00:00
* Emits a signal in the object.
*
2022-05-30 01:30:33 +00:00
* @param {string} id The signal identifier
2022-05-26 06:08:31 +00:00
*/
2022-06-06 16:02:17 +00:00
emit(id) {
2022-05-30 01:30:33 +00:00
if (!this._thisArg)
2015-11-09 08:14:33 +00:00
return;
2022-05-30 01:30:33 +00:00
var callbacks = this._thisArg.signals[id];
if (!callbacks)
return;
var callbackArgs = [];
2022-05-28 15:49:46 +00:00
callbackArgs.push(this);
for (var i = 1; i < arguments.length; i++)
2022-05-28 15:49:46 +00:00
callbackArgs.push(arguments[i]);
for (var i = 0; i < callbacks.length; i++)
if (!callbacks[i].blocked)
2022-05-28 15:49:46 +00:00
callbacks[i].callback.apply(callbacks[i].instance, callbackArgs);
}
/**
* Disconnects a signal from current object.
*
2022-05-30 01:30:33 +00:00
* @param {string} id The signal identifier
* @param {function} callback The connected callback
* @param {Object} instance The instance
2022-05-26 06:08:31 +00:00
*/
2022-06-06 16:02:17 +00:00
disconnect(id, callback, instance) {
2022-05-30 01:30:33 +00:00
if (!this._thisArg)
2015-11-09 08:14:33 +00:00
return;
2022-05-30 01:30:33 +00:00
var callbacks = this._thisArg.signals[id];
2022-05-30 01:30:33 +00:00
if (callbacks)
for (var i = callbacks.length; i--;)
if (callbacks[i].callback === callback
&& callbacks[i].instance === instance)
callbacks.splice(i, 1);
}
/**
* Disconnects all signals for the given instance.
*
* @param {Object} instance The instance
2022-05-26 06:08:31 +00:00
*/
2022-06-06 16:02:17 +00:00
disconnectByInstance(instance) {
2022-05-30 01:30:33 +00:00
if (!this._thisArg)
2015-11-09 08:14:33 +00:00
return;
2022-05-30 01:30:33 +00:00
var signals = this._thisArg.signals;
2015-11-09 08:14:33 +00:00
2022-05-28 15:49:46 +00:00
for (var signalId in signals) {
2015-11-09 08:14:33 +00:00
var callbacks = signals[signalId];
2022-05-30 01:30:33 +00:00
if (callbacks)
for (var i = callbacks.length; i--;)
if (callbacks[i].instance === instance)
callbacks.splice(i, 1);
}
}
/**
* Destroys the object, this method should only be called before losing
2022-05-30 01:30:33 +00:00
* the last reference to the object. It can be overwritten by child classes
* but should always call the parent method.
2022-05-26 06:08:31 +00:00
*/
2022-06-06 16:02:17 +00:00
_destroy() {
2022-05-30 01:30:33 +00:00
if (!this._thisArg)
2015-11-09 08:14:33 +00:00
return;
2022-05-30 01:30:33 +00:00
var links = this._thisArg.links;
for (var key in links)
2022-05-30 01:30:33 +00:00
this._unlink(links[key]);
2022-05-30 01:30:33 +00:00
this._thisArg = null;
}
2022-05-30 01:30:33 +00:00
/**
* Links the object with another object.
*
* @param {Object} prop The linked property
* @param {Object} handlers The object events to listen with
*/
2022-06-06 16:02:17 +00:00
link(prop, handlers) {
2022-05-28 15:49:46 +00:00
this._signalInit();
2022-05-30 01:30:33 +00:00
var links = this._thisArg.links;
2015-11-09 08:14:33 +00:00
2022-05-28 15:49:46 +00:00
for (var key in prop) {
var newObject = prop[key];
var oldObject = this[key];
2022-05-30 01:30:33 +00:00
if (oldObject)
this._unlink(oldObject);
this[key] = newObject;
2022-05-28 15:49:46 +00:00
if (newObject) {
links[key] = newObject.ref();
for (var signal in handlers)
2022-05-28 15:49:46 +00:00
newObject.on(signal, handlers[signal], this);
} else if (oldObject)
2022-05-30 01:30:33 +00:00
links[key] = undefined;
}
}
2015-10-14 11:51:43 +00:00
2022-06-06 16:02:17 +00:00
_unlink(object) {
2022-05-30 01:30:33 +00:00
object.disconnectByInstance(this);
object.unref();
}
2022-06-06 16:02:17 +00:00
_signalInit() {
2022-05-30 01:30:33 +00:00
if (!this._thisArg)
this._thisArg = {
signals: {},
links: {}
};
}
2022-06-06 16:02:17 +00:00
}