bootstrap之dropdown
来源:互联网 发布:微信打开未备案域名 编辑:程序博客网 时间:2024/05/17 06:32
一、前言
这节介绍下dropdown(下拉菜单)模块的源码实现。
二、源码
1、dropdowns.less
// // Dropdown menus(下拉菜单) // -------------------------------------------------- // Dropdown arrow/caret(下拉菜单箭头) .caret { display: inline-block; width: 0; height: 0; margin-left: 2px; vertical-align: middle; border-top: @caret-width-base dashed; border-top: @caret-width-base solid ~"\9"; // IE8 border-right: @caret-width-base solid transparent; border-left: @caret-width-base solid transparent; } // The dropdown wrapper (div: 下拉菜单容器) .dropup, .dropdown { position: relative; } // Prevent the focus on the dropdown toggle when closing dropdowns .dropdown-toggle:focus { outline: 0; } // The dropdown menu (ul: 下拉菜单) .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: @zindex-dropdown; display: none; // none by default, but block on "open" of the menu float: left; min-width: 160px; padding: 5px 0; margin: 2px 0 0; // override default ul list-style: none; font-size: @font-size-base; text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) background-color: @dropdown-bg; border: 1px solid @dropdown-fallback-border; // IE8 fallback border: 1px solid @dropdown-border; border-radius: @border-radius-base; .box-shadow(0 6px 12px rgba(0,0,0,.175)); background-clip: padding-box; // Aligns the dropdown menu to right(下拉菜单右对齐) // // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]` &.pull-right { right: 0; left: auto; } // Dividers (basically an hr) within the dropdown(下拉分割线) .divider { .nav-divider(@dropdown-divider-bg); } // Links within the dropdown menu(下拉菜单链接) > li > a { display: block; padding: 3px 20px; clear: both; font-weight: normal; line-height: @line-height-base; color: @dropdown-link-color; white-space: nowrap; // prevent links from randomly breaking onto new lines } } // Hover/Focus state(菜单项状态: 悬浮状态、焦点状态) .dropdown-menu > li > a { &:hover, &:focus { text-decoration: none; color: @dropdown-link-hover-color; background-color: @dropdown-link-hover-bg; } } // Active state(当前状态) .dropdown-menu > .active > a { &, &:hover, &:focus { color: @dropdown-link-active-color; text-decoration: none; outline: 0; background-color: @dropdown-link-active-bg; } } // Disabled state(禁用状态) // // Gray out text and ensure the hover/focus state remains gray .dropdown-menu > .disabled > a { &, &:hover, &:focus { color: @dropdown-link-disabled-color; } // Nuke hover/focus effects &:hover, &:focus { text-decoration: none; background-color: transparent; background-image: none; // Remove CSS gradient .reset-filter(); cursor: @cursor-disabled; } } // Open state for the dropdown(展开下拉菜单) .open { // Show the menu > .dropdown-menu { display: block; } // Remove the outline when :focus is triggered > a { outline: 0; } } // Menu positioning(下拉菜单对齐方式) // // Add extra class to `.dropdown-menu` to flip the alignment of the dropdown // menu with the parent.(右对齐) .dropdown-menu-right { left: auto; // Reset the default from `.dropdown-menu` right: 0; } // With v3, we enabled auto-flipping if you have a dropdown within a right // aligned nav component. To enable the undoing of that, we provide an override // to restore the default dropdown menu alignment. // // This is only for left-aligning a dropdown menu within a `.navbar-right` or // `.pull-right` nav component.(左对齐) .dropdown-menu-left { left: 0; right: auto; } // Dropdown section headers(下拉菜单标题) .dropdown-header { display: block; padding: 3px 20px; font-size: @font-size-small; line-height: @line-height-base; color: @dropdown-header-color; white-space: nowrap; // as with > li > a } // Backdrop to catch body clicks on mobile, etc.(背景遮罩层) .dropdown-backdrop { position: fixed; left: 0; right: 0; bottom: 0; top: 0; z-index: (@zindex-dropdown - 10); } // Right aligned dropdowns(右对齐下拉菜单) .pull-right > .dropdown-menu { right: 0; left: auto; } // Allow for dropdowns to go bottom up (aka, dropup-menu) // // Just add .dropup after the standard .dropdown class and you're set, bro. // TODO: abstract this so that the navbar fixed styles are not placed here? .dropup, .navbar-fixed-bottom .dropdown { // Reverse the caret .caret { border-top: 0; border-bottom: @caret-width-base dashed; border-bottom: @caret-width-base solid ~"\9"; // IE8 content: ""; } // Different positioning for bottom up menu .dropdown-menu { top: auto; bottom: 100%; margin-bottom: 2px; } } // Component alignment // // Reiterate per navbar.less and the modified component alignment there. @media (min-width: @grid-float-breakpoint) { .navbar-right { .dropdown-menu { .dropdown-menu-right(); } // Necessary for overrides of the default right aligned menu. // Will remove come v4 in all likelihood. .dropdown-menu-left { .dropdown-menu-left(); } } }
2、dropdown.js
/* ======================================================================== * Bootstrap: dropdown.js v3.3.7(下拉菜单) * http://getbootstrap.com/javascript/#dropdowns * ======================================================================== * Copyright 2011-2016 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // DROPDOWN CLASS DEFINITION // ========================= var backdrop = '.dropdown-backdrop' var toggle = '[data-toggle="dropdown"]' var Dropdown = function (element) { $(element).on('click.bs.dropdown', this.toggle) } Dropdown.VERSION = '3.3.7' // 获取触发按钮或链接的目标元素 function getParent($this) { var selector = $this.attr('data-target') // 如果不存在data-target,那么获取href属性并将格式处理为CSS选择器 if (!selector) { selector = $this.attr('href') selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } // 如果存在目标元素,那么直接选中 var $parent = selector && $(selector) // 否则默认使用触发元素的父元素 return $parent && $parent.length ? $parent : $this.parent() } // 隐藏下拉菜单 function clearMenus(e) { // 如果鼠标右键点击不做任何处理 if (e && e.which === 3) return // 移除背景 $(backdrop).remove() $(toggle).each(function () { var $this = $(this) var $parent = getParent($this) var relatedTarget = { relatedTarget: this } // 如果不是下拉菜单已经展开菜单了,那么不做任何处理 if (!$parent.hasClass('open')) return // 如果事件发生在目标元素中的input/textarea元素中,那么不做任何处理 if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return // 触发开始隐藏菜单事件 $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) if (e.isDefaultPrevented()) return $this.attr('aria-expanded', 'false') // 触发已经隐藏菜单事件 $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) }) } // 切换下拉菜单显示状态 Dropdown.prototype.toggle = function (e) { var $this = $(this) if ($this.is('.disabled, :disabled')) return var $parent = getParent($this) var isActive = $parent.hasClass('open') clearMenus() // 显示下拉菜单 if (!isActive) { // 如果是在移动设备上,那么点击后添加遮罩层 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { // if mobile we use a backdrop because click events don't delegate $(document.createElement('div')) .addClass('dropdown-backdrop') .insertAfter($(this)) .on('click', clearMenus) } var relatedTarget = { relatedTarget: this } $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) if (e.isDefaultPrevented()) return $this .trigger('focus') .attr('aria-expanded', 'true') $parent .toggleClass('open') .trigger($.Event('shown.bs.dropdown', relatedTarget)) } // 返回false,阻止冒泡和默认事件发生;如果是用JS直接触发,而且JS绑定的元素是document的子元素就可以避免绑定触发多次的问题,因为这里返回了false return false } // 键盘事件处理函数 Dropdown.prototype.keydown = function (e) { // 38:Up Arrow; 40:Down Arrow; 27:Esc; 32:Spacebar if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return var $this = $(this) e.preventDefault() e.stopPropagation() if ($this.is('.disabled, :disabled')) return var $parent = getParent($this) var isActive = $parent.hasClass('open') if (!isActive && e.which != 27 || isActive && e.which == 27) { // 如果菜单处于展开状态而且点击esc键盘按钮,那么让触发元素获取焦点 if (e.which == 27) $parent.find(toggle).trigger('focus') // 触发元素上触发点击事件 return $this.trigger('click') } var desc = ' li:not(.disabled):visible a' var $items = $parent.find('.dropdown-menu' + desc) // 如果$items.length == false,说明拓展菜单隐藏,不执行下面操作;否则执行下拉菜单选择,选中菜单触发focus事件 if (!$items.length) return var index = $items.index(e.target) if (e.which == 38 && index > 0) index-- // up if (e.which == 40 && index < $items.length - 1) index++ // down if (!~index) index = 0 $items.eq(index).trigger('focus') } // DROPDOWN PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.dropdown') if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) if (typeof option == 'string') data[option].call($this) }) } var old = $.fn.dropdown $.fn.dropdown = Plugin $.fn.dropdown.Constructor = Dropdown // DROPDOWN NO CONFLICT // ==================== $.fn.dropdown.noConflict = function () { $.fn.dropdown = old return this } // APPLY TO STANDARD DROPDOWN ELEMENTS // =================================== $(document) // 如果点击发生在document上,那么隐藏拓展开的菜单 .on('click.bs.dropdown.data-api', clearMenus) // 如果点击事件发生在下拉菜单元素上,那么阻止冒泡到document上 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) // 如果点击在触发元素上,触发Dropdown.prototype.toggle事件 .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) // 在触发元素上设置键盘监听函数 .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) // 如果是展开状态(只有展开状态才有.dropdown-menu),那么则在展开菜单上也设置监听函数 .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) }(jQuery);
三、应用 & 源码分析
1、应用
<nav class="navbar navbar-default" role="navigation"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="#">菜鸟教程</a> </div> <div> <ul class="nav navbar-nav"> <li class="active"><a href="#">iOS</a></li> <li><a href="#">SVN</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> Java <b class="caret"></b> </a> <ul class="dropdown-menu pull-right"> <li role="presentation" class="dropdown-header">下拉菜单标题</li> <li><a href="#">jmeter</a></li> <li><a href="#">EJB</a></li> <li><a href="#">Jasper Report</a></li> <li class="divider"></li> <li><a href="#">分离的链接</a></li> <li class="divider"></li> <li><a href="#">另一个分离的链接</a></li> </ul> </li> </ul> </div> </div> </nav>
2、源码分析
2.1、dropdowns.less
1、可通过向 .dropdown-menu 添加 class .pull-right 或 .dropdown-menu-right 来向右对齐下拉菜单,默认左对齐
2、可使用 class dropdown-header 向下拉菜单的标签区域添加标题
3、可使用 class disabled 向下拉菜单的标签区域设置禁用项
4、可使用 class divider 向下拉菜单的标签区域设置分割线
2.2、dropdown.js
1、如果点击事件发生在 document ,那么执行 clearMenus 隐藏下拉框
2、监听属性 data-toggle=”dropdown” 的点击事件,触发下拉菜单显示隐藏切换,并返回false,阻止事件冒泡到document上
3、在 data-toggle=”dropdown” 和 class dropdown-menu 元素上监听键盘事件,执行相应操作
阅读全文
0 0
- bootstrap之dropdown
- bootstrap之dropdown下拉菜单
- Bootstrap简单认识之Dropdown组件
- bootstrap dropdown演示
- bootstrap中的dropdown
- 【Bootstrap】下拉菜单Dropdown
- Bootstrap之下拉菜单dropdown
- bootstrap中的dropdown组件…
- bootstrap学习31---dropdown.js
- bootstrap框架学习之---如何让dropdown-menu按钮式下拉框长度一致
- Ajax控件之DropDown
- CSS之dropdown
- Keep Bootstrap dropdown open on click
- Bootstrap插件dropdown源码的学习
- bootstrap分页dropdown标签滚动问题
- BootStrap--CSS组件--下拉菜单(dropdown)
- bootstrap中的dropdown组件扩展hover事件
- dropdown
- Mac:source .bash_profile
- JavaSwing_5.4: 多线程并发与线程安全
- 大数据技术
- redis应用【五】 -- java连接redis
- Java高级工程师常见面试题
- bootstrap之dropdown
- thinkphp5 去掉url里的index.php
- JavaSwing_5.5: 拖拽功能
- HDU2057aA + B again
- 我的第一个上海国际10K精英赛
- [Mac]显示系统默认隐藏文件
- 如何正确理解CAP理论?
- 用服务器制作自己的图床
- JavaSwing_5.6: 系统托盘(System Tray)