Подтвердить что ты не робот

Twitter Bootstrap/jQuery - Как временно запретить закрытие модала?

Я использую мотивы Twitter Bootstrap с настройками по умолчанию, где вы можете щелкнуть по фону или нажать [Esc], чтобы закрыть модальный.

Однако, когда я запускаю операцию ajax в модальном режиме, я хочу каким-либо образом отключить модаль. Поэтому я отключил кнопки и скрывал кнопку закрытия мода, но я не могу понять, как отключить фоновый рисунок и клавишу [Esc].

Я пробовал:

$('#myModal').modal({
    backdrop: 'static',
    keyboard: false
});

Но это, похоже, не работает на лету.

Мне нужно будет снова включить фоновый рисунок и клавиатуру после завершения операции ajax.

4b9b3361

Ответ 1

Примечание. Это решение нацелено на twitter bootstrap 2.x! См. этот ответ (чуть ниже) для различий по бутстрапу 3.


Расширение модальности загрузки без изменения исходного источника.

Благодаря @David и его предложению в Как продлить плагин Twitter-Bootstrap Я, наконец, получил его на работу. Это немного измененная версия его решения с добавлением модального "замка". Я отправляю его как дополнительный ответ, так как я думаю, что это может быть отправной точкой для других, которые, как и я, изо всех сил пытались решить эту проблему.

// save the original function object
var _superModal = $.fn.modal;

// add locked as a new option
$.extend( _superModal.defaults, {
    locked: false
});

// create a new constructor
var Modal = function(element, options) {
    _superModal.Constructor.apply( this, arguments )
}

// extend prototype and add a super function
Modal.prototype = $.extend({}, _superModal.Constructor.prototype, {
    constructor: Modal

    , _super: function() {
        var args = $.makeArray(arguments)
        // call bootstrap core
        _superModal.Constructor.prototype[args.shift()].apply(this, args)
    }

    , lock : function() {
        this.options.locked = true
    }

    , unlock : function() {
        this.options.locked = false
    }

    , hide: function() {
        if (this.options.locked) return
        this._super('hide')
    }
});

// override the old initialization with the new constructor
$.fn.modal = $.extend(function(option) {
    var args = $.makeArray(arguments),
    option = args.shift()

    // this is executed everytime element.modal() is called
    return this.each(function() {
        var $this = $(this)
        var data = $this.data('modal'),
            options = $.extend({}, _superModal.defaults, $this.data(), typeof option == 'object' && option)

        if (!data) {
            $this.data('modal', (data = new Modal(this, options)))
        }
        if (typeof option == 'string') {
            data[option].apply( data, args )
        }
    });
}, $.fn.modal);

С помощью этого метода не обязательно изменять файл bootstrap.js, и те же функции могут быть легко доступны для проектов начальной загрузки. Этот метод должен быть применим ко всем другим плагинам загрузки. До сих пор только пытались с кнопкой, но я не могу понять, почему это не должно.

см. рабочий скрипт → http://jsfiddle.net/Sz7ZS/

Ответ 2

Вы не единственный, у кого отсутствует эта функция. Я думаю, что bootstrap иногда слишком "минималистичен", у людей, за которыми стоит идея, многое должно быть сделано на "уровне реализации", но это бесполезно, когда сами загрузочные плагины jQuery делают невозможным!

Вам нужно реализовать свои функции самостоятельно, например:

в bootstrap.js v2.1.1 модаль начинается с строки 61.

в Modal.prototype, добавьте две функции lock и unlock, так что это выглядит так (я показываю здесь только начало Modal.prototype, потому что это слишком много кода)

  Modal.prototype = {

      constructor: Modal

      //add this function
    , lock: function () {
        this.options.locked = true
      }

      //add this function
    , unlock: function () {
        this.options.locked = false
      }

    , toggle: function () {
    ... 
    ...

Затем, также в Modal.prototype, найдите функцию hide и добавьте строку, чтобы она выглядела так (опять же отображается только верхняя часть скрыть)

, hide: function (e) {
    e && e.preventDefault()

    var that = this

    //add this line
    if (that.options.locked) return

    e = $.Event('hide')
    ...
    ...

И, наконец, измените $.fn.modal.defaults на:

  $.fn.modal.defaults = {
      backdrop: true
    , keyboard: true
    , show: true
    , locked: false //this line is added
  }

Теперь у вас есть функция блокировки/разблокировки "на лету" в вашем модуле bootstrap, не позволяя пользователю закрывать модальную систему в критические моменты.

Пример:

Это измененная версия "Live Demo" из http://twitter.github.com/bootstrap/javascript.html#modals

<!-- Button to trigger modal -->
<a href="#myModal" role="button" class="btn" data-toggle="modal">Launch demo modal</a>

<!-- Modal -->
<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 id="myModalLabel">Modal header</h3>
  </div>
  <div class="modal-body">
    <p>One fine body…</p>
  </div>
  <div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    <button class="btn btn-primary" onclick="$('#myModal').modal('lock');">lock</button>
    <button class="btn btn-primary" onclick="$('#myModal').modal('unlock');">unLock</button>
  </div>
</div>
<script type="text/javascript">

Я вставил две кнопки: "блокировка" и "разблокировка" - при нажатии кнопки они устанавливают модальный режим как в заблокированном, так и в обычном режиме (настройки, которые он инициализируется)

Изменить, в вашем случае вам просто нужно вызвать lock/onlock при выполнении ajax:

$("myModal").modal('lock');
$.ajax({
    url: url,
    ...
    ...
    , success(html) {
       ...
       ...
       $("#myModal").modal('unlock');
    }
});

Ответ 3

Существует более простой способ сделать это. Этот запрос загрузки bootstrap объясняет немного больше. Решение отключает все методы закрытия модального (клавиатура, мышь, кнопка закрытия).

Все, что вам нужно сделать, чтобы отключить закрытие модального файла:

$('#myModal').data('bs.modal').isShown = false;

Чтобы снова включить закрытие:

$('#myModal').data('bs.modal').isShown = true;

Пример

Вот пример кода, который работает в сочетании с jQuery get:

// disable closing the modal
$('#myModal').data('bs.modal').isShown = false;

// Send an HTTP GET request to the server - replace this with getJSON, post or ajax as needed
$.get( "ajax/test.html", function( data ) {
  // enable closing the modal
  $('#myModal').data('bs.modal').isShown = true;

  // Do something with the data
  $( ".result" ).html( data );
});

Ответ 4

Вы можете создать переменную isBlocked, которую вы можете установить при выполнении вызовов AJAX в значение true, тогда вы можете проверить это в случае модального скрыть событие bootsrap таким образом:

$('#myModal').on('hide.bs.modal', function (e) {
      //Prevent modal from closing is isBlocked is true
      if(isBlocked) return e.preventDefault();
})

Я думаю, что этот способ проще, чем продлить Bootsrap, надеюсь, что это поможет кому-то: D

Ответ 5

Спасибо @davidkonrad за вашу работу над этим. Я также пытался реализовать это, и кажется, что все изменилось с помощью bootstrap 3. Теперь вместо:

_superModal.defaults

теперь он привязан к конструктору, поэтому вам нужно сделать

_superModal.Constructor.DEFAULTS

И изменился конструктор, что означало, что я должен был скопировать его и изменить его, который не идеален. Вместо этого я придумал следующий код, который работает и не копирует конструктор, и должен быть более безупречным, если бутстрап изменится в будущем. Пойдите:

// save the original function object
var _superModal = $.fn.modal;

// add locked as a new option
$.extend( _superModal.Constructor.DEFAULTS, {
    locked: false
});

// capture the original hide
var _hide = _superModal.Constructor.prototype.hide;
// console.log('HIDE:', _hide);

// add the lock, unlock and override the hide of modal
$.extend(_superModal.Constructor.prototype, {
    // locks the dialog so that it cannot be hidden
    lock: function() {
        // console.log('lock called');
        // console.log('OPTIONS',this.options);
        this.options.locked = true;
    }
    // unlocks the dialog so that it can be hidden by 'esc' or clicking on the backdrop (if not static)
    ,unlock: function() {
        // console.log('unlock called');
        this.options.locked = false;
    }
    // override the original hide so that the original is only called if the modal is unlocked
    ,hide: function() {
        // console.log('hide called');
        if (this.options.locked) return;

        _hide.apply(this, arguments);
    }
});

Итак, чтобы заблокировать модальный:

$('#dlg').modal('lock');

и разблокировать:

$('#dlg').modal('unlock');

Yay!