dropdown.js 4.44 KB
Newer Older
1
/* ========================================================================
Mark Otto's avatar
Mark Otto committed
2
 * Bootstrap: dropdown.js v3.1.1
3
 * http://getbootstrap.com/javascript/#dropdowns
4
 * ========================================================================
5
 * Copyright 2011-2014 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

Katie Zhu's avatar
Katie Zhu committed
10
11
12
13
14
(function (o_o) {
  typeof define  === 'function' && define.amd ? define(['jquery'], o_o) :
  typeof exports === 'object' ? o_o(require('jquery')) : o_o(this.jQuery)
})(function ($) {

Zlatan Vasović's avatar
Zlatan Vasović committed
15
  'use strict';
16

17
18
  // DROPDOWN CLASS DEFINITION
  // =========================
19

20
  var backdrop = '.dropdown-backdrop'
21
  var toggle   = '[data-toggle="dropdown"]'
22
  var Dropdown = function (element) {
mdxs's avatar
mdxs committed
23
    $(element).on('click.bs.dropdown', this.toggle)
24
  }
25

fat's avatar
fat committed
26
27
  Dropdown.VERSION = '3.1.1'

28
29
  Dropdown.prototype.toggle = function (e) {
    var $this = $(this)
30

31
    if ($this.is('.disabled, :disabled')) return
32

33
34
    var $parent  = getParent($this)
    var isActive = $parent.hasClass('open')
Jacob Thornton's avatar
Jacob Thornton committed
35

36
    clearMenus()
fat's avatar
fat committed
37

38
    if (!isActive) {
fat's avatar
fat committed
39
      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
Valera Rozuvan's avatar
Valera Rozuvan committed
40
        // if mobile we use a backdrop because click events don't delegate
Jacob Thornton's avatar
Jacob Thornton committed
41
        $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
fat's avatar
fat committed
42
      }
43

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

      if (e.isDefaultPrevented()) return

49
50
      $this.trigger('focus')

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

56
57
    return false
  }
58

59
  Dropdown.prototype.keydown = function (e) {
fat's avatar
fat committed
60
    if (!/(38|40|27)/.test(e.keyCode)) return
61

62
    var $this = $(this)
63

64
65
    e.preventDefault()
    e.stopPropagation()
Jacob Thornton's avatar
Jacob Thornton committed
66

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

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

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

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

80
    if (!$items.length) return
81

82
    var index = $items.index($items.filter(':focus'))
83

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

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

91
  function clearMenus(e) {
92
    if (e && e.which === 3) return
93
    $(backdrop).remove()
94
    $(toggle).each(function () {
95
      var $parent = getParent($(this))
96
      var relatedTarget = { relatedTarget: this }
97
      if (!$parent.hasClass('open')) return
98
      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
99
      if (e.isDefaultPrevented()) return
100
      $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
101
    })
102
103
104
105
106
107
108
  }

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

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

112
    var $parent = selector && $(selector)
113

114
    return $parent && $parent.length ? $parent : $this.parent()
115
116
117
  }


118
119
  // DROPDOWN PLUGIN DEFINITION
  // ==========================
120

121
  function Plugin(option) {
122
    return this.each(function () {
123
      var $this = $(this)
124
      var data  = $this.data('bs.dropdown')
125

126
      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
127
      if (typeof option == 'string') data[option].call($this)
128
129
    })
  }
Jacob Thornton's avatar
Jacob Thornton committed
130

131
132
133
  var old = $.fn.dropdown

  $.fn.dropdown             = Plugin
134
135
  $.fn.dropdown.Constructor = Dropdown

136

137
138
  // DROPDOWN NO CONFLICT
  // ====================
139
140
141
142
143
144
145

  $.fn.dropdown.noConflict = function () {
    $.fn.dropdown = old
    return this
  }


146
147
148
  // APPLY TO STANDARD DROPDOWN ELEMENTS
  // ===================================

149
  $(document)
150
151
    .on('click.bs.dropdown.data-api', clearMenus)
    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
Zlatan Vasović's avatar
Zlatan Vasović committed
152
    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
153
    .on('keydown.bs.dropdown.data-api', toggle + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown)
154

Katie Zhu's avatar
Katie Zhu committed
155
});