1. 程式人生 > >html選擇框多級聯動

html選擇框多級聯動

Demo來源:http://www.imuum.com/plugin-jquery-cityselect-js-provinces-linkage-effect.html

我把Demo改寫成最多可以到5級聯動,需要增加修改也很容易

資料來源,Java端通過Spring boot輸出將實體類轉成JSON物件,轉換效率有點低

TreeItem.java

public class TreeItem {
    private String id;
    private String pId;
    private String name;
    private String extra;
    public TreeItem(String id,String pId,String name) {
        this.id = id;
        this.pId = pId;
        this.name = name;

    }
    public TreeItem(String id,String pId, String name, String extra) {
        this.id = id;
        this.pId = pId;
        this.name = name;
        this.extra = extra;
    }
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getpId() {
        return pId;
    }

    public void setpId(String pId) {
        this.pId = pId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
Tree.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Tree {
    private List<TreeItem> nodes;

    public Tree(List<TreeItem> nodes){
        this.nodes = nodes;
    }

    public Map buildTree(){
        List<Map<String,Object>> list=new ArrayList<>();
        for (TreeItem node : nodes) {
            String id = node.getId();
            if (node.getpId() == null) {
               list.add(build(node));
            }
        }
        Map treeMap=new HashMap<>();
        treeMap.put("citylist",list);
       return treeMap;
    }

    private Map build(TreeItem node){
        List<TreeItem> children = getChildren(node);
        List<Map<String,Object>> list=new ArrayList<>();
        Map<String,Object> map=new HashMap<>();
        map.put("node",node);
        if (children.isEmpty()) {
            return map;
        }
        for (TreeItem child : children) {
            list.add(build(child));
        }
        map.put("children",list);
        return map;
    }

    private List<TreeItem> getChildren(TreeItem node){
        List<TreeItem> children = new ArrayList<TreeItem>();
        String id = node.getId();
        for (TreeItem child : nodes) {
            if (id.equals(child.getpId())) {
                children.add(child);
            }
        }
        return children;
    }
}
通過呼叫Tree.buildTree函式就可以生成我們需要的json資料

然後就是前端頁面了,預設值部分還沒有做

index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>基於jQuery+JSON的省市聯動效果</title>
<script type="text/javascript" src="js/jquery.2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery.cityselect2.js"></script>
<script type="text/javascript">
$(function(){
	$("#city").citySelect({
		nodata:null,
		required:false
	}); 
});
</script>
</head>

<body>
<div id="main">  
  <div class="demo">
  	<h3>設定省份、城市、地區(縣)的預設值</h3>
    <p>三級聯動</p>
    <div id="city">
  		<select class="s0"></select> 
    	<select class="s1" disabled="disabled"></select>
      <select class="s2" disabled="disabled"></select>
      <select class="s3" disabled="disabled"></select>
      <select class="s4" disabled="disabled"></select>
    </div>
  </div>
  </div>
  <br />
<br />
</div>
</body>
</html>

cityselect2.js
/*
Ajax 多級聯動
http://code.ciaoca.cn/
日期:2012-7-18

settings 引數說明
-----
url:省市資料josn檔案路徑
prov:預設省份
city:預設城市
dist:預設地區(縣)
nodata:無資料狀態
required:必選項
------------------------------ */
(function($){
	$.fn.citySelect=function(settings){
		if(this.length<1){return;};

		// 預設值
		settings=$.extend({
			url:"js/city.js",
			prov:null,
			city:null,
			dist:null,
			nodata:null,
			required:true
		},settings);

		var box_obj=this;
		var s0_obj=box_obj.find(".s0");
		var s1_obj=box_obj.find(".s1");
		var s2_obj=box_obj.find(".s2");
		var s3_obj=box_obj.find(".s3");
		var s4_obj=box_obj.find(".s4");
	
		var prov_val=settings.prov;
		
		var select_prehtml=(settings.required) ? "" : "<option value=''>請選擇</option>";
		var city_json;

		//獲取當前選擇框前面的選擇框
		var getPreS=function(s){
			if(s==s1_obj) return s0_obj;
			if(s==s2_obj) return s1_obj;
			if(s==s3_obj) return s2_obj;
			if(s==s4_obj) return s3_obj;
			return null;
		}
		//獲取當前選擇框的下一個選擇框
		var getNextS=function(s){
			if(s==s0_obj) return s1_obj;
			if(s==s1_obj) return s2_obj;
			if(s==s2_obj) return s3_obj;
			if(s==s3_obj) return s4_obj;
			return null;
		}
		//獲取當前選擇框的序號
		var getSelectN=function(s){
			if(s==s0_obj) return 0;
			if(s==s1_obj) return 1;
			if(s==s2_obj) return 2;
			if(s==s3_obj) return 3;
			return 4;
		}
		//根據當前選擇框的值獲取json資料的children
		var getCityChildren=function(s){
			var s0_id=s0_obj.get(0).selectedIndex;
			var s1_id=s1_obj.get(0).selectedIndex;
			var s2_id=s2_obj.get(0).selectedIndex;
			var s3_id=s3_obj.get(0).selectedIndex;
			var s4_id=s4_obj.get(0).selectedIndex;
			if(!settings.required){
				s0_id--;
				s1_id--;
				s2_id--;
				s3_id--;
				s4_id--;
			};
			if(s==s0_obj) return city_json.citylist[s0_id].children;
			if(s==s1_obj) return city_json.citylist[s0_id].children[s1_id].children;
			if(s==s2_obj) return city_json.citylist[s0_id].children[s1_id].children[s2_id].children;
			if(s==s3_obj) return city_json.citylist[s0_id].children[s1_id].children[s2_id].children[s3_id].children;
			return null;
		}
		//根據序號隱藏選擇框
		var hidSubSelect=function(n){
			if(n<1){
				s1_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s1_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s1_obj.css("visibility","hidden");
				};
			}
			if(n<2){
				s2_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s2_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s2_obj.css("visibility","hidden");
				};
			}
			if(n<3){
				s3_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s3_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s3_obj.css("visibility","hidden");
				};
			}
			if(n<4){
				s4_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s4_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s4_obj.css("visibility","hidden");
				};
			}
		}

		// 賦值地區(縣)函式
		var distStart=function(s){
			
			var current_id=s.selectedIndex;
			if(!settings.required){
				current_id--;
			};
			hidSubSelect(getSelectN(s));
			if(current_id<0||typeof(getCityChildren(s))=="undefined"||getCityChildren(s)==null){
				if(settings.nodata=="none"){
					getNextS(s).css("display","none");
				}else if(settings.nodata=="hidden"){
					getNextS(s).css("visibility","hidden");
				};
				return;
			};
			
			// 遍歷
			temp_html=select_prehtml;
			$.each(getCityChildren(s),function(i,dist){
				temp_html+="<option value='"+dist.node.id+"'>"+dist.node.name+"</option>";
			});
			getNextS(s).html(temp_html).attr("disabled",false).css({"display":"","visibility":""});
		};

		var init=function(){
			// 遍歷賦值省份下拉列表
			temp_html=select_prehtml;
			$.each(city_json.citylist,function(i,prov){
				temp_html+="<option value='"+prov.node.id+"'>"+prov.node.name+"</option>";
			});
			s0_obj.html(temp_html);

			// 若有傳入省份與市級的值,則選中。(setTimeout為相容IE6而設定)
			setTimeout(function(){
				if(settings.prov!=null){
					prov_obj.val(settings.prov);
					cityStart();
					setTimeout(function(){
						if(settings.city!=null){
							city_obj.val(settings.city);
							distStart();
							setTimeout(function(){
								if(settings.dist!=null){
									dist_obj.val(settings.dist);
								};
							},1);
						};
					},1);
				};
			},1);

			// 選擇省份時發生事件
			s0_obj.bind("change",function(){
				distStart(s0_obj);
			});
			s1_obj.bind("change",function(){
				distStart(s1_obj);
			});
			s2_obj.bind("change",function(){
				distStart(s2_obj);
			});
			s3_obj.bind("change",function(){
				distStart(s3_obj);
			});
			s4_obj.bind("change",function(){
				distStart(s4_obj);
			});
		};

		// 設定省市json資料
		if(typeof(settings.url)=="string"){
			$.getJSON(settings.url,function(json){
				city_json=json;
				init();
			});
		}else{
			city_json=settings.url;
			init();
		};
	};
})(jQuery);

把樹的建立放到了前端js來建立

後端直接輸出List<TreeItem>物件,框架自動輸出JSON陣列,前端js遞迴建樹的程式碼如下

var districts;
        var arrayToTree=function(parentId) {
            var temp = [];
            for (var index in districts) {
                if (districts[index].pId == parentId) {
                    var children=arrayToTree(districts[index].id);
                    temp.push({
                        node: districts[index],
                        children: children
                    });
                }
            }
           return temp;
        };
        var buildTree= function (parentId) {
            var temp = {citylist:[]};
            for (var index in districts) {
                if (districts[index].id == parentId) {
                    temp.citylist.push({
                        node: districts[index],
                        children: arrayToTree(districts[index].id)
                    });
                }
            }
            return temp;
        };

在得到資料的時候修改一下

$.getJSON(settings.url, function (json) {
                    districts=json;
					city_json = buildTree('000');//000是根節點的ID
init();
}

jquery.cityselect.js最後的Javascript程式碼如下

/*
多級聯動 劉放
日期:2016-8-22

settings 引數說明
-----
url:省市資料josn檔案路徑
s0:預設省份
s1:預設市
s2:預設縣
s3:預設鄉鎮
s4:預設村
nodata:無資料狀態  如果需要隱藏則填寫none或者hidden
required:必選項

依賴於web-storage-cache.min.js
------------------------------ */
(function($){
	$.fn.citySelect=function(settings){
		if(this.length<1){return;};
		var wsCache = new WebStorageCache();
		// 預設值
		settings=$.extend({
			url:null,
			s1:null,
			s2:null,
			s3:null,
			s4:null,
			s0:null,
			nodata:null,
			required:true
		},settings);

		var box_obj=this;
		var s0_obj=box_obj.find(".s0");
		var s1_obj=box_obj.find(".s1");
		var s2_obj=box_obj.find(".s2");
		var s3_obj=box_obj.find(".s3");
		var s4_obj=box_obj.find(".s4");
        var text_obj=box_obj.find("input[type=hidden]");

        var setTextObj=function(){
            if(text_obj.length>0) {
                if(s4_obj.val()!=="") {
                    text_obj.val(
                    s0_obj.find("option:selected").text()+
                    s1_obj.find("option:selected").text()+
                    s2_obj.find("option:selected").text()+
                    s3_obj.find("option:selected").text()+
                    s4_obj.find("option:selected").text());
                }else{
                    text_obj.val("");
                }
            }
        };

        var prov_val=settings.prov;
		
		var select_prehtml=(settings.required) ? "" : "<option value=''>請選擇</option>";
		var city_json;

		//獲取當前選擇框前面的選擇框
		var getPreS=function(s){
			if(s==s1_obj) return s0_obj;
			if(s==s2_obj) return s1_obj;
			if(s==s3_obj) return s2_obj;
			if(s==s4_obj) return s3_obj;
			return null;
		}
		//獲取當前選擇框的下一個選擇框
		var getNextS=function(s){
			if(s==s0_obj) return s1_obj;
			if(s==s1_obj) return s2_obj;
			if(s==s2_obj) return s3_obj;
			if(s==s3_obj) return s4_obj;
			return null;
		}
		//獲取當前選擇框的序號
		var getSelectN=function(s){
			if(s==s0_obj) return 0;
			if(s==s1_obj) return 1;
			if(s==s2_obj) return 2;
			if(s==s3_obj) return 3;
			return 4;
		}
		//根據當前選擇框的值獲取json資料的children
		var getCityChildren=function(s){
			var s0_id=s0_obj.get(0).selectedIndex;
			var s1_id=s1_obj.get(0).selectedIndex;
			var s2_id=s2_obj.get(0).selectedIndex;
			var s3_id=s3_obj.get(0).selectedIndex;
			var s4_id=s4_obj.get(0).selectedIndex;
			if(!settings.required){
				s0_id--;
				s1_id--;
				s2_id--;
				s3_id--;
				s4_id--;
			};
			if(s===s0_obj) return city_json.list[s0_id].children;
			if(s===s1_obj) return city_json.list[s0_id].children[s1_id].children;
			if(s===s2_obj) return city_json.list[s0_id].children[s1_id].children[s2_id].children;
			if(s===s3_obj) return city_json.list[s0_id].children[s1_id].children[s2_id].children[s3_id].children;
			return null;
		}
		//根據序號隱藏選擇框
		var hidSubSelect=function(n){
			if(n<1){
				s1_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s1_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s1_obj.css("visibility","hidden");
				};
			}
			if(n<2){
				s2_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s2_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s2_obj.css("visibility","hidden");
				};
			}
			if(n<3){
				s3_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s3_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s3_obj.css("visibility","hidden");
				};
			}
			if(n<4){
				s4_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s4_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s4_obj.css("visibility","hidden");
				};
			}
		}

		// 賦值地區(縣)函式
		var distStart=function(s){
			if($(s).val()==="") return;
			var current_id=s.selectedIndex;
			if(!settings.required){
				current_id--;
			};
			hidSubSelect(getSelectN(s));
			if(current_id<0||typeof(getCityChildren(s))=="undefined"||getCityChildren(s)==null){
				if(settings.nodata=="none"){
					getNextS(s).css("display","none");
				}else if(settings.nodata=="hidden"){
					getNextS(s).css("visibility","hidden");
				};
				return;
			};

            var next_obj=getNextS(s);//獲取到下一個元件
            if(next_obj==null) return;
			// 遍歷
			temp_html=select_prehtml;
			$.each(getCityChildren(s),function(i,dist){
				temp_html+="<option value='"+dist.node.id+"'>"+dist.node.name+"</option>";
			});
            next_obj.html(temp_html).attr("disabled",false).css({"display":"","visibility":""});
            if($(s).val()!==""){
                distStart(next_obj);
            }
		};

		var initCity=function(){
			// 遍歷賦值省份下拉列表
			temp_html=select_prehtml;
			$.each(city_json.list,function(i,prov){
				temp_html+="<option value='"+prov.node.id+"'>"+prov.node.name+"</option>";
			});
			s0_obj.html(temp_html);
			distStart(s0_obj);
			// 若有傳入省份與市級的值,則選中。(setTimeout為相容IE6而設定)
			setTimeout(function(){
				if(settings.s0!==null&&settings.s0!==""){
					s0_obj.val(settings.s0);
					distStart(s0_obj);
					setTimeout(function(){
						if(settings.s1!=null){
							if(s1_obj==null) return;
							s1_obj.val(settings.s1);
							distStart(s1_obj);
							setTimeout(function(){
								if(s2_obj==null) return;
								if(settings.s2!=null){
									s2_obj.val(settings.s2);
									distStart(s2_obj);
									setTimeout(function(){
										if(s3_obj==null) return;
										if(settings.s3!=null){
											s3_obj.val(settings.s3);
											distStart(s3_obj);
											setTimeout(function(){
												if(s4_obj==null) return;
												if(settings.s4!=null){
													s4_obj.val(settings.s4);
												};
											},1);
										};
									},1);
								};
							},1);
						};
					},1);
				};
			},1);
            setTimeout(function(){
                // 選擇省份時發生事件
                s0_obj.bind("change",function(){
                    distStart(s0_obj);
                });
                s1_obj.bind("change",function(){
                    distStart(s1_obj);
                });
                s2_obj.bind("change",function(){
                    distStart(s2_obj);
                });
                s3_obj.bind("change",function(){
                    distStart(s3_obj);
                });
                s4_obj.bind("change",function(){
                    distStart(s4_obj);
                    setTextObj();
                });
            },50);
		};

        var districts;
        var arrayToTree=function(parentId) {
            var temp = [];
            for (var index in districts) {
                if (districts[index].pId == parentId) {
                    var children=arrayToTree(districts[index].id);
                    temp.push({
                        node: districts[index],
                        children: children
                    });
                }
            }
           return temp;
        };
        var buildTree= function (parentId) {
            var temp = {list:[]};
            for (var index in districts) {
                if (districts[index].id == parentId) {
                    temp.list.push({
                        node: districts[index],
                        children: arrayToTree(districts[index].id)
                    });
                }
            }
            return temp;
        };
		// 設定省市json資料
		if(typeof(settings.url)=="string"){
			city_json=wsCache.get("allCity");
			if(city_json!==undefined&&city_json!==null){
				initCity();
			}
			else {
				$.getJSON(settings.url, function (json) {
                    districts=json;
					city_json = buildTree('320000000000');//前端建好樹
					wsCache.set('allCity', city_json, {exp : 60*12});//快取12*60s
					initCity();
				});
			}
		}else{
			city_json=settings.url;
			initCity();
		};
	};
})(jQuery);