dropdown.js 4.61 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

XhmikosR's avatar
XhmikosR committed
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  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()
  }

  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

      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('hidden.bs.dropdown', relatedTarget)
    })
  }

58
59
  Dropdown.prototype.toggle = function (e) {
    var $this = $(this)
fat's avatar
fat committed
60

61
    if ($this.is('.disabled, :disabled')) return
62

63
64
    var $parent  = getParent($this)
    var isActive = $parent.hasClass('open')
65

66
    clearMenus()
Jacob Thornton's avatar
Jacob Thornton committed
67

68
69
70
    if (!isActive) {
      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
        // if mobile we use a backdrop because click events don't delegate
71
72
73
74
        $(document.createElement('div'))
          .addClass('dropdown-backdrop')
          .insertAfter($(this))
          .on('click', clearMenus)
75
      }
fat's avatar
fat committed
76

77
78
      var relatedTarget = { relatedTarget: this }
      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
79

80
      if (e.isDefaultPrevented()) return
81

82
83
84
      $this
        .trigger('focus')
        .attr('aria-expanded', 'true')
85

86
87
88
      $parent
        .toggleClass('open')
        .trigger('shown.bs.dropdown', relatedTarget)
fat's avatar
fat committed
89
    }
90

91
92
    return false
  }
93

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

97
    var $this = $(this)
Jacob Thornton's avatar
Jacob Thornton committed
98

99
100
    e.preventDefault()
    e.stopPropagation()
101

102
    if ($this.is('.disabled, :disabled')) return
103

104
105
    var $parent  = getParent($this)
    var isActive = $parent.hasClass('open')
106

XhmikosR's avatar
XhmikosR committed
107
    if (!isActive && e.which != 27 || isActive && e.which == 27) {
108
109
110
      if (e.which == 27) $parent.find(toggle).trigger('focus')
      return $this.trigger('click')
    }
111

112
    var desc = ' li:not(.disabled):visible a'
113
    var $items = $parent.find('.dropdown-menu' + desc)
114

115
    if (!$items.length) return
116

vsn4ik's avatar
vsn4ik committed
117
    var index = $items.index(e.target)
118

XhmikosR's avatar
XhmikosR committed
119
120
121
    if (e.which == 38 && index > 0)                 index--         // up
    if (e.which == 40 && index < $items.length - 1) index++         // down
    if (!~index)                                    index = 0
122

123
124
    $items.eq(index).trigger('focus')
  }
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
    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
163
    .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
164

165
}(jQuery);