1 /* ========================================================================
2 * Bootstrap: dropdown.js v3.3.2
3 * http://getbootstrap.com/javascript/#dropdowns
4 * ========================================================================
5 * Copyright 2011-2015 Twitter, Inc.
6 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7 * ======================================================================== */
13 // DROPDOWN CLASS DEFINITION
14 // =========================
16 var backdrop = '.dropdown-backdrop'
17 var toggle = '[data-toggle="dropdown"]'
18 var Dropdown = function (element) {
19 $(element).on('click.bs.dropdown', this.toggle)
22 Dropdown.VERSION = '3.3.2'
24 Dropdown.prototype.toggle = function (e) {
27 if ($this.is('.disabled, :disabled')) return
29 var $parent = getParent($this)
30 var isActive = $parent.hasClass('open')
35 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
36 // if mobile we use a backdrop because click events don't delegate
37 $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
40 var relatedTarget = { relatedTarget: this }
41 $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
43 if (e.isDefaultPrevented()) return
47 .attr('aria-expanded', 'true')
51 .trigger('shown.bs.dropdown', relatedTarget)
57 Dropdown.prototype.keydown = function (e) {
58 if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
65 if ($this.is('.disabled, :disabled')) return
67 var $parent = getParent($this)
68 var isActive = $parent.hasClass('open')
70 if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
71 if (e.which == 27) $parent.find(toggle).trigger('focus')
72 return $this.trigger('click')
75 var desc = ' li:not(.divider):visible a'
76 var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
78 if (!$items.length) return
80 var index = $items.index(e.target)
82 if (e.which == 38 && index > 0) index-- // up
83 if (e.which == 40 && index < $items.length - 1) index++ // down
84 if (!~index) index = 0
86 $items.eq(index).trigger('focus')
89 function clearMenus(e) {
90 if (e && e.which === 3) return
92 $(toggle).each(function () {
94 var $parent = getParent($this)
95 var relatedTarget = { relatedTarget: this }
97 if (!$parent.hasClass('open')) return
99 $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
101 if (e.isDefaultPrevented()) return
103 $this.attr('aria-expanded', 'false')
104 $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
108 function getParent($this) {
109 var selector = $this.attr('data-target')
112 selector = $this.attr('href')
113 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
116 var $parent = selector && $(selector)
118 return $parent && $parent.length ? $parent : $this.parent()
122 // DROPDOWN PLUGIN DEFINITION
123 // ==========================
125 function Plugin(option) {
126 return this.each(function () {
128 var data = $this.data('bs.dropdown')
130 if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
131 if (typeof option == 'string') data[option].call($this)
135 var old = $.fn.dropdown
137 $.fn.dropdown = Plugin
138 $.fn.dropdown.Constructor = Dropdown
141 // DROPDOWN NO CONFLICT
142 // ====================
144 $.fn.dropdown.noConflict = function () {
150 // APPLY TO STANDARD DROPDOWN ELEMENTS
151 // ===================================
154 .on('click.bs.dropdown.data-api', clearMenus)
155 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
156 .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
157 .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
158 .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
159 .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)