导航菜单
导航菜单早已 深入民心, 在博客上的应用日益重要且多样. 从本文开始, 我将开展几个关于 wordpress 导航菜单的话题, 讨论如何在 wordpress 上使用和加强导航菜单, 话题间有一定的承接关系, 难度也会逐步增加.
wordpress 上的导航菜单一般有两种, 页面导航菜单和分类导航菜单.
可曾记得? wordpress 是可以撰写独立页面的, 页面导航菜单就是以首页和各个独立页面组成的菜单. 而分类导航菜单则是以首页和各个分类组成的菜单.
这是效果演示
既然菜单由首页和独立页面列表或首页和分类列表所组成, 我们就需要处理两个环节, 即首页菜单项和其他菜单项.
另外, 我们还需要处理菜单项的三个状态, 即一般状态, 当前菜单项状态 (如: 在首页中, 首页菜单项就是当前菜单项) 和选中菜单项状态.
也就是说, 我们共需要处理 3 个事情:
1. 首页外的其他菜单项
2. 首页菜单项
3. 菜单项处于不同状态时的视觉效果
预想结构:
home 菜单项1 菜单项2 菜单项3 ...
页面导航菜单
1. 独立页面列表作为菜单项
调用 wp_list_pages 获取独立页面列表, 并使用以下参数:
depth: 列表深度(层的最大数量), 本文讨论的是一级菜单, 故最大深度为 1
title_li: 标题字符串, 这里不需要, 设为 0
sort_column: 列表项的排序方式, 根据创建页面时所设定的 order 进行升序排列
打印独立页面菜单项的语句是:
2. 首页菜单项
由于一般独立页面的 class 是 page_item, 当前独立页面的 class 是 current_page_item. 当页面是首页时, 首页菜单项的 class 应该是 current_page_item, 其他情况则是 page_item. 为此, 我们需要一段分支代码来为它确定 class:
打印首页菜单项的语句是:
home
3. 菜单的样式
这是一个从普遍到特殊的处理过程, 一般菜单项的样式放前面, 当前和选中菜单项的样式放在后面, 当后者条件满足就会覆盖前者的样式, 从而改变外观.
/* 菜单项 */#menubar ul.menus li { float:left; /* 靠左浮动 */ list-style:none; /* 清空列表风格 */ margin-right:1px; /* 右侧的间隔 */}/* 菜单项链接 */#menubar ul.menus li a { padding:5px 10px; /* 内边距 */ display:block; /* 显示为块 */ color:#fff; /* 文字颜色 */ background:#67ace5; /* 背景颜色 */ text-decoration:none; /* 没有下横线 */}/* 当前菜单项链接 */#menubar ul.menus li.current_page_item a { background:#5495cd; /* 背景颜色 */}/* 选中菜单项链接 */#menubar ul.menus li a:hover { background:#4281b7; /* 背景颜色 */}
分类导航菜单
1. 分类列表作为菜单项
调用方法 wp_list_categories 获取分类列表, 并使用以下参数:
depth: 列表深度(层的最大数量), 本文讨论的是一级菜单, 故最大深度为 1
title_li: 标题字符串, 这里不需要, 设为 0
orderby: 列表项的排序方式, 根据创建页面时所设定的 order 进行升序排列
show_count: 是否显示该分类的文章数量, 这里不需要显示, 设为 0
打印分类菜单项的语句是:
2. 首页菜单项
与页面导航菜单相似, 只是菜单项的 class 有所不同.
page_item 更改为 cat-item
current_page_item 更改为 current-cat
3. 菜单的样式
因为菜单项的 class 略有不同, 所以也需稍作修改.
current_page_item 更改为 current-cat
二级导航菜单
我们已经知道菜单如何创建了, 这回我们要使用分类列表做成二级导航菜单. 我们要做的其实是在原有的基础上改出二级菜单, 以及对二级菜单进行处理. (请确保的的分类中包含子分类, 否则调不出二级菜单.)
我们共需要处理 3 个事情:
1. 调出二级菜单 (子分类)
2. 二级菜单的样式
3. 二级菜单的效果
预想结构
home 菜单1 菜单项1 菜单项2 菜单项3 菜单2 菜单项4 菜单3 菜单项5 菜单项6 ...
实施操作
1. 调出二级菜单 (子分类)
是否还记得制作导航菜单时是如何设定列表深度的? 当时将深度设为 1 是为了不显示子分类, 现在要二级子分类当然要将深度设为 2 了.
depth: 列表深度(层的最大数量), 本文讨论的是二级菜单, 故最大深度为 2.
打印分类菜单项的语句是:
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 来说十分很重要 */}
打印首页菜单项的语句是:
home
3. 二级菜单的效果
全部使用 javascript 实现, 为便于理解, 使用面向对象方式编写代码, 借鉴了部分 prototype 框架的代码. 因为代码比较多, 不适合逐句解说, 所以我已标上了大量注释. 代码不是很复杂, 有 js 基础的话应该不会存在障碍.
另外为了迎合个别人的口味, 加上透明效果. enjoy!
/* author: mg12feature: menulist with second-level menusupdate: 2008/08/30tutorial 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);}
