web-dev-qa-db-ja.com

Twitter Bootstrap / jQuery-モーダルが一時的に閉じられるのを防ぐ方法は?

私はTwitter Bootstrap modalsを使用しています。デフォルトのオプションでは、背景をクリックするか、[Esc]を押してモーダルを閉じます。

ただし、モーダルでajax操作を開始するときは、モーダルが何らかの方法で閉じられないようにします。そのため、ボタンを無効にしてモーダルの閉じるボタンを非表示にしていますが、背景と[Esc]キーを無効にする方法がわかりません。

私は試した:

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

しかし、これはその場では機能しないようです。

また、ajax操作が終了したら、背景とキーボードを再度有効にする必要があります。

35
BadHorsie

:このソリューションの対象は Twitter bootstrap 2.x !参照 この回答 (すぐ下)bootstrap 3。


拡張bootstrap=モーダル機能なしで元のソースを変更せずに.

@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を変更する必要はありません。同じ機能をbootstrapプロジェクト間でより簡単に共有できます。このメソッドは、他のすべてのbootstrap plugins。これまでのところ、ボタンのみで試してみましたが、なぜそれがいけないのかわかりません。

動作中のフィドルを参照->http://jsfiddle.net/Sz7ZS/

17
davidkonrad

それを行う簡単な方法があります。 これ 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 );
});
10
qingu

その機能が欠けているのはあなただけではありません。 bootstrapは時々「ミニマル」すぎると思います。背後の人々は「実装層」で多くのことを行うべきだと考えていますが、bootstrap jQueryプラグイン自体はそれを不可能にします!

次のように、自分で機能を実装する必要があります

bootstrap.js v2.1.1モーダルは61行目から始まります。

Modal.prototype、2つの関数lockunlockを追加すると、次のようになります(ここでは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モーダルにオンザフライのロック/ロック解除機能があり、ユーザーが重要な瞬間にモーダルを閉じることができなくなりました。

これは 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">

「ロック」と「ロック解除」の2つのボタンを挿入しました。クリックすると、モーダルがロックモードまたは通常モード(初期化された設定)に設定されます。

編集、あなたの場合、あなたはajaxを行うときにlock/onlockを呼び出す必要があります:

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

AJAXをtrueに呼び出しているときに設定できる変数isBlockedを作成できます。その後、ブートストラップモーダル非表示イベントで次のように確認できます。

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

この方法はBootsrapを拡張するよりも簡単だと思います。誰かを助けることを願っています:D

8
alez

これに関するあなたの仕事を@davidkonradに感謝します。私もこれを実装しようとしていましたが、bootstrap 3で変更されているようです。

__superModal.defaults_

これはコンストラクタにアタッチされているので、

__superModal.Constructor.DEFAULTS_

また、コンストラクターが変更されたため、コピーして変更する必要があり、理想的ではありませんでした。代わりに、機能し、コンストラクターをコピーしない以下のコードを考え出しました。bootstrap変更が今後行われる場合、より確実になります。試してみてください。

_// 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');

わーい!

6
ragamufin

Bootstrap 4&3で動作するようにこの素晴らしいスクリプトを更新しました。プロジェクトで使用しているグローバルスクリプトがあり、それらの一部が両方を使用しているため、両方のシナリオを維持していますBoostrapのバージョン(心配しないでください、プロジェクトごとに1つbootstrap)。より良いアイデアがある場合は、私たちと共有してください。

// save the original function object
var _superModal = $.fn.modal;
// Bootstrap 3: Constructor.DEFAULTS
// Bootstrap 4: Constructor.Default
var _superModalDefault = (typeof _superModal.Constructor.DEFAULTS === 'undefined') ? _superModal.Constructor.Default : _superModal.Constructor.DEFAULTS;

// add locked as a new option
$.extend(_superModalDefault, {
    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
    // Bootstrap 3: this.options
    // Bootstrap 4: this._config
    lock: function() {
        // console.log('lock called');
        if (this.options)
            this.options.locked = true;  // Bootstrap 3
        else
            this._config.locked = true;  // Bootstrap 4
    }
    // 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');
        if (this.options)
            this.options.locked = false;  // Bootstrap 3
        else
            this._config.locked = false;  // Bootstrap 4
    }
    // 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)
            if (this.options.locked) return;  // Bootstrap 3
        else
            if (this._config.locked) return;  // Bootstrap 4

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