dropdown.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  2. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3. /**
  4. * --------------------------------------------------------------------------
  5. * Bootstrap (v4.0.0-alpha.6): dropdown.js
  6. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  7. * --------------------------------------------------------------------------
  8. */
  9. var Dropdown = function ($) {
  10. /**
  11. * ------------------------------------------------------------------------
  12. * Constants
  13. * ------------------------------------------------------------------------
  14. */
  15. var NAME = 'dropdown';
  16. var VERSION = '4.0.0-alpha.6';
  17. var DATA_KEY = 'bs.dropdown';
  18. var EVENT_KEY = '.' + DATA_KEY;
  19. var DATA_API_KEY = '.data-api';
  20. var JQUERY_NO_CONFLICT = $.fn[NAME];
  21. var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
  22. var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key
  23. var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
  24. var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
  25. var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
  26. var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + '|' + ARROW_DOWN_KEYCODE + '|' + ESCAPE_KEYCODE + '|' + SPACE_KEYCODE);
  27. var Event = {
  28. HIDE: 'hide' + EVENT_KEY,
  29. HIDDEN: 'hidden' + EVENT_KEY,
  30. SHOW: 'show' + EVENT_KEY,
  31. SHOWN: 'shown' + EVENT_KEY,
  32. CLICK: 'click' + EVENT_KEY,
  33. CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
  34. FOCUSIN_DATA_API: 'focusin' + EVENT_KEY + DATA_API_KEY,
  35. KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY
  36. };
  37. var ClassName = {
  38. BACKDROP: 'dropdown-backdrop',
  39. DISABLED: 'disabled',
  40. SHOW: 'show'
  41. };
  42. var Selector = {
  43. BACKDROP: '.dropdown-backdrop',
  44. DATA_TOGGLE: '[data-toggle="dropdown"]',
  45. FORM_CHILD: '.dropdown form',
  46. ROLE_MENU: '[role="menu"]',
  47. ROLE_LISTBOX: '[role="listbox"]',
  48. NAVBAR_NAV: '.navbar-nav',
  49. VISIBLE_ITEMS: '[role="menu"] li:not(.disabled) a, ' + '[role="listbox"] li:not(.disabled) a'
  50. };
  51. /**
  52. * ------------------------------------------------------------------------
  53. * Class Definition
  54. * ------------------------------------------------------------------------
  55. */
  56. var Dropdown = function () {
  57. function Dropdown(element) {
  58. _classCallCheck(this, Dropdown);
  59. this._element = element;
  60. this._addEventListeners();
  61. }
  62. // getters
  63. // public
  64. Dropdown.prototype.toggle = function toggle() {
  65. if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
  66. return false;
  67. }
  68. var parent = Dropdown._getParentFromElement(this);
  69. var isActive = $(parent).hasClass(ClassName.SHOW);
  70. Dropdown._clearMenus();
  71. if (isActive) {
  72. return false;
  73. }
  74. if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {
  75. // if mobile we use a backdrop because click events don't delegate
  76. var dropdown = document.createElement('div');
  77. dropdown.className = ClassName.BACKDROP;
  78. $(dropdown).insertBefore(this);
  79. $(dropdown).on('click', Dropdown._clearMenus);
  80. }
  81. var relatedTarget = {
  82. relatedTarget: this
  83. };
  84. var showEvent = $.Event(Event.SHOW, relatedTarget);
  85. $(parent).trigger(showEvent);
  86. if (showEvent.isDefaultPrevented()) {
  87. return false;
  88. }
  89. this.focus();
  90. this.setAttribute('aria-expanded', true);
  91. $(parent).toggleClass(ClassName.SHOW);
  92. $(parent).trigger($.Event(Event.SHOWN, relatedTarget));
  93. return false;
  94. };
  95. Dropdown.prototype.dispose = function dispose() {
  96. $.removeData(this._element, DATA_KEY);
  97. $(this._element).off(EVENT_KEY);
  98. this._element = null;
  99. };
  100. // private
  101. Dropdown.prototype._addEventListeners = function _addEventListeners() {
  102. $(this._element).on(Event.CLICK, this.toggle);
  103. };
  104. // static
  105. Dropdown._jQueryInterface = function _jQueryInterface(config) {
  106. return this.each(function () {
  107. var data = $(this).data(DATA_KEY);
  108. if (!data) {
  109. data = new Dropdown(this);
  110. $(this).data(DATA_KEY, data);
  111. }
  112. if (typeof config === 'string') {
  113. if (data[config] === undefined) {
  114. throw new Error('No method named "' + config + '"');
  115. }
  116. data[config].call(this);
  117. }
  118. });
  119. };
  120. Dropdown._clearMenus = function _clearMenus(event) {
  121. if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) {
  122. return;
  123. }
  124. var backdrop = $(Selector.BACKDROP)[0];
  125. if (backdrop) {
  126. backdrop.parentNode.removeChild(backdrop);
  127. }
  128. var toggles = $.makeArray($(Selector.DATA_TOGGLE));
  129. for (var i = 0; i < toggles.length; i++) {
  130. var parent = Dropdown._getParentFromElement(toggles[i]);
  131. var relatedTarget = {
  132. relatedTarget: toggles[i]
  133. };
  134. if (!$(parent).hasClass(ClassName.SHOW)) {
  135. continue;
  136. }
  137. if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'focusin') && $.contains(parent, event.target)) {
  138. continue;
  139. }
  140. var hideEvent = $.Event(Event.HIDE, relatedTarget);
  141. $(parent).trigger(hideEvent);
  142. if (hideEvent.isDefaultPrevented()) {
  143. continue;
  144. }
  145. toggles[i].setAttribute('aria-expanded', 'false');
  146. $(parent).removeClass(ClassName.SHOW).trigger($.Event(Event.HIDDEN, relatedTarget));
  147. }
  148. };
  149. Dropdown._getParentFromElement = function _getParentFromElement(element) {
  150. var parent = void 0;
  151. var selector = Util.getSelectorFromElement(element);
  152. if (selector) {
  153. parent = $(selector)[0];
  154. }
  155. return parent || element.parentNode;
  156. };
  157. Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
  158. if (!REGEXP_KEYDOWN.test(event.which) || /input|textarea/i.test(event.target.tagName)) {
  159. return;
  160. }
  161. event.preventDefault();
  162. event.stopPropagation();
  163. if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
  164. return;
  165. }
  166. var parent = Dropdown._getParentFromElement(this);
  167. var isActive = $(parent).hasClass(ClassName.SHOW);
  168. if (!isActive && event.which !== ESCAPE_KEYCODE || isActive && event.which === ESCAPE_KEYCODE) {
  169. if (event.which === ESCAPE_KEYCODE) {
  170. var toggle = $(parent).find(Selector.DATA_TOGGLE)[0];
  171. $(toggle).trigger('focus');
  172. }
  173. $(this).trigger('click');
  174. return;
  175. }
  176. var items = $(parent).find(Selector.VISIBLE_ITEMS).get();
  177. if (!items.length) {
  178. return;
  179. }
  180. var index = items.indexOf(event.target);
  181. if (event.which === ARROW_UP_KEYCODE && index > 0) {
  182. // up
  183. index--;
  184. }
  185. if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
  186. // down
  187. index++;
  188. }
  189. if (index < 0) {
  190. index = 0;
  191. }
  192. items[index].focus();
  193. };
  194. _createClass(Dropdown, null, [{
  195. key: 'VERSION',
  196. get: function get() {
  197. return VERSION;
  198. }
  199. }]);
  200. return Dropdown;
  201. }();
  202. /**
  203. * ------------------------------------------------------------------------
  204. * Data Api implementation
  205. * ------------------------------------------------------------------------
  206. */
  207. $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + ' ' + Event.FOCUSIN_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
  208. e.stopPropagation();
  209. });
  210. /**
  211. * ------------------------------------------------------------------------
  212. * jQuery
  213. * ------------------------------------------------------------------------
  214. */
  215. $.fn[NAME] = Dropdown._jQueryInterface;
  216. $.fn[NAME].Constructor = Dropdown;
  217. $.fn[NAME].noConflict = function () {
  218. $.fn[NAME] = JQUERY_NO_CONFLICT;
  219. return Dropdown._jQueryInterface;
  220. };
  221. return Dropdown;
  222. }(jQuery);
  223. //# sourceMappingURL=dropdown.js.map