Click to See Complete Forum and Search --> : Recursive Function Error - 800a01a8 (Object Required)


vouzamo
04-02-2009, 05:55 AM
Hi,

I have made a recursive ASP function to write a nested collapsable list in tabular form from a database of categories (parents and children).

The function encounters a problem when it has completed and the outer function should resume... the Object Required error is thrown so rather than the outer function continue, the process stops. I have included my code below (with the connection string masked) and the output can be viewed at http://www.vouzamo.co.uk/category/category.asp


<html>
<head>
<script type="text/javascript">
var selectedCategories = '';
var flag = false;
<%
table = "var categories=["
set db = server.createobject("adodb.connection")
connection = "driver={MySql ODBC 3.51 Driver};server=mysql11.streamline.net;uid=*********;pwd=*******;database=vouzamoco"
db.open (connection)
set rs = server.createobject("adodb.recordset")
sql = "SELECT * FROM categories"
set rs = db.execute(sql)
if not rs.EOF then
while not rs.EOF
id = rs("id")
parent = rs("parent")
table = table & "['" & id & "'],['" & parent & "'],"
rs.movenext()
wend
end if
table = left(table,(len(table) - 1))
table = table & "];"
%>
<%= table %>
function category(id)
{
var e = document.getElementById(id);
if(e.src.match(/^(.*)on\.png$/) === null)
{
document.getElementById(id).setAttribute('src','on.png');
selectedCategories = selectedCategories + ',' + id;
selectChild(id);
selectParent(id);
}
else
{
document.getElementById(id).setAttribute('src','off.png');
selectedCategories = selectedCategories.replace(',' + id,'');
unselectChild(id);
unselectParent(id);
}
}

function getChild(id)
{
var children = '';
for(var x = 0; x < categories.length; x++)
{
if(categories[x][1] == id)
{
if(children == '')
{
children = children + categories[x][0];
}
else
{
children = children + ',' + categories[x][0];
}
}
}
return children;
}

function getParent(id)
{
var parent = '';
for(var x = 0; x < categories.length; x++)
{
if(categories[x][0] == id)
{
parent = categories[x][1];
}
}
return parent;
}

function selectChild(id)
{
if(getChild(id) != '')
{
var children = getChild(id).split(',');
for(var x = 0; x < children.length; x++)
{
document.getElementById(children[x]).setAttribute('src','on.png');
selectedCategories = selectedCategories + ',' + children[x];
selectChild(children[x]);
}
}
}

function selectParent(id)
{
if(getParent(id) != '')
{
var parent = getParent(id);
var children = getChild(parent).split(',');
var flag = true;
for(var x = 0; x < children.length; x++)
{
var e = document.getElementById(children[x]);
if(e.src.match(/^(.*)on\.png$/) === null)
{
flag = false;
}
}
if(flag)
{
document.getElementById(parent).setAttribute('src','on.png');
}
else
{
document.getElementById(parent).setAttribute('src','part.png');
}
selectedCategories = selectedCategories + ',' + parent;
selectParent(parent);
}
}

function unselectChild(id)
{
if(getChild(id) != '')
{
var children = getChild(id).split(',');
for(var x = 0; x < children.length; x++)
{
document.getElementById(children[x]).setAttribute('src','off.png');
selectedCategories = selectedCategories.replace(',' + children[x],'');
unselectChild(children[x]);
}
}
}

function unselectParent(id)
{
if(getParent(id) != '')
{
var parent = getParent(id);
var children = getChild(parent).split(',');
var flag = false;
for(var x = 0; x < children.length; x++)
{
var e = document.getElementById(children[x]);
if(e.src.match(/^(.*)off\.png$/) === null)
{
flag = true;
}
}
if(!flag)
{
document.getElementById(parent).setAttribute('src','off.png');
}
else
{
document.getElementById(parent).setAttribute('src','part.png');
}
selectedCategories = selectedCategories.replace(',' + parent,'');
unselectParent(parent);
}
}
</script>
</head>
<body>
<table width="500">
<%
indent = 0
function categories(parent)
set db = server.createobject("adodb.connection")
connection = "driver={MySql ODBC 3.51 Driver};server=mysql11.streamline.net;uid=*********;pwd=*******;database=vouzamoco"
db.open (connection)
set rs = server.createobject("adodb.recordset")
sql = "SELECT * FROM categories WHERE parent = '" & parent & "' ORDER BY name"
set rs = db.execute(sql)
if not rs.EOF then
while not rs.EOF
id = rs("id")
name = rs("name")
width = 460 - (indent * 20)
hasChild = false
set db2 = server.createobject("adodb.connection")
connection2 = "driver={MySql ODBC 3.51 Driver};server=mysql11.streamline.net;uid=*********;pwd=*******;database=vouzamoco"
db2.open (connection2)
set rs2 = server.createobject("adodb.recordset")
sql2 = "SELECT * FROM categories WHERE parent = '" & id & "' LIMIT 1"
set rs2 = db2.execute(sql2)
if not rs2.EOF then
while not rs2.EOF
hasChild = true
rs2.movenext()
wend
end if
rs2.close
set rs2 = nothing
db2.close
set db2 = nothing
%>
<tr>
<%
x = 1
if(indent > 0) then
for x = 1 to indent step 1
%>
<td width="20"></td>
<%
next
end if
if(hasChild) then
if(parent = "") then
%>
<td width="20"><img id="<%= id %>_toggle" src="minus.gif" onClick="toggle('<%= id %>');"></td>
<%
else
%>
<td width="20"><img id="<%= id %>_toggle" src="plus.gif" onClick="toggle('<%= id %>');"></td>
<%
end if
else
%>
<td width="20"><img src="bullet.gif"></td>
<%
end if
%>
<td width="<%= width %>"><%= name %></td>
<td width="20"><img id="<%= id %>" src="off.png" onClick="category('<%= id %>');"></td>
</tr>
<%
if(hasChild) then
if(parent = "") then
%>
<tr id="<%= id %>_container" class="show">
<%
else
%>
<tr id="<%= id %>_container" class="hide">
<%
end if
%>
<td width="500">
<table width="500" cellpadding="0" cellspacing="0">
<%
indent = indent + 1
categories(id)
indent = indent - 1
%>
</table>
</td>
</tr>
<%
end if
rs.movenext()
wend
end if
rs.close
set rs = nothing
db.close
set db = nothing
end function
categories("")
%>
</table>
</body>
</html>


Note: the javascript is for a secondary function which allows the parents to inherit selection from the children client-side. It does not affect the ASP code.

Images used in this code can be found in the .zip file attached.

vouzamo
04-02-2009, 07:59 AM
I think the problem may be caused by the fact that the recordset is closed in the function so when the outer function resumes and tries rs.movenext the rs object doesn't exist. I am not sure how to resolve this. Can the rs have a dynamic name based on the function parameter so that the rs in each function is unique? can something be done so that the rs is an object within the function instance rather than the page?

Any advise is much appreciated.