Javascript - SetTimeout causes Browser to freeze - javascript

The problem I'm currently running into is the following:
I have a table containing of two rows. The first row contains the letters of a given word in alphabetical order. The second row is empty at the start. Every second, one letter from the first row shall be moved to the correct position. This works correctly for the first 5 letters, but then nothing happens anymore and after a short time, the browser freezes and I get a prompt, asking to stop the skript or to keep it running.
Here's my code
test.html:
<!DOCTYPE html>
<html>
<head>
<script src=".\test.js"></script>
</head>
<body>
<div onclick="m_show_letter_example()">
<table>
<tr>
<td><input id="example_01" name="example_alphabet_01" type="text" value="A"/></td>
<td><input id="example_02" name="example_alphabet_02" type="text" value="E"/></td>
<td><input id="example_03" name="example_alphabet_03" type="text" value="E"/></td>
<td><input id="example_04" name="example_alphabet_04" type="text" value="L"/></td>
<td><input id="example_05" name="example_alphabet_05" type="text" value="M"/></td>
<td><input id="example_06" name="example_alphabet_06" type="text" value="P"/></td>
<td><input id="example_07" name="example_alphabet_07" type="text" value="S"/></td>
<td><input id="example_08" name="example_alphabet_08" type="text" value="X"/></td>
</tr>
<tr>
<td><input id="example_solution_02" name="example_solution_02" type="text"/></td>
<td><input id="example_solution_08" name="example_solution_08" type="text"/></td>
<td><input id="example_solution_01" name="example_solution_01" type="text"/></td>
<td><input id="example_solution_05" name="example_solution_05" type="text"/></td>
<td><input id="example_solution_06" name="example_solution_06" type="text"/></td>
<td><input id="example_solution_04" name="example_solution_04" type="text"/></td>
<td><input id="example_solution_03" name="example_solution_03" type="text"/></td>
<td><input id="example_solution_07" name="example_solution_07" type="text"/></td>
</tr>
</table>
</div>
</body>
And the javascript file:
test.js
var timeout = null;
function m_show_letter_example()
{
timeout = setTimeout(function()
{
var inputs = document.getElementsByTagName('input');
var unplaced_letters = [];
for (var input_index = 0; input_index < inputs.length; ++input_index)
{
if (inputs[input_index].name.indexOf('example_alphabet_') == 0) {
unplaced_letters.push(inputs[input_index]);
}
}
var random_index = 0;
var field = document.getElementsByName('example_alphabet_0' + random_index);
while (document.getElementsByName('example_alphabet_0' + random_index).length == 0 )
{
random_index = Math.floor( (Math.random() * unplaced_letters.length) + 1);
}
var letter = document.getElementById('example_0' + random_index);
var solution = document.getElementById('example_solution_0' + random_index);
solution.value = letter.value;
letter.value = "";
letter.name = "used";
m_show_letter_example();
}, 1000);
}
I would be happy to hear any insights on why this is happening and how to solve this.
In case it matters, I have tested this in Firefox and Chrome.
Thanks in advance
Edit: added test.js

The issue is because of the random number selecting in while loop.
When there are 3 values this loop is going into infinite loop.
I have made few changes in script file and also add a data-index attribute to every example_alphabet_ input tag.
var timeout = null;
function m_show_letter_example()
{
timeout = setTimeout(function()
{
var unplaced_letters = document.querySelectorAll("input[name^='example_alphabet_']");
var unplaced_index = []
for (var input_index = 0; input_index < unplaced_letters.length; ++input_index)
{
unplaced_index.push(unplaced_letters[input_index].getAttribute('data-index'));
}
var random_index = 0;
var field = document.getElementsByName('example_alphabet_0' + random_index);
while (document.getElementsByName('example_alphabet_0' + random_index).length == 0 )
{
random_index = unplaced_index[Math.floor( (Math.random() * unplaced_index.length))];
}
var letter = document.getElementById('example_0' + random_index);
var solution = document.getElementById('example_solution_0' + random_index);
solution.value = letter.value;
letter.value = "";
letter.name = "used";
m_show_letter_example();
}, 1000);
}
Hope this helps you in resolving the problem.

the problem is right here:
while (document.getElementsByName('example_alphabet_0' + random_index).length == 0 )
{
random_index = Math.floor( (Math.random() * unplaced_letters.length) + 1);
}
when this condition is true
document.getElementsByName('example_alphabet_0' + random_index).length == 0
and the length returned is always 0 the while loop will run indefinitely as there is no condition to stop it. An unending while loop will always freeze your browser.

Related

Exclude certain rows while calculating the minimum value

I have the following table and I need to find the minimum value in that column.
In this case the value is 20.
However, I need to exclude the last 2 part names and use the rest of the values in the cell to calculate the minimum. In that case the minimum value should be 100.
Here is the code i have for calculating the minimum:
function getMin() {
var maximum = 0;
jQuery(".used").each(function() {
$used= jQuery(this).val();
var usedValue = $used.replace(/,/g, "");
value = parseFloat(usedValue);
maximum = (value > maximum) ? value : maximum;
});
var min = maximum;
jQuery(".used").each(function() {
$used = jQuery(this).val();
var usedValue = $used.replace(/,/g, "");
value = parseFloat(usedValue);
min = (value < min) ? value : min;
});
jQuery(".minimum").val(min);
}
<div><input type="text" class="minimum" name="minimum" id="minimum" value="" size="5" onchange="getMin();" readonly>cycles</div>
I couldn't find a way to exclude the last 2 values here. The number of rows can also differ and is not fixed so I need to exclude it based on those 2 string values. Any help is appreciated!! Thank you in advance!
Here is a quick and dirty solution. Loop through the parent object of each row, and ignore the value of used if the label (text) is one of those strings.
I also updated the minimum function to use the math.min on an array of values.
function getMin() {
let vals = [];
$(".row").each(function() {
if ($(this).find("label").html() != "Ignore") {
$used = $(this).find(".used").val();
var usedValue = $used.replace(/,/g, "");
vals.push(parseFloat(usedValue));
}
});
let min = Math.min(...vals);
$(".minimum").val(min);
}
getMin();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
<label>Ignore</label>
<input type="text" class="used" value=41>
</div>
<div class="row">
<label>Keep</label>
<input type="text" class="used" value=222>
</div>
<div class="row">
<label>Keep</label>
<input type="text" class="used" value=200>
</div>
<div><input type="text" class="minimum" name="minimum" id="minimum" value="" size="5" onchange="" readonly>cycles</div>
I would mark these different rows in HTML somehow, let's say with excluded class. Hardcoding the labels in JavaScript asks for trouble.
Here's an example, using excluded class for these two last <tr>:
const min = Math.min(...$(':not(.excluded) .used').map(function () {
return Number($(this).val());
}).get());
You could do it like this: Exclude in your each() function every <tr> that has a first column that contains any of the 2 strings you want to exclude:
function getMin() {
var maximum = 0;
jQuery(".used").each(function() {
$used = jQuery(this).val();
var usedValue = $used.replace(/,/g, "");
value = parseFloat(usedValue);
maximum = (value > maximum) ? value : maximum;
});
var min = maximum;
jQuery("tr").each(function() {
var check = jQuery(this).find("td:nth-child(1)").text();
if (!check.includes("Fan Blade") && !check.includes("Annulus Filler"))
{
$used = jQuery(this).val();
var usedValue = $used.replace(/,/g, "");
value = parseFloat(usedValue);
min = (value < min) ? value : min;
}
});
jQuery(".minimum").val(min);
}
getMin();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td></td>
<td></td>
<td><input class="used" value="100" /></td>
</tr>
<tr>
<td>Fan Blade (26 off)</td>
<td></td>
<td><input class="used" value="50" /></td>
</tr>
<tr>
<td>Annulus Filler (26 off)</td>
<td></td>
<td><input class="used" value="50" /></td>
</tr>
</table>
<div><input type="text" class="minimum" name="minimum" id="minimum" value="" size="5" onchange="getMin();" readonly>cycles</div>

Multiple countdown timers comparing a given time and current time?

Really struggling with this part for some reason.
I'm creating a timer I can use to keep track of bids. I want to be able to compare two times and have the difference (in minutes and seconds) shown in the countdown column. It should be comparing the bid start time and the time right now.
Perhaps when it reaches bid start it could also change to show how long until bid ends. Eventually I want to add background changes once it's getting close to the time, and perhaps the ablility to set alarms with a prompt window.
Here's the code I have so far:
HTML
<table>
<tr>
<td>Item Name</td>
<td><input id="itemNameField" placeholder="" type="text"></td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td>Time of Notice</td>
<td><input id="noticeField" type="time"></td>
</tr>
</table>
<input id="addButton" onclick="insRow()" type="button" value="Add Timer">
<div id="errorMessage"></div>
<hr>
<div id="marketTimerTableDiv">
<table border="1" id="marketTimerTable">
<tr>
<td></td>
<td>Item Name</td>
<td>Time of Notice</td>
<td>Bid Start</td>
<td>Bid End</td>
<td>Countdown</td>
<td></td>
</tr>
<tr>
<td></td>
<td>
<div id="itembox"></div>Example Item
</td>
<td>
<div id="noticebox"></div>12:52
</td>
<td>
<div id="bidstartbox"></div>13:02
</td>
<td>
<div id="bidendbox"></div>13:07
</td>
<td>
<div id="countdownbox"></div>
</td>
<td><input id="delbutton" onclick="deleteRow(this)" type="button" value="X"></td>
</tr>
</table>
</div>
JAVASCRIPT
function deleteRow(row) {
var i = row.parentNode.parentNode.rowIndex;
if (i == 1) {
console.log = "hi";
} else {
document.getElementById('marketTimerTable').deleteRow(i);
}
}
function insRow() {
if (itemNameField.value == "" || noticeField.value == "") {
var div = document.getElementById('errorMessage');
div.innerHTML = "*Please fill in the fields*";
div.style.color = 'red';
document.body.appendChild(div);
} else {
var div = document.getElementById('errorMessage');
div.innerHTML = "";
var x = document.getElementById('marketTimerTable');
var new_row = x.rows[1].cloneNode(true);
var len = x.rows.length;
var inp1 = new_row.cells[1].getElementsByTagName('div')[0];
inp1.id += len;
inp1.innerHTML = itemNameField.value;
itemNameField.value = "";
var inp2 = new_row.cells[2].getElementsByTagName('div')[0];
inp2.id += len;
inp2.innerHTML = noticeField.value;
noticeField.stepUp(10);
var inp3 = new_row.cells[3].getElementsByTagName('div')[0];
inp3.id += len;
inp3.innerHTML = noticeField.value;
noticeField.stepUp(5);
var inp4 = new_row.cells[4].getElementsByTagName('div')[0];
inp4.id += len;
inp4.innerHTML = noticeField.value;
var inp5 = new_row.cells[5].getElementsByTagName('div')[0];
inp5.id += len;
inp5.innerHTML = "";
noticeField.value = "";
x.appendChild(new_row);
}
}
I apologize in advance because my code is probably really messy and badly formatted. Here's a JSFIDDLE as well! Thanks :)
To calculate the difference between the current and given time, you can use setInterval
Example :
var noticeTime = noticeField.value.split(":");
const interval = setInterval(function(){
var currentDate = (new Date());
var diffInHours = currentDate.getHours() - noticeTime[0];
var diffInMinutes = currentDate.getMinutes() - noticeTime[1];
inp5.innerHTML = diffInHours + ":" + diffInMinutes;
if(diffInHours === 0 && diffInMinutes === 0) {
clearInterval(interval);
}
},1000)
I managed to do it with the help of the code from ProgXx.
I added the following code:
var noticeTime = noticeField.value.split(":");
var originalTime = noticeField.value.split(":");
const interval = setInterval(function(){
var currentDate = (new Date());
noticeTime[1] = originalTime[1] - currentDate.getMinutes() + 10;
noticeTime[1] = noticeTime[1] + (originalTime[0] * 60) - (currentDate.getHours() * 60);
Here's a JSFIDDLE of the finihsed code: http://jsfiddle.net/joefj8wb/

percentages when converting sterling to euro

Hi I am trying to convert Sterling to Euros. But I can't seem to get the percentages correct. I have tried it several ways without luck. The idea is to get 1% of the sterling price then multiply it by the conversion rate and add it to the sterling price to make the euro total, and then do the same with vat.
Hope someone can help, thanks!
Here is my code.
var input = document.querySelectorAll('input');
var conversionRate = input[0];
var sterling = input[1];
var vat = input[2];
var euro = input[3];
init();
function init() {
calculateKeyUp();
}
function calculateKeyUp() {
for (var i = 0; i < input.length; i++) {
input[i].addEventListener("keyup", function() {
//var totalLessVat = (sterling.value) + (conversionRate.value * (sterling.value / 100));
var sterling1Per = sterling.value / 100;
var convert = sterling1Per * conversionRate.value;
var totalLessVat = convert + sterling.value;
//var total = (totalLessVat) + (vat.value * (totalLessVat / 100));
var euro1Per = totalLessVat / 100;
var addVat = euro1Per * vat.value;
var total = addVat + totalLessVat;
euro.value = Math.floor(total);
});
}
}
<div id="calculator-form">
<table>
<tr>
<td>Conversion Rate: </td>
<td><input type="number" id="conversionRate"> %</td>
</tr>
<tr>
<td>Sterling Price: </td>
<td><input type="number" id="sterling"> £</td>
</tr>
<tr>
<td>Vat: </td>
<td><input type="number" id="vat"> %</td>
</tr>
<tr>
<td>Euro Price is </td>
<td><input type="number" id="euro" disabled> €</td>
</tr>
</table>
</div>
The .value of an input is going to be a String, so you will need to parse the number out of each input you are working with. If it's an int you can use:
var sterling1Per = parseInt(sterling.value, 10) / 100;
If it's a float, you can use:
var sterling1Per = parseFloat(sterling.value) / 100;
Anywhere that you use an input .value that needs to be a number needs to be parsed accordingly

Javascript - Insert code segments at multiple locations

What I like to do is: If any of the 3 optional fields is filled out, a chunk of code(row) will be inserted into the source code(table) and then the entire code will be outputted.
My issue right now is: If more than one of the fields is entered, only the last input is inserted. I need all of them inserted. I suspect that the "code =" statement needs to be changed/relocated but not sure how to go about it. I'm a beginner in javascript, so please keep your answers as basic as you can. Thank you!!
html:
<input id="input1" onChange="update()">
<input id="input2" onChange="update()">
<input id="input3" onChange="update()">
javascript:
var source = '<table><!--PlaceHolder1--><!--PlaceHolder2--><!--PlaceHolder3--></table>';
var insert = '<tr><td>InsertText</td></tr>';
function update(){
if(document.getElementById("input1").value != ""){
var x = document.getElementById("input1").value;
var y = insert.replace("InsertText", x );
code = source.replace("<!--PlaceHolder1-->", y );
}
if(document.getElementById("input2").value != ""){
var x = document.getElementById("input2").value;
var y = insert.replace("InsertText", x );
code = source.replace("<!--PlaceHolder2-->", y );
}
if(document.getElementById("input3").value != ""){
var x = document.getElementById("input3").value;
var y = insert.replace("InsertText", x );
code = source.replace("<!--PlaceHolder3-->", y );
}
}
document.write(code);
It looks like you're losing the result of the first replace, which is in the variable "code" because you're overwriting it with the contents of "source" on subsequent replaces.
Instead of this:
code = source.replace("<!--PlaceHolder2-->", y );
Try this:
code = code.replace("<!--PlaceHolder2-->", y );
And I think you'll get what you're expecting.
Part of the problem is that you're trying to do this with string replacement. You should be using proper DOM manipulation. This will also allow you to clean up your code a lot:
window.onload = function() {
function update(e) {
var target = e.target,
num = target.getAttribute("data-num"),
td = document.querySelectorAll("#theTable td")[num - 1];
td.textContent = target.value;
td.parentNode.style.display = "table-row";
}
for (var i = 1; i <= 3; i += 1) {
document.getElementById("input" + i).onchange = update;
}
}
#theTable tr {
display: none;
}
<input id="input1" data-num="1">
<input id="input2" data-num="2">
<input id="input3" data-num="3">
<table id="theTable">
<tr>
<td></td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td></td>
</tr>
</table>

Generating a random number in JavaScript and passing it to an HTML input tag

My script, stored as a separate js file:
function randomNumber(len) {
var randomNumber;
var n = '';
for(var count = 0; count < len; count++) {
randomNumber = Math.floor(Math.random() * 10);
n += randomNumber.toString();
}
return n;
}
var finalSequence = randomNumber(9);
document.write('<INPUT TYPE=TEXT NAME="ACCOUNT" VALUE='+finalSequence +' MAXLENGTH=16 SIZE=16>');
I have included this td tag in my html file:
<td align=left><FONT FACE="Arial,Helvetica"><script src="nexgen.js"></script>
Do you suggest that I write my script inside the html file itself?
I would like to display the generated random number using an input tag, such as that below. How do I do this?
<INPUT TYPE=TEXT NAME="ACCOUNT" VALUE= ??? MAXLENGTH=16 SIZE=16>
Update:
I am combining the JavaScript and html in one html file as follows. Please see if you can find any mistakes because the number generated is not being displayed on html page.
Javascript part:
function randomNumber(len) {
var randomNumber;
var n = '';
for(var count = 0; count < len; count++) {
randomNumber = Math.floor(Math.random() * 10);
n += randomNumber.toString();
}
document.getElementById("ACCOUNT").value = n;
return n;
}
HTML part:
<tr>
<td><FONT FACE="Arial,Helvetica" color="red"> Transaction ID: </font></td>
<td align=left>
<FONT FACE="Arial,Helvetica">
<script> randomNumber(9); </script>
<INPUT TYPE=TEXT NAME="ACCOUNT" ID="ACCOUNT" VALUE="" MAXLENGTH=16 SIZE=16 readonly>
</font>
</td>
</tr>
Assign an ID to your input element, then in your JavaScript, assign the generated value to that element.
function randomNumber(len) {
var randomNumber;
var n = '';
for (var count = 0; count < len; count++) {
randomNumber = Math.floor(Math.random() * 10);
n += randomNumber.toString();
}
return n;
}
document.getElementById("ACCOUNT").value = randomNumber(9);
<INPUT TYPE=TEXT NAME="ACCOUNT" ID="ACCOUNT" VALUE="" MAXLENGTH=16 SIZE=16>
Working jsFiddle.
BTW, if you want to generate a random number of a certain length, you can do it in much bigger chunks than one digit at a time, e.g.:
function longRandom(length) {
var n = '';
while (n.length < length) {
n += ('' + Math.random()).split('.')[1];
}
return n.substr(0, length);
}
console.log(longRandom(42)); // 134434793311713322660940870849409308530315
will do it in chunks of about 15 digits on each loop. :-)
A random number is generated using javascript and also passed in the input form tag in html using code similar to ones mentioned below.
Javascript :
function randomNumber(len) {
var randomNumber;
var n = '';
for(var count = 0; count < len; count++) {
randomNumber = Math.floor(Math.random() * 10);
n += randomNumber.toString();
}
return n;
}
window.onload = function() {
document.getElementById("ACCOUNT").value = randomNumber(9);
};
HTML part:
<INPUT TYPE=TEXT NAME="ACCOUNT" ID="ACCOUNT" VALUE="" MAXLENGTH=16 SIZE=16>
Something like this, but you can do that in different ways:
http://jsbin.com/hujefopa/1/edit
function rand(len){
return Math.floor(Math.random() * Math.pow(10, len));
}
function setRand(){
document.getElementById('rand').value = rand(9);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body onload="setRand()">
<input type="text" id="rand">
</body>
</html>
Please note that:
If your script is small, it's better to put it inside the page itself rather than importing a new file (new request to the server).
Using document.write is not recommended. See this question.
To update the value of html input you can use:
document.getElementById('id-of-your-input-element').value = newValue;
or using jQuery:
$('#id-of-your-input-element').val(newValue);
HTML PART
<tr>
<td><FONT FACE="Arial,Helvetica" color="red"> Transaction ID: </font></td>
<td align=left>
<FONT FACE="Arial,Helvetica">
<INPUT TYPE=TEXT NAME="ACCOUNT" ID="ACCOUNT" VALUE="" MAXLENGTH=16 SIZE=16
readonly>
</font>
</td>
</tr>
JavaScript Part
<script>
document.getElementById('ACCOUNT').value=Math.floor(Math.random() * 10);
</script>

Categories

Resources