读源码 | metisMenu侧边栏插件
—————————————————————————————————————————————————————————
使用方法
实现效果
引入文件
<link rel="stylesheet" href="vendor/bootstrap/css/bootstrap.css"> // bootstrap样式
<link href="vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css"> // 图标使用font-awesome
<link rel="stylesheet" href="vendor/metisMenu/metisMenu.css"> // 插件样式
<script src="vendor/jquery/jquery.js"></script> // 基于jquery实现
<script src="vendor/bootstrap/js/bootstrap.min.js"></script> // 使用bootstrap的collapse插件
<script src="vendor/metisMenu/metisMenu.min.js"></script> // 插件代码
调用方法
<script type="text/javascript">
$(function() {
$('#side-menu').metisMenu(); // ul.nav#side-menu
})
</script>
使用样例
<<Demo.html>>
<nav class="navbar navbar-default navbar-static-top">
<div class="navbar-default sidebar" role="navigation">
<div class="sidebar-nav navbar-collapse">
<ul class="nav" id="side-menu">
<li class="sidebar-search">
<div class="input-group custom-search-form">
<input type="text" class="form-control" placeholder="Search...">
<span class="input-group-btn">
<button class="btn btn-default" type="button">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</li>
<li>
<a href=""><i class="fa fa-dashboard fa-fw"></i> Dashboard</a>
</li>
<li>
<a href="#"><i class="fa fa-bar-chart-o fa-fw"></i> Charts<span
class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li>
<a href="">Flot Charts</a>
</li>
<li>
<a href="">Morris.js Charts</a>
</li>
</ul>
</li>
<li>
<a href=""><i class="fa fa-table fa-fw"></i> Tables</a>
</li>
<li>
<a href=""><i class="fa fa-edit fa-fw"></i> Forms</a>
</li>
<li>
<a href="#"><i class="fa fa-wrench fa-fw"></i> UI Elements<span
class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li>
<a href="">Panels and Wells</a>
</li>
<li>
<a href="">Buttons</a>
</li>
<li>
<a href="">Notifications</a>
</li>
<li>
<a href="">Typography</a>
</li>
<li>
<a href=""> Icons</a>
</li>
<li>
<a href="">Grid</a>
</li>
</ul>
</li>
<li>
<a href="#"><i class="fa fa-sitemap fa-fw"></i> Multi-Level Dropdown<span
class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li>
<a href="#">Second Level Item</a>
</li>
<li>
<a href="#">Second Level Item</a>
</li>
<li>
<a href="#">Third Level <span class="fa arrow"></span></a>
<ul class="nav nav-third-level">
<li>
<a href="#">Third Level Item</a>
</li>
<li>
<a href="#">Third Level Item</a>
</li>
<li>
<a href="#">Third Level Item</a>
</li>
<li>
<a href="#">Third Level Item</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="active">
<a href="#"><i class="fa fa-files-o fa-fw"></i> Sample Pages<span
class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li>
<a class="active" href="#">Blank Page</a>
</li>
<li>
<a href="#">Login Page</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<<blank.css>>
@media (min-width: 768px) {
.sidebar {position: absolute;width: 250px;margin-top: 51px;z-index:;}
}
.sidebar .sidebar-search {padding: 15px;}
.sidebar ul li a.active {background-color: #eee;}
.sidebar ul li {background: #f8f8f8;border-bottom: #e7e7e7 1px solid;}
.nav-second-level li {border-bottom: 0 !important;}
.nav-second-level li a {padding-left: 38px;}
树形图
p.s.自定义样式用下划线表示
—————————————————————————————————————————————————————————
源码解读
调用
使用$.fn.extend(object)的方式为jquery类添加成员方法,功能封装在原型中,能够全局调用;
通过$("#side-menu")生成的jquery类实例来调用该方法;
初始配置
全局定义插件名称pluginName,定义对象defaults存放toggle(展开/闭合)与doubleTapToGo(双击事件)的开关;
样式
使用font-awesome来扩展侧边栏图标和展开标识(三角),引入font-awesome.css后只需要通过i.fa.fa-***来调用就可以了
基础布局通过bootstrap类实现,详细分支情况见属性图
初始化展开
借助bootstrap内置的collapse插件来实现;
通过检测<li.active>来标识当前页对应的列表,在metisMenu.js中检查是否需要展开的列表;
判断激活的标签栏是否有子列表,如果有则添加.collapse.in类(bootstrap.css),实际为添加样式{display:block};
未被激活的标签栏如果有子列表则添加.collapse类(boostrap.css),{display:none};
监听点击事件
监听方法借助bootstrap的collapse插件;
绑定事件时需要遵循collapse插件规则.on("click"+"."+pluginName,function(e){});
为点击的标签栏添加激活样式.active,如果有子列表则展开/关闭,使用collapse插件方法.collapse("toggle");
闭合其他所有有子列表的标签栏,使用.collapse("hide");
—————————————————————————————————————————————————————————
简单版 v1.0
功能
仅实现基础效果
复写代码
<<metisMenu-demo1.js>>
/**
* Created by hughd on 2017/8/9.
* 简单版 - v1.0
* 仅实现基础折叠
*/
;(function ($, window, document, undefined) {
var pluginName = "metisMenu";
var toggle = true; function Plugin(element, options) {
this.element = $(element);
this.init();
} Plugin.prototype = {
init: function () {
var $this = this.element;
// var obj = this;
$this.find("li.active").has("ul").children("ul").addClass('collapse in');// 初始激活的元素的后代全部展开
$this.find('li').not(".active").has("ul").children("ul").addClass('collapse');// 未激活的元素显示隐藏
// 监听点击事件
$this.find("li").children("a").on("click." + pluginName, function () {
//被点击的元素激活样式并展开
$(this).parent('li').toggleClass('active').children("ul").collapse("toggle");
if (toggle) {
//将其他被展开的元素闭合
$(this).parent("li").siblings().removeClass("active").children("ul").collapse("hide");
}
});
}
}
$.fn[pluginName] = function (options) {
// 实例化Plugin对象,并存放在元素<ul#side-menu>._proto_.metisMenu中
this.data(pluginName, new Plugin(this, options));
return this;
}
})(jQuery, window, document);
实现思路
- 初始化
获取当前激活的标签,将该标签的内容显示(如果没有子标签则不显示)
未激活的标签,所有子列表隐藏
- 点击事件(通过boostrap的collapse插件)
当前点击的标签获取激活样式,子列表展开
除点击标签之外的其他标签移除激活样式,并闭合
—————————————————————————————————————————————————————————
完整插件
功能
IE浏览器兼容情况;
移除已有metisMenu数据情况
双击标题事件
源码
<<metisMenu.js>>
/*
* metismenu - v1.1.3
* Easy menu jQuery plugin for Twitter Bootstrap 3
* https://github.com/onokumus/metisMenu
*
* Made by Osman Nuri Okumus
* Under MIT License
*/
;(function($, window, document, undefined) { var pluginName = "metisMenu",
defaults = {
toggle: true,
doubleTapToGo: false
}; function Plugin(element, options) {
this.element = $(element);
this.settings = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
} Plugin.prototype = {
init: function() { var $this = this.element,
$toggle = this.settings.toggle,
obj = this; if (this.isIE() <= 9) {
$this.find("li.active").has("ul").children("ul").collapse("show");
$this.find("li").not(".active").has("ul").children("ul").collapse("hide");
} else {
$this.find("li.active").has("ul").children("ul").addClass("collapse in");
$this.find("li").not(".active").has("ul").children("ul").addClass("collapse");
} //add the "doubleTapToGo" class to active items if needed
if (obj.settings.doubleTapToGo) {
$this.find("li.active").has("ul").children("a").addClass("doubleTapToGo");
} $this.find("li").has("ul").children("a").on("click" + "." + pluginName, function(e) {
e.preventDefault(); //Do we need to enable the double tap
if (obj.settings.doubleTapToGo) { //if we hit a second time on the link and the href is valid, navigate to that url
if (obj.doubleTapToGo($(this)) && $(this).attr("href") !== "#" && $(this).attr("href") !== "") {
e.stopPropagation();
document.location = $(this).attr("href");
return;
}
} $(this).parent("li").toggleClass("active").children("ul").collapse("toggle"); if ($toggle) {
$(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide");
} });
}, isIE: function() { //https://gist.github.com/padolsey/527683
var undef,
v = 3,
div = document.createElement("div"),
all = div.getElementsByTagName("i"); while (
div.innerHTML = "<!--[if gt IE " + (++v) + "]><i></i><![endif]-->",
all[0]
) {
return v > 4 ? v : undef;
}
}, //Enable the link on the second click.
doubleTapToGo: function(elem) {
var $this = this.element; //if the class "doubleTapToGo" exists, remove it and return
if (elem.hasClass("doubleTapToGo")) {
elem.removeClass("doubleTapToGo");
return true;
} //does not exists, add a new class and return false
if (elem.parent().children("ul").length) {
//first remove all other class
$this.find(".doubleTapToGo").removeClass("doubleTapToGo");
//add the class on the current element
elem.addClass("doubleTapToGo");
return false;
}
}, remove: function() {
this.element.off("." + pluginName);
this.element.removeData(pluginName);
} }; $.fn[pluginName] = function(options) {
this.each(function () {
var el = $(this);
if (el.data(pluginName)) {
el.data(pluginName).remove();
}
el.data(pluginName, new Plugin(this, options));
});
return this;
}; })(jQuery, window, document);
<<metisMenu.css>>
/*
* metismenu - v1.1.3
* Easy menu jQuery plugin for Twitter Bootstrap 3
* https://github.com/onokumus/metisMenu
*
* Made by Osman Nuri Okumus
* Under MIT License
*/
.arrow {
float: right;
line-height: 1.42857;
} .glyphicon.arrow:before {
content: "\e079";
} .active > a > .glyphicon.arrow:before {
content: "\e114";
} /*
* Require Font-Awesome
* http://fortawesome.github.io/Font-Awesome/
*/ .fa.arrow:before {
content: "\f104";
} .active > a > .fa.arrow:before {
content: "\f107";
} .plus-times {
float: right;
} .fa.plus-times:before {
content: "\f067";
} .active > a > .fa.plus-times {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
} .plus-minus {
float: right;
} .fa.plus-minus:before {
content: "\f067";
} .active > a > .fa.plus-minus:before {
content: "\f068";
}
读源码 | metisMenu侧边栏插件的更多相关文章
- 读源码【读mybatis的源码的思路】
✿ 需要掌握的编译器知识 ★ 编译器为eclipse为例子 调试准备工作(步骤:Window -> Show View ->...): □ 打开调试断点Breakpoint: □ 打开变量 ...
- [一起读源码]走进C#并发队列ConcurrentQueue的内部世界
决定从这篇文章开始,开一个读源码系列,不限制平台语言或工具,任何自己感兴趣的都会写.前几天碰到一个小问题又读了一遍ConcurrentQueue的源码,那就拿C#中比较常用的并发队列Concurren ...
- Java读源码之ReentrantLock
前言 ReentrantLock 可重入锁,应该是除了 synchronized 关键字外用的最多的线程同步手段了,虽然JVM维护者疯狂优化 synchronized 使其已经拥有了很好的性能.但 R ...
- Java读源码之ReentrantLock(2)
前言 本文是 ReentrantLock 源码的第二篇,第一篇主要介绍了公平锁非公平锁正常的加锁解锁流程,虽然表达能力有限不知道有没有讲清楚,本着不太监的原则,本文填补下第一篇中挖的坑. Java读源 ...
- Java读源码之CountDownLatch
前言 相信大家都挺熟悉 CountDownLatch 的,顾名思义就是一个栅栏,其主要作用是多线程环境下,让多个线程在栅栏门口等待,所有线程到齐后,栅栏打开程序继续执行. 案例 用一个最简单的案例引出 ...
- 阅读源码很重要,以logback为例,分享一个小白都能学会的读源码方法
作为一个程序员,经常需要读一些开源项目的源码.同时呢,读源码对我们也有很多好处: 1.提升自己 阅读优秀的代码,第一可以提升我们自身的编码水平,第二可以开拓我们写代码的思路,第三还可能让我们拿到大厂 ...
- WeMall微信商城源码活动报名插件代码详情
WeMall微信商城源码插件活动报名代码是用于商业推广的比较有效的方式,分享了部分比较重要的代码,供技术员学习参考,商家可自由设置报名项目,活动时间,报名内容 代码详情地址:http://addon. ...
- 【MyBatis源码分析】插件实现原理
MyBatis插件原理----从<plugins>解析开始 本文分析一下MyBatis的插件实现原理,在此之前,如果对MyBatis插件不是很熟悉的朋友,可参看此文MyBatis7:MyB ...
- 跟大佬一起读源码:CurrentHashMap的扩容机制
并发编程——ConcurrentHashMap#transfer() 扩容逐行分析 前言 ConcurrentHashMap 是并发中的重中之重,也是最常用的数据结构,之前的文章中,我们介绍了 put ...
随机推荐
- C#遍历系统所安装的打印机,使用WMI方式获取打印机的所有属性
有网友发消息来询问,C#如何遍历系统已经安装的所有打印机,并获得每个打印机的相关信息,如:端口,名称等等 C#里面,虽然在 System.Drawing.Printing 这个namespace下,提 ...
- linu下修改mysql数据库面
修改密码:1.例如你的 root用户现在没有密码,你希望的密码修改为123456,那么命令是:mysqladmin -u root password 1234562.如果你的root现在有密码了(12 ...
- arcgis10.5新功能图形缓冲
摘要 在输入要素周围某一指定距离内创建缓冲区多边形.在要素周围生成缓冲区时,大部分制图形状对缓冲区末端(端头)和拐角(连接)可用. 插图
- 如何停止一个正在运行的java线程
与此问题相关的内容主要涉及三部分:已废弃的Thread.stop().迷惑的thread.interrupt系列.最佳实践Shared Variable. 已废弃的Thread.stop() @Dep ...
- 基于nginx实现protobuf RPC
老婆一起来上海工作,每个月消费立马上来了,做了一个android记账应用,把每笔帐都实时记录进去.开始是单机版的,只能两个人分别记,月底再merge一下.刚好有一台阿里云的ECS,于是准备升级为带服务 ...
- ING【转载】epoll总结系列
epoll的总结之一基本的参数设置 http://fpcfjf.blog.163.com/blog/static/55469793201452095738566/?suggestedreading&a ...
- 【Gson】简介 文档 基本使用 示例
简介 new TypeToken<List<Person>>() {}.getType() 1 1 1 new TypeToken<List<Person> ...
- RecyclerView 判断滑到底部 顶部 预加载 更多 分页 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- python中的exec()、eval()以及complie()
参考博客:http://www.cnblogs.com/yyds/p/6276746.html 1.eval函数 函数的作用: 计算指定表达式的值.也就是说它要执行的python代码只能是单个表达式( ...
- GO语言基础语法
1. Go项目的目录结构 一般的,一个Go项目在GOPATH下,会有如下三个目录: project --- bin --- pkg --- src 其中,bin 存放编译后的可执行文件:p ...