@@ -386,16 +386,8 @@ export default Vue.extend({
386
386
return
387
387
}
388
388
this . is_opening = true
389
- // Note: On IE11, `document.activeElement` may be null. So we test it for
390
- // truthyness first.
391
- // https://github.com/bootstrap-vue/bootstrap-vue/issues/3206
392
- if ( isBrowser && document . activeElement && document . activeElement . focus ) {
393
- // Preset the fallback return focus value if it is not set
394
- // `document.activeElement` should be the trigger element that was clicked or
395
- // in the case of using the v-model, which ever element has current focus
396
- // Will be overridden by some commands such as toggle, etc.
397
- this . return_focus = this . return_focus || document . activeElement
398
- }
389
+ // Set the element to return focus to when closed
390
+ this . return_focus = this . return_focus || this . getActiveElement ( )
399
391
const showEvt = new BvModalEvent ( 'show' , {
400
392
cancelable : true ,
401
393
vueTarget : this ,
@@ -465,6 +457,25 @@ export default Vue.extend({
465
457
this . show ( )
466
458
}
467
459
} ,
460
+ // Private method to get the current document active element
461
+ getActiveElement ( ) {
462
+ if ( isBrowser ) {
463
+ const activeElement = document . activeElement
464
+ // Note: On IE11, `document.activeElement` may be null. So we test it for
465
+ // truthyness first.
466
+ // https://github.com/bootstrap-vue/bootstrap-vue/issues/3206
467
+ // Returning focus to document.body may cause unwanted scrolls, so we
468
+ // exclude setting focus on body
469
+ if ( activeElement && activeElement !== document . body && activeElement . focus ) {
470
+ // Preset the fallback return focus value if it is not set
471
+ // `document.activeElement` should be the trigger element that was clicked or
472
+ // in the case of using the v-model, which ever element has current focus
473
+ // Will be overridden by some commands such as toggle, etc.
474
+ return activeElement
475
+ }
476
+ }
477
+ return null
478
+ } ,
468
479
// Private method to finish showing modal
469
480
doShow ( ) {
470
481
/* istanbul ignore next: commenting out for now until we can test stacking */
@@ -631,7 +642,7 @@ export default Vue.extend({
631
642
// Root listener handlers
632
643
showHandler ( id , triggerEl ) {
633
644
if ( id === this . id ) {
634
- this . return_focus = triggerEl || document . activeElement || null
645
+ this . return_focus = triggerEl || this . getActiveElement ( )
635
646
this . show ( )
636
647
}
637
648
} ,
@@ -658,7 +669,7 @@ export default Vue.extend({
658
669
// Don't try and focus if we are SSR
659
670
if ( isBrowser ) {
660
671
const modal = this . $refs . modal
661
- const activeElement = document . activeElement
672
+ const activeElement = this . getActiveElement ( )
662
673
// If the modal contains the activeElement, we don't do anything
663
674
if ( modal && ! ( activeElement && contains ( modal , activeElement ) ) ) {
664
675
// Make sure top of modal is showing (if longer than the viewport)
@@ -673,7 +684,7 @@ export default Vue.extend({
673
684
returnFocusTo ( ) {
674
685
// Prefer `returnFocus` prop over event specified
675
686
// `return_focus` value
676
- let el = this . returnFocus || this . return_focus || document . activeElement || null
687
+ let el = this . returnFocus || this . return_focus || null
677
688
// Is el a string CSS selector?
678
689
el = isString ( el ) ? select ( el ) : el
679
690
if ( el ) {
0 commit comments