El mensaje de alerta de Twitter Bootstrap se cierra y se abre de nuevo

103

Tengo un problema con los mensajes de alerta. Se muestra normalmente y puedo cerrarlo cuando el usuario presiona x(cerrar), pero cuando el usuario intenta mostrarlo nuevamente (por ejemplo, hacer clic en el evento del botón), no se muestra. (Además, si imprimo este mensaje de alerta en la consola, es igual a []). Mi código está aquí:

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

Y evento:

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

¡PD! Necesito mostrar un mensaje de alerta solo después de que sucedió algún evento (por ejemplo, se hizo clic en el botón). ¿O qué estoy haciendo mal?

ben3000
fuente

Respuestas:

180

La eliminación de datos elimina por completo el elemento. En su lugar, use el método .hide () de jQuery.

El método de arreglarlo rápido:

Usando javascript en línea para ocultar el elemento al hacer clic así:

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

Sin embargo, esto solo debe usarse si eres vago (lo cual no es bueno si quieres una aplicación que se pueda mantener).

El método de hacerlo bien:

Cree un nuevo atributo de datos para ocultar un elemento.

Javascript:

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

y luego cambie el descarte de datos a ocultar datos en el marcado. Ejemplo en jsfiddle .

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

Esto ocultará todos los elementos con la clase especificada en data-hide, es decir: data-hide="alert"ocultará todos los elementos con la clase de alerta.

Xeon06 proporcionó una solución alternativa:

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

Esto solo ocultará el elemento padre más cercano. Esto es muy útil si no desea asignar a cada alerta una clase única. Sin embargo, tenga en cuenta que debe colocar el botón de cierre dentro de la alerta.

Definición de .closest de jquery doc :

Para cada elemento del conjunto, obtenga el primer elemento que coincida con el selector probando el elemento en sí y recorriendo sus antepasados ​​en el árbol DOM.

Henrik Karlsson
fuente
4
¡Oye! En cuanto a su respuesta correcta. Esto ocultará CADA elemento que tenga la misma clase (es decir, alert) en la página. Una solución para esto sería reemplazar el contenido de la devolución de llamada con esta línea $(this).closest("." + $(this).attr("data-hide")).hide();, que solo afectará al elemento principal más cercano, ya que el botón de descarte generalmente se coloca dentro de la alerta que afecta.
Alex Turpin
1
Eso es cierto, no pensé en hacerlo funcionar de esa manera. Sin embargo, eso eliminará en pequeña medida la simplicidad de esta solución. Lo agregaré como comentario al código existente. ¡Gracias!
Henrik Karlsson
1
Nuevo en esto ... ¿dónde definiría el '$ (function () {..'
S Rosam
1
En cualquier lugar de un archivo JavaScript o en una etiqueta <script> código aquí </script>.
Henrik Karlsson
1
Si usara $ (document) .on ('click', '[data-hide]', function () {/ * * /}) Su respuesta sería perfecta;)
shock_gone_wild
26

Acabo de usar una variable de modelo para mostrar / ocultar el diálogo y eliminé el data-dismiss="alert"

Ejemplo:

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

funciona para mí y detiene la necesidad de salir a jquery

user1661621
fuente
1
¡Una solución mucho más simple / mejor que la respuesta aceptada altamente votada!
Abs
Mucho mejor solución en mi opinión
devqon
me gusta tu idea
Kumaresan Perumal
15

Creo que un buen enfoque para este problema sería aprovechar el close.bs.alerttipo de evento de Bootstrap para ocultar la alerta en lugar de eliminarla. La razón por la que Bootstrap expone este tipo de evento es para que pueda sobrescribir el comportamiento predeterminado de eliminar la alerta del DOM.

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

Si está utilizando una biblioteca MVVM como knockout.js (que recomiendo encarecidamente) puede hacerlo de forma más limpia:

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

Ohad Schneider
fuente
data-bind="click:function(){showAlert(false);}es un ejemplo perfecto de javascript intrusivo que está lejos de ser más limpio . Recomiendo encarecidamente NO seguir este enfoque
Leo
@Leo molesto de qué manera?
Ohad Schneider
Entrometido en todos los sentidos. Estás "incorporando" activamente el comportamiento a tu estructura / marcado html. Imagina que tuvieras que cambiar ese comportamiento ... ¿cuántas páginas y elementos html tendrás que cambiar? No me malinterpretes, todavía responde a la pregunta formulada y es por eso que no la rechazaré. Pero esto está lejos de ser una solución "más limpia"
Leo
No, lo que en realidad estoy diciendo es utilizar la separación de preocupaciones . Sus vistas (html) nunca deben contener javascript, las implicaciones negativas podrían ser enormes en un equipo de desarrollo. Aquí hay una gran pregunta (y respuestas) sobre Knockout y el data-bindatributo algo controvertido stackoverflow.com/questions/13451414/unobtrusive-knockout
Leo
¿Qué considera "JavaScript"? ¿Qué pasa si solo contiene el nombre del método a invocar? ¿Es el hecho de que lo llame con un parámetro (falso) lo que lo hace molesto a sus ojos?
Ohad Schneider
2

Entonces, si desea una solución que pueda hacer frente a páginas html dinámicas, como ya lo incluye, debe usar jQuery's live para configurar el controlador en todos los elementos que están ahora y en el futuro en el dom o se eliminan.

yo suelo

$(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>

Joschi
fuente
2

Esto funcionó mejor para mí:

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

También encontré este problema y el problema de simplemente piratear el botón de cierre es que todavía necesito acceso a los eventos de cierre de alerta de arranque estándar.

Mi solución fue escribir un pequeño complemento de jquery personalizable que inyecta una alerta Bootstrap 3 correctamente formada (con o sin botón de cierre, según lo necesite) con un mínimo de alboroto y le permite regenerarlo fácilmente después de cerrar la caja.

Consulte https://github.com/davesag/jquery-bs3Alert para ver el uso, las pruebas y los ejemplos.

Dave Sag
fuente
1

Estoy de acuerdo con la respuesta publicada por Henrik Karlsson y editada por Martin Prikryl. Tengo una sugerencia basada en la accesibilidad. Agregaría .attr ("aria-hidden", "true") al final, para que se vea así:

$(this).closest("." + $(this).attr("data-hide")).attr("aria-hidden", "true");
cfnerd
fuente
2
¿Es eso realmente necesario? jQuerys .hide conjuntos de funciones mostrar: ninguno, ¿no deberían los lectores de pantalla ser lo suficientemente inteligentes como para reconocerlo como oculto de todos modos?
Henrik Karlsson
1

Todas las soluciones anteriores utilizan bibliotecas externas, ya sean angulares o jQuery, y una versión anterior de Bootstrap. Entonces, aquí está la solución de Charles Wyke-Smith en JavaScript puro , aplicada a Bootstrap 4 . Sí, Bootstrap requiere jQuery para su propio código modal y de alertas, pero ya no todos escriben su propio código con jQuery.

Aquí está el html de la alerta:

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

Tenga en cuenta que inicialmente la alerta está oculta ( style="display: none;"), y en lugar del estándar data-dismiss="alert", hemos utilizado aquí data-hide="alert".

Aquí está el JavaScript para mostrar la alerta y anular el botón de cierre:

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

Si desea ocultar o mostrar la alerta mediante programación en otra parte del código, simplemente haga myAlert.style.display = 'none';o myAlert.style.display = 'block';.

Jaifroid
fuente
0

El problema se debe al uso de style="display:none", debe ocultar la alerta con Javascript o al menos al mostrarla, eliminar el atributo de estilo.

Plamen Nikolov
fuente
2
Realmente no, el problema es que Data-descarte eliminando el elemento
Henrik Karlsson
0

Según las otras respuestas y el cambio de descartar datos a ocultar datos, este ejemplo maneja la apertura de la alerta desde un enlace y permite que la alerta se abra y cierre repetidamente.

$('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 */
   });
});
Charles Wyke-Smith
fuente
0

Probé todos los métodos y la mejor manera para mí es usar las clases de arranque integradas .fadey.in

Ejemplo:

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

Nota: En jQuery, addClass ('in') para mostrar la alerta, removeClass ('in') para ocultarla.

Dato curioso: esto funciona para todos los elementos. No solo alertas.

clodal
fuente
0

Aquí hay una solución basada en la respuesta de Henrik Karlsson pero con la activación de eventos adecuada (basada en fuentes de 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 respuesta principalmente para mí, como una nota.

maxkoryukov
fuente
0

¿No se puede hacer esto simplemente agregando un div "contenedor" adicional y agregando el div de alerta eliminado nuevamente en él cada vez? ¿Parece funcionar para mi?

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');
Lightning_young
fuente