Twitter загружает несколько модальных ошибок
Я пытаюсь иметь модал внутри другого модала. Тем не менее, я получил ошибку, как "слишком много рекурсии" в Firefox.
Я использовал последние jQuery и Twitterbootstrap, но все еще имею эту проблему.
Вот плункер, который показывает ошибку
Вы можете найти "Uncaught RangeError: Превышен максимальный размер стека вызовов" или "Слишком много рекурсии"
ошибка в консоли
Кто-нибудь знает, как это исправить? Спасибо
9 ответов
Хорошо, это похоже на проблему, которая была обнаружена.
(очевидно, я должен использовать ключевое слово "Uncaught RangeError: Превышен максимальный размер стека вызовов" вместо "слишком много рекурсии":()
Вот решения.
1. изменить modal.js
в этом посте, https://github.com/twbs/bootstrap/pull/5022
@onassar предложи решение
Последующие действия: для тех, кто работает с bootstrap-modal v2.2.0, в методе forceceFocus, комментируя это, $element.focus(), похоже, решает проблему.
Результатом этого является то, что модал не фокусируется (pfft, я могу сделать это сам:P), и, таким образом, множественные модалы не бросают вызов друг другу для фокусировки (что приводило к бесконечному циклу и rangerror/ рекурсивный цикл).
Надеюсь, это поможет:)
Я пытался, и это работает. ( плункер)
2. Используйте другой плагин для решения этой демонстрации
Кажется, это работает довольно хорошо.
3. Ждите официального решения.
В своей дорожной карте они хотят переписать этот модальный плагин в какой-то момент.
Вы можете применить первое решение ответа maxisam, не изменяя файлы начальной загрузки (если вы не можете или не хотите).
Просто напишите эту строку где-нибудь после включения файлов начальной загрузки.
$.fn.modal.Constructor.prototype.enforceFocus = function () {};
Примечание: это было проверено только с Bootstrap 2, а не с Bootstrap 3.
Ответ SmartLove, к сожалению, не дотягивает; если вы собираетесь в неоперативный $.fn.modal.Constructor.prototype.enforceFocus
, вы должны сбросить его, когда ваш модал закрывается; следующее прямо из нашего кода, о котором я не имею никаких сомнений, вводя в производство:
// 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 });
4. Или вы можете сделать следующее при показе нового модала:
- Скрыть любой модальный, который в настоящее время активен
- Показать новый модал
Когда вы закрываете новый модал, покажите ранее скрытые модальные окна
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'); } };
Примечание: я использую $.one
чтобы слушатель подавался только один раз, а не заботиться о bind
/unbind
(on
/off
)
Для Bootstrap 4 замените:$.fn.modal.Constructor.prototype.**enforceFocus**
От $.fn.modal.Constructor.prototype.**_enforceFocus**
Попробуйте следующее CSS. Это сработало для меня.
span.select2-container {
z-index:10050;
}
Bootstrap 5 версия ответа @Dexygen:
const enforceModalFocusFn = bootstrap.Modal.prototype._enforceFocusOnElement;
const onMyModalHidden = function(){
bootstrap.Modal.prototype._enforceFocusOnElement = enforceModalFocusFn;
}
//let modalElem = ...;
modalElem.addEventListener('hidden.bs.modal', onMyModalHidden);
bootstrap.Modal.prototype._enforceFocusOnElement = function () {};
Важное примечание: вы должны переопределить функцию до отображения модального окна. Это означает, например, "show.bs.modal". Если вы инициализируете переопределение позже, то есть на «shown.bs.modal», это не сработает, потому что исходная функция уже была передана.
То же самое работает для offcanvas (это было то, что мне нужно), просто измените .Modal на .Offcanvas
Я решил это с помощью стека.
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
}
});
});
Вы можете опустить:
tabindex="-1"
, вверху модального окна И вы можете открыть модальное окно следующим образом:
$('#modal').show();
и закрыть:
$('#modal').hide();
That works!