dropdown.js 4.14 KB
Newer Older
1
/* ========================================================================
2
 * Bootstrap: dropdown.js v3.0.3
3
 * http://getbootstrap.com/javascript/#dropdowns
4
 * ========================================================================
Zlatan Vasović's avatar
Zlatan Vasović committed
5
 * Copyright 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

XhmikosR's avatar
XhmikosR committed
10
+function ($) { 'use strict';
11

12
13
  // DROPDOWN CLASS DEFINITION
  // =========================
14

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

21
22
  Dropdown.prototype.toggle = function (e) {
    var $this = $(this)
23

24
    if ($this.is('.disabled, :disabled')) return
25

26
27
    var $parent  = getParent($this)
    var isActive = $parent.hasClass('open')
Jacob Thornton's avatar
Jacob Thornton committed
28

29
    clearMenus()
fat's avatar
fat committed
30

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

37
38
      var relatedTarget = { relatedTarget: this }
      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
39
40
41
42
43

      if (e.isDefaultPrevented()) return

      $parent
        .toggleClass('open')
44
        .trigger('shown.bs.dropdown', relatedTarget)
45

fat's avatar
fat committed
46
47
      $this.focus()
    }
48

49
50
    return false
  }
51

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

55
    var $this = $(this)
56

57
58
    e.preventDefault()
    e.stopPropagation()
Jacob Thornton's avatar
Jacob Thornton committed
59

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

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

65
66
67
68
    if (!isActive || (isActive && e.keyCode == 27)) {
      if (e.which == 27) $parent.find(toggle).focus()
      return $this.click()
    }
69

70
71
    var desc = ' li:not(.divider):visible a'
    var $items = $parent.find('[role=menu]' + desc + ', [role=listbox]' + desc)
72

73
    if (!$items.length) return
74

75
    var index = $items.index($items.filter(':focus'))
76

77
78
    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
79
    if (!~index)                                      index = 0
80

81
    $items.eq(index).focus()
82
83
  }

84
  function clearMenus(e) {
85
    $(backdrop).remove()
86
    $(toggle).each(function () {
87
      var $parent = getParent($(this))
88
      var relatedTarget = { relatedTarget: this }
89
      if (!$parent.hasClass('open')) return
90
      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
91
      if (e.isDefaultPrevented()) return
92
      $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
93
    })
94
95
96
97
98
99
100
  }

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

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

104
    var $parent = selector && $(selector)
105

106
    return $parent && $parent.length ? $parent : $this.parent()
107
108
109
  }


110
111
  // DROPDOWN PLUGIN DEFINITION
  // ==========================
112

113
114
  var old = $.fn.dropdown

115
  $.fn.dropdown = function (option) {
116
    return this.each(function () {
117
      var $this = $(this)
118
      var data  = $this.data('bs.dropdown')
119

120
      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
121
      if (typeof option == 'string') data[option].call($this)
122
123
    })
  }
Jacob Thornton's avatar
Jacob Thornton committed
124

125
126
  $.fn.dropdown.Constructor = Dropdown

127

128
129
  // DROPDOWN NO CONFLICT
  // ====================
130
131
132
133
134
135
136

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


137
138
139
  // APPLY TO STANDARD DROPDOWN ELEMENTS
  // ===================================

140
  $(document)
141
142
    .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
143
    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
144
    .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu], [role=listbox]', Dropdown.prototype.keydown)
145

146
}(jQuery);