省市县乡村 动态级联加载控件AreaRender(二)

今天很激动啊,昨天下午赶时间写的省市县乡村 动态级联加载控件AreaRender(一)已经有博友评论了,

对于刚开始写博客的我是莫大的鼓励,我会继续写下去,逐步提高自己的文学素养,写出像 T2噬菌体博主一样受到大家欢迎的作品。

好了,言归真转,接下来我们先分析一下关于分布视图~/Views/AreaManager/AreaRender.cshtml的编写问题。

该分布视图包含两个部分:隐藏域(即用户要搜集的数据部分)和五个select下拉列表

@*
  //功能:实现对省市县乡村的自动级联加载
  //作者:刘帅 liushuai@upway.cn
  //时间:2012.11.29 周四
  //使用说明:首先,用户需要提供一个字典,其中键对应字段名称,值就是对应字段的值;
  //         其次,要提供获取省份数据的url和获取下一级区划的url。
  //版本:v1.0
*@
@if (Model.data != null)
{
    //原始数据
    Dictionary<string, string> ds = Model.data;
    //随即生成工作区,以免相互干扰
    Random random = new Random();
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    sb.Append((char)random.Next(65, 90));
    sb.Append((char)random.Next(97, 122));
    sb.Append((char)random.Next(97, 122));
    sb.Append((char)random.Next(97, 122));
    //定义工作区
    <div id="@sb.ToString()-div">
        @{
    //生成隐藏域,一次按照省市县乡村的顺序进行加载,便于操作 
    for (int i = 0; i < ds.Count; i++)
    {
            <input type="hidden" id="@ds.ElementAt(i).Key.Replace('.', '-')" name="@ds.ElementAt(i).Key" value="@ds.ElementAt(i).Value" />
    }
    //生成级联加载的结束标记
            <input type="hidden" id="end" value="@ds.ElementAt(5).Key.Replace('.', '-')" />
    //生成五个select:id,name和class的前缀均为'Spring-'以免发生冲突,也是我最喜欢的单词和季节;
    //onchange事件:1.刷新隐藏域的值,2.加载下一级;
    //第一个参数是工作区,第二个参数当前select的Id,第三个参数是下一个select的id,第四个参数是获取下一级区划的url,第五个参数是select的类
            <select id="Spring-province" name="Spring-province" class="Spring-select" onchange="AddNextLevel('#' + '@sb.ToString()-div #','Spring-province','Spring-city','@Model.nextUrl',' .Spring-select')">
            </select>
            <select id="Spring-city" name="Spring-city" class="Spring-select" onchange="AddNextLevel('#' + '@sb.ToString()-div #','Spring-city','Spring-country','@Model.nextUrl',' .Spring-select')">
            </select>
            <select id="Spring-country" name="Spring-country" class="Spring-select" onchange="AddNextLevel('#' + '@sb.ToString()-div #','Spring-country','Spring-town','@Model.nextUrl',' .Spring-select')">
            </select>
            <select id="Spring-town" name="Spring-town" class="Spring-select" onchange="AddNextLevel('#' + '@sb.ToString()-div #','Spring-town','Spring-village','@Model.nextUrl',' .Spring-select')">
            </select>
            <select id="Spring-village" name="Spring-village" class="Spring-select" onchange="AddNextLevel('#' + '@sb.ToString()-div #','Spring-village','','',' .Spring-select')">
            </select>
            <script type="text/javascript">
                //触发加载省份信息
                AddProvince("#" + "@sb.ToString()-div #", "Spring-province", "Spring-city", "@ds.ElementAt(0).Key.Replace('.', '-')", "@ds.ElementAt(1).Key.Replace('.', '-')", '@Model.provinceUrl', '@Model.nextUrl');
            </script>
        }
    </div>
}

出于对通用性的要求,我将该控件包含在一个动态生成id的div中,以避免不必要的冲突;

这样一来,该控件就可以在同一个页面中存在多个,而又不产生混淆。当然这段代码也不是一蹴而就的,是在不断地思考,不断地修改。

并且尽量减少该分部视图对外部的耦合度。

我又详细的注释,大家又不理解的地方可以提出来,共同讨论。

 

到目前为止,还有最终要的js文件没有编写,接下来让我们开始吧:

首先,为便于理解,我将每一个方法都独立为一个Js文件。

为了将该问题简化,我将该控件的加载过程很自然的分为两个阶段(大家很自然就能想到):

1.为下拉选项卡赋值阶段

2.动态级联加载阶段,也就是select的onchange事件

其中第一阶段包含三个函数:AddProvince、SetValue和InitNextLevel

//功能:初始化省份,调用SetValue为select赋值
//作者:刘帅 liushuai@upway.cn
//时间:2012.11.29 周四
//参数说明:c->工作区div; province->省份对应的select的id; city->市对应的select的id
//          f->当前隐藏域的id; s->下一个隐藏域的id; provinceUrl->获取省份信息的路径
//          nextUrl->获取下一级数据的路径
//版本:v1.0
function AddProvince(c, province, city, f, s, provinceUrl, nextUrl) {
    //当前省份对应的select
    var sprovince = $(c + province);
    //异步加载所有省份,加载之后根据隐藏域的值为select赋值
    $.ajax(
        {
            type: "post",
            url: provinceUrl,
            datatype: "Json",
            success: function (data) {
                if (data != null) {
                    //清空残留
                    sprovince.empty();
                    //追加新的options
                    var option = $("<option>").text(" ").val("");
                    sprovince.append(option);
                    $.each(data, function (i, item) {
                        var option = $("<option>").text(item.Name).val(item.Code)
                        sprovince.append(option);
                    });
                    SetValue(c, province, city, f, s, nextUrl);
                }
            }
        });
}
//功能:初始化数据时,为select赋值,并调用InitNextLevel加载下一级
//      当没有初始值时返回,当遇到结束标志是返回
//作者:刘帅 liushuai@upway.cn
//时间:2012.11.29 周四
//参数说明:c->工作区div; fs->当前select的id; ss->下一个select的id
//          f->当前隐藏域的id; s->下一个隐藏域的id; url->获取下一级数据的路径
//版本:v1.0
function SetValue(c, fs, ss, f, s, url) {
    //隐藏域的值
    var hiddenValue = $(c + f).val();
    if (hiddenValue == 0 || hiddenValue == null || hiddenValue == 'undefined') {
        //alert("没有值!!"); 没有初始值,返回
        return;
    }
    //为select赋值
    $(c + fs).val(hiddenValue);
    //如果遇到结束标志,返回
    if (f == $(c + "end").val()) {
        return;
    }
    //初始化下一级
    InitNextLevel(c, fs, ss, f, s, url);
}
//功能:初始化省以外的select,并调用SetValue为select赋值
//作者:刘帅 liushuai@upway.cn
//时间:2012.11.29 周四
//参数说明:c->工作区div; fs->当前select的id; ss->下一个select的id
//         f->当前隐藏域的id; s->下一个隐藏域的id; url->获取下一级数据的路径
//版本:v1.0
function InitNextLevel(c, fs, ss, f, s, url) {
    //隐藏域的值,根据上一个select的值获取下级数据
    var hiddenValue = $(c + f).val();
    var nextSelect = $(c + ss);
    $.ajax({
        type: "post",
        data: { "code": hiddenValue },
        url: url,
        datatype: "Json",
        success: function (data) {
            if (data != null) {
                nextSelect.empty();
                var option = $("<option>").text(" ").val("");
                nextSelect.append(option);
                $.each(data, function (i, item) {
                    var option = $("<option>").text(item.Name).val(item.Code)
                    nextSelect.append(option);
                });
                //移动到下一级别
                fs = ss;
                ss = $(c + fs).next("select").attr("id");
                f = s;
                s = $(c + f).next("input").attr("id");
                SetValue(c, fs, ss, f, s, url);
            }
        }
    });
}

第二个阶段包含一个方法:AddNextLevel

//功能:select的onchange事件,保存已选值,加载下一级数据
//作者:刘帅 liushuai@upway.cn
//时间:2012.11.29 周四
//参数说明:c->工作区div; fs->当前select的id; ss->下一个select的id selectClass->select的class
//版本:v1.0
function AddNextLevel(c, fs, ss, url, selectClass) {
    //清除当前节点之后所有select的值
    $(c + fs).nextAll("select").each(function (i, item) {
        $(item).empty();
    });
    var selects = $(c.substr(0, c.length - 2) + selectClass);
    var ids = $(c.substr(0, c.length - 2) + " input");
    //遍历c区域中所有的select值,并赋值给隐藏域(包含两部分:id和name,需要重载)
    for (var i = 0; i < 5; i++) {
        ids[i].value = selects[i].value;
        var selectValue = $(c + selects[i].id + " option:selected").text();
        ids[i + 5].value = selectValue;
    }
    var nextSelect = $(c + ss);
    //异步加载下一级别
    $.ajax({
        type: "post",
        data: { "code": $(c + fs + " option:selected").val() },
        url: url,
        datatype: "Json",
        success: function (data) {
            if (data != null) {
                nextSelect.empty();
                var option = $("<option>").text(" ").val("");
                nextSelect.append(option);
                $.each(data, function (i, item) {
                    var option = $("<option>").text(item.Name).val(item.Code)
                    nextSelect.append(option);
                });
            }
        }
    });
}

F5调试:

更改第一个省份之后:

修改第二个的所有值:

生成的html代码:

<!DOCTYPE html>
<html>
<head>
    <title>测试地区的级联加载</title>
    <link href="/Content/Site.css" rel="stylesheet" type="text/css" />
    <script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
</head>

<body>
        <script src="http://www.cnblogs.com/Scripts/InitNextLevle.js" type="text/javascript"></script>
    <script src="http://www.cnblogs.com/Scripts/AddNextLevel.js" type="text/javascript"></script>
    <script src="http://www.cnblogs.com/Scripts/SetValue.js" type="text/javascript"></script>
    <script src="http://www.cnblogs.com/Scripts/AddProvince.js" type="text/javascript"></script>
<form action="/Home/Save" method="post">
    <div id="Sjih-div">
            <input type="hidden" id="pro-id" name="pro.id" value="650000000000" />
            <input type="hidden" id="cit-id" name="cit.id" value="650100000000" />
            <input type="hidden" id="cou-id" name="cou.id" value="650102000000" />
            <input type="hidden" id="tow-id" name="tow.id" value="650102002000" />
            <input type="hidden" id="vil-id" name="vil.id" value="650102002002" />
            <input type="hidden" id="pro-name" name="pro.name" value="新疆维吾尔自治区" />
            <input type="hidden" id="cit-name" name="cit.name" value="乌鲁木齐市" />
            <input type="hidden" id="cou-name" name="cou.name" value="天山区" />
            <input type="hidden" id="tow-name" name="tow.name" value="燕儿窝街道" />
            <input type="hidden" id="vil-name" name="vil.name" value="燕儿窝南社区居委会" />
            <input type="hidden" id="end" value="pro-name" />
            <select id="Spring-province" name="Spring-province" class="Spring-select" onchange="AddNextLevel('#' + 'Sjih-div #','Spring-province','Spring-city','/Home/GetNextLevel',' .Spring-select')">
            </select>
            <select id="Spring-city" name="Spring-city" class="Spring-select" onchange="AddNextLevel('#' + 'Sjih-div #','Spring-city','Spring-country','/Home/GetNextLevel',' .Spring-select')">
            </select>
            <select id="Spring-country" name="Spring-country" class="Spring-select" onchange="AddNextLevel('#' + 'Sjih-div #','Spring-country','Spring-town','/Home/GetNextLevel',' .Spring-select')">
            </select>
            <select id="Spring-town" name="Spring-town" class="Spring-select" onchange="AddNextLevel('#' + 'Sjih-div #','Spring-town','Spring-village','/Home/GetNextLevel',' .Spring-select')">
            </select>
            <select id="Spring-village" name="Spring-village" class="Spring-select" onchange="AddNextLevel('#' + 'Sjih-div #','Spring-village','','',' .Spring-select')">
            </select>
            <script type="text/javascript">
                //触发加载省份信息
                AddProvince("#" + "Sjih-div #", "Spring-province", "Spring-city", "pro-id", "cit-id", '/Home/GetProvinces', '/Home/GetNextLevel');
            </script>
    </div>

    <div id="Rwpe-div">
            <input type="hidden" id="pro-id" name="pro.id" value="650000000000" />
            <input type="hidden" id="cit-id" name="cit.id" value="650100000000" />
            <input type="hidden" id="cou-id" name="cou.id" value="650102000000" />
            <input type="hidden" id="tow-id" name="tow.id" value="650102002000" />
            <input type="hidden" id="vil-id" name="vil.id" value="650102002002" />
            <input type="hidden" id="pro-name" name="pro.name" value="新疆维吾尔自治区" />
            <input type="hidden" id="cit-name" name="cit.name" value="乌鲁木齐市" />
            <input type="hidden" id="cou-name" name="cou.name" value="天山区" />
            <input type="hidden" id="tow-name" name="tow.name" value="燕儿窝街道" />
            <input type="hidden" id="vil-name" name="vil.name" value="燕儿窝南社区居委会" />
            <input type="hidden" id="end" value="pro-name" />
            <select id="Spring-province" name="Spring-province" class="Spring-select" onchange="AddNextLevel('#' + 'Rwpe-div #','Spring-province','Spring-city','/Home/GetNextLevel',' .Spring-select')">
            </select>
            <select id="Spring-city" name="Spring-city" class="Spring-select" onchange="AddNextLevel('#' + 'Rwpe-div #','Spring-city','Spring-country','/Home/GetNextLevel',' .Spring-select')">
            </select>
            <select id="Spring-country" name="Spring-country" class="Spring-select" onchange="AddNextLevel('#' + 'Rwpe-div #','Spring-country','Spring-town','/Home/GetNextLevel',' .Spring-select')">
            </select>
            <select id="Spring-town" name="Spring-town" class="Spring-select" onchange="AddNextLevel('#' + 'Rwpe-div #','Spring-town','Spring-village','/Home/GetNextLevel',' .Spring-select')">
            </select>
            <select id="Spring-village" name="Spring-village" class="Spring-select" onchange="AddNextLevel('#' + 'Rwpe-div #','Spring-village','','',' .Spring-select')">
            </select>
            <script type="text/javascript">
                //触发加载省份信息
                AddProvince("#" + "Rwpe-div #", "Spring-province", "Spring-city", "pro-id", "cit-id", '/Home/GetProvinces', '/Home/GetNextLevel');
            </script>
    </div>
</form>
</body>
</html>

到这里,我已经把所有的文件都分享出来了,希望大家提出其中的bug和修改办法,共同学习进步!

期待大家的评论,顺便可以加关注!呵呵呵

posted @ 2012-11-30 10:26  xiaobudian8493  阅读(2115)  评论(16编辑  收藏  举报