Il messaggio di avviso Bootstrap di Twitter si chiude e si riapre


103

Ho un problema con i messaggi di avviso. Viene visualizzato normalmente e posso chiuderlo quando l'utente preme x(chiudi), ma quando l'utente tenta di visualizzarlo di nuovo (ad esempio, fare clic sull'evento del pulsante), non viene visualizzato. (Inoltre, se stampo questo messaggio di avviso sulla console, è uguale a [].) Il mio codice è qui:

 <div class="alert" style="display: none">
   <a class="close" data-dismiss="alert">×</a>
   <strong>Warning!</strong> Best check yo self, you're not looking too good.
 </div>

E evento:

 $(".alert").show();

PS! Devo mostrare un messaggio di avviso solo dopo che si è verificato un evento (ad esempio, il pulsante ha fatto clic). O cosa sto facendo di sbagliato?

Risposte:


180

L'eliminazione dei dati rimuove completamente l'elemento. Usa invece il metodo .hide () di jQuery.

Il metodo fix-it-quick:

Utilizzando javascript in linea per nascondere l'elemento su clic in questo modo:

<div class="alert" style="display: none"> 
    <a class="close" onclick="$('.alert').hide()">×</a>  
    <strong>Warning!</strong> Best check yo self, you're not looking too good.  
</div>

<a href="#" onclick="$('alert').show()">show</a>

http://jsfiddle.net/cQNFL/

Questo dovrebbe tuttavia essere usato solo se sei pigro (il che non va bene se vuoi un'app manutenibile).

Il metodo fai-da-te:

Crea un nuovo attributo di dati per nascondere un elemento.

Javascript:

$(function(){
    $("[data-hide]").on("click", function(){
        $("." + $(this).attr("data-hide")).hide()
        // -or-, see below
        // $(this).closest("." + $(this).attr("data-hide")).hide()
    })
})

e quindi modifica data-ignora in data-hide nel markup. Esempio su jsfiddle .

$("." + $(this).attr("data-hide")).hide()

Questo nasconderà tutti gli elementi con la classe specificata in data-hide, cioè: data-hide="alert"nasconderà tutti gli elementi con la classe alert.

Xeon06 ha fornito una soluzione alternativa:

$(this).closest("." + $(this).attr("data-hide")).hide()

Questo nasconderà solo l'elemento genitore più vicino. Questo è molto utile se non vuoi assegnare a ogni avviso una classe unica. Tieni presente che, tuttavia, devi posizionare il pulsante di chiusura all'interno dell'avviso.

Definizione di .closest da jquery doc :

Per ogni elemento nel set, ottieni il primo elemento che corrisponde al selettore testando l'elemento stesso e attraversando i suoi antenati nell'albero DOM.


4
Hey! Per quanto riguarda la tua risposta corretta. Questo nasconderà OGNI elemento che ha la stessa classe (cioè alert) nella pagina. Una soluzione per questo sarebbe sostituire il contenuto della richiamata con questa riga $(this).closest("." + $(this).attr("data-hide")).hide();, che interesserà solo l'elemento genitore più vicino, visto che il pulsante di chiusura è tipicamente posizionato all'interno dell'avviso che interessa.
Alex Turpin

1
È vero, non pensavo di farlo funzionare in quel modo. Ciò, tuttavia, rimuoverà in piccola parte la semplicità di questa soluzione. Lo aggiungerò come commento al codice esistente. Grazie!
Henrik Karlsson

1
Nuovo in questo .. dove definiresti "$ (function () {.."
S Rosam

1
Ovunque in un file JavaScript o in un tag <script> code here </script>.
Henrik Karlsson

1
Se usassi $ (document) .on ('click', '[data-hide]', function () {/ * * /}) La tua risposta sarebbe perfetta;)
shock_gone_wild

26

Ho appena usato una variabile del modello per mostrare / nascondere la finestra di dialogo e ho rimosso il file data-dismiss="alert"

Esempio:

<div data-ng-show="vm.result == 'error'" class="alert alert-danger alert-dismissable">
    <button type="button" class="close" data-ng-click="vm.result = null" aria-hidden="true">&times;</button>
    <strong>Error  !  </strong>{{vm.exception}}
</div>

funziona per me e ferma la necessità di andare a jquery


1
Una soluzione molto più semplice / migliore rispetto alla risposta accettata molto votata!
Abs

Soluzione molto migliore secondo me
devqon

mi piace la tua idea
Kumaresan Perumal

15

Penso che un buon approccio a questo problema sarebbe quello di sfruttare il close.bs.alerttipo di evento di Bootstrap per nascondere l'avviso invece di rimuoverlo. Il motivo per cui Bootstrap espone questo tipo di evento è che puoi sovrascrivere il comportamento predefinito di rimozione dell'avviso dal DOM.

$('.alert').on('close.bs.alert', function (e) {
    e.preventDefault();
    $(this).addClass('hidden');
});

5

Se stai usando una libreria MVVM come knockout.js (che consiglio vivamente) puoi farlo in modo più pulito:

<div class="alert alert-info alert-dismissible" data-bind="visible:showAlert">
   <button type="button" class="close" data-bind="click:function(){showAlert(false);}>
        <span aria-hidden="true">&times;</span>
        <span class="sr-only">Close</span>
   </button>
   Warning! Better check yourself, you're not looking too good.
</div>

http://jsfiddle.net/bce9gsav/5/


data-bind="click:function(){showAlert(false);}è un perfetto esempio di javascript invadente che è ben lungi dall'essere più pulito . Consiglio vivamente di NON seguire questo approccio
Leo

@ Leo invadente in che modo?
Ohad Schneider

Invadente in ogni singolo modo. Stai attivamente "incorporando" il comportamento nella tua struttura / markup html. Immagina di dover cambiare quel comportamento ... quante pagine ed elementi html dovrai cambiare? Non fraintendetemi, risponde comunque alla domanda posta ed è per questo che non lo ridurrò. Ma questa è ben lungi dall'essere una soluzione "più pulita"
Leo

No, quello che sto dicendo in realtà è usare la separazione delle preoccupazioni . Le tue visualizzazioni (html) non dovrebbero mai contenere javascript, le implicazioni negative potrebbero essere enormi in un team di sviluppo. Ecco una grande domanda (e risposte) su Knockout e l' data-bindattributo alquanto controverso stackoverflow.com/questions/13451414/unobtrusive-knockout
Leo

Cosa consideri "JavaScript"? E se contenesse solo il nome del metodo da invocare? È il fatto che lo chiami con un parametro (falso) che lo rende invadente ai tuoi occhi?
Ohad Schneider

2

Quindi, se vuoi una soluzione che possa far fronte a pagine html dinamiche, dato che la includi già dovresti usare jQuery's live per impostare il gestore su tutti gli elementi che sono ora e in futuro nel dom o vengono rimossi.

Io uso

$(document).on("click", "[data-hide-closest]", function(e) {
  e.preventDefault();
  var $this = $(this);
  $this.closest($this.attr("data-hide-closest")).hide();
});
.alert-success {
    background-color: #dff0d8;
    border-color: #d6e9c6;
    color: #3c763d;
}
.alert {
    border: 1px solid transparent;
    border-radius: 4px;
    margin-bottom: 20px;
    padding: 15px;
}
.close {
    color: #000;
    float: right;
    font-size: 21px;
    font-weight: bold;
    line-height: 1;
    opacity: 0.2;
    text-shadow: 0 1px 0 #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="alert alert-success">
  <a class="close" data-hide-closest=".alert">×</a>
  <strong>Success!</strong> Your entries were saved.
</div>


2

Questo ha funzionato meglio per me:

$('.alert').on('close.bs.alert', function (e) {
    e.preventDefault();
    $(this).hide();
});

1

Mi sono imbattuto anche in questo problema e il problema con il semplice hacking del pulsante di chiusura è che ho ancora bisogno di accedere agli eventi di chiusura avviso di bootstrap standard.

La mia soluzione era scrivere un piccolo plug-in jquery personalizzabile che inietta un avviso Bootstrap 3 correttamente formato (con o senza pulsante di chiusura in base alle tue esigenze) con il minimo sforzo e ti consente di rigenerarlo facilmente dopo che la scatola è chiusa.

Vedi https://github.com/davesag/jquery-bs3Alert per utilizzo, test ed esempi.


1

Sono d'accordo con la risposta pubblicata da Henrik Karlsson e modificata da Martin Prikryl. Ho un suggerimento, basato sull'accessibilità. Aggiungerei .attr ("aria-hidden", "true") alla fine, in modo che assomigli a:

$(this).closest("." + $(this).attr("data-hide")).attr("aria-hidden", "true");

2
È davvero necessario? jQuerys .hide set di funzioni display: nessuno, non dovrebbero comunque essere abbastanza intelligenti da riconoscerlo come nascosto?
Henrik Karlsson

1

Tutte le soluzioni di cui sopra utilizzano librerie esterne, angolari o jQuery, e una vecchia versione di Bootstrap. Quindi, ecco la soluzione di Charles Wyke-Smith in puro JavaScript , applicata a Bootstrap 4 . Sì, Bootstrap richiede jQuery per il proprio codice modale e di avviso, ma non tutti scrivono più il proprio codice con jQuery.

Ecco l'html dell'avviso:

<div id="myAlert" style="display: none;" 
    class="alert alert-success alert-dismissible fade show">
    <button type="button" class="close" data-hide="alert">&times;</button>
    <strong>Success!</strong> You did it!
</div>

Nota che inizialmente l'avviso è nascosto ( style="display: none;"), e invece dello standard data-dismiss="alert", qui abbiamo usato data-hide="alert".

Ecco il JavaScript per mostrare l'avviso e sovrascrivere il pulsante di chiusura:

var myAlert = document.getElementById('myAlert');
// Show the alert box
myAlert.style.display = 'block';
// Override Bootstrap's standard close action
myAlert.querySelector('button[data-hide]').addEventListener('click', function() {
    myAlert.style.display = 'none';
});

Se desideri nascondere o mostrare l'avviso a livello di codice altrove nel codice, esegui semplicemente myAlert.style.display = 'none';o myAlert.style.display = 'block';.


0

Il problema è causato dall'utilizzo di style="display:none", dovresti nascondere l' avviso con Javascript o almeno quando lo mostri, rimuovere l'attributo style.


2
Non proprio, il problema è che Data-ignora rimuove l'elemento
Henrik Karlsson

0

In base alle altre risposte e alla modifica di data-ignora in data-hide, questo esempio gestisce l'apertura dell'avviso da un collegamento e consente l'apertura e la chiusura dell'avviso ripetutamente

$('a.show_alert').click(function() {
    var $theAlert = $('.my_alert'); /* class on the alert */
    $theAlert.css('display','block');
   // set up the close event when the alert opens
   $theAlert.find('a[data-hide]').click(function() {
     $(this).parent().hide(); /* hide the alert */
   });
});

0

Ho provato tutti i metodi e il modo migliore per me è usare le classi bootstrap integrate .fadee.in

Esempio:

<div class="alert alert-danger fade <?php echo ($show) ? 'in' : '' ?>" role="alert">...</div>

Nota: in jQuery, addClass ('in') per mostrare l'avviso, removeClass ('in') per nasconderlo.

Fatto divertente: funziona per tutti gli elementi. Non solo avvisi.


0

Ecco una soluzione basata sulla risposta di Henrik Karlsson ma con un corretto trigger di eventi (basato su sorgenti Bootstrap ):

$(function(){
    $('[data-hide]').on('click', function ___alert_hide(e) {
        var $this = $(this)
        var selector = $this.attr('data-target')
        if (!selector) {
            selector = $this.attr('href')
            selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
        }

        var $parent = $(selector === '#' ? [] : selector)

        if (!$parent.length) {
            $parent = $this.closest('.alert')
        }

        $parent.trigger(e = $.Event('close.bs.alert'))

        if (e.isDefaultPrevented()) return

        $parent.hide()

        $parent.trigger($.Event('closed.bs.alert'))
    })
});

La risposta principalmente per me, come nota.


0

Non è possibile farlo semplicemente aggiungendo un div "contenitore" aggiuntivo e aggiungendo di nuovo ogni volta il div di avviso rimosso. Sembra funzionare per me?

HTML

<div id="alert_container"></div>

JS

 $("#alert_container").html('<div id="alert"></div>');          
 $("#alert").addClass("alert alert-info  alert-dismissible");
 $("#alert").html('<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a><strong>Info!</strong>message');
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.