+ -
当前位置:首页 → 问答吧 → 结合省市区的下拉显示,讨论级联菜单的处理方式

结合省市区的下拉显示,讨论级联菜单的处理方式

时间: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控件的初始值

省市区级联处理所用文件下载

作者: evangui   发布时间: 2009-05-14

我曾经用java写过一个,分步提取数据。

楼主的代码有点乱啊!

作者: kaki   发布时间: 2009-05-18