JSON 無限摺疊選單
阿新 • • 發佈:2019-01-13
最近看了一篇關於JSON無限摺疊選單的文章 感覺寫的不錯,也研究了下程式碼,自己也實際應用到公司專案裡了,很實用,推薦一下.
推薦地址:http://www.cnblogs.com/tugenhua0707/p/3474791.html
可根據自己想要的樣式以及效果自定義更改。
js程式碼:
/** * JSON無限摺疊選單 * @constructor {AccordionMenu} * @param {options} 物件 */ function AccordionMenu(options) { this.config = { containerCls : '.wrap-menu', // 外層容器 menuArrs : '', // JSON傳進來的資料 type : 'click', // 預設為click 也可以mouseover renderCallBack : null, // 渲染html結構後回撥 clickItemCallBack : null // 每點選某一項時候回撥 }; this.cache = { }; this.init(options); } AccordionMenu.prototype = { constructor: AccordionMenu, init: function(options){ this.config = $.extend(this.config,options || {}); var self = this, _config = self.config, _cache = self.cache; // 渲染html結構 $(_config.containerCls).each(function(index,item){ self._renderHTML(item); // 處理點選事件 self._bindEnv(item); }); }, _renderHTML: function(container){ var self = this, _config = self.config, _cache = self.cache; var ulhtml = $('<ul></ul>'); $(_config.menuArrs).each(function(index,item){ var lihtml = $('<li><h2>'+item.name+'</h2></li>'); if(item.submenu && item.submenu.length > 0) { self._createSubMenu(item.submenu,lihtml); } $(ulhtml).append(lihtml); }); $(container).append(ulhtml); _config.renderCallBack && $.isFunction(_config.renderCallBack) && _config.renderCallBack(); // 處理層級縮排 self._levelIndent(ulhtml); }, /** * 建立子選單 * @param {array} 子選單 * @param {lihtml} li項 */ _createSubMenu: function(submenu,lihtml){ var self = this, _config = self.config, _cache = self.cache; var subUl = $('<ul></ul>'), callee = arguments.callee, subLi; $(submenu).each(function(index,item){ var url = item.url || 'javascript:void(0)'; subLi = $('<li><a href="'+url+'">'+item.name+'</a></li>'); if(item.submenu && item.submenu.length > 0) { $(subLi).children('a').prepend('<img src="images/blank.gif" alt=""/>'); callee(item.submenu, subLi); } $(subUl).append(subLi); }); $(lihtml).append(subUl); }, /** * 處理層級縮排 */ _levelIndent: function(ulList){ var self = this, _config = self.config, _cache = self.cache, callee = arguments.callee; var initTextIndent = 2, lev = 1, $oUl = $(ulList); while($oUl.find('ul').length > 0){ initTextIndent = parseInt(initTextIndent,10) + 2 + 'em'; $oUl.children().children('ul').addClass('lev-' + lev) .children('li').css('text-indent', initTextIndent); $oUl = $oUl.children().children('ul'); lev++; } $(ulList).find('ul').hide(); $(ulList).find('ul:first').show(); }, /** * 繫結事件 */ _bindEnv: function(container) { var self = this, _config = self.config; $('h2,a',container).unbind(_config.type); $('h2,a',container).bind(_config.type,function(e){ if($(this).siblings('ul').length > 0) { $(this).siblings('ul').slideToggle('slow').end().children('img').toggleClass('unfold'); } $(this).parent('li').siblings().find('ul').hide() .end().find('img.unfold').removeClass('unfold'); _config.clickItemCallBack && $.isFunction(_config.clickItemCallBack) && _config.clickItemCallBack($(this)); }); } };
選單預設樣式:
.wrap-menu { overflow:auto; width:300px; background:#F6F6F6; font:12px/1.5 Tahoma,Arial,sans-serif } .wrap-menu ul { list-style:none; margin:0; padding:0; } .wrap-menu ul li { text-indent:3em; white-space:nowrap; } .wrap-menu ul li h2 { cursor:pointer; height:100%; width:100%; margin:0 0 1px 0; font:12px/31px '宋體'; color:#fff; background:red; } .wrap-menu ul li a { display:block; outline:none; height:25px; line-height:25px; margin:1px 0; color:#1A385C; text-decoration:none; } .wrap-menu ul li img { margin-right:10px; margin-left:-17px; margin-top:9px; width:7px; height:7px; background:url(images/arrow.gif) no-repeat; border:none; } .wrap-menu ul li img.unfold { background-position:0 -9px; } .wrap-menu ul li a:hover { background-color:#ccc; background-image:none; }
引用程式碼:(初始化呼叫)
$(function(){
new AccordionMenu({menuArrs:testMenu});
});
提示:
new AccordionMenu({menuArrs:testMenu}); 其中testMenu 就是下面定義的JSON格式
測試選單資料:
var testMenu=[ { "name": "一級選單", "submenu": [ { "name": "二級選單", "url": "" }, { "name": "二級選單", "url": "" } ] }, { "name": "一級選單", "submenu": [ { "name": "二級選單", "url": "" }, { "name": "二級選單", "submenu": [ { "name": "三級選單", "submenu": [ { "name": "四級選單", "url": "" } ] }, { "name": "三級選單", "url": "" } ] }, { "name": "二級選單", "url": "" }, { "name": "二級選單", "submenu": [ { "name": "三級選單", "submenu": [ { "name": "四級選單", "url": "" }, { "name": "四級選單", "submenu": [ { "name": "五級選單", "url": "" }, { "name": "五級選單", "url": "" } ] } ] }, { "name": "三級選單", "url": "" } ] }, { "name": "二級選單", "url": "" } ] }, { "name": "一級選單", "submenu": [ { "name": "二級選單", "url": "" }, { "name": "二級選單", "url": "" }, { "name": "二級選單", "url": "" } ] } ];
為了方便,自行寫了Java無限選單遞迴封裝的程式碼以及無限選單程式碼,如下:
Java無限選單遞迴封裝的程式碼:(controller)
/**
* 初始化載入選單,獲取選單列表
*
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/getMenuList", method = RequestMethod.POST, produces = {
"application/json; charset=UTF-8"})
public Object getMenuList(@RequestBody JSONObject jsonP) throws Exception {
JSONArray menuArray = new JSONArray();
JSONObject menuList = new JSONObject();
JSONObject menuObject = new JSONObject();
List<TbMenu> menuListAll = iMenuService.getMenuList();
JSONArray menuArrayAll = JSONArray.parseArray(JSONArray.toJSONString(menuListAll));
if (menuArrayAll != null && !menuArrayAll .isEmpty()) {
for (int i = 0; i < menuArrayAll.size(); i++) {
JSONObject jsonObj = menuArrayAll.getJSONObject(i);
JSONArray menuItems = menuObject.getJSONArray(jsonObj.getString("menuTid"));
if (menuItems == null || menuItems.isEmpty()) {
JSONArray jsonArr = new JSONArray();
jsonArr.add(jsonObj);
menuObject.put(jsonObj.getString("menuTid"), jsonArr);
} else {
menuItems.add(jsonObj);
menuObject.put(jsonObj.getString("menuTid"), menuItems);
}
JSONObject menu = new JSONObject();
menu.put("idx", i + 1); // 序號
menu.put("id", jsonObj.getString("menuPid")); // ID
menu.put("name", jsonObj.getString("menuName"));
menuArray.add(menu);
}
}
menuList.put("menuList", getMenuListByTid(menuObject, jsonP.getIntValue("menuTid")));
menuList.put("mArray", menuArray);
return menuList;
}
/**
* 遞進選單列表
*
* @param menuTid
* @return
*/
private JSONArray getMenuListByTid(JSONObject menuObject, Integer menuTid) {
JSONArray menuArray = new JSONArray();
JSONArray menuList = menuObject.getJSONArray(menuTid.toString());
if (menuList != null && !menuList.isEmpty()) {
for (int i = 0; i < menuList.size(); i++) {
JSONObject menuItem = new JSONObject();
TbMenu tbMenu = menuList.getObject(i, TbMenu.class);
menuItem.put("name", tbMenu.getMenuName()); // 選單名稱
JSONArray menuListItem = menuObject.getJSONArray(tbMenu.getMenuPid().toString());
if (menuListItem == null || menuListItem.isEmpty()) {
menuItem.put("target", tbMenu.getMenuTarget()); // 跳轉方式
menuItem.put("url", tbMenu.getMenuUrl()); // 訪問url
} else {
menuItem.put("submenu", getMenuListByTid(menuObject, tbMenu.getMenuPid()));
}
menuArray.add(menuItem);
}
}
return menuArray;
}
封裝的初始化js程式碼:
/*
* metismenu - v1.1.3
* Easy menu jQuery plugin for Twitter Bootstrap 3
* https://github.com/onokumus/metisMenu
*
* Made by Osman Nuri Okumus
* Under MIT License
*/
;(function ($, window, document, undefined) {
// 資料初始化
var menuDatas = null;
$.ajax({
url: "/menu/getMenuList",
type: "POST",
data: JSON.stringify({"menuTid": 0}), //傳參為0,載入根(一級)選單,1載入二級選單,2載入三級選單...
dataType: "json",
async: false, //開啟同步,先載入完ajax請求,再繼續往下執行選單渲染程式碼
contentType: "application/json",
success: function (menuData) {
// console.log("成功:" + JSON.stringify(menuData));
menuDatas = JSON.stringify(menuData.menuList);
},
error: function (msg) {
console.log("失敗:" + msg);
}
});
var renderCallBack = null;
// 渲染html結構
$(".sidebar-collapse").each(function (index, item) {
_renderHTML(item);
});
/**
* 建立主選單
* @param {array} 主選單
* @param {lihtml} li項
*/
function _renderHTML(container) {
var ulhtml = $('<ul class="nav" id="side-menu"></ul>'),
lihtml;
var liheader = $('<li class="nav-header"><div class="dropdown profile-element">'
+ '<img alt="image" src="/img/iconfont-logo.png" /></div><div class="logo-element">D+</div></li>');
$(ulhtml).append(liheader);
$(menuDatas).each(function (index, item) {
var url = (item.url) || ('/?path=welcome&random=' + Math.random());
if (item.submenu && item.submenu.length > 0) {
lihtml = $('<li><a href="' + url + '"><i class="glyphicon glyphicon-folder-open"></i>'
+ '<span class="nav-label">' + item.name + '</span>'
+ ((item.submenu && item.submenu.length > 0) ? '<span class="fa arrow"></span>' : '')
+ '</a></li>');
_createSubMenu(item.submenu, lihtml);
} else if (item.target && item.target.length > 0) {
lihtml = $('<li><a href="' + url + '" target="' + item.target
+ '"><i class="glyphicon glyphicon-folder-open"></i>'
+ '<span class="nav-label">' + item.name + '</span></a></li>');
} else {
lihtml = $('<li><a class="J_menuItem" href="' + url
+ '"><i class="glyphicon glyphicon-folder-open"></i>'
+ '<span class="nav-label">' + item.name + '</span></a></li>');
}
$(ulhtml).append(lihtml);
});
$(container).append(ulhtml);
renderCallBack && $.isFunction(renderCallBack) && renderCallBack();
}
/**
* 建立子選單
* @param {array} 子選單
* @param {lihtml} li項
*/
function _createSubMenu(children, lihtml) {
var subUl = $('<ul class="nav nav-second-level"></ul>'),
callee = arguments.callee,
subLi;
$(children).each(function (index, item) {
var url = (item.url) || ('/?path=welcome&random=' + Math.random());
if (item.submenu && item.submenu.length > 0) {
subLi = $('<li><a href="#"><span class="nav-label">' + item.name + '</span>'
+ ((item.submenu && item.submenu.length > 0) ? '<span class="fa arrow"></span>' : '')
+ '</a></li>');
callee(item.submenu, subLi);
} else if (item.target && item.target.length > 0) {
subLi = $('<li><a href="' + url + '" target="' + item.target + '">' + item.name + '</a></li>');
} else {
subLi = $('<li><a class="J_menuItem" href="' + url + '">' + item.name + '</a></li>');
}
$(subUl).append(subLi);
});
$(lihtml).append(subUl);
// 處理層級縮排
_levelIndent(subUl);
}
/**
* 處理層級縮排
*/
function _levelIndent(ulList) {
var lev = 1,
$oUl = $(ulList);
while ($oUl.find('ul').length > 0) {
$oUl.children().children('ul').addClass("coll");
$oUl = $oUl.children().children('ul');
lev++;
}
$(ulList).find('ul').slideUp(200);
// $(ulList).find('ul:first').slideUp(200);
}
var pluginName = "metisMenu",
defaults = {
toggle: true,
doubleTapToGo: false
};
function Plugin(element, options) {
this.element = $(element);
this.settings = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype = {
init: function () {
if (menuDatas.length == 0) {
return;
}
var $this = this.element,
$toggle = this.settings.toggle,
obj = this;
if (this.isIE() <= 9) {
$this.find("li.active").has("ul").children("ul").collapse("show");
$this.find("li").not(".active").has("ul").children("ul").collapse("hide");
} else {
$this.find("li.active").has("ul").children("ul").addClass("collapse in");
$this.find("li").not(".active").has("ul").children("ul").addClass("collapse");
}
//add the "doubleTapToGo" class to active items if needed
if (obj.settings.doubleTapToGo) {
$this.find("li.active").has("ul").children("a").addClass("doubleTapToGo");
}
$this.find("li").has("ul").children("a").on("click" + "." + pluginName, function (e) {
e.preventDefault();
//Do we need to enable the double tap
if (obj.settings.doubleTapToGo) {
//if we hit a second time on the link and the href is valid, navigate to that url
if (obj.doubleTapToGo($(this)) && $(this).attr("href") !== "#" && $(this).attr("href") !== "") {
e.stopPropagation();
document.location = $(this).attr("href");
return;
}
}
$(this).parent("li").toggleClass("active").children("ul").collapse("toggle");
if ($toggle) {
$(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide");
}
});
},
isIE: function () { //https://gist.github.com/padolsey/527683
var undef,
v = 3,
div = document.createElement("div"),
all = div.getElementsByTagName("i");
while (
div.innerHTML = "<!--[if gt IE " + (++v) + "]><i></i><![endif]-->",
all[0]
) {
return v > 4 ? v : undef;
}
},
//Enable the link on the second click.
doubleTapToGo: function (elem) {
var $this = this.element;
//if the class "doubleTapToGo" exists, remove it and return
if (elem.hasClass("doubleTapToGo")) {
elem.removeClass("doubleTapToGo");
return true;
}
//does not exists, add a new class and return false
if (elem.parent().children("ul").length) {
//first remove all other class
$this.find(".doubleTapToGo").removeClass("doubleTapToGo");
//add the class on the current element
elem.addClass("doubleTapToGo");
return false;
}
},
remove: function () {
this.element.off("." + pluginName);
this.element.removeData(pluginName);
}
};
$.fn[pluginName] = function (options) {
this.each(function () {
var el = $(this);
if (el.data(pluginName)) {
el.data(pluginName).remove();
}
el.data(pluginName, new Plugin(this, options));
});
return this;
};
})(jQuery, window, document);
轉載請註明出處!