Created
August 17, 2014 16:19
-
-
Save yardfarmer/ed820ef7faa2d7ceceec to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ======================================================================== | |
* Bootstrap: dropdown.js v3.2.0 | |
* http://getbootstrap.com/javascript/#dropdowns | |
* ======================================================================== | |
* Copyright 2011-2014 Twitter, Inc. | |
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) | |
* ======================================================================== */ | |
+function ($) { | |
'use strict'; | |
// DROPDOWN CLASS DEFINITION | |
// ========================= | |
// as a click area for closing dropdown menus when clicking outside the menu. | |
var backdrop = '.dropdown-backdrop'; | |
// attribute is relied on for closing dropdown menus at an application level, so it's a good idea to always use it. | |
var toggle = '[data-toggle="dropdown"]'; | |
var Dropdown = function (element) { | |
$(element).on('click.bs.dropdown', this.toggle) | |
} | |
Dropdown.VERSION = '3.2.0' | |
Dropdown.prototype.toggle = function (e) { | |
var $this = $(this); | |
// :disable 表单对象属性过滤选择器 | |
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 | |
$('<div class="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') | |
$parent | |
.toggleClass('open') | |
.trigger('shown.bs.dropdown', relatedTarget) | |
} | |
return false | |
} | |
Dropdown.prototype.keydown = function (e) { | |
if (!/(38|40|27)/.test(e.keyCode)) 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 || (isActive && e.keyCode == 27)) { | |
if (e.which == 27) $parent.find(toggle).trigger('focus') | |
return $this.trigger('click') | |
} | |
var desc = ' li:not(.divider):visible a' | |
var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc) | |
if (!$items.length) return | |
var index = $items.index($items.filter(':focus')) | |
if (e.keyCode == 38 && index > 0) index-- // up | |
if (e.keyCode == 40 && index < $items.length - 1) index++ // down | |
if (!~index) index = 0 | |
$items.eq(index).trigger('focus') | |
} | |
function clearMenus(e) { | |
if (e && e.which === 3) return | |
$(backdrop).remove() | |
$(toggle).each(function () { | |
var $parent = getParent($(this)) | |
var relatedTarget = { relatedTarget: this } | |
if (!$parent.hasClass('open')) return | |
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) | |
if (e.isDefaultPrevented()) return | |
$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget) | |
}) | |
} | |
function getParent($this) { | |
var selector = $this.attr('data-target'); | |
if (!selector) { | |
selector = $this.attr('href') | |
/** | |
* gist 咀嚼 | |
* | |
* 1. #[A-Za-z] id 选择器 | |
* | |
* 2. /.*(?=#[^\s]*$)/ 这个表达式是为了选择 `#id` 选择器前面的空格。 | |
* (?=xxx) 意为匹配 xxx 之前的字符。 | |
* | |
* 3. 所以,全面的看来,若 selector 为 空, 直接返回 false; | |
* 只有最有一个之前的表达式为真时,才会返回最后一个表达式结果; | |
* 如遇当前表达式为假,后续不再执行。 | |
* | |
* 4. selector 不为空, 并且为 id(#xx) 选择器, 在后在替换掉 id 前的空格,返回选择符号 | |
*/ | |
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 | |
} | |
var $parent = selector && $(selector); | |
return $parent && $parent.length ? $parent : $this.parent(); | |
} | |
// 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) | |
.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 + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown) | |
}(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment