完整中英文世界国家级联下拉列表插件【前端版】

原创
2014/11/02 01:21
阅读数 6.3K

这个小东西是之前小项目上临时增加功能的产物,那时候在网上找了很久都没有能用的插件,要么是数据残缺少得可怜,还有就是实现手段非常低效不可维护那种,各种奇拔问题!反正就没有逞心如意!那时候又急需要这样一个功能,百般无奈后灵机一动,想起某企鹅功能选项不是有这样的世界国家级联功能嚒!那肯定有地方存着这数据的哇!嘿嘿!心里突然暗喜,终于有方向,然后就是向这企鹅开刀找!在某个i18n国际化文件夹中找到了!立马放下心头大石!

 

这样子中英文版本的数据都有了!但是问题又来了!该怎么开始做呢?

怎么去调用这个数据呢?

想法一:把数据拆分出来导入数据库,然后Ajax级联获取数据

想法二:把数据转换成熟悉的格式,在前端获取后递归拆分

想法三:直接利用jquery读取xml然后捉取数据(这是完成这插件后很久回头想到!逼于屌丝项目时间赶没多考虑的结果)

后来我是选择了第二种方案,转换成json对象,在前端递归获取数据;

其实这个方案也是不错的!JS对象属性查找效率是非常不错的!

那这个方案要怎么转换成又方便又简单的数组数据呢?又地让国家、省份、城市、区级之间又有关联

那时候是直接用元素名作为keyName关联;

其实那时候具体过程已经忘记了,直接贴那时候PHP的代码,

<?php

	$file = dirname(__FILE__).'/LocList_en.xml';
	$obj  = simplexml_load_file($file);
	
	$CountryArr = array();
	$StateArr   = array();
	$CityArr    = array();
	$RegionArr  = array();
	
	$cCode = 1; $cState = 1; $cCity = 1; $cRegion = 1;
	
	foreach ( $obj as $CountryRegion ) {
		
		$CountryArr[] = array('Name'=>(string)$CountryRegion['Name'],'Code'=>'c'.$cCode);
		
		foreach ( $CountryRegion as $State ) {
			
			if(!empty($State['Name']))
			{
				$StateArr['c'.$cCode][] = array('Name'=>(string)$State['Name'],'Code'=>'s'.$cState);
			}
			
			foreach ( $State as $City ) {
				
				if(!empty($City['Name']))
				{
					if(!empty($State['Code']))
						$CityArr['s'.$cState][] = array('Name'=>(string)$City['Name'],'Code'=>'c'.$cCity);
					else
						$CityArr['c'.$cCode][] = array('Name'=>(string)$City['Name'],'Code'=>'c'.$cCity);
				}
				
				foreach ( $City as $Region ) {
					
					if(!empty($Region['Name']))
					{
						if(!empty($City['Code']))
							$RegionArr['c'.$cCity][] = array('Name'=>(string)$Region['Name'],'Code'=>'r'.$cRegion);
					}
					#县级代码
					$cRegion++;
				}
				#城市代码
				$cCity++;	
			}
			#省份代码
			$cState++;
		}
		#国家代码
		$cCode++;
	}
	//echo '<pre>';print_r(array('country'=>$CountryArr,'state'=>$StateArr,'city'=>$CityArr,'region'=>$RegionArr));exit;
	echo(json_encode(array('country'=>$CountryArr,'state'=>$StateArr,'city'=>$CityArr,'region'=>$RegionArr)));exit;
?>

JSON数据的样子

接着就是前段JS的编写!碍于当时没多少时间去写!代码非常糟糕!哎!算是一个工程版!

用jquery框架辅助!开发效率十分高!执行效率也还行!就是需要加载完整的地理数据稍稍慢!320kb的数据还能接受吧!对于客户突来的需求!

(function($){
	$.fn.extend({
		GlobalGeography:function(){
			
			/* ._GlobalGeography_ { width:282px; height:30px !important; position:relative; left:-282px; top:2px; } */
			
			var relatedObj = ['div[id="country"]','div[id="state"]','div[id="city"]','div[id="region"]'];
			var excludeObj = ['div[id="region"]'];	
			var selectmenu = ['country','state','city','region'];
			var selector   = this.selector;
			
			/*输出下拉列表*/
			function _traversal(source,type){
				if(typeof(source)!='undefined'){
					var _select_  = '<select class="_GlobalGeography_">';
						_select_ += '<option value=""></option>';
					$.each(source,function(i,v){
						_select_ += '<option value="'+v.Code+'">'+v.Name+'</option>';
					});
					_select_ += '</select>';
					return _select_;
				}
				return false;
			};
			
			/*清除/还原下级关联下拉菜单*/
			function cleanNextMenu(index){
				for(var i=index;i<relatedObj.length;i++){
					if(typeof(relatedObj[(i+1)])!='undefined'){
						$(relatedObj[(i+1)]).find('._GlobalGeography_').remove();
						$(relatedObj[(i+1)]).find('input').val('');
					}
				}
			}
			
			/*遍历获取下拉菜单内容*/
			function checkMenu(json){
				/*遍历赋值所有类型*/
				$.each(relatedObj,function(i,v){
					if($.inArray(v,excludeObj)==-1){
						$(v).find('select').bind('change',function(){
							var _code_ = $(this).val(); cleanNextMenu(i);
							if(typeof(json[selectmenu[(i+1)]][_code_])!='undefined'){
								$(relatedObj[(i+1)]).append(_traversal(json[selectmenu[(i+1)]][_code_],selectmenu[(i+1)]));
								/*绑定方法*/
								$(relatedObj[(i+1)]).find('._GlobalGeography_').bind('change',function(){
									$(relatedObj[(i+1)]).find('input').val($(this).find('option:selected').text());
								});
								checkMenu(json);
							} else {
								$(relatedObj[(i+2)]).append(_traversal(json[selectmenu[(i+2)]][_code_]));
								/*绑定方法*/
								$(relatedObj[(i+2)]).find('._GlobalGeography_').bind('change',function(){
									$(relatedObj[(i+2)]).find('input').val($(this).find('option:selected').text());
								});
							}
						});
					}
				});
			}
			
			/*加载世界国家城市数据*/
			$.getJSON("db_en.dat",function(json){
				/*输出国家列表*/
				$(selector).append(_traversal(json.country,'country'));
				$(selector).find('._GlobalGeography_').bind('change',function(){
					$(selector).find('input').val($(this).find('option:selected').text());
				});
				checkMenu(json);
			});
		}
	})
})(jQuery);

html代码

<!DOCTYPE>
<html>
	<head>
		<meta charset="utf-8">
		<script src="jquery.js"></script>
		<script src="country_noinv.js"></script>
		<style type="text/css">
			._GlobalGeography_ { width:200px; }
		</style>
	</head>
	<body>
		<div id="country"></div>
		<div id="state"></div>
		<div id="city"></div>
		<div id="region"></div>
	</body>
</html>
<script>
$(document).ready(function(){
	$('#country').GlobalGeography();
});
</script>

执行效果,这里有一个问题,就是英文版只去到城市就没了!所以数据包大小也减半只有148kb

//这里主要是用了非入侵方式,数组元素分别对应selectmenu
var relatedObj = ['div[id="country"]','div[id="state"]','div[id="city"]','div[id="region"]'];
//这里主要控制级联到哪个级别就不再继续执行
var excludeObj = ['div[id="region"]'];
var selectmenu = ['country','state','city','region'];

这个小东西是抛砖引玉了!实现手段并不高效!代码有很多地方可以改进!

整理代码时候翻出来,希望能帮助到有需要的人!



展开阅读全文
打赏
2
29 收藏
分享
加载中
尐桀博主
链接:https://pan.baidu.com/s/1vYxjrvp4Ez7AwdQdz5Buvw
密码:y9wb
2018/05/04 09:53
回复
举报
@尐桀 你好,能把这个地理数据在分享一下么?万分感谢
2018/05/04 09:44
回复
举报
这个链接没有了 能在共享一下吗 ?
2018/03/02 09:12
回复
举报
尐桀博主

引用来自“尐桀”的评论

如果需要地理数据请到云盘下载已分享
http://yunpan.cn/cs5gEyCyuBg7d 提取码 fd09

引用来自“name彬”的评论

这个链接没有了 能在共享一下吗 ?
http://pan.baidu.com/s/1mhYyiLU
2016/12/05 21:44
回复
举报

引用来自“尐桀”的评论

如果需要地理数据请到云盘下载已分享
http://yunpan.cn/cs5gEyCyuBg7d 提取码 fd09
这个链接没有了 能在共享一下吗 ?
2016/09/02 15:15
回复
举报
有源文件吗 可以共享一下吗 ?
2016/09/01 16:29
回复
举报

引用来自“尐桀”的评论

如果需要地理数据请到云盘下载已分享
http://yunpan.cn/cs5gEyCyuBg7d 提取码 fd09
求数据,这个资源删了吗? 数据是全世界的吗?
2015/06/19 12:07
回复
举报
不好意思,示例页面地址弄错了,是这个: http://tams.oschina.mopaas.com/demo/ComponentTest
2014/12/03 09:07
回复
举报
我很认同写死始终是不个不好的解决方案,采用代码+配置的方法是最佳的,我也写了一个级联的组件,支持无限级的级联扩展和无限级的纵向级联,博文如下:http://my.oschina.net/rjzjh/blog?catalog=577754
示例页面如下:http://localhost:8080/demo/ComponentTest 仅供参考。
2014/12/03 09:06
回复
举报
尐桀博主

引用来自“Skiychan”的评论

if true?放这里没有啥用处呢。主要是{}这货。 我一般是。if (false) die();
谢谢提醒!已经去掉 之前是判断其他东西!后来修改!就一直遗留下来!
2014/11/02 12:02
回复
举报
更多评论
打赏
12 评论
29 收藏
2
分享
返回顶部
顶部