gristlabs_grist-core/app/client/components/Base.js

95 lines
2.6 KiB
JavaScript
Raw Normal View History

/**
* This is the base class for components. The purpose is to abstract away several
* common idioms to make derived components simpler.
*
* Usage:
* function Component(gristDoc) {
* Base.call(this, gristDoc);
* ...
* }
* Base.setBaseFor(Component);
*
* To create an object:
* var obj = Component.create(constructor_args...);
*/
/* global $ */
var dispose = require('../lib/dispose');
/**
* gristDoc may be null when there is no active document.
*/
function Base(gristDoc) {
this.gristDoc = gristDoc;
this._debugName = this.constructor.name + '[' + Base._nextObjectId + ']';
// TODO: devise a logging system that allows turning on/off different debug tags and levels.
//console.log(this._debugName, "Base constructor");
this._eventNamespace = '.Events_' + (Base._nextObjectId++);
this._eventSources = [];
this.autoDisposeCallback(this.clearEvents);
}
Base._nextObjectId = 1;
/**
* Sets ctor to inherit prototype methods from Base.
* @param {function} ctor Constructor function which needs to inherit Base's prototype.
*/
Base.setBaseFor = function(ctor) {
ctor.prototype = Object.create(Base.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
dispose.makeDisposable(ctor);
};
/**
* Subscribe to eventType on source, similarly to $(source).on(eventType, optSelector, method).
* In fact, this uses JQuery internally. The convenience is that it allows unsubscribing in bulk.
* Also, method is called with the context of `this`.
*/
Base.prototype.onEvent = function(source, eventType, optSelector, method) {
if (typeof optSelector != 'string') {
method = optSelector;
optSelector = null;
}
if (this._eventSources.indexOf(source) === -1)
this._eventSources.push(source);
var self = this;
$(source).on(eventType + this._eventNamespace, optSelector, function(event_args) {
Array.prototype.unshift.call(arguments, this); // Unshift is generic enough for 'arguments'.
if (self._eventSources)
return method.apply(self, arguments);
});
};
/**
* Unsubscribes this object from eventType on source, similarly to $(source).off(eventType).
*/
Base.prototype.clearEvent = function(source, eventType) {
$(source).off(eventType + this._eventNamespace);
};
/**
* Unsubscribes this object from all events that it subscribed to via onEvent().
*/
Base.prototype.clearEvents = function() {
var sources = this._eventSources;
for (var i = 0; i < sources.length; i++) {
$(sources[i]).off(this._eventNamespace);
}
this._eventSources.length = 0;
};
module.exports = Base;