diff options
Diffstat (limited to 'js/dist/dropdown.js')
-rw-r--r-- | js/dist/dropdown.js | 203 |
1 files changed, 109 insertions, 94 deletions
diff --git a/js/dist/dropdown.js b/js/dist/dropdown.js index af421d5bcd..d8313bdabc 100644 --- a/js/dist/dropdown.js +++ b/js/dist/dropdown.js @@ -1,5 +1,5 @@ /*! - * Bootstrap dropdown.js v5.0.0-beta3 (https://getbootstrap.com/) + * Bootstrap dropdown.js v5.0.0 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ @@ -40,7 +40,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.0-beta3): util/index.js + * Bootstrap (v5.0.0): util/index.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -68,7 +68,7 @@ if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) { - hrefAttr = '#' + hrefAttr.split('#')[1]; + hrefAttr = `#${hrefAttr.split('#')[1]}`; } selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null; @@ -91,7 +91,7 @@ const valueType = value && isElement(value) ? 'element' : toType(value); if (!new RegExp(expectedTypes).test(valueType)) { - throw new TypeError(`${componentName.toUpperCase()}: ` + `Option "${property}" provided type "${valueType}" ` + `but expected type "${expectedTypes}".`); + throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`); } }); }; @@ -110,7 +110,23 @@ return false; }; - const noop = () => function () {}; + const isDisabled = element => { + if (!element || element.nodeType !== Node.ELEMENT_NODE) { + return true; + } + + if (element.classList.contains('disabled')) { + return true; + } + + if (typeof element.disabled !== 'undefined') { + return element.disabled; + } + + return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; + }; + + const noop = () => {}; const getjQuery = () => { const { @@ -154,7 +170,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.0-beta3): dropdown.js + * Bootstrap (v5.0.0): dropdown.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -184,7 +200,6 @@ const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`; const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`; - const CLASS_NAME_DISABLED = 'disabled'; const CLASS_NAME_SHOW = 'show'; const CLASS_NAME_DROPUP = 'dropup'; const CLASS_NAME_DROPEND = 'dropend'; @@ -205,14 +220,16 @@ boundary: 'clippingParents', reference: 'toggle', display: 'dynamic', - popperConfig: null + popperConfig: null, + autoClose: true }; const DefaultType = { offset: '(array|string|function)', boundary: '(string|element)', reference: '(string|element|object)', display: 'string', - popperConfig: '(null|object|function)' + popperConfig: '(null|object|function)', + autoClose: '(boolean|string)' }; /** * ------------------------------------------------------------------------ @@ -246,15 +263,14 @@ toggle() { - if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED)) { + if (isDisabled(this._element)) { return; } const isActive = this._element.classList.contains(CLASS_NAME_SHOW); - Dropdown.clearMenus(); - if (isActive) { + this.hide(); return; } @@ -262,7 +278,7 @@ } show() { - if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED) || this._menu.classList.contains(CLASS_NAME_SHOW)) { + if (isDisabled(this._element) || this._menu.classList.contains(CLASS_NAME_SHOW)) { return; } @@ -313,7 +329,7 @@ if ('ontouchstart' in document.documentElement && !parent.closest(SELECTOR_NAVBAR_NAV)) { - [].concat(...document.body.children).forEach(elem => EventHandler__default['default'].on(elem, 'mouseover', null, noop())); + [].concat(...document.body.children).forEach(elem => EventHandler__default['default'].on(elem, 'mouseover', noop)); } this._element.focus(); @@ -328,33 +344,18 @@ } hide() { - if (this._element.disabled || this._element.classList.contains(CLASS_NAME_DISABLED) || !this._menu.classList.contains(CLASS_NAME_SHOW)) { + if (isDisabled(this._element) || !this._menu.classList.contains(CLASS_NAME_SHOW)) { return; } const relatedTarget = { relatedTarget: this._element }; - const hideEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE, relatedTarget); - - if (hideEvent.defaultPrevented) { - return; - } - if (this._popper) { - this._popper.destroy(); - } - - this._menu.classList.toggle(CLASS_NAME_SHOW); - - this._element.classList.toggle(CLASS_NAME_SHOW); - - Manipulator__default['default'].removeDataAttribute(this._menu, 'popper'); - EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN, relatedTarget); + this._completeHide(relatedTarget); } dispose() { - EventHandler__default['default'].off(this._element, EVENT_KEY); this._menu = null; if (this._popper) { @@ -382,6 +383,33 @@ }); } + _completeHide(relatedTarget) { + const hideEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE, relatedTarget); + + if (hideEvent.defaultPrevented) { + return; + } // If this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + + + if ('ontouchstart' in document.documentElement) { + [].concat(...document.body.children).forEach(elem => EventHandler__default['default'].off(elem, 'mouseover', noop)); + } + + if (this._popper) { + this._popper.destroy(); + } + + this._menu.classList.remove(CLASS_NAME_SHOW); + + this._element.classList.remove(CLASS_NAME_SHOW); + + this._element.setAttribute('aria-expanded', 'false'); + + Manipulator__default['default'].removeDataAttribute(this._menu, 'popper'); + EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN, relatedTarget); + } + _getConfig(config) { config = { ...this.constructor.Default, ...Manipulator__default['default'].getDataAttributes(this._element), @@ -468,6 +496,29 @@ return { ...defaultBsPopperConfig, ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig) }; + } + + _selectMenuItem(event) { + const items = SelectorEngine__default['default'].find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(isVisible); + + if (!items.length) { + return; + } + + let index = items.indexOf(event.target); // Up + + if (event.key === ARROW_UP_KEY && index > 0) { + index--; + } // Down + + + if (event.key === ARROW_DOWN_KEY && index < items.length - 1) { + index++; + } // index is -1 if the first keydown is an ArrowUp + + + index = index === -1 ? 0 : index; + items[index].focus(); } // Static @@ -501,7 +552,7 @@ return; } - if (/input|select|textarea|form/i.test(event.target.tagName)) { + if (/input|select|option|textarea|form/i.test(event.target.tagName)) { return; } } @@ -510,58 +561,38 @@ for (let i = 0, len = toggles.length; i < len; i++) { const context = Data__default['default'].get(toggles[i], DATA_KEY); - const relatedTarget = { - relatedTarget: toggles[i] - }; - - if (event && event.type === 'click') { - relatedTarget.clickEvent = event; - } - if (!context) { + if (!context || context._config.autoClose === false) { continue; } - const dropdownMenu = context._menu; - - if (!toggles[i].classList.contains(CLASS_NAME_SHOW)) { + if (!context._element.classList.contains(CLASS_NAME_SHOW)) { continue; } + const relatedTarget = { + relatedTarget: context._element + }; + if (event) { - // Don't close the menu if the clicked element or one of its parents is the dropdown button - if ([context._element].some(element => event.composedPath().includes(element))) { + const composedPath = event.composedPath(); + const isMenuTarget = composedPath.includes(context._menu); + + if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) { continue; } // Tab navigation through the dropdown menu shouldn't close the menu - if (event.type === 'keyup' && event.key === TAB_KEY && dropdownMenu.contains(event.target)) { + if (event.type === 'keyup' && event.key === TAB_KEY && context._menu.contains(event.target)) { continue; } - } - - const hideEvent = EventHandler__default['default'].trigger(toggles[i], EVENT_HIDE, relatedTarget); - - if (hideEvent.defaultPrevented) { - continue; - } // If this is a touch-enabled device we remove the extra - // empty mouseover listeners we added for iOS support - - - if ('ontouchstart' in document.documentElement) { - [].concat(...document.body.children).forEach(elem => EventHandler__default['default'].off(elem, 'mouseover', null, noop())); - } - - toggles[i].setAttribute('aria-expanded', 'false'); - if (context._popper) { - context._popper.destroy(); + if (event.type === 'click') { + relatedTarget.clickEvent = event; + } } - dropdownMenu.classList.remove(CLASS_NAME_SHOW); - toggles[i].classList.remove(CLASS_NAME_SHOW); - Manipulator__default['default'].removeDataAttribute(dropdownMenu, 'popper'); - EventHandler__default['default'].trigger(toggles[i], EVENT_HIDDEN, relatedTarget); + context._completeHide(relatedTarget); } } @@ -581,26 +612,29 @@ return; } + const isActive = this.classList.contains(CLASS_NAME_SHOW); + + if (!isActive && event.key === ESCAPE_KEY) { + return; + } + event.preventDefault(); event.stopPropagation(); - if (this.disabled || this.classList.contains(CLASS_NAME_DISABLED)) { + if (isDisabled(this)) { return; } - const parent = Dropdown.getParentFromElement(this); - const isActive = this.classList.contains(CLASS_NAME_SHOW); + const getToggleButton = () => this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine__default['default'].prev(this, SELECTOR_DATA_TOGGLE)[0]; if (event.key === ESCAPE_KEY) { - const button = this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine__default['default'].prev(this, SELECTOR_DATA_TOGGLE)[0]; - button.focus(); + getToggleButton().focus(); Dropdown.clearMenus(); return; } if (!isActive && (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY)) { - const button = this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine__default['default'].prev(this, SELECTOR_DATA_TOGGLE)[0]; - button.click(); + getToggleButton().click(); return; } @@ -609,26 +643,7 @@ return; } - const items = SelectorEngine__default['default'].find(SELECTOR_VISIBLE_ITEMS, parent).filter(isVisible); - - if (!items.length) { - return; - } - - let index = items.indexOf(event.target); // Up - - if (event.key === ARROW_UP_KEY && index > 0) { - index--; - } // Down - - - if (event.key === ARROW_DOWN_KEY && index < items.length - 1) { - index++; - } // index is -1 if the first keydown is an ArrowUp - - - index = index === -1 ? 0 : index; - items[index].focus(); + Dropdown.getInstance(getToggleButton())._selectMenuItem(event); } } |