BootStrap实现树形目录组件代码详解_javascript技巧

需求描述

产品添加页面,需要选择车型。在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_"><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="">';
 }
 } 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 -;
 }
 else {
 return ;
 }
 }
 }
 // 保存事件
 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: }, );
 });
 }
 // 统计带价格的返回数据
 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 levelName;

 // 遍历4层
 $('#cb_').children().children('li').children('input:checkbox').each(function (i) {
 if ($(this).is(':checked')) {
 flag = true;
 } else {
 flag = false;
 }
 $(this).parent().children().children('li').children('input:checkbox').each(function (i) {
 if ($(this).is(':checked')) {
 flag = false;
 flag = true;
 } else {
 flag = 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 (flag) {
 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 + ' ' + levelName + ' ' + 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实现树形目录组件代码详解的相关知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索bootstrap树形目录
bootstrap树形组件
vue树形组件、react 树形组件、树形组件、js 树形组件、bootstrap 树形菜单,以便于您获取更多的相关知识。

时间: 2024-10-02 09:58:48

BootStrap实现树形目录组件代码详解_javascript技巧的相关文章

Bootstrap Fileinput文件上传组件用法详解_javascript技巧

一.效果展示 1.原始的input type='file',简直不忍直视. 2.不做任何装饰的bootstrap fileinput:(bootstrap fileinput初级进化) 3.bootstrap fileinput高级进化:中文化.可拖拽上传.文件扩展名校验(如果不是需要的文件,不让上传) 拖拽上传 上传中 4.bootstrap fileinput究极进化:允许同时多线程上传多个文件. 上传中 上传完成后 二.代码示例 怎么样?效果如何?不要急,我们一步一步来实现以上的效果. 1

Bootstrap表格和栅格分页实例详解_javascript技巧

拼接table请将以下代码直接运行:换下 bootstrap.css jquery-1.12.3.min.js bootstrap-paginator.min.js" <!DOCTYPE html> <html> <head lang="zh-cn"> <title>产品列表</title> <meta charset="utf-" /> <meta http-equiv=&qu

JavaScript知识点总结(十六)之Javascript闭包(Closure)代码详解_javascript技巧

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.很早就接触过闭包这个概念了,但是一直糊里糊涂的,没有能够弄明白JavaScript的闭包到底是什么,有什么用,今天在网上看到了一篇讲JavaScript闭包的文章(原文链接),讲得非常好,这下算是彻底明白了JavaScript的闭包到底是个神马东东以及闭包的用途了,在此写出来和大家分享一下,希望不理解JavaScript闭包的朋友们看了之后能够理解闭包!以下内容大部分是来自原文,我在原文的基础

表单验证正则表达式实例代码详解_javascript技巧

表单验证正则表达式具体内容如下所示: 首先给大家解释一些符号相关的意义      1.  /^$/ 这个是个通用的格式.          ^ 匹配输入字符串的开始位置:$匹配输入字符串的结束位置      2. 里面输入需要实现的功能.         * 匹配前面的子表达式零次或多次:        + 匹配前面的子表达式一次或多次:        ?匹配前面的子表达式零次或一次:        \d  匹配一个数字字符,等价于[0-9] 下面通过一段代码给大家分析表单验证正则表达式,具体代

JavaScript操作class和style样式代码详解_javascript技巧

废话不多说了,直接给大家贴js代码了,具体代码如下所示: <!doctype html> <html> <head> <meta charset="utf-"> <title>无标题文档</title> <style> .fontSize { font-size:px; } .fontWeight { font-weight:bold; } </style> </head> &l

webpack+vue.js实现组件化详解_javascript技巧

简介 在vue中实现组件化用到了vue特有的文件格式.vue,在每一个.vue文件就是一个组件,在组件中我们将html,css,js全部写入,然后在webpack中配置vue-loader就可以了. 建立vue组件 在src目录下建立components文件夹,并在其中建立app.vue文件,这样我们项目的目录结构如下: |--dist //webpack打包后生成的文件夹 | |--build.js |--node_modules //项目的依赖所在的文件夹 |--src //文件入口 | |

Webwork 实现文件上传下载代码详解_javascript技巧

本文主要从三个方面给大家介绍webwork文件上传下载知识,包括以下三个方面: 1. 包装 Request 请求 2. 获取文件上传的解析类 3. 项目实战配置和使用 Web上传和下载应该是很普遍的一个需求,无论是小型网站还是大并发访问的交易网站.WebWork 当然也提供了很友好的拦截器来实现对文件的上传,让我们可以专注与业务逻辑的设计和实现,在实现上传和下载时顺便关注了下框架上传下载的实现. 1. 包装 Request 请求 •每次客户端请求 Action 时,都会调用 WebWork 调度

Bootstrap Paginator分页插件使用方法详解_javascript技巧

最近做的asp.netMVC项目中需要对数据列表进行分类,这个本来就是基于bootstrap开发的后台,因此也就想着bootstrap是否有分页插件呢,或者说是基于jquery支持的分页功能,这样整体的网站后台风格便能够统一,又不用自己去写一套分页的功能. 首先便是要下载Bootstrap Paginator了,下载地址:Bootstrap Paginator分页插件 首先视图的上面应该需要引入js和css文件,主要有三个文件,分别是bootstrap的css,jquery以及Paginator

利用google提供的API(JavaScript接口)获取网站访问者IP地理位置的代码详解_javascript技巧

首先引入JavaScript API文件 <script type="text/javascript" src="http://j.maxmind.com/app/geoip.js"></script> 此API提供的接口共有6个,geoip_country_code(){国家代码},geoip_country_ name(){国家名称},geoip_city() {城市名称},geoip_region(){地区代码},geoip_latit