Surely, many used the functionality to display and hide certain content through Bootstrap Collapse . So I use it, everything is successful, but I have some shortcomings that I wanted to remove. There is the following code:

<input id="btnShowHideDeletedLft" onclick="changeTextBtnDeletedLft()" type="button" class="btn btn-info" data-toggle="collapse" data-target="#tblDeletedLft" value="Посмотреть удаленные" /> <div id="tblDeletedLft" class="collapse" style="margin-top: 10px;"> @* тут мой контент - небольшая таблица *@ </div> 

This code block successfully fulfills. But, there is also JavaScript , in which the text of my button changes, here it is:

 function changeTextBtnDeletedLft() { var elem = document.getElementById("btnShowHideDeletedLft"); //elem.disabled = true; if (elem.value === 'Посмотреть удаленные') { elem.value = 'Скрыть удаленные'; } else { elem.value = 'Посмотреть удаленные'; } //setTimeout(function() { elem.disabled = false; }, 500); } 

This code also works, but alas, it does not work the way I would like, it is the problem that lies in it, namely: if you quickly double-click a button, the text in it changes twice, and the table is displayed (hidden) once. As a result, the test in the button will be View deleted and the table will already be displayed, or vice versa, that is, there will be a mismatch of the label in the button and the content.

After that, the thought came to me, and what if the disable button is half a second after the click, the table will appear in time for this time, and the user will not click twice in a row!

If you use commented code in JavaScript , then Collapse stops working. That is, the display and hide the table does not occur. The text in the button changes, it disappears, but the display and hide doesn't work.

Of course, you can write on the View / Hide deleted button and you will not need to change the text, which means that timeouts are not needed, but I would like to use Feng Shui to disable the button and change the text in it and display / hide the content. How to do it?

    2 answers 2

    Once you are using Bootstrap, you must have jQuery connected.

    When an element is collapsing , the block has a collapsing class, by which it can be accurately determined that the element is currently animated. In this case, cancel the execution of the script:

     if ($(elem.data("target")).is(".collapsing")) return; 

    Total:

     function changeTextBtnDeletedLft() { var elem = $("#btnShowHideDeletedLft"); if ($(elem.data("target")).is(".collapsing")) return; if (elem.val() === 'Посмотреть удаленные') { elem.val('Скрыть удаленные'); } else { elem.val('Посмотреть удаленные'); } } 
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <input id="btnShowHideDeletedLft" onclick="changeTextBtnDeletedLft()" type="button" class="btn btn-info" data-toggle="collapse" data-target="#tblDeletedLft" value="Посмотреть удаленные" /> <div id="tblDeletedLft" class="collapse" style="margin-top: 10px;"> @* тут мой контент - небольшая таблица *@ </div> 

    • I changed your code a bit to make it work, added a $(elem) wrapper for an element like this: if ($($(elem).data("target")).is(".collapsing")) return; But everything also does not work. Some kind of magic, I am surprised, if you look at the content, then everything is normal there, the content is loaded onto the page right away, just hidden. The only thing that does not exist is the connected styles of bootstrap.min.css and bootstrap-theme.min.css on the page, but I do not think that this is a direct big problem. The search continues. - Denis Bubnov
    • When opening or closing the bootstrap element occurs, it checks whether it is executed now or not before execution. If the animation is on, then it does nothing, if it does not, then it opens or closes the element again. This check is to ensure that the element is not broken or did not jump here and there with quick clicks. Actually you did not have such a check and the clicks worked instantly. - DarkSir
    • Yes, look at how I get content, not like you have: var elem = $("#btnShowHideDeletedLft"); I use jQuery here too - Crantisz
    • What your code does is I understand, but I don’t understand why it works differently than here on SO in the snippet. Thank you for the answer, it is useful. The solution implemented a little differently, explaining that collapsing occurs after calling the function changeTextBtnDeletedLft() . You +1 :) - Denis Bubnov

    When adding a check of the condition of display / hide at the moment of clicking on the called function:

     if ($($(elem).data("target")).is(".collapsing")) return; 

    the expression inside the check is always false . In debugging, we managed to find out that collapsing occurs after the completion of the changeTextBtnDeletedLft() function. It was not possible to find out the reason for this behavior and I had to choose a different solution without verification.

    In the open spaces, SO found this answer: jQuery show.bs.collapse event for nested Bootstrap collapsible buttons for related events Collapse . The idea to solve his problem took from this answer.

    I added and modified my JavaScript handling of Collapse events that occur while hiding and displaying content:

     <script type="text/javascript"> var elemBtnShowHide = document.getElementById("btnShowHideDeletedLft"); function changeTextBtnDeletedLft() { // меняем текст в кнопке if (elemBtnShowHide.value === 'Посмотреть удаленные лифты') { elemBtnShowHide.value = 'Скрыть удаленные лифты'; } else { elemBtnShowHide.value = 'Посмотреть удаленные лифты'; } } $('#tblDeletedLft').on('shown.bs.collapse', function () { // после отображения elemBtnShowHide.disabled = false; // кнопка активна }).on('show.bs.collapse', function () { // перед отображением elemBtnShowHide.disabled = true; // кнопка не активна }); $('#tblDeletedLft').on('hidden.bs.collapse', function () { // после скрытия elemBtnShowHide.disabled = false; // кнопка активна }).on('hide.bs.collapse', function () { // перед скрытием elemBtnShowHide.disabled = true; // кнопка не активна }); </script> 

    The function of changing the text of the button was left unchanged, added Collapse event handling. Thus, the button is disabled at the beginning of the animation and becomes active after its completion for both cases, both for display and for hiding.

    All necessary additional information on events Collapse found here: Bootstrap JS Collapse . Information on events Collapse translated and attached for completeness of the answer:

    Collapse Events

    1. show.bs.collapse - occurs when the collapsible element is shown before it is shown;
    2. shown.bs.collapse - occurs when collapsible element is fully shown (after CSS transitions have completed) - occurs when the collapsible element is fully displayed (after the CSS transitions are completed);
    3. hide.bs.collapse - occurs when the collapsible element is hidden to be hidden - occurs before the folding element is hidden;
    4. hidden.bs.collapse - occurs when collapsible element is fully hidden (after CSS transitions have completed) - occurs when the folding element is completely hidden (after the CSS transitions are completed)