WordPress 二级导航菜单
前一篇已经讨论过如何创建 WordPress 导航菜单, 这回我们继续导航菜单的话题, 创建一个二级导航菜单. 如果你还不知道如何创建一个简单的导航菜单, 建议你先看看上一篇, 相关内容本文不再重复.
原本计划分两种方法来讨论这个二级导航菜单, 即 CSS 方式和 JavaScript 方式. 但由于我不知道 CSS 的该从何说起, IE 处理相当麻烦, 并且它与后面的话题也没有太多承接关系. 所以决定撤掉那个话题, 现在只讨论以 JavaScript 实现二级导航菜单. 你很快就能发现写 JavaScript 会比较快乐的.
何为二级导航菜单?
二级导航菜单就是类似桌面软件的菜单栏, 当鼠标移动到某一菜单时, 就会显示该菜单的菜单项, 也就是可以看到二级分类. 目前在 Web 上的应用已十分广泛, 今天我刚注册了一个网易的 yeah.net 邮箱, 里面有三级菜单呢. (请不要贪婪, 三级已经是应用极限了)
相关话题:
WordPress 导航菜单
二级导航菜单
淡出淡入导航菜单
滚动导航菜单
多级导航菜单
jQuery 导航菜单
点选式导航菜单 (待定话题)
作业分析:
我们已经知道菜单如何创建了, 这回我们要使用分类列表做成二级导航菜单. 我们要做的其实是在原有的基础上改出二级菜单, 以及对二级菜单进行处理. (请确保的的分类中包含子分类, 否则调不出二级菜单.)
我们共需要处理 3 个事情:
1. 调出二级菜单 (子分类)
2. 二级菜单的样式
3. 二级菜单的效果
预想结构:
<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://.../">菜单项1</a></li> <li class="..."><a href="http://.../">菜单项2</a></li> <li class="..."><a href="http://.../">菜单项3</a></li> </ul> </li> <li class="..."> <a href="http://.../">菜单2</a> <ul class="children"> <li class="..."><a href="http://.../">菜单项4</a></li> </ul> </li> <li class="..."> <a href="http://.../">菜单3</a> <ul class="children"> <li class="..."><a href="http://.../">菜单项5</a></li> <li class="..."><a href="http://.../">菜单项6</a></li> </ul> </li> ... </ul> </div>
实施操作:
1. 调出二级菜单 (子分类)
是否还记得制作导航菜单时是如何设定列表深度的? 当时将深度设为 1 是为了不显示子分类, 现在要二级子分类当然要将深度设为 2 了.
depth: 列表深度(层的最大数量), 本文讨论的是二级菜单, 故最大深度为 2.
打印分类菜单项的语句是:
<?php wp_list_pages('depth=2&title_li=0&sort_column=menu_order'); ?>
2. 二级菜单的样式
也只是在本来的样式上进行修改, 加上子分类的样式.
/* 二级菜单 */ #menubar ul.children { display:none; /* 初始化页面时不显示出来 */ padding:0; margin:0; } /* 二级菜单的菜单项 */ #menubar ul.children li { float:none; /* 垂直排列 */ margin:0; padding:0; } /* 二级菜单的当前菜单项链接 */ #menubar ul.children li a { width:100px; /* 对 IE6 来说十分很重要 */ }
打印首页菜单项的语句是:
<li class="<?php echo($home_menu_class); ?>"> <a title="Home" href="<?php echo get_settings('home'); ?>/">Home</a> </li>
3. 二级菜单的效果
全部使用 JavaScript 实现, 为便于理解, 使用面向对象方式编写代码, 借鉴了部分 Prototype 框架的代码. 因为代码比较多, 不适合逐句解说, 所以我已标上了大量注释. 代码不是很复杂, 有 JS 基础的话应该不会存在障碍.
另外为了迎合个别人的口味, 加上透明效果. Enjoy!
/* Author: mg12 Feature: MenuList with second-level menus Update: 2008/08/30 Tutorial URL: http://www.neoease.com/wordpress-menubar-2/ */ /** 类 */ var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } } } /** 菜单列表 */ var MenuList = Class.create(); MenuList.prototype = { /** * 构造方法 * id: 菜单列表 * opacity: 透明度 (0.0 - 1.0, 0.0 为全透明, 1.0 为不透明) */ initialize: function(id, opacity) { // 获取菜单列表 this.obj = document.getElementById(id); if (!this.obj) { return; } // 对菜单列表内的所有菜单进行处理 var menus = this.obj.childNodes; for (var i = 0; i < menus.length; i++) { var menu = menus[i]; if (menu.tagName == 'LI') { // 构建菜单 new Menu(menu, opacity); } } } } /** 菜单 */ var Menu = Class.create(); Menu.prototype = { /** * 构造方法 * target: 目标菜单 * opacity: 透明度 (0.0 - 1.0, 0.0 为全透明, 1.0 为不透明) */ initialize: function(target, opacity) { this.util = new MenuUtil(); // 获取目标菜单 (没多余元素) this.obj = this.util.cleanWhitespace(target); // 定义透明度, 默认为不透明 this.opacity = opacity || 1; // 获取菜单 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'); this.util.setStyle(this.body, 'overflow', 'hidden'); 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); }, /** * 激活方法 * 当鼠标移动到菜单标题是激活 */ activate: function() { // 获取当前菜单体的位置 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, 'left', left + 'px'); this.util.setStyle(this.body, 'top', top + 'px'); this.util.setStyle(this.body, 'visibility', 'visible'); this.util.setStyle(this.body, 'opacity', this.opacity); this.util.setStyle(this.body, 'filter', 'alpha(opacity=' + this.opacity * 100 + ')'); }, /** * 解除方法 * 当鼠标移动出菜单标题是激活 */ deactivate: function(){ // 定义解除时样式 this.util.setStyle(this.body, 'visibility', 'hidden'); }, /** * 监听方法 * element: 监听对象 * name: 监听方法 * observer: 执行的方法 * useCapture: 浏览器调用事件的方式 (true 为 Capture 方式, false 为 Bubbling 方式) */ addListener: function(element, name, observer, useCapture) { if(element.addEventListener) { element.addEventListener(name, observer, useCapture); } else if(element.attachEvent) { element.attachEvent('on' + name, observer); } } } /** 一些实用的方法 */ var MenuUtil = Class.create(); MenuUtil.prototype = { initialize: function() { }, $: function(id) { return document.getElementById(id); }, $A: function(iterable) { if(!iterable) { return []; } if(iterable.toArray) { return iterable.toArray(); } else { var results = []; for(var i = 0; i < iterable.length; i++) { results.push(iterable[i]); } return results; } }, bind: function() { var array = this.$A(arguments); var func = array[array.length - 1]; var _method = func, args = array, object = args.shift(); return function() { return _method.apply(object, args.concat(array)); } }, getHeight: function(element) { return element.offsetHeight; }, setStyle: function(element, key, value) { element.style[key] = value; }, getStyle: function(element, key) { return element.style[key]; }, cleanWhitespace: function(list) { var node = list.firstChild; while (node) { var nextNode = node.nextSibling; if(node.nodeType == 3 && !/\S/.test(node.nodeValue)) { list.removeChild(node); } node = nextNode; } return list; }, cumulativeOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; } while (element); return [valueL, valueT]; } } /** 添加到页面加载事件 */ window.onload = function(e) { new MenuList('menus', 0.9); }
演示主题:
以 WordPress 自带主题 default 为基础, 仅做学习参考使用, 修改过的文件有 header.php 和 style.css, 添加了文件 js/menu.js
下载主题: default_with_menubar_2.zip
下回预告:
下回我们要进入淡出淡入导航菜单的话题. 页面代码和 CSS 会沿用这次的结果, 要修改的只是 JavaScript 代码. 主要修改激活和解除两个方法, 有兴趣的同学可以预习一下. ![]()
看到代码就头疼,试试看怎么样,谢谢博主分享
你好,我想问一下,如果想把多级导航菜单做成鼠标点击才显示的应该怎么做呢?因为iPad上不能hover,所以会出现卡死现象,点开了就关不掉了。
我下个问下 你这个JS怎么获取菜单对象的
@mg12
不好意思,没认真看代码,只看了演示的代码,以为链接是javascript:void(0);代码。
我弄了试试。
@Adolph
这么如何不利爬虫爬取了? 请指教.
哥,能搞隔CSS的么?这个js的不利于SEO优化哦,不利于搜索引擎爬取收录。
我直接把您头部的的一些代码copy过去 再加上css +js
可是发现导航依次紧贴着左边向下排列 那个鼠标移到到一级页面才显示二级页面倒是实现了
主要我的css方面不大会..。。。。
很强,拜读。
哇,这里可真热闹,谢谢您的主题.节日快乐
mg12,滚动2级菜单,如果想二级菜单横向,应该怎么修改呢。
@mg12
已经没问题了:)
@Sunxc
Highslide4WP
@metoit
什么叫 "单页单页" 的?
@Rui
? 没有红点啊
@Jimay
能用上就好.
道理没弄懂,我是个直接拿来主义者。用了那个menu.js,说点小经验:开始的时候,menu.js被我放到 head 里面去了,结果没显示出来(我用的YO2就没效果,本地测试却有,不然我还以为是有问题呢),后来放到 header.php的末尾载入就没事了。
我用的主题是加了 jQuery 的,所以在 menu.js 最后那里 window.load 函数里用了 jQuery('#menus a').removeAttr('title'); 这个语句,搞定了把分类放到菜单里面的会出现提示(tooltip)这个有点恼人的问题,菜单不需要提示的吧。要去掉这个提示还真让我花了不少功夫才找到办法,没法啊,水平太菜。
@大胖小
没有设置头像吧?FF里图像刷不出来就是红点。
为什么我的头像是个红点。。。郁闷
向站长学习
这样菜单出来后,内容都是单页单页的哦...
正是我需要的 谢谢了
顺便问下 那个表情是什么插件啊 有意思
……的确不同。
但由于我不知道 CSS 的该从何说起, IE 处理相当麻烦,……/blockqoute>
话说最近用到div的hover,最后在 IE6 用行为解决了,嘎嘎~
@fan
最近没激情弄, 过一段时间吧. 原理差不多的.
老兄,能否再做个三级菜单的淡出版本,不胜感激!
对于我来讲较复杂。作者能不能帮助实现二级导航的功能啊。谢谢!
@sand
OK, 到时讨论讨论.
因为项目比较赶,
我用了htmldog上关于制作二级菜单的例子,
站子上线了再跟你说。
很喜欢你的滑动菜单的教程!:P
“是什么不是什么……”原来我写的标签被屏蔽了:P
就是二级的ul并没有加上class="children"标记,只纯粹只是<ul>。
因为还在做本地测试,所以没办法给到链接你:(
今天我也测试了一下,FF和IE确实可以,不过Google新出的Chrome貌似还没得到jQuery的支持,还是通过onload来处理的。
@JAY
看了一下 jQuery 的源代码, 它是分开不同浏览器进行处理的. 最后如果全部条件都不满足的话, 就是用 onload 操作.
应该都可以用吧,jQuery里面的$(document).ready就是这样做的,但是具体怎么处理平台相关的没有细看。在别的浏览器上应该都可以,可能方法不一样。
Opp! 这个好像是 IE Only 的.
@JAY
对可以这样, 我竟然没想到, 谢了.
你可以在onreadystatechange回调里面判断document.readyState == "loaded",这样只要源代码加载完毕,即DOM创建完毕就可以开始处理。
window.onload是要等所有的东西都加载完,包括图片那些,会比较慢。
@sand
是什么? 而不是什么?
希望您能留个网址, 我去看看什么情况.
children 是自动生成的, 没这 className 也行, 改一下 CSS 就行了.
嗨~mg12
我试着加上了你这段代码(我用在page而不是category,相应的cat_item也改过来了),
但是生成的二级是
而不是
我搜了你的代码,但找不到你在哪里定义它为children的,
请问可以怎样解决哈:D
@向右
可能会.
这个好~ 会不会集成到下一个主题去?
@leojn
是的, 你被插件 spam 了.
@JAY
不太明白你的意思.
document.readyState != "loaded" 只是判断状态而已.
window.onload 会在页面加载完之后调用.
这个效果应该要比
好吧
真详细:)
恩, 我会使用搜索.. 我只要记住你 blog 有这么篇文就 ok 了..
JS 和 Java 根本就不是一回事.. 拜托..
JS和Java有些地方不同, 很不爽
刚才是不是又成垃圾评论了.换个名字试试
看来要恶补一下js了,以前对js就没花多少心思。
这么快就出来了.我学着试试
@漫漫鱼
我当做笔记.
@icyleaf
其实我对 JavaScript 也有点畏惧, 写代码的时候尤为谨慎.
@锐风
哈! 你要记住地址, 或许以后会有用, 呵呵~
哈, 用不到.
这篇教程值得我学习....一直是我的弱项。
坐沙发了!技巧性文章