JSON 无限折叠菜单

最近看了一篇关于JSON无限折叠菜单的文章 感觉写的不错,也研究了下代码,自己也实际应用到公司项目里了,很实用,推荐一下.
推荐地址:http://www.cnblogs.com/tugenhua0707/p/3474791.html

JSON 无限折叠菜单_第1张图片
可根据自己想要的样式以及效果自定义更改。

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 = $('
    '); $(_config.menuArrs).each(function(index,item){ var lihtml = $('
  • '+item.name+'

  • '); 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 = $('
      '), callee = arguments.callee, subLi; $(submenu).each(function(index,item){ var url = item.url || 'javascript:void(0)'; subLi = $('
    • '+item.name+'
    • '); if(item.submenu && item.submenu.length > 0) { $(subLi).children('a').prepend(''); 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 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 = $(''),
                  lihtml;
              var liheader = $('');
              $(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 = $('
    • ' + '' + item.name + '' + ((item.submenu && item.submenu.length > 0) ? '' : '') + '
    • '); _createSubMenu(item.submenu, lihtml); } else if (item.target && item.target.length > 0) { lihtml = $('
    • ' + '' + item.name + '
    • '); } else { lihtml = $('
    • ' + '' + item.name + '
    • '); } $(ulhtml).append(lihtml); }); $(container).append(ulhtml); renderCallBack && $.isFunction(renderCallBack) && renderCallBack(); } /** * 创建子菜单 * @param {array} 子菜单 * @param {lihtml} li项 */ function _createSubMenu(children, lihtml) { var subUl = $(''), 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 = $('
    • ' + item.name + '' + ((item.submenu && item.submenu.length > 0) ? '' : '') + '
    • '); callee(item.submenu, subLi); } else if (item.target && item.target.length > 0) { subLi = $('
    • ' + item.name + '
    • '); } else { subLi = $('
    • ' + item.name + '
    • '); } $(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 = "", 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);

      转载请注明出处!

      你可能感兴趣的:(Json)