Komunikat ostrzegawczy Twitter Bootstrap zamyka się i otwiera ponownie

103

Mam problem z komunikatami ostrzegawczymi. Jest wyświetlany normalnie i mogę go zamknąć, gdy użytkownik naciśnie x(zamknij), ale gdy użytkownik spróbuje go ponownie wyświetlić (na przykład kliknięcie zdarzenia przycisku), nie jest on wyświetlany. (Co więcej, jeśli wydrukuję ten komunikat ostrzegawczy na konsoli, jest on równy [].) Mój kod jest tutaj:

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

I wydarzenie:

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

PS! Muszę pokazać komunikat ostrzegawczy dopiero po wystąpieniu jakiegoś zdarzenia (na przykład po kliknięciu przycisku). Albo co robię źle?

ben3000
źródło

Odpowiedzi:

180

Odrzucenie danych całkowicie usuwa element. Zamiast tego użyj metody .hide () jQuery.

Szybka metoda naprawy:

Używanie wbudowanego javascript do ukrycia elementu onclick w następujący sposób:

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

Powinno to jednak być używane tylko wtedy, gdy jesteś leniwy (co nie jest dobre, jeśli potrzebujesz aplikacji, którą można utrzymać).

Metoda zrób to dobrze:

Utwórz nowy atrybut danych w celu ukrycia elementu.

JavaScript:

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

a następnie zmień odrzucanie danych na ukrywanie danych w znacznikach. Przykład na jsfiddle .

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

Spowoduje to ukrycie wszystkich elementów z klasą określoną w data-hide, tj .: data-hide="alert"ukryje wszystkie elementy z klasą alert.

Xeon06 dostarczył alternatywne rozwiązanie:

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

Spowoduje to ukrycie tylko najbliższego elementu nadrzędnego. Jest to bardzo przydatne, jeśli nie chcesz przypisywać każdemu alertowi unikalnej klasy. Należy jednak pamiętać, że w alercie należy umieścić przycisk zamykania.

Definicja .closest z dokumentu jquery :

Dla każdego elementu w zestawie pobierz pierwszy element, który pasuje do selektora, testując sam element i przechodząc przez jego przodków w drzewie DOM.

Henrik Karlsson
źródło
4
Hej! Jeśli chodzi o twoją zrób to właściwą odpowiedź. Spowoduje to ukrycie KAŻDEGO elementu, który ma tę samą klasę (tj. alert) Na stronie. Rozwiązaniem byłoby zastąpienie treści wywołania zwrotnego tą linią $(this).closest("." + $(this).attr("data-hide")).hide();, co wpłynie tylko na najbliższy element nadrzędny, ponieważ przycisk odrzucenia jest zwykle umieszczony w alercie, na który ma wpływ.
Alex Turpin
1
To prawda, nie myślałem o tym, żeby to działało w ten sposób. To jednak w niewielkim stopniu zniweluje prostotę tego rozwiązania. Dodam to jako komentarz do istniejącego kodu. Dzięki!
Henrik Karlsson
1
Nowość w tym .. gdzie można zdefiniować „$ (function () {..”
S Rosam
1
W dowolnym miejscu w pliku JavaScript lub w tagu <script> kod tutaj </script>.
Henrik Karlsson
1
Jeśli użyjesz $ (document) .on ('click', '[data-hide]', function () {/ * * /}) Twoja odpowiedź byłaby idealna;)
shock_gone_wild
26

Właśnie użyłem zmiennej modelu, aby pokazać / ukryć okno dialogowe i usunąłem plik data-dismiss="alert"

Przykład:

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

działa dla mnie i nie ma potrzeby wychodzenia do jquery

user1661621
źródło
1
O wiele prostsze / lepsze rozwiązanie niż wysoko oceniona, zaakceptowana odpowiedź!
Abs
Moim zdaniem dużo lepsze rozwiązanie
devqon
Podoba mi się twój pomysł
Kumaresan Perumal
15

Myślę, że dobrym podejściem do tego problemu byłoby skorzystanie z close.bs.alerttypu zdarzenia Bootstrap, aby ukryć alert zamiast go usuwać. Powodem, dla którego Bootstrap ujawnia ten typ zdarzenia, jest to, że możesz nadpisać domyślne zachowanie polegające na usuwaniu alertu z DOM.

$('.alert').on('close.bs.alert', function (e) {
    e.preventDefault();
    $(this).addClass('hidden');
});
kimbaudi
źródło
5

Jeśli używasz biblioteki MVVM, takiej jak knockout.js (co bardzo polecam), możesz to zrobić w bardziej przejrzysty sposób:

<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
źródło
data-bind="click:function(){showAlert(false);}jest doskonałym przykładem natrętnego javascript, który nie jest bardziej przejrzysty . Zdecydowanie polecam NIE stosować tego podejścia
Leo,
@Leo natrętne w jaki sposób?
Ohad Schneider,
Natrętny pod każdym względem. Aktywnie „osadzasz” zachowanie w swojej strukturze / znacznikach html. Wyobraź sobie, że musiałeś zmienić to zachowanie ... ile stron i elementów html będziesz musiał zmienić? Nie zrozum mnie źle, nadal odpowiada na zadane pytanie i dlatego nie będę go odrzucał. Ale to dalekie od „czystszego” rozwiązania
Leo,
Nie, tak naprawdę mówię o oddzieleniu obaw . Twoje poglądy (html) nigdy nie powinny zawierać javascript, negatywne konsekwencje mogą być ogromne w zespole deweloperskim. Oto wielkie pytanie (i odpowiedzi) o Knockout i nieco kontrowersyjnej data-bindatrybutu stackoverflow.com/questions/13451414/unobtrusive-knockout
Leo
Co uważasz za „JavaScript”? A co by było, gdyby zawierał tylko nazwę metody do wywołania? Czy to fakt, że nazywa go parametrem (fałsz), który sprawia, że ​​jest on natrętny w twoich oczach?
Ohad Schneider,
2

Jeśli więc potrzebujesz rozwiązania, które poradzi sobie z dynamicznymi stronami html, ponieważ już je dołączasz, powinieneś użyć live jQuery, aby ustawić obsługę wszystkich elementów, które są teraz iw przyszłości w dom lub zostaną usunięte.

używam

$(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
źródło
2

To zadziałało dla mnie najlepiej:

$('.alert').on('close.bs.alert', function (e) {
    e.preventDefault();
    $(this).hide();
});
Harshal Lonare
źródło
1

Natknąłem się również na ten problem, a problem z hakowaniem przycisku zamykania polega na tym, że nadal potrzebuję dostępu do standardowych zdarzeń typu alert-close podczas ładowania początkowego.

Moim rozwiązaniem było napisanie małej, dostosowywalnej wtyczki jquery która wstrzykuje odpowiednio uformowany alert Bootstrap 3 (z przyciskiem zamykania lub bez, jak tego potrzebujesz) przy minimalnym zamieszaniu i pozwala łatwo go zregenerować po zamknięciu pudełka.

Zobacz https://github.com/davesag/jquery-bs3Alert, aby uzyskać informacje na temat użycia, testów i przykładów.

Dave Sag
źródło
1

Zgadzam się z odpowiedzią zamieszczoną przez Henrika Karlssona i zredagowaną przez Martina Prikryla. Mam jedną sugestię dotyczącą dostępności. Dodałbym .attr ("aria-hidden", "true") na końcu, tak aby wyglądało to tak:

$(this).closest("." + $(this).attr("data-hide")).attr("aria-hidden", "true");
cfnerd
źródło
2
Czy to naprawdę potrzebne? jQuerys .hide zestawy funkcji display: none, czy czytniki ekranu nie powinny być na tyle sprytne, aby i tak rozpoznać je jako ukryte?
Henrik Karlsson
1

Wszystkie powyższe rozwiązania wykorzystują zewnętrzne biblioteki, angular lub jQuery oraz starą wersję Bootstrap. Oto rozwiązanie Charlesa Wyke-Smitha w czystym JavaScript , zastosowane w Bootstrap 4 . Tak, Bootstrap wymaga jQuery jako własnego kodu modalnego i alertów, ale nie każdy już pisze swój własny kod za pomocą jQuery.

Oto html alertu:

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

Zauważ, że początkowo alert jest ukryty ( style="display: none;"), a zamiast standardu data-dismiss="alert"użyliśmy tutaj data-hide="alert".

Oto JavaScript, który pokazuje alert i zastępuje przycisk zamykania:

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

Jeśli chcesz programowo ukryć lub pokazać alert w innym miejscu kodu, po prostu zrób myAlert.style.display = 'none';lub myAlert.style.display = 'block';.

Jaifroid
źródło
0

Problem jest spowodowany użyciem style="display:none", powinieneś ukryć alert za pomocą JavaScript lub przynajmniej podczas jego wyświetlania usunąć atrybut style.

Plamen Nikolov
źródło
2
Nie do końca, problemem jest odrzucenie danych przez usunięcie elementu
Henrik Karlsson
0

W oparciu o inne odpowiedzi i zmianę odrzucania danych na ukrywanie danych, ten przykład obsługuje otwieranie alertu z linku i umożliwia wielokrotne otwieranie i zamykanie alertu

$('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
źródło
0

Wypróbowałem wszystkie metody i najlepszym sposobem jest dla mnie użycie wbudowanych klas ładowania początkowego .fade i.in

Przykład:

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

Uwaga: w jQuery dodajClass („in”), aby wyświetlić alert, usuńClass („in”), aby go ukryć.

Ciekawostka: działa to dla wszystkich elementów. Nie tylko alerty.

clodal
źródło
0

Oto rozwiązanie oparte na odpowiedź przez Henrik Karlsson ale z właściwego zdarzenia wyzwalającego (na podstawie źró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'))
    })
});

Odpowiedź głównie dla mnie, jako notatka.

maxkoryukov
źródło
0

Czy nie można tego zrobić po prostu dodając dodatkowy element div „container” i za każdym razem dodając z powrotem usunięty element div alert. Wydaje mi się, że to działa dla mnie?

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
źródło