Lavios
Lavios

Reputation: 1179

How to animate this function?

I need to animate the function descramble(). So, it changes the first character then moves on the next character and so on. I have tried using setTimeout() but that just delays the launch of the function. I just need to animate the ROT13 conversion letter by letter.

I'm using slice() to remove the first element of the string replacing it with ROT13 then replacing the string with the new letter plus the whole string. I was unable to found a way to only remove the first letter of the paragraph. You can click the third paragraph in the jsfiddle to see the conversion.

$("#last-second-inside p:nth-child(3)").one('click', function() {
  $(this).css('cursor', 'default');
  var str = "Vg'f fvzcyr lbh jvyy whfg nqq nabgure pbyhza nsgre sbhe'f cynpr naq gung pbyhza jvyy unir gur cynpr inyhr bs rvtug'f.";
  var strArr = str.split('');
  var decodedArr = [];
  var increaseNum = -1;
  descramble();

  function descramble() {
    strArr.map(function(num) {
      increaseNum++;
      var currentLetter = num.charCodeAt();
      if (currentLetter >= 65 && currentLetter <= 90 || currentLetter >= 97 && currentLetter <= 122) {
        if (currentLetter >= 78 && currentLetter <= 90 || currentLetter >= 110 && currentLetter >= 97) {
          decodedArr.push(String.fromCharCode(currentLetter - 13));
        } else {
          decodedArr.push(String.fromCharCode(currentLetter + 13));
        }
      } else {
        decodedArr.push(num);
      }
      var sliced = str.slice(increaseNum + 1, str.length - 1);
      $("#last-second-inside p:nth-child(3)").text(decodedArr.join('') + sliced);
    })
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="last-second-inside">
  <p>You probably now understand that how binary works and how simple it is.</p>
  <p>Now, I need you to think about that how you might display 8 in binary. After giving it a shot, you can click on the next paragraph to descramble it.</p>
  <p>Vg'f fvzcyr lbh jvyy whfg nqq nabgure pbyhza nsgre sbhe'f cynpr naq gung pbyhza jvyy unir gur cynpr inyhr bs rvtug'f.</p>
</div>

Upvotes: 1

Views: 59

Answers (4)

guest271314
guest271314

Reputation: 1

Try using .queue()

$("#last-second-inside p:nth-child(3)").one('click', function() {
  $(this).css('cursor', 'default');
  var str = "Vg'f fvzcyr lbh jvyy whfg nqq nabgure pbyhza nsgre sbhe'f cynpr naq gung pbyhza jvyy unir gur cynpr inyhr bs rvtug'f.";
  var strArr = str.split('');
  var decodedArr = [];
  var increaseNum = -1;
  descramble();

  function descramble() {
    $({}).queue("descramble", strArr.map(function(num) {
      return function(next) {
        increaseNum++;
        var currentLetter = num.charCodeAt();
        if (currentLetter >= 65 && currentLetter <= 90 || currentLetter >= 97 && currentLetter <= 122) {
          if (currentLetter >= 78 && currentLetter <= 90 || currentLetter >= 110 && currentLetter >= 97) {
            decodedArr.push(String.fromCharCode(currentLetter - 13));
          } else {
            decodedArr.push(String.fromCharCode(currentLetter + 13));
          }
        } else {
          decodedArr.push(num);
        }
        var sliced = str.slice(increaseNum + 1, str.length - 1);
        $("#last-second-inside p:nth-child(3)").text(decodedArr.join('') + sliced);
        // set duration of `setTimeout` here
        setTimeout(next, 100)
      };
    })).dequeue("descramble")
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="last-second-inside">
  <p>You probably now understand that how binary works and how simple it is.</p>
  <p>Now, I need you to think about that how you might display 8 in binary. After giving it a shot, you can click on the next paragraph to descramble it.</p>
  <p>Vg'f fvzcyr lbh jvyy whfg nqq nabgure pbyhza nsgre sbhe'f cynpr naq gung pbyhza jvyy unir gur cynpr inyhr bs rvtug'f.</p>
</div>

Upvotes: 1

Rick Hitchcock
Rick Hitchcock

Reputation: 35670

Instead of using map(), let descramble() work on only one letter at a time, based on the value of increaseNum.

After descramble() has run, use setTimeout() to call it again after an appropriate interval:

$("#last-second-inside p:nth-child(3)").one('click', function() {
  $(this).css('cursor', 'default');
  var str = "Vg'f fvzcyr lbh jvyy whfg nqq nabgure pbyhza nsgre sbhe'f cynpr naq gung pbyhza jvyy unir gur cynpr inyhr bs rvtug'f.";
  var strArr = str.split('');
  var decodedArr = [];
  var increaseNum = 0;  // changed from -1
  descramble();

  function descramble() {
    var num = str[increaseNum++],
        currentLetter = num.charCodeAt();

    if (currentLetter >= 65 && currentLetter <= 90 || currentLetter >= 97 && currentLetter <= 122) {
      if (currentLetter >= 78 && currentLetter <= 90 || currentLetter >= 110 && currentLetter >= 97) {
        decodedArr.push(String.fromCharCode(currentLetter - 13));
      } else {
        decodedArr.push(String.fromCharCode(currentLetter + 13));
      }
    } else {
      decodedArr.push(num);
    }
    var sliced = str.slice(increaseNum + 1, str.length - 1);
    $("#last-second-inside p:nth-child(3)").text(decodedArr.join('') + sliced);
    if(increaseNum < str.length) {
      setTimeout(descramble, 10);
    }
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="last-second-inside">
  <p>You probably now understand that how binary works and how simple it is.</p>
  <p>Now, I need you to think about that how you might display 8 in binary. After giving it a shot, you can click on the next paragraph to descramble it.</p>
  <p>Vg'f fvzcyr lbh jvyy whfg nqq nabgure pbyhza nsgre sbhe'f cynpr naq gung pbyhza jvyy unir gur cynpr inyhr bs rvtug'f.</p>
</div>

Upvotes: 1

mhodges
mhodges

Reputation: 11116

I believe you are going to have to do the mapping manually. You cannot use setTimeout or setInterval inside of an iterator like each, map, etc. and get the results you are expecting because setTimeout is non-blocking, so it returns immediately. You'll have to call a self-invoking function that converts 1 letter at a time and has break logic when you reach the end of the string like so: How do I add a delay in a JavaScript loop?

Upvotes: 0

Korgrue
Korgrue

Reputation: 3478

use setInterval, not setTimeout. setTimeout will only run once (after the timer expires). setInterval will keep firing at the interval you set until you escape out of the loop.

You can consider setTimeout as a single trigger countdown timer. setInterval can be viewed as a loop that triggers at the interval you set.

Upvotes: 0

Related Questions