JQuery - getting mixed up with variable scope in parameter functions - javascript

JSFiddle - SSCCE
function restoreTitle() {
for (var i = 0; i < 4; i++) {
clicks[i] = false;
letter = $('#title-wrapper p[index="' + i + '"]');
letter.css('cursor', "pointer");
}
animateTitle();
}
function animateTitle() {
for (var i = 0; i < 4; i++) {
letter = $('#title-wrapper p[index="' + i + '"]');
direction = i < 2 ? 1 : -1;
letter.css('right', 50 * direction + "%");
doAnimateLetter(i, letter, direction);
}
}
function doAnimateLetter(i, letter, direction) {
loop(function(){
var current = letter.css('right').replace("%", "");
var incoming = parseInt(current) - (5 * direction);
letter.css('right', incoming + "%");
var completed = incoming == 0;
if(completed) letter.fadeTo(animation_speed, 1);
return !completed;
});
}
function loop(run) {
if (run.apply()) requestAnimationFrame(function () {
loop(run);
});
}
What I would like to achieve is for the two left letters to fly in from the left and for the two right ones to fly in from the right. I can't find where I'm going wrong.

Related

How to stop Jquery function from running?

Newbie here. Probably because I'm already sleepy and can't find a solution. I'm trying to stop a function when I click on another button.
Here's the code so far:
When I click on a button (.start), it runs a function that messes up the text randomly without finish. But then, I want to click on button #stop and stop that specific function from running. I've tried toggles, preventDefault, event.stopPropagation(), setInterval, etc... None of them works. I've tried putting inside my function and outside as well.
Here's the current js code:
$(".start").click(function(){
var getTextNodesIn = function(el) {
// Look at all the page elements and returns the text nodes
return $(el)
.find(":not(iframe,script)")
.addBack()
.contents()
.filter(function() {
return this.nodeType == 3; // Text node types are type 3
});
};
// var textNodes = getTextNodesIn($("p, h1, h2, h3","*"));
var textNodes = getTextNodesIn($("p"));
function isLetter(char) {
return /^[\d]$/.test(char);
}
var wordsInTextNodes = [];
for (var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
var words = [];
var re = /\w+/g;
var match;
while ((match = re.exec(node.nodeValue)) != null) {
var word = match[0];
var position = match.index;
words.push({
length: word.length,
position: position
});
}
wordsInTextNodes[i] = words;
}
function messUpWords() {
for (var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
for (var j = 0; j < wordsInTextNodes[i].length; j++) {
// Only change a tenth of the words each round.
if (Math.random() > 1 / 10) {
continue;
}
var wordMeta = wordsInTextNodes[i][j];
var word = node.nodeValue.slice(
wordMeta.position,
wordMeta.position + wordMeta.length
);
var before = node.nodeValue.slice(0, wordMeta.position);
var after = node.nodeValue.slice(wordMeta.position + wordMeta.length);
node.nodeValue = before + messUpWord(word) + after;
}
}
}
function messUpWord(word) {
if (word.length < 3) {
return word;
}
return word[0] + messUpMessyPart(word.slice(1, -1)) + word[word.length - 1];
}
function messUpMessyPart(messyPart) {
if (messyPart.length < 2) {
return messyPart;
}
var a, b;
while (!(a < b)) {
a = getRandomInt(0, messyPart.length - 1);
b = getRandomInt(0, messyPart.length - 1);
}
return (
messyPart.slice(0, a) +
messyPart[b] +
messyPart.slice(a + 1, b) +
messyPart[a] +
messyPart.slice(b + 1)
);
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
setInterval(messUpWords, 50);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="controls pt-5">
<button class="start">Simulate</button>
<button id="stop">Stop</button>
</div>
<br>
<br>
<br>
<div>
<h1>Trying</h1>
<p>Friends who have dyslexia described to me how they experience reading. She <em>can</em> read, but it takes a lot of concentration, and the letters seems to "jump around".</p>
</div>
The function works pretty well. I'm just having a hard time making another button stop this function from running... Any help would be appreciated and I wish y'all a nice week.
You cannot stop a function from running because only one function can ever run at a time within the JavaScript runtime environment (single-threaded). When you click the button to try to stop the first function, what actually happens is that the first function finishes and then the click event associated with the button runs. And, by then, the first function has completed, so it's too late to stop it.
You can look into asynchronous operations, which run outside of the JavaScript runtime. In your case, using setInterval() to run a function repeatedly at regular intervals would probably be the best way to go. This would allow you to check between invocations to see if something else has occurred, which should stop the function from running at the next interval.
Now, you are using the interval timer, but you aren't setting up a reference to it, so you can't tell it to stop when you need it to. The solution is to associate a variable with the timer and then to call clearInterval() and pass it the timer reference as shown here:
let timer = null; // This will hold a reference to the timer so you can stop it later
$("#stop").on("click", function(){
clearInterval(timer); // Stop the timer
});
$(".start").click(function(){
var getTextNodesIn = function(el) {
// Look at all the page elements and returns the text nodes
return $(el).find(":not(iframe,script)")
.addBack()
.contents()
.filter(function() {
return this.nodeType == 3; // Text node types are type 3
});
};
// var textNodes = getTextNodesIn($("p, h1, h2, h3","*"));
var textNodes = getTextNodesIn($("p"));
function isLetter(char) {
return /^[\d]$/.test(char);
}
var wordsInTextNodes = [];
for (var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
var words = [];
var re = /\w+/g;
var match;
while ((match = re.exec(node.nodeValue)) != null) {
var word = match[0];
var position = match.index;
words.push({
length: word.length,
position: position
});
}
wordsInTextNodes[i] = words;
}
function messUpWords() {
for (var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
for (var j = 0; j < wordsInTextNodes[i].length; j++) {
// Only change a tenth of the words each round.
if (Math.random() > 1 / 10) {
continue;
}
var wordMeta = wordsInTextNodes[i][j];
var word = node.nodeValue.slice(
wordMeta.position,
wordMeta.position + wordMeta.length
);
var before = node.nodeValue.slice(0, wordMeta.position);
var after = node.nodeValue.slice(wordMeta.position + wordMeta.length);
node.nodeValue = before + messUpWord(word) + after;
}
}
}
function messUpWord(word) {
if (word.length < 3) {
return word;
}
return word[0] + messUpMessyPart(word.slice(1, -1)) + word[word.length - 1];
}
function messUpMessyPart(messyPart) {
if (messyPart.length < 2) {
return messyPart;
}
var a, b;
while (!(a < b)) {
a = getRandomInt(0, messyPart.length - 1);
b = getRandomInt(0, messyPart.length - 1);
}
return (
messyPart.slice(0, a) +
messyPart[b] +
messyPart.slice(a + 1, b) +
messyPart[a] +
messyPart.slice(b + 1)
);
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
timer = setInterval(messUpWords, 50); // Set interval reference to variable
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="controls pt-5">
<button class="start">Simulate</button>
<button id="stop">Stop</button>
</div>
<br>
<br>
<br>
<div>
<h1>Trying</h1>
<p>Friends who have dyslexia described to me how they experience reading. She <em>can</em> read, but it takes a lot of concentration, and the letters seems to "jump around".</p>
</div>
You can check at the top of the messUpWords function to see if the stop button has been clicked. If it has, you can clear the interval, reset the the stop button flag, and escape the routine.
var stopBtnClicked = false;
var stopBtn = document.getElementById("stop");
stopBtn.addEventListener("click", function() {
stopBtnClicked = true;
}, false);
$(".start").click(function() {
var getTextNodesIn = function(el) {
// Look at all the page elements and returns the text nodes
return $(el)
.find(":not(iframe,script)")
.addBack()
.contents()
.filter(function() {
return this.nodeType == 3; // Text node types are type 3
});
};
// var textNodes = getTextNodesIn($("p, h1, h2, h3","*"));
var textNodes = getTextNodesIn($("p"));
function isLetter(char) {
return /^[\d]$/.test(char);
}
var wordsInTextNodes = [];
for (var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
var words = [];
var re = /\w+/g;
var match;
while ((match = re.exec(node.nodeValue)) != null) {
var word = match[0];
var position = match.index;
words.push({
length: word.length,
position: position
});
}
wordsInTextNodes[i] = words;
}
function messUpWords() {
if (stopBtnClicked) {
clearInterval(jumbleTimer);
stopBtnClicked = false;
return;
}
for (var i = 0; i < textNodes.length; i++) {
var node = textNodes[i];
for (var j = 0; j < wordsInTextNodes[i].length; j++) {
// Only change a tenth of the words each round.
if (Math.random() > 1 / 10) {
continue;
}
var wordMeta = wordsInTextNodes[i][j];
var word = node.nodeValue.slice(
wordMeta.position,
wordMeta.position + wordMeta.length
);
var before = node.nodeValue.slice(0, wordMeta.position);
var after = node.nodeValue.slice(wordMeta.position + wordMeta.length);
node.nodeValue = before + messUpWord(word) + after;
}
}
}
function messUpWord(word) {
if (word.length < 3) {
return word;
}
return word[0] + messUpMessyPart(word.slice(1, -1)) + word[word.length - 1];
}
function messUpMessyPart(messyPart) {
if (messyPart.length < 2) {
return messyPart;
}
var a, b;
while (!(a < b)) {
a = getRandomInt(0, messyPart.length - 1);
b = getRandomInt(0, messyPart.length - 1);
}
return (
messyPart.slice(0, a) +
messyPart[b] +
messyPart.slice(a + 1, b) +
messyPart[a] +
messyPart.slice(b + 1)
);
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
var jumbleTimer = setInterval(messUpWords, 50);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="controls pt-5">
<button class="start">Simulate</button>
<button id="stop">Stop</button>
</div>
<br>
<br>
<br>
<div>
<h1>Trying</h1>
<p>Friends who have dyslexia described to me how they experience reading. She <em>can</em> read, but it takes a lot of concentration, and the letters seems to "jump around".</p>
</div>

Recursion prevents function from being clicked more times in a row

I have created a simple script using recursion, to change the position of images.
It loop throught them and adjust their position , the script is relative easy code :
var img = document.getElementsByClassName("container")[0];
var X = 0;
var Y = 0;
var check;
function all() {
var decko = img.children;
for (var i = 0; i < decko.length; i++) {
if (i !== 0 && i % 3 === 0) {
X = 0;
Y++;
}
decko[i].style.transform = "translate3d(" + X * 100 + "px," + Y * 100 + "px,0)";
X++;
}
X = 0;
Y = 0;
check = false;
}
all()
window.onclick = function() {
pushIt(img.length, img.children, 0, 0)
}
function pushIt(max, target, index, count) {
if (count == max) {
return;
}
var tmp = target[index];
var matrix =window.getComputedStyle(tmp).getPropertyValue("transform");
var translate_left=matrix.split(",")[4];
var translate_top=matrix.split(",")[5].split(")")[0]-100;
tmp.style.transform = "translate3d(" + translate_left + "px," + translate_top + "px,0)";
setTimeout(function(){
pushIt(max, target, index + 1, count + 1);
},150)
}
Here you can see how it works. The problem is when there are a lot of images.
When i click which invokes the function , it loops throught all images ( 30 + in my case ). If i click two times in a sec , it will loop throught the all images , and THEN it will execute the function 2 nd time which is in my case unwanted behavior ( looks laggy ). Is there any way to prevent this behavior? I have chosen recursion , bcs it seems like easiest choice for this.
You had a couple if issues with your JavaScript that were throwing some errors, namely max was undefined in your function. I got this working HERE
var img = document.getElementsByClassName("container")[0];
var decko = img.children;
var X = 0;
var Y = 0;
var check;
var running = false;
function all() {
for (var i = 0; i < decko.length; i++) {
if (i !== 0 && i % 3 === 0) {
X = 0;
Y++;
}
decko[i].style.transform = "translate3d(" + X * 100 + "px," + Y * 100 + "px,0)";
X++;
}
X = 0;
Y = 0;
check = false;
}
all()
window.onclick = function () {
if (!running) {
running = true;
pushIt(decko.length, img.children, 0, 0);
}
}
var pushIt = function (max, target, index, count) {
if (count == max) {
running = false;
return;
}
var tmp = target[index];
var matrix = window.getComputedStyle(tmp).getPropertyValue("transform");
var translate_left = matrix.split(",")[4];
var translate_top = matrix.split(",")[5].split(")")[0] - 100;
tmp.style.transform = "translate3d(" + translate_left + "px," + translate_top + "px,0)";
setTimeout(function () {
console.log(running);
pushIt(max, target, index + 1, count + 1);
}, 150)
}

How to display a div with random ID without repeating it using jQuery?

I have a function to select a random number from 0 to 45 and then I show the div with the specific ID. It's working fine but it repeats a number.
Can anyone advise so it won't repeat numbers?
I call the function onclick like this
$(".skip").click(function () {
scared++;
$("#counter").html("My current count is: " + dared);
var d = 50;
/*$(".question").addClass("hideMe");
$(this).parents("div").next("div").removeClass("hideMe");*/
var r = Math.round(Math.random() * 44) + 1;
var newquestion = "q" + r;
$('.active').removeClass("active");
$("#" + newquestion).addClass("active");
if (scared > 44) {
$('.main').fadeOut('fast');
$('.logo').switchClass("logo", "share");
$('.progress').css("display", "none");
$('.share-game').css("display", "block");
$('.hero').css("right", "-240px");
$('#score-total').html(score + '');
} else {
}
$('.red-line').append('<div id="children' + (d++) + '" class="red"></div>');
return false;
});
You can see what i did.
var usedNumbers = [];
var randomNumbers = [];
$(function() {
//Getting 20 random numbers
for (i = 0; i < 20; i++) {
randomNumbers.push(getRandomNumber());
}
console.log(randomNumbers);
function getRandomNumber() {
var hasInArray = true;
do {
var r = Math.round(Math.random() * 44) + 1;
if (usedNumbers.indexOf(r) === -1) {
usedNumbers.push(r);
hasInArray = false;
return r;
}
} while (hasInArray === true);
}
});
Warning to not set the numbers of randomnumbers more then what you want to get, because that will cause an infinite loop!
Use an array to capture the used numbers and then check that array on each click, generating a new number if that one is found. It resets back to an empty array when it is full.
var savedNumbers = [];
function getRandom() {
if (savedNumbers.length === 45) {
savedNumbers = [];
}
var r = Math.round(Math.random() * 44) + 1;
if (savedNumbers.indexOf(r) > -1) {
getRandom();
} else {
savedNumbers.push(r);
return r;
}
}
DEMO

How to submit the value of an input field?

I have a math game that works partially. What I need to have happen is to take the values of the divs (one is x and the other is y), type in the answer of those two multiplied, be able to submit it and refresh to solve another.
Any help would be much appreciated!
http://jsfiddle.net/justinw001/Mttw6/11/
<script type="text/javascript">
function myFunction() {
score = 0;
var number = document.getElementById('inputElement').value;
questionAmount = number;
for(i = 0; i < questionAmount; i++) {
var x = Math.floor(Math.random() * 13);
var y = Math.floor(Math.random() * 13);
$('#input1').text(x);
$('#input2').text(y);
<!-- question = prompt('What is ' + x + ' * ' + y + ' = ?'); -->
question = document.getElementById('answer').value;
if(question == null || isNaN(question)) {
break;
}
if(question == x * y) {
score++;
}
}
alert('You got ' + score + ' out of ' + questionAmount + ' correct.');
}
</script>
Try to bind the process with your buttons. Clicking the left button, produce the questions.
And Clicking the right one, verify the answer.
Demo: Fiddle
var score = 0;
var questions = [];
// Generate questions
$('#gen').click(function () {
score = 0;
questions = [];
var questionAmount = parseInt($('#inputElement').val(), 10);
for (var i = 0; i < questionAmount; i++) {
var q = {
x: Math.floor(Math.random() * 13),
y: Math.floor(Math.random() * 13)
};
questions.push(q);
}
nextQuest(questions.pop());
});
// Verify the answer
$('#sub').click(function () {
var ans, x, y;
if (questions.length >= 0) {
ans = parseInt($('#answer').val(), 10);
x = parseInt($('#input1').text(), 10);
y = parseInt($('#input2').text(), 10);
if (ans === x * y) {
score++;
nextQuest(questions.pop());
} else {
alert('err');
}
}
});
var nextQuest = function (q) {
if (q) {
$('#input1').text(q.x);
$('#input2').text(q.y);
$('#answer').val('');
$('#inputElement').val(questions.length);
} else {
$('#input1, #input2').text('');
$('#answer, #inputElement').val('');
alert(score);
}
};

javascript function for calculating

I meet a trouble with a function. actually I need to make this function to perform a calculation on some text fields. When I worked on a single line no problems. But recently, someone asked to make a table with multiple lines (one line can be added dynamically) so, I do the following function so that it can not only duplicate line but id change all the fields concerned, so I add class to these fields. therefore I proceed as follows:
function clone(line) {
newLine = line.cloneNode(true);
line.parentNode.appendChild(newLine);
var tab = document.getElementsByClassName('libelle_debours')
var i = -1;
while (tab[++i]) {
tab[i].setAttribute("id", "_" + i);
};
var cab = document.getElementsByClassName('ht_no_tva')
var j = -1;
while (cab[++j]) {
cab[j].setAttribute("id", "_" + j);
};
var dab = document.getElementsByClassName('ht_tva')
var k = -1;
while (dab[++k]) {
dab[k].setAttribute("id", "_" + k);
};
var eab = document.getElementsByClassName('taux')
var l = -1;
while (eab[++l]) {
eab[l].setAttribute("id", "_" + l);
};
var fab = document.getElementsByClassName('tva')
var m = -1;
while (fab[++m]) {
fab[m].setAttribute("id", "_" + m);
};
}
function delRow() {
var current = window.event.srcElement;
//here we will delete the line
while ((current = current.parentElement) && current.tagName != "TR");
current.parentElement.removeChild(current);
}
The problem in fact is the second function that is used to make the calculation:
function calcdebours() {
var taux = document.getElementById('debours_taux_tva').value;
var ht_no_tva = document.getElementById('debours_montant_ht_no_tva').value;
var ht_tva = document.getElementById('debours_montant_ht_tva').value;
var tva = Math.round((((ht_tva) * (taux)) / 100) * 100) / 100;;
if (taux == '') {
taux = 0;
}
if (ht_no_tva == '') {
ht_no_tva = 0;
}
if (ht_tva == '') {
ht_tva = 0;
}
document.getElementById('debours_montant_tva').value = tva;
document.getElementById('debours_montant_ttc').value = (tva) + parseFloat(ht_tva) + parseFloat(ht_no_tva)
}
function
montant_debours() {
var ttc = document.getElementById('debours_montant_ttc').value;
var ttc2 = document.getElementById('debours_montant_ttc2').value;
if (ttc == '') {
var ttc = 0;
} else {
var ttc = document.getElementById('debours_montant_ttc').value;
}
if (ttc2 == '') {
var ttc2 = 0;
} else {
var ttc2 = document.getElementById('debours_montant_ttc2').value;
}
tx = parseFloat(ttc) + parseFloat(ttc2);
document.getElementById('ttc_cheque').value = Math.round(tx * 100) / 100;
}
As Id are not the same, do I have to create as many functions
there are lines?
Is it possible to fit a single function to process each line?
If so can you tell me how?
If I'm not mistaken you can use for loop and append increment to the end of element's id. Like this:
trs = document.getElementById('container Id').getElementsByTagName('tr');
For (var i = 1, i <= trs.length; i++)
{
var el = document.getElementById('debours_montant_ttc' + i);
}

Categories

Resources