结合省市区的下拉显示,讨论级联菜单的处理方式
时间:2009-05-14
来源:互联网
本帖最后由 evangui 于 2009-5-24 15:39 编辑
原文发表于http://www.guigui8.com/index.php/archives/139.html
目前对于级联下拉菜单的处理,是在客户端js中,通过勾选某一级的select控件内容,来触发一个onchange事件,该事件无疑要完成 获取当前select控件相对应的子项的内容 并 重置其下属的select控件列表。
对于 如何获取当前select控件相对应的子项的内容,有两种方式供选择.
一种是,在客户端进行 与服务器端异步交互,可以表现为向服务器端发送ajax请求,来获取数据。
另一种是,预先将所有用到的数据 在js文件中,以一种树状的数据结构进行存储。获取数据的过程,就表现为获取当前select控件所对应的child对象内容。
第一种方式,需要不断地与服务器端交互,在网络不好的情况下,这个过程还是挺难受的;而第二种方式,缺陷是构造数据的过程显得有点麻烦,且数据文件不宜过大。
但一般的下拉菜单的级联处理,其数据量并不会大,而且在总结了构造js数据的经验后,我个人更喜欢第二种方式进行级联菜单的现实处理。
——————————————————————–
下面以一个中国省市区的级联菜单为例,讲述整个处理过程。
1. 原始数据来源
曾经做项目的时候,找这个省市区的数据还并不轻松,主要是网上google到的省市区数据,都是仍到js数组里面的,而我还需要把数据存到数据库,在服务器端进行分析处理。
最后幸好被我找到了,本人整理成了location.txt,数据表示成 id号:层级路径表示符:地区名:层数 这样的形式。
如湖北省和武汉市分别为 1867:17:湖北省:0 和 1868:1701:武汉市:1
2. 将loaction.txt的数据,也送入到数据库进行存储。
就是一次导入数据的过程,这个很简单(逐行读文件,逐行插数据)。导入后的表名为location 。导入的数据库数据如:location.sql.txt
3. 将数据以树状分级形式,缓存成json数据格式。
缓存过程如下:
[php]
<?php
/**
* 更新目录缓存,每次对目录信息进行修改后都要进行次操作。
*/
static function cacheItems() {
$arr = self::findAll();
// 可以将数据也缓存成服务端程序 能 处理的数据。在此略过
$json_data = json_encode($arr);
$json_data = "var cLocationsData = " . $json_data . ";";
file_put_contents('js/location_data.js', $json_data);
}
/**
* 从数据库中取出所有分类信息,并组织成层级的树状结构
*
* @param interger $in_id
* @return array
*/
private static function findAll($in_id=0) {
global $db;
$query = "SELECT * FROM `" . LocationMgr::$_table . "` ORDER BY `l_layer` ";
$result = $db->query($query);
$arr_out = array();
while ($row = $db->fetch_array($result)) {
$arr_out[$row['l_layer']] = $row; //注意,这里的l_layer作为索引项了
}
//将最近一层孩子接点添加到child索引上。
foreach ($arr_out as $key => $value) {
$len_key = strlen($key);
//第3层结点
if ($len_key > 4) continue; //针对省市区只有3层,加上了这个跳出判断
foreach ($arr_out as $sub_key => $sub_value) {
$len_expected = $len_key + 2; //下一级孩子结点layer长度
if (strlen($sub_key) == $len_expected) {
if (substr($sub_key, 0, $len_key) == $key) {
$arr_out[$key]['child'][] = $sub_key;
}
}
}
}
return $arr_out;
}
?>
[/php]
4. 客户端js处理
4.1 定义省,市,区的下拉列表显示方法。
如根据省的层级路径,来显示市下拉列表过程如下:
(移除原来市的select空间下的所有options项;获取指定省份的所有城市数据;逐个将城市数据绑定到市的select的option项下)
[code]
//市显示
function showCities(city_id, sFatherLayer) {
var oSelectCity = document.getElementById(city_id);
var oOption;
var len = oSelectCity.length;
for (var i=0; i < len; i++) {
//oSelectCity.remove(i);
oSelectCity.removeChild(oSelectCity.options[0]);
}
oOption = document.createElement('option');
oOption.name = "city_info";
oOption.value = -1;
oOption.text = '请选择城市';
oSelectCity.options.add(oOption);
var aCity = cLocationsData[sFatherLayer].child; //当前省的所有城市layer值集合
for (var i = 0; i < aCity.length; i++) {
var sCurLayer = aCity;
oOption = document.createElement('option');
oOption.name = "city_info";
oOption.value = cLocationsData[sCurLayer].l_layer;
oOption.text = cLocationsData[sCurLayer].l_name;
oSelectCity.options.add(oOption);
}
}
[/code]
4.2 定义省,市的下拉控件的onchange事件方法。
如修改城市的select,则要触发所选择的城市所包含区的显示;
[code]//更改市的onchange事件触发
//更改市的onchange事件触发
function setCity(city_id, area_id) {
var oSelectCity = document.getElementById(city_id);
var index = oSelectCity.selectedIndex;
if (index == 0) {
return false;
}
var sLayer = oSelectCity.options[index].value;
showAreas(area_id, sLayer);
}
[/code]
使用方法:示例页面 http://www.guigui8.com/demo/shengshiqu-jilianxiala/
在页面加载完毕后,调用GYJ_initLocation方法.
function GYJ_initLocation(province_id, city_id, area_id, province_val, city_val, area_val)
参数说明如下:
province_id : 省份的select控件id名
city_id : 城市的select控件id名
area_id : 区的select控件id名
province_val : 省份的select控件的初始值
city_val : 城市的select控件的初始值
area_val : 区的select控件的初始值
省市区级联处理所用文件下载
原文发表于http://www.guigui8.com/index.php/archives/139.html
目前对于级联下拉菜单的处理,是在客户端js中,通过勾选某一级的select控件内容,来触发一个onchange事件,该事件无疑要完成 获取当前select控件相对应的子项的内容 并 重置其下属的select控件列表。
对于 如何获取当前select控件相对应的子项的内容,有两种方式供选择.
一种是,在客户端进行 与服务器端异步交互,可以表现为向服务器端发送ajax请求,来获取数据。
另一种是,预先将所有用到的数据 在js文件中,以一种树状的数据结构进行存储。获取数据的过程,就表现为获取当前select控件所对应的child对象内容。
第一种方式,需要不断地与服务器端交互,在网络不好的情况下,这个过程还是挺难受的;而第二种方式,缺陷是构造数据的过程显得有点麻烦,且数据文件不宜过大。
但一般的下拉菜单的级联处理,其数据量并不会大,而且在总结了构造js数据的经验后,我个人更喜欢第二种方式进行级联菜单的现实处理。
——————————————————————–
下面以一个中国省市区的级联菜单为例,讲述整个处理过程。
1. 原始数据来源
曾经做项目的时候,找这个省市区的数据还并不轻松,主要是网上google到的省市区数据,都是仍到js数组里面的,而我还需要把数据存到数据库,在服务器端进行分析处理。
最后幸好被我找到了,本人整理成了location.txt,数据表示成 id号:层级路径表示符:地区名:层数 这样的形式。
如湖北省和武汉市分别为 1867:17:湖北省:0 和 1868:1701:武汉市:1
2. 将loaction.txt的数据,也送入到数据库进行存储。
就是一次导入数据的过程,这个很简单(逐行读文件,逐行插数据)。导入后的表名为location 。导入的数据库数据如:location.sql.txt
3. 将数据以树状分级形式,缓存成json数据格式。
缓存过程如下:
[php]
<?php
/**
* 更新目录缓存,每次对目录信息进行修改后都要进行次操作。
*/
static function cacheItems() {
$arr = self::findAll();
// 可以将数据也缓存成服务端程序 能 处理的数据。在此略过
$json_data = json_encode($arr);
$json_data = "var cLocationsData = " . $json_data . ";";
file_put_contents('js/location_data.js', $json_data);
}
/**
* 从数据库中取出所有分类信息,并组织成层级的树状结构
*
* @param interger $in_id
* @return array
*/
private static function findAll($in_id=0) {
global $db;
$query = "SELECT * FROM `" . LocationMgr::$_table . "` ORDER BY `l_layer` ";
$result = $db->query($query);
$arr_out = array();
while ($row = $db->fetch_array($result)) {
$arr_out[$row['l_layer']] = $row; //注意,这里的l_layer作为索引项了
}
//将最近一层孩子接点添加到child索引上。
foreach ($arr_out as $key => $value) {
$len_key = strlen($key);
//第3层结点
if ($len_key > 4) continue; //针对省市区只有3层,加上了这个跳出判断
foreach ($arr_out as $sub_key => $sub_value) {
$len_expected = $len_key + 2; //下一级孩子结点layer长度
if (strlen($sub_key) == $len_expected) {
if (substr($sub_key, 0, $len_key) == $key) {
$arr_out[$key]['child'][] = $sub_key;
}
}
}
}
return $arr_out;
}
?>
[/php]
4. 客户端js处理
4.1 定义省,市,区的下拉列表显示方法。
如根据省的层级路径,来显示市下拉列表过程如下:
(移除原来市的select空间下的所有options项;获取指定省份的所有城市数据;逐个将城市数据绑定到市的select的option项下)
[code]
//市显示
function showCities(city_id, sFatherLayer) {
var oSelectCity = document.getElementById(city_id);
var oOption;
var len = oSelectCity.length;
for (var i=0; i < len; i++) {
//oSelectCity.remove(i);
oSelectCity.removeChild(oSelectCity.options[0]);
}
oOption = document.createElement('option');
oOption.name = "city_info";
oOption.value = -1;
oOption.text = '请选择城市';
oSelectCity.options.add(oOption);
var aCity = cLocationsData[sFatherLayer].child; //当前省的所有城市layer值集合
for (var i = 0; i < aCity.length; i++) {
var sCurLayer = aCity;
oOption = document.createElement('option');
oOption.name = "city_info";
oOption.value = cLocationsData[sCurLayer].l_layer;
oOption.text = cLocationsData[sCurLayer].l_name;
oSelectCity.options.add(oOption);
}
}
[/code]
4.2 定义省,市的下拉控件的onchange事件方法。
如修改城市的select,则要触发所选择的城市所包含区的显示;
[code]//更改市的onchange事件触发
//更改市的onchange事件触发
function setCity(city_id, area_id) {
var oSelectCity = document.getElementById(city_id);
var index = oSelectCity.selectedIndex;
if (index == 0) {
return false;
}
var sLayer = oSelectCity.options[index].value;
showAreas(area_id, sLayer);
}
[/code]
使用方法:示例页面 http://www.guigui8.com/demo/shengshiqu-jilianxiala/
在页面加载完毕后,调用GYJ_initLocation方法.
function GYJ_initLocation(province_id, city_id, area_id, province_val, city_val, area_val)
参数说明如下:
province_id : 省份的select控件id名
city_id : 城市的select控件id名
area_id : 区的select控件id名
province_val : 省份的select控件的初始值
city_val : 城市的select控件的初始值
area_val : 区的select控件的初始值
省市区级联处理所用文件下载
作者: evangui 发布时间: 2009-05-14
我曾经用java写过一个,分步提取数据。
楼主的代码有点乱啊!
楼主的代码有点乱啊!
作者: kaki 发布时间: 2009-05-18
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28