dropdown.js 4.76 KB
Newer Older
1
/* ========================================================================
Chris Rebert's avatar
Chris Rebert committed
2
 * Bootstrap: dropdown.js v3.3.4
3
 * http://getbootstrap.com/javascript/#dropdowns
4
 * ========================================================================
Zlatan Vasović's avatar
Zlatan Vasović committed
5
 * Copyright 2011-2015 Twitter, Inc.
6
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7
 * ======================================================================== */
Jacob Thornton's avatar
Jacob Thornton committed
8

Jacob Thornton's avatar
Jacob Thornton committed
9

10
11
+function ($) {
  'use strict';
Katie Zhu's avatar
Katie Zhu committed
12

13
14
  // DROPDOWN CLASS DEFINITION
  // =========================
15

16
17
18
19
20
  var backdrop = '.dropdown-backdrop'
  var toggle   = '[data-toggle="dropdown"]'
  var Dropdown = function (element) {
    $(element).on('click.bs.dropdown', this.toggle)
  }
21

Chris Rebert's avatar
Chris Rebert committed
22
  Dropdown.VERSION = '3.3.4'
23

24
25
  Dropdown.prototype.toggle = function (e) {
    var $this = $(this)
fat's avatar
fat committed
26

27
    if ($this.is('.disabled, :disabled')) return
28

29
30
    var $parent  = getParent($this)
    var isActive = $parent.hasClass('open')
31

32
    clearMenus()
Jacob Thornton's avatar
Jacob Thornton committed
33

34
35
36
    if (!isActive) {
      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
        // if mobile we use a backdrop because click events don't delegate
37
38
39
40
        $(document.createElement('div'))
          .addClass('dropdown-backdrop')
          .insertAfter($(this))
          .on('click', clearMenus)
41
      }
fat's avatar
fat committed
42

43
44
      var relatedTarget = { relatedTarget: this }
      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
45

46
      if (e.isDefaultPrevented()) return
47

48
49
50
      $this
        .trigger('focus')
        .attr('aria-expanded', 'true')
51

52
53
54
      $parent
        .toggleClass('open')
        .trigger('shown.bs.dropdown', relatedTarget)
fat's avatar
fat committed
55
    }
56

57
58
    return false
  }
59

60
  Dropdown.prototype.keydown = function (e) {
61
    if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
62

63
    var $this = $(this)
Jacob Thornton's avatar
Jacob Thornton committed
64

65
66
    e.preventDefault()
    e.stopPropagation()
67

68
    if ($this.is('.disabled, :disabled')) return
69

70
71
    var $parent  = getParent($this)
    var isActive = $parent.hasClass('open')
72

fat's avatar
fat committed
73
    if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
74
75
76
      if (e.which == 27) $parent.find(toggle).trigger('focus')
      return $this.trigger('click')
    }
77

78
    var desc = ' li:not(.disabled):visible a'
79
    var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
80

81
    if (!$items.length) return
82

vsn4ik's avatar
vsn4ik committed
83
    var index = $items.index(e.target)
84

fat's avatar
fat committed
85
86
    if (e.which == 38 && index > 0)                 index--                        // up
    if (e.which == 40 && index < $items.length - 1) index++                        // down
87
    if (!~index)                                      index = 0
88

89
90
    $items.eq(index).trigger('focus')
  }
91

92
93
94
95
  function clearMenus(e) {
    if (e && e.which === 3) return
    $(backdrop).remove()
    $(toggle).each(function () {
96
97
      var $this         = $(this)
      var $parent       = getParent($this)
98
      var relatedTarget = { relatedTarget: this }
99

100
      if (!$parent.hasClass('open')) return
101

102
103
      if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return

104
      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
105

106
      if (e.isDefaultPrevented()) return
107

108
      $this.attr('aria-expanded', 'false')
109
110
111
      $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
    })
  }
112

113
114
  function getParent($this) {
    var selector = $this.attr('data-target')
115

116
117
118
    if (!selector) {
      selector = $this.attr('href')
      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
119
    }
120

121
    var $parent = selector && $(selector)
122

123
124
    return $parent && $parent.length ? $parent : $this.parent()
  }
125

126

127
128
129
130
131
132
133
  // DROPDOWN PLUGIN DEFINITION
  // ==========================

  function Plugin(option) {
    return this.each(function () {
      var $this = $(this)
      var data  = $this.data('bs.dropdown')
134

135
136
137
138
      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
      if (typeof option == 'string') data[option].call($this)
    })
  }
Jacob Thornton's avatar
Jacob Thornton committed
139

140
  var old = $.fn.dropdown
141

142
143
  $.fn.dropdown             = Plugin
  $.fn.dropdown.Constructor = Dropdown
144

145

146
147
  // DROPDOWN NO CONFLICT
  // ====================
148

149
150
151
152
  $.fn.dropdown.noConflict = function () {
    $.fn.dropdown = old
    return this
  }
153
154


155
156
  // APPLY TO STANDARD DROPDOWN ELEMENTS
  // ===================================
157

158
159
160
161
  $(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)
162
163
164
    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
    .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
    .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
165

166
}(jQuery);