BootStrap實(shí)現(xiàn)樹形目錄組件代碼詳解
需求描述
產(chǎn)品添加頁(yè)面,需要選擇車型。在bootStrap的modal上彈出子modal來(lái)使用。
車型一共有4級(jí)目錄。要使用目錄樹。
然后分活動(dòng)和商品兩種,需要能夠通過(guò)不通參數(shù)來(lái)調(diào)用該組件。
車型品牌要使用字母導(dǎo)航。
技術(shù)實(shí)現(xiàn)
數(shù)據(jù)都是后端傳json過(guò)來(lái),我們ajax獲取然后操作。
由于車型總數(shù)據(jù)有幾萬(wàn)條以上,不可能一次性請(qǐng)求過(guò)來(lái)。這里我們使用異步的方式,每點(diǎn)擊一次目錄節(jié)點(diǎn),加載它的下一級(jí)。
這里我們用兩個(gè)參數(shù)來(lái)控制活動(dòng)和商品的不同加載。_showPrice和opened
后端傳過(guò)來(lái)的第一級(jí)數(shù)據(jù)是車型品牌,其中有首字母的字段。字母導(dǎo)航的初始化,就是把這個(gè)數(shù)據(jù)用firstWord屬性來(lái)排序,然后忽略掉其他首字母相同的元素。
對(duì)于活動(dòng)類型,需要返回所勾選的最低一級(jí)的數(shù)據(jù)。(勾選奧迪和奧迪A6,則只返回A6的意思),這里用了整整4層循環(huán)。不過(guò)它是根據(jù)是否有checked來(lái)遍歷的,速度不慢。
/** * Created by nuenfeng on 2016/5/23. * 車型選擇組件 * 參數(shù): * showPrice 是否要輸入價(jià)格(不輸入價(jià)格的從品牌開始就有選項(xiàng)框,沒(méi)有全選功能) * params 外部傳入的對(duì)象 * callback 回調(diào)函數(shù) */ (function () { var uriCarBrand = global.url.carBrandList; //var uri = uriCarBrand.url; var opened = false; //當(dāng)前頁(yè)面是否打開過(guò)本組件 var _callback; //回調(diào)函數(shù) var requestParams; //請(qǐng)求時(shí)要使用的參數(shù) var _showPrice; //是否要輸入價(jià)格 var lastShowPrice; //前一次打開狀態(tài) var charNavArr; //字母導(dǎo)航數(shù)組 function CarTree(showPrice, params, callback) { // 沒(méi)打開過(guò),初始化; 打開過(guò),直接顯示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(); //設(shè)置大模態(tài)框 $('#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 表示第一次加載,用于加載成功后判斷時(shí)候要初始化字母導(dǎo)航 $('#zc-sub-modal-body').html(str); $('#zc-sub-modal').modal({ keyboard: false, show: true }); // 點(diǎn)擊保存事件 $('#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){//選中 則其上層節(jié)點(diǎn)全部展開并選中 // //上級(jí)選中 // $(this).parents("li").each(function(){ // $(this).find("input[type=checkbox]:first").attr("checked",true) // }); // } else { // //下級(jí)取消選中 // $(this).siblings("ul").find("input[type=checkbox]").each(function(){ // $(this).removeAttr("checked"); // }); // } //}); //隱藏子窗口后 保持父窗口的滾動(dòng) $("#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風(fēng)騷地排個(gè)序 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 + '">'; // 帶價(jià)格的樹 if (_showPrice) { // 最后一級(jí),添加選項(xiàng)框 if (menu.level > 3) { menuHtml += '<input type="checkbox" name="resourceIds" value="' + menu.carBrandId + '" />'; } menuHtml += '<span>' + menu.name + '</span>'; // 最后一級(jí),添加輸入框 if (menu.level == 4) { menuHtml += '<input type="text" maxlength="">'; } } else { // 不帶價(jià)格的樹 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'); //汽車類型第一級(jí)加載完成后,初始化字符導(dǎo)航 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(); // 點(diǎn)擊保存事件 $('.charNavSaveBtn').unbind().bind("click", function () { save(); }); } }); } // 此處是風(fēng)騷的數(shù)組對(duì)象排序 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(){ // 確認(rèn)后,執(zhí)行回調(diào)函數(shù) if (_showPrice) { var res = getPriceResult(); if (res.status) { _callback(res.data); } else { alert(res.error); return; } } else { _callback(getNopriceResult()); } //返回?cái)?shù)據(jù),然后隱藏 $('#zc-sub-modal').modal('hide'); } // 設(shè)置字符導(dǎo)航初始化 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: }, ); }); } // 統(tǒng)計(jì)帶價(jià)格的返回?cái)?shù)據(jù) 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(); // 如果價(jià)格沒(méi)有輸入,返回保存失敗,并返回沒(méi)有輸入的carBrandName if(objTemp.unitPrice == '') { result.status = false; result.error = '請(qǐng)輸入 ' + objTemp.carBrandName + ' 的價(jià)格!'; return result; } result.data.push(objTemp); }); return result; } // 統(tǒng)計(jì)不帶價(jià)格的返回?cái)?shù)據(jù) 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; } // 獲取第二級(jí)的名字,給第三級(jí)使用 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; } // 給目錄樹綁定點(diǎn)擊事件 $(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'); //加載過(guò)的不執(zhí)行 if ($(this).attr('data-load')) { return; } loadSubMenu(objId, carBrandId); }); // 點(diǎn)擊多選框時(shí)候不下拉 $(document).on('click', 'input[type="checkbox"]', function (e) { e.stopPropagation(); }); window.CarTree = CarTree; }());
調(diào)用方法:
carTree = new CarTree(false, {}, function (data) { console.log(data); });
以上所述是小編給大家介紹的BootStrap實(shí)現(xiàn)樹形目錄組件代碼詳解的相關(guān)知識(shí),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
javascript模擬php函數(shù)in_array
就是判斷一個(gè)元素是否存在于數(shù)組中的函數(shù),既然js里string都有indexOf函數(shù),為什么不在Array對(duì)象里設(shè)置一個(gè)這樣的函數(shù)呢,其實(shí)就用indexOf這個(gè)思想挺好的,不知道制定JS標(biāo)準(zhǔn)的人是基于什么考慮,把這樣一個(gè)如此常用的功能沒(méi)考慮在內(nèi)的。2015-04-04JavaScript判斷FileUpload控件上傳文件類型
在CS后臺(tái)代碼中獲取FileUpload控件上傳文件的類型是比較容易的!那么,能否在客戶端通過(guò)JavaScript腳本判斷FileUpload上傳文件類型呢?答案是可以的,下面通過(guò)一個(gè)小例子為大家展示2015-09-09javascript打印大全(打印頁(yè)面設(shè)置/打印預(yù)覽代碼)
打印頁(yè)面設(shè)置,打印頁(yè)面預(yù)覽在打印過(guò)程中經(jīng)常會(huì)遇到,網(wǎng)上搜集整理了一些實(shí)用的打印方法與大家分享,感興趣的朋友可以了解下哈2013-03-03快速解決bootstrap下拉菜單無(wú)法隱藏的問(wèn)題
今天小編就為大家分享一篇快速解決bootstrap下拉菜單無(wú)法隱藏的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08JS?簡(jiǎn)單實(shí)現(xiàn)拖拽評(píng)星的示例代碼
本文主要介紹了JS?簡(jiǎn)單實(shí)現(xiàn)拖拽評(píng)星,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05微信小程序?qū)W習(xí)總結(jié)(四)事件與冒泡實(shí)例分析
這篇文章主要介紹了微信小程序?qū)W習(xí)總結(jié)(四)事件與冒泡,結(jié)合實(shí)例形式分析了微信小程序事件、冒泡、數(shù)據(jù)獲取相關(guān)機(jī)制、原理與操作注意事項(xiàng),需要的朋友可以參考下2020-06-06JavaScript Accessor實(shí)現(xiàn)說(shuō)明
關(guān)于Getter與Setter大家一定不會(huì)陌生,下面簡(jiǎn)單介紹幾種我所知道的在JavaScript中實(shí)現(xiàn)G/S的方法.2010-12-12JavaScript高級(jí)教程5.6之基本包裝類型(詳細(xì))
在基本類型當(dāng)中,有三種類型是我們經(jīng)常使用的:boolean,number,string,通過(guò)本篇文章給大家介紹javascript高級(jí)教程5.6之基本包裝類型,感興趣的朋友一起學(xué)習(xí)吧2015-11-11鼠標(biāo)右擊事件代碼(asp.net后臺(tái))
本程序由一個(gè)js文件和aspx文件組成,沒(méi)有后臺(tái)CS代碼。2011-01-01