(纯静态)js有限级级联下拉框

本代码纯属个人js练手,写着写着,顺便整理。(望哥们姐们手下留砖)

/**
 * N级联动v2.0
 *
 * @说明: 使用json数据格式,生成N级下拉框联运,
 *        在初始化联动前,可灵活设置json数据中相对应的id\text\value\parent以及topParent
 *
 * @author: tips
 * @date: 2009-09-07
 * @lastupdate: 2010-04-14
 * @调用: SelectN(数组, '下拉框id1', '下拉框id2', ...'第N个..ID');
 * @注意: 级数N<=254
 *       setProperties只能在其它初始化级联效果之前运行,否则将有可能出现异常
 *
 *       数据格式为: [{id:'cn', text:'中国', parent:'-'}, ...]
 *
 *       若需要设定其它键为id\text\parent,则使用SelectN.setProperties(json);
 *       例:SelectN.setProperties({idKey: 'ucode', textKey:'uname', textKey:'uname', parentKey:'fatherCode'});
 *           此时解析的数据格式将发生变化:[{ucode: 'aaa', uname: 'bbb', fatherCode:'xxx'}]
 *
 */
;(function() {

    var myData;
    var topParent='-';
    var idKey='id', textKey='text', valueKey=idKey, parentKey='parent';

    var SelectN = window.SelectN = function(data) {
        myData = data;
        var ids = [].slice.call(arguments, 1);//下拉框级数的ID,按级数顺序存入数组selectN

        //length-1 => 最后一个下拉框不添加onchange
        for(var i=0, len=ids.length-1; i<len; i++){
            var o = $(ids[i]);
            addEventHandler(o, 'change', (function() {
                var self=o, index=i+1;
                return function() {
                    showChild(self, ids, index);
                }
            })());
        }

        showChild(null, ids, 0);

        return SelectN;
    }
    /**
     * 指定data中的哪一项代表相应的id、text、value、parent等
     *
     * 设置属性,该方法必须在SelectN所有其它初始化方法之前调用!
     * @param Object opt 配置参数
     *        topParent - 代表顶级节点的值,默认为"-"
     *        idKey - 代表id的键名,默认为"id"
     *        textKey - 代表下拉框text的键名,默认为"text"
     *        valueKey - 代表下拉框value的键名,默认使用idKey
     *        parentKey - 代表parent的键名,默认为"parent"
     */
    SelectN.setProperties = function(opt) {
        topParent = opt.topParent || topParent;
        idKey = opt.idKey || idKey;
        textKey = opt.textKey || textKey;
        valueKey = opt.valueKey || idKey;
        parentKey = opt.parentKey || parentKey;

        return SelectN;
    }

    /**
     * 显示子级下拉框
     * @param Object(Select) oSelect 当前change的下拉框DOM
     * @param Array ids 联动的下拉框ID数组
     * @param int index 当前下拉框的下一级索引
     */
    function showChild(oSelect, ids, index) {
        var p = null == oSelect ? topParent : oSelect.options[oSelect.selectedIndex].xid;
        var ds = getChilds(p);
        clearSelect(ids, index);
        var child = $(ids[index]);
        for(var i=0,len=ds.length; i<len; i++){
            var currentObj = ds[i];
            //child.options[child.length] = new Option(ds[i].text, ds[i].text);
            var currentOpt = child.options[child.length] = new Option(currentObj[textKey], currentObj[valueKey]);
            //child.options[child.length-1].xid=ds[i].id;
            currentOpt.xid=currentObj[idKey];
            currentOpt.ownerObj = currentObj;
        }
    }

    /**
     * 获得子级数据
     * @param String p 父级代号
     * @return Array childs
     */
    function getChilds(p) {
        var childs = [];
        for(var i=0, len=myData.length; i<len; i++){
            //if(p == myData[i].parent)
            if(p == myData[i][parentKey]){
                childs.push(myData[i]);
            }
        }
        return childs;
    }
    /**
     * 清除所有子级下拉框
     * @param Array ids 联动的下拉框ID数组
     * @param int index 当前下拉框的下一级索引
     */
    function clearSelect(ids, index) {
        for(var i=index, len=ids.length; i<len; i++){
            $(ids[i]).length=1;
        }
    }
    function $(sid) {
        return document.getElementById(sid);
    }
    //为对象obj追加事件 -- 兼容IE与FF
    function addEventHandler(oTarget, sEventType, fnHandler) {
        if (oTarget.addEventListener) {
            oTarget.addEventListener(sEventType, fnHandler, false);
        } else if (oTarget.attachEvent) {
            oTarget.attachEvent("on" + sEventType, fnHandler);
        } else {
            oTarget["on" + sEventType] = fnHandler;
        }
    };
})();


下面是demo(附带几行测试用的数据):
    var data = [];

    data.push({id:'cn', text:'中国', parent:'-'});

    data.push({id:'fj', text:'福建', parent:'cn'});
    data.push({id:'gd', text:'广东', parent:'cn'});

    data.push({id:'fz', text:'福州', parent:'fj'});
    data.push({id:'xm', text:'厦门', parent:'fj'});
    data.push({id:'ly', text:'龙岩', parent:'fj'});

    data.push({id:'fz-fq', text:'福州1', parent:'fz'});
    data.push({id:'fz-mh', text:'福州2', parent:'fz'});
    data.push({id:'fz-cl', text:'福州3', parent:'fz'});

    data.push({id:'xm-dn', text:'厦门1', parent:'xm'});
    data.push({id:'xm-jm', text:'厦门2', parent:'xm'});
    data.push({id:'xm-xl', text:'厦门3', parent:'xm'});

    data.push({id:'yl-xl', text:'龙岩1', parent:'ly'});
    data.push({id:'yl-lc', text:'龙岩2', parent:'ly'});
    data.push({id:'yl-sh', text:'龙岩3', parent:'ly'});
    data.push({id:'yl-wp', text:'龙岩4', parent:'ly'});

    data.push({id:'gz', text:'广州', parent:'gd'});
    data.push({id:'sz', text:'深圳', parent:'gd'});
    data.push({id:'mx', text:'梅县', parent:'gd'});

    data.push({id:'gz-fq', text:'广州1', parent:'gz'});
    data.push({id:'gz-mh', text:'广州2', parent:'gz'});
    data.push({id:'gz-cl', text:'广州3', parent:'gz'});

    data.push({id:'sz-dn', text:'深圳1', parent:'sz'});
    data.push({id:'sz-jm', text:'深圳2', parent:'sz'});
    data.push({id:'sz-xl', text:'深圳3', parent:'sz'});

    data.push({id:'mx-xl', text:'梅县1', parent:'mx'});
    data.push({id:'mx-lc', text:'梅县2', parent:'mx'});
    data.push({id:'mx-sh', text:'梅县3', parent:'mx'});
    data.push({id:'mx-wp', text:'梅县4', parent:'mx'});

    data.push({id:'am', text:'美国', parent:'-'});

    data.push({id:'ny', text:'纽约', parent:'am'});
    data.push({id:'hsd', text:'华盛顿', parent:'am'});

//在onload后执行
window.onload = function() {
    /*
    SelectN.setProperties({
        topParent:'gd',  //设置顶级节点的parent值
         idKey:'ucode',   //指定data中的哪一项代表id
        textKey:'text',  //指定data中的哪一项代表下拉框中的text
        valueKey:'text', //指定data中的哪一项代表下拉框中的value
        parentKey:'parent' //指定data中的哪一项代表parent
    })(data, 'p1', 'p2', 'p3', 'p4');

    */
    SelectN.setProperties({valueKey:'text'}); //重新设定各属性的键值
    SelectN(data, 'p1', 'p2', 'p3', 'p4'); //初始化级联关系
}


下面是html相关的代码:
<body>
    <select id="p1"><option>-选择-</option></select><br/>
    <select id="p2"><option>-选择-</option></select><br/>
    <select id="p3"><option>-选择-</option></select><br/>
    <select id="p4"><option>-选择-</option></select>
</body>


把上面三段代码放到一起,就能看见效果了。

等哪天突然心血来潮了,再重构一下,加上Ajax动态级联功能

你可能感兴趣的:(json,Ajax)