Disable click while Hide/show effect ends with jQuery

Asked

Viewed 202 times

0

I have a menu with 3 buttons. Each button shows the respective DIV and hides the rest, with hide/show, for example. How do I prevent the button from being clicked again before the effect hide/show finished? Or if someone has another method so that when quick clicks occur one div does not overlap the other.

$('.items').first().show();	
	$('.menu-services li a').click(function() {
		item_id = $(this).attr("data-service");
		$('.items').fadeOut(400, function(){
			$('.'+item_id).delay(700).fadeIn(400);
		});
	});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<ul class="menu-services">
  <li>
    <a href="javascript:;" data-service="item-1">Serviço 1</a>
  </li>
  <li>
    <a href="javascript:;" data-service="item-2">Serviço 2</a>
  </li>
</ul>

<div class="items item-1 row" style="display: none;">
  <h1>Serviço 1</h1> 
</div>
<div class="items item-2 row" style="display: none;">
  <h1>Serviço 2</h1> 
</div>

2 answers

1

When using the selector $('.items').fadeOut... you will call the fadeOut twice, because there are two elements with the class .items. The point was that the fadeOut occurred only once.

For this put the pseudo selector :visible fadeOut only reaches the visible element:

$('.items:visible').fadeOut...

Now, so that one animation does not run over the other, use .stop(), that for the animation that is taking place:

Example:

$('.items').first().show();

$('.menu-services li a').click(function(){
    $('.items').stop();
    var item_id = $(this).attr("data-service");
    $('.items:visible').fadeOut(400, function(){
       $('.'+item_id).delay(700).fadeIn(400);
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="menu-services">
  <li>
    <a href="javascript:;" data-service="item-1">Serviço 1</a>
  </li>
  <li>
    <a href="javascript:;" data-service="item-2">Serviço 2</a>
  </li>
</ul>

<div class="items item-1 row" style="display: none;">
  <h1>Serviço 1</h1> 
</div>
<div class="items item-2 row" style="display: none;">
  <h1>Serviço 2</h1> 
</div>

  • Mass! I thought I would come a reply with rss setTimeout

  • @hugocsl just updated my algorithm, what do you think?

  • here still gave bug to me! I clicked fast and displayed the contents

1


First of all I analyzed your code and I checked that you are using the hyperlink anchor <a> as if it were a button, for good practice don’t do this! Instead of hyperlink <a> use the tag <button>!

Definition of Tag usage <a>

The tag <a> sets a hyperlink, which is used to link from one page to another. The most important attribute of the element <a> is the attribute href, that indicates the destination of the link.

OFFICIAL SOURCE: W3SCHOOLS

Definition of Tag usage

The tag <button> defines a clickable button. Within an element <button> you can place content such as text or images. This is the difference between this element and the buttons created with the element <input>.

TIP: Always specify the type attribute for an element <button>. Different browsers use different standard types for the element <button>.

OFFICIAL SOURCE: W3SCHOOLS

Now let’s go to the options we have according to the scenario, as you did not god us any business rule and did not detail much your problem I drew the following conclusion:

You will have several buttons (services) and several containers that are the Divs (list of items of certain services). They will be static in HTML, that is, I could not create a container for all service items, and dynamically insert the contents of that item in this container.

        // PERCORRE A ÁRVORE HTML, DENTRO DA LISTA ONDE SE ENCONTRAM OS BOTÕES
        // RETORNA UM ARRAY DE BOTÕES ENCONTRADOS
        $.fn.searchButtons = function () {
            return $('.menu-services li button').each(() => { });
        }

        // PERCORRE A ÁRVORE HTML, DENTRO DO BODY ONDE SE ENCONTRAM OS CONTAINERS
        // RETORNA UM ARRAY DE CONTAINERS ENCONTRADOS
        $.fn.searchContainers = function () {
            return $('div').each(() => { });
        }

        // EXIBE & ESCONDE TODOS OS CONTAINERS DOS ITEMS DE SERVIÇOS
        $.fn.displayContainers = function (_buttonClickedEl) {
            $.fn.searchContainers().each((i, el) => {
                if (this.id === _buttonClickedEl.id) {
                    $(el).show();
                }
            });
        }

        $.fn.hideContainers = function (_buttonClickedEl) {
            $.fn.searchContainers().each((i, el) => {
                if (this.id !== _buttonClickedEl.id) {
                    $(el).hide();
                }
            });
        }

        // HABILITA & DESABILITA TODOS OS BOTÕES DA LISTA DE SERVIÇOS
        $.fn.enableAllButtons = function () {
            $.fn.searchButtons().each((i, el) => {
                $(el).attr("disabled", false);
            });
        }

        $.fn.disableAllButtons = function () {
            $.fn.searchButtons().each((i, el) => {
                $(el).attr("disabled", true);
            });
        }

        // CRIA O EFEITO DE FADEOUT E FADEIN
        $.fn.createEffectContainer = function (_buttonClickedID, _fadeOutTimer, _fadeInTimer, _delayFadeInTimer) {
            var containerItemService = `#items-${_buttonClickedID}`;

            $(containerItemService).fadeOut(_fadeOutTimer, function () {
                $(this).delay(_delayFadeInTimer).fadeIn(_fadeInTimer, function () {
                    $.fn.enableAllButtons();
                });
            });
        }

        // EVENTO DE ONCLICK NO DETERMINADO BOTÃO DE SERVIÇO DA LISTA
        $('.menu-services li button').click(function () {
            $.fn.disableAllButtons();
            $.fn.displayContainers(this);
            $.fn.hideContainers(this);
            $.fn.createEffectContainer(this.id, 400, 400, 700);
        });
    <ul class="menu-services">
        <li>
            <button type="button" id="service-one">Serviço 1</button>
        </li>
        <li>
            <button type="button" id="service-two">Serviço 2</button>
        </li>
    </ul>

    <div id="items-service-one" class="row" style="display: block;">
        <h1>Serviço 1</h1>
    </div>
    <div id="items-service-two" class="row" style="display: none;">
        <h1>Serviço 2</h1>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>

  • I don’t think you solved https://imgur.com/6vuECLs

  • @hugocsl the disabled is working, but the timestamp is too low, so it gives you the feeling that you are clicking several times in a row on the disabled button.. However, you can understand whether he wants to disable all buttons or just what he clicked?

  • Sorry to disagree, but the <a> tag has flexibility of use, and can be used for actions other than just to direct to another page via href. This tag is widely used in menus (mainly). The button tag does not serve in menus.

  • But in fact, she could be dismissed, leaving only the <li> clickable.

  • @Sam understand your point of view, really the anchors <a> are used at times as if it were a <button>, as for example giving that effect in transition of <section> you know? But following the documentation of prestige and good practices they should not be used in this way. As a developer I follow good practices and documentation, but I understand your point of view.

  • @Sam as he did not expand his question, leaving the business rules (RN) and detailing what the "system" should do, I ended up drawing that conclusion. But he could have done it in a dynamic way, like I said.

  • But the quotes you stressed in your reply don’t say you can’t use the <a> tag with different actions, it just describes the default use of the tag. Moreover, the citation is still incomplete, since the hrefcan be used as an anchor for a id of some element: href="#id_do_elemento" .

  • @Correct Sam, I just passed what was written under the documentation and did not detail much to get to the point, the same should research on the subject after this reading of the reply and draw its own conclusions, so it becomes a good developer.

  • I’m sorry I didn’t have more details, but I wanted to ask a very direct question in the case and also wanted to make the code very simple. The question of the <a> button is really a custom, but thanks for the tip too. Your solution worked well for what we saw here. I thought the script would be smaller, but what matters is that you found the solution! kkk.. and really, I’m using dynamic content! Thanks for your help!

  • @Caiquesouza hello, I used good practices and design Patterns, creating functions for each action. But if you want to leave everything in one place can only, but do not recommend it. I recommend following good practices, code reuse and Patterns design.

Show 5 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.