Issues (141)

resources/bootstrap/js/dropdown.js (1 issue)

1
/*!
2
  * Bootstrap dropdown.js v4.6.2 (https://getbootstrap.com/)
3
  * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
  */
6
(function (global, factory) {
7
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('popper.js'), require('./util.js')) :
8
  typeof define === 'function' && define.amd ? define(['jquery', 'popper.js', './util'], factory) :
9
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Dropdown = factory(global.jQuery, global.Popper, global.Util));
10
})(this, (function ($, Popper, Util) { 'use strict';
11
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
14
  var $__default = /*#__PURE__*/_interopDefaultLegacy($);
15
  var Popper__default = /*#__PURE__*/_interopDefaultLegacy(Popper);
16
  var Util__default = /*#__PURE__*/_interopDefaultLegacy(Util);
17
18
  function _defineProperties(target, props) {
19
    for (var i = 0; i < props.length; i++) {
20
      var descriptor = props[i];
21
      descriptor.enumerable = descriptor.enumerable || false;
22
      descriptor.configurable = true;
23
      if ("value" in descriptor) descriptor.writable = true;
24
      Object.defineProperty(target, descriptor.key, descriptor);
25
    }
26
  }
27
28
  function _createClass(Constructor, protoProps, staticProps) {
29
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
30
    if (staticProps) _defineProperties(Constructor, staticProps);
31
    Object.defineProperty(Constructor, "prototype", {
32
      writable: false
33
    });
34
    return Constructor;
35
  }
36
37
  function _extends() {
38
    _extends = Object.assign ? Object.assign.bind() : function (target) {
39
      for (var i = 1; i < arguments.length; i++) {
40
        var source = arguments[i];
41
42
        for (var key in source) {
0 ignored issues
show
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
43
          if (Object.prototype.hasOwnProperty.call(source, key)) {
44
            target[key] = source[key];
45
          }
46
        }
47
      }
48
49
      return target;
50
    };
51
    return _extends.apply(this, arguments);
52
  }
53
54
  /**
55
   * Constants
56
   */
57
58
  var NAME = 'dropdown';
59
  var VERSION = '4.6.2';
60
  var DATA_KEY = 'bs.dropdown';
61
  var EVENT_KEY = "." + DATA_KEY;
62
  var DATA_API_KEY = '.data-api';
63
  var JQUERY_NO_CONFLICT = $__default["default"].fn[NAME];
64
  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
65
66
  var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key
67
68
  var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key
69
70
  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
71
72
  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
73
74
  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
75
76
  var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE);
77
  var CLASS_NAME_DISABLED = 'disabled';
78
  var CLASS_NAME_SHOW = 'show';
79
  var CLASS_NAME_DROPUP = 'dropup';
80
  var CLASS_NAME_DROPRIGHT = 'dropright';
81
  var CLASS_NAME_DROPLEFT = 'dropleft';
82
  var CLASS_NAME_MENURIGHT = 'dropdown-menu-right';
83
  var CLASS_NAME_POSITION_STATIC = 'position-static';
84
  var EVENT_HIDE = "hide" + EVENT_KEY;
85
  var EVENT_HIDDEN = "hidden" + EVENT_KEY;
86
  var EVENT_SHOW = "show" + EVENT_KEY;
87
  var EVENT_SHOWN = "shown" + EVENT_KEY;
88
  var EVENT_CLICK = "click" + EVENT_KEY;
89
  var EVENT_CLICK_DATA_API = "click" + EVENT_KEY + DATA_API_KEY;
90
  var EVENT_KEYDOWN_DATA_API = "keydown" + EVENT_KEY + DATA_API_KEY;
91
  var EVENT_KEYUP_DATA_API = "keyup" + EVENT_KEY + DATA_API_KEY;
92
  var SELECTOR_DATA_TOGGLE = '[data-toggle="dropdown"]';
93
  var SELECTOR_FORM_CHILD = '.dropdown form';
94
  var SELECTOR_MENU = '.dropdown-menu';
95
  var SELECTOR_NAVBAR_NAV = '.navbar-nav';
96
  var SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';
97
  var PLACEMENT_TOP = 'top-start';
98
  var PLACEMENT_TOPEND = 'top-end';
99
  var PLACEMENT_BOTTOM = 'bottom-start';
100
  var PLACEMENT_BOTTOMEND = 'bottom-end';
101
  var PLACEMENT_RIGHT = 'right-start';
102
  var PLACEMENT_LEFT = 'left-start';
103
  var Default = {
104
    offset: 0,
105
    flip: true,
106
    boundary: 'scrollParent',
107
    reference: 'toggle',
108
    display: 'dynamic',
109
    popperConfig: null
110
  };
111
  var DefaultType = {
112
    offset: '(number|string|function)',
113
    flip: 'boolean',
114
    boundary: '(string|element)',
115
    reference: '(string|element)',
116
    display: 'string',
117
    popperConfig: '(null|object)'
118
  };
119
  /**
120
   * Class definition
121
   */
122
123
  var Dropdown = /*#__PURE__*/function () {
124
    function Dropdown(element, config) {
125
      this._element = element;
126
      this._popper = null;
127
      this._config = this._getConfig(config);
128
      this._menu = this._getMenuElement();
129
      this._inNavbar = this._detectNavbar();
130
131
      this._addEventListeners();
132
    } // Getters
133
134
135
    var _proto = Dropdown.prototype;
136
137
    // Public
138
    _proto.toggle = function toggle() {
139
      if (this._element.disabled || $__default["default"](this._element).hasClass(CLASS_NAME_DISABLED)) {
140
        return;
141
      }
142
143
      var isActive = $__default["default"](this._menu).hasClass(CLASS_NAME_SHOW);
144
145
      Dropdown._clearMenus();
146
147
      if (isActive) {
148
        return;
149
      }
150
151
      this.show(true);
152
    };
153
154
    _proto.show = function show(usePopper) {
155
      if (usePopper === void 0) {
156
        usePopper = false;
157
      }
158
159
      if (this._element.disabled || $__default["default"](this._element).hasClass(CLASS_NAME_DISABLED) || $__default["default"](this._menu).hasClass(CLASS_NAME_SHOW)) {
160
        return;
161
      }
162
163
      var relatedTarget = {
164
        relatedTarget: this._element
165
      };
166
      var showEvent = $__default["default"].Event(EVENT_SHOW, relatedTarget);
167
168
      var parent = Dropdown._getParentFromElement(this._element);
169
170
      $__default["default"](parent).trigger(showEvent);
171
172
      if (showEvent.isDefaultPrevented()) {
173
        return;
174
      } // Totally disable Popper for Dropdowns in Navbar
175
176
177
      if (!this._inNavbar && usePopper) {
178
        // Check for Popper dependency
179
        if (typeof Popper__default["default"] === 'undefined') {
180
          throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)');
181
        }
182
183
        var referenceElement = this._element;
184
185
        if (this._config.reference === 'parent') {
186
          referenceElement = parent;
187
        } else if (Util__default["default"].isElement(this._config.reference)) {
188
          referenceElement = this._config.reference; // Check if it's jQuery element
189
190
          if (typeof this._config.reference.jquery !== 'undefined') {
191
            referenceElement = this._config.reference[0];
192
          }
193
        } // If boundary is not `scrollParent`, then set position to `static`
194
        // to allow the menu to "escape" the scroll parent's boundaries
195
        // https://github.com/twbs/bootstrap/issues/24251
196
197
198
        if (this._config.boundary !== 'scrollParent') {
199
          $__default["default"](parent).addClass(CLASS_NAME_POSITION_STATIC);
200
        }
201
202
        this._popper = new Popper__default["default"](referenceElement, this._menu, this._getPopperConfig());
203
      } // If this is a touch-enabled device we add extra
204
      // empty mouseover listeners to the body's immediate children;
205
      // only needed because of broken event delegation on iOS
206
      // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
207
208
209
      if ('ontouchstart' in document.documentElement && $__default["default"](parent).closest(SELECTOR_NAVBAR_NAV).length === 0) {
210
        $__default["default"](document.body).children().on('mouseover', null, $__default["default"].noop);
211
      }
212
213
      this._element.focus();
214
215
      this._element.setAttribute('aria-expanded', true);
216
217
      $__default["default"](this._menu).toggleClass(CLASS_NAME_SHOW);
218
      $__default["default"](parent).toggleClass(CLASS_NAME_SHOW).trigger($__default["default"].Event(EVENT_SHOWN, relatedTarget));
219
    };
220
221
    _proto.hide = function hide() {
222
      if (this._element.disabled || $__default["default"](this._element).hasClass(CLASS_NAME_DISABLED) || !$__default["default"](this._menu).hasClass(CLASS_NAME_SHOW)) {
223
        return;
224
      }
225
226
      var relatedTarget = {
227
        relatedTarget: this._element
228
      };
229
      var hideEvent = $__default["default"].Event(EVENT_HIDE, relatedTarget);
230
231
      var parent = Dropdown._getParentFromElement(this._element);
232
233
      $__default["default"](parent).trigger(hideEvent);
234
235
      if (hideEvent.isDefaultPrevented()) {
236
        return;
237
      }
238
239
      if (this._popper) {
240
        this._popper.destroy();
241
      }
242
243
      $__default["default"](this._menu).toggleClass(CLASS_NAME_SHOW);
244
      $__default["default"](parent).toggleClass(CLASS_NAME_SHOW).trigger($__default["default"].Event(EVENT_HIDDEN, relatedTarget));
245
    };
246
247
    _proto.dispose = function dispose() {
248
      $__default["default"].removeData(this._element, DATA_KEY);
249
      $__default["default"](this._element).off(EVENT_KEY);
250
      this._element = null;
251
      this._menu = null;
252
253
      if (this._popper !== null) {
254
        this._popper.destroy();
255
256
        this._popper = null;
257
      }
258
    };
259
260
    _proto.update = function update() {
261
      this._inNavbar = this._detectNavbar();
262
263
      if (this._popper !== null) {
264
        this._popper.scheduleUpdate();
265
      }
266
    } // Private
267
    ;
268
269
    _proto._addEventListeners = function _addEventListeners() {
270
      var _this = this;
271
272
      $__default["default"](this._element).on(EVENT_CLICK, function (event) {
273
        event.preventDefault();
274
        event.stopPropagation();
275
276
        _this.toggle();
277
      });
278
    };
279
280
    _proto._getConfig = function _getConfig(config) {
281
      config = _extends({}, this.constructor.Default, $__default["default"](this._element).data(), config);
282
      Util__default["default"].typeCheckConfig(NAME, config, this.constructor.DefaultType);
283
      return config;
284
    };
285
286
    _proto._getMenuElement = function _getMenuElement() {
287
      if (!this._menu) {
288
        var parent = Dropdown._getParentFromElement(this._element);
289
290
        if (parent) {
291
          this._menu = parent.querySelector(SELECTOR_MENU);
292
        }
293
      }
294
295
      return this._menu;
296
    };
297
298
    _proto._getPlacement = function _getPlacement() {
299
      var $parentDropdown = $__default["default"](this._element.parentNode);
300
      var placement = PLACEMENT_BOTTOM; // Handle dropup
301
302
      if ($parentDropdown.hasClass(CLASS_NAME_DROPUP)) {
303
        placement = $__default["default"](this._menu).hasClass(CLASS_NAME_MENURIGHT) ? PLACEMENT_TOPEND : PLACEMENT_TOP;
304
      } else if ($parentDropdown.hasClass(CLASS_NAME_DROPRIGHT)) {
305
        placement = PLACEMENT_RIGHT;
306
      } else if ($parentDropdown.hasClass(CLASS_NAME_DROPLEFT)) {
307
        placement = PLACEMENT_LEFT;
308
      } else if ($__default["default"](this._menu).hasClass(CLASS_NAME_MENURIGHT)) {
309
        placement = PLACEMENT_BOTTOMEND;
310
      }
311
312
      return placement;
313
    };
314
315
    _proto._detectNavbar = function _detectNavbar() {
316
      return $__default["default"](this._element).closest('.navbar').length > 0;
317
    };
318
319
    _proto._getOffset = function _getOffset() {
320
      var _this2 = this;
321
322
      var offset = {};
323
324
      if (typeof this._config.offset === 'function') {
325
        offset.fn = function (data) {
326
          data.offsets = _extends({}, data.offsets, _this2._config.offset(data.offsets, _this2._element));
327
          return data;
328
        };
329
      } else {
330
        offset.offset = this._config.offset;
331
      }
332
333
      return offset;
334
    };
335
336
    _proto._getPopperConfig = function _getPopperConfig() {
337
      var popperConfig = {
338
        placement: this._getPlacement(),
339
        modifiers: {
340
          offset: this._getOffset(),
341
          flip: {
342
            enabled: this._config.flip
343
          },
344
          preventOverflow: {
345
            boundariesElement: this._config.boundary
346
          }
347
        }
348
      }; // Disable Popper if we have a static display
349
350
      if (this._config.display === 'static') {
351
        popperConfig.modifiers.applyStyle = {
352
          enabled: false
353
        };
354
      }
355
356
      return _extends({}, popperConfig, this._config.popperConfig);
357
    } // Static
358
    ;
359
360 View Code Duplication
    Dropdown._jQueryInterface = function _jQueryInterface(config) {
361
      return this.each(function () {
362
        var data = $__default["default"](this).data(DATA_KEY);
363
364
        var _config = typeof config === 'object' ? config : null;
365
366
        if (!data) {
367
          data = new Dropdown(this, _config);
368
          $__default["default"](this).data(DATA_KEY, data);
369
        }
370
371
        if (typeof config === 'string') {
372
          if (typeof data[config] === 'undefined') {
373
            throw new TypeError("No method named \"" + config + "\"");
374
          }
375
376
          data[config]();
377
        }
378
      });
379
    };
380
381
    Dropdown._clearMenus = function _clearMenus(event) {
382
      if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {
383
        return;
384
      }
385
386
      var toggles = [].slice.call(document.querySelectorAll(SELECTOR_DATA_TOGGLE));
387
388
      for (var i = 0, len = toggles.length; i < len; i++) {
389
        var parent = Dropdown._getParentFromElement(toggles[i]);
390
391
        var context = $__default["default"](toggles[i]).data(DATA_KEY);
392
        var relatedTarget = {
393
          relatedTarget: toggles[i]
394
        };
395
396
        if (event && event.type === 'click') {
397
          relatedTarget.clickEvent = event;
398
        }
399
400
        if (!context) {
401
          continue;
402
        }
403
404
        var dropdownMenu = context._menu;
405
406
        if (!$__default["default"](parent).hasClass(CLASS_NAME_SHOW)) {
407
          continue;
408
        }
409
410
        if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $__default["default"].contains(parent, event.target)) {
411
          continue;
412
        }
413
414
        var hideEvent = $__default["default"].Event(EVENT_HIDE, relatedTarget);
415
        $__default["default"](parent).trigger(hideEvent);
416
417
        if (hideEvent.isDefaultPrevented()) {
418
          continue;
419
        } // If this is a touch-enabled device we remove the extra
420
        // empty mouseover listeners we added for iOS support
421
422
423
        if ('ontouchstart' in document.documentElement) {
424
          $__default["default"](document.body).children().off('mouseover', null, $__default["default"].noop);
425
        }
426
427
        toggles[i].setAttribute('aria-expanded', 'false');
428
429
        if (context._popper) {
430
          context._popper.destroy();
431
        }
432
433
        $__default["default"](dropdownMenu).removeClass(CLASS_NAME_SHOW);
434
        $__default["default"](parent).removeClass(CLASS_NAME_SHOW).trigger($__default["default"].Event(EVENT_HIDDEN, relatedTarget));
435
      }
436
    };
437
438
    Dropdown._getParentFromElement = function _getParentFromElement(element) {
439
      var parent;
440
      var selector = Util__default["default"].getSelectorFromElement(element);
441
442
      if (selector) {
443
        parent = document.querySelector(selector);
444
      }
445
446
      return parent || element.parentNode;
447
    } // eslint-disable-next-line complexity
448
    ;
449
450
    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
451
      // If not input/textarea:
452
      //  - And not a key in REGEXP_KEYDOWN => not a dropdown command
453
      // If input/textarea:
454
      //  - If space key => not a dropdown command
455
      //  - If key is other than escape
456
      //    - If key is not up or down => not a dropdown command
457
      //    - If trigger inside the menu => not a dropdown command
458
      if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $__default["default"](event.target).closest(SELECTOR_MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {
459
        return;
460
      }
461
462
      if (this.disabled || $__default["default"](this).hasClass(CLASS_NAME_DISABLED)) {
463
        return;
464
      }
465
466
      var parent = Dropdown._getParentFromElement(this);
467
468
      var isActive = $__default["default"](parent).hasClass(CLASS_NAME_SHOW);
469
470
      if (!isActive && event.which === ESCAPE_KEYCODE) {
471
        return;
472
      }
473
474
      event.preventDefault();
475
      event.stopPropagation();
476
477
      if (!isActive || event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE) {
478
        if (event.which === ESCAPE_KEYCODE) {
479
          $__default["default"](parent.querySelector(SELECTOR_DATA_TOGGLE)).trigger('focus');
480
        }
481
482
        $__default["default"](this).trigger('click');
483
        return;
484
      }
485
486
      var items = [].slice.call(parent.querySelectorAll(SELECTOR_VISIBLE_ITEMS)).filter(function (item) {
487
        return $__default["default"](item).is(':visible');
488
      });
489
490
      if (items.length === 0) {
491
        return;
492
      }
493
494
      var index = items.indexOf(event.target);
495
496
      if (event.which === ARROW_UP_KEYCODE && index > 0) {
497
        // Up
498
        index--;
499
      }
500
501
      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
502
        // Down
503
        index++;
504
      }
505
506
      if (index < 0) {
507
        index = 0;
508
      }
509
510
      items[index].focus();
511
    };
512
513
    _createClass(Dropdown, null, [{
514
      key: "VERSION",
515
      get: function get() {
516
        return VERSION;
517
      }
518
    }, {
519
      key: "Default",
520
      get: function get() {
521
        return Default;
522
      }
523
    }, {
524
      key: "DefaultType",
525
      get: function get() {
526
        return DefaultType;
527
      }
528
    }]);
529
530
    return Dropdown;
531
  }();
532
  /**
533
   * Data API implementation
534
   */
535
536
537
  $__default["default"](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) {
538
    event.preventDefault();
539
    event.stopPropagation();
540
541
    Dropdown._jQueryInterface.call($__default["default"](this), 'toggle');
542
  }).on(EVENT_CLICK_DATA_API, SELECTOR_FORM_CHILD, function (e) {
543
    e.stopPropagation();
544
  });
545
  /**
546
   * jQuery
547
   */
548
549
  $__default["default"].fn[NAME] = Dropdown._jQueryInterface;
550
  $__default["default"].fn[NAME].Constructor = Dropdown;
551
552
  $__default["default"].fn[NAME].noConflict = function () {
553
    $__default["default"].fn[NAME] = JQUERY_NO_CONFLICT;
554
    return Dropdown._jQueryInterface;
555
  };
556
557
  return Dropdown;
558
559
}));
560
//# sourceMappingURL=dropdown.js.map
561