diff options
| author | Mark Otto <[email protected]> | 2017-04-16 14:03:25 -0700 |
|---|---|---|
| committer | Mark Otto <[email protected]> | 2017-04-16 14:03:25 -0700 |
| commit | 570efe1df6620c9bd6e70cf0bd8d87e42ac6e892 (patch) | |
| tree | e4a0600341e579a45d4e2fe550362656d503490d /js/src | |
| parent | 0cb2576bf25220d35a5f4e1d33c16c2e6f3abaee (diff) | |
| parent | ea1d69c64be168bb644ae9fc4450a5c85b51609b (diff) | |
| download | bootstrap-570efe1df6620c9bd6e70cf0bd8d87e42ac6e892.tar.xz bootstrap-570efe1df6620c9bd6e70cf0bd8d87e42ac6e892.zip | |
Merge branch 'v4-dev' into form-tweaks
Diffstat (limited to 'js/src')
| -rw-r--r-- | js/src/button.js | 8 | ||||
| -rw-r--r-- | js/src/collapse.js | 4 | ||||
| -rw-r--r-- | js/src/dropdown.js | 51 | ||||
| -rw-r--r-- | js/src/modal.js | 1 |
4 files changed, 30 insertions, 34 deletions
diff --git a/js/src/button.js b/js/src/button.js index 76c5cdd15..6295d0db0 100644 --- a/js/src/button.js +++ b/js/src/button.js @@ -66,6 +66,7 @@ const Button = (($) => { toggle() { let triggerChangeEvent = true + let addAriaPressed = true const rootElement = $(this._element).closest( Selector.DATA_TOGGLE )[0] @@ -94,12 +95,15 @@ const Button = (($) => { } input.focus() + addAriaPressed = false } } - this._element.setAttribute('aria-pressed', - !$(this._element).hasClass(ClassName.ACTIVE)) + if (addAriaPressed) { + this._element.setAttribute('aria-pressed', + !$(this._element).hasClass(ClassName.ACTIVE)) + } if (triggerChangeEvent) { $(this._element).toggleClass(ClassName.ACTIVE) diff --git a/js/src/collapse.js b/js/src/collapse.js index 88428310d..dec272297 100644 --- a/js/src/collapse.js +++ b/js/src/collapse.js @@ -162,7 +162,6 @@ const Collapse = (($) => { .addClass(ClassName.COLLAPSING) this._element.style[dimension] = 0 - this._element.setAttribute('aria-expanded', true) if (this._triggerArray.length) { $(this._triggerArray) @@ -223,8 +222,6 @@ const Collapse = (($) => { .removeClass(ClassName.COLLAPSE) .removeClass(ClassName.SHOW) - this._element.setAttribute('aria-expanded', false) - if (this._triggerArray.length) { $(this._triggerArray) .addClass(ClassName.COLLAPSED) @@ -300,7 +297,6 @@ const Collapse = (($) => { _addAriaAndCollapsedClass(element, triggerArray) { if (element) { const isOpen = $(element).hasClass(ClassName.SHOW) - element.setAttribute('aria-expanded', isOpen) if (triggerArray.length) { $(triggerArray) diff --git a/js/src/dropdown.js b/js/src/dropdown.js index 644273a0a..812e718a8 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -25,10 +25,11 @@ const Dropdown = (($) => { const JQUERY_NO_CONFLICT = $.fn[NAME] const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key const SPACE_KEYCODE = 32 // KeyboardEvent.which value for space key + const TAB_KEYCODE = 9 // KeyboardEvent.which value for tab key const ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key const ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse) - const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}|${SPACE_KEYCODE}`) + const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`) const Event = { HIDE : `hide${EVENT_KEY}`, @@ -37,25 +38,21 @@ const Dropdown = (($) => { SHOWN : `shown${EVENT_KEY}`, CLICK : `click${EVENT_KEY}`, CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`, - FOCUSIN_DATA_API : `focusin${EVENT_KEY}${DATA_API_KEY}`, - KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}` + KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`, + KEYUP_DATA_API : `keyup${EVENT_KEY}${DATA_API_KEY}` } const ClassName = { - BACKDROP : 'dropdown-backdrop', DISABLED : 'disabled', SHOW : 'show' } const Selector = { - BACKDROP : '.dropdown-backdrop', DATA_TOGGLE : '[data-toggle="dropdown"]', FORM_CHILD : '.dropdown form', - ROLE_MENU : '[role="menu"]', - ROLE_LISTBOX : '[role="listbox"]', + MENU : '.dropdown-menu', NAVBAR_NAV : '.navbar-nav', - VISIBLE_ITEMS : '[role="menu"] li:not(.disabled) a, ' - + '[role="listbox"] li:not(.disabled) a' + VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled)' } @@ -108,15 +105,13 @@ const Dropdown = (($) => { return false } - // set the backdrop only if the dropdown menu will be opened + // 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) { - - // if mobile we use a backdrop because click events don't delegate - const dropdown = document.createElement('div') - dropdown.className = ClassName.BACKDROP - $(dropdown).insertBefore(this) - $(dropdown).on('click', Dropdown._clearMenus) + $('body').children().on('mouseover', '*', $.noop) } this.focus() @@ -163,7 +158,8 @@ const Dropdown = (($) => { } static _clearMenus(event) { - if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) { + if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || + event.type === 'keyup' && event.which !== TAB_KEYCODE)) { return } @@ -180,7 +176,7 @@ const Dropdown = (($) => { } if (event && (event.type === 'click' && - /input|textarea/i.test(event.target.tagName) || event.type === 'focusin') + /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $.contains(parent, event.target)) { continue } @@ -191,10 +187,10 @@ const Dropdown = (($) => { continue } - // remove backdrop only if the dropdown menu will be hidden - const backdrop = $(parent).find(Selector.BACKDROP)[0] - if (backdrop) { - backdrop.parentNode.removeChild(backdrop) + // 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', '*', $.noop) } toggles[i].setAttribute('aria-expanded', 'false') @@ -217,7 +213,7 @@ const Dropdown = (($) => { } static _dataApiKeydownHandler(event) { - if (!REGEXP_KEYDOWN.test(event.which) || + if (!REGEXP_KEYDOWN.test(event.which) || /button/i.test(event.target.tagName) && event.which === SPACE_KEYCODE || /input|textarea/i.test(event.target.tagName)) { return } @@ -232,8 +228,8 @@ const Dropdown = (($) => { const parent = Dropdown._getParentFromElement(this) const isActive = $(parent).hasClass(ClassName.SHOW) - if (!isActive && event.which !== ESCAPE_KEYCODE || - isActive && event.which === ESCAPE_KEYCODE) { + if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || + isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { if (event.which === ESCAPE_KEYCODE) { const toggle = $(parent).find(Selector.DATA_TOGGLE)[0] @@ -278,9 +274,8 @@ const Dropdown = (($) => { $(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.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, Dropdown.prototype.toggle) .on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => { e.stopPropagation() diff --git a/js/src/modal.js b/js/src/modal.js index 779b9a402..02d463945 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -289,6 +289,7 @@ const Modal = (($) => { if (this._isShown && this._config.keyboard) { $(this._element).on(Event.KEYDOWN_DISMISS, (event) => { if (event.which === ESCAPE_KEYCODE) { + event.preventDefault() this.hide() } }) |
