🌐 AI搜索 & 代理 主页
Skip to content

Commit a9a395b

Browse files
committed
Update dropdown.js
1 parent 853751d commit a9a395b

File tree

1 file changed

+25
-49
lines changed

1 file changed

+25
-49
lines changed

src/mixins/dropdown.js

Lines changed: 25 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import Popper from 'popper.js'
22
import KeyCodes from '../utils/key-codes'
33
import warn from '../utils/warn'
44
import { BvEvent } from '../utils/bv-event.class'
5-
import { from as arrayFrom } from '../utils/array'
6-
import { closest, contains, isVisible, requestAF, selectAll, eventOn, eventOff } from '../utils/dom'
5+
import { closest, contains, isVisible, requestAF, selectAll } from '../utils/dom'
76
import { isNull } from '../utils/inspect'
7+
import clickOutMixin from './click-out'
8+
import focusInMixin from './focus-in'
89
import idMixin from './id'
910

1011
// Return an array of visible items
@@ -15,9 +16,6 @@ const ROOT_DROPDOWN_PREFIX = 'bv::dropdown::'
1516
const ROOT_DROPDOWN_SHOWN = `${ROOT_DROPDOWN_PREFIX}shown`
1617
const ROOT_DROPDOWN_HIDDEN = `${ROOT_DROPDOWN_PREFIX}hidden`
1718

18-
// Delay when loosing focus before closing menu (in ms)
19-
const FOCUSOUT_DELAY = 100
20-
2119
// Dropdown item CSS selectors
2220
const Selector = {
2321
FORM_CHILD: '.dropdown form',
@@ -48,7 +46,7 @@ const AttachmentMap = {
4846

4947
// @vue/component
5048
export default {
51-
mixins: [idMixin],
49+
mixins: [idMixin, clickOutMixin, focusInMixin],
5250
provide() {
5351
return {
5452
bvDropdown: this
@@ -273,31 +271,18 @@ export default {
273271
}
274272
return { ...popperConfig, ...(this.popperOpts || {}) }
275273
},
274+
isDropdownElement(el) {
275+
return contains(this.$refs.menu, el) || contains(this.toggler, el)
276+
},
277+
// Turn listeners on/off while open
276278
whileOpenListen(isOpen) {
277-
// turn listeners on/off while open
278-
if (isOpen) {
279-
// If another dropdown is opened
280-
this.$root.$on(ROOT_DROPDOWN_SHOWN, this.rootCloseListener)
281-
// Hide the menu when focus moves out
282-
eventOn(this.$el, 'focusout', this.onFocusOut, { passive: true })
283-
} else {
284-
this.$root.$off(ROOT_DROPDOWN_SHOWN, this.rootCloseListener)
285-
eventOff(this.$el, 'focusout', this.onFocusOut, { passive: true })
286-
}
287-
// Handle special case for touch events on iOS
288-
this.setOnTouchStartListener(isOpen)
289-
},
290-
setOnTouchStartListener(isOpen) /* istanbul ignore next: No JSDOM support of `ontouchstart` */ {
291-
// If this is a touch-enabled device we add extra empty
292-
// `mouseover` listeners to the body's immediate children
293-
// Only needed because of broken event delegation on iOS
294-
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
295-
if ('ontouchstart' in document.documentElement) {
296-
const method = isOpen ? eventOn : eventOff
297-
arrayFrom(document.body.children).forEach(el => {
298-
method(el, 'mouseover', this.$_noop)
299-
})
300-
}
279+
// Hide the dropdown when clicked outside
280+
this.listenForClickOut = isOpen
281+
// Hide the dropdown when it loses focus
282+
this.listenForFocusIn = isOpen
283+
// Hide the dropdown when another dropdown is opened
284+
const method = isOpen ? '$on' : '$off'
285+
this.$root[method](ROOT_DROPDOWN_SHOWN, this.rootCloseListener)
301286
},
302287
rootCloseListener(vm) {
303288
if (vm !== this) {
@@ -391,25 +376,16 @@ export default {
391376
this.$once('hidden', this.focusToggler)
392377
}
393378
},
394-
// Dropdown wrapper focusOut handler
395-
onFocusOut(evt) {
396-
// `relatedTarget` is the element gaining focus
397-
const relatedTarget = evt.relatedTarget
398-
// If focus moves outside the menu or toggler, then close menu
399-
if (
400-
this.visible &&
401-
!contains(this.$refs.menu, relatedTarget) &&
402-
!contains(this.toggler, relatedTarget)
403-
) {
404-
const doHide = () => {
405-
this.visible = false
406-
}
407-
// When we are in a navbar (which has been responsively stacked), we
408-
// delay the dropdown's closing so that the next element has a chance
409-
// to have it's click handler fired (in case it's position moves on
410-
// the screen do to a navbar menu above it collapsing)
411-
// https://github.com/bootstrap-vue/bootstrap-vue/issues/4113
412-
this.inNavbar ? setTimeout(doHide, FOCUSOUT_DELAY) : doHide()
379+
// Document click out listener
380+
clickOutHandler(evt) {
381+
if (this.visible && !this.isDropdownElement(evt.target)) {
382+
this.visible = false
383+
}
384+
},
385+
// Document focusin listener
386+
focusInHandler(evt) {
387+
if (this.visible && !this.isDropdownElement(evt.target)) {
388+
this.visible = false
413389
}
414390
},
415391
// Keyboard nav

0 commit comments

Comments
 (0)