Hi,
I managed to find the leaks inthe end. In the latest updates to IE6 MS says that they have fixed the circular reference (from DOM to javascript & vice versa) causing leaks problem, however I then found that that only counts for elements still attached to the document. When an UpdatePanel refreshes, the contents are removed from the DOM and so the leaks persist. I then found this article (NB: I'm new to this JS leak stuff, so the content of this link may be old hat to most) http://javascript.crockford.com/memory/leak.html. I adapted the brute force cleanup code in this article to output a quasi-xpath stringto a textbox containingthe locations of all handlers it finds under the DayPilot markup.
Here's the modified brute force code... supply d = DayPilot DIV, path = "".
function purge(d, path)
{
var a = d.attributes, i, l, n;
var tb = document.getElementById('<% =Console.ClientID %>');
if (a)
{
l = a.length;
for (i = 0; i < l; i += 1)
{
n = a[i].name;
if (typeof d[n] === 'function')
{
if (d[n] != null)
tb.text += path + '.' + n + '()' + '\n';
d[n] = null;
}
}
}
a = d.childNodes;
if (a)
{
l = a.length;
for (i = 0; i < l; i += 1)
purge(d.childNodes[i], ((d.childNodes[i].id != null && d.childNodes[i].id != '') ? d.childNodes[i].tagName + '[@id=\'' + d.childNodes[i].id + '\']' : path + '.' + d.childNodes[i].tagName));
}
}
From the output I then wrote the following cleanupDayPilotHandlers function which should be calledbefore refreshing an update panel containing DayPilot. I guess it would have to be modified if it's to be called before a call back (by the way this leaks too, but only when the number of columns change).
function getFirstChildByTagName(parent, childTagName)
{
var child = parent.firstChild;
while(child!=null)
{
if (child.tagName == childTagName)
return child;
child = child.nextSibling;
}
return null;
}
//dayPilot is the javaScript dayPilot instance eg. dpc1.
function cleanupHandlers(dayPilot)
{
dayPilot.selectedEvents = [];
var dayPilotName = dayPilot.id;
var header = document.getElementById(dayPilotName + '_header');
var scroller = document.getElementById(dayPilotName + '_scroll');
var main = document.getElementById(dayPilotName + '_main');
var events = document.getElementById(dayPilotName + '_events');
var headerTBody = getFirstChildByTagName(header, 'TBODY');
var headerTR = getFirstChildByTagName(headerTBody, 'TR');
headerTD = headerTR.firstChild
while (headerTD != null)
{
if (headerTD.tagName == 'TD')
headerTD.onclick = null;
headerTD = headerTD.nextSibling;
}
scroller.onscroll = null;
main.onmouseup = null;
main.onmousemove = null;
eventsTD = events.firstChild;
while (eventsTD != null)
{
if (eventsTD.tagName == 'TD')
{
var outerDIV = getFirstChildByTagName(eventsTD, 'DIV');
var innerDIV = outerDIV.firstChild;
while (innerDIV != null)
{
if (innerDIV.tagName == 'DIV')
{
innerDIV.data = null;
innerDIV.event = null;
innerDIV.oncontextmenu = null;
innerDIV.onmousemove = null;
innerDIV.onmousedown = null;
}
innerDIV = innerDIV.nextSibling;
}
}
eventsTD = eventsTD.nextSibling;
}
var mainTBody = getFirstChildByTagName(main, 'TBODY');
var mainTR = mainTBody.firstChild;
while (mainTR != null)
{
if (mainTR.tagName == 'TR')
{
var mainTD = mainTR.firstChild;
while(mainTD != null)
{
if (mainTD.tagName == 'TD')
{
mainTD.onmouseup = null;
mainTD.oncontextmenu = null;
mainTD.onmousemove = null;
mainTD.onclick = null;
mainTD.root = null;
}
mainTD = mainTD.nextSibling;
}
}
mainTR = mainTR.nextSibling;
}
}
NB: I'm not sure that this is exhaustive as we're only using a limited set of features (basically displaying a schedule, selecting an event and selecting time ranges), so if you find more memory leaks, use the purge function above to track them down.
Regards,
Phil.