WordPress 多级导航菜单

Jun 13th, 2009 Add Comment

多级导航菜单, 是指菜单存在多个层次, 层层嵌套, 当鼠标移动到某个菜单时, 如果其包含子菜单则将相应的子菜单显示出来. 本文将提供此功能在 WordPress 的实现方法, 一般的 HTML 页面和其他程序也可以加工套用.

Multi Level Menus

时隔 9 个多月, 关于导航菜单的话题又回来了. 上次写到三级菜单就不写了是因为我发现自己根本用不上, 就没去研究. 最近我在做一个小玩意儿用到了这个, 所以把它给做了出来并集成到 iNove 主题上. 因为内容繁多, 所以还是以之前的文章和代码作为基础来展开讲解, 希望这个文章会对大家有所帮助.

为了简化处理, 明确目标, 这次我们会以二级导航菜单作为原型进行扩展. 本文只对多级菜单相关处理进行讨论, 其他内容请参考以前的几篇关于菜单导航的文章, 文章链接你可以在本文相关话题中找到.

这是效果演示

相关话题:

WordPress 导航菜单
二级导航菜单
淡出淡入导航菜单
滚动导航菜单
jQuery 导航菜单
多级导航菜单
点选式导航菜单 (待定话题)

作业分析:

因为菜单由本来的二级菜单变成了多级菜单, 所以菜单结构会有些变化 (会有新的更深层的子菜单加入). 另外, 页面的样式和脚本都会有相应的变更, 重点在于对 JavaScript 的加工.

主要操作如下:
1. 鼠标移动到一级菜单的菜单项时, 如果该菜单项包含了二级菜单, 那么在下方显示其子菜单.
2. 鼠标移动到 N (N >= 2) 级菜单的菜单项时, 如果该菜单项包含了 N+1 级菜单, 那么在右侧显示其子菜单.

预想结构:

<div id="menubar">
	<ul class="menus">
		<li class="..."><a href="http://.../">Home</a></li>
		<li class="...">
			<a href="http://.../">菜单1</a>
			<ul class="children">
				<li class="..."><a href="http://.../">菜单11</a></li>
				<li class="...">
					<a href="http://.../">菜单12</a>
					<ul class="children">
						<li class="..."><a href="http://.../">菜单121</a></li>
						<li class="..."><a href="http://.../">菜单122</a></li>
						<li class="..."><a href="http://.../">菜单123</a></li>
						<li class="..."><a href="http://.../">菜单124</a></li>
					</ul>
				</li>
				<li class="...">
					<a href="http://.../">菜单13</a>
					<ul class="children">
						<li class="..."><a href="http://.../">菜单131</a></li>
						<li class="..."><a href="http://.../">菜单132</a></li>
					</ul>
				</li>
			</ul>
		</li>
		<li class="...">
			<a href="http://.../">菜单2</a>
			<ul class="children">
				<li class="..."><a href="http://.../">菜单21</a></li>
			</ul>
		</li>
		<li class="...">
			<a href="http://.../">菜单3</a>
			<ul class="children">
				<li class="..."><a href="http://.../">菜单31</a></li>
				<li class="...">
					<a href="http://.../">菜单32</a>
					<ul class="children">
						<li class="..."><a href="http://.../">菜单321</a></li>
						<li class="..."><a href="http://.../">菜单322</a></li>
					</ul>
				</li>
			</ul>
		</li>
		...
	</ul>
</div>

实施操作:

1. 调出无限级菜单 (子分类)
是否还记得如何设定列表的深度? 可以通过参数 depth 来进行设定. 当我们将深度设为 1 时不显示子分类, 将深度设为 2 时显示二级菜单. 现在我们要无限制层数的菜单, 所以可以去除这个参数, 系统会自动返回所有菜单. 所以显示菜单的代码如下:

<?php wp_list_pages('depth=2&title_li=0&sort_column=menu_order'); ?>

2. 修改菜单的样式
在子菜单项添加 display:inline; 以免在 IE (IE6/IE7/IE8) 中发生错位.

/* 子菜单的菜单项 */
#menubar ul.children li {
	float:none; /* 垂直排列 */
	margin:0;
	padding:0;
	/* multi 2009/06/11 ADD START */
	display:inline; /* 对 IE 来说十分很重要 */
	/* multi 2009/06/11 ADD END */
}

追加包含子菜单的菜单项的样式

#menubar ul.children li a.subtitle {
	border-right:3px solid #4281B7;
	width:97px;
}

添加当前菜单的效果, 以明确当前路径.

#menubar ul.menus li a:hover, 
/* multi 2009/06/11 ADD START */
#menubar ul.menus li a.current {
/* multi 2009/06/11 ADD END */
	background:#4281B7; /* 背景颜色 */
}

3. 加载菜单
加载菜单是应该分开处理, 对于对层次的菜单, 菜单显示有两种状态. (1) 作为二级菜单显示在上一级菜单的下方; (2) 而三级和以上层次的菜单则会显示在上一级菜单的右侧.

// 找到所有的菜单
var menus = this.obj.getElementsByTagName('ul');
for (var i = 0; i < menus.length; i++) {
	// 找到菜单的父节点 (包括标题链接部分)
	var menu = menus[i].parentNode;
 
	// 如果菜单的父节点就是根菜单, 显示一般的菜单
	if(menu.parentNode === this.obj) {
		new Menu(menu, opacity);
 
	// 如果菜单的父节点不是根菜单, 说明当前菜单是子菜单
	} else {
		new Menu(menu, opacity, 1);
		// 在子菜单的标题链接上加上 class 名, 以便定义样式
		menu.firstChild.className += ' subtitle';
	}
}

4. 菜单的初始化
添加一个参数, 以识别是否为子菜单 (三级以上的菜单); 去除 overflow:hidden; 的设置, 否则子菜单无法显示出来.

initialize: function(target, opacity, sub) {
	this.util = new MenuUtil();
 
	// 获取目标菜单 (没多余元素)
	this.obj = this.util.cleanWhitespace(target);
 
	// 定义透明度, 默认透明
	this.opacity = opacity || 1;
 
	/* multi 2009/06/11 ADD START */
	// 是否为子菜单
	this.sub = sub || -1;
	/* multi 2009/06/11 ADD START */
 
	// 获取菜单
	this.menu = this.obj.childNodes
 
	// 重要! 如果菜单不包含菜单项, 则不进行处理
	if (this.menu.length < 2) { return; }
 
	// 菜单标题和菜单体
	this.title = this.menu[0];
	this.body = this.menu[1];
 
	// 定义初始样式
	this.util.setStyle(this.body, 'visibility', 'hidden');
	this.util.setStyle(this.body, 'position', 'absolute');
	/* multi 2009/06/11 DELETE START */
	//this.util.setStyle(this.body, 'overflow', 'hidden');
	/* multi 2009/06/11 DELETE END */
	this.util.setStyle(this.body, 'display', 'block');
 
	// 添加监听器
	this.addListener(this.obj, 'mouseover', this.util.bind(this, this.activate), false);
	this.addListener(this.obj, 'mouseout', this.util.bind(this, this.deactivate), false);
	}

5. 对菜单和子菜单分开处理
菜单 (二级菜单) 的位置是相对于窗口的, 而子菜单 (三级或以上菜单) 是的位置是相对于上一级菜单的, 所以必须判断是哪种菜单类型, 并以不同的方法来确定位置. 另外, 两者要显示的位置也不相同, 所以在激活方法内还需要以不同的方式将 top 和 left 位置计算出来.

// 获取当前菜单体的位置 (子菜单)
if(this.sub == 1) {
	var pos = this.util.currentOffset(this.title);
	var left = this.util.getWidth(this.body);
	var top = pos[1];
 
// 获取当前菜单体的位置 (菜单)
} else {
	var pos = this.util.cumulativeOffset(this.title);
	var left = pos[0];
	var top = pos[1] + this.util.getHeight(this.title);
	// 子菜单不需要设置不透明度, 否则会形成多重透明, 效果不好.
	this.util.setStyle(this.body, 'opacity', this.opacity);
}

6. 添加当前菜单的 className
为了更好的表示当前菜单的上级菜单, 在激活菜单的时候为当前菜单加上 className.

// 当前选中菜单加上 class 名为, 以便定义样式
this.title.className += ' current';

并且在解除菜单的时候移除菜单上的 className.

// 离开菜单时取消当前菜单上的 class 名, 恢复原本的样式
this.title.className = this.title.className.replace('current', '');

演示主题:

以 WordPress 自带主题 default 为基础, 仅做学习参考使用, 修改过的文件有 header.phpstyle.css, 添加了文件 js/menu.js

下载主题: default_with_menubar_5.zip

下回预告:

下次讨论点选式菜单, 或者 CSS 实现的菜单, 或者 jQuery 实现的各类菜单.

声明: 本文采用 BY-NC-SA 协议进行授权. 转载请注明转自: WordPress 多级导航菜单

  1. http://1.gravatar.com/avatar/573b17b5f5ba8f2b149a2eb09f400f7b?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    菜单是出来了,没法下拉,继续学习~

  2. http://0.gravatar.com/avatar/05147e21dab0ef8bd7fa33168489a6ca?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    不错的讲解,正好需要集成这个功能

  3. http://1.gravatar.com/avatar/b5bce33239d69ae1dd920fa5fb6c7b3b?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    效果感觉很好哈,试试看……

  4. http://0.gravatar.com/avatar/afdf6f07b394a5d219f70df9fbcdd480?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    请问子菜单的背景要怎么设?
    #menubar ul.menus li a:hover,
    #menubar ul.menus li a.current {
    background:#4281B7; /* 背景颜色 */
    这个背景颜色是鼠标移到子菜单上才显示的,但是鼠标在一级菜单上时下拉子菜单的背景是透明的,怎么样让子菜单只要显示出来就有背景?

  5. http://1.gravatar.com/avatar/1df059127b05d00385c48ef56a07c887?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    特来道谢
    感谢你的这个多级导航菜单
    帮了我不少忙
    谢谢mg12

  6. http://0.gravatar.com/avatar/a80d90a92f44827e5155e569f219d827?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    我做了,不好看,我不知道如何弄成竖排的

  7. http://1.gravatar.com/avatar/b95deee94873128f0e9c725a01ffd91a?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    Internet Explorer 8 have been my most used browser this year, it is definitely stable and fast loading too. .'

  8. http://1.gravatar.com/avatar/7c4d86d9822356b6a6b88c6a4a8af500?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    Internet Explorer 8 is very good because it is as stable as Opera. I hate the previous versions of IE like IE6 because it hangs frequently. .

  9. http://0.gravatar.com/avatar/490cf262668eebb0f0f1a50d9d48d702?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    @wpmuer
    Purecss 是什么主题? 我不能保证代码不修改就能适用所有主题, 请找主题作者问一下吧.

    @John
    这是 WP 默认就生成的.

    @bolo
    Yeah~

  10. http://0.gravatar.com/avatar/2a9c4f525050372a6fe0b10ce4fe8957?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    @John
    wp_list_pages的depth等于0或大于1,当存在子页面时就自动生成了

  11. http://0.gravatar.com/avatar/29ae2517381a3c0b4e0a5a3243b6b36b?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    请问楼主那个中的class=children 是怎么加进去的?thanks!

  12. http://1.gravatar.com/avatar/1df059127b05d00385c48ef56a07c887?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    首先感谢楼主的教程
    想向楼主请教
    我想把这种菜单添加到其他主题
    Purecss 但始终无法显示多级效果
    但是在其他的主题中成功了
    请问这是问什么
    希望楼主赐教

  13. http://1.gravatar.com/avatar/1ef4e47a2c3cf52ec848bb5b23a20249?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    谢谢mg12,是我没注意仔细看,以为通不过xhtml是这个原因,现在问题已解决。
    @mg12

  14. http://0.gravatar.com/avatar/490cf262668eebb0f0f1a50d9d48d702?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    @SorryDreams
    ul 里面嵌套 li, li 再嵌套 ul, 为什么不符合嵌套规则? 可以通过 XHTML 的.

  15. http://1.gravatar.com/avatar/1ef4e47a2c3cf52ec848bb5b23a20249?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    可以实现预想的效果,但是ul里面嵌套ul,不符合嵌套规则,也通不过xhtml检验吧。有没有其他方法?

  16. http://0.gravatar.com/avatar/acb833676d4887ce1d92439e5e5092bf?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    哦 这个可以试一试的

  17. http://0.gravatar.com/avatar/c869a99b600a88333c73483cec0db606?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    Thanks a lot for this tip.

  18. http://0.gravatar.com/avatar/ab6034a4a2a06b382ed2e08c821ef4fb?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    @mg12
    原来如此~ 我可以帮你测试哈哈~~

  19. http://0.gravatar.com/avatar/490cf262668eebb0f0f1a50d9d48d702?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    @chisdy
    这篇文章就是教你怎么用的, 以后我的所有主题都会集成.

    @brea
    不是, 我显卡驱动有点问题, 我还没配置好. 等闲点再弄.

  20. http://0.gravatar.com/avatar/87992a7c1d327a19ebd942e003e5e83f?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G
  21. http://0.gravatar.com/avatar/ab6034a4a2a06b382ed2e08c821ef4fb?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    @mg12
    不好意思,少写了个0,是3.0.11~~
    不过以我浅薄的经验,linux似乎不太容易垮的吧。。。你是不是干什么坏事了 :)

  22. http://1.gravatar.com/avatar/71981550e606563e4f569c420b2276cf?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G

    这东西好,哪都能用。

Comment pages
  1. Loading...