javascript - Flere modaler overlagret


Jeg trenger at overleggen vises over den første modalen, ikke bak.

$('#openBtn').click(function(){
	$('#myModal').modal({show:true})
});
<a data-toggle="modal" href="#myModal" class="btn btn-primary">Launch modal</a>

<div class="modal" id="myModal">
	<div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
          <h4 class="modal-title">Modal title</h4>
        </div><div class="container"></div>
        <div class="modal-body">
          Content for the dialog / modal goes here.
          <br>
          <br>
          <br>
          <br>
          <br>
          <a data-toggle="modal" href="#myModal2" class="btn btn-primary">Launch modal</a>
        </div>
        <div class="modal-footer">
          <a href="#" data-dismiss="modal" class="btn">Close</a>
          <a href="#" class="btn btn-primary">Save changes</a>
        </div>
      </div>
    </div>
</div>
<div class="modal" id="myModal2" data-backdrop="static">
	<div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
          <h4 class="modal-title">Second Modal title</h4>
        </div><div class="container"></div>
        <div class="modal-body">
          Content for the dialog / modal goes here.
        </div>
        <div class="modal-footer">
          <a href="#" data-dismiss="modal" class="btn">Close</a>
          <a href="#" class="btn btn-primary">Save changes</a>
        </div>
      </div>
    </div>
</div>


<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/js/bootstrap.min.js"></script>

Jeg prøvde å endre z-index til .modal-backdrop, men det blir kaos.

I noen tilfeller har jeg mer enn to modale på samme side.

Svar #1

Løsning inspirert av svarene fra @YermoLamers & @Ketwaroo.

Backdrop z-indeks løsning
Denne løsningen bruker en setTimeout fordi .modal-backdrop ikke er opprettet når hendelsen show.bs.modal utløses.

$(document).on('show.bs.modal', '.modal', function() {
  const zIndex = 1040 + 10 * $('.modal:visible').length;
  $(this).css('z-index', zIndex);
  setTimeout(() => $('.modal-backdrop').not('.modal-stack').css('z-index', zIndex - 1).addClass('modal-stack'));
});
  • Dette fungerer for hver .modal som er opprettet på siden (selv dynamiske modalvinduer)
  • Bakgrunnen legges straks over den forrige modalen

Eksempel jsfiddle

z-index
Hvis du ikke liker den hardkodede z-index av en eller annen grunn, kan du beregne den høyeste z-indexen på siden slik:

const zIndex = 10 +
  Math.max(...Array.from(document.querySelectorAll('*')).map((el) => +el.style.zIndex));

Rullefeltfiks
Hvis du har en modal på siden din som overskrider nettleserens høyde, kan du ikke bla i den når du lukker en annen modal. For å fikse dette, legg til:

$(document).on('hidden.bs.modal', '.modal',
  () => $('.modal:visible').length && $(document.body).addClass('modal-open'));

Versjoner
Denne løsningen er testet med bootstrap 3.1.0 - 3.3.5

Svar #2

Jeg innser at et svar har blitt akseptert, men jeg anbefaler sterkt å ikke hacke bootstrap for å fikse dette.

Du kan ganske enkelt oppnå samme effekt ved å koble til eventhåndtererne shown.bs.modal og hidden.bs.modal og justere z-indeksen der.

Her er et fungerende eksempel

Litt mer informasjon er tilgjengelig her.

Denne løsningen fungerer automatisk med modaler som er stablet vilkårlig dypt.

Kildkoden til skriptet:

$(document).ready(function() {

    $('.modal').on('hidden.bs.modal', function(event) {
        $(this).removeClass( 'fv-modal-stack' );
        $('body').data( 'fv_open_modals', $('body').data( 'fv_open_modals' ) - 1 );
    });

    $('.modal').on('shown.bs.modal', function (event) {
        // keep track of the number of open modals
        if ( typeof( $('body').data( 'fv_open_modals' ) ) == 'undefined' ) {
            $('body').data( 'fv_open_modals', 0 );
        }

        // if the z-index of this modal has been set, ignore.
        if ($(this).hasClass('fv-modal-stack')) {
            return;
        }

        $(this).addClass('fv-modal-stack');
        $('body').data('fv_open_modals', $('body').data('fv_open_modals' ) + 1 );
        $(this).css('z-index', 1040 + (10 * $('body').data('fv_open_modals' )));
        $('.modal-backdrop').not('.fv-modal-stack').css('z-index', 1039 + (10 * $('body').data('fv_open_modals')));
        $('.modal-backdrop').not('fv-modal-stack').addClass('fv-modal-stack'); 

    });        
});

Svar #3

Kombinert A1rPuns svar med forslaget fra StriplingWarrior, kom jeg opp med dette:

$(document).on({
    'show.bs.modal': function () {
        var zIndex = 1040 + (10 * $('.modal:visible').length);
        $(this).css('z-index', zIndex);
        setTimeout(function() {
            $('.modal-backdrop').not('.modal-stack').css('z-index', zIndex - 1).addClass('modal-stack');
        }, 0);
    },
    'hidden.bs.modal': function() {
        if ($('.modal:visible').length > 0) {
            // restore the modal-open class to the body element, so that scrolling works
            // properly after de-stacking a modal.
            setTimeout(function() {
                $(document.body).addClass('modal-open');
            }, 0);
        }
    }
}, '.modal');

Fungerer selv for dynamiske modaler som legges til i ettertid, og fjerner problemet med den andre rullefeltet. Det mest bemerkelsesverdige jeg fant dette nyttig for, var å integrere skjemaer inne i modaler med valideringsmeldinger fra Bootbox-varsler, siden disse bruker dynamiske modaler og dermed krever at du binder hendelsen til dokumentet i stedet for til .modal, siden det bare fester den til eksisterende modaler.

Fiolin her.

Svar #4

Noe kortere versjon basert på Yermo Lamers' forslag, dette ser ut til å fungere greit. Selv med enkle animasjoner som fade inn/ut og til og med sprø Batman-avis-rotasjon. http://jsfiddle.net/ketwaroo/mXy3E/

$('.modal').on('show.bs.modal', function(event) {
    var idx = $('.modal:visible').length;
    $(this).css('z-index', 1040 + (10 * idx));
});
$('.modal').on('shown.bs.modal', function(event) {
    var idx = ($('.modal:visible').length) -1; // raise backdrop after animation.
    $('.modal-backdrop').not('.stacked').css('z-index', 1039 + (10 * idx));
    $('.modal-backdrop').not('.stacked').addClass('stacked');
});

Svar #5

En enkel løsning for Bootstrap 4.5

.modal.fade {
  background: rgba(0, 0, 0, 0.5);
}

.modal-backdrop.fade {
  opacity: 0;
}

Svar #6

Jeg laget en Bootstrap-plugin som inkorporerer mange av ideene som ble lagt ut her.

Demo på Bootply: http://www.bootply.com/cObcYInvpq

Github: https://github.com/jhaygt/bootstrap-multimodal

Det tar også opp problemet med påfølgende modaler som gjør bakgrunnen mørkere og mørkere. Dette sikrer at bare én bakgrunn er synlig til enhver tid:

if(modalIndex > 0)
    $('.modal-backdrop').not(':first').addClass('hidden');

Z-indeksen til den synlige bakgrunnen oppdateres både ved show.bs.modal og hidden.bs.modal-hendelsene:

$('.modal-backdrop:first').css('z-index', MultiModal.BASE_ZINDEX + (modalIndex * 20));

Svar #7

Hvis du leter etter en Bootstrap 4-løsning, finnes det en enkel en som bruker ren CSS:

.modal.fade {
    background: rgba(0,0,0,0.5);
}

Svar #8

Når man løser problemet med at stablet modaler ruller hovedsiden når en lukkes, fant jeg at nyere versjoner av Bootstrap (minst siden versjon 3.0.3) ikke krever noen ekstra kode for å stable modaler.

Du kan legge til mer enn en modal (selvfølgelig med forskjellig ID) på siden din. Det eneste problemet som oppstår når du åpner mer enn en modal, er at det å lukke én fjerner modal-open-klassen for body-selektoren.

Du kan bruke følgende Javascript-kode for å legge til modal-open igjen :

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

I tilfelle du ikke trenger bakgrunnseffekten for den stablede modalen, kan du sette data-backdrop="false".

Versjon 3.1.1. fikset problemet med modalens bakgrunn som overlapper modalens rullefelt, men løsningen ovenfor ser også ut til å fungere med tidligere versjoner.

Relaterte artikler