现在,我要实现这样一个功能,
1. 根据数据库的配置,动态生成横向导航菜单,如下图所示:
2. 点击横向导航菜单的时候,再动态生成左侧菜单。
现在,我是这样实现的,在系统登录进来的时候,初始化横向导航菜单,并用横向菜单的第一个项(id=1)来初始化左菜单。初始化的过程是用ajax传递id=1到后台,然后查询到id=1的所有子菜单,以xml的形式返回给前台。然后前台解析xml生成左菜单。
登录进来之后,点击横向菜单按钮,执行的也是上面的这段逻辑。
现在遇到的问题是:一开始登录进来初始化的时候,没什么问题;但之后点击横向导航的时候,就出现问题了,左侧菜单树(tree)的样式就没有了,导致菜单没办法使用。如下图所示
出现该问题的具体原因如下:
<div id="accordion" class="accordion" fillSpace="sidebar"> </div>
DWZ初始化加载这个组件的时候,使用的是(function($){})(jQuery);(即初始化执行一次)这种方式,在js代码中初始化各个元素的样式和绑定事件(而不是通过CSS来进行初始化)。这种情况下,在一次刷新页面过程中,样式只执行一次加载,如果要重新加载样式,必须要重新刷新页面。
这样就导致在登录进来之后,再次点击横向导航(比如资讯管理)的时候,动态生成的html内容,因为没有经过初始化js对其进行样式加载,从而不会出现任何样式效果。
具体解决方案:
1. 将初始化左菜单样式的js从(function($){})(jQuery);里面抽取出来,重写一个js方法fillSpace()。
2. 在动态生成html内容之后,再调用上面的js方法初始化样式。
具体的实现方式见源码(index.jsp)
------------------------------------------------------------------------------------------------------------------------------------
具体的代码我简单的贴一下,这里只有前台页面的代码,后台动态返回结果的代码,是struts2的,暂时不提供了,只提供最终返回的JSON数据
<%@ page contentType="text/html; charset=UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=8" /> <title>EMBoss</title> <link href="themes/default/style.css" rel="stylesheet" type="text/css" media="screen"/> <link href="themes/css/core.css" rel="stylesheet" type="text/css" media="screen"/> <link href="themes/css/print.css" rel="stylesheet" type="text/css" media="print"/> <link href="uploadify/css/uploadify.css" rel="stylesheet" type="text/css" media="screen"/> <!--[if IE]> <link href="themes/css/ieHack.css" rel="stylesheet" type="text/css" media="screen"/> <![endif]--> <style type="text/css"> #header{height:85px} #leftside, #container, #splitBar, #splitBarProxy{top:90px} </style> <!--[if lte IE 9]> <script src="js/speedup.js" type="text/javascript"></script> <![endif]--> <script src="js/jquery-1.7.2.min.js" type="text/javascript"></script> <script src="js/jquery.cookie.js" type="text/javascript"></script> <script src="js/jquery.validate.js" type="text/javascript"></script> <script src="js/jquery.bgiframe.js" type="text/javascript"></script> <script src="xheditor/xheditor-1.2.1.min.js" type="text/javascript"></script> <script src="xheditor/xheditor_lang/zh-cn.js" type="text/javascript"></script> <script src="uploadify/scripts/jquery.uploadify.min.js" type="text/javascript"></script> <script src="bin/dwz.min.js" type="text/javascript"></script> <script src="js/dwz.regional.zh.js" type="text/javascript"></script> <script type="text/javascript"> var ts=""; /* 把xml字符串转成xml对象 */ function parseXml(xmlStr){ var xml; if($.browser.msie){ xml = new ActiveXObject("Microsoft.XMLDOM"); xml.async = false; xml.loadXML(xmlStr); }else{ xml = new DOMParser().parseFromString(xmlStr, "text/xml"); } return xml; } //设置横向导航菜单 //通过struts2的action获取横向导航的json字符串,data.returnList数据如下: /* Object { tmid=1, tmname="资讯管理"} Object { tmid=2, tmname="订单管理"} Object { tmid=3, tmname="产品管理"} Object { tmid=4, tmname="会员管理"} Object { tmid=5, tmname="服务管理"} Object { tmid=6, tmname="系统设置"} */ function settopmenu() { $.getJSON("<%=request.getContextPath()%>/menumgr!getTopMenu.action", function(data){ var tm='<ul>'; $.each(data.returnList, function(i,item){ if(i==0){ //selectClass = "selected"; tm+='<li class="selected"><a href="javascript:void(0)" onclick="changeMenu(this,'+item.tmid+')" rel="'+item.tmid+'"><span>'+item.tmname+'</span></a></li>'; }else{ //selectClass = "none"; tm+='<li><a href="javascript:void(0)" onclick="changeMenu(this,'+item.tmid+')" rel="'+item.tmid+'"><span>'+item.tmname+'</span></a></li>'; } //tm+='<li class="'+selectClass+'"><a href="index_menu.jsp?pid='+item.tmid+'"><span>'+item.tmname+'</span></a></li>'; }); tm+="</ul>"; $("#navMenu").html(tm); } ); } //递归生成左侧菜单树div function setts(nodes,flag) { for(var i=0;i<nodes.length;i++) { var cnodes=$(nodes[i]).children(); if(cnodes.length==0) { ts+='<li><a href="'+$(nodes[i]).attr("url")+'" target="navTab" rel="'+$(nodes[i]).attr("id")+'">'+$(nodes[i]).attr("name")+'</a></li>'; if((i==nodes.length-1) && (nodes[i].parentNode.nodeName=="treenode") && flag==1) ts+='</ul></li>'; }else { if(nodes[i].parentNode.nodeName=="root"){ ts+='<div class="accordionHeader">'+ '<h2><span>Folder</span>'+$(nodes[i]).attr("name")+'</h2>'+ '</div>'+ '<div class="accordionContent">'+ '<ul class="tree treeFolder">'; //setts(cnodes); }else{ flag = 1; ts+='<li><a href="'+$(nodes[i]).attr("url")+'" target="navTab" rel="'+$(nodes[i]).attr("id")+'">'+$(nodes[i]).attr("name")+'</a>'; ts+='<ul>'; } setts(cnodes,flag); if(nodes[i].parentNode.nodeName=="root") ts+='</ul></div>'; } } } //横向导航点击之后的函数调用 //更改点击之后的按钮样式,调用左侧菜单树生成函数 function changeMenu(obj,tmid){ //设置点击横向菜单后横向菜单的样式 $('#navMenu ul li').each(function(idx){ $('#navMenu ul li').removeClass(); }); $(obj).parent().addClass("selected"); //获取横向菜单的所有子菜单,并显示 getSubMenuClick(tmid); } //初始化左侧滑动菜单的样式 function fillSpace(obj) { if (!obj) return; var parent = $(obj).parent(); var hht = parent.height() - (($(".accordionHeader", obj).size()) * ($(".accordionHeader:first-child", obj).outerHeight())) - 2; var os = parent.children().not(obj); $.each(os, function(i) { hht -= $(os[i]).outerHeight(); }); //设置第一个滑动菜单标题按钮为打开状态 $(".accordionHeader h2",obj).eq(0).addClass("collapsable"); //设置所有的滑动菜单内容不可见 $(".accordionContent",obj).css({ display:"none", height:hht }); //设置第一个滑动菜单内容为可见状态 $(".accordionContent",obj).eq(0).css({ display:"block", height:hht }); //第一个滑动菜单标题按钮默认为已点击状态 $(".accordionHeader h2",obj).eq(0).click(); } //页面第一次加载的时候,初始化左菜单树,不需要加载样式,同getSubMenuClick方法 //调用struts2的action查询tmid的子菜单,以xml返回结果,data.returnString属性的xml格式如下: /* <?xml version="1.0" encoding="UTF-8"?><root><treenode id="102" name="界面组件"><treenode id="1021" name="主框架面板" url="demo_page4.html"/><treenode id="1022" name="主框架面板" url="demo_page4.html"/></treenode><treenode id="103" name="界面组件"><treenode id="1031" name="主框架面板2" url="demo_page4.html"/></treenode><treenode id="104" name="界面组件"><treenode id="1041" name="主框架面板3" url="demo_page4.html"/></treenode><treenode id="101" name="界面组件"><treenode id="1012" name="主框架面板2"><treenode id="10121" name="子菜单" url="demo_page4.html"/><treenode id="10122" name="子菜单" url="demo_page4.html"/></treenode><treenode id="1011" name="主框架面板"><treenode id="10112" name="我的主页2" url="demo_page4.html"/><treenode id="10113" name="我的主页3" url="demo_page4.html"/><treenode id="10111" name="我的主页1" url="demo_page4.html"/></treenode></treenode></root> */ function getSubMenu(tmid) { $.ajax({ type: "GET", /menumgr!getMenuTree.action'">url:'<%=request.getContextPath()%>/menumgr!getMenuTree.action', data:{ pid:tmid }, dataType:"json", cache: false, success: function(data){ ts=""; var nodes=$("root>treenode",parseXml(data.returnString)); setts(nodes,0); $("#loading").show(); $("#accordion").html(ts); $("#loading").hide(); } }); } //点击横向导航菜单的时候,动态加载左菜单树,需要加载样式 function getSubMenuClick(tmid) { $.ajax({ type: "GET", /menumgr!getMenuTree.action'">url:'<%=request.getContextPath()%>/menumgr!getMenuTree.action', data:{ pid:tmid }, dataType:"json", cache: false, success: function(data){ ts=""; var nodes=$("root>treenode",parseXml(data.returnString)); setts(nodes,0); $("#loading").show(); $("#accordion").html(ts); $("#loading").hide(); //以下三项初始化左菜单样式 fillSpace($("#accordion")); initLayout(); initUI(); } }); } } //DWZ初始化 function dwzInit(){ DWZ.init("dwz.frag.xml", { loginUrl:"login_dialog.html", loginTitle:"登录", // 弹出登录对话框 // loginUrl:"login.html", // 跳到登录页面 statusCode:{ok:200, error:300, timeout:301}, //【可选】 pageInfo:{pageNum:"pageNum", numPerPage:"numPerPage", orderField:"orderField", orderDirection:"orderDirection"}, //【可选】 debug:false, // 调试模式 【true|false】 callback:function(){ initEnv(); $("#themeList").theme({themeBase:"themes"}); //setTimeout(function() {$("#sidebar .toggleCollapse div").trigger("click");}, 10); } }); } //页面加载后初始化所有元素,包含初始化第一个横向导航的子菜单(左菜单树) $(function(){ //设置顶部菜单 settopmenu(); //设置默认菜单列表 getSubMenu(1); dwzInit(); }); </script> </head> <body scroll="no"> <div id="layout"> <div id="header"> <div class="headerNav"> <a class="logo" href="o'>http://j-ui.com">o标志</a> <ul class="nav"> <li id="switchEnvBox"><a href="javascript:">(<span>北京</span>)切换城市</a> <ul> <li><a href="sidebar_1.html">北京</a></li> <li><a href="sidebar_2.html">上海</a></li> <li><a href="sidebar_2.html">南京</a></li> <li><a href="sidebar_2.html">深圳</a></li> <li><a href="sidebar_2.html">广州</a></li> <li><a href="sidebar_2.html">天津</a></li> <li><a href="sidebar_2.html">杭州</a></li> </ul> </li> <li><a href="https://me.alipay.com/dwzteam" target="_blank">捐赠</a></li> <li><a href="changepwd.html" target="dialog" width="600">设置</a></li> <li><a href="http://www.cnblogs.com/dwzjs" target="_blank">博客</a></li> <li><a href="http://weibo.com/dwzui" target="_blank">微博</a></li> <li><a href="http://bbs.dwzjs.com" target="_blank">论坛</a></li> <li><a href="login.html">退出</a></li> </ul> <ul class="themeList" id="themeList"> <li theme="default"> <div class="selected">蓝色</div> </li> <li theme="green"> <div>绿色</div> </li> <!--<li theme="red"><div>红色</div></li>--> <li theme="purple"> <div>紫色</div> </li> <li theme="silver"> <div>银色</div> </li> <li theme="azure"> <div>天蓝</div> </li> </ul> </div> <div id="navMenu"> </div> </div> <div id="leftside"> <div id="sidebar_s"> <div class="collapse"> <div class="toggleCollapse"> <div></div> </div> </div> </div> <div id="sidebar"> <div id="loading" style="color:#ff0000;">Loading....</div> <div class="toggleCollapse"> <h2>主菜单</h2> <div>收缩</div> </div> <div id="accordion" class="accordion" fillSpace="sidebar"> </div> </div> </div> <div id="container"> <div id="navTab" class="tabsPage"> <div class="tabsPageHeader"> <div class="tabsPageHeaderContent"> <!-- 显示左右控制时添加 class="tabsPageHeaderMargin" --> <ul class="navTab-tab"> <li tabid="main" class="main"><a href="javascript:;"><span><span class="home_icon">我的主页</span></span></a></li> </ul> </div> <div class="tabsLeft">left</div> <!-- 禁用只需要添加一个样式 class="tabsLeft tabsLeftDisabled" --> <div class="tabsRight">right</div> <!-- 禁用只需要添加一个样式 class="tabsRight tabsRightDisabled" --> <div class="tabsMore">more</div> </div> <ul class="tabsMoreList"> <li><a href="javascript:;">我的主页</a></li> </ul> <div class="navTab-panel tabsPageContent layoutBox"> <div class="page unitBox"> <div class="accountInfo"> <div class="alertInfo"> <h2><a href="doc/dwz-user-guide.pdf" target="_blank">DWZ框架使用手册(PDF)</a></h2> <a href="doc/dwz-user-guide.swf" target="_blank">DWZ框架演示视频</a> </div> <div class="right"> <p><a href="doc/dwz-user-guide.zip" target="_blank" style="line-height:19px">DWZ框架使用手册(CHM)</a></p> <p><a href="doc/dwz-ajax-develop.swf" target="_blank" style="line-height:19px">DWZ框架Ajax开发视频教材</a></p> </div> <p><span>DWZ富客户端框架</span></p> <p>DWZ官方微博:<a href="http://weibo.com/dwzui" target="_blank">http://weibo.com/dwzui</a></p> </div> <div class="pageFormContent" layoutH="80"> </div> </div> </div> </div> </div> </div> <div id="footer">Copyright © 2010 <a href="demo_page2.html" target="dialog">DWZ团队</a></div> </body> </html>
问题已经解决,解决方法见下面的红色粗体字体部分
------------------------------------------------------------------------------
3. 横向导航点击之后的函数调用如下:
//更改点击之后的按钮样式,调用左侧菜单树生成函数
function changeMenu(obj,tmid){ $('#navMenu ul li').each(function(idx){ $('#navMenu ul li').removeClass(); }); $(obj).parent().addClass("selected"); //再次执行DWZ初始化方法,否则重新加载的菜单树会丢失样式 dwzInit(); //设置默认菜单列表 getSubMenu(tmid); }
--------------------------------------------------------------------------------------
另外,在测试的过程中发现,在IE中运行这个程序时,点击横向导航后,出现数据加载中提示,一直无法去掉
参照网上的说明处理如下:
-----
我发现官网给的index.jsp里面<meta http-equiv="X-UA-Compatible" content="IE=7" />,就是说文档的格式是IE7标准,
后来我这样的解决的,把这个文档标准换成了IE8,即:<meta http-equiv="X-UA-Compatible" content="IE=8" />,
然后再IE下面就不出现这个问题了。。。。
问题补充:
console.log('');今天又发现了一个问题,在IE下,又出现了上面的这个问题,调试了半天,原来是js里面console.log(''); 的问题,把它去掉就行了。。
-----
希望对大家有帮助。
哎,杯具一个接着一个,测试的时候,又发现虽然有样式了,但菜单树默认情况下是全打开的,而且左侧没有完全纵向展开,如下所示:
正常: 不正常:
已解决,核心代码是:
增加一个JS方法:
//初始化左侧滑动菜单的样式 function fillSpace(obj) { if (!obj) return; var parent = $(obj).parent(); var hht = parent.height() - (($(".accordionHeader", obj).size()) * ($(".accordionHeader:first-child", obj).outerHeight())) - 2; var os = parent.children().not(obj); $.each(os, function(i) { hht -= $(os[i]).outerHeight(); }); //设置第一个滑动菜单标题按钮为打开状态 $(".accordionHeader h2",obj).eq(0).addClass("collapsable"); //设置所有的滑动菜单内容不可见 $(".accordionContent",obj).css({ display:"none", height:hht }); //设置第一个滑动菜单内容为可见状态 $(".accordionContent",obj).eq(0).css({ display:"block", height:hht }); //第一个滑动菜单标题按钮默认为已点击状态 $(".accordionHeader h2",obj).eq(0).click(); }
如果在界面中使用了$("#accordion").html(ts);这种方式动态生成界面,必须要重新执行js生成样式代码,DWZ初始化的时候,有两个初始化方法我们可以直接调用:
initLayout(); initUI();
如果执行这两个方法之后,还有问题,那么只能具体原因具体分析,再去根据源码重新加载相应的组件样式。
上面新增的这个方法是专门针对左侧滑动菜单树的样式重新加载方法。
在此感谢 王海峰 提供。