虽然这不是多么高深的技术,但对于新手来说还是颇有难度。如果你是一个新手,我希望你能从本文中学到东西;如果你是高手,我希望你能留下你宝贵的意见和建议
一.要做什么插件?
我想要实现一个可以在网站或WEB应用系统中使用,可以灵活的定制外观、简单、易于使用、方便扩展、稳定的菜单插件。它可以被用在网站主导航条上,亦可以用在管理后台。
二.想要的效果是什么?
平时菜单处于收起状态,当鼠标移入显示其下级菜单,以此类推;可以方便的使用html标签设置菜单的结构,也可以使用数组动态生成。
三.设计一下功能
菜单项默认的状态。
拥有下级菜单且鼠标移入时的状态。
间隔(起到分组的效果)
拥有下级菜单,鼠标未移入时的状态。
竖排拥有下级菜单且鼠标移入时的状态。
获得焦点时的状态。
其他功能
菜单所有状态的样式均通过CSS控制,可以根据需要灵活修改。
通过HTML和javascript两种方式生成菜单。
为菜单项指定点击回调函数和跳转地址(当指定回调函数时,不设置URL地址,而是将URL地址传入回调函数)。
四.如何实现功能?
1.使用CSS样式控制外观。
*为了避免CSS命名冲突,我们需要为插件确定一个名字空间,其下所有样式都在该命名空间下。
2.菜单标签的选择
*一般来说实现菜单的标签多数会选择列表标签<ul><li></li></ul>来实现,我们也不例外。
菜单项:<li><a href="链接地址"><span>菜单项显示名称</span></a></li>
3.控制UL标签的显示方式
*使用CSS去掉符号和缩进
*使用CSS横向排列,横向排列有两种方法:
(1).用的比较多的是浮动排列(float:left;);但是这种方式有个最大的问题是会破坏页面结构,我不是很喜欢这种方式。
(2).使用内联(display:inline-block)的方式;目前已知的问题是低版本浏览器可能支持的不太好,这个问题网络上有专门的文章讨论,这里我就不再赘述了。
*当我在使用这种方式是出现了一个小问题,就是块与块之间有大概10px的空隙。我删除掉HTML代码里标签之间的空隙(换行)后,这些空隙消失了;这虽然可以解决问题,但是缺破坏了代码的结构,可读性差;如果是动态生成的还能接受。所以我想到了另一种解决办法,那就是设置每一个块(<li>标签)的的左边距为-10px;同时设置<ul>的左内距为10px,perfect!!!
五.浏览器兼容
未在IE6和IE7下进行相关测试。
六.功能实现和调用
样式控制
View Code /*为了避免命名冲突,我们将该插件所有样式都放在该类之下*/ .ctcx-menu { font-size:14px; } .ctcx-menu ul { list-style-type:none; margin:0; padding:0; } /*设置偏移量*/ .ctcx-menu ul.offset { position:relative; top:-32px; left:100px; } .ctcx-menu ul li /*菜单项样式*/ { width:100px; height:30px; line-height:30px; text-align:center; vertical-align:top; margin:0; padding:0; } /*菜单项样式*/ .ctcx-menu a { display:block; height:100%; border:1px solid #999; background-color:#FFF; text-decoration:none; color:#000; } .ctcx-menu a:hover { background-color:#999; color:#FFF; } .ctcx-menu a:active{} /*横向菜单*/ .ctcx-menu .horizontal { padding-left:7px; } .ctcx-menu .horizontal li { display:inline-block; margin-left:-7px; } .ctcx-menu .horizontal li.item-has-children > a /*拥有子菜单的菜单项样式*/ { } .ctcx-menu .horizontal li.spacing /*横向间隔*/ { height:30px; width:10px; background-color:#000; } /*竖向菜单*/ .ctcx-menu .vertical { } .ctcx-menu .vertical li { margin-left:0px; } .ctcx-menu .vertical li.item-has-children > a /*拥有子菜单的菜单项样式*/ { } .ctcx-menu .vertical li.spacing /*纵向间隔*/ { height:10px; width:100px; background-color:#000; }
插件代码
View Code (function ($) { $.fn.menu = function (options) { if (typeof options != 'undefined' && options.constructor === Array) options = { data: options }; var opts = $.extend({}, $.fn.menu.defaults, options); var _tempMenuData = []; //返回数据级别 function getLevel(id) { var _level = 0; var _o = getMenuData(id); while (_o != null) { _level++; _o = getMenuData(_o.pid); } return _level; } //返回数据对象 function getMenuData(id) { for (var i = 0; i < opts.data.length; i++) { if (opts.data[i].id == id) return opts.data[i]; } return null; } //返回生成的HTML function getHtml(pid) { var _li_data = getData(pid); if (_li_data.length == 0) return null; var _ul = $('<ul></ul>'); $.each(_li_data, function (i, _d) { var _children = getHtml(_d.id); var _li = $('<li></li>').appendTo(_ul); if (_d.n == null || _d.n.length == 0) { _li.addClass('spacing'); } else if (typeof _d.fn === 'function') { $('<a href="javascript:;"></a>').html(_d.n) .click(function () { _d.fn(_d.url); }).appendTo(_li); } else if (_d.url.length > 0) { $('<a href="' + _d.url + '"></a>').html(_d.n).appendTo(_li); } if (_children != null) { _li.addClass('item-has-children'); _children.appendTo(_li); _li.bind({ mouseover: function () { _children.show(); }, mouseout: function () { _children.hide(); } }); } }) if (pid == null && opts.type == 1) { _ul.addClass('horizontal'); } else { var _level = getLevel(pid); _level > 0 && _ul.hide(); _ul.addClass('vertical'); if (_level > opts.type) _ul.addClass('offset'); } return _ul; } //返回下级数据数组 function getData(pid) { var _data = []; _tempMenuData = $.grep(_tempMenuData, function (_d) { if (_d.pid == pid) { _data.push(_d); return true; } return false; }, true); return _data; } return this.each(function () { var me = $(this); me.addClass('ctcx-menu'); if (opts.data != null && opts.data.length > 0) { $.merge(_tempMenuData, opts.data); me.append(getHtml(null)); } else { me.find('.item-has-children').each(function () { var self = $(this); var _ul = self.children('ul'); _ul.hide(); self.bind({ mouseover: function () { _ul.show(); }, mouseout: function () { _ul.hide(); } }); }); } }); } //设置默认参数 $.fn.menu.defaults = { type: 1, //菜单的显示方式(主要是指第一级是横向还是纵向,默认横向1,纵向0) /* data:动态生成菜单的数组数据,如果指定的此数据则会以此数据填充菜单(菜单内原有数据被替代) 数据格式:[menu,menu,...] menu对象格式:{ id: 1, pid: null, n: '菜单名称1', url: '#', fn:回调函数 } */ data: null } })(jQuery);
调用JS代码
View Code $(function () { var _menuData = [ { id: 1, pid: null, n: '菜单名称1', url: '#' }, { id: 2, pid: null, n: '菜单名称2', url: '#' }, { id: 3, pid: null, n: '菜单名称3', url: '#' }, { id: 4, pid: null, n: '菜单名称4', url: '#' }, { id: 5, pid: null, n: '菜单名称5', url: '#' }, { id: 6, pid: 3, n: '菜单名称6', url: '#' }, { id: 7, pid: 3, n: '菜单名称7', url: '#' }, { id: 8, pid: 3, n: '菜单名称8', url: '#' }, { id: 9, pid: 3, n: '菜单名称9', url: '#' }, { id: 10, pid: 9, n: '菜单名称10', url: '#' }, { id: 11, pid: 9, n: '菜单名称11', url: '#' }, { id: 12, pid: 9, n: '菜单名称12', url: '#' }, { id: 13, pid: 9, n: '菜单名称13', url: '#' }, { id: 14, pid: 13, n: '菜单名称14', url: '#' }, { id: 15, pid: 1, n: '菜单名称15', url: '#' } ]; $('#dynamic-menu1').menu({ type: 0, data: _menuData }); $('#dynamic-menu2').menu(); $('#dynamic-menu3').menu(); });
HTML
View Code <div id="dynamic-menu3" class="ctcx-menu"> <ul class="horizontal"> <li><a href="#"><span>一级菜单1</span></a></li> <li><a href="#"><span>一级菜单2</span></a></li> <li class="item-has-children"> <a href="#"><span>一级菜单3</span></a> <ul class="vertical"> <li><a href="#"><span>二级菜单1</span></a></li> <li><a href="#"><span>二级菜单2</span></a></li> <li><a href="#"><span>二级菜单3</span></a></li> <li class="item-has-children"> <a href="#"><span>二级菜单4</span></a> <ul class="vertical offset"> <li><a href="#"><span>三级菜单1</span></a></li> <li><a href="#"><span>三级菜单2</span></a></li> <li><a href="#"><span>三级菜单3</span></a></li> <li><a href="#"><span>三级菜单4</span></a></li> <li><a href="#"><span>三级菜单5</span></a></li> </ul> </li> <li><a href="#"><span>二级菜单5</span></a></li> </ul> </li> <li><a href="#"><span>一级菜单4</span></a></li> <li><a href="#"><span>一级菜单5</span></a></li> </ul> </div> <div id="dynamic-menu1" class="ctcx-menu" style="margin-top:30px;"></div> <div id="dynamic-menu2" class="ctcx-menu" style="margin-top:60px;"> <ul class="vertical"> <li><a href="#"><span>一级菜单1</span></a></li> <li><a href="#"><span>一级菜单2</span></a></li> <li class="item-has-children"> <a href="#"><span>一级菜单3</span></a> <ul class="vertical offset"> <li><a href="#"><span>二级菜单1</span></a></li> <li><a href="#"><span>二级菜单2</span></a></li> <li><a href="#"><span>二级菜单3</span></a></li> <li class="item-has-children"> <a href="#"><span>二级菜单4</span></a> <ul class="vertical offset"> <li><a href="#"><span>三级菜单1</span></a></li> <li><a href="#"><span>三级菜单2</span></a></li> <li><a href="#"><span>三级菜单3</span></a></li> <li><a href="#"><span>三级菜单4</span></a></li> <li><a href="#"><span>三级菜单5</span></a></li> </ul> </li> <li><a href="#"><span>二级菜单5</span></a></li> </ul> </li> <li><a href="#"><span>一级菜单4</span></a></li> <li><a href="#"><span>一级菜单5</span></a></li> </ul> </div>
七.下载
点击这里 下载使用例子,和所有文件。
学习从实践开始之jQuery插件开发 菜单插件开发
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@