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

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

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>

Grand Total showing NaN Javascript/Jquery

Iam working on an application, in the Grand Total field, its showing the sum of all the margin fields totals. But when the page loads its showing NaN in the total field. How can i show the existing total to show up in the Grand Total field?
This is my script.
demo
js
function getIndexedElement(item, index) {
if (item.length) {
if (index < item.length) {
return item[index];
} else {
return false;
}
} else {
if (index === 0) {
return item;
}
}
return false;
}
function isNum(value) {
return 123;
}
function calcTotals() {
var grandTotal = 0;
var margin_total = 0;
var total_inr1 = 0;
var i = 0;
while (getIndexedElement(document.forms['cart'].elements['add_percentage[]'], i)) {
add_percentageObj = getIndexedElement(document.forms['cart'].elements['add_percentage[]'], i);
addon_valueObj = getIndexedElement(document.forms['cart'].elements['addon_value[]'], i);
total_inr_valueObj = getIndexedElement(document.forms['cart'].elements['total_inr[]'], i);
totalObj = getIndexedElement(document.forms['cart'].elements['add_value[]'], i);
priceunitObj = getIndexedElement(document.forms['cart'].elements['price_unit[]'], i);
qtyObj = getIndexedElement(document.forms['cart'].elements['qty[]'], i);
marginObj = getIndexedElement(document.forms['cart'].elements['margin_for[]'], i);
if (isNaN(add_percentageObj.value)) {
add_percentageObj = '';
}
if (isNaN(addon_valueObj.value)) {
addon_valueObj = '';
}
if (add_percentageObj.value != 0) {
totalObj.value = (((total_inr_valueObj.value * 1) * add_percentageObj.value / 100) + total_inr_valueObj.value * 1).toFixed(3);
grandTotal = grandTotal + parseFloat(totalObj.value);
marginObj.value = ((totalObj.value * 1) - (total_inr_valueObj.value * 1)).toFixed(3);
margin_total = ((margin_total * 1) + marginObj.value * 1);
//total_inr1 = total_inr1 + parseFloat(total_inr_valueObj.value);
//c.value=Math.round((b.value/100) *a.value ).toFixed(2);
} else if (addon_valueObj.value != 0) {
totalObj.value = ((addon_valueObj.value * 1) + total_inr_valueObj.value * 1).toFixed(3);
grandTotal = grandTotal + parseFloat(totalObj.value);
marginObj.value = ((totalObj.value * 1) - (total_inr_valueObj.value * 1)).toFixed(3);
margin_total = ((margin_total * 1) + marginObj.value * 1);
//total_inr1 = total_inr1 + parseFloat(total_inr_valueObj.value);
} else {
totalObj.value = ((addon_valueObj.value * 1) + total_inr_valueObj.value * 1).toFixed(3);
grandTotal = grandTotal + parseFloat(totalObj.value);
marginObj.value = ((totalObj.value * 1) - (total_inr_valueObj.value * 1)).toFixed(3);
margin_total = ((margin_total * 1) + marginObj.value * 1);
//total_inr1 = total_inr1 + parseFloat(total_inr_valueObj.value);
}
i++;
}
//document.getElementById('grand_total').value = grandTotal.toFixed(3);
//document.getElementById('margin_total').value = margin_total.toFixed(3);
//document.getElementById('total_inr1').value = total_inr1.toFixed(3);
//document.getElementById('margin_for').value = margin_for;
marginTotal();
return;
}
function marginTotal() {
var x = $('[name="gt[]"]:checked').length;
if (x != 0) return;
var sum = 0;
$('input[name="margin_for[]"]').each(function () {
sum += +this.value;
});
$("#total12").val(sum);
}
$(function () {
$("input[type='checkbox'").on("change", function () {
recalcTotal();
}).change();
function recalcTotal() {
var total12 = 0;
var checkedinput = $("input:checked");
var targetcheckboxes = checkedinput.length ? checkedinput : $("input:checkbox");
targetcheckboxes.each(function () {
total12 += parseFloat($(this).next("input").val(), 10) * 1;
});
$("#total12").val(total12.toFixed(3));
}
});
$(window).load(function () {
$(document).ready(function () {
$("select").on('change', function () {
var dept_number = $(this).val();
var price = $(this).find(':selected').data('price');
var selected = $(this).find('option:selected').text();
if (selected == "INR") {
$(this).closest('table').find('.total1').val($(this).closest('table').find('.total').val());
} else {
$(this).closest('table').find('.total1').val((($(this).closest('table').find('.total').val() * price) / $(this).closest('table').find('.inrvalue').val()).toFixed(3));
}
$(this).closest('table').find('.price_unit').val(($(this).closest('table').find('.total1').val() / $(this).closest('table').find('.qty').val()).toFixed(3));
});
});
}); //]]>
In the fiddle you can see the last field, that is margin field. And extreme down you can see the Grand Total. Page Load its showing NaN..
you simply need to check input value next to checkbox whether its isNaN() or notDEMO There are many bugs like if you enter Text in Total colum you get NaN in textbox beside checkbox as well in Grandtotal since your updating it after change in input you need to validate the textbox on change
targetcheckboxes.each(function () {
var temp=$(this).next("input").val();
if(temp){
total12 += parseFloat(temp, 10) * 1;
}
});
$("#total12").val(total12.toFixed(3));
UPDATED ANSWER
So I was wrong, after some more testing its just that your first 3 readonly checkboxes don't have value=0.000 as an attribute.
As they are text inputs, javascript doesn't automatically assume that an empty input is equal to 0.
just add value=0.000 to the first three checkboxes
INCORRECT OLD ANSWER
In your targetcheckboxes.each() loop, your expression:
total12 += parseFloat($(this).next("input").val(), 10) * 1;
is causing the problem.
next("input") will match any type of input including text inputs. somewhere along the line you are concatenating a string to your total12 variable and hence the final value of total12 can not be parsed to a float.
I think you should use
parseInt(yourvalue);
parseFloat(yourvalue).toFixed(2);
whenever you are calculating something using js

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);
}
};

JQuery - getting mixed up with variable scope in parameter functions

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.

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