dropdown.js 4.07 KB
Newer Older
Jacob Thornton's avatar
Jacob Thornton committed
1
/* ============================================================
fat's avatar
fat committed
2
 * Bootstrap: dropdown.js v3.0.0
Jon Stevens's avatar
Jon Stevens committed
3
 * http://twitter.github.com/bootstrap/javascript.html#dropdowns
Jacob Thornton's avatar
Jacob Thornton committed
4
 * ============================================================
Mark Otto's avatar
Mark Otto committed
5
 * Copyright 2012 Twitter, Inc.
Jacob Thornton's avatar
Jacob Thornton committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============================================================ */

Jacob Thornton's avatar
Jacob Thornton committed
20

21
!function ($) { "use strict";
22

23
24
  // DROPDOWN CLASS DEFINITION
  // =========================
25

26
27
28
29
30
31
32
33
  var backdrop = '.dropdown-backdrop'
  var toggle   = '[data-toggle=dropdown]'
  var Dropdown = function (element) {
    var $el = $(element).on('click.dropdown.data-api', this.toggle)
    $('html').on('click.dropdown.data-api', function () {
      $el.parent().removeClass('open')
    })
  }
34

35
36
  Dropdown.prototype.toggle = function (e) {
    var $this = $(this)
37

38
    if ($this.is('.disabled, :disabled')) return
39

40
41
    var $parent  = getParent($this)
    var isActive = $parent.hasClass('open')
Jacob Thornton's avatar
Jacob Thornton committed
42

43
    clearMenus()
fat's avatar
fat committed
44

45
    if (!isActive) {
fat's avatar
fat committed
46
47
48
49
      if ('ontouchstart' in document.documentElement) {
        // if mobile we we use a backdrop because click events don't delegate
        $('<div class="dropdown-backdrop"/>').insertBefore($(this)).on('click', clearMenus)
      }
50
      $parent.toggleClass('open')
51
    }
52

53
    $this.focus()
54

55
56
    return false
  }
57

58
59
  Dropdown.prototype.keydown = function (e) {
    if (!/(38|40|27)/.test(e.keyCode)) return
60

61
    var $this = $(this)
62

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

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

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

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

76
    var $items = $('[role=menu] li:not(.divider):visible a', $parent)
77

78
    if (!$items.length) return
79

80
    var index = $items.index($items.filter(':focus'))
81

82
83
84
    if (e.keyCode == 38 && index > 0)                 index--                        // up
    if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
    if (!~index)                                      index=0
85

86
    $items.eq(index).focus()
87
88
89
  }

  function clearMenus() {
90
91
    $(backdrop).remove()
    $(toggle).each(function () { getParent($(this)).removeClass('open') })
92
93
94
95
96
97
98
  }

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

    if (!selector) {
      selector = $this.attr('href')
99
      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
100
101
    }

102
    var $parent = selector && $(selector)
103

104
    return $parent && $parent.length ? $parent : $this.parent()
105
106
107
  }


108
109
  // DROPDOWN PLUGIN DEFINITION
  // ==========================
110

111
112
  var old = $.fn.dropdown

113
  $.fn.dropdown = function (option) {
114
    return this.each(function () {
115
      var $this = $(this)
116
117
      var data  = $this.data('dropdown')

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

123
124
  $.fn.dropdown.Constructor = Dropdown

125

126
127
  // DROPDOWN NO CONFLICT
  // ====================
128
129
130
131
132
133
134

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


135
136
137
  // APPLY TO STANDARD DROPDOWN ELEMENTS
  // ===================================

138

139
  $(document)
fat's avatar
fat committed
140
    .on('click.dropdown.data-api', clearMenus)
141
142
143
    .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
    .on('click.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)
    .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
144

145
}(window.jQuery);