33

Sto utilizzando i modal di Twitter Bootstrap, con le opzioni predefinite in cui è possibile fare clic sullo sfondo o premere [Esc] per chiudere la modal.Twitter Bootstrap/jQuery - Come impedire temporaneamente la chiusura della modale?

Tuttavia, quando avvio un'operazione ajax nel modale, desidero disattivare la modale dall'essere chiusa in alcun modo. Quindi disabilito i pulsanti e nascondo il pulsante di chiusura del modale, ma non riesco a capire come disabilitare lo sfondo e il tasto [Esc].

ho provato:

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

Ma questo non sembra funzionare al volo.

Avrò anche bisogno di riattivare lo sfondo e la tastiera una volta che l'operazione ajax è finita.

risposta

17

Nota: Questa soluzione si rivolge twitter bootstrap 2.x! Vedi this answer (appena sotto) per le differenze in base al bootstrap 3.


allungabile funzionalità modale bootstrap senza modificare sorgente originale.

Grazie a @David e al suo suggerimento allo How to Extend Twitter Bootstrap Plugin ho finalmente funzionato. È una versione leggermente modificata della sua soluzione con "blocco" modale aggiunto. Lo postò come risposta aggiuntiva poiché penso che potrebbe essere un punto di partenza per gli altri che come me hanno faticato molto a risolvere questo problema.

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

Con questa tecnica non dovrebbe essere nessecary alterare bootstrap.js, e la stessa funzionalità può essere facilmente condivisa tra progetti bootstrap. Questo metodo dovrebbe essere applicabile a tutti gli altri plugin di bootstrap. Finora ho provato solo con il pulsante, ma non riesco a capire perché non dovrebbe.

vedere violino di lavoro ->http://jsfiddle.net/Sz7ZS/

+0

dopo aver applicato questo metodo, lo sfondo (lo sfondo grigio) sembra scomparire. ho bisogno di manualmente $ ('# thisModal'). modal ({backdrop: true}); per usarlo. è un errore o questo è l'unico modo per farlo? –

+0

@TianLoon. Ho aggiornato la risposta con la notifica sulla versione bootstrap e un [jsfiddle] (http://jsfiddle.net/Sz7ZS/) usando bootstrap 2.3.2 (la versione più popolare della versione 2.x). Nel violino appare lo sfondo - forse l'hai accidentalmente impostato su opaco 0, bianco o qualcosa del genere? – davidkonrad

+0

GRAZIE MOLTO PER QUESTO !!!!! –

9

Non sei l'unico a mancare quella funzione. Penso che il bootstrap a volte sia troppo "minimalista", le persone dietro hanno l'idea che molto dovrebbe essere fatto nel "livello di implementazione", ma è inutile quando il bootstrap che i plugin jQuery rendono impossibile!

si deve implementare la funzionalità da soli, in questo modo:

in bootstrap.js v2.1.1 modale inizia alla linea 61.

in Modal.prototype, aggiungere due funzioni, lock e unlock, in modo che appaia come questo (mi mostra qui solo l'inizio di modal.prototype, becuase è troppo codice)

Modal.prototype = { 

     constructor: Modal 

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

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

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

Quindi, anche in Modal.prototype, trovare la funzione hide, e aggiungere una riga in modo che appaia come questo (ancora una volta, solo top di pelle viene mostrato)

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

    var that = this 

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

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

E, infine, alterare $.fn.modal.defaults a:

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

Ora hai la funzionalità di blocco/sblocco al volo nel tuo modal bootstrap, impedendo all'utente di chiudere il modal nei momenti critici.

Esempio:

Questa è una versione alterata di "Live Demo" dal 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"> 

ho inserito due pulsanti, "Lock" e "sbloccare" - quando si fa clic, si misero la modale in modalità chiusa o normale (le impostazioni sono inizializzate con)

Modifica, nel tuo caso, devi solo chiamare blocco/onlock quando facendo ajax:

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

Funziona bene, ma puoi implementarlo estendendo il codice di bootstrap principale, anziché modificarlo? – BadHorsie

+0

Sì, finalmente l'ho capito :) grazie a @david e grazie a te. – davidkonrad

6

Grazie @davidkonrad per il vostro lavoro su questo. Stavo cercando di implementare questa come bene e sembra che le cose sono cambiate con il bootstrap 3. Ora, invece di:

_superModal.defaults

è ora fissata al costruttore in modo da avere a che fare

_superModal.Constructor.DEFAULTS

Anche il costruttore è cambiato, il che significava che dovevo copiarlo e modificarlo che non è l'ideale. Invece ho trovato il seguente codice che funziona e non copia il costruttore e dovrebbe essere più infallibile se il bootstrap cambia in avanti. Avere un andare:

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

Quindi, al fine di bloccare il modal:

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

e sbloccare:

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

Yay!

+0

Questo non sembra funzionare per me; Si ferma la modale dalla chiusura mentre faccio clic all'esterno di essa quando il modulo viene inviato, ma non appena il modulo viene inviato e chiamo .modal ("unlock") - la modal si nasconde ... Non chiamo .modal ("nascondi"), solo sblocco. Non sono sicuro di come sarebbe possibile. qualche idea? grazie – Wesley

+1

Quale versione di bootstrap stai usando? – ragamufin

+0

Grazie mille per questo. –

10

C'è un modo più semplice per farlo. This richiesta di bootstrap pull spiega un po 'di più. La soluzione disabilita tutti i metodi per chiudere il modale (tastiera, clic del mouse, pulsante di chiusura).

Tutto quello che dovete fare per disabilitare la chiusura del modale è:

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

Per attivare la chiusura di nuovo:

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

Esempio

Ecco alcuni esempi di codice che funziona in congiunzione con un jQuery ottenere:

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

È possibile creare una variabile isBlocked che è possibile impostare, mentre facendo chiamate AJAX al vero, allora si può controllare sul bootsrap modale nascondere evento in questo modo:

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

Penso che in questo modo è più facile che si estende Bootsrap , spero che aiuti qualcuno: D

+0

definately il modo più pulito per raggiungere questo obiettivo. +1 – con

Problemi correlati