Le message d'alerte Twitter Bootstrap se ferme et s'ouvre à nouveau

103

J'ai un problème avec les messages d'alerte. Il s'affiche normalement et je peux le fermer lorsque l'utilisateur appuie sur x(fermer), mais lorsque l'utilisateur essaie de l'afficher à nouveau (par exemple, cliquez sur l'événement de bouton), il n'est pas affiché. (De plus, si j'imprime ce message d'alerte sur la console, il est égal à [].) Mon code est ici:

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

Et événement:

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

PS! Je n'ai besoin d'afficher un message d'alerte qu'après un événement (par exemple, un clic sur un bouton). Ou ce que je fais mal?

ben3000
la source

Réponses:

180

Le rejet des données supprime complètement l'élément. Utilisez plutôt la méthode .hide () de jQuery.

La méthode fix-it-quick:

Utilisation de javascript en ligne pour masquer l'élément en cliquant comme ceci:

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

Cela ne devrait cependant être utilisé que si vous êtes paresseux (ce qui n'est pas une bonne chose si vous voulez une application maintenable).

La méthode do-it-right:

Créez un nouvel attribut de données pour masquer un élément.

Javascript:

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

puis remplacez les données par masquer les données dans le balisage. Exemple à jsfiddle .

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

Cela masquera tous les éléments avec la classe spécifiée dans data-hide, c'est-à-dire: data-hide="alert"masquera tous les éléments avec la classe alert.

Xeon06 a fourni une solution alternative:

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

Cela ne masquera que l'élément parent le plus proche. Ceci est très utile si vous ne souhaitez pas attribuer à chaque alerte une classe unique. Veuillez noter que, cependant, vous devez placer le bouton de fermeture dans l'alerte.

Définition de .closest de jquery doc :

Pour chaque élément de l'ensemble, obtenez le premier élément qui correspond au sélecteur en testant l'élément lui-même et en parcourant ses ancêtres dans l'arborescence DOM.

Henrik Karlsson
la source
4
Hey! En ce qui concerne votre bonne réponse. Cela masquera TOUS les éléments qui ont la même classe (c'est-à-dire alert) sur la page. Une solution pour cela serait de remplacer le contenu du rappel par cette ligne $(this).closest("." + $(this).attr("data-hide")).hide();, ce qui n'affectera que l'élément parent le plus proche, étant donné que le bouton de rejet est généralement placé dans l'alerte qu'il affecte.
Alex Turpin
1
C'est vrai, je n'ai pas pensé à le faire fonctionner de cette façon. Cela enlèvera cependant dans une faible mesure la simplicité de cette solution. Je l'ajouterai en commentaire au code existant. Merci!
Henrik Karlsson
1
Nouveau dans ce domaine .. où définiriez-vous le '$ (function () {..'
S Rosam
1
N'importe où dans un fichier JavaScript ou dans une balise <script> code here </script>.
Henrik Karlsson
1
Si vous utilisiez $ (document) .on ('click', '[data-hide]', function () {/ * * /}) Votre réponse serait parfaite;)
shock_gone_wild
26

Je viens d'utiliser une variable de modèle pour afficher / masquer la boîte de dialogue et supprimer le data-dismiss="alert"

Exemple:

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

fonctionne pour moi et arrête le besoin d'aller à jquery

user1661621
la source
1
Une solution beaucoup plus simple / meilleure que la réponse hautement votée!
Abs
Une bien meilleure solution à mon avis
devqon
j'aime ton idée
Kumaresan Perumal
15

Je pense qu'une bonne approche à ce problème serait de profiter du close.bs.alerttype d'événement de Bootstrap pour masquer l'alerte au lieu de la supprimer. La raison pour laquelle Bootstrap expose ce type d'événement est que vous pouvez remplacer le comportement par défaut de suppression de l'alerte du DOM.

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

Si vous utilisez une bibliothèque MVVM telle que knockout.js (que je recommande vivement), vous pouvez le faire plus proprement:

<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
la source
data-bind="click:function(){showAlert(false);}est un exemple parfait de javascript intrusif qui est loin d'être plus propre . Je recommande fortement de NE PAS suivre cette approche
Leo
@Leo envahissant de quelle manière?
Ohad Schneider
Obtrusif à tous points de vue. Vous intégrez activement un comportement à votre structure / balisage html. Imaginez que vous deviez changer ce comportement ... combien de pages et d'éléments html devrez-vous changer? Ne vous méprenez pas, il répond toujours à la question posée et c'est pourquoi je ne le voterai pas. Mais c'est loin d'être une solution "plus propre"
Leo
Non, ce que je dis en fait, c'est d' utiliser la séparation des préoccupations . Vos vues (html) ne doivent jamais contenir de javascript, les implications négatives pourraient être énormes dans une équipe de développement. Voici une excellente question (et réponses) sur Knockout et l' data-bindattribut quelque peu controversé stackoverflow.com/questions/13451414/unobtrusive-knockout
Leo
Que considérez-vous comme "JavaScript"? Et s'il ne contenait que le nom de la méthode à invoquer? Est-ce le fait qu'il l'appelle avec un paramètre (faux) qui le rend intrusif à vos yeux?
Ohad Schneider
2

Donc, si vous voulez une solution capable de gérer les pages html dynamiques, comme vous l'incluez déjà, vous devez utiliser live de jQuery pour définir le gestionnaire sur tous les éléments qui sont maintenant et à l'avenir dans le dom ou qui sont supprimés.

j'utilise

$(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
la source
2

Cela a fonctionné le mieux pour moi:

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

J'ai également rencontré ce problème et le problème avec le simple piratage du bouton de fermeture est que j'ai toujours besoin d'accéder aux événements de fermeture d'alerte d'amorçage standard.

Ma solution était d'écrire un petit plugin jquery personnalisable qui injecte une alerte Bootstrap 3 correctement formée (avec ou sans bouton de fermeture selon vos besoins) avec un minimum de tracas et vous permet de le régénérer facilement après la fermeture de la boîte.

Voir https://github.com/davesag/jquery-bs3Alert pour l'utilisation, les tests et les exemples.

Dave Sag
la source
1

Je suis d'accord avec la réponse publiée par Henrik Karlsson et éditée par Martin Prikryl. J'ai une suggestion, basée sur l'accessibilité. J'ajouterais .attr ("aria-hidden", "true") à la fin, pour qu'il ressemble à:

$(this).closest("." + $(this).attr("data-hide")).attr("aria-hidden", "true");
cfnerd
la source
2
Est-ce vraiment nécessaire? Affichage des ensembles de fonctions jQuerys .hide: aucun, les lecteurs d'écran ne devraient-ils pas être assez intelligents pour le reconnaître de toute façon comme caché?
Henrik Karlsson
1

Toutes les solutions ci-dessus utilisent des bibliothèques externes, angular ou jQuery, et une ancienne version de Bootstrap. Voici donc la solution de Charles Wyke-Smith en pur JavaScript , appliquée à Bootstrap 4 . Oui, Bootstrap nécessite jQuery pour son propre code modal et d'alertes, mais tout le monde n'écrit plus son propre code avec jQuery.

Voici le html de l'alerte:

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

Notez qu'au départ l'alerte est masquée ( style="display: none;"), et à la place du standard data-dismiss="alert", nous l'avons ici utilisé data-hide="alert".

Voici le JavaScript pour afficher l'alerte et remplacer le bouton de fermeture:

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 vous souhaitez masquer ou afficher l'alerte par programmation ailleurs dans le code, faites simplement myAlert.style.display = 'none';ou myAlert.style.display = 'block';.

Jaifroid
la source
0

Le problème est causé par l'utilisation de style="display:none", vous devez masquer l' alerte avec Javascript ou du moins lors de son affichage, supprimer l'attribut style.

Plamen Nikolov
la source
2
Pas vraiment, le problème est de supprimer l'élément Data-rejet
Henrik Karlsson
0

Sur la base des autres réponses et de la modification des données rejetées par masquage des données, cet exemple gère l'ouverture de l'alerte à partir d'un lien et permet à l'alerte d'être ouverte et fermée à plusieurs reprises

$('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
la source
0

J'ai essayé toutes les méthodes et le meilleur moyen pour moi est d'utiliser les classes bootstrap intégrées .fadeet.in

Exemple:

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

Remarque: dans jQuery, addClass ('in') pour afficher l'alerte, removeClass ('in') pour la masquer.

Fait amusant: cela fonctionne pour tous les éléments. Pas seulement des alertes.

clodal
la source
0

Voici une solution basée sur la réponse d' Henrik Karlsson mais avec un déclenchement d'événement approprié (basé sur les sources 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 réponse principalement pour moi, en guise de note.

maxkoryukov
la source
0

Cela ne peut-il pas être fait simplement en ajoutant un div "conteneur" supplémentaire et en y ajoutant à chaque fois le div d'alerte supprimé. Semble travailler pour moi?

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