PDA

View Full Version : remove panel getBoundingClientRect error IE



young_matthewd
23 Jul 2007, 4:48 AM
using Ext 1.1 rc1 with IE 6 and FireFox 2.0.5

must disposing of panels in the wrong way because anytime the layout is recalled in IE (6) an error associated with getBoundingClientRect() is called. have seen other posts that say the error arises because of duplicate elements or that there is an element missing.

when i create panels and add them into the center region I make a new object which extends observable:


MATRIX.widget.baseElement.Edit = function(config) {
Ext.apply(this, config);

// add some events (destroy/beforedestroy/render/etc...)

MATRIX.widget.baseElement.Edit.superclass.constructor.call(this);
};

Ext.extend(MATRIX.widget.baseElement.Edit, Ext.util.Observable, {
// properties ....

// renders the Edit panel
render : function(){
if(!this.rendered && this.fireEvent("beforerender", this) !== false) {
// create Panel
this.panel = new Ext.ContentPanel(this.id , {
autoCreate: true,
title: this.title,
closable: true,
autoScroll: true
});

/**
* add to application layout (layout part of singelton class
* called on startup)
*/
var layout = MATRIX.layout.ApplicationController.getLayout();
layout.add('center', this.panel);

/**
* listen for remove of panel via the region
*/
layout.getRegion(this.region).on('panelremoved', this.destroy, this);

/**
* display panel in region
*/
layout.getRegion(this.region).showPanel(this.panel.getId());

/**
* objects inheriting this get their onRender called
*/
this.onRender();

/**
* earmark rendered so the next render call
* simply returns the element
*/
this.rendered = true;

/**
* singal that element is rendered
*/
this.fireEvent("render", this);
}
return this;
},

// other funcitons

destroy : function() {
if(this.fireEvent("beforedestroy", this) !== false) {
this.purgeListeners();

/**
* inherited destory
*/
this.beforeDestroy();
this.onDestroy();

/**
* signal destroy / notify Mgr
*/
this.fireEvent("destroy", this);
MATRIX.widget.elementMgr.unregister(this);

}
}
});


inside the onDestroy from inherited classes to baseElement.Edit I remove items/buttons associated with forms and in the destroy i take away listeners.

even if I remove (by issuing a delete) the passed "this" (housing the reference to the panel, form, etc) in the elementMgr when the unregister is called the error still pops up in IE.

kind of a show stopper for me since we use IE.

young_matthewd
23 Jul 2007, 5:50 AM
debugged some more...

turned out my removal of form items/buttons was working right. problem still exists but that is likely due to a custom field not being destroyed properly.

inside this custom field is a container houses a toolbar and tree. having problems destroying the toolbar on the subsequent instances of the panel.

creating inside the custom field the contain as follows:


/**
* compose a widget container inside the field element
*/
var container = Ext.DomHelper.append(
this.el ,
{
tag: 'div',
cls: 'widget-ct',
cn:[
{tag: 'div', cls: 'widget-tb'}
]
},
true
);

/**
* add a toolbar to the tree component
* (houses the menus)
*/
var tbdiv = container.child('div.widget-tb');
this.toolbar = new Ext.Toolbar(tbdiv);

// add buttons (items) to the toolbar/etc.

/**
* construct the tree (view of relationships)
*/
this.tree = new Ext.tree.TreePanel(container, {
animate: true,
enableDD: true,
containerScroll: true,
lines: false,
rootVisible: false,
loader: new Ext.tree.TreeLoader()
});

.... //render tree


when the onDestroy (for this field) is called upon removing my form i just called this.toolbar.destroy (which should blow away all of it's items). on the second instance of panel (thus the form containing a new instance of the custom field) i get an error:

"this.td.parentNode.removeChild(this.td);"

there is no parentNode to the this.td. any ideas?

young_matthewd
24 Jul 2007, 2:24 AM
reworked my custom Field like the HTMLEditor....

build the tree around the defaultAutoCreate element (a div in my case) then created a wrap and appended the toolbar so that on destroying the field (onDestroy) i could remove all HTML inside the wrap (including the element) plus remove the wrap element.

but the toolbar on all subsequent instances (of a new form in a new panel) looses it's parentNode (this.td.parentNode.removeChild(this.td);).

thought maybe i was removing elements inside the custom field oddly. so i tried creating a new HTMLEditor in place of my custom field. exact same problem when the onDestroy method is called inside the HTMLEditor.

must be something related to how fields within the form are removed (below):


onDestroy : function() {
/**
* remove fields/buttons
*/
if (this.form) {
for(var itemIndex = 0, itemsLength = this.form.items.length; itemIndex < itemsLength; itemIndex++){
this.form.items.itemAt(itemIndex).destroy();
}

for(var buttonIndex = 0, buttonsLength = this.form.buttons.length; buttonIndex < buttonsLength; buttonIndex++){
this.form.buttons[buttonIndex].destroy();
}
}
}


tried adding a this.form = null at the end. then the td parentNode error disappeared with HTMLEditor (at least in FireFox but in IE i pops up).

ideas?

young_matthewd
24 Jul 2007, 6:33 AM
if i override (ie. "Ext.form.HtmlEditor.prototype.destroy = Ext.emptyFn;") the destroy method to an empty function with the HtmlEditor the panel can be removed in IE/Firefox without a problem.

still having an issue with my custom field. can remove everything associated with the toolbar but the tree i am having trouble getting rid of.

using destroy logic borrowed from this post (http://extjs.com/forum/showthread.php?t=8616&highlight=destroy+tree+node). however, can to modify the code a bit. and it still doesn't work.

anybody got code for destroying trees? from the panel down through the root node to asyn onto leafs?


/ matthew

young_matthewd
25 Jul 2007, 12:26 AM
after chilling out from yesterday i found the root cause of my problems in this post. writing here in hopes that somebody else has a similar issue.

my error was how i was handling the 'panelremoved' event (see code in the 3rd post inside MATRIX.widget.baseElement.Edit where the this.destroy gets called). the listener registered gets fired for every created panel. not just that particular instance. unsure how i was thinking but for some bone-head reason i thought 'added listener is one-to-one with the function called'.

that is why the parent containers for the toolbar kept getting blown away. i was calling all listeners: old panels which had already been removed but the hook (panel variable) in the array of listeners with the region was still around.

my quick fix is to still kick off the this.destroy when a panel is removed but now i check to see if the passed panel (in the arguements) is equal to the this.panel (see below):


destroy : function(region, panel, event) {
if (this.panel == panel) {
// do destroy stuff

/**
* unregister the listener 'beforedestroy'
* from the region
*/
region.removeListener('beforeremove', this.beforePanelDestroy, this);
MATRIX.layout.ApplicationController.setMessage('Closed panel ' + panel.getTitle());
}
}


plus i take awy the listener at the end.

still don't like how i am an removing the tree in my custom field but until total tree removal is supported i use (from a previous post):


this.tree.el.removeAllListeners();

var treeDom = this.tree.el.dom;
while(treeDom.firstChild){
treeDom.removeChild(treeDom.firstChild);
}


this obviously doesn't remove the Ext elements but at least the DOM is updated and won't irritate IE.