How can I have a counter like transition for a button label with JQuery

Viewed 74

I have a button and I want to change its label from say 1 to 2, so that 1 slides up and meanwhile 2 replaces it. It's what I tried in the snippet. However, nothing is shown in the end. Please note that 1 and 2 are examples, in general it should replaces the old value with a new value on an event.

$('#slideIndexBox').slideDown().promise().done(function() {
  $(this).text('2');
  $(this).slideUp();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button id="indicator" class="btn mb-2 btn-block btn-outline-info ">
  <!--<span id="slideIndicator"></span>-->
  <span id="slideIndexBox">1</span>
</button>

3 Answers

Please try it:

<button>
  <label class="show">1</label>
  <label class="hide">2</label>
</button>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$('button').on( 'click', function() {
    $(this).find('.hide').slideDown();
    $(this).find('.show').slideUp();
});
</script>

<style>
.show { display: block; }
.hide { display: none; }
</style>

If I'm understanding the effect you're going for, I would add a new element each time the number is incremented. These numbers could be added to a container, and with each click, the container would slide up to reveal the newly-appended element.

It would look something like this:

$("#indicator").click(function() {
  let number = $(".slideIndexBox", this).length + 1;
  let $num = $("<span class='slideIndexBox' />");
  $num.text(number);
  
  let $container = $(".slideContainer", this);
  let height = Math.round($(this).css("height").replace("px",""));
  $container
    .append($num)
    .css("transform", `translateY(-${(number-1)*height}px)`);
});
button {
  width: 30px;
  height: 30px;
  overflow: hidden;
  padding: 0;
}

.slideIndexBox {
  display: block;
  height: 30px;
  width: 100%;
  text-align: center;
  transform: translateY(6px);
}

.slideContainer {
  display: block;
  transition: transform 0.5s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button id="indicator" class="btn mb-2 btn-block btn-outline-info ">
  <span class="slideContainer">
    <span class="slideIndexBox">1</span>
  </span>
</button>

You could do this, but it will scroll back to the top after the last one. In this case below I've just added all the items right from the start since it will give your button an accurate width. You can just add items as you go however you like but the button will change width in that case.

This solution will however require that your button text is on one line to work. Also the button height is just arbitrary in the css.

$('#indicator').on('click', function () {
  var $container = $('div', this),
    index = ($container.data('i') || 0) + 1;
  if (index + 1 > $('span', $container).length) {
    $container.data('i', 0);
    $container.css('transform', 'translateY(0)');
  } else {
    $container.data('i', index);
    $container.css('transform', 'translateY(' + -$('span', this).height() * index + 'px)');
  }
});
.btn { height: 1.5em; overflow: hidden; display: inline-block; }
.btn span {
  display: block;
}
.btn div {
  transform: translateY(0);
  transition: transform 0.5s ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button id="indicator" class="btn mb-2 btn-block btn-outline-info ">
  <div>
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>Moar content</span>
  </div>
</button>

I see you need to replace the value though so this might not be what you are looking for.

Related