dropdown.js 8.69 KB
Newer Older
Mark Otto's avatar
grunt    
Mark Otto committed
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; }; }();
fat's avatar
fat committed
2

Mark Otto's avatar
grunt    
Mark Otto committed
3
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
fat's avatar
fat committed
4
5
6

/**
 * --------------------------------------------------------------------------
Mark Otto's avatar
Mark Otto committed
7
 * Bootstrap (v4.0.0-alpha.4): dropdown.js
fat's avatar
fat committed
8
9
10
11
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

Mark Otto's avatar
grunt    
Mark Otto committed
12
var Dropdown = function ($) {
fat's avatar
fat committed
13
14
15
16
17
18
19
20

  /**
   * ------------------------------------------------------------------------
   * Constants
   * ------------------------------------------------------------------------
   */

  var NAME = 'dropdown';
Mark Otto's avatar
Mark Otto committed
21
  var VERSION = '4.0.0-alpha.4';
fat's avatar
fat committed
22
  var DATA_KEY = 'bs.dropdown';
fat's avatar
fat committed
23
24
  var EVENT_KEY = '.' + DATA_KEY;
  var DATA_API_KEY = '.data-api';
fat's avatar
fat committed
25
  var JQUERY_NO_CONFLICT = $.fn[NAME];
Chris Rebert's avatar
grunt    
Chris Rebert committed
26
27
28
29
  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
fat's avatar
fat committed
30
31

  var Event = {
fat's avatar
fat committed
32
33
34
35
36
    HIDE: 'hide' + EVENT_KEY,
    HIDDEN: 'hidden' + EVENT_KEY,
    SHOW: 'show' + EVENT_KEY,
    SHOWN: 'shown' + EVENT_KEY,
    CLICK: 'click' + EVENT_KEY,
Jacob Thornton's avatar
Jacob Thornton committed
37
38
    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
    KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY
fat's avatar
fat committed
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  };

  var ClassName = {
    BACKDROP: 'dropdown-backdrop',
    DISABLED: 'disabled',
    OPEN: 'open'
  };

  var Selector = {
    BACKDROP: '.dropdown-backdrop',
    DATA_TOGGLE: '[data-toggle="dropdown"]',
    FORM_CHILD: '.dropdown form',
    ROLE_MENU: '[role="menu"]',
    ROLE_LISTBOX: '[role="listbox"]',
    NAVBAR_NAV: '.navbar-nav',
    VISIBLE_ITEMS: '[role="menu"] li:not(.disabled) a, ' + '[role="listbox"] li:not(.disabled) a'
  };

  /**
   * ------------------------------------------------------------------------
   * Class Definition
   * ------------------------------------------------------------------------
   */

Mark Otto's avatar
grunt    
Mark Otto committed
63
  var Dropdown = function () {
fat's avatar
fat committed
64
65
66
    function Dropdown(element) {
      _classCallCheck(this, Dropdown);

fat's avatar
fat committed
67
68
69
      this._element = element;

      this._addEventListeners();
fat's avatar
fat committed
70
71
    }

Jacob Thornton's avatar
Jacob Thornton committed
72
73
    // getters

Mark Otto's avatar
grunt    
Mark Otto committed
74
    // public
fat's avatar
fat committed
75

Mark Otto's avatar
grunt    
Mark Otto committed
76
77
78
79
    Dropdown.prototype.toggle = function toggle() {
      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
        return false;
      }
fat's avatar
fat committed
80

Mark Otto's avatar
grunt    
Mark Otto committed
81
82
      var parent = Dropdown._getParentFromElement(this);
      var isActive = $(parent).hasClass(ClassName.OPEN);
fat's avatar
fat committed
83

Mark Otto's avatar
grunt    
Mark Otto committed
84
      Dropdown._clearMenus();
fat's avatar
fat committed
85

Mark Otto's avatar
grunt    
Mark Otto committed
86
87
88
      if (isActive) {
        return false;
      }
fat's avatar
fat committed
89

Mark Otto's avatar
grunt    
Mark Otto committed
90
      if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {
fat's avatar
fat committed
91

Mark Otto's avatar
grunt    
Mark Otto committed
92
93
94
95
96
97
        // if mobile we use a backdrop because click events don't delegate
        var dropdown = document.createElement('div');
        dropdown.className = ClassName.BACKDROP;
        $(dropdown).insertBefore(this);
        $(dropdown).on('click', Dropdown._clearMenus);
      }
fat's avatar
fat committed
98

Mark Otto's avatar
grunt    
Mark Otto committed
99
100
      var relatedTarget = { relatedTarget: this };
      var showEvent = $.Event(Event.SHOW, relatedTarget);
fat's avatar
fat committed
101

Mark Otto's avatar
grunt    
Mark Otto committed
102
      $(parent).trigger(showEvent);
fat's avatar
fat committed
103

Mark Otto's avatar
grunt    
Mark Otto committed
104
105
106
      if (showEvent.isDefaultPrevented()) {
        return false;
      }
fat's avatar
fat committed
107

Mark Otto's avatar
grunt    
Mark Otto committed
108
109
      this.focus();
      this.setAttribute('aria-expanded', 'true');
fat's avatar
fat committed
110

Mark Otto's avatar
grunt    
Mark Otto committed
111
112
      $(parent).toggleClass(ClassName.OPEN);
      $(parent).trigger($.Event(Event.SHOWN, relatedTarget));
fat's avatar
fat committed
113

Mark Otto's avatar
grunt    
Mark Otto committed
114
115
      return false;
    };
fat's avatar
fat committed
116

Mark Otto's avatar
grunt    
Mark Otto committed
117
118
119
120
121
    Dropdown.prototype.dispose = function dispose() {
      $.removeData(this._element, DATA_KEY);
      $(this._element).off(EVENT_KEY);
      this._element = null;
    };
fat's avatar
fat committed
122

Mark Otto's avatar
grunt    
Mark Otto committed
123
    // private
fat's avatar
fat committed
124

Mark Otto's avatar
grunt    
Mark Otto committed
125
126
127
    Dropdown.prototype._addEventListeners = function _addEventListeners() {
      $(this._element).on(Event.CLICK, this.toggle);
    };
fat's avatar
fat committed
128

Mark Otto's avatar
grunt    
Mark Otto committed
129
    // static
fat's avatar
fat committed
130

Mark Otto's avatar
grunt    
Mark Otto committed
131
132
133
    Dropdown._jQueryInterface = function _jQueryInterface(config) {
      return this.each(function () {
        var data = $(this).data(DATA_KEY);
fat's avatar
fat committed
134

Mark Otto's avatar
grunt    
Mark Otto committed
135
136
        if (!data) {
          $(this).data(DATA_KEY, data = new Dropdown(this));
fat's avatar
fat committed
137
138
        }

Mark Otto's avatar
grunt    
Mark Otto committed
139
140
141
142
143
        if (typeof config === 'string') {
          if (data[config] === undefined) {
            throw new Error('No method named "' + config + '"');
          }
          data[config].call(this);
fat's avatar
fat committed
144
        }
Mark Otto's avatar
grunt    
Mark Otto committed
145
146
      });
    };
fat's avatar
fat committed
147

Mark Otto's avatar
grunt    
Mark Otto committed
148
149
150
151
    Dropdown._clearMenus = function _clearMenus(event) {
      if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) {
        return;
      }
fat's avatar
fat committed
152

Mark Otto's avatar
grunt    
Mark Otto committed
153
154
155
156
      var backdrop = $(Selector.BACKDROP)[0];
      if (backdrop) {
        backdrop.parentNode.removeChild(backdrop);
      }
fat's avatar
fat committed
157

Mark Otto's avatar
grunt    
Mark Otto committed
158
      var toggles = $.makeArray($(Selector.DATA_TOGGLE));
fat's avatar
fat committed
159

Mark Otto's avatar
grunt    
Mark Otto committed
160
161
162
      for (var i = 0; i < toggles.length; i++) {
        var parent = Dropdown._getParentFromElement(toggles[i]);
        var relatedTarget = { relatedTarget: toggles[i] };
fat's avatar
fat committed
163

Mark Otto's avatar
grunt    
Mark Otto committed
164
165
166
        if (!$(parent).hasClass(ClassName.OPEN)) {
          continue;
        }
fat's avatar
fat committed
167

Mark Otto's avatar
grunt    
Mark Otto committed
168
169
170
        if (event && event.type === 'click' && /input|textarea/i.test(event.target.tagName) && $.contains(parent, event.target)) {
          continue;
        }
fat's avatar
fat committed
171

Mark Otto's avatar
grunt    
Mark Otto committed
172
173
174
175
        var hideEvent = $.Event(Event.HIDE, relatedTarget);
        $(parent).trigger(hideEvent);
        if (hideEvent.isDefaultPrevented()) {
          continue;
fat's avatar
fat committed
176
        }
Mark Otto's avatar
grunt    
Mark Otto committed
177
178
179
180

        toggles[i].setAttribute('aria-expanded', 'false');

        $(parent).removeClass(ClassName.OPEN).trigger($.Event(Event.HIDDEN, relatedTarget));
fat's avatar
fat committed
181
      }
Mark Otto's avatar
grunt    
Mark Otto committed
182
183
184
185
186
    };

    Dropdown._getParentFromElement = function _getParentFromElement(element) {
      var parent = void 0;
      var selector = Util.getSelectorFromElement(element);
fat's avatar
fat committed
187

Mark Otto's avatar
grunt    
Mark Otto committed
188
189
      if (selector) {
        parent = $(selector)[0];
fat's avatar
fat committed
190
191
      }

Mark Otto's avatar
grunt    
Mark Otto committed
192
193
      return parent || element.parentNode;
    };
fat's avatar
fat committed
194

Mark Otto's avatar
grunt    
Mark Otto committed
195
196
197
198
    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
      if (!/(38|40|27|32)/.test(event.which) || /input|textarea/i.test(event.target.tagName)) {
        return;
      }
fat's avatar
fat committed
199

Mark Otto's avatar
grunt    
Mark Otto committed
200
201
      event.preventDefault();
      event.stopPropagation();
fat's avatar
fat committed
202

Mark Otto's avatar
grunt    
Mark Otto committed
203
204
205
      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
        return;
      }
fat's avatar
fat committed
206

Mark Otto's avatar
grunt    
Mark Otto committed
207
208
      var parent = Dropdown._getParentFromElement(this);
      var isActive = $(parent).hasClass(ClassName.OPEN);
fat's avatar
fat committed
209

Mark Otto's avatar
grunt    
Mark Otto committed
210
211
212
213
214
      if (!isActive && event.which !== ESCAPE_KEYCODE || isActive && event.which === ESCAPE_KEYCODE) {

        if (event.which === ESCAPE_KEYCODE) {
          var toggle = $(parent).find(Selector.DATA_TOGGLE)[0];
          $(toggle).trigger('focus');
fat's avatar
fat committed
215
216
        }

Mark Otto's avatar
grunt    
Mark Otto committed
217
218
219
        $(this).trigger('click');
        return;
      }
fat's avatar
fat committed
220

Mark Otto's avatar
grunt    
Mark Otto committed
221
      var items = $.makeArray($(Selector.VISIBLE_ITEMS));
fat's avatar
fat committed
222

Mark Otto's avatar
grunt    
Mark Otto committed
223
224
225
      items = items.filter(function (item) {
        return item.offsetWidth || item.offsetHeight;
      });
fat's avatar
fat committed
226

Mark Otto's avatar
grunt    
Mark Otto committed
227
228
229
      if (!items.length) {
        return;
      }
fat's avatar
fat committed
230

Mark Otto's avatar
grunt    
Mark Otto committed
231
      var index = items.indexOf(event.target);
Mark Otto's avatar
Mark Otto committed
232

Mark Otto's avatar
grunt    
Mark Otto committed
233
234
235
236
      if (event.which === ARROW_UP_KEYCODE && index > 0) {
        // up
        index--;
      }
Mark Otto's avatar
Mark Otto committed
237

Mark Otto's avatar
grunt    
Mark Otto committed
238
239
240
241
      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
        // down
        index++;
      }
fat's avatar
fat committed
242

Mark Otto's avatar
grunt    
Mark Otto committed
243
244
      if (index < 0) {
        index = 0;
fat's avatar
fat committed
245
      }
Mark Otto's avatar
grunt    
Mark Otto committed
246
247
248
249
250

      items[index].focus();
    };

    _createClass(Dropdown, null, [{
Jacob Thornton's avatar
Jacob Thornton committed
251
252
253
254
      key: 'VERSION',
      get: function get() {
        return VERSION;
      }
fat's avatar
fat committed
255
256
257
    }]);

    return Dropdown;
Mark Otto's avatar
grunt    
Mark Otto committed
258
259
260
261
262
263
264
  }();

  /**
   * ------------------------------------------------------------------------
   * Data Api implementation
   * ------------------------------------------------------------------------
   */
fat's avatar
fat committed
265

fat's avatar
fat committed
266
  $(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, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
fat's avatar
fat committed
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
    e.stopPropagation();
  });

  /**
   * ------------------------------------------------------------------------
   * jQuery
   * ------------------------------------------------------------------------
   */

  $.fn[NAME] = Dropdown._jQueryInterface;
  $.fn[NAME].Constructor = Dropdown;
  $.fn[NAME].noConflict = function () {
    $.fn[NAME] = JQUERY_NO_CONFLICT;
    return Dropdown._jQueryInterface;
  };

  return Dropdown;
Mark Otto's avatar
grunt    
Mark Otto committed
284
}(jQuery);
Jacob Thornton's avatar
Jacob Thornton committed
285
//# sourceMappingURL=dropdown.js.map