系统开发中,经常遇到级联Select的状况,而级联的Select Option数据一般记录于DB,如果每次都重新写一套级联Select,工作将是繁琐滴。。。
一般来说,写一套级联的Select的几个步骤:
- 从DB读取Select Option的级联数据
- 将数据封装成JSON或xml传到前台
- 在前台由JS动态组装/填充Select元素
- 用JS调整各个级联Select之间的交互,如父Select值发生改变,重新填充子Select的选项,并清空子Select的已选值
而这次,想写一套可重用的代码,便于以后有需要的时候可方便的搬进以后的项目,本代码依赖于
- Gson 2.2.4
- Jquery 1.6.1
Kick-off:
首先,由于是Demo,我们不从DB查询数据,只是用Collection直接模拟数据,为了便于生成JSON,使用Gson转换,为了组装级联数据结构方便,使用Selector.java和SelectorOption.java作为存储的结构:
1 import java.io.IOException; 2 import java.util.ArrayList; 3 import java.util.HashMap; 4 import java.util.List; 5 import java.util.Map; 6 7 import javax.servlet.ServletException; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 12 import com.google.gson.Gson; 13 import com.google.gson.GsonBuilder; 14 15 public class CascapeSelectorServlet extends HttpServlet { 16 private static final long serialVersionUID = 1L; 17 18 public CascapeSelectorServlet() { 19 super(); 20 } 21 22 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 23 this.doPost(request, response); 24 } 25 26 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 27 28 /* country */ 29 Selector countrySelector = new Selector("country", null, getCountry()); 30 31 /* province */ 32 Selector provinceSelector = new Selector("province", null, new HashMap()); 33 List<SelectorOption> provinceList = getProvince(); 34 for (int i = 0; i < provinceList.size(); i++) { 35 provinceSelector.put(provinceList.get(i).getParent(), provinceList.get(i)); 36 } 37 38 /* city */ 39 Selector citySelector = new Selector("city", null, new HashMap()); 40 List<SelectorOption> cityList = getCity(); 41 for (int i = 0; i < cityList.size(); i++) { 42 citySelector.put(cityList.get(i).getParent(), cityList.get(i)); 43 } 44 45 Map dataMap = new HashMap(); 46 dataMap.put("country", countrySelector); 47 dataMap.put("province", provinceSelector); 48 dataMap.put("city", citySelector); 49 50 /* Gson */ 51 GsonBuilder gsonBuilder = new GsonBuilder(); 52 gsonBuilder.setPrettyPrinting(); 53 Gson gson = gsonBuilder.create(); 54 55 /* To json */ 56 String json = gson.toJson(dataMap); 57 58 System.out.println("json -> " + json); 59 response.getWriter().write(json); 60 } 61 62 /** 63 * Analog data 64 * @return 65 */ 66 private List<SelectorOption> getCountry() { 67 List countryList = new ArrayList(); 68 countryList.add(new SelectorOption("cn", "China")); 69 countryList.add(new SelectorOption("uk", "United Kingdom")); 70 countryList.add(new SelectorOption("ca", "Canada")); 71 countryList.add(new SelectorOption("us", "United States")); 72 73 return countryList; 74 } 75 76 /** 77 * Analog data 78 * @return 79 */ 80 private List<SelectorOption> getProvince() { 81 List provinceList = new ArrayList(); 82 provinceList.add(new SelectorOption("hb", "Heibei", "cn")); 83 provinceList.add(new SelectorOption("zj", "Zhejiang", "cn")); 84 provinceList.add(new SelectorOption("gd", "Guangdong", "cn")); 85 provinceList.add(new SelectorOption("gx", "Guangxi", "cn")); 86 provinceList.add(new SelectorOption("ca", "California", "us")); 87 88 return provinceList; 89 } 90 91 /** 92 * Analog data 93 * @return 94 */ 95 private List<SelectorOption> getCity() { 96 List cityList = new ArrayList(); 97 cityList.add(new SelectorOption("gz", "Guangzhou", "gd")); 98 cityList.add(new SelectorOption("nn", "Nanning", "gx")); 99 cityList.add(new SelectorOption("fs", "Foshan", "gd")); 100 cityList.add(new SelectorOption("hz", "Huizhou", "gd")); 101 cityList.add(new SelectorOption("la", "Los Angeles", "ca")); 102 103 return cityList; 104 } 105 106 }
SelectorOption.java用于装一个Select的Option数据:
1 public class SelectorOption { 2 3 private String value; 4 private String name; 5 private String parent; 6 7 public String getValue() { 8 return value; 9 } 10 11 public void setValue(String value) { 12 this.value = value; 13 } 14 15 public String getName() { 16 return name; 17 } 18 19 public void setName(String name) { 20 this.name = name; 21 } 22 23 public String getParent() { 24 return parent; 25 } 26 27 public void setParent(String parent) { 28 this.parent = parent; 29 } 30 31 public SelectorOption(String value, String name) { 32 super(); 33 this.value = value; 34 this.name = name; 35 } 36 37 public SelectorOption(String value, String name, String parent) { 38 super(); 39 this.value = value; 40 this.name = name; 41 this.parent = parent; 42 } 43 44 }
Selector.java用于装一个Selecti的数据:
1 import java.util.ArrayList; 2 import java.util.HashMap; 3 import java.util.List; 4 import java.util.Map; 5 6 public class Selector { 7 8 private String name; 9 private String parent; 10 private Map dataMap; 11 12 public String getName() { 13 return name; 14 } 15 16 public void setName(String name) { 17 this.name = name; 18 } 19 20 public String getParent() { 21 return parent; 22 } 23 24 public void setParent(String parent) { 25 this.parent = parent; 26 } 27 28 public Map getDataMap() { 29 return dataMap; 30 } 31 32 public void setDataMap(Map dataMap) { 33 this.dataMap = dataMap; 34 } 35 36 public Selector(String name, String parent, List dataList) { 37 super(); 38 this.name = name; 39 this.parent = parent; 40 this.dataMap = new HashMap(); 41 this.dataMap.put("default", dataList); 42 } 43 44 public Selector(String name, String parent, Map dataMap) { 45 super(); 46 this.name = name; 47 this.parent = parent; 48 this.dataMap = dataMap; 49 } 50 51 public void put(String key, Object object) { 52 53 if (key == null || key.length() == 0) { 54 return; 55 } 56 57 if (object == null) { 58 return; 59 } 60 61 if (this.dataMap == null) { 62 this.dataMap = new HashMap(); 63 } 64 65 if (this.dataMap.containsKey(key) && this.dataMap.get(key) != null) { 66 List tempList = (List)this.dataMap.get(key); 67 tempList.add(object); 68 } 69 70 if (!this.dataMap.containsKey(key)) { 71 List tempList = new ArrayList(); 72 tempList.add(object); 73 74 this.dataMap.put(key, tempList); 75 } 76 77 } 78 79 }
cascsel.js则用于处理各个级联Select之间的交互:
1 /** 2 * Register & initialize select 3 */ 4 function registerSelector(data, array, index) { 5 if (!array || array.length == 0) { 6 return; 7 } 8 9 if (index < 0 || index >= array.length) { 10 return; 11 } 12 13 if (!data[array[index]]) { 14 return; 15 } 16 17 var $select = $("[name=‘" + array[index] + "‘]"); 18 19 /* Initialize default select */ 20 var dataList = data[array[index]]["dataMap"]["default"]; 21 if (dataList && dataList.length > 0) { 22 $select.empty(); 23 for (var i = 0; i < dataList.length; i++) { 24 $select.append("<option value=‘" + dataList[i]["value"] + "‘>" + dataList[i]["name"] + "</option>") 25 } 26 } 27 28 /* Register onchange event for select */ 29 if ((index + 1) < array.length && data[array[index + 1]]) { 30 $select.bind("change", function(event) { 31 var value = $select.val(); 32 var dataList = data[array[index + 1]]["dataMap"][value]; 33 34 $nextSelect = $("[name=‘" + array[index + 1] + "‘]"); 35 /* If the option of select changes, refactor the cascape select */ 36 if (dataList && dataList.length > 0) { 37 $nextSelect.empty(); 38 for (var i = 0; i < dataList.length; i++) { 39 $nextSelect.append("<option value=‘" + dataList[i]["value"] + "‘>" + dataList[i]["name"] + "</option>") 40 } 41 } else { 42 $nextSelect.empty(); 43 } 44 45 /* Trigger */ 46 $nextSelect.trigger("change"); 47 }); 48 49 $select.trigger("change"); 50 } 51 52 registerSelector(data, array, index + 1); 53 54 }
cascsel.jsp为Demo的展示页面(调用cascsel.js):
1 <%@ page language="java" contentType="text/html; charset=utf-8" 2 pageEncoding="utf-8"%> 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 4 <html> 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 7 <script type="text/javascript" src="js/jquery-1.6.1.js"></script> 8 <script type="text/javascript" src="js/cascsel.js"></script> 9 <script type="text/javascript"> 10 $().ready(function() { 11 12 querySelector(); 13 14 }); 15 16 /** 17 * Get select json by ajax 18 */ 19 function querySelector() { 20 $.ajax({ 21 url : "CascapeSelectorServlet", 22 dataType : "json", 23 type : "post", 24 contentType : "application/x-www-form-urlencoded; charset=utf-8", 25 cache : false, 26 error : function(dty, errorType) { 27 alert(errorType); 28 }, 29 success : function(data) { 30 registerSelector(data, ["country", "province", "city"], 0); 31 } 32 }); 33 } 34 35 </script> 36 37 <title>Cascape Select</title> 38 </head> 39 <body> 40 41 <select name="country" ></select> 42 <select name="province" ></select> 43 <select name="city" ></select> 44 45 </body> 46 </html>
Enjoy it!