系统设计地址为省市县三级联动,规范是规范了,但是无形中增加了系统操作的时间成本,因此设计地址自动返填技术,只要把地址拷贝到详细地址框中,可以自动返填到省市县三级联动的下拉框中。
还好洒家的大学不是混过来的,写起这个模块来感觉饶有趣味。
一、dom结构
省市县三级自然以三个下拉框的形式展现,详细地址为一个textarea框,id分别使用province、city、coll、detailAddress代表。
1 <%@ page contentType="text/html;charset=UTF-8" language="java"%>
2 <%@include file="/WEB-INF/webpage/common/taglibs.jspf"%>
3 <!-- Author : guanghe-->
4 <%--
5 引用方法:
6 <form id="itemForm" action="item" method="post">
7 <jsp:include page="../../common/address.jsp">
8 <jsp:param name="init" value="true" />
9 <jsp:param name="amount" value="false" />
10 </jsp:include>
11 </form>
12 --%>
13 <table class="table table-bordered table-condensed dataTables-example dataTable no-footer">
14 <tbody>
15 <tr>
16 <td class="width-15 active text-right">
17 <label><font color="red">*</font>名称:</label>
18 </td>
19 <td class="width-35">
20 <input id="name" name="name" class="form-control inputxt" datatype="*" errormsg="请填写名称!" />
21 <label class="Validform_checktip"></label>
22 </td>
23 </tr>
24 <tr>
25 <td class="width-15 active text-right">
26 <label><font color="red">*</font>联系人:</label>
27 </td>
28 <td class="width-35">
29 <input id="contactsName" name="contactsName" class="form-control inputxt" datatype="*" errormsg="请填写联系人!" />
30 <label class="Validform_checktip"></label>
31 </td>
32 </tr>
33 <tr>
34 <td class="width-15 active text-right">
35 <label>电话:</label>
36 </td>
37 <td class="width-35">
38 <input id="phone" name="phone" class="form-control inputxt" datatype="/(^13[0-9]{9}$|14[0-9]{9}|15[0-9]{9}$|18[0-9]{9}$)|^-$|^s*$/" errormsg="请填写固话号、手机号或空!" />
39 <label class="Validform_checktip"></label>
40 </td>
41 </tr>
42 <c:if test="${param.amount}">
43 <tr>
44 <td class="width-15 active text-right">
45 <label><font color="red">*</font>配送数量:</label>
46 </td>
47 <td class="width-35">
48 <input type="text" id="amount" name="text" class="form-control inputxt" datatype="/^[1-9][0-9]*$/" errormsg="请填写配送数量!" />
49 <label class="Validform_checktip"></label>
50 </td>
51 </tr>
52 </c:if>
53 <tr>
54 <td class="width-15 active text-right">
55 <label><font color="red">*</font>地址:</label>
56 </td>
57 <td class="width-35">
58 <div style="margin-bottom: 5px;">
59 <select name="province" class="inputxtcommon" id="province"
60 onchange="changCity('${adminPath}/basic/usualaddress/regionSelect');">
61 <option value="0">请选择省份</option>
62 </select>
63 <select name="city" class="inputxtcommon" id="city"
64 onchange="changColl('${adminPath}/basic/usualaddress/regionSelect')">
65 <option value="0">请选择市</option>
66 </select>
67 <select name="coll" id="coll" class="inputxtcommon" onchange="setColl() ">
68 <option value="0">请选择区</option>
69 </select>
70 </div>
71 <div>
72 <textarea id="detailAddress" name="detailAddress" class="form-control inputxt" datatype="*" errormsg="请填写具体地址!"></textarea>
73 <label class="Validform_checktip"></label>
74 </div>
75 </td>
76 </tr>
77 </tbody>
78 </table>
79 <script>
80 //省数据字典
81 var proDict = null;
82 //页面初始化
83 $(function(){
84 <c:if test="${param.init}">
85 var address = null;
86 <c:if test="${not empty data && not empty data.province}">
87 address = {
88 province : "${data.province}",
89 city : "${data.city}",
90 coll : "${data.coll}",
91 detailAddress : "${data.detailAddress}"
92 };
93 </c:if>
94 //初始化地址组件
95 setAddress(address);
96 //加载已有数据
97 var item = {
98 name : "${data.name}",
99 contactsName : "${data.contactsName}",
100 phone : "${data.phone}",
101 <c:if test="${param.amount}">
102 amount : "${data.amount}"
103 </c:if>
104 };
105 setItem(item);
106 </c:if>
107 });
108 //初始化地址组件
109 function setAddress(address) {
110 proDict = window.initSelect(1, 'province','${adminPath}/basic/usualaddress/regionSelect');
111 //加载默认地址数据
112 if(address && address.province) {
113 window.$("#province").val(address.province);
114 window.changCity('${adminPath}/basic/usualaddress/regionSelect');
115 window.$("#city").val(address.city);
116 window.changColl('${adminPath}/basic/usualaddress/regionSelect');
117 window.$("#coll").val(address.coll);
118 window.$("#detailAddress").val(address.detailAddress);
119 }
120 //绑定地址自动识别功能
121 $("#detailAddress").blur(function(e) {
122 autoRecognition(1, 1);
123 });
124 }
125 //初始化已有地址相关数据
126 function setItem(item) {
127 $("#name").val(item.name);
128 $("#contactsName").val(item.contactsName);
129 $("#phone").val(item.phone);
130 <c:if test="${param.amount}">
131 $("#amount").val(item.amount);
132 </c:if>
133 }
134 //获取地址字段信息
135 function getItem() {
136 var proId = $("#province").val();
137 var directCity = [2, 3, 10, 23];
138 var address = "";
139 if($.inArray(proId - 0, directCity) >= 0) {
140 address = $("#province").find("option:selected").text() +
141 $("#coll").find("option:selected").text() + $("#detailAddress").val();
142 } else {
143 address = $("#province").find("option:selected").text() + $("#city").find("option:selected").text() +
144 $("#coll").find("option:selected").text() + $("#detailAddress").val();
145 }
146 return {
147 name : $("#name").val(),
148 contactsName : $("#contactsName").val(),
149 phone : $("#phone").val(),
150 <c:if test="${param.amount}">
151 amount : $("#amount").val(),
152 </c:if>
153 province : $("#province").val(),
154 city : $("#city").val(),
155 coll : $("#coll").val(),
156 detailAddress : $("#detailAddress").val(),
157 address : address
158 };
159 }
160 </script>
二、工具函数与核心递归函数
主要是设计地址数据的查询、dom修改工具函数、核心递归函数
1 //初始化选项,并拿到数据字典
2 function initSelect(pid, selectId,url) {
3 var dict = {};
4 selectUrl = url;
5 $("#" + selectId + "").find('option').not(':eq(0)').remove();
6 $.ajax({
7 url : url,
8 type : 'post',
9 dataType : "json",
10 data : { pid : pid },
11 async : false,
12 success : function(result,status,xhr) {
13 var list = result.list;
14 var options = "";
15 for (var index in list) {
16 var opt = list[index];
17 options += '<option value="' + opt.id+'">' + opt.name + '</option>';
18 dict[opt.id] = opt.name;
19 }
20 $("#" + selectId + "").append(options);
21 },
22 error : function(xhr,status,err) {
23 top.layer.alert(err);
24 }
25 });
26 return dict;
27 }
28 function changCity(url) {
29 var dict = null;
30 if ($("#province").val() != 0) {
31 dict = initSelect($("#province").val(), 'city',url);
32 province = $("#province").find("option:selected").text();
33 $("#coll").find('option').not(':eq(0)').remove();
34 }else{
35 $("#city").find('option').not(':eq(0)').remove();
36 $("#city").val("0");
37 $("#coll").find('option').not(':eq(0)').remove();
38 $("#coll").val("0");
39 }
40 return dict;
41 }
42 function changColl(url) {
43 var dict = null;
44 if ($("city").val() != 0) {
45 dict = initSelect($("#city").val(), 'coll',url);
46 city = $("#city").find("option:selected").text();
47 }
48 return dict;
49 }
50 //地址自动识别器 level 1:省 2:市 3:县
51 function autoRecognition(level, pid) {
52 var address = $("#detailAddress").val();
53 var isMatched = false; //终止器
54 //迭代体
55 if(address && level) { //剪枝函数
56 var url = '${adminPath}/basic/usualaddress/regionSelect';
57 var dict = null;
58 var dom = null;
59 var nextLevel = null;
60 var exeMatcher = true;
61 if(level == 1) {
62 dict = proDict;
63 dom = "#province";
64 nextLevel = 2;
65 } else if(level == 2){
66 dict = window.changCity(url);
67 dom = "#city";
68 nextLevel = 3;
69 //如果是直辖市
70 if($.inArray(pid - 0, [2, 3, 10, 23]) >= 0) {
71 //关闭匹配器
72 exeMatcher = false;
73 }
74 } else if(level == 3) {
75 dict = window.changColl(url);
76 dom = "#coll";
77 nextLevel = 0;
78 }
79 //开启匹配则运行匹配器
80 if(exeMatcher) {
81 $.each(dict, function(key, value) {
82 if(address.indexOf(value) == 0) {
83 window.$(dom).val(key);
84 address = address.substring(value.length, address.length);
85 $("#detailAddress").val(address);
86 autoRecognition(nextLevel, key);
87 isMatched = true;
88 return false;
89 }
90 });
91 } else { //直辖市跳过市级遍历,直接进入区级遍历
92 $.each(dict, function(key, value) {
93 window.$(dom).val(key);
94 var isFound = autoRecognition(nextLevel, key);
95 if(isFound) {
96 return false;
97 }
98 });
99 }
100 }
101 return isMatched;
102 }