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


Posted in Javascript onJune 21, 2016

需求描述

产品添加页面,需要选择车型。在bootStrap的modal上弹出子modal来使用。

车型一共有4级目录。要使用目录树。

然后分活动和商品两种,需要能够通过不通参数来调用该组件。

车型品牌要使用字母导航。

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

技术实现

数据都是后端传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实现树形目录组件代码详解的相关知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
利用jQuery的$.event.fix函数统一浏览器event事件处理
Dec 21 Javascript
jQuery EasyUI API 中文文档 可调整尺寸
Sep 29 Javascript
实用框架(iframe)操作代码
Oct 23 Javascript
JS实现向表格行添加新单元格的方法
Mar 30 Javascript
JS拖拽组件学习使用
Jan 19 Javascript
深入浅析JavaScript中的constructor
Apr 19 Javascript
使用Webpack提高Vue.js应用的方式汇总(四种)
Jul 10 Javascript
浅谈PDF.js使用心得
Jun 07 Javascript
vue+elementUI实现图片上传功能
Aug 20 Javascript
JS函数本身的作用域实例分析
Mar 16 Javascript
详细分析JavaScript中的深浅拷贝
Sep 17 Javascript
vue 递归组件的简单使用示例
Jan 14 Vue.js
jQuery实现的跨容器无缝拖动效果代码
Jun 21 #Javascript
解决微信浏览器Javascript无法使用window.location.reload()刷新页面
Jun 21 #Javascript
JS基于构造函数实现的菜单滑动显隐效果【测试可用】
Jun 21 #Javascript
Bootstrap中的表单验证插件bootstrapValidator使用方法整理(推荐)
Jun 21 #Javascript
关于JS中setTimeout()无法调用带参函数问题的解决方法
Jun 21 #Javascript
原生JS封装ajax 传json,str,excel文件上传提交表单(推荐)
Jun 21 #Javascript
jQuery动态添加可拖动元素完整实例(附demo源码下载)
Jun 21 #Javascript
You might like
解析获取优酷视频真实下载地址的PHP源代码
2013/06/26 PHP
php使用ob_flush不能每隔一秒输出原理分析
2015/06/02 PHP
在Mac OS下搭建LNMP开发环境的步骤详解
2017/03/10 PHP
php使用QueryList轻松采集js动态渲染页面方法
2018/09/11 PHP
php源码的安装方法和实例
2019/09/26 PHP
jquery的index方法实现tab效果
2011/02/16 Javascript
基于jquery的loading 加载提示效果实现代码
2011/09/01 Javascript
JavaScript闭包 懂不懂由你反正我是懂了
2011/10/21 Javascript
利用jq让你的div居中的好方法分享
2013/11/21 Javascript
浅析jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法
2014/01/10 Javascript
toggle()隐藏问题的解决方法
2014/02/17 Javascript
浅谈Javascript中深复制
2014/12/01 Javascript
深入理解JavaScript系列(30):设计模式之外观模式详解
2015/03/03 Javascript
js实现简单的联动菜单效果
2015/08/19 Javascript
AngularJS 实现按需异步加载实例代码
2015/10/18 Javascript
jquery动画效果学习笔记(8种效果)
2015/11/13 Javascript
jQuery自动完成插件completer附源码下载
2016/01/04 Javascript
js简单实现调整网页字体大小的方法
2016/07/23 Javascript
AngularJS操作键值对象类似java的hashmap(填坑小结)
2016/11/12 Javascript
jQuery插件DataTable使用方法详解(.Net平台)
2016/12/22 Javascript
原生js实现返回顶部缓冲效果
2017/01/18 Javascript
javascript基础进阶_深入剖析执行环境及作用域链
2017/09/05 Javascript
使用Vuex实现一个笔记应用的方法
2018/03/13 Javascript
解决vue-cli项目打包出现空白页和路径错误的问题
2018/09/04 Javascript
jQuery事件多次绑定与解绑问题实例分析
2019/02/19 jQuery
jQuery实现验证用户登录
2019/12/10 jQuery
javascript 数组(list)添加/删除的实现
2020/12/17 Javascript
200 行python 代码实现 2048 游戏
2018/01/12 Python
python随机模块random的22种函数(小结)
2020/05/15 Python
python打包多类型文件的操作方法
2020/09/21 Python
Python导入父文件夹中模块并读取当前文件夹内的资源
2020/11/19 Python
意大利奢华内衣制造商:Cosabella
2017/08/29 全球购物
PHP两种查询函数array/row的区别
2013/06/03 面试题
党员实事承诺书
2014/03/26 职场文书
离婚协议书怎么写
2014/09/12 职场文书
2014客服代表实习自我鉴定
2014/09/18 职场文书