Superposición de múltiples modales


Necesito que la superposición se muestre por encima del primer modal, no en la parte posterior.

Superposición modal detrás

$('#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>

Traté de cambiar el z-index de .modal-backdrop, pero se convierte en un desastre.

En algunos casos tengo más de dos modales en la misma página.

Author: Emile Bergeron, 0000-00-00

7 answers

Después de ver muchas correcciones para esto, y ninguna de ellas era exactamente lo que necesitaba, se me ocurrió una solución aún más corta que está inspirada en @YermoLamers y @Ketwaroo.

Fondo z-index fix
Esta solución utiliza un setTimeout porque el .modal-backdrop no se crea cuando se activa el evento show.bs.modal.

$(document).on('show.bs.modal', '.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);
});
  • Esto funciona para cada .modal creado en la página (incluso los modales dinámicos)
  • El telón de fondo se superpone instantáneamente al anterior modal

Ejemplo jsfiddle

Si no le gusta el índice z codificado por cualquier razón, puede calcular el índice z más alto en la página de esta manera:

var zIndex = Math.max.apply(null, Array.prototype.map.call(document.querySelectorAll('*'), function(el) {
  return +el.style.zIndex;
})) + 10;

Scrollbar fix
Si tiene un modal en su página que excede la altura del navegador, entonces no puede desplazarse en él al cerrar un segundo modal. Para arreglar esto agregue:

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

Versiones
Esta solución se prueba con bootstrap 3.1.0-3.3.5

 333
Author: A1rPun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-04 20:08:51

Me doy cuenta de que se ha aceptado una respuesta, pero sugiero encarecidamente no hackear bootstrap para solucionar esto.

Puede lograr fácilmente el mismo efecto conectando los controladores de eventos.bs.modal mostrados y.bs.modal ocultos y ajustando el índice z allí.

Aquí hay un ejemplo de trabajo

Un poco más de información está disponible aquí.

Esta solución funciona automáticamente con modales arbitrariamente profundamente apilados.

El código fuente del script:

$(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'); 

    });        
});
 72
Author: Yermo Lamers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-21 12:46:01

Versión algo más corta basada en la sugerencia de Yermo Lamers, esto parece funcionar bien. Incluso con animaciones básicas como fade in / out e incluso crazy batman newspaper rotar. 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');
});
 21
Author: Ketwaroo D. Yaasir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-15 16:19:51

Combinando la respuesta de A1rPun con la sugerencia de StriplingWarrior, se me ocurrió esto:

$(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');

Funciona incluso para los modales dinámicos agregados después del hecho, y elimina el problema de la segunda barra de desplazamiento. Lo más notable para lo que encontré esto útil fue integrar formularios dentro de los modales con la retroalimentación de validación de las alertas de Bootbox, ya que usan modales dinámicos y, por lo tanto, requieren que vincules el evento al documento en lugar de a .modal, ya que sólo se une a los existentes modal.

Fiddle aquí.

 18
Author: Seven Deadly Sins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-22 19:38:43

He creado un plugin Bootstrap que incorpora muchas de las ideas publicadas aquí.

Demo en Bootply: http://www.bootply.com/cObcYInvpq

[4]} Github: https://github.com/jhaygt/bootstrap-multimodal

También aborda el problema con los modales sucesivos que hacen que el telón de fondo se vuelva más y más oscuro. Esto asegura que solo un telón de fondo sea visible en un momento dado:

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

El índice z del fondo visible se actualiza tanto en el show.bs.modal y hidden.bs.modal eventos:

$('.modal-backdrop:first').css('z-index', MultiModal.BASE_ZINDEX + (modalIndex * 20));
 11
Author: jhay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-10 21:29:03

Al resolver Apilar modales se desplaza por la página principal cuando se cierra encontré que las versiones más recientes de Bootstrap (al menos desde la versión 3.0.3) no requieren ningún código adicional para apilar modales.

Puede agregar más de un modal (por supuesto que tiene un ID diferente) a su página. El único problema que se encuentra al abrir más de un modal será que el cierre elimina la clase modal-open para el selector de cuerpo.

Puede usar el siguiente código Javascript para volver a agregar el modal-open :

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

En el caso de que no necesite el efecto de fondo para el modal apilado puede configurar data-backdrop="false".

Versión 3.1.1. se corrigió Se corrigió el telón de fondo modal que superponía la barra de desplazamiento del modal, pero la solución anterior también parece funcionar con versiones anteriores.

 9
Author: Bass Jobsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:50

Finalmente resuelto. Lo probé de muchas maneras y funciona bien.

Aquí está la solución para cualquiera que tenga el mismo problema: Cambie el modal .prototipo.mostrar función (en bootstrap.js o modal.js)

DE:

if (transition) {
   that.$element[0].offsetWidth // force reflow
}   

that.$element
   .addClass('in')
   .attr('aria-hidden', false)

that.enforceFocus()

PARA:

if (transition) {
    that.$element[0].offsetWidth // force reflow
}

that.$backdrop
   .css("z-index", (1030 + (10 * $(".modal.fade.in").length)))

that.$element
   .css("z-index", (1040 + (10 * $(".modal.fade.in").length)))
   .addClass('in')
   .attr('aria-hidden', false)

that.enforceFocus()

Es la mejor manera que he encontrado: comprobar cuántos modales se abren y cambiar el índice z del modal y el telón de fondo a un valor más alto.

 8
Author: Willian Bonho Daiprai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-11 15:00:56