New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scroll and focus issue with multiple modals open. #70

Open
mreis1 opened this Issue Aug 17, 2014 · 34 comments

Comments

Projects
None yet
@mreis1

mreis1 commented Aug 17, 2014

Tested with version 1.33 and 1.32.

If 2 modals are open at the same time and we close the top level modal, the second loses focus.

By losing focus i mean:

  • scrolling the modal is not possible if it exceeds the page height of our viewport
  • the page (behind the modal) scrolls.

Probably this has an easy fix:
By getting the modal that were open before the last modal (the one that we are closing) and calling
$('modal_behind_toplevel_modal').data()['bs.modal'].show() solves the problem.

@mreis1

This comment has been minimized.

mreis1 commented Aug 17, 2014

This does the trick but probably needs more work.
Changes were made at BootstrapDialog.prototype

handleModalEvents: function(){ 
this.getModal().on('hidden.bs.modal', {
                dialog: this
            }, $.proxy(function(event) {
                var dialog = event.data.dialog;
                typeof dialog.options.onhidden === 'function' && dialog.options.onhidden(dialog);
                dialog.isAutodestroy() && $(this).remove();
                dialog.showPageScrollBar(false);

                setTimeout($.proxy(function(){
                    if (this.modalBehind) this.modalBehind.show();
                },this),100);

            },this));
},
//........... other methods
close: function() {
            this.getModal().modal('hide');

            var modalBehind;
            this.modalBehind = modalBehind = this.getModalBehind();
            if (this.isAutodestroy()) {
                delete BootstrapDialog.dialogs[this.getId()];
            }

            this.setOpened(false);

            return this;
        },
        getModalBehind: function(){
            var keys = [],
                numKeys = 0;

            $.each(BootstrapDialog.dialogs, function( key, value ){
                keys.push(key);
            });

            numKeys = keys.length;

            if ( numKeys > 1){

                var pos = keys.indexOf(this.getId());

                if (pos == 0 || pos == -1){
                    return false;
                } else {

                    var dialog = BootstrapDialog.dialogs[ keys[pos - 1] ];
                    return dialog.$modal.data()["bs.modal"];
                }


            } else {
                return false;
            }
        }
@nakupanda

This comment has been minimized.

Owner

nakupanda commented Aug 18, 2014

Hi,

Thanks for this report and the hints.

Will look into it!

Thank you.

@nakupanda

This comment has been minimized.

Owner

nakupanda commented Aug 18, 2014

Hi,

Please see this first. http://jsbin.com/hekizevaseqi/1/edit

It seems to work ok on scrolling, but another problem was found: clicking on the scrollbar will cause the dialog closing..

@mreis1

This comment has been minimized.

mreis1 commented Aug 18, 2014

Thanks, I'll check in my code to see what might be causing the problem. The truth is, without the lines added above i got a unscrollable "modalBehind" and a scrollable HTML page. The reason is still a mystery because your demo is working fine.

@mreis1

This comment has been minimized.

mreis1 commented Aug 21, 2014

Ok, the problem related to last visible modal focus when the top level modal is closed seems to be solved in your last version.

Anyway I would like to ask you are aware of a very well known issue related with bootstrap modal plugin (not bootstrap3-dialog). It seems that iOS devices have issues rendering fixed elements like TWBS reported here twbs/bootstrap@53c80ed

Also, overflow:hidden doesn't seem to work when applied to

Focusing elements inside fixed elements like inputs or textareas that trigger the virtual keyboard to appear also cause the rendering issues as can be seen below:
http://remysharp.com/2012/05/24/issues-with-position-fixed-scrolling-on-ios/

@nakupanda

This comment has been minimized.

Owner

nakupanda commented Sep 2, 2014

Still have no idea :(

@fithwith

This comment has been minimized.

fithwith commented Nov 26, 2014

+1 yes i have the same issue, its to much important.

@yavuz

This comment has been minimized.

yavuz commented Nov 27, 2014

I wrote it in my file;

.modal { overflow: auto !important; }

but, only temporary

@nakupanda

This comment has been minimized.

Owner

nakupanda commented Nov 27, 2014

Maybe this is why Bootstrap doesn't support opening multiple modals at the same time.

@nakupanda

This comment has been minimized.

Owner

nakupanda commented Dec 3, 2014

Have just created some stuff for this problem for modal v3.3.0+, it worked like a charm.

I was confusing if I should create one more compatible version for older version of modal, as I'm not sure if people would be glad to update their bootstrap to the latest one.

@mreis1

This comment has been minimized.

mreis1 commented Jan 15, 2015

@nakupanda sorry, I've been way from github. Have you come to a decision?

@nakupanda

This comment has been minimized.

Owner

nakupanda commented Jan 19, 2015

Yep, some updates have been applied, hope they're working well.

@GabLeRoux

This comment has been minimized.

GabLeRoux commented Apr 30, 2015

Had similar issue on bootstrap#3.3.4, having multiple modals one over the others seems bad to me, but thanks to @yavuz, it did the trick for now

.modal { overflow: auto !important; }
@cdiazr

This comment has been minimized.

cdiazr commented Jun 12, 2015

easy man! when you open a modal, exist one class named "modal-open" on the first modal. When you close the sencond one, that class is going to delete. Just you have to program "close button" on the second modal with javascript.

when you click on Close or Cancel-> $('{modal}').addClass('modal-open);

@taburetkin

This comment has been minimized.

taburetkin commented Jul 2, 2015

i have faced same problem.
i don't understand why this happens but the key thing in body class 'modal-open'
my case:
when i open first modal body tag receives class 'modal-open'.
then i open the second modal without closing first and it opens - everything is ok
then i close second modal and this action removes from body class 'modal-open'
so the first one lose overflow-y:auto directive

there no such promblem in the fiddle of nakupanda - after closing second modal the body don't lose class 'modal-open'

@simonalmar

This comment has been minimized.

simonalmar commented Jul 18, 2015

$('{modal}').on('hidden.bs.modal', function (e) {
    $('body').addClass('modal-open');
})';

@efkan

This comment has been minimized.

efkan commented Aug 13, 2015

Thanx Simon, it works like a charm! 👍
Actually I tried to add the class to the modal div for 3 hour. I couldn't see the modal-open class an inherited styles from the body. Really thanx!

@FireSBurnsmuP

This comment has been minimized.

FireSBurnsmuP commented Aug 18, 2015

Still had this problem with the latest version when opening a dialog from within a native .modal,
but probably only because I'm mixing BootstrapDialogs with multiple native modals, but here's a fix for anyone who requires one.

// This just makes all bootstrap native .modals jive together
$('.modal').on("hidden.bs.modal", function (e) {
    if($('.modal:visible').length)
    {
        $('.modal-backdrop').first().css('z-index', parseInt($('.modal:visible').last().css('z-index')) - 10);
        $('body').addClass('modal-open');
    }
}).on("show.bs.modal", function (e) {
    if($('.modal:visible').length)
    {
        $('.modal-backdrop.in').first().css('z-index', parseInt($('.modal:visible').last().css('z-index')) + 10);
        $(this).css('z-index', parseInt($('.modal-backdrop.in').first().css('z-index')) + 10);
    }
});

Since I was already using multiple native .modals, and had used this fix on them, in order for BootstrapDialogs to jive with my stuff, I needed to do this for them as well.

// This dialog will not break other dialogs or modals
var myDialog = new BootstrapDialog({
    onhidden: function(dialogRef){
        if($('.modal:visible').length)
        {
            $('.modal-backdrop').first().css('z-index', parseInt($('.modal:visible').last().css('z-index')) - 10);
            $('body').addClass('modal-open');
        }
    },
    onshow: function(dialogRef){
        if($('.modal:visible').length)
        {
            $('.modal-backdrop.in').first().css('z-index', parseInt($('.modal:visible').last().css('z-index')) + 10);
            $(this).css('z-index', parseInt($('.modal-backdrop.in').first().css('z-index')) + 10);
        }
    }
});

Hope this helps the next person with my particular problem. @simonalmar has a solution above for anyone that doesn't need multiple modals and dialogs open at the same time.

@nakupanda

This comment has been minimized.

Owner

nakupanda commented Aug 19, 2015

Hi @FireSBurnsmuP ,

Can you please create an online example to reproduce the problem? If native modal got modified by BootstrapDialog, I think it's a problem.

@FireSBurnsmuP

This comment has been minimized.

FireSBurnsmuP commented Aug 26, 2015

@nakupanda I believe you misunderstood.
My problem was that I had already patched the native .modal to make multiple native .modals work (with the first code-block), which, for some reason, made BootstrapDialogs not hide their backdrop and break scrolling again. I couldn't figure out why that code block didn't affect the modals generated by BootstrapDialog, but the fact remained that it did.
However, if the second code block is used when creating a BootstrapDialog this will fix the problem.

I tried to get a jsfiddle up and running, but I couldn't get bootstrap-dialog to work in the fiddle, so I'm afraid I cannot give you an online demo.
However, if you simply add the first code-block from my previous post earlier in the javascript execution, then try to open a BootstrapDialog from within a native modal, you'll notice that scrolling is broken and the backdrop doesn't go away when you close the dialog.
Using the code from my second code-block you should be able to get it working again.

@Chintan7027

This comment has been minimized.

Chintan7027 commented Sep 10, 2015

Thanks @FireSBurnsmuP Your code is work for me

@omaji7

This comment has been minimized.

omaji7 commented Nov 6, 2015

Thanks alot @FireSBurnsmuP, your code rocks.

@mxmauro

This comment has been minimized.

mxmauro commented May 21, 2016

Based on @FireSBurnsmuP help, run this code snippet somewhere after jQuey is initialized (and before any modal is opened)

This will override the trigger method used by modal dialogs to inform about events so all modals (yours and opened by third-party plugins) should be affected.

var oldJqTrigger = jQuery.fn.trigger;
jQuery.fn.trigger = function()
{
    if ( arguments && arguments.length > 0) {
        if (typeof arguments[0] == "object") {
            if (typeof arguments[0].type == "string") {
                if (arguments[0].type == "show.bs.modal") {
                    var ret = oldJqTrigger.apply(this, arguments);
                    if ($('.modal:visible').length) {
                        $('.modal-backdrop.in').first().css('z-index', parseInt($('.modal:visible').last().css('z-index')) + 10);
                        $(this).css('z-index', parseInt($('.modal-backdrop.in').first().css('z-index')) + 10);
                    }
                    return ret;
                }
            }
        }
        else if (typeof arguments[0] == "string") {
            if (arguments[0] == "hidden.bs.modal") {
                if ($('.modal:visible').length) {
                    $('.modal-backdrop').first().css('z-index', parseInt($('.modal:visible').last().css('z-index')) - 10);
                    $('body').addClass('modal-open');
                }
            }
        }
    }
    return oldJqTrigger.apply(this, arguments);
};
@luislobo

This comment has been minimized.

luislobo commented Jun 16, 2016

@mxmauro Your snippet rocks!

@ibrahimokdadov

This comment has been minimized.

ibrahimokdadov commented Jul 11, 2016

@FireSBurnsmuP your solution worked for me. I used it on summernote plugin and worked as well. thnx

@lrsousa

This comment has been minimized.

lrsousa commented Jul 22, 2016

var stackModal = 0;
$(document).on('show.bs.modal',` '.modal', function (event) {
    var zIndex = 1040 + (10 * $('.modal:visible').length);
    $(this).css('z-index', zIndex);
    stackModal++;
    setTimeout(function() {
        $('.modal-backdrop').not('.modal-stack').css('z-index', zIndex - 1).addClass('modal-stack');
    }, 0);
});

$(document).on('hidden.bs.modal', '.modal', function (event) {
    stackModal--;
    if(stackModal > 0) {
        $('body').addClass("modal-open");
    } else {
        $('body').removeClass("modal-open");
    }
});
@mxmauro

This comment has been minimized.

mxmauro commented Jul 22, 2016

@lrsousa as far as I remember, the modal might not be on the body so you won't catch show.bs.modal event. If you see bootstrap source code, after backdrop loop ends, the $element is added to the main dom.

@jofftiquez

This comment has been minimized.

jofftiquez commented Oct 10, 2016

.modal { overflow: auto !important; } Not all heroes wear capes. Thanks @yavuz <3

@dyegoalves

This comment has been minimized.

dyegoalves commented Jul 20, 2017

@FireSBurnsmuP Thank my friend , me save :)

@dmikester1

This comment has been minimized.

dmikester1 commented Jul 31, 2017

Thanks @FireSBurnsmuP! Worked great for me as well! Wish they would make this work in the official Bootstrap code!

@sohaibjaved44

This comment has been minimized.

sohaibjaved44 commented Aug 17, 2017

Hey @jofftiquez Thanks!! I have tried your workaround it was not working using css file so I implemented it with jquery $(".modal-content").parent().parent().css("overflow", "auto");
it worked for me this way.
I am facing this problem in latest version i.e. "@ng-bootstrap/ng-bootstrap": "^1.6.3" so its not fixed yet?

@DougInAlabama

This comment has been minimized.

DougInAlabama commented Aug 24, 2017

Thanks @sohaibjaved44! I was in the same boat also, your one line was what I needed!

@saumitrak11

This comment has been minimized.

saumitrak11 commented Oct 16, 2018

.modal { overflow: auto !important; }
Not all heros wear Caps !!

@alirazashah

This comment has been minimized.

alirazashah commented Jan 5, 2019

.modal { overflow: auto !important; }
Works like charm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment