dropdown.js 13.9 KB
Newer Older
Mark Otto's avatar
dist    
Mark Otto committed
1
2
'use strict';

Johann-S's avatar
build    
Johann-S committed
3
4
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

Mark Otto's avatar
grunt    
Mark Otto committed
5
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
6

Mark Otto's avatar
grunt    
Mark Otto committed
7
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
fat's avatar
fat committed
8
9
10

/**
 * --------------------------------------------------------------------------
Mark Otto's avatar
Mark Otto committed
11
 * Bootstrap (v4.0.0-beta): dropdown.js
fat's avatar
fat committed
12
13
14
15
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

Mark Otto's avatar
dist    
Mark Otto committed
16
var Dropdown = function () {
fat's avatar
fat committed
17

Johann-S's avatar
build    
Johann-S committed
18
19
20
21
22
23
24
25
  /**
   * Check for Popper dependency
   * Popper - https://popper.js.org
   */
  if (typeof Popper === 'undefined') {
    throw new Error('Bootstrap dropdown require Popper.js (https://popper.js.org)');
  }

fat's avatar
fat committed
26
27
28
29
30
31
32
  /**
   * ------------------------------------------------------------------------
   * Constants
   * ------------------------------------------------------------------------
   */

  var NAME = 'dropdown';
Mark Otto's avatar
Mark Otto committed
33
  var VERSION = '4.0.0-beta';
fat's avatar
fat committed
34
  var DATA_KEY = 'bs.dropdown';
fat's avatar
fat committed
35
36
  var EVENT_KEY = '.' + DATA_KEY;
  var DATA_API_KEY = '.data-api';
fat's avatar
fat committed
37
  var JQUERY_NO_CONFLICT = $.fn[NAME];
Chris Rebert's avatar
grunt    
Chris Rebert committed
38
  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
Mark Otto's avatar
grunt    
Mark Otto committed
39
  var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key
Mark Otto's avatar
grunt    
Mark Otto committed
40
  var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key
Chris Rebert's avatar
grunt    
Chris Rebert committed
41
42
43
  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)
Mark Otto's avatar
grunt    
Mark Otto committed
44
  var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + '|' + ARROW_DOWN_KEYCODE + '|' + ESCAPE_KEYCODE);
fat's avatar
fat committed
45
46

  var Event = {
fat's avatar
fat committed
47
48
49
50
51
    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
52
    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
Mark Otto's avatar
grunt    
Mark Otto committed
53
54
    KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY,
    KEYUP_DATA_API: 'keyup' + EVENT_KEY + DATA_API_KEY
fat's avatar
fat committed
55
56
57
58
  };

  var ClassName = {
    DISABLED: 'disabled',
Mark Otto's avatar
build    
Mark Otto committed
59
60
61
62
    SHOW: 'show',
    DROPUP: 'dropup',
    MENURIGHT: 'dropdown-menu-right',
    MENULEFT: 'dropdown-menu-left'
fat's avatar
fat committed
63
64
65
66
67
  };

  var Selector = {
    DATA_TOGGLE: '[data-toggle="dropdown"]',
    FORM_CHILD: '.dropdown form',
Mark Otto's avatar
grunt    
Mark Otto committed
68
    MENU: '.dropdown-menu',
fat's avatar
fat committed
69
    NAVBAR_NAV: '.navbar-nav',
Mark Otto's avatar
grunt    
Mark Otto committed
70
    VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled)'
fat's avatar
fat committed
71
72
  };

Johann-S's avatar
build    
Johann-S committed
73
74
  var AttachmentMap = {
    TOP: 'top-start',
Mark Otto's avatar
build    
Mark Otto committed
75
76
77
    TOPEND: 'top-end',
    BOTTOM: 'bottom-start',
    BOTTOMEND: 'bottom-end'
Johann-S's avatar
build    
Johann-S committed
78
79
80
81
82
83
84
85
86
87
  };

  var Default = {
    offset: 0,
    flip: true
  };

  var DefaultType = {
    offset: '(number|string)',
    flip: 'boolean'
Mark Otto's avatar
dist    
Mark Otto committed
88
  };
Johann-S's avatar
build    
Johann-S committed
89

Mark Otto's avatar
dist    
Mark Otto committed
90
91
92
93
94
  /**
   * ------------------------------------------------------------------------
   * Class Definition
   * ------------------------------------------------------------------------
   */
fat's avatar
fat committed
95

Mark Otto's avatar
grunt    
Mark Otto committed
96
  var Dropdown = function () {
Johann-S's avatar
build    
Johann-S committed
97
    function Dropdown(element, config) {
fat's avatar
fat committed
98
99
      _classCallCheck(this, Dropdown);

fat's avatar
fat committed
100
      this._element = element;
Johann-S's avatar
build    
Johann-S committed
101
102
103
      this._popper = null;
      this._config = this._getConfig(config);
      this._menu = this._getMenuElement();
Mark Otto's avatar
build    
Mark Otto committed
104
      this._inNavbar = this._detectNavbar();
fat's avatar
fat committed
105
106

      this._addEventListeners();
fat's avatar
fat committed
107
108
    }

Jacob Thornton's avatar
Jacob Thornton committed
109
110
    // getters

Mark Otto's avatar
dist    
Mark Otto committed
111
112
    _createClass(Dropdown, [{
      key: 'toggle',
fat's avatar
fat committed
113
114


Mark Otto's avatar
dist    
Mark Otto committed
115
      // public
fat's avatar
fat committed
116

Mark Otto's avatar
dist    
Mark Otto committed
117
118
119
120
      value: function toggle() {
        if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {
          return;
        }
fat's avatar
fat committed
121

Mark Otto's avatar
dist    
Mark Otto committed
122
123
        var parent = Dropdown._getParentFromElement(this._element);
        var isActive = $(this._menu).hasClass(ClassName.SHOW);
fat's avatar
fat committed
124

Mark Otto's avatar
dist    
Mark Otto committed
125
        Dropdown._clearMenus();
fat's avatar
fat committed
126

Mark Otto's avatar
dist    
Mark Otto committed
127
128
129
        if (isActive) {
          return;
        }
fat's avatar
fat committed
130

Mark Otto's avatar
dist    
Mark Otto committed
131
132
133
134
        var relatedTarget = {
          relatedTarget: this._element
        };
        var showEvent = $.Event(Event.SHOW, relatedTarget);
fat's avatar
fat committed
135

Mark Otto's avatar
dist    
Mark Otto committed
136
137
138
139
        $(parent).trigger(showEvent);

        if (showEvent.isDefaultPrevented()) {
          return;
Mark Otto's avatar
build    
Mark Otto committed
140
        }
Mark Otto's avatar
grunt    
Mark Otto committed
141

Mark Otto's avatar
dist    
Mark Otto committed
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
        var element = this._element;
        // for dropup with alignment we use the parent as popper container
        if ($(parent).hasClass(ClassName.DROPUP)) {
          if ($(this._menu).hasClass(ClassName.MENULEFT) || $(this._menu).hasClass(ClassName.MENURIGHT)) {
            element = parent;
          }
        }
        this._popper = new Popper(element, this._menu, this._getPopperConfig());

        // if this is a touch-enabled device we add extra
        // empty mouseover listeners to the body's immediate children;
        // only needed because of broken event delegation on iOS
        // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
        if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {
          $('body').children().on('mouseover', null, $.noop);
        }
fat's avatar
fat committed
158

Mark Otto's avatar
dist    
Mark Otto committed
159
160
        this._element.focus();
        this._element.setAttribute('aria-expanded', true);
fat's avatar
fat committed
161

Mark Otto's avatar
dist    
Mark Otto committed
162
163
        $(this._menu).toggleClass(ClassName.SHOW);
        $(parent).toggleClass(ClassName.SHOW).trigger($.Event(Event.SHOWN, relatedTarget));
Johann-S's avatar
build    
Johann-S committed
164
      }
Mark Otto's avatar
dist    
Mark Otto committed
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
    }, {
      key: 'dispose',
      value: function dispose() {
        $.removeData(this._element, DATA_KEY);
        $(this._element).off(EVENT_KEY);
        this._element = null;
        this._menu = null;
        if (this._popper !== null) {
          this._popper.destroy();
        }
        this._popper = null;
      }
    }, {
      key: 'update',
      value: function update() {
        this._inNavbar = this._detectNavbar();
        if (this._popper !== null) {
          this._popper.scheduleUpdate();
        }
Johann-S's avatar
build    
Johann-S committed
184
      }
fat's avatar
fat committed
185

Mark Otto's avatar
dist    
Mark Otto committed
186
      // private
Johann-S's avatar
build    
Johann-S committed
187

Mark Otto's avatar
dist    
Mark Otto committed
188
189
190
191
192
193
194
195
196
197
    }, {
      key: '_addEventListeners',
      value: function _addEventListeners() {
        var _this = this;

        $(this._element).on(Event.CLICK, function (event) {
          event.preventDefault();
          event.stopPropagation();
          _this.toggle();
        });
Johann-S's avatar
build    
Johann-S committed
198
      }
Mark Otto's avatar
dist    
Mark Otto committed
199
200
201
202
    }, {
      key: '_getConfig',
      value: function _getConfig(config) {
        config = $.extend({}, this.constructor.Default, $(this._element).data(), config);
Johann-S's avatar
build    
Johann-S committed
203

Mark Otto's avatar
dist    
Mark Otto committed
204
        Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
Johann-S's avatar
build    
Johann-S committed
205

Mark Otto's avatar
dist    
Mark Otto committed
206
        return config;
Johann-S's avatar
build    
Johann-S committed
207
      }
Mark Otto's avatar
dist    
Mark Otto committed
208
209
210
211
212
213
    }, {
      key: '_getMenuElement',
      value: function _getMenuElement() {
        if (!this._menu) {
          var parent = Dropdown._getParentFromElement(this._element);
          this._menu = $(parent).find(Selector.MENU)[0];
Mark Otto's avatar
build    
Mark Otto committed
214
        }
Mark Otto's avatar
dist    
Mark Otto committed
215
        return this._menu;
Mark Otto's avatar
build    
Mark Otto committed
216
      }
Mark Otto's avatar
dist    
Mark Otto committed
217
218
219
220
    }, {
      key: '_getPlacement',
      value: function _getPlacement() {
        var $parentDropdown = $(this._element).parent();
Mark Otto's avatar
dist    
Mark Otto committed
221
        var placement = AttachmentMap.BOTTOM;
Mark Otto's avatar
dist    
Mark Otto committed
222
223

        // Handle dropup
Mark Otto's avatar
dist    
Mark Otto committed
224
        if ($parentDropdown.hasClass(ClassName.DROPUP)) {
Mark Otto's avatar
dist    
Mark Otto committed
225
226
227
          placement = AttachmentMap.TOP;
          if ($(this._menu).hasClass(ClassName.MENURIGHT)) {
            placement = AttachmentMap.TOPEND;
Mark Otto's avatar
build    
Mark Otto committed
228
          }
Mark Otto's avatar
dist    
Mark Otto committed
229
230
        } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {
          placement = AttachmentMap.BOTTOMEND;
Mark Otto's avatar
build    
Mark Otto committed
231
        }
Mark Otto's avatar
dist    
Mark Otto committed
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
        return placement;
      }
    }, {
      key: '_detectNavbar',
      value: function _detectNavbar() {
        return $(this._element).closest('.navbar').length > 0;
      }
    }, {
      key: '_getPopperConfig',
      value: function _getPopperConfig() {
        var popperConfig = {
          placement: this._getPlacement(),
          modifiers: {
            offset: {
              offset: this._config.offset
            },
            flip: {
              enabled: this._config.flip
            }
          }
Mark Otto's avatar
dist    
Mark Otto committed
252
        };
Mark Otto's avatar
build    
Mark Otto committed
253

Mark Otto's avatar
dist    
Mark Otto committed
254
255
        // Disable Popper.js for Dropdown in Navbar
        if (this._inNavbar) {
Mark Otto's avatar
dist    
Mark Otto committed
256
257
258
259
260
          popperConfig.modifiers.applyStyle = {
            enabled: !this._inNavbar
          };
        }
        return popperConfig;
Mark Otto's avatar
build    
Mark Otto committed
261
262
      }

Mark Otto's avatar
dist    
Mark Otto committed
263
      // static
fat's avatar
fat committed
264

Mark Otto's avatar
dist    
Mark Otto committed
265
266
267
268
269
270
    }], [{
      key: '_jQueryInterface',
      value: function _jQueryInterface(config) {
        return this.each(function () {
          var data = $(this).data(DATA_KEY);
          var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
fat's avatar
fat committed
271

Mark Otto's avatar
dist    
Mark Otto committed
272
273
274
          if (!data) {
            data = new Dropdown(this, _config);
            $(this).data(DATA_KEY, data);
Mark Otto's avatar
grunt    
Mark Otto committed
275
          }
fat's avatar
fat committed
276

Mark Otto's avatar
dist    
Mark Otto committed
277
278
279
280
281
282
283
          if (typeof config === 'string') {
            if (typeof data[config] === 'undefined') {
              throw new Error('No method named "' + config + '"');
            }
            data[config]();
          }
        });
Mark Otto's avatar
grunt    
Mark Otto committed
284
      }
Mark Otto's avatar
dist    
Mark Otto committed
285
286
287
288
289
    }, {
      key: '_clearMenus',
      value: function _clearMenus(event) {
        if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {
          return;
Johann-S's avatar
build    
Johann-S committed
290
291
        }

Mark Otto's avatar
dist    
Mark Otto committed
292
293
294
295
296
297
298
        var toggles = $.makeArray($(Selector.DATA_TOGGLE));
        for (var i = 0; i < toggles.length; i++) {
          var parent = Dropdown._getParentFromElement(toggles[i]);
          var context = $(toggles[i]).data(DATA_KEY);
          var relatedTarget = {
            relatedTarget: toggles[i]
          };
fat's avatar
fat committed
299

Mark Otto's avatar
dist    
Mark Otto committed
300
301
302
          if (!context) {
            continue;
          }
fat's avatar
fat committed
303

Mark Otto's avatar
dist    
Mark Otto committed
304
305
306
307
          var dropdownMenu = context._menu;
          if (!$(parent).hasClass(ClassName.SHOW)) {
            continue;
          }
Mark Otto's avatar
grunt    
Mark Otto committed
308

Mark Otto's avatar
dist    
Mark Otto committed
309
310
311
          if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $.contains(parent, event.target)) {
            continue;
          }
Mark Otto's avatar
grunt    
Mark Otto committed
312

Mark Otto's avatar
dist    
Mark Otto committed
313
314
315
316
317
          var hideEvent = $.Event(Event.HIDE, relatedTarget);
          $(parent).trigger(hideEvent);
          if (hideEvent.isDefaultPrevented()) {
            continue;
          }
Mark Otto's avatar
grunt    
Mark Otto committed
318

Mark Otto's avatar
dist    
Mark Otto committed
319
320
321
322
323
          // if this is a touch-enabled device we remove the extra
          // empty mouseover listeners we added for iOS support
          if ('ontouchstart' in document.documentElement) {
            $('body').children().off('mouseover', null, $.noop);
          }
Mark Otto's avatar
grunt    
Mark Otto committed
324

Mark Otto's avatar
dist    
Mark Otto committed
325
          toggles[i].setAttribute('aria-expanded', 'false');
fat's avatar
fat committed
326

Mark Otto's avatar
dist    
Mark Otto committed
327
328
329
          $(dropdownMenu).removeClass(ClassName.SHOW);
          $(parent).removeClass(ClassName.SHOW).trigger($.Event(Event.HIDDEN, relatedTarget));
        }
fat's avatar
fat committed
330
      }
Mark Otto's avatar
dist    
Mark Otto committed
331
332
333
334
335
    }, {
      key: '_getParentFromElement',
      value: function _getParentFromElement(element) {
        var parent = void 0;
        var selector = Util.getSelectorFromElement(element);
fat's avatar
fat committed
336

Mark Otto's avatar
dist    
Mark Otto committed
337
338
339
        if (selector) {
          parent = $(selector)[0];
        }
fat's avatar
fat committed
340

Mark Otto's avatar
dist    
Mark Otto committed
341
        return parent || element.parentNode;
Mark Otto's avatar
grunt    
Mark Otto committed
342
      }
Mark Otto's avatar
dist    
Mark Otto committed
343
344
345
346
347
348
349
350
351
    }, {
      key: '_dataApiKeydownHandler',
      value: function _dataApiKeydownHandler(event) {
        if (!REGEXP_KEYDOWN.test(event.which) || /button/i.test(event.target.tagName) && event.which === SPACE_KEYCODE || /input|textarea/i.test(event.target.tagName)) {
          return;
        }

        event.preventDefault();
        event.stopPropagation();
fat's avatar
fat committed
352

Mark Otto's avatar
dist    
Mark Otto committed
353
354
355
        if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
          return;
        }
fat's avatar
fat committed
356

Mark Otto's avatar
dist    
Mark Otto committed
357
358
        var parent = Dropdown._getParentFromElement(this);
        var isActive = $(parent).hasClass(ClassName.SHOW);
fat's avatar
fat committed
359

Mark Otto's avatar
dist    
Mark Otto committed
360
        if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {
fat's avatar
fat committed
361

Mark Otto's avatar
dist    
Mark Otto committed
362
363
364
365
          if (event.which === ESCAPE_KEYCODE) {
            var toggle = $(parent).find(Selector.DATA_TOGGLE)[0];
            $(toggle).trigger('focus');
          }
Mark Otto's avatar
grunt    
Mark Otto committed
366

Mark Otto's avatar
dist    
Mark Otto committed
367
368
          $(this).trigger('click');
          return;
fat's avatar
fat committed
369
370
        }

Mark Otto's avatar
dist    
Mark Otto committed
371
        var items = $(parent).find(Selector.VISIBLE_ITEMS).get();
fat's avatar
fat committed
372

Mark Otto's avatar
dist    
Mark Otto committed
373
374
375
        if (!items.length) {
          return;
        }
fat's avatar
fat committed
376

Mark Otto's avatar
dist    
Mark Otto committed
377
        var index = items.indexOf(event.target);
fat's avatar
fat committed
378

Mark Otto's avatar
dist    
Mark Otto committed
379
380
381
382
        if (event.which === ARROW_UP_KEYCODE && index > 0) {
          // up
          index--;
        }
Mark Otto's avatar
Mark Otto committed
383

Mark Otto's avatar
dist    
Mark Otto committed
384
385
386
387
        if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
          // down
          index++;
        }
Mark Otto's avatar
Mark Otto committed
388

Mark Otto's avatar
dist    
Mark Otto committed
389
390
391
        if (index < 0) {
          index = 0;
        }
fat's avatar
fat committed
392

Mark Otto's avatar
dist    
Mark Otto committed
393
        items[index].focus();
fat's avatar
fat committed
394
      }
Mark Otto's avatar
dist    
Mark Otto committed
395
    }, {
Jacob Thornton's avatar
Jacob Thornton committed
396
397
398
399
      key: 'VERSION',
      get: function get() {
        return VERSION;
      }
Johann-S's avatar
build    
Johann-S committed
400
401
402
403
404
405
406
407
408
409
    }, {
      key: 'Default',
      get: function get() {
        return Default;
      }
    }, {
      key: 'DefaultType',
      get: function get() {
        return DefaultType;
      }
fat's avatar
fat committed
410
411
412
    }]);

    return Dropdown;
Mark Otto's avatar
grunt    
Mark Otto committed
413
414
415
416
417
418
419
  }();

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

Johann-S's avatar
build    
Johann-S committed
421
422
423
424
425
  $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + ' ' + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
    event.preventDefault();
    event.stopPropagation();
    Dropdown._jQueryInterface.call($(this), 'toggle');
  }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
fat's avatar
fat committed
426
    e.stopPropagation();
Mark Otto's avatar
Mark Otto committed
427
  });
fat's avatar
fat committed
428
429
430
431
432
433
434

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

Mark Otto's avatar
Mark Otto committed
435
  $.fn[NAME] = Dropdown._jQueryInterface;
fat's avatar
fat committed
436
437
438
439
440
441
442
  $.fn[NAME].Constructor = Dropdown;
  $.fn[NAME].noConflict = function () {
    $.fn[NAME] = JQUERY_NO_CONFLICT;
    return Dropdown._jQueryInterface;
  };

  return Dropdown;
Mark Otto's avatar
dist    
Mark Otto committed
443
}(jQuery, Popper);
Mark Otto's avatar
build    
Mark Otto committed
444
//# sourceMappingURL=dropdown.js.map