use onScreenEvent to prevent memory leaks.

This commit is contained in:
Christopher Jeffrey 2015-05-01 21:58:26 -07:00
parent de4aa27d70
commit c435b03bdc
2 changed files with 64 additions and 28 deletions

View File

@ -501,8 +501,19 @@ The base element.
- __onceKey(name, listener)__ - bind a keypress listener for a specific key - __onceKey(name, listener)__ - bind a keypress listener for a specific key
once. once.
- __unkey(name, listener)__ - remove a keypress listener for a specific key. - __unkey(name, listener)__ - remove a keypress listener for a specific key.
- __onScreenEvent(type, listener)__ - same as`el.on('screen', ...)` except this - __onScreenEvent(type, handler)__ - same as`el.on('screen', ...)` except this
will automatically cleanup listeners after the element is detached. will automatically keep track of which listeners are bound to the screen
object. for use with `removeScreenEvent()`, `free()`, and `destroy()`.
- __removeScreenEvent(type, handler)__ - same as`el.removeListener('screen',
...)` except this will automatically keep track of which listeners are bound
to the screen object. for use with `onScreenEvent()`, `free()`, and
`destroy()`.
- __free()__ - free up the element. automatically unbind all events that may
have been bound to the screen object. this prevents memory leaks. for use
with `onScreenEvent()`, `removeScreenEvent()`, and `destroy()`.
- __destroy()__ - same as the `detach()` method, except this will automatically
call `free()` and unbind any screen events to prevent memory leaks. for use
with `onScreenEvent()`, `removeScreenEvent()`, and `free()`.
- __setIndex(z)__ - set the z-index of the element (changes rendering order). - __setIndex(z)__ - set the z-index of the element (changes rendering order).
- __setFront()__ - put the element in front of its siblings. - __setFront()__ - put the element in front of its siblings.
- __setBack()__ - put the element in back of its siblings. - __setBack()__ - put the element in back of its siblings.

View File

@ -2395,7 +2395,7 @@ function Element(options) {
this.setHover(options.hoverText); this.setHover(options.hoverText);
} }
// TODO: Possibly move this to Node for screen.on('mouse', ...). // TODO: Possibly move this to Node for onScreenEvent('mouse', ...).
this.on('newListener', function fn(type) { this.on('newListener', function fn(type) {
// type = type.split(' ').slice(1).join(' '); // type = type.split(' ').slice(1).join(' ');
if (type === 'mouse' if (type === 'mouse'
@ -2502,17 +2502,42 @@ Element.prototype.sattr = function(style, fg, bg) {
| colors.convert(bg); | colors.convert(bg);
}; };
Element.prototype.onScreenEvent = function(type, listener) { Element.prototype.onScreenEvent = function(type, handler) {
var self = this; this.screen.on(type, handler);
if (this.parent) { this._elisteners = this._elisteners || {};
this.screen.on(type, listener); this._elisteners[this.uid] = this._elisteners[this.uid] || [];
this._elisteners[this.uid].push({ type: type, handler: handler });
};
Element.prototype.removeScreenEvent = function(type, handler) {
this.screen.removeListener(type, handler);
this._elisteners = this._elisteners || {};
var listeners = this.screen._elisteners[this.uid] || [];
for (var i = 0; i < listeners.length; i++) {
var listener = listeners[i];
if (listener.type === type && listener.handler === handler) {
listeners.splice(i, 1);
if (this.screen._elisteners[this.uid].length === 0) {
delete this.screen._elisteners[this.uid];
} }
this.on('attach', function() { return;
self.screen.on(type, listener); }
}); }
this.on('detach', function() { };
self.screen.removeListener(type, listener);
}); Element.prototype.free = function() {
this._elisteners = this._elisteners || {};
var listeners = this.screen._elisteners[this.uid] || [];
for (var i = 0; i < listeners.length; i++) {
var listener = listeners[i];
this.screen.removeListener(listener.type, listener.handler);
}
};
Element.prototype.destroy = function() {
this.detach();
this.free();
this.screen.render();
}; };
Element.prototype.hide = function() { Element.prototype.hide = function() {
@ -3006,7 +3031,7 @@ Element.prototype.enableDrag = function() {
self.setFront(); self.setFront();
}); });
this.screen.on('mouse', this._dragM = function(data) { this.onScreenEvent('mouse', this._dragM = function(data) {
if (self.screen._dragging !== self) return; if (self.screen._dragging !== self) return;
if (data.action !== 'mousedown') { if (data.action !== 'mousedown') {
@ -3050,7 +3075,7 @@ Element.prototype.disableDrag = function() {
delete this.screen._dragging; delete this.screen._dragging;
delete this._drag; delete this._drag;
this.removeListener('mousedown', this._dragMD); this.removeListener('mousedown', this._dragMD);
this.screen.removeListener('mouse', this._dragM); this.removeScreenEvent('mouse', this._dragM);
return this._draggable = false; return this._draggable = false;
}; };
@ -4981,7 +5006,7 @@ function ScrollableBox(options) {
self.screen.render(); self.screen.render();
var smd, smu; var smd, smu;
self._scrollingBar = true; self._scrollingBar = true;
self.screen.on('mousedown', smd = function(data) { self.onScreenEvent('mousedown', smd = function(data) {
var y = data.y - self.atop; var y = data.y - self.atop;
var perc = y / self.height; var perc = y / self.height;
self.setScrollPerc(perc * 100 | 0); self.setScrollPerc(perc * 100 | 0);
@ -4990,10 +5015,10 @@ function ScrollableBox(options) {
// If mouseup occurs out of the window, no mouseup event fires, and // If mouseup occurs out of the window, no mouseup event fires, and
// scrollbar will drag again on mousedown until another mouseup // scrollbar will drag again on mousedown until another mouseup
// occurs. // occurs.
self.screen.on('mouseup', smu = function(data) { self.onScreenEvent('mouseup', smu = function(data) {
self._scrollingBar = false; self._scrollingBar = false;
self.screen.removeListener('mousedown', smd); self.removeScreenEvent('mousedown', smd);
self.screen.removeListener('mouseup', smu); self.removeScreenEvent('mouseup', smu);
}); });
} }
}); });
@ -7111,7 +7136,7 @@ Question.prototype.ask = function(text, callback) {
this.show(); this.show();
this.setContent(' ' + text); this.setContent(' ' + text);
this.screen.on('keypress', press = function(ch, key) { this.onScreenEvent('keypress', press = function(ch, key) {
if (key.name === 'mouse') return; if (key.name === 'mouse') return;
if (key.name !== 'enter' if (key.name !== 'enter'
&& key.name !== 'escape' && key.name !== 'escape'
@ -7137,7 +7162,7 @@ Question.prototype.ask = function(text, callback) {
function done(err, data) { function done(err, data) {
self.hide(); self.hide();
self.screen.restoreFocus(); self.screen.restoreFocus();
self.screen.removeListener('keypress', press); self.removeScreenEvent('keypress', press);
self._.okay.removeListener('press', okay); self._.okay.removeListener('press', okay);
self._.cancel.removeListener('press', cancel); self._.cancel.removeListener('press', cancel);
return callback(err, data); return callback(err, data);
@ -7210,7 +7235,7 @@ Message.prototype.display = function(text, time, callback) {
}; };
setTimeout(function() { setTimeout(function() {
self.screen.on('keypress', function fn(ch, key) { self.onScreenEvent('keypress', function fn(ch, key) {
if (key.name === 'mouse') return; if (key.name === 'mouse') return;
if (self.scrollable) { if (self.scrollable) {
if ((key.name === 'up' || (self.options.vi && key.name === 'k')) if ((key.name === 'up' || (self.options.vi && key.name === 'k'))
@ -7227,13 +7252,13 @@ Message.prototype.display = function(text, time, callback) {
if (self.options.ignoreKeys && ~self.options.ignoreKeys.indexOf(key.name)) { if (self.options.ignoreKeys && ~self.options.ignoreKeys.indexOf(key.name)) {
return; return;
} }
self.screen.removeListener('keypress', fn); self.removeScreenEvent('keypress', fn);
end(); end();
}); });
if (!self.options.mouse) return; if (!self.options.mouse) return;
self.screen.on('mouse', function fn(data) { self.onScreenEvent('mouse', function fn(data) {
if (data.action === 'mousemove') return; if (data.action === 'mousemove') return;
self.screen.removeListener('mouse', fn); self.removeScreenEvent('mouse', fn);
end(); end();
}); });
}, 10); }, 10);
@ -7399,7 +7424,7 @@ function Listbar(options) {
} }
if (options.autoCommandKeys) { if (options.autoCommandKeys) {
this.screen.on('keypress', function(ch, key) { this.onScreenEvent('keypress', function(ch, key) {
if (/^[0-9]$/.test(ch)) { if (/^[0-9]$/.test(ch)) {
var i = +ch - 1; var i = +ch - 1;
if (!~i) i = 9; if (!~i) i = 9;
@ -8406,7 +8431,7 @@ Terminal.prototype.bootstrap = function() {
} }
}); });
this.screen.on('mouse', function(data) { this.onScreenEvent('mouse', function(data) {
if (self.screen.focused !== self) return; if (self.screen.focused !== self) return;
if (data.x < self.aleft + self.ileft) return; if (data.x < self.aleft + self.ileft) return;
@ -8510,7 +8535,7 @@ Terminal.prototype.bootstrap = function() {
self.emit('exit', code || null); self.emit('exit', code || null);
}); });
this.screen.on('keypress', function() { this.onScreenEvent('keypress', function() {
self.screen.render(); self.screen.render();
}); });