1.插件的使用
<!--[if !supportLists]-->1.? ? ? ? ? ?通过data-toggle绑定触发事件的父集元素,点击添加或删除open样式类,由此展开或折叠下拉菜单;
$(“. ? ? ? ?dropdown-toggle”).dropdown(‘toggle’)触发下拉菜单的展开或折叠;
? 包裹元素的样式类是dropdown,触发元素的样式类是dropdown-toggle,下拉框元素的样式类是dropdown-menu。
? 包裹元素dropdown中设置show(展开前)、focus(展开中)、shown(展开后)、hide(隐藏前)、hidden(隐藏后)事件,show和hide事件中可以阻止默认事件发生。
?
<div class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Java
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<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>
</div>
?
2.整体架构
? ? ? 构建dropdwon类,当即触发click事件,调用dropdwon.prototype.toggle方法,toggle发放中调用clearMenus函数折叠下拉框,下拉框折叠的情况触发if语句展开下拉框;
? ? ? 构建$.fn.dropdown插件,data属性中new出一个dropdown类实现初始化,drop类初始化过程中绑定事件。
?
3.js和jquery的新认识
? ? ? ?函数中通过return以及状态改变、if条件前的数据记录使函数拥有不同的功能;
? ? ? ?$.event()为事件设置event-data数据,包括relatedTarget元素,trigger触发事件,on绑定函数,当事件触发执行绑定函数,通过绑定函数的方式使下拉框有效;
? ? ? ? ?event.isDefaultPrevented判断是否调用了preventDefault方法,使preventDefault()函数有效,event.preventDefault()阻止默认事件;
? ? ? ?event.stopPropagation()阻止事件冒泡,event.isPropagationStopped()判断有否调用stopPropagation方法。
?
function ($) {
‘use strict‘;
// DROPDOWN CLASS DEFINITION
// =========================
// 触发元素和下拉元素为兄弟节点关系,[data-toggle="dropdown"]触发元素,dropdown-menu下拉框元素,dropdown包裹元素
var backdrop = ‘.dropdown-backdrop‘
var toggle = ‘[data-toggle="dropdown"]‘
// click.bs.dropdown事件在click事件的触发的时候也执行toggle函数,hide.bs.drop事件只能通过hide.bs.drop绑定,不能通过hide绑定
var Dropdown = function (element) {
$(element).on(‘click.bs.dropdown‘, this.toggle)
}
Dropdown.VERSION = ‘3.3.5‘
//通过data-target或者href获取包裹元素,不存在就选择父元素
function getParent($this) {
var selector = $this.attr(‘data-target‘)
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()
}
// clearMenus函数下拉框若为展开状态,就执行收起动作,折叠和展开通过添加open样式类实现
// 通过return使函数具有多种用途,折叠状态不执行后续操作
// trigger触发hide.bs.dropdown(折叠前)、hidden.bs.dropdown(折叠后)事件,on方法绑定函数,触发时间在clearMenus函数执行过程中
// e.isDefaultPrevented()判断使hide事件中e.preventDefault()能阻止下拉框折叠、hidden事件触发,同样效果可以通过缓存实现
function clearMenus(e) {
if (e && e.which === 3) return //e.which哪个按钮或按键被点击
$(backdrop).remove()
$(toggle).each(function () {
// dropdown方法被调用以外,还需要用[data-toggle="dropdown"]属性指向触发元素,查看该元素的属性填写情况是否合法
var $this = $(this)
var $parent = getParent($this)
var relatedTarget = { relatedTarget: this }
if (!$parent.hasClass(‘open‘)) return
// 触发元素中包含input、textarea时跳出clearMenus函数
if (e && e.type == ‘click‘ && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
// 父级元素触发hide事件,relatedTarget的目的是为mouseout、mouseleave指定相关元素/目标元素
// $.event构建事件,可以配置数据以及relatedTarget关联元素,以便使用
$parent.trigger(e = $.Event(‘hide.bs.dropdown‘, relatedTarget))
// event.isDefaultPrevented判断是否调用了preventDefault方法,event.preventDefault()阻止默认事件
// event.stopPropagation()阻止事件冒泡,event.isPropagationStopped()判断有否调用stopPropagation方法
if (e.isDefaultPrevented()) return
$this.attr(‘aria-expanded‘, ‘false‘)
$parent.removeClass(‘open‘).trigger(‘hidden.bs.dropdown‘, relatedTarget);
})
}
// trigger触发show(展开前)、focus(展开中)、shown(展开后)事件
// toggle通过单if语句实现折叠时展开,展开时折叠的效果,即顺序执行折叠,折叠前获取展开折叠状态,若为折叠if语句展开
Dropdown.prototype.toggle = function (e) {
// this指代调用dropdown方法的元素,clearMenus函数里再取填写[data-toggle="dropdown"]属性的元素,避免该属性未曾填写的元素
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) {
// 手机端使用backdrop,以使点击事件有效
$(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(‘shown.bs.dropdown‘, relatedTarget)
}
return false
}
// 下拉框以及触发元素处点击向上向下、空格Esc箭头通过trigger触发相应事件,
Dropdown.prototype.keydown = function (e) {
// 向上38、向下40、空格32、Esc键27
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‘)
// 触发元素折叠时按键触发点击事件,e.target也随之改变,以便上下箭头在下拉框中选择,展开时Esc按键触发focus事件折叠
if (!isActive && e.which != 27 || isActive && e.which == 27) {
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)
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
// ==========================
// 由触发元素dropdown-toggle调用dropdown方法,通过data属性new出一个dropdown实例,data属性也记录该对象,继而通过传入的option参数调用实例的toggle方法
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
// $.fn.dropdown已存在,使用old保存该值,$.fn.dropdown空闲出来完成操作,执行$.fn.dropdown.noConflict回归原$.fn.dropdown
$.fn.dropdown.noConflict = function () {
$.fn.dropdown = old
return this
}
// APPLY TO STANDARD DROPDOWN ELEMENTS
// ===================================
// 点击[data-toggle="dropdown"]元素触发toggle方法,toggle方法中调用clearMenus函数先折叠,回到toggle再展开,点击其他区域折叠
$(document)
.on(‘click.bs.dropdown.data-api‘, clearMenus)
.on(‘click.bs.dropdown.data-api‘, ‘.dropdown form‘, function (e) { e.stopPropagation() })
.on(‘click.bs.dropdown.data-api‘, toggle, Dropdown.prototype.toggle)
.on(‘keydown.bs.dropdown.data-api‘, toggle, Dropdown.prototype.keydown)
.on(‘keydown.bs.dropdown.data-api‘, ‘.dropdown-menu‘, Dropdown.prototype.keydown)
}(jQuery);
?
原文:http://schifred.iteye.com/blog/2267763