使用情景是填写快递邮寄到的地址信息,介绍实现此功能的方法之一,实现之后效果如图所示:
选择省市区,逐个选择逐个出现,如果选择的是北京、天津等直辖市,就不是四级联动是三级联动。
选择镇或街道。
实现步骤:
1. 获取资源数据
/**
* 获取省市区数据
* @return
*/
public static String getListJson() {
String url = "http://passer-by.com/data_location/list.json";
return httpGet(url);
}
/**
* 根据区ID获取街道数据
* @param zone
* @return
*/
public static String getStreetsByZone(String zone) {
String url = "http://passer-by.com/data_location/town/" + zone + ".json";
return httpGet(url);
}
其中 zone 是获取省市区数据的key,将得到的json数据转换成json文件保存到本地,从数据中可以看出,省的key是以0000结尾,市是以00结尾的,可以根据自己的需求去批量的修改得到的数据,例如上图中的"其他"和“暂不填写”就是后加的。保存在本地的数据应该是一个list.json和很多的.json文件,list.json是所有的省市区数据,其他的都是街道数据。
2. 初始化和配置
/**
* jquery.citys.js 1.0
* http://jquerywidget.com
*/
;(function (factory) {
if (typeof define === "function" && (define.amd || define.cmd) && !jQuery) {
// AMD或CMD
define([ "jquery" ],factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = function( root, jQuery ) {
if ( jQuery === undefined ) {
if ( typeof window !== 'undefined' ) {
jQuery = require('jquery');
} else {
jQuery = require('jquery')(root);
}
}
factory(jQuery);
return jQuery;
};
} else {
//Browser globals
factory(jQuery);
}
}(function ($) {
$.support.cors = true;
$.fn.citys = function(parameter,getApi) {
if(typeof parameter == 'function'){ //重载
getApi = parameter;
parameter = {};
}else{
parameter = parameter || {};
getApi = getApi||function(){};
}
var defaults = {
dataUrl:ctx + '/resources/streets/list.json', //数据库地址
dataType:'json', //数据库类型:'json'或'jsonp'
provinceField:'province', //省份字段名
cityField:'city', //城市字段名
areaField:'area', //地区字段名
code:0, //地区编码
province:0, //省份,可以为地区编码或者名称
city:0, //城市,可以为地区编码或者名称
area:0, //地区,可以为地区编码或者名称
required: false, //是否必须选一个
nodata: 'hidden', //当无数据时的表现形式:'hidden'隐藏,'disabled'禁用,为空不做任何处理
onChange:function(){} //地区切换时触发,回调函数传入地区数据
};
var options = $.extend({}, defaults, parameter);
return this.each(function() {
//对象定义
var _api = {};
var $this = $(this);
var $province = $this.find('select[name="'+options.provinceField+'"]'),
$city = $this.find('select[name="'+options.cityField+'"]'),
$area = $this.find('select[name="'+options.areaField+'"]');
$.ajax({
url:options.dataUrl,
type:'GET',
crossDomain: true,
dataType:options.dataType,
jsonpCallback:'jsonp_location',
success:function(data){
var province,city,area,hasCity;
if(options.code){ //如果设置地区编码,则忽略单独设置的信息
var c = options.code - options.code%1e4;
if(data[c]){
options.province = c;
}
c = options.code - (options.code%1e4 ? options.code%1e2 : options.code);
if(data[c]){
options.city = c;
}
c = options.code%1e2 ? options.code : 0;
if(data[c]){
options.area = c;
}
}
var updateData = function(){
province = {},city={},area={};
hasCity = false; //判断是非有地级城市
for(var code in data){
if(!(code%1e4)){ //获取所有的省级行政单位
province[code]=data[code];
if(options.required&&!options.province){
if(options.city&&!(options.city%1e4)){ //省未填,并判断为直辖市
options.province = options.city;
}else{
options.province = code;
}
}else if(data[code].indexOf(options.province)>-1){
options.province = isNaN(options.province)?code:options.province;
}
}else{
var p = code-options.province;
if(options.province&&p>0&&p<1e4){ //同省的城市或地区
if(!(code%100)){
hasCity = true;
city[code]=data[code];
if(options.required&&!options.city){
options.city = code;
}else if(data[code].indexOf(options.city)>-1){
options.city = isNaN(options.city)?code:options.city;
}
}else if(p>9000){ //省直辖县级行政单位
city[code]=data[code];
}else if(hasCity){ //非直辖市
var c = code-options.city;
if(options.city&&c>0&&c<100){ //同个城市的地区
area[code]=data[code];
if(options.required&&!options.area){
options.area = code;
}else if(data[code].indexOf(options.area)>-1){
options.area = isNaN(options.area)?code:options.area;
}
}
}else{
city[code]=data[code]; //直辖市
if(options.area){
options.city = options.area;
options.area = '';
}
if(options.required&&!options.city){
options.city = code;
}else if(data[code].indexOf(options.city)>-1){
options.city = isNaN(options.city)?code:options.city;
}
}
}
}
}
};
var format = {
province:function(){
$province.empty();
if(!options.required){
$province.append('<option value=""> - 请选择省 - </option>');
}
for(var i in province){
$province.append('<option value="'+i+'">'+province[i]+'</option>');
}
if(options.province){
$province.val(options.province);
}
this.city();
},
city:function(){
$city.empty();
if(!options.required){
$city.append('<option value=""> - 请选择 - </option>');
}
if(options.nodata=='disabled'){
$city.prop('disabled',$.isEmptyObject(city));
}else if(options.nodata=='hidden'){
$city.css('display',$.isEmptyObject(city)?'none':'');
}
for(var i in city){
$city.append('<option value="'+i+'">'+city[i]+'</option>');
}
if(options.city){
$city.val(options.city);
}
this.area();
},
area:function(){
$area.empty();
if(!hasCity){
$area.css('display','none');
}else{
$area.css('display','');
if(!options.required){
$area.append('<option value=""> - 请选择区 - </option>');
}
if(options.nodata=='disabled'){
$area.prop('disabled',$.isEmptyObject(area));
}else if(options.nodata=='hidden'){
$area.css('display',$.isEmptyObject(area)?'none':'');
}
for(var i in area){
$area.append('<option value="'+i+'">'+area[i]+'</option>');
}
if(options.area){
$area.val(options.area);
}
}
}
};
//获取当前地理信息
_api.getInfo = function(){
var status = {
direct:!hasCity,
province:data[options.province]||'',
city:data[options.city]||'',
area:data[options.area]||'',
code:options.area||options.city||options.province
};
return status;
};
//事件绑定
$province.on('change',function(){
options.province = $(this).val();
options.city = 0;
options.area = 0;
updateData();
format.city();
options.onChange(_api.getInfo());
});
$city.on('change',function(){
options.city = $(this).val();
options.area = 0;
updateData();
format.area();
options.onChange(_api.getInfo());
});
$area.on('change',function(){
options.area = $(this).val();
options.onChange(_api.getInfo());
});
//初始化
updateData();
format.province();
if(options.code){
options.onChange(_api.getInfo());
}
getApi(_api);
}
});
});
};
}));
在调用控件所在页面之前初始化该js文件,其中dataUrl是获取list.json数据的地址,稍后会在server.xml中进行相应的配置。
<div id="jqcities" > <select id="delivery_province" name="province" class="province" data-value="${model.delivery_province}" ></select> <select id="delivery_city" name="city" class="city" data-value="${model.delivery_city}" ></select> <select id="delivery_area" name="area" class="area" data-value="${model.delivery_area}" ></select> </div>
<select id="town" name="town" class="town" data-value="${model.town}"></select>
在jsp页面中添加控件,并获取初始值,方便在初始化的时候添加默认值。<input type="hidden" id="province1" name="order_token" value="<c:out value="${model.province}" />"> <input type="hidden" id="city1" name="order_token" value="<c:out value="${model.city}" />"> <input type="hidden" id="area1" name="order_token" value="<c:out value="${model.area}" />"> <input type="hidden" id="town1" name="order_token" value="<c:out value="${model.town}" />">
在jsp对应的js文件中初始化街道联动,每次重新选择区会重新获取相应的街道数据。function init() { // 省市区街道联动 //扩展显示行政区划第四级(街道)信息: var $town = $('#town'); var townFormat = function(info){ $town.hide().empty(); if(info['code']%1e4&&info['code']<7e6){ //是否为“区”且不是港澳台地区 $.ajax({ url:ctx + '/resources/streets/'+info['code']+'.json', dataType:'json', required:false, nodata:'disabled', success:function(town){ if(null!=town){ $town.show(); for(i in town){ $town.append('<option value="'+i+'">'+town[i]+'</option>'); } } } }); } }; var province1 = $("#province1").val(); var city1 = $("#city1").val(); var area1 = $("#area1").val(); $('#jqcities').citys({ province:province1, city:city1, area:area1, onChange:function(info){ townFormat(info); } },function(api){ var info = api.getInfo(); townFormat(info); }); setTimeout(function(){ var town1 = $("#town1").val(); var elemTown = document.getElementById("town"); var selIndex = 0; for(var i=0; i<elemTown.children.length; i++){ if (elemTown.children[i].text==town1) { selIndex = i;break; } } elemTown.selectedIndex = selIndex; },1000); // 省市区街道联动 $('.right_wp').css('background-color','#f3f3f3'); $('.right_wp_box').css({'width':'1065px','border':'0'}); $('.right_wp').css({'min-height':'900px','width':'1065px'}); $('.title').css('width','1045px'); if ($("#success").val() == 'true') { $("input:radio[name=addressType]").click(function() { var type = $(this).val(); if (type == "1") { $("#revAddress").focus(); // 切换时,重新验证 $("#revOtherAddress").attr("disabled", false); $("#revAddress").attr("disabled", true); } else { $("#revOtherAddress").focus(); // 切换时,重新验证 $("#revAddress").attr("disabled", false); $("#revOtherAddress").attr("disabled", true); } }); } isEdit = $('#isEdit').val(); $.each($("input[name=nums]"), function() { if (lastGiftIds != "") { lastGiftIds += ","; lastNums += ","; } lastGiftIds += $(this).parent().find("input:hidden[name=ids]").val(); lastNums += $(this).val(); }); $.each($("input[name=numsNotLive]"), function() { if (lastIdsNotlive != "") { lastIdsNotlive += ","; lastNumsNotlive += ","; } lastIdsNotlive += $(this).parent().find("input:hidden[name=idsNotLive]").val(); lastNumsNotlive += $(this).val(); }); $.each($("input[name=numsLive]"), function() { if (lastIdslive != "") { lastIdslive += ","; lastNumslive += ","; } lastIdslive += $(this).parent().find("input:hidden[name=idsLive]").val(); lastNumslive += $(this).val(); }); if($("#commentUserString").val()){ $("#revComment").val($("#commentUserString").val()); } }
3. 配置虚拟路径
在Tomcat的server.xml中Host下配置资源的路径和虚拟路径,
我是放在D盘的streets文件夹中,能访问到就好,不然前端会报错。<Context docBase="D:\streets" path="**/resources/streets" reloadable="true"/>
数据每一两年或在需要更新的时候重新获取替换就好了,应该不需要太频繁。