it-swarm.com.de

Twitter Bootstrap/jQuery - Wie kann das Modal vorübergehend geschlossen werden?

Ich verwende Twitter-Bootstrap-Modals mit den Standardoptionen, bei denen Sie auf den Hintergrund klicken oder [Esc] drücken, um das Modal zu schließen.

Wenn ich jedoch eine Ajax-Operation in der Modalität initiiere, möchte ich verhindern, dass die Modalität in irgendeiner Weise geschlossen wird. Ich deaktiviere die Schaltflächen und blende die Schließen-Schaltfläche des Modals aus, kann aber nicht herausfinden, wie der Hintergrund und die [Esc] -Taste deaktiviert werden.

Ich habe es versucht:

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

Dies scheint jedoch nicht sofort zu funktionieren.

Ich muss auch den Hintergrund und die Tastatur wieder aktivieren, wenn der Ajax-Vorgang abgeschlossen ist.

34
BadHorsie

Note: Diese Lösung zielt auf Twitter bootstrap 2.x ! Siehe diese Antwort (knapp darunter) für Unterschiede nach Bootstrap 3.


Bootstrap-Modalfunktionalität erweitern ohne ursprüngliche Quelle ändern. 

Danke an @David und seinen Vorschlag unter How to Extend Twitter Bootstrap Plugin Endlich habe ich es geschafft. Es ist eine leicht modifizierte Version seiner Lösung mit modalem "Lock". Ich poste es als zusätzliche Antwort, da ich denke, es könnte ein Ausgangspunkt für andere sein, die wie ich mit diesem Thema schwer zu kämpfen haben. 

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

Bei dieser Technik sollte es nicht notwendig sein, bootstrap.js zu ändern, und die gleiche Funktionalität kann einfacher zwischen Bootstrap-Projekten verwendet werden. Diese Methode sollte auf alle anderen Bootstrap-Plugins anwendbar sein. Habe es bisher nur mit Button probiert, aber ich kann nicht sehen, warum es nicht sollte. 

siehe Arbeitsgeige -> http://jsfiddle.net/Sz7ZS/

17
davidkonrad

Es gibt einen einfacheren Weg, dies zu tun. Diese Bootstrap-Pull-Anfrage erklärt etwas mehr. Die Lösung deaktiviert alle Methoden zum Schließen des Modals (Tastatur, Mausklick, Schließen-Schaltfläche).

Alles, was Sie tun müssen, um das Schließen des Modals zu deaktivieren, ist:

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

So aktivieren Sie das Schließen wieder:

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

Beispiel

Hier ist ein Beispielcode, der in Verbindung mit einem jQuery-Get funktioniert:

// 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

Sie sind nicht der einzige, dem diese Funktion fehlt. Ich denke, Bootstrap ist manchmal zu "minimalistisch", die Leute, die dahinterstehen, haben die Idee, dass eine Menge in der "Implementierungsschicht" getan werden sollte, aber es nützt nichts, wenn das Bootstrap-Plugin jQuery es selbst unmöglich macht!

Sie müssen die Funktionalität selbst wie folgt implementieren:

in bootstrap.js v2.1.1 beginnt modal in Zeile 61. 

fügen Sie in Modal.prototype zwei Funktionen hinzu, lock und unlock, so dass es so aussieht (ich zeige hier nur den Anfang von modal.prototype, da es zu viel Code ist)

  Modal.prototype = {

      constructor: Modal

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

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

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

Suchen Sie dann auch in Modal.prototype die Funktion hide und fügen Sie eine Zeile hinzu, sodass es so aussieht (wieder wird nur oberer Teil von hide angezeigt).

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

    var that = this

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

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

Und schließlich $.fn.modal.defaults zu:

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

Jetzt haben Sie in Ihrem Bootstrap-Modal eine On-The-Fly-Sperre/Entsperrfunktion, die den Benutzer daran hindert, das Modal in kritischen Momenten zu schließen. 

Beispiel:

Dies ist eine veränderte Version von "Live Demo" von 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">

Ich habe zwei Knöpfe eingefügt, "Sperren" und "Entsperren" - wenn Sie darauf klicken, wird der modale Modus entweder im gesperrten oder im normalen Modus festgelegt (die Einstellungen, mit denen er initialisiert wird).

Edit, in Ihrem Fall müssen Sie bei ajax nur lock/onlock aufrufen:

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

Sie können eine Variable isBlocked erstellen, die Sie während des Aufrufs von AJAX auf true setzen können. Anschließend können Sie sie auf das modifizierte Hiderap-Ereignis von bootrap überprüfen:

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

Ich denke, dieser Weg ist einfacher als das Erweitern von Bootsrap. Ich hoffe, es hilft jemandem: D

8
alez

Vielen Dank an @davidkonrad für Ihre Arbeit an diesem Thema. Ich habe versucht, dies auch umzusetzen, und es scheint, dass sich die Dinge mit bootstrap 3 geändert haben. Jetzt statt:

_superModal.defaults

es ist jetzt an den Konstruktor angehängt, so dass Sie tun müssen

_superModal.Constructor.DEFAULTS

Auch der Konstruktor hat sich geändert, was bedeutete, dass ich ihn kopieren und modifizieren musste, was alles andere als ideal ist. Stattdessen habe ich mir den folgenden Code ausgedacht, der funktioniert und den Konstruktor nicht kopiert und der idiotensicherer sein sollte, wenn sich bootstrap in Zukunft ändert. Probieren:

// 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);
    }
});

So, um den Modal zu sperren:

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

und freischalten:

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

Yay!

6
ragamufin

Ich habe dieses großartige Skript für die Arbeit mit Bootstrap 4 und 3 aktualisiert. __ Ich halte beide Szenarien, da ich ein globales Skript habe, das ich in meinen Projekten verwende. keine Sorge, ein Bootstrap pro Projekt). Wenn jemand eine bessere Idee hat, teilen Sie uns diese bitte mit.

// 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