Hi,
Just tracked down something that's been driving me batty for quite a while. The onUnload event fires quite often on a dijit.layout.ContentPane, but there's no onDestroy or equivalent... onUnload does not fire when a parent container of ContentPane is destroyed without DestroyRecursive or DestroyDescendants. This currently happens when the parent container is closed, as in a tab container.
Meta-code to reproduce the problem:
1. Load a dijit.layout.TabContainer.
2. Create a dijit.layout.ContentPane with property closable:true, and add as a child to the TabContainer. Call it c1.
3. Create another dijit.layout.ContentPane (or any other related dijit), and add as child to the first ContentPane. Let's call this one c2.
4. Set any of the following: c2.onUnload, dojo.connect(c2,'onUnload', func), dojo.connect(c2,'destroy', func).
5. c2.setContent() or c2.setHref() to get new content.
Result: onUnload events fired, as expected.
6. c1.close().
Result: c2.onUnload events don't fire. c2.destroy() doesn't happen. Memory leaks?
Expected behavior: I would think these events/methods should all get called on c2, when its parent container is closed.
I've patched my build, in dijit.layout.StackContainer.closeChild(), line 224 of trunk, changing page.destroy() to page.destroyRecursive(), and this seems to resolve the issue in my test case. Not sure if this would break anything else.
Is there a better place for this fix?
I was going to suggest an onDestroy event to fire when a ContentPane is destroyed, rather than just unloaded... but dojo.connect(c2,'destroy',func) does exactly that, just fine, if the widget is properly destroyed!

ContentPane's dont have
ContentPane's dont have children... so they don't pass along destroy() and such AFAIK... ContentPane is for content, not containing children...
-Karl
Not quite the issue
Hi,
Thanks for your response, but I think you're missing the issue. It's actually probably an issue with StackContainer.
The issue is this: the onUnload event never fires, and the destroy method is never called, on widgets that are descendants of a content pane used in a tabcontainer when they're in a container that is closed. This probably affects any closable container.
While a ContentPane doesn't have methods like addChild or getChildren, it does have getAllDescendents, and destroyDescendants. These are not getting called when a container is closed, and it seems to me that they should--the destroy methods appear to do a fine job of freeing up objects, but they're not getting called in a pretty crucial event.
So far I haven't seen any adverse effects from the StackContainer fix I listed above, but then again I'm only using a TabContainer here and don't know what else uses this...
Cheers,
--
John Locke
http://www.freelock.com
Makes more sense
Thanks for clarifying that John, that post makes more sense, can you file a bug on trac with this info? l/p: guest/guest
-Karl
Bug #4381 created. P.S. I
Bug #4381 created.
P.S. I filed two other bugs in the past couple weeks (since the 0.9 release) and they've both been resolved already. Keep up the good work!
--
John Locke
http://www.freelock.com
The issue still appears in
The issue still appears in contentpane for dojox. I have to use this code to fix it:
var fisheye = dijit.byId('fisheye1');
if (fisheye){
fisheye.destroyRecursive();
}
content.destroyDescendants();
fixed
The destroy/destroyRecursive thing for StackContainer was fixed 2 months ago in [12317] and is in the 1.1 release. Not sure about dojox.ContentPane; I don't see any destroy() or destroyRecursive calls in that file.
=========
Bill Keese
Project Lead (aka BDFL) of Dijit
I'm calling
I'm calling destroyDescendants() which is inherited from dijit._Widget, if I've understood everything right. My ContentPane has a FisheyeList widget in it that is created through setContent(response.data) (an ajax call).
For some reason the FisheyeList is not considered a descendant of my ContentPane and is therefor not destroyed in the destroyDescendants(). I don't know if this has to do with dojox.layout.ContentPane not defining the FisheyeList as a descendant and _Widget therefore not catching it or if it's some other problem.
containerNode?
I'm not sure what your issue is but maybe the FishEyeList isn't inside the containerNode of your ContentPane based widget? Or maybe more likely, your widget doesn't define containerNode at all? Try defining that (to the node that contains all your descendants.
=========
Bill Keese
Project Lead (aka BDFL) of Dijit
containerNode!?
The FishEyeList is loaded through a setContent() call containing an ajax response data with all the html. I've looked at the firebug HTML tab and the FishEye-div is indeed a child node of the dojox.layout.contentPane:
adjustPaths="true"
renderStyles="false"
executeScripts="true">
The contentPane is set through this animated function (I love eyecandy... I guess the child in me is still alive):
dojo.require('dojo.fx');
var changeElement = dojo.byId(changeElementId);
dojo.style(changeElementId, 'overflow', 'hidden');
dojo.style(changeElement, 'overflow', 'hidden');
var flashAnim = this.flashAnim('customer_data_div', "#FFFF00", 1000);
if (newContent != null) {
dojo.connect(flashAnim, 'beforeBegin', function(){
dijit.byId(changeElementId).setContent(newContent);
});
}
return flashAnim;
},
It must be something with FishEye not defining containerNode.... The html with the ajax response is pretty basic though:
<div dojoType="dojox.widget.FisheyeList" itemWidth="64" itemHeight="64"
itemMaxWidth="128" itemMaxHeight="128" orientation="horizontal"
effectUnits="2" itemPadding="25" attachEdge="top" labelEdge="bottom"
id="fisheye1">
<div dojoType="dojox.widget.FisheyeListItem"
onclick="document.location = 'my_loc_1'"
label="coool"
iconSrc="/pics/icons/cool.png">
</div>
<div dojoType="dojox.widget.FisheyeListItem"
onclick="document.location = 'my_loc_2'"
label="coool 2"
iconSrc="/pics/icons/cool_2.png">
</div>
</div>
All my cool stuff goes here
</div>
How do I define the containerNode?
containerNode on ContentPane
Sorry, I meant containerNode on the ContentPane. Maybe the problem is that you are using dojox.layout.ContentPane rather than dijit.layout.ContentPane although I just checked the code and it seems like it should work.
If you have firebug you can try dijit.byId("customer_data_div").containerNode (from the console tab) and see if it's set to something
=========
Bill Keese
Project Lead (aka BDFL) of Dijit
It finds the right div, I
It finds the right div, I can't see any problem with the location of the FishEyeList. It is not straight under the contentpane but that shouldn't matter...
<div other>
<div fisheye>
</div>
</div>
</div>
This is not a big issue but I was annoyed at first when I kept getting the firebug error that I got by not destroying it properly. I wan't to use dojox since I sometimes have js code to be evaluated.