Mensagem de alerta do Twitter Bootstrap fechada e aberta novamente


103

Eu tenho um problema com mensagens de alerta. Ele é exibido normalmente, e posso fechá-lo quando o usuário pressiona x(fechar), mas quando o usuário tenta exibi-lo novamente (por exemplo, clicar no evento do botão), ele não é mostrado. (Além disso, se eu imprimir esta mensagem de alerta no console, é igual a [].) Meu código está aqui:

 <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! Preciso mostrar a mensagem de alerta somente depois que algum evento acontecer (por exemplo, botão clicado). Ou o que estou fazendo de errado?

Respostas:


180

A dispensa de dados remove completamente o elemento. Em vez disso, use o método .hide () do jQuery.

O método de correção rápida:

Usando javascript embutido para ocultar o elemento ao clicar desta forma:

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

No entanto, isso só deve ser usado se você for preguiçoso (o que não é bom se você quiser um aplicativo de fácil manutenção).

O método do-it-right:

Crie um novo atributo de dados para ocultar um elemento.

Javascript:

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

e, em seguida, altere dispensar dados para ocultar dados na marcação. Exemplo em jsfiddle .

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

Isso ocultará todos os elementos com a classe especificada em data-hide, ou seja: data-hide="alert"ocultará todos os elementos com a classe de alerta.

Xeon06 forneceu uma solução alternativa:

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

Isso ocultará apenas o elemento pai mais próximo. Isso é muito útil se você não quiser dar a cada alerta uma classe exclusiva. Observe que, no entanto, você precisa colocar o botão Fechar no alerta.

Definição de .closest do jquery doc :

Para cada elemento do conjunto, obtenha o primeiro elemento que corresponda ao seletor testando o próprio elemento e percorrendo seus ancestrais na árvore DOM.


4
Ei! Em relação à sua resposta certa. Isso ocultará TODOS os elementos que possuem a mesma classe (ou seja, alert) na página. Uma solução para isso seria substituir o conteúdo do retorno de chamada por esta linha $(this).closest("." + $(this).attr("data-hide")).hide();, o que afetará apenas o elemento pai mais próximo, visto que o botão de dispensar normalmente é colocado dentro do alerta que afeta.
— Alex Turpin

1
É verdade, não pensei em fazer funcionar dessa forma. Isso, no entanto, removerá em pequena medida a simplicidade desta solução. Vou adicioná-lo como um comentário ao código existente. Obrigado!
— Henrik Karlsson de

1
Novo nisso .. onde você definiria '$ (function () {..'
— S Rosam

1
Em qualquer lugar em um arquivo JavaScript ou em uma tag <script> code here </script>.
— Henrik Karlsson,

1
Se você usasse $ (document) .on ('click', '[data-hide]', function () {/ * * /}) Sua resposta seria perfeita;)
— shock_gone_wild

26

Acabei de usar uma variável de modelo para mostrar / ocultar a caixa de diálogo e removi o data-dismiss="alert"

Exemplo:

<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 mim e evita a necessidade de sair para jquery


1
Uma solução muito mais simples / melhor do que a resposta aceita com grande votação!
— Abs

Solução muito melhor, na minha opinião
— devqon


15

Acho que uma boa abordagem para esse problema seria aproveitar as vantagens do close.bs.alerttipo de evento do Bootstrap para ocultar o alerta em vez de removê-lo. O motivo pelo qual o Bootstrap expõe esse tipo de evento é para que você possa sobrescrever o comportamento padrão de remoção do alerta do DOM.

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

5

Se você estiver usando uma biblioteca MVVM, como knockout.js (que eu recomendo), você pode fazer isso de forma mais limpa:

<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);}é um exemplo perfeito de javascript intrusivo que está longe de ser mais limpo . Eu recomendo fortemente NÃO seguir esta abordagem
— Leo

@Leo intrusivo de que maneira?
— Ohad Schneider

Obstrusivo em todos os sentidos. Você está ativamente "embutindo" o comportamento em sua estrutura / marcação html. Imagine que você teve que mudar esse comportamento ... quantas páginas e elementos html você terá que mudar? Não me entenda mal, ele ainda responde à pergunta feita e é por isso que não vou votar contra ele. Mas isso está longe de ser uma solução "mais limpa"
— Leo

Não, o que estou realmente dizendo é usar separação de interesses . Suas visualizações (html) nunca devem conter javascript, as implicações negativas podem ser enormes em uma equipe de desenvolvimento. Aqui está uma ótima pergunta (e respostas) sobre Knockout e o data-bindatributo um tanto controverso stackoverflow.com/questions/13451414/unobtrusive-knockout
— Leo

O que você considera "JavaScript"? E se ele contivesse apenas o nome do método a ser invocado? É o fato de que ele o chama com um parâmetro (falso) que o torna intrusivo aos seus olhos?
— Ohad Schneider

2

Portanto, se você deseja uma solução que possa lidar com páginas html dinâmicas, como você já a incluiu, você deve usar o jQuery's live para definir o manipulador em todos os elementos que estão agora e no futuro no dom ou serão removidos.

eu 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

Isso funcionou melhor para mim:

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

1

Eu também encontrei esse problema e o problema de simplesmente hackear o botão Fechar é que ainda preciso acessar os eventos de alerta de fechamento padrão do bootstrap.

Minha solução foi escrever um pequeno plug-in jquery personalizável que injeta um alerta Bootstrap 3 formado corretamente (com ou sem o botão Fechar conforme necessário) com o mínimo de barulho e permite que você o regenere facilmente após o fechamento da caixa.

Consulte https://github.com/davesag/jquery-bs3Alert para uso, testes e exemplos.


1

Concordo com a resposta postada por Henrik Karlsson e editada por Martin Prikryl. Tenho uma sugestão, baseada na acessibilidade. Eu adicionaria .attr ("aria-hidden", "true") ao final dele, para que se pareça com:

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

2
Isso é realmente necessário? jQuerys .hide function sets display: none, não deveriam os leitores de tela ser inteligentes o suficiente para reconhecê-lo como oculto de qualquer maneira?
— Henrik Karlsson

1

Todas as soluções acima usam bibliotecas externas, angular ou jQuery, e uma versão antiga do Bootstrap. Então, aqui está a solução de Charles Wyke-Smith em JavaScript puro , aplicada ao Bootstrap 4 . Sim, o Bootstrap requer jQuery para seu próprio código modal e de alertas, mas nem todo mundo escreve seu próprio código com jQuery.

Aqui está o html do 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>

Observe que inicialmente o alerta está oculto ( style="display: none;") e, em vez do padrão data-dismiss="alert", usamos aqui data-hide="alert".

Aqui está o JavaScript para mostrar o alerta e substituir o botão Fechar:

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 desejar ocultar ou mostrar o alerta programaticamente em outro lugar no código, basta fazer myAlert.style.display = 'none';ou myAlert.style.display = 'block';.


0

O problema é causado pelo uso do style="display:none", você deve ocultar o alerta com Javascript ou pelo menos ao exibi-lo, remover o atributo de estilo.


2
Não realmente, o problema é ignorar dados ao remover o elemento
— Henrik Karlsson

0

Com base nas outras respostas e na alteração de dispensar dados para ocultar, este exemplo trata da abertura do alerta de um link e permite que o alerta seja aberto e fechado 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 */
   });
});

0

Eu tentei todos os métodos e a melhor maneira para mim é usar as classes de bootstrap integradas .fadee.in

Exemplo:

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

Nota: Em jQuery, addClass ('in') para mostrar o alerta, removeClass ('in') para ocultá-lo.

Curiosidade: isso funciona para todos os elementos. Não apenas alertas.


0

Aqui está uma solução baseada no resposta de Henrik Karlsson, mas com o acionamento de evento adequado (com base em fontes 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'))
    })
});

A resposta principalmente para mim, como uma nota.


0

Isso não pode ser feito simplesmente adicionando um div "contêiner" adicional e adicionando o div de alerta removido de volta nele a cada vez. Parece funcionar para mim?

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');
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.