多级联动下拉框控件实现

现在实现控件联动的有纯脚本实现和AJAX,当数据量大时,AJAX的确不错,当数据不是很多时,用AJAX就有点浪费了。
这里我们介绍如何用纯脚本实现多级联动下拉框控件的生成。
希望大家给与建议。

脚本 LinkageControl.js
负责生成多个下拉框,并实现父级控件改变时刷新子列表。
  1. /*********************************
  2. 描述:多级级联控件基础脚本
  3. 作者:叶浩恩
  4. 日期:2008-8-2
  5. 版本:0.1
  6. 使用说明:
  7. 需要在页面进行以下初始化工作
  8. 1。在脚本定义前,建立脚本输出的容器
  9. <div id="LinkageContor"></div>
  10. 2。定义级联控件列表
  11. 3。如果需要处理最后一层节点改变,定义函数  LastLinkageControlChange()
  12. 4。调用初始化函数 InitControl("LinkageContor");
  13. 5. 支持页面回调保持原来选择
  14. 服务器端根据页面提交的信息,生成脚本
  15.     var LinkageContorBindValues = new Array();
  16.     LinkageContorBindValues[0] = "key1";
  17.     LinkageContorBindValues[1] = "key8";
  18.     ...
  19.     生成的脚本需要在调用InitControl前
  20. **********************************/
  21. // 多级级联控件树结点定义类
  22. function LinkageControlNode(p_name, p_value, p_level, p_chiltNodes)
  23. {
  24.     // 定义 tagName 值
  25.     this.tagName = "LinkageControlNode";
  26.     
  27.     // 节点ID
  28.     this.KeyId = "";
  29.     
  30.     // 节点名称
  31.     this.Name=p_name;
  32.     // 节点值
  33.     this.Value = p_value;
  34.     // 节点值2,保存额外的数据
  35.     this.Value2 = p_value;
  36.     // 节点深度值
  37.     this.Level = p_level;
  38.     // 子节点列表
  39.     if (p_chiltNodes!=null)
  40.         this.ClientNodes = p_chiltNodes;
  41.     else
  42.         this.ClientNodes = new Array();
  43. }
  44. // 根据节点定义创建一个列表的 OPTION 项,并进行必要的付值。
  45. LinkageControlNode.prototype.CreateOptionElement= function()
  46. {
  47.     // 创建列表项
  48.     var oOption = document.createElement("OPTION");
  49.     oOption.text = this.Name;
  50.     oOption.value= this.Value;
  51.     
  52.     // 列表项可以通过 Node 属性访问对应的节点信息
  53.     oOption.Node = this;
  54.     return oOption;
  55. }
  56.     
  57. // 实现多级级联控件列表数据绑定
  58. // ctrl: 绑定的下拉框控件
  59. // source:数据源 LinkageControlNode 数组,
  60. function BindLinkageControl(ctrl, source)
  61. {
  62.     if (ctrl == null)
  63.         alert("BindLinkageControl:: ctrl 参数为空!");
  64.     if (ctrl.tagName != "SELECT")
  65.         alert("BindLinkageControl:: ctrl 参数不是下拉框控件类型!");
  66.     if (source == null)
  67.         alert("BindLinkageControl:: source 参数为空!");
  68.         
  69.     // 清空原列表
  70.     var i = 0;
  71.     ctrl.options.length = 0;
  72.     for (i = 0; i < source.length; i++)
  73.     {
  74.         ctrl.options[i] = source[i].CreateOptionElement();
  75.     }
  76.     
  77.     // 如果列表只有一项,不会触发onchange事件,
  78.     // 我们需要选择他,让它可以自动绑定到下一层空间
  79.     if (ctrl.options.length > 0 && ctrl.options[0].Node != null && ctrl.LinkageLevel < linkageControlLevel - 1)
  80.     {
  81.         BindLinkageControl(ctrl.NextLevelControl, ctrl.options[0].Node.ClientNodes);
  82.     }
  83.     
  84. }
  85. // 级联控件选择变化事件处理函数
  86. function LinkageControlChange(e)
  87. {
  88.     var oSource;
  89.     if(e!=null)
  90.         oSource = e.target;
  91.     else
  92.         oSource = window.event.srcElement;
  93.     if (oSource == null)
  94.     {
  95.         alert("LinkageControlChange 无法获得当前事件源控件!");
  96.         return;
  97.     }
  98.         
  99.     // 取当前值
  100.     var currentControlLevel = oSource.LinkageLevel;
  101.     var selectOption = oSource.options[oSource.selectedIndex];
  102.     if (selectOption == null)
  103.     {
  104.         alert("无法获得当前选择项数据!");
  105.         return;
  106.     }
  107.     //alert("selectOption="+selectOption);
  108.     //alert("selectOption.Node="+selectOption.Node);
  109.     //alert("selectOption.Node.ClientNodes="+selectOption.Node.ClientNodes);
  110.     var selectName  = selectOption.text;
  111.     var selectValue = selectOption.value;
  112.     //alert("selectName="+selectName);
  113.     //alert("selectValue="+selectValue);
  114.     oSource.TextField.value = selectName;
  115.     // 取下一个控件
  116.     var nextControl = oSource.NextLevelControl;
  117.     //alert(nextControl);
  118.     if (nextControl == null)
  119.     {
  120.         alert("无法获得下一个级联控件!");
  121.         return;
  122.     }
  123.     if (selectOption.Node == null)
  124.     {
  125.         alert("当前选择项未设置 Node 数据!");
  126.         return;
  127.     }
  128.     // 重新绑定内容
  129.     BindLinkageControl(nextControl, selectOption.Node.ClientNodes);
  130. }
  131. // 创建级联控件
  132. function CreateLinkageControl(obj, level, linkageContorName, linkageContorTitle)
  133. {
  134.     if (obj == null)
  135.     {
  136.         alert("CreateLinkageControl obj 参数为空!");
  137.         return ;
  138.     }
  139.     if (typeof(level) != "number")
  140.     {
  141.         alert("CreateLinkageControl level 参数为空或不是整数!");
  142.         return;
  143.     }
  144.     if (level < 2)
  145.     {
  146.         alert("CreateLinkageControl level 参数值小于2,无法创建级联控件!");
  147.         return;
  148.     }
  149.     // 存放控件的数组
  150.     var listControls = new Array();
  151.     var i = 0;
  152.     // 检查是否需要显示标题
  153.     var bCreateLabel = (typeof(linkageContorTitle)!="undefined");
  154.     
  155.     for (i = 0; i < level; i++)
  156.     {
  157.         // 控件名称和ID
  158.         var ctrlName = linkageContorName + "_" + i;
  159.         
  160.         // 建立一个隐藏域,存放选择项的文本值。
  161.         var textFieldName = ctrlName + "_text";
  162.         var textField = document.createElement("input");
  163.         textField.type = "hidden";
  164.         textField.id = textFieldName;
  165.         textField.name = textFieldName;
  166.         // 加入列表
  167.         obj.appendChild(textField);
  168.         if(bCreateLabel && linkageContorTitle[i] != null)
  169.         {
  170.             // 创建标题字符
  171.             var label = document.createElement("LABEL");
  172.             label.FOR = ctrlName;
  173.             label.innerHTML = linkageContorTitle[i];
  174.             obj.appendChild(label);
  175.         }
  176.         
  177.         // 创建下拉框
  178.         listControls[i] = document.createElement("select");
  179.         listControls[i].id = ctrlName;
  180.         listControls[i].name = ctrlName;
  181.         listControls[i].LinkageLevel = i;
  182.         listControls[i].TextField = textField;
  183.         if (i > 0){
  184.             listControls[i - 1].NextLevelControl = listControls[i];
  185.         }
  186.         
  187.         // 加入列表
  188.         obj.appendChild(listControls[i]);
  189.         
  190.         // 绑定改变选择事件
  191.         // 如果不是最后一层空间,绑定 LinkageControlChange 函数
  192.         if (i < linkageControlLevel - 1){
  193.             listControls[i].onchange = LinkageControlChange;
  194.         }
  195.         else
  196.         {   // 最后一层时,如果用户定义了 LastLinkageControlChange 函数,则绑定该函数
  197.             if (typeof(LastLinkageControlChange) == "function")
  198.             {
  199.                 listControls[i].onchange = LastLinkageControlChange;
  200.             }
  201.         }
  202.     }
  203.     //alert("创建级联控件"+listControls.length);
  204.     
  205.     return listControls;
  206. }
  207. // 处理页面回传后的控件绑定
  208. function RebindControl(listControls, linkageControlLevel)
  209. {
  210.     // 检查由服务器端输出的原控件值。
  211.     // 当页面PostBack后,需要将原控件的值,填写道教本数组 LinkageContorBindValues 中。
  212.     if (typeof(LinkageContorBindValues) == "undefined")
  213.     {
  214.         return;
  215.     }
  216.     var i = 0, j = 0;
  217.     // 检查每个下拉框控件
  218.     for (i = 0; i < linkageControlLevel && i < listControls.length; i++)
  219.     {
  220.         // 将下拉框每个选择项值与服务器绑定值比较
  221.         for (j = 0 ; j < listControls[i].options.length; j++)
  222.         {
  223.             if (listControls[i].options[j].value == LinkageContorBindValues[i])
  224.             {
  225.                 // 找到后,让该项选中,刷新下一个联动控件的值,并退出循环
  226.                 listControls[i].selectedIndex = j;
  227.                 
  228.                 if (i < linkageControlLevel -1)
  229.                 {
  230.                     BindLinkageControl(listControls[i+1], listControls[i].options[j].Node.ClientNodes);
  231.                 }
  232.                 break;
  233.             }
  234.         }
  235.     }
  236. }
  237. // 初始化并创建多级绑定控件
  238. function InitControl(divName, linkageControlLevel, linkageContorName, linkageContorTitle, rootNodes)
  239. {
  240.     var obj = document.getElementById(divName);
  241.     if (obj == null)
  242.     {
  243.         alert("找不到用于填充级联控件的指定元素!");
  244.         return;
  245.     }
  246.     if (rootNodes == nullreturn;
  247.     
  248.     // 创建级联控件
  249.     var listControls = CreateLinkageControl(obj, linkageControlLevel, linkageContorName, linkageContorTitle);
  250.     // 绑定第一层空间
  251.     if (listControls != null && listControls.length > 0)
  252.     {
  253.         BindLinkageControl( listControls[0], rootNodes);
  254.         RebindControl(listControls, linkageControlLevel);
  255.     }
  256. }

以下是页面文件内容:
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml" >
  3. <head>
  4.     <title>级联控件测试</title>
  5.     <script src="LinkageControl.js" type="text/javascript" language="javascript"></script>
  6. </head>
  7. <body>
  8. <form action="LinkageControl.htm" >
  9.     <div id="LinkageContor"></div>
  10.     <script type="text/javascript" language="javascript">
  11.     <!--
  12.     // 定义级联控件数量
  13.     var linkageControlLevel = 3;
  14.     // 级联控件的名称
  15.     var linkageContorName = "AreaZoneSelect";
  16.     // 控件前面显示的标题
  17.     var linkageContorTitle = new Array();
  18.     i = 0;
  19.     linkageContorTitle[i++] = "省";
  20.     linkageContorTitle[i++] = "市";
  21.     linkageContorTitle[i++] = "地区";
  22. // <%= GetRebindData() %> 调用服务器端代码。。。输出一下格式数据
  23. //  var LinkageContorBindValues = new Array();
  24. //  LinkageContorBindValues[0] = "key1";
  25. //  LinkageContorBindValues[1] = "key8";
  26.     
  27.     function CreateData()
  28.     {
  29.         i = 0j = 0;
  30.         rootNodes = new Array();
  31. // <%= GetCreateDataScript() %> 调用服务器端代码。。。填充节点内容。。。输出一下格式数据
  32.         rootNodes[i] = new LinkageControlNode("--请选择--", null, 0, null);
  33.         i++;
  34.         
  35.         j = 0;
  36.         rootNodes[i] = new LinkageControlNode("广东省", "T_guangdong", 0, null);
  37.         rootNodes[i].ClientNodes[j] = new LinkageControlNode("深圳市", "S_shenzhen", 1, null);
  38.         rootNodes[i].ClientNodes[j].ClientNodes[0] = new LinkageControlNode("罗湖区", "S_shenzhen_luohu", 1, null);
  39.         rootNodes[i].ClientNodes[j].ClientNodes[1] = new LinkageControlNode("福田区", "S_shenzhen_futian", 1, null);
  40.         j++;
  41.         rootNodes[i].ClientNodes[j] = new LinkageControlNode("广州市", "S_guangzhou", 1, null);
  42.         rootNodes[i].ClientNodes[j].ClientNodes[0] = new LinkageControlNode("越秀区", "S_guangzhou", 1, null);
  43.         rootNodes[i].ClientNodes[j].ClientNodes[1] = new LinkageControlNode("荔湾区", "S_guangzhou", 1, null);
  44.         i++;
  45.         
  46.         j = 0;
  47.         rootNodes[i] = new LinkageControlNode("湖南省", "T_hunan", 0, null);
  48.         rootNodes[i].ClientNodes[j] = new LinkageControlNode("长沙市", "S_changsha", 1);
  49.         rootNodes[i].ClientNodes[j].ClientNodes[0] = new LinkageControlNode("芙蓉区", "S_changsha1", 1, null);
  50.         rootNodes[i].ClientNodes[j].ClientNodes[1] = new LinkageControlNode("雨花区", "S_changsha2", 1, null);
  51.         j++;
  52.         rootNodes[i].ClientNodes[j] = new LinkageControlNode("株洲市", "S_zhuzhou", 1);
  53.         rootNodes[i].ClientNodes[j].ClientNodes[0] = new LinkageControlNode("动物园", "S_zhuzhou1", 1, null);
  54.         rootNodes[i].ClientNodes[j].ClientNodes[1] = new LinkageControlNode("火车站", "S_zhuzhou2", 1, null);
  55.         return rootNodes;
  56.     }
  57.     InitControl("LinkageContor", linkageControlLevel, linkageContorName, linkageContorTitle, CreateData());
  58.     --></script>
  59.     
  60.     <input type="button" value="view" onclick="alert(document.getElementById('AreaZoneSelect_2').value);" />
  61. </form>
  62.     </body>
  63. </html>


  • 0
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值