ajax+asp无限级分类树型结构的代码

复制代码 代码如下:

  <%

  '数据库字段为类属性,添加、删除、修改、操作检查等函数为类的方法

  Class Cls_Leibie

  Private nClassID,sClassName,nParentID,sParentPath,nDepth,nRootID,nChild,nOrderID,sFilePath '定义私有变量(类的属性,即数据库字段对应的变量)

  Private rs,sql,ErrorStr

  Private Sub Class_Initialize()

  ErrorStr=""                    '初始化错误信息为空

  End Sub

  Private Sub Class_Terminate()    '销毁类时关闭数据库连接

  If IsObject(Conn) Then

  Conn.Close

  Set Conn = Nothing

  End If

  End Sub

  '*******************设置各个属性******************************************************

  Public Property Let ClassID(str)    '获取类别ID(主键)

  nClassID=str

  call ClassProperty()            '获取类别ID时调用此函数读出类的所有属性

  End Property

  Public Property Let ClassName(str)    '获取类别名称

  sClassName=str

  End Property

  Public Property Get ClassName

  ClassName=sClassName

  End Property

  Public Property Let ParentID(str)    '获取类别父ID

  nParentID=str

  End Property

  Public Property Get ParentID

  ParentID=nParentID

  End Property

  Public Property Let ParentPath(str)    '获取父路径ID

  sParentPath=str

  End Property

  Public Property Get ParentPath

  ParentPath=sParentPath

  End Property

  Public Property Let Depth(str)        '获取类别深度

  nDepth=str

  End Property

  Public Property Get Depth

  Depth=nDepth

  End Property

  Public Property Let RootID(str)        '获取类别根ID

  nRootID=str

  End Property

  Public Property Get RootID

  RootID=nRootID

  End Property

  Public Property Let Child(str)        '子类别个数

  nChild=str

  End Property

  Public Property Get Child

  Child=nChild

  End Property

  Public Property Let OrderID(str)    '排序ID

  nOrderID=str

  End Property

  Public Property Get OrderID

  OrderID=nOrderID

  End Property

  Public Property Let FilePath(str)    '类别文件根目录(生成静态文件路径,小站奇人异事网([url]www.guaishi.org[/url])用的是生成静态,故设置此字段)

  sFilePath=str

  End Property

  Public Property Get FilePath

  FilePath=sFilePath

  End Property

  '******************************************************************************

  Private Sub ClassProperty()            '读取类的所有属性

  sql="select * from ArticleClass where ClassID="& nClassID

  set rs=conn.execute(sql)

  if not rs.eof then

  sClassName=trim(rs("ClassName"))

  nParentID=trim(rs("ParentID"))

  sParentPath=trim(rs("ParentPath"))

  nDepth=trim(rs("Depth"))

  nRootID=trim(rs("RootID"))

  nChild=trim(rs("Child"))

  nOrderID=trim(rs("OrderID"))

  sFilePath=trim(rs("FilePath"))

  end if

  set rs=nothing

  End Sub

  Public Function FAddCheck()        '类别添加检查函数,结果为0表示通过检查,为1表示有错误发生,有错误发生时退出函数,将错误信息写入错误变量ErrorStr

  dim temprs

  FAddCheck=0

  if sClassName="" then        '类名为空

  FAddCheck=1

  ErrorStr="类名不能为空!"

  exit Function

  else

  if nParentID="" then        '父id为空

  FAddCheck=1

  ErrorStr="父id不能为空!"

  exit Function

  else

  if nParentID<>0 then

  set temprs=conn.execute("select ClassID From ArticleClass where ClassID=" & nParentID)        '父类别不存在

  if temprs.eof then

  FAddCheck=1

  ErrorStr="所属类别不存在或已经被删除!"

  exit Function

  else

  sql="select ClassID from ArticleClass where ClassName='"& sClassName &"' and ParentID="& nParentID        '类名重复

  set rs=conn.execute(sql)

  if not rs.eof then

  FAddCheck=1

  ErrorStr="类名重复!"

  exit Function

  end if

  set rs=nothing

  end if

  set temprs=nothing

  else

  sql="select ClassID from ArticleClass where ClassName='"& sClassName &"' and ParentID="& nParentID        '类名重复

  set rs=conn.execute(sql)

  if not rs.eof then

  FAddCheck=1

  ErrorStr="类名重复!"

  exit Function

  end if

  set rs=nothing

  end if

  end if

  end if

  End Function

  Public Sub SAdd()

  dim maxClassID,maxRootID

  set rs = conn.execute("select Max(ClassID) from ArticleClass")        '查找当前数据库中最大的类别id,如果没有数据则设置为0,要插入的类别id为当前最大id加1

  maxClassID=rs(0)

  if isnull(maxClassID) then

  maxClassID=0

  end if

  set rs=nothing

  nClassID=maxClassID+1

  set rs=conn.execute("select max(rootid) From ArticleClass")        '查找当前数据库中最大的根id,如果没有数据则设置为0,要插入的根id为当前最大根id加1

  maxRootID=rs(0)

  if isnull(maxRootID) then

  maxRootID=0

  end if

  nRootID=maxRootID+1

  set rs=conn.execute("select RootID,Depth,ParentPath,Child,OrderID From ArticleClass where ClassID=" & nParentID)    '查找父类别相应信息

  if not rs.eof then

  nRootID=trim(rs("Rootid"))        '根id与父类别根id相同

  sParentPath=trim(rs("ParentPath"))& "," &nParentID

  if cint(trim(nParentID))>0 then            '父id大于0则有父类别,故要插入的类别的深度父类别的深度加1,父id不大于0则当前要插入的类别为根类别,则深度为0

  nDepth=cint(trim(rs("Depth")))+1

  else

  nDepth=0

  end if

  if cint(trim(rs("Child")))>0 then

  dim rsPrevOrderID

  '得到与本栏目同级的最后一个栏目的OrderID

  set rsPrevOrderID=conn.execute("select Max(OrderID) From ArticleClass where ParentID=" & ParentID)

  prevOrderID=rsPrevOrderID(0)

  '得到同一父栏目但比本栏目级数大的子栏目的最大OrderID,如果比前一个值大,则改用这个值。

  set rsPrevOrderID=conn.execute("select Max(OrderID) From ArticleClass where ParentPath like '" & ParentPath & ",%'")

  if (not(rsPrevOrderID.bof and rsPrevOrderID.eof)) then

  if not IsNull(rsPrevOrderID(0))  then

  if rsPrevOrderID(0)>prevOrderID then

  prevOrderID=rsPrevOrderID(0)

  end if

  end if

  end if

  set rsPrevOrderID=nothing

  end if

  nOrderID=prevOrderID+1

  else

  nOrderID=0

  sParentPath="0"

  nDepth=0

  end if

  set rs=nothing

  nChild=0

  sql="insert into ArticleClass (ClassID,ClassName,ParentID,ParentPath,Depth,RootID,Child,OrderID,FilePath) values ("& nClassID &",'"& sClassName &"',"& nParentID &",'"& sParentPath &"',"& nDepth &","& nRootID &","& nChild &","& nOrderID &",'"& sFilePath &"')"

  conn.execute(sql)

  if ParentID>0 then

  '更新其父类的子栏目数

  conn.execute("update ArticleClass set child=child+1 where ClassID="& nParentID)

  '更新该栏目排序以及大于本需要和同在本分类下的栏目排序序号

  if prevOrderID<>"" then

  conn.execute("update ArticleClass set OrderID=OrderID+1 where rootid=" & nRootid & " and OrderID>"& prevOrderID &" and ClassID<>"& nClassID)

  end if

  end if

  End Sub

  Public Function FEditCheck()    '类别修改检查函数,结果为0表示通过检查,为1表示有错误发生,有错误发生时退出函数,将错误信息写入错误变量ErrorStr

  dim temprs

  FEditCheck=0

  if nClassID="" then                    '类别id为空

  FEditCheck=1

  ErrorStr="类别id不能为空!"

  exit Function

  else

  if sClassName="" then            '类名为空

  FEditCheck=1

  ErrorStr="类名不能为空!"

  exit Function

  else

  if nParentID<>0 then

  set temprs=conn.execute("select ClassID From ArticleClass where ClassID=" & nParentID)        '父类别不存在

  if temprs.eof then

  FAddCheck=1

  ErrorStr="所属类别不存在或已经被删除!"

  exit Function

  else

  set rs=conn.execute("select ClassID from ArticleClass where ClassName='"& sClassName &"' and ClassID<>"& nClassID &"and ParentID="& nParentID)

  if not rs.eof then                '类名重复

  FEditCheck=1

  ErrorStr="类名重复!"

  exit Function

  end if

  set rs=nothing

  end if

  set temprs=nothing

  end if

  end if

  end if

  End Function

  Public Sub SEdit()        '类别修改

  sql="update ArticleClass set ClassName='"& sClassName &"',FilePath='"& sFilePath &"' where ClassID="& nClassID

  conn.execute(sql)

  End Sub

  Public Function FDeleteCheck()    '类别删除检查函数,结果为0表示通过检查,为1表示有错误发生,有错误发生时退出函数,将错误信息写入错误变量ErrorStr

  FDeleteCheck=0                '这里删除没有写级联删除文章部分的代码,删除时应该级联删除

  if nClassID="" then

  FDeleteCheck=1

  ErrorStr="要删除的类别id不能为空!"

  exit Function

  else

  set rs=conn.execute("select Child from ArticleClass where ClassID="& nClassID)

  if rs.bof and rs.eof then

  FDeleteCheck=1

  ErrorStr="类别不存在或者已经被删除!"

  exit Function

  else

  if trim(rs("Child"))>0 then

  FDeleteCheck=1

  ErrorStr="该类别含有子类别,请删除其子类别后再进行删除本类别的操作!"

  exit Function

  end if

  end if

  end if

  End Function

  Public Sub SDelete()

  if nDepth>0 then            '修改父id孩子数

  conn.execute("update ArticleClass set child=child-1 where child>0 and ClassID=" & nParentID)

  end if

  sql="delete from ArticleClass where ClassID="& nClassID

  conn.execute(sql)

  End Sub

  Public Function FErrStr()

  FErrStr=ErrorStr

  End Function

  End Class

  %>

  核心js代码

  

复制代码 代码如下:

  var xmlHttp; //定义一个全局变量

  var currentID=1;//设置当前选中ID,如果此ID不存在则会发生js错误

  //类别显示主函数

  //cid--子类别所在层id

  //id --类别id

  //pid--[+]和[-]图标id

  //fid--类别图标id

  function DivDisplay(cid,id,pid,fid)

  {

  if (GetId(cid).style.display=='')    //子类别不显示时图标显示控制

  {

  GetId(cid).style.display='none';

  GetId(pid).src = 'images/closed.gif';

  GetId(fid).src = 'images/folder.gif';

  }

  else        //展开子类别时的操作

  {

  GetId(cid).style.display='';

  GetId(pid).src = 'images/opened.gif';

  GetId(fid).src = 'images/folderopen.gif';

  if (GetId(cid).innerHTML==''||GetId(cid).innerHTML=='正在提交数据...')

  {

  GetId(cid).innerHTML='';

  ShowChild(cid,id);        //调用显示子类别函数

  }

  }

  }

  //与上一个函数作用相同,只作用在最后一个类别

  function DivDisplay2(cid,id,pid,fid)

  {

  if (GetId(cid).style.display=='')

  {

  GetId(cid).style.display='none';

  GetId(pid).src = 'images/lastclosed.gif';

  GetId(fid).src = 'images/folder.gif';

  }

  else

  {

  GetId(cid).style.display='';

  GetId(pid).src = 'images/lastopen.gif';

  GetId(fid).src = 'images/folderopen.gif';

  if (GetId(cid).innerHTML==''||GetId(cid).innerHTML=='正在提交数据...')

  {

  GetId(cid).innerHTML='';

  ShowChild(cid,id);

  }

  }

  }

  //类别添加函数

  //id--类别id

  function ClassAdd(id){

  if (GetId("p"+id).src.indexOf("last")>0){    //最后一个类别时的添加操作

  if (!GetId("p"+id).onclick){

  GetId("p"+id).onclick=function (){DivDisplay2("c"+id,id,"p"+id,"f"+id);};    //为[+]和[-]添加单击事件

  GetId("s"+id).ondblclick=function (){DivDisplay2("c"+id,id,"p"+id,"f"+id);};    //为显示类别文字的span添加双击事件

  GetId("p"+id).src = 'images/lastopen.gif';

  }

  }

  else{

  if (!GetId("p"+id).onclick){    //不为最后一个类别的添加操作

  GetId("p"+id).onclick=function (){DivDisplay("c"+id,id,"p"+id,"f"+id);};

  GetId("s"+id).ondblclick=function (){DivDisplay("c"+id,id,"p"+id,"f"+id);};

  GetId("p"+id).src = 'images/opened.gif';

  }

  }

  GetId("c"+id).style.display='';

  ShowChild("c"+id,id);

  }

  //类别修改函数

  function ClassEdit(id,classname){

  GetId("s"+id).innerHTML=classname;

  }

  //有多个子类别的类别的删除函数

  function ClassDel(id){

  ShowChild("c"+id,id);

  CurrentSelect(currentID,id)

  BrowseRight(id);

  }

  //只有一个子类别的类别的删除函数

  function ClassDel1(id){

  if (GetId("p"+id).src.indexOf("last")>0){        //当类别是当前类别的最后一个类别时

  GetId("p"+id).style.cursor="cursor";        //设置图标的鼠标经过样式

  GetId("p"+id).onclick=function (){};        //因为只有一个子类别删除后就不再有子类别,故将图标单击事件修改为空函数

  GetId("s"+id).ondblclick=function (){};        //同上

  GetId("p"+id).src = 'images/lastnochild.gif';    //图标设置

  }

  else{

  GetId("p"+id).style.cursor="cursor";        //非最后一个类别的删除操作

  GetId("p"+id).onclick=function (){};

  GetId("s"+id).ondblclick=function (){};

  GetId("p"+id).src = 'images/nofollow2.gif';        //这里的图标设置与前面不一样

  }

  ShowChild("c"+id,id);

  CurrentSelect(currentID,id);

  BrowseRight(id);

  }

  //向右边框架传递参数

  function BrowseRight(id){

  CurrentSelect(currentID,id);

  top.ContentFrame.location="../ArticleMain.asp?ClassID="+ id;

  }

  //设置类别选中状态的函数

  function CurrentSelect(oldid,newid){

  currentID=newid;

  document.getElementById("s"+oldid).style.backgroundColor="white";

  document.getElementById("s"+currentID).style.backgroundColor="#C0C0E9";

  }

  //创建XMLHttpRequest对象

  function CreateXMLHttpRequest()

  {

  if (window.ActiveXObject)

  {

  xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");

  }

  else

  {

  xmlHttp = new XMLHttpRequest();

  }

  }

  //Ajax处理函数

  //id,层id

  //rid,数据在表中的id

  function ShowChild(cid,id)

  {

  CreateXMLHttpRequest();

  if(xmlHttp)

  {

  xmlHttp.open('POST','child.asp',true);

  xmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

  var SendData = 'id='+id;

  xmlHttp.send(SendData);

  xmlHttp.onreadystatechange=function()

  {

  if(xmlHttp.readyState==4)

  {

  if(xmlHttp.status==200)

  {

  GetId(cid).innerHTML = xmlHttp.responseText;

  }

  else

  {

  GetId(cid).innerHTML='出错:'+xmlHttp.statusText;

  }

  }

  else

  {

  GetId(cid).innerHTML="正在提交数据...";

  }

  }

  }

  else

  {

  GetId(cid).innerHTML='抱歉,您的浏览器不支持XMLHttpRequest,请使用IE6以上版本!';

  }

  }

  //取得页面对象

  //id,层id

  function GetId(id)

  {

  return document.getElementById(id);

  }