web-dev-qa-db-fra.com

Erreur d'amorçage multiple modal sur Twitter

J'essaie d'avoir un modal dans un autre modal. Cependant, j'ai eu une erreur comme "trop ​​de récursivité" dans firefox.

J'ai utilisé les derniers jQuery et Twitterbootstrap mais j'ai toujours ce problème.

Voici le plunker qui montre l'erreur

Vous pouvez trouver "Uncaught RangeError: taille maximale de la pile d'appels dépassée" ou "trop ​​de récursivité"

erreur dans la console

Quelqu'un sait comment le réparer? Merci

55
maxisam

Ok, cela semble être un problème qui a été découvert.

(apparemment, je devrais utiliser le mot-clé "Uncaught RangeError: taille maximale de la pile d'appels dépassée" au lieu de "trop ​​de récursivité" :()

Voici les solutions.

1. modifier le modal.js

dans cet article, https://github.com/twbs/bootstrap/pull/5022

@onassar apporte une solution

Suivi: pour toute personne travaillant avec bootstrap-modal v2.2.0, dans le fichier EnforceFocus, en commentant que. $ element.focus () semble réparer le problème.

Le résultat de ceci est que les modaux ne sont pas focalisés sur (pfft, je peux Le faire moi-même: P), et donc, les multiples modaux ne contestent pas l'un pour l'autre pour le focus (ce qui a entraîné une boucle infinie et une boucle rangerror/récursive).

J'espère que cela pourra aider :)

J'ai essayé et ça marche. ( plunker )

2. Utilisez un autre plugin pour résoudre ce problèmeDemo

On dirait que ça marche plutôt bien.

3. Attendre la solution officielle.

Dans leur roadmap , ils veulent réécrire ce plugin modal à un moment donné.

34
maxisam

Vous pouvez appliquer la première solution de maxisam answer, sans modifier les fichiers d'amorçage (si vous ne pouvez pas, ou ne voulez pas).

Il suffit d’écrire cette ligne quelque part après l’inclusion des fichiers bootstrap.

$.fn.modal.Constructor.prototype.enforceFocus = function () {};

Remarque: Ceci a été testé avec Bootstrap 2 uniquement, pas avec Bootstrap 3.

101

La réponse de SmartLove est malheureusement incomplète; si vous utilisez le $.fn.modal.Constructor.prototype.enforceFocus sans opération, vous devez le réinitialiser à la fermeture de votre modal; Ce qui suit est directement issu de notre code, sur lequel j’ai mis en production sans scrupule:

// Since confModal is essentially a nested modal it's enforceFocus method
// must be no-op'd or the following error results 
// "Uncaught RangeError: Maximum call stack size exceeded"
// But then when the nested modal is hidden we reset modal.enforceFocus
var enforceModalFocusFn = $.fn.modal.Constructor.prototype.enforceFocus;

$.fn.modal.Constructor.prototype.enforceFocus = function() {};

$confModal.on('hidden', function() {
    $.fn.modal.Constructor.prototype.enforceFocus = enforceModalFocusFn;
});

$confModal.modal({ backdrop : false });
27
George Jempty

4. Vous pouvez également procéder comme suit pour afficher un nouveau modal:

  1. Masquer tout modal actuellement actif
  2. Montrer le nouveau modal
  3. Lorsque vous fermez le nouveau modal, affichez les modaux précédemment masqués.

    var showModal = function ($dialog) {
        var $currentModals = $('.modal.in');
        if ($currentModals.length > 0) { // if we have active modals
            $currentModals.one('hidden', function () { 
                // when they've finished hiding
                $dialog.modal('show');
                $dialog.one('hidden', function () {
                    // when we close the dialog
                    $currentModals.modal('show');
    
                });
            }).modal('hide');
        } else { // otherwise just simply show the modal
            $dialog.modal('show');
        }
    };
    

Remarque: J'utilise $.one pour que l'écouteur ne soit appliqué qu'une seule fois, sans me soucier de bind/unbind (on/off)

7
Matyas

Essayez le css suivant. Cela a fonctionné pour moi.

span.select2-container {
    z-index:10050;
}
1
nidhin

Pour Bootstrap 4, remplacez: $.fn.modal.Constructor.prototype.**enforceFocus**par $.fn.modal.Constructor.prototype.**_enforceFocus**

1
bbastou

J'ai résolu ceci en utilisant une pile.

var openmodals = [];
$(function(){
  var ts = new Date().getTime();
  $("div.modal").each(function( d ) {
    ts++;
    $( this ).data( "uid", ts );
  });

  // after closing > 1 level modals we want to reopen the previous level modal
  $('div.modal').on('show', function ( d ) {
    openmodals.Push({ 'id' : $( this ).data( "uid" ), 'el' : this });
    if( openmodals.length > 1 ){
        $( openmodals[ openmodals.length - 2 ].el ).modal('hide');
    }
  });
  $('div.modal').on('hide', function ( d ) {
    if( openmodals.length > 1 ){
        if( openmodals[ openmodals.length - 1 ].id == $( this ).data( "uid" ) ){
            openmodals.pop(); // pop current modal 
            $( openmodals.pop().el ).modal('show'); // pop previous modal and show, will be pushed on show 
        }
    } else if( openmodals.length > 0 ){
        openmodals.pop(); // last modal closing, empty the stack
    } 
  });
});
1
Ryan