bootstrap-dropdown.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* ============================================================
  2. * bootstrap-dropdown.js v2.3.2
  3. * http://getbootstrap.com/2.3.2/javascript.html#dropdowns
  4. * ============================================================
  5. * Copyright 2013 Twitter, Inc.
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. * ============================================================ */
  19. !function ($) {
  20. "use strict"; // jshint ;_;
  21. /* DROPDOWN CLASS DEFINITION
  22. * ========================= */
  23. var toggle = '[data-toggle=dropdown]'
  24. , Dropdown = function (element) {
  25. var $el = $(element).on('click.dropdown.data-api', this.toggle)
  26. $('html').on('click.dropdown.data-api', function () {
  27. $el.parent().removeClass('open')
  28. })
  29. }
  30. Dropdown.prototype = {
  31. constructor: Dropdown
  32. , toggle: function (e) {
  33. var $this = $(this)
  34. , $parent
  35. , isActive
  36. if ($this.is('.disabled, :disabled')) return
  37. $parent = getParent($this)
  38. isActive = $parent.hasClass('open')
  39. clearMenus()
  40. if (!isActive) {
  41. if ('ontouchstart' in document.documentElement) {
  42. // if mobile we we use a backdrop because click events don't delegate
  43. $('<div class="dropdown-backdrop"/>').insertBefore($(this)).on('click', clearMenus)
  44. }
  45. $parent.toggleClass('open')
  46. }
  47. $this.focus()
  48. return false
  49. }
  50. , keydown: function (e) {
  51. var $this
  52. , $items
  53. , $active
  54. , $parent
  55. , isActive
  56. , index
  57. if (!/(38|40|27)/.test(e.keyCode)) return
  58. $this = $(this)
  59. e.preventDefault()
  60. e.stopPropagation()
  61. if ($this.is('.disabled, :disabled')) return
  62. $parent = getParent($this)
  63. isActive = $parent.hasClass('open')
  64. if (!isActive || (isActive && e.keyCode == 27)) {
  65. if (e.which == 27) $parent.find(toggle).focus()
  66. return $this.click()
  67. }
  68. $items = $('[role=menu] li:not(.divider):visible a', $parent)
  69. if (!$items.length) return
  70. index = $items.index($items.filter(':focus'))
  71. if (e.keyCode == 38 && index > 0) index-- // up
  72. if (e.keyCode == 40 && index < $items.length - 1) index++ // down
  73. if (!~index) index = 0
  74. $items
  75. .eq(index)
  76. .focus()
  77. }
  78. }
  79. function clearMenus() {
  80. $('.dropdown-backdrop').remove()
  81. $(toggle).each(function () {
  82. getParent($(this)).removeClass('open')
  83. })
  84. }
  85. function getParent($this) {
  86. var selector = $this.attr('data-target')
  87. , $parent
  88. if (!selector) {
  89. selector = $this.attr('href')
  90. selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
  91. }
  92. $parent = selector && $(selector)
  93. if (!$parent || !$parent.length) $parent = $this.parent()
  94. return $parent
  95. }
  96. /* DROPDOWN PLUGIN DEFINITION
  97. * ========================== */
  98. var old = $.fn.dropdown
  99. $.fn.dropdown = function (option) {
  100. return this.each(function () {
  101. var $this = $(this)
  102. , data = $this.data('dropdown')
  103. if (!data) $this.data('dropdown', (data = new Dropdown(this)))
  104. if (typeof option == 'string') data[option].call($this)
  105. })
  106. }
  107. $.fn.dropdown.Constructor = Dropdown
  108. /* DROPDOWN NO CONFLICT
  109. * ==================== */
  110. $.fn.dropdown.noConflict = function () {
  111. $.fn.dropdown = old
  112. return this
  113. }
  114. /* APPLY TO STANDARD DROPDOWN ELEMENTS
  115. * =================================== */
  116. $(document)
  117. .on('click.dropdown.data-api', clearMenus)
  118. .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
  119. .on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
  120. .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
  121. }(window.jQuery);