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?

ben3000
fonte

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.

Henrik Karlsson
fonte
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

user1661621
fonte
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
Gosto da
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');
});
Kimbaudi
fonte
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/

Ohad Schneider
fonte
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>

Joschi
fonte
2

Isso funcionou melhor para mim:

$('.alert').on('close.bs.alert', function (e) {
    e.preventDefault();
    $(this).hide();
});
Harshal Lonare
fonte
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.

Dave Sag
fonte
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");
cfnerd
fonte
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';.

Jaifroid
fonte
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.

Plamen Nikolov
fonte
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 */
   });
});
Charles Wyke-Smith
fonte
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.

clodal
fonte
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.

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