0

If I have a .slideUp() that runs against a class that belongs to multiple elements, how do I run code after the last element has completed its slideup effect? It seems like using the built in complete callback runs the callback after every individual element completes its slideup instead of doing it once when theyre all complete.

Here's some example code that might help illustrate the issue I'm having:

$("#my-button").click(() => {
  $(".my-target-class").slideUp(400, () => {
    console.log("I only want this to fire once...");
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>
    <div class="my-target-class">div 1</div>
    <div class="my-target-class">div 2</div>
    <div class="my-target-class">div 3</div>
    <button id="my-button">try me</button>
</section>
the8thbit
  • 601
  • 1
  • 5
  • 20

2 Answers2

2

In jQuery, this will actually run your slideUp (including its callback) on all elements, so the callback also fires several times.

You can use .promise to get a promise for the whole operation, and react on it being done:

$("#my-button").click(() => {
  $(".my-target-class").slideUp(400).promise().done(() => {
    console.log("I only want this to fire once...");
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>
    <div class="my-target-class">div 1</div>
    <div class="my-target-class">div 2</div>
    <div class="my-target-class">div 3</div>
    <button id="my-button">try me</button>
</section>
CherryDT
  • 25,571
  • 5
  • 49
  • 74
  • 1
    Thank you! I also found that using $.when(...).then(...); worked as per the links you and XCS provided as comments on my original question. In 5 min when I'm allowed to do it I'll checkmark this answer. :) – the8thbit Apr 18 '20 at 23:14
1

It seems like you should containerize the divs and only slide that one up:

$("#my-button").click(() => {
  $(".target-container").slideUp(400, () => {
    console.log("I only want this to fire once...");
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>
  <div class="target-container">
    <div class="my-target-class">div 1</div>
    <div class="my-target-class">div 2</div>
    <div class="my-target-class">div 3</div>
  </div>
  <button id="my-button">try me</button>
</section>
Mike
  • 1,279
  • 7
  • 18
  • 1
    Depends... it will look differently. – CherryDT Apr 18 '20 at 23:11
  • 1
    @CherryDT's answer is better for your issue. It'd be my preference, at least. I undeleted this answer because you're right, others may find value in it. – Mike Apr 18 '20 at 23:20
  • this is not suitable for the actual project I'm working on, unfortunately. Some of the elements with this class need to be visible when others aren't. However, CherryDT's answer worked. For other people who are able to structure their code in this way without losing functionality, this is absolutely a more intuitive solution. – the8thbit Apr 18 '20 at 23:22
  • 1
    Removed my copy of it now. – CherryDT Apr 18 '20 at 23:26