1. 论坛系统升级为Xenforo,欢迎大家测试!
    排除公告

无限分类 之 无限级联下拉选择 (ASP + AJAX)

本帖由 不学无术2005-10-18 发布。版面名称:前端开发

  1. 不学无术

    不学无术 Ulysses 的元神

    注册:
    2005-08-31
    帖子:
    16,714
    赞:
    39
    关于如何实现无限分类,请看教程:http://bbs.chinahtml.com/t2991.html

    关于本无限级联下拉选择,演示请看:http://www.purewhite.cn/demo/sorts/select.html

    先给出各部分代码,稍后解释。

    select.html
    功能:显示下拉选择
    代码:
    代码:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>无限分类 之 无限级联下拉选择(ASP版)</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="xmlhttprequest.js"></script>
    <script type="text/javascript">
    <!--
    //    Unlimited sorts
    var objSorts;
    var objValue;
    
    function init() {
        objSorts = document.getElementById("sorts");
    	objValue = document.getElementById("selectedValue");
    }
    
    function getSorts(strURL) {	
        var req = new XMLHttpRequest();	
    	var xml;
    	
    	req.open("GET", strURL, true);
    	if (req) {
    	    req.onreadystatechange = function() {
    		    if (req.readyState == 4 && req.status == 200) {
    			    xml = req.responseXML;
    				var arrIDs = xml.getElementsByTagName("ID");
    				var arrTitles = xml.getElementsByTagName("TITLE");
    				var k = objSorts.childNodes.length;
    				
    				if (arrIDs.length > 0) {
    				    var objSelect = document.createElement("select");
    					objSelect.setAttribute("name", "sel_" + k);
    					objSelect.setAttribute("id", "sel_" + k);
    					objSelect.setAttribute("onchange", "getChildSorts('sel_" + k + "', this);");
    					
    					var objOption = document.createElement("option");
    					objOption.setAttribute("value", "")
    					
    					var objText = document.createTextNode("");
    					objOption.appendChild(objText);
    					
    					objSelect.appendChild(objOption);
    					
    					for (var l = 0; l < arrIDs.length; l++) {
    					    objOption = document.createElement("option");
    						objOption.setAttribute("value", arrIDs[l].childNodes[0].nodeValue);
    						
    						objText = document.createTextNode(arrTitles[l].childNodes[0].nodeValue);
    						
    						objOption.appendChild(objText);
    						
    						objSelect.appendChild(objOption);
    					}
    					
    					objSorts.appendChild(objSelect);
    				}
    			}
    		}
    	}
        req.send(null);
    }
    
    function getChildSorts(so, o) {
        var myValue = o.options[o.selectedIndex].value;
    	var obj = document.getElementById(so);
    	
        if (myValue != "" && myValue > 0) {
    	    doKillSorts(obj);  //remove the old child sorts
    		
    	    objValue.value = myValue;
    	    
    	    var strURL = "getXML.asp?action=list&SortID=" + myValue;
    		
    		getSorts(strURL);
        }
    	else {
    	    doKillSorts(obj);
    		
    		if (obj.previousSibling) {    //abort
    		    objValue.value = obj.previousSibling.options[obj.previousSibling.selectedIndex].value;
    		}
    		else {
    		    objValue.value = 0;
    		}
    		
    	    return false;
    	}
    }
    
    function doKillSorts(obj) {    //remove the old child sorts
        while (obj.nextSibling) {
    	    obj.parentNode.removeChild(obj.nextSibling);
    	}
    }
    //-->
    </script>
    </head>
    
    <body onload="init(); getSorts('getXML.asp?action=list&amp;SortID=0');">
    <div id="sorts"></div>
    <br />
    <p><input name="selectedValue" type="text" id="selectedValue" size="4" value="0" /></p>
    </body>
    </html>
     
    #1 不学无术, 2005-10-18
    最后编辑: 2005-10-18
  2. 不学无术

    不学无术 Ulysses 的元神

    注册:
    2005-08-31
    帖子:
    16,714
    赞:
    39
    getXML.asp
    功能:根据传递过来的 SortID ,列出子类别列表,以 XML 文档的形式返回数据。
    代码:
    代码:
    <%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
    <% Option Explicit %>
    <%
    Dim conn
    Set conn = Server.CreateObject("ADODB.Connection")
    conn.Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & Server.MapPath("sorts.mdb")
    
    
    
    
    Call listData()
    
    
    
    
    Sub listData()
        Dim intSortID : intSortID = CID(Request.QueryString("SortID"))
    	
    	Dim strXML : strXML = "<?xml version=""1.0"" encoding=""utf-8""?><SORTS>"
    	
    	Dim rs, sql
    	Set rs = Server.CreateObject("ADODB.Recordset")
    	sql = "SELECT ID, Title FROM Sorts WHERE ParentID = " & intSortID & ";"
    	rs.Open sql, conn, 1, 1, 1
    	Do While Not rs.EOF
    	    strXML = strXML & "<SORT><ID>" & rs("ID") & "</ID><TITLE>" & rs("Title") & "</TITLE></SORT>"
    		rs.MoveNext
    	Loop
    	rs.Close
    	Set rs = Nothing
    	
    	strXML = strXML & "</SORTS>"
    	
    	Response.ContentType = "text/xml"
    	Response.Write(strXML)
    End Sub
    
    
    
    
    '--------------------------------------------------------------------------------
    Function CID(strS)
    '--------------------------------------------------------------------------------
    '    转换为有效的 ID
    '    返回值类型:Integer (>=0)
    '--------------------------------------------------------------------------------
        Dim intI
    	intI = 0
    	
        If IsNull(strS) Or strS = "" Then
    	    intI = 0
    	Else
    	    If Not IsNumeric(strS) Then
    		    intI = 0
    		Else
    		    Dim intk
    		    On Error Resume Next
    			intk = Abs(Clng(strS))
    			If Err.Number = 6 Then intk = 0  ''数据溢出
    			Err.Clear
    		    intI = intk
    		End If
    	End If
    	
    	CID = intI
    End Function
    %>
    这里依然用到了无限分类中的 CID() 自定义函数。
     
  3. 不学无术

    不学无术 Ulysses 的元神

    注册:
    2005-08-31
    帖子:
    16,714
    赞:
    39
    xmlhttprequest.js
    功能:定义跨平台的 XMLHttpRequest 对象(这个是网上的资源)
    代码:
    代码:
    /*
    
    Cross-Browser XMLHttpRequest v1.1
    =================================
    
    Emulate Gecko 'XMLHttpRequest()' functionality in IE and Opera. Opera requires
    the Sun Java Runtime Environment <http://www.java.com/>.
    
    by Andrew Gregory
    http://www.scss.com.au/family/andrew/webdesign/xmlhttprequest/
    
    This work is licensed under the Creative Commons Attribution License. To view a
    copy of this license, visit http://creativecommons.org/licenses/by/1.0/ or send
    a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305,
    USA.
    
    Not Supported in Opera
    ----------------------
    * user/password authentication
    * responseXML data member
    
    Not Fully Supported in Opera
    ----------------------------
    * async requests
    * abort()
    * getAllResponseHeaders(), getAllResponseHeader(header)
    
    */
    // IE support
    if (window.ActiveXObject && !window.XMLHttpRequest) {
      window.XMLHttpRequest = function() {
        return new ActiveXObject((navigator.userAgent.toLowerCase().indexOf('msie 5') != -1) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP');
      };
    }
    // Gecko support
    /* ;-) */
    // Opera support
    if (window.opera && !window.XMLHttpRequest) {
      window.XMLHttpRequest = function() {
        this.readyState = 0; // 0=uninitialized,1=loading,2=loaded,3=interactive,4=complete
        this.status = 0; // HTTP status codes
        this.statusText = '';
        this._headers = [];
        this._aborted = false;
        this._async = true;
        this.abort = function() {
          this._aborted = true;
        };
        this.getAllResponseHeaders = function() {
          return this.getAllResponseHeader('*');
        };
        this.getAllResponseHeader = function(header) {
          var ret = '';
          for (var i = 0; i < this._headers.length; i++) {
            if (header == '*' || this._headers.h == header) {
              ret += this._headers.h + ': ' + this._headers.v + '\n';
            }
          }
          return ret;
        };
        this.setRequestHeader = function(header, value) {
          this._headers[this._headers.length] = {h:header, v:value};
        };
        this.open = function(method, url, async, user, password) {
          this.method = method;
          this.url = url;
          this._async = true;
          this._aborted = false;
          if (arguments.length >= 3) {
            this._async = async;
          }
          if (arguments.length > 3) {
            // user/password support requires a custom Authenticator class
            opera.postError('XMLHttpRequest.open() - user/password not supported');
          }
          this._headers = [];
          this.readyState = 1;
          if (this.onreadystatechange) {
            this.onreadystatechange();
          }
        };
        this.send = function(data) {
          if (!navigator.javaEnabled()) {
            alert("XMLHttpRequest.send() - Java must be installed and enabled.");
            return;
          }
          if (this._async) {
            setTimeout(this._sendasync, 0, this, data);
            // this is not really asynchronous and won't execute until the current
            // execution context ends
          } else {
            this._sendsync(data);
          }
        }
        this._sendasync = function(req, data) {
          if (!req._aborted) {
            req._sendsync(data);
          }
        };
        this._sendsync = function(data) {
          this.readyState = 2;
          if (this.onreadystatechange) {
            this.onreadystatechange();
          }
          // open connection
          var url = new java.net.URL(new java.net.URL(window.location.href), this.url);
          var conn = url.openConnection();
          for (var i = 0; i < this._headers.length; i++) {
            conn.setRequestProperty(this._headers.h, this._headers.v);
          }
          this._headers = [];
          if (this.method == 'POST') {
            // POST data
            conn.setDoOutput(true);
            var wr = new java.io.OutputStreamWriter(conn.getOutputStream());
            wr.write(data);
            wr.flush();
            wr.close();
          }
          // read response headers
          // NOTE: the getHeaderField() methods always return nulls for me :(
          var gotContentEncoding = false;
          var gotContentLength = false;
          var gotContentType = false;
          var gotDate = false;
          var gotExpiration = false;
          var gotLastModified = false;
          for (var i = 0; ; i++) {
            var hdrName = conn.getHeaderFieldKey(i);
            var hdrValue = conn.getHeaderField(i);
            if (hdrName == null && hdrValue == null) {
              break;
            }
            if (hdrName != null) {
              this._headers[this._headers.length] = {h:hdrName, v:hdrValue};
              switch (hdrName.toLowerCase()) {
                case 'content-encoding': gotContentEncoding = true; break;
                case 'content-length'  : gotContentLength   = true; break;
                case 'content-type'    : gotContentType     = true; break;
                case 'date'            : gotDate            = true; break;
                case 'expires'         : gotExpiration      = true; break;
                case 'last-modified'   : gotLastModified    = true; break;
              }
            }
          }
          // try to fill in any missing header information
          var val;
          val = conn.getContentEncoding();
          if (val != null && !gotContentEncoding) this._headers[this._headers.length] = {h:'Content-encoding', v:val};
          val = conn.getContentLength();
          if (val != -1 && !gotContentLength) this._headers[this._headers.length] = {h:'Content-length', v:val};
          val = conn.getContentType();
          if (val != null && !gotContentType) this._headers[this._headers.length] = {h:'Content-type', v:val};
          val = conn.getDate();
          if (val != 0 && !gotDate) this._headers[this._headers.length] = {h:'Date', v:(new Date(val)).toUTCString()};
          val = conn.getExpiration();
          if (val != 0 && !gotExpiration) this._headers[this._headers.length] = {h:'Expires', v:(new Date(val)).toUTCString()};
          val = conn.getLastModified();
          if (val != 0 && !gotLastModified) this._headers[this._headers.length] = {h:'Last-modified', v:(new Date(val)).toUTCString()};
          // read response data
          var reqdata = '';
          var stream = conn.getInputStream();
          if (stream) {
            var reader = new java.io.BufferedReader(new java.io.InputStreamReader(stream));
            var line;
            while ((line = reader.readLine()) != null) {
              if (this.readyState == 2) {
                this.readyState = 3;
                if (this.onreadystatechange) {
                  this.onreadystatechange();
                }
              }
              reqdata += line + '\n';
            }
            reader.close();
            this.status = 200;
            this.statusText = 'OK';
            this.responseText = reqdata;
            this.readyState = 4;
            if (this.onreadystatechange) {
              this.onreadystatechange();
            }
            if (this.onload) {
              this.onload();
            }
          } else {
            // error
            this.status = 404;
            this.statusText = 'Not Found';
            this.responseText = '';
            this.readyState = 4;
            if (this.onreadystatechange) {
              this.onreadystatechange();
            }
            if (this.onerror) {
              this.onerror();
            }
          }
        };
      };
    }
    // ActiveXObject emulation
    if (!window.ActiveXObject && window.XMLHttpRequest) {
      window.ActiveXObject = function(type) {
        switch (type.toLowerCase()) {
          case 'microsoft.xmlhttp':
          case 'msxml2.xmlhttp':
            return new XMLHttpRequest();
        }
        return null;
      };
    }
     
  4. 不学无术

    不学无术 Ulysses 的元神

    注册:
    2005-08-31
    帖子:
    16,714
    赞:
    39
    啊哦,在 FF 下面一点问题没有,在 IE 下面毫无动静,也没有提示出错。

    检查检查——稍后完成教程。
     
  5. 不学无术

    不学无术 Ulysses 的元神

    注册:
    2005-08-31
    帖子:
    16,714
    赞:
    39
    IE 下的问题已经解决。

    问题就在于通过 setAttribute() 添加的 event 属性,在 IE 下仅作为普通属性,不能被执行。
     
  6. zmjin

    zmjin New Member

    注册:
    2005-12-27
    帖子:
    2
    赞:
    0
    不学无术,很高兴看到你的贴,程序写得太好了.
    我想问一下,目前我使用你的程序完成我的项目时,遇到个问题,你目前只能取最未一级的ID号,我需要取得每一级的ID号,应该如何实现?
    希望能得到你的回答,QQ:371143491,E-MAIL:[email protected]
     
  7. 风

    New Member

    注册:
    2005-09-05
    帖子:
    145
    赞:
    0
    看了一下他的数据库结构,IDPath 字段中已经记录了每一级的编号,只要根据最末一级的 ID 取出对应的 IDPath 内容即可满足你的要求。
     
  8. zmjin

    zmjin New Member

    注册:
    2005-12-27
    帖子:
    2
    赞:
    0
    风,我对他的代码不熟悉,能告诉我一下吗?或者联系我的QQ.谢谢
     
  9. ivvi

    ivvi New Member

    注册:
    2006-05-18
    帖子:
    2
    赞:
    0
    楼主,请问IE下不支持setAttribute,你是怎么解决的?
     
  10. ivvi

    ivvi New Member

    注册:
    2006-05-18
    帖子:
    2
    赞:
    0
    挖哈哈哈,谢谢你在蓝色发的帖子,偶晓得了~
    在 objSelect.setAttribute("onchange", "getChildSorts('sel_" + k + "', this);");下面加上这句

    objSelect.onchange = function() {
    getChildSorts("sel_" + k ,this);
    }