Reputation: 1179
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
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
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
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
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