distpicker插件使用自定义数据

来源:互联网 发布:java关键字有多少个 编辑:程序博客网 时间:2024/05/21 05:59

前段时间主管给我来了这样一个需求,写个省市区三级联动下拉框插件,要求能自定义数据,后台给的数据格式如下:

var areadata = [{            "id": "0",            "sort": 1,            "abbrName": '湖南省',            "abbrName1": '湖南省1',            "abbrName2": '湖南省2'        }, {            "pId": "0",            "sort": 1,            "id": "1124436",            "abbrName": '长沙市',            "abbrName1": '长沙1',            "abbrName2": '长沙2'        }, {            "pId": "0",            "sort": 2,            "id": "354346756",            "abbrName": '常德市',            "abbrName1": '常德1',            "abbrName2": '常德2'        }, {            "pId": "1124436",            "sort": 2,            "id": "21231241",            "abbrName": '芙蓉区',            "abbrName1": '芙蓉区1',            "abbrName2": '芙蓉区2'        }, {            "pId": "1124436",            "sort": 1,            "id": "115345234",            "abbrName": '天心区',            "abbrName1": '天心区1',            "abbrName2": '天心区2'        }, {            "pId": "354346756",            "sort": 1,            "id": "789564",            "abbrName": '武陵区',            "abbrName1": '武陵区1',            "abbrName2": '武陵区2'        }, {            "pId": "354346756",            "sort": 1,            "id": "4365892",            "abbrName": '鼎城区',            "abbrName1": '鼎城区1',            "abbrName2": '鼎城区2'        }];

1、其中id我随便写的,实际上是很长的一串数字,然后我需要在解析成json前转成字符串;

2、pId就是父级id,祖先无pId;

3、要根据sort值顺序显示,比如上面数据长沙市sort值为1,常德市为2,那长沙市就排在在常德市前面;

4、abbrName,默认使用key,但是要支持任意组合,比如 湖南省(abbrName)-长沙2(abbrName2)-天心区1(abbrName1) 这样;

实际上我很不明白为什么要有这样的需求欸,明明很多东西没必要搞的这么麻烦,但是没办法,层级压力啊。

公司项目用的是古老的MVC模式,后端渲染,我这边就是jq+bt然后一大堆的插件(主管要求),requirejs处理依赖,如果说全自己写,怎么说也不符合主管的思想,所以就只能想办法在现有插件上修改了,并且很多插件都是经过了多次迭代可以稳定使用,不会增加多余的维护成本。

ok,修改插件当然是在不影响原功能的基础上去改,首先看看distpicker默认的数据结构:

var ChineseDistricts = {    86: {      110000: '北京市',      ...    },    110000: {      110100: '北京市市辖区'    },    110100: {      110101: '东城区',      ...    },

然后源码中有一段:

code = (    type === PROVINCE ? 86 :    type === CIRY ? this.$province && this.$province.find(':selected').data('code') :    type === DISTRICT ? this.$city && this.$city.find(':selected').data('code') : code);

除了这个86外,其他的key只要父子对应好就OK了,所以我的数据需要转换成这样:

{    "86": {        "0": "湖南省"    },    "0": {        "1124436": "长沙市",        "354346756": "常德市"    },    "1124436": {        "21231241": "芙蓉区",        "115345234": "天心区"    },    "354346756": {        "789564": "武陵区",        "4365892": "鼎城区"    }}

但是这个数据用在distpicker中似乎没法保证排序,也拿不到排序的数据,想到可以把数据转成如下的样子,然后在distpicker源码中去排序,多加的字符随意处理,只要不和数据冲突就行了:

{    "86": {        "0": "湖南省sort(1)"    },    "0": {        "1124436": "长沙市sort(1)",        "354346756": "常德市sort(2)"    },    "1124436": {        "21231241": "芙蓉区sort(2)",        "115345234": "天心区sort(1)"    },    "354346756": {        "789564": "武陵区sort(1)",        "4365892": "鼎城区sort(1)"    }}

下面是转换数据具体代码,返回格式如上:

var distpickerDataFormat = function(cachename, options) {    var pid = options.pid || 'pId',        id = options.id || 'id',        keys = options.keys || ['abbrName', 'abbrName', 'abbrName'];    // 对数据格式化,并通过指定cachename缓存    distpickerDataFormat[cachename] = distpickerDataFormat[cachename] || function() {        var json = {},            parent = {};        options.data.forEach(function(o, i) {            if (!o[pid]) {                parent[o[id]] = o;                return;            }            json[o[pid]] = json[o[pid]] || {};            json[o[pid]][o[id]] = o;        });        // 一级数据        json["86"] = parent;        // 因为要支持使用不同属性组合数据,增加一个_level值(0,1,2),keys[_level]获取当前级别指定的属性名        sort('86', json, 0);        return json;    }();    // 将数据替换成指定key值并返回    return function() {        var json = {},            data = distpickerDataFormat[cachename];        for(var k in data) {            var level = data[k]._level;            json[k] = {};            for(var i in data[k]) {                if(i !== '_level') {                    json[k][i] = data[k][i][keys[level]] + 'sort('+ data[k][i].sort +')';                }            }        }        return {data:json};    }();    // 递归增加级别_level,    function sort(n, data, i) {        if(!data[n]) {            return false;        }        data[n]._level = i;        i++;        $.each(data[n], function(k) {            sort(k, data, i);        })    }}

接下来就是改源码了,插件本身使用的数据是ChineseDistricts,这里不去覆盖他,改动如下:

// data为新增项,这样可以通过外部配置Distpicker.DEFAULTS = {    autoSelect: true,    placeholder: true,    province: '—— 省 ——',    city: '—— 市 ——',    district: '—— 区 ——',    data: ChineseDistricts};/*code = (    type === PROVINCE ? 86 :    type === CIRY ? this.$province && this.$province.find(':selected').data('code') :    type === DISTRICT ? this.$city && this.$city.find(':selected').data('code') : code);后面修改*/// 修改options.ChineseDistrictsdistricts = $.isNumeric(code) ? options.data[code] : null;// 增加sort属性if ($.isPlainObject(districts)) {    $.each(districts, function(code, address) {        var selected = address === value,            adr = address.replace(/sort\((\d+)\)/g, ''),            sort = +RegExp.$1;        if (selected) {            matched = true;        }        data.push({            code: code,            address: adr,            selected: selected,            sort: sort        });    });}// 排序data.sort(function(a, b) {    return a.sort - b.sort;})

接下来就可以这样调用:

// 转换数据var data = gm.distpickerDataFormat('cachename', {        data: areadata,        pid: 'pId',        id: 'id',        keys: ['abbrName', 'abbrName1', 'abbrName']    })// 初始化$('...').distpicker(data);

如果不需要ChineseDistricts,可以在兼容CommonJS, AMD, CMD处去掉,抛错也去掉。

原创粉丝点击