PDA

View Full Version : Memory Management with closeable load-tabs



christocracy
28 Aug 2007, 8:16 PM
wow. keep an eye on the number of component in Ext.ComponentMgr when using destroyable load-tabs in an Ext.BorderLayout. make sure you end up with the same amount of components you started with after you close a tab.

Ext.form.Form requires a destroy method so that it removes all Ext.form.Fields.

today I made base class for myself called RExt.CloseTab. it has a destroy method. it will listen to a supplied Ext.LayoutRegion's 'beforeclose' event

the idea is you create components and this.register(them) or this.register(grid) or this.register(form) or this.register(menu) and the destory() method will iterate through its Ext.MixedCollection and gracefully kill each of them.

usage:


var center = layout.getRegion('center');
var view = new RExt.CloseTab(id, center); // <-- normally extend RExt.CloseTab and provide your own onRender()
var panel = new Ext.NestedLayoutPanel(view.render(el), {
title : view.getTitle(),
closable : true,
loadOnce : true
});
layout.add('center', panel);





/***
* RExt.CloseTab
* A destroyable load-tab
* @author Chris Scott
* @param {Integer} id the primary key this CloseTab is associated with
* @param {Ext.LayoutRegion} the layout region this Tab was added to
*
*/
RExt.CloseTab = function(id, region) {

if (! (region instanceof Ext.LayoutRegion) ) {
alert('ERROR RExt.CloseTab::initialize -- 2nd param to constructor must be an instance of Ext.LayoutRegion');
return false;
}
/*** @private the primary key assocated with this tab ***/
this.id = id;

/*** @private Collection of components ***/
this.components = new Ext.util.MixedCollection();

// listen to beforeremove event on Ext.LayoutRegion. that's the cue to destroy everything.
region.on('beforeremove', this.destroy, this, {});



};
RExt.CloseTab.prototype = {

/***
* getId
* return teh associated primary key of this Tab.
*
* @return {Integer}
*/
getId : function() {
return this.id;
},

/***
* register
* register a component
* @param {String} component name
* @param {Object} component
*
*/
register : function(component) {
this.components.add(component);
},

/***
* get
* get a registered component
* @param {String} component name
* @return {Object} component
*
*/
get : function(key) {
return this.components.get(key);
},

/***
* render
* render the LoadTab
* @param {Object} el
*/
render: function(el) {
this.el = el;
this.layout = this.onRender(el);
return this.layout;
},

/***
* onRender
* override this to provide custom layout.
* @param {Object} el
* @return {Ext.BorderLayout} return only an Ext.BorderLayout for now.
*/
onRender : function(el) {
alert('RExt.LoadTab::onRender() -- NO IMPLEMENTATION -- YOU MUST OVERRIDE THIS METHOD IN YOU EXTENSION!');
},

/***
* destroy
* destroy this LoadTabdelete this.components;
* iterates collection of components and destroys them
* @param {Ext.LayoutRegion} associated region
* @param {Ext.ContentPanel} destroyed panel
*
*/
destroy : function(region, panel) {

// remove beforeremove listener
region.un('beforeremove', this.destroy, this, {});

// must check to see of panel's id matches this.el.id. all LoadTab listen to same region's beforeremove event.
if (panel.getId() == this.el.id) {
console.log('RExt.LoadTab::destroy() ' + this.id);
this.components.each(function(c) { // iterate registered components and destroy them
if (typeof(c.removeAll) == 'function') {
c.removeAll();
}
Ext.destroy(c);
});
this.components.clear(); // <-- clear the MixedCollection

// destroy Layout
Ext.destroy(this.layout);
delete this.layout;

// remove reference to this.el to prevent memory leak.
delete this.el;
}
}
};


[code]

christocracy
28 Aug 2007, 8:39 PM
here's an implementation of destroy for both Ext.form.Form and Ext.grid.EditorGrid that I pulled out of my ass a few days ago.



/***
* Experimental Ext.form.Form::destroy() funciton.
*/
Ext.form.Form.prototype.destroy = function() {
this.items.each(Ext.destroy, Ext);
function destroyRecursive(layout) {
if (typeof(layout.stack) != 'undefined') {
for (var t=0,lent=layout.stack.length;t<lent;t++) {
destroyRecursive(layout.stack[t]);
}
}
Ext.destroy(layout);
}
destroyRecursive(this.root);
};
/***
* Experimental Ext.grid.EditorGrid::destroy() function
*/
Ext.grid.EditorGrid.prototype.destroy = function() {
var cm = this.getColumnModel();
for (var n=0,len=cm.config.length;n<len;n++) {
if (typeof(cm.config[n].editor) == 'object') {
Ext.destroy(cm.config[n].editor.field);
Ext.destroy(cm.config[n].editor);

}
}
Ext.grid.EditorGrid.superclass.destroy.apply(this, arguments);
};

mystix
28 Aug 2007, 8:49 PM
that's one heck of an ass you have there ;)

jon.whitcraft
29 Aug 2007, 11:30 AM
Moved to User Extensions as this is what it is.

:D