bootStrap树形目录组件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bootStrap树形目录组件相关的知识,希望对你有一定的参考价值。

需求描述

产品添加页面,需要选择车型。在bootStrap的modal上弹出子modal来使用。
车型一共有4级目录。要使用目录树。
然后分活动和商品两种,需要能够通过不通参数来调用该组件。
车型品牌要使用字母导航。

技术分享

 

技术实现

数据都是后端传json过来,我们ajax获取然后操作。
由于车型总数据有几万条以上,不可能一次性请求过来。这里我们使用异步的方式,每点击一次目录节点,加载它的下一级。
这里我们用两个参数来控制活动和商品的不同加载。_showPrice和opened
后端传过来的第一级数据是车型品牌,其中有首字母的字段。字母导航的初始化,就是把这个数据用firstWord属性来排序,然后忽略掉其他首字母相同的元素。
对于活动类型,需要返回所勾选的最低一级的数据。(勾选奥迪和奥迪A6,则只返回A6的意思),这里用了整整4层循环。不过它是根据是否有checked来遍历的,速度不慢。

 

/**
 * Created by nuenfeng on 2016/5/23.
 * 车型选择组件
 * 参数:
 * showPrice 是否要输入价格(不输入价格的从品牌开始就有选项框,没有全选功能)
 * params 外部传入的对象
 * callback 回调函数
 */
(function () {
    var uriCarBrand = global.url.carBrandList;
    //var uri = uriCarBrand.url;
    var opened = false; //当前页面是否打开过本组件
    var _callback;      //回调函数
    var requestParams;  //请求时要使用的参数
    var _showPrice;     //是否要输入价格
    var lastShowPrice;  //前一次打开状态
    var charNavArr;     //字母导航数组

    function CarTree(showPrice, params, callback) {
        // 没打开过,初始化; 打开过,直接显示modal
        requestParams = params;
        _showPrice = showPrice;
        _callback = callback;

        if (!opened || lastShowPrice != showPrice) {
            this.init();
            opened = true;
            lastShowPrice = showPrice;
        } else {
            $(‘#zc-sub-modal‘).modal(‘show‘);
        }
    }

    CarTree.prototype.init = function () {

        msjcTools.addSubModal();
        //设置大模态框
        $(‘#zc-sub-modal‘).addClass("bs-example-modal-lg");
        $(‘#zc-sub-modal .modal-dialog‘).addClass("modal-lg");

        var str = ‘<form id="info-form" data-parsley-validate class="form-horizontal form-label-left">‘;
        str += ‘<ul id="resourceId" class="treeview-gray">‘
        str += ‘<li id="cb_0"><span>汽车品牌选择</span>‘;
        str += "</li>"
        str += ‘</ul>‘
        str += ‘</form>‘;

        var objId = ‘cb_0‘;
        var carBrandId = 0;
        loadSubMenu(objId, carBrandId, 1);  //1 表示第一次加载,用于加载成功后判断时候要初始化字母导航

        $(‘#zc-sub-modal-body‘).html(str);
        $(‘#zc-sub-modal‘).modal({
            keyboard: false,
            show: true
        });

        // 点击保存事件
        $(‘#zc-sub-modal .modal-footer .btn.btn-primary‘).unbind().bind("click", function () {
            save();
        });


        //$("#resourceId").find("input[type=checkbox]").unbind().bind("click",function(){
        //    if($(this).is(‘:checked‘)==true){//选中 则其上层节点全部展开并选中
        //        //上级选中
        //        $(this).parents("li").each(function(){
        //            $(this).find("input[type=checkbox]:first").attr("checked",true)
        //        });
        //    } else {
        //        //下级取消选中
        //        $(this).siblings("ul").find("input[type=checkbox]").each(function(){
        //            $(this).removeAttr("checked");
        //        });
        //    }
        //});


        //隐藏子窗口后 保持父窗口的滚动
        $("#zc-sub-modal").on("hidden.bs.modal", function () {
            $(‘body‘).addClass(‘modal-open‘)
        });
    }

    CarTree.prototype.empty = function () {
        opened = false;
        console.log(‘empty me‘);
    }

    //加载子菜单
    var loadSubMenu = function (objId, carBrandId, times) {

        requestParams.brandId = carBrandId;
        executeAjax(global.url.carBrandList, requestParams, function (data) {
            // 给data风骚地排个序
            data.sort(keysrt("firstWord"));

            var menuHtml = "<ul>";
            for (var index in data) {
                var menu = data[index];
                menuHtml += ‘<li id="cb_‘ + menu.carBrandId + ‘" value="‘ + menu.carBrandId + ‘" brand="‘ + menu.brand + ‘">‘;

                // 带价格的树
                if (_showPrice) {
                    // 最后一级,添加选项框
                    if (menu.level > 3) {
                        menuHtml += ‘<input type="checkbox" name="resourceIds" value="‘ + menu.carBrandId + ‘" />‘;
                    }
                    menuHtml += ‘<span>‘ + menu.name + ‘</span>‘;

                    // 最后一级,添加输入框
                    if (menu.level == 4) {
                        menuHtml += ‘<input type="text" maxlength="9">‘;
                    }
                } else { // 不带价格的树
                    menuHtml += ‘<input type="checkbox" name="resourceIds" value="‘ + menu.carBrandId + ‘" />‘;
                    menuHtml += ‘<span>‘ + menu.name + ‘</span>‘;
                }

                menuHtml += "</li>";
            }
            menuHtml += "</ul>";
            $(‘#‘ + objId).append(menuHtml);
            $(‘#‘ + objId).attr(‘data-load‘, ‘loaded‘);

            //汽车类型第一级加载完成后,初始化字符导航
            charNavArr = [];
            var fwdLast = ‘‘;    //上一次的首字母

            for (var i in data) {
                var cobjTemp = {};
                if (fwdLast != data[i].firstWord) {
                    fwdLast = data[i].firstWord;
                    cobjTemp.firstWord = fwdLast;
                    cobjTemp.targetId = ‘cb_‘+data[i].carBrandId;
                    charNavArr.push(cobjTemp);
                }
            }
            if (times == 1) {
                initCharNav();
                // 点击保存事件
                $(‘.charNavSaveBtn‘).unbind().bind("click", function () {
                    save();
                });
            }
        });

    }

    // 此处是风骚的数组对象排序
    var keysrt = function (propertyName) {
        return function (object1, object2) {
            var value1 = object1[propertyName];
            var value2 = object2[propertyName];
            if (value2 < value1) {
                return 1;
            }
            else if (value2 > value1) {
                return -1;
            }
            else {
                return 0;
            }
        }
    }

    // 保存事件
    var save = function(){
        // 确认后,执行回调函数
        if (_showPrice) {
            var res = getPriceResult();
            if (res.status) {
                _callback(res.data);
            } else {
                alert(res.error);
                return;
            }
        } else {
            _callback(getNopriceResult());
        }
        //返回数据,然后隐藏
        $(‘#zc-sub-modal‘).modal(‘hide‘);
    }

    // 设置字符导航初始化
    var initCharNav = function () {
        var charNavHtml = ‘<ul id="charNavBar" class="charNavBar pagination">‘;
        for (var i in charNavArr) {
            charNavHtml += ‘<li><a href="#‘+charNavArr[i].targetId+‘">‘+charNavArr[i].firstWord+‘</a></li>‘;
        }
        charNavHtml += ‘<li><a class="modalGoTop">↑</a></li>‘;
        charNavHtml += ‘<button type="button" class="btn btn-primary charNavSaveBtn">保存</button>‘;
        charNavHtml += ‘</ul>‘;

        $(‘#zc-sub-modal‘).append(charNavHtml);

        $(‘.modalGoTop‘).on(‘click‘, function(e){
            $(‘#zc-sub-modal‘).animate({scrollTop: 0}, 500);
        });
    }

    // 统计带价格的返回数据
    var getPriceResult = function () {
        var result = {
            status : true,
            data : [],
            error : ‘‘
        };
        var liTemp;
        var objTemp;
        $(‘.treeview-gray input:checkbox:checked‘).each(function (i) {
            liTemp = $(this).parent(‘li‘);
            objTemp = {};
            objTemp.carBrandId = liTemp.attr(‘value‘);
            objTemp.brand = liTemp.attr(‘brand‘);
            objTemp.carBrandName = liTemp.find(‘span‘).text();
            objTemp.unitPrice = liTemp.find(‘input:text‘).val();

            // 如果价格没有输入,返回保存失败,并返回没有输入的carBrandName
            if(objTemp.unitPrice == ‘‘) {
                result.status = false;
                result.error = ‘请输入 ‘ + objTemp.carBrandName + ‘ 的价格!‘;
                return result;
            }
            result.data.push(objTemp);
        });
        return result;
    }

    // 统计不带价格的返回数据
    var getNopriceResult = function () {
        var result = [];
        var liTemp;
        var objTemp;
        var flag1;
        var flag2;
        var flag3;
        var flag4;
        var level2Name;

        // 遍历4层
        $(‘#cb_0‘).children().children(‘li‘).children(‘input:checkbox‘).each(function (i1) {
            if ($(this).is(‘:checked‘)) {
                flag1 = true;
            } else {
                flag1 = false;
            }
            $(this).parent().children().children(‘li‘).children(‘input:checkbox‘).each(function (i2) {
                if ($(this).is(‘:checked‘)) {
                    flag1 = false;
                    flag2 = true;
                } else {
                    flag2 = false;
                }
                // 获取第二级的名字,给第三级使用
                liTemp = $(this).parent(‘li‘);
                level2Name = liTemp.children(‘span‘).text();
                $(this).parent().children().children(‘li‘).children(‘input:checkbox‘).each(function (i3) {
                    if ($(this).is(‘:checked‘)) {
                        flag1 = false;
                        flag2 = false;
                        flag3 = true;
                    } else {
                        flag3 = false;
                    }
                    $(this).parent().children().children(‘li‘).children(‘input:checkbox‘).each(function (i4) {
                        if ($(this).is(‘:checked‘)) {
                            flag1 = false;
                            flag2 = false;
                            flag3 = false;
                            flag4 = true;
                        } else {
                            flag4 = false;
                        }
                        if (flag4) {
                            liTemp = $(this).parent(‘li‘);
                            objTemp = {};
                            objTemp.carBrandId = liTemp.attr(‘value‘);
                            objTemp.brand = liTemp.attr(‘brand‘);
                            //objTemp.carBrandName = liTemp.children(‘span‘).text();
                            objTemp.carBrandName = objTemp.brand + ‘ ‘ + liTemp.children(‘span‘).text();
                            result.push(objTemp);
                        }
                    });
                    if (flag3) {
                        liTemp = $(this).parent(‘li‘);
                        objTemp = {};
                        objTemp.carBrandId = liTemp.attr(‘value‘);
                        objTemp.brand = liTemp.attr(‘brand‘);
                        //objTemp.carBrandName = liTemp.children(‘span‘).text();
                        objTemp.carBrandName = objTemp.brand + ‘ ‘ + level2Name + ‘ ‘ + liTemp.children(‘span‘).text();
                        result.push(objTemp);
                    }
                });
                if (flag2) {
                    //liTemp = $(this).parent(‘li‘);
                    objTemp = {};
                    objTemp.carBrandId = liTemp.attr(‘value‘);
                    objTemp.brand = liTemp.attr(‘brand‘);
                    //objTemp.carBrandName = objTemp.brand + liTemp.children(‘span‘).text();
                    objTemp.carBrandName = objTemp.brand + ‘ ‘ + liTemp.children(‘span‘).text();
                    result.push(objTemp);
                }
            });
            if (flag1) {
                liTemp = $(this).parent(‘li‘);
                objTemp = {};
                objTemp.carBrandId = liTemp.attr(‘value‘);
                objTemp.brand = liTemp.attr(‘brand‘);
                objTemp.carBrandName = liTemp.children(‘span‘).text();
                result.push(objTemp);
            }
        });

        return result;
    }


    // 给目录树绑定点击事件
    $(document).on(‘click‘, ‘#resourceId li‘, function (e) {


        e.stopPropagation();

        if ($(this).attr(‘open‘)) {
            $(this).removeAttr(‘open‘);
            $(this).children(‘ul‘).hide();
        } else {
            $(this).attr(‘open‘, ‘opened‘);
            $(this).children(‘ul‘).show();
        }
        var objId = $(this).attr(‘id‘);
        var carBrandId = $(this).attr(‘value‘);
        //加载过的不执行
        if ($(this).attr(‘data-load‘)) {
            return;
        }
        loadSubMenu(objId, carBrandId);
    });

    // 点击多选框时候不下拉
    $(document).on(‘click‘, ‘input[type="checkbox"]‘, function (e) {
        e.stopPropagation();
    });

    window.CarTree = CarTree;
}());

 

调用方法:

carTree = new CarTree(false, {}, function (data) {
    console.log(data);
 });

 

以上是关于bootStrap树形目录组件的主要内容,如果未能解决你的问题,请参考以下文章

treeview-树形菜单js组件编写及应用

树形控件如何隐藏vue

EasyUI---layout布局树形组件选项卡tabs

MUI

BootStrap有用代码片段(持续总结)

Mint-UI