I'm making an array that will look like this var qwe = [[a,b],[c],[d]] with the purpose of a and b being the identifiers.
a - d are coming from reading the DOM. My current JS is doing what I want it to but I want to combine the similar arrays by their identifiers. Running the below code will give me
qwe =[
[100,200],[3],[2],
[200, 300],[12],[4],
[100,200],[2],[6]
]
but I want the final array to add the similar arrays by their identifiers so it will end up looking like (based on previous example)
qwe =[
[100,200],[5],[8],
[200, 300],[12],[4]
]
HTML
<table name="tab" id="tab">
<tr>
<th>ID</th>
<th>Location</th>
<th>Value</th>
<th>Other</th>
</tr>
<tr>
<td><input name="itinValue" value="100"></td>
<td><input name="location" value="200"></td>
<td><input name="num" value='3'></td>
<td><input name="other" value='2'></td>
</tr>
<tr>
<td><input name="itinValue" value="200"></td>
<td><input name="location" value="300"></td>
<td><input name="num" value='12'></td>
<td><input name="other" value='4'></td>
</tr>
<tr>
<td><input name="itinValue" value="100"></td>
<td><input name="location" value="200"></td>
<td><input name="num" value='2'></td>
<td><input name="other" value='6'></td>
</tr>
</table>
JS
var table = document.querySelectorAll('[name="itinValue"]');
var qwe = [];
for(var i = 0; i < table.length; i++) {
var a = document.getElementsByName('itinValue')[i].value;
var b = document.getElementsByName('location')[i].value;
var c = document.getElementsByName('num')[i].value;
var d = document.getElementsByName('other')[i].value;
var x = [[a,b],[c],[d]];
//Compare,find,add here
//if identifiers do not exist
qwe.push(x);
}
This is a fiddle to my example that also correctly outputs the html too https://jsfiddle.net/3oge7wxg/125/
It looks like you want something called an associative array, "dict" in python, a key/value pairing, with the keys being your [a,b] part and the values your [c,d] parts.
You can emulate this in JavaScript through objects.
Further reading is here:
JavaScript Associative Arrays Demystified
JavaScript Basics: How to create a Dictionary with Key/Value pairs
I would use objects, just create a composite key:
var table = document.querySelectorAll('[name="itinValue"]');
var qwe = {};
for(var i = 0; i < table.length; i++) {
var a = document.getElementsByName('itinValue')[i].value;
var b = document.getElementsByName('location')[i].value;
var c = new Number(document.getElementsByName('num')[i].value);
var d = new Number(document.getElementsByName('other')[i].value);
var key = a + "_" + b;
previousValue = qwe[key];
qwe[key] = previousValue ? [previousValue[0] + c, previousValue[1] + d] : [c, d];
}
You can convert to your desired array like so:
Object.keys(qwe).map(key => [key.split("_")].concat(qwe[key]));
https://jsfiddle.net/3oge7wxg/161/
Edit: Number constructors; Added fiddle
There are key facts I am taking note of in your question:
you are looping an array of data.
you are storing data based on a key which is a tuple.
values where key is a match is an addition option.
a,b,c,d are all ints,so if these are strings, you would need to run parseint() if they are strings. This can be done by checking if it is currently type is a string, and if so, convert it.
Since it is a tuple and those are not implmented in javascript, you can do something like this.
var m = {};
var table = document.querySelectorAll('[name="itinValue"]');
for(var i = 0; i < table.length; i++) {
var a = +document.getElementsByName('itinValue')[i].value;
var b = +document.getElementsByName('location')[i].value;
var c = +document.getElementsByName('num')[i].value;
var d = +document.getElementsByName('other')[i].value;
var key = a.toString() + "-" + b.toString();
//creates key = "100-200"
if (m[key]){
m[key] = [m[key][0] + c, m[key][1] + d]
}else{
m[key] = [c,d]
}
}
in the end, your map will now have unique keys and a map that looks like:
{
"100-200": [5,8],
"200-300": [12,4]
}
and if for whatever reason, you need to break up they keys later, you just split on the key. map.keys[index].split("-")
I think this is clean, but if you want to go a bit more, you could turn it into a class.
You then store the information in qwe. If you need to, you can easily convert that from a map to a list, but it depends on your desired implementation goal. The key difference generally is whether or not you wish to maintain order. qwe is populated only with this information, and given your comment based on this being your implementation not the best one, it gives me enough insight to believe that order isnt really as important as preservation of they key data elements, this key/tuple, and 2 values.
If you know the amount of fields per row, here is an alternate way of retrieving your array.
var qwe = {};
var els = document.querySelectorAll('table#tab input');
for (i=0; i<els.length; i+=4) {
var indexer = i < 4 ? 0 : i;
var row = {
a: [
parseInt(els[indexer].value)
, parseInt(els[indexer+1].value)
]
, c: parseInt(els[indexer+2].value)
, d: parseInt(els[indexer+3].value)
};
row.key = row.a.join('_');
if (qwe[row.key]) {
qwe[row.key][1][0]+=row.c;
qwe[row.key][2][0]+=row.d;
} else {
qwe[row.key] = [row.a, [row.c], [row.d]];
}
}
console.log( Object.values(qwe) );
You could try to find the item for updating and if not push the new array.
var table = document.querySelectorAll('[name="itinValue"]'),
qwe = [],
a, b, c, d, i,
item;
for (i = 0; i < table.length; i++) {
a = +document.getElementsByName('itinValue')[i].value;
b = +document.getElementsByName('location')[i].value;
c = +document.getElementsByName('num')[i].value;
d = +document.getElementsByName('other')[i].value;
item = qwe.find(([[l, r]]) => l === a && r === b);
if (item) {
item[1][0] += c;
item[2][0] += d;
} else {
qwe.push([[a, b], [c], [d]]);
}
}
console.log(qwe);
<table name="tab" id="tab">
<tr>
<th>ID</th>
<th>Location</th>
<th>Value</th>
<th>Other</th>
</tr>
<tr>
<td><input name="itinValue" value="100"></td>
<td><input name="location" value="200"></td>
<td><input name="num" value='3'></td>
<td><input name="other" value='2'></td>
</tr>
<tr>
<td><input name="itinValue" value="200"></td>
<td><input name="location" value="300"></td>
<td><input name="num" value='12'></td>
<td><input name="other" value='4'></td>
</tr>
<tr>
<td><input name="itinValue" value="100"></td>
<td><input name="location" value="200"></td>
<td><input name="num" value='2'></td>
<td><input name="other" value='6'></td>
</tr>
</table>
Version with Map.
var table = document.querySelectorAll('[name="itinValue"]'),
qwe = [],
a, b, c, d, i,
item
map = new Map;
for (i = 0; i < table.length; i++) {
a = +document.getElementsByName('itinValue')[i].value;
b = +document.getElementsByName('location')[i].value;
c = +document.getElementsByName('num')[i].value;
d = +document.getElementsByName('other')[i].value;
item = map.get([a, b].join('|'));
if (item) {
item[1][0] += c;
item[2][0] += d;
} else {
item = [[a, b], [c], [d]]
map.set([a, b].join('|'), item);
qwe.push(item);
}
}
console.log(qwe);
<table name="tab" id="tab">
<tr>
<th>ID</th>
<th>Location</th>
<th>Value</th>
<th>Other</th>
</tr>
<tr>
<td><input name="itinValue" value="100"></td>
<td><input name="location" value="200"></td>
<td><input name="num" value='3'></td>
<td><input name="other" value='2'></td>
</tr>
<tr>
<td><input name="itinValue" value="200"></td>
<td><input name="location" value="300"></td>
<td><input name="num" value='12'></td>
<td><input name="other" value='4'></td>
</tr>
<tr>
<td><input name="itinValue" value="100"></td>
<td><input name="location" value="200"></td>
<td><input name="num" value='2'></td>
<td><input name="other" value='6'></td>
</tr>
</table>
Related
<td><input size="12" type="text" name="invoice[promcode][]" /></td>
<td><input size="12" onchange='bitExtention(0)' id="itemname0" type="text" name="invoice[itemname][]"/></td>
<td><input type="number" name="invoice[basecode][]"/></td>
<td><input size="12" type="text" name="invoice[mm][]"/></td>
<td><input onchange='bitExtention(0)' type="number" id="posotita0" name="invoice[quantity][]"/></td>
<td><input onchange='bitExtention(0)' type="number" id="timi0" name="invoice[price][]" step="0.01"/></td>
<td><input onchange='bitExtention(0)' type="number" id="discount0" name="invoice[discount][]" step="0.01"/></td>
<td><input onchange='bitExtention(0)' type="number" id="sum0" name="invoice[sum][]" step="0.01"/></td>
<td><input onchange='bitExtention(0)' type="number" id="foros0" name="invoice[tax][]" step="0.01"/></td>
i want to put a default value for each var like
var timi = document.getElementById("timi"+x.toString()).defaultValue = 50;
this seams to work but when i run the program i change the value to 100 but var timi dont get updated and stuck to 50
function bitExtention(x)
{
var itemname = document.getElementById("itemname"+x.toString()).value;
var test = JSON.parse('<%= raw Item.select('itemName','promCode','baseCode','monadaMe','price','fpa').collect { |p| [p.itemName, p.promCode, p.baseCode, p.monadaMe, p.price, p.fpa] }.join("\n").gsub("\n", " ").split(" ")%>');
var dokimi = test.indexOf(itemname);
var maura = test[dokimi+4];
var posotita = document.getElementById("posotita"+x.toString()).value;
var timi = document.getElementById("timi"+x.toString()).defaultValue = 50;
var sum= document.getElementById("sum"+x.toString()).value;
var fpa= document.getElementById("foros"+x.toString()).value;
var discount= document.getElementById("discount"+x.toString()).value /100;
var total = timi - (timi * discount);
var total_foros = timi*fpa/100;
sum = total * posotita + total_foros
document.getElementById("sum"+x.toString()).value = sum;
}
i just notices tha the 0 || 50 works but it's no visibale at html table
fixed while puting this at the bottom of the code document.getElementById("timi"+x.toString()).value = timi; looks wrong but works for now
You can do
let myVar = document.getElementById(...).value || "default value";
Javascript default parameter
Mozila mdn firefox for default parameter
I am working on a Script for sorting boxes.
Here my problem.
In the code:
Size_XS = document.getElementById('Size_XS'+i).value*1;
seems to work without any problem.
While this one:
document.getElementById('Size_XS'+i).value = Size_XS;
will give me the error message: document.getElementById(...) is null or not an object.
if I change to:
document.getElementById('Size_XS1').value = Size_XS;
It all works, but then I cannot loop the file later and why does it work with i above?
My script below:
function calcbox(){
var count = document.getElementById('count').value*1;
count = count+1;
var box_num = 0;
var header = "<table style='border:#000 1px solid; background-color:#fff;'><tr><td width='25'><b>Box</b></td><td width='200'><b>Item name</b></td><td width='100'><b>Sizes</b></td><td width='250'><b>Pcs</b></td></tr>";
var output = header+document.getElementById('output').innerHTML;
var total_qty;
var box_qty;
var item_name;
var Size_XS=0;
var Size_S=0;
var Size_M=0;
var Size_L=0;
/*for(var i=1;i<count;i++){*/
var i=1;
total_qty = document.getElementById('total_qty'+i).value*1;
box_qty = document.getElementById('box_qty'+i).value*1;
item_name = document.getElementById('item_name'+i).value;
Size_XS = document.getElementById('Size_XS'+i).value*1;
Size_S = document.getElementById('Size_S'+i).value*1;
Size_M = document.getElementById('Size_M'+i).value*1;
Size_L = document.getElementById('Size_L'+i).value*1;
//Packing whole boxes
if(Size_XS>=box_qty){
var Box_count = parseInt(Size_XS/box_qty);
for(var i=1;i<=Box_count;i++){
box_num = box_num+1;
output = output+"<tr><td>"+box_num+"</td><td>"+item_name+"</td><td>S</td><td>"+box_qty+"</td></tr>";
}
Size_XS = Size_XS-(box_qty*Box_count);
alert(Size_XS);
document.getElementById('Size_XS'+i).value = Size_XS;
}
if(Size_S>=box_qty){
var Box_count = parseInt(Size_S/box_qty);
for(var i=1;i<=Box_count;i++){
box_num = box_num+1;
output = output+"<tr><td>"+box_num+"</td><td>"+item_name+"</td><td>S</td><td>"+box_qty+"</td></tr>";
}
Size_S = Size_S-(box_qty*Box_count);
document.getElementById('Size_S'+i).value = Size_S;
}
if(Size_M>=box_qty){
var Box_count = parseInt(Size_M/box_qty);
for(var i=1;i<=Box_count;i++){
box_num = box_num+1;
output = output+"<tr><td>"+box_num+"</td><td>"+item_name+"</td><td>M</td><td>"+box_qty+"</td></tr>";
}
Size_M = Size_M-(box_qty*Box_count);
document.getElementById('Size_M'+i).value = Size_M;
}
if(Size_L>=box_qty){
var Box_count = parseInt(Size_L/box_qty);
for(var i=1;i<=Box_count;i++){
box_num = box_num+1;
output = output+"<tr><td>"+box_num+"</td><td>"+item_name+" </td><td>L</td><td>"+box_qty+"</td></tr>";
}
Size_L = Size_L-(box_qty*Box_count);
document.getElementById('Size_L'+i).value = Size_L;
}
document.getElementById("output").innerHTML = output+"</table>";
document.getElementById("qty_boxes").value = box_num;
show('Volume_weight');
}
I'm getting my values from here in the HTML code:
<table>
<tr>
<td width="10">1</td>
<td width="120"><input id="item_name1" type="text" style="width:100px;" /></td>
<td width="80"><input id="box_qty1" type="text" style="width:30px;" /></td>
<td width="40"><input id="Size_XS1" type="text" style="width:30px;" onchange="totcalc(1);" /></td>
<td width="40"><input id="Size_S1" type="text" style="width:30px;" onchange="totcalc(1);" /></td>
<td width="40"><input id="Size_M1" type="text" style="width:30px;" onchange="totcalc(1);" /></td>
<td width="40"><input id="Size_L1" type="text" style="width:30px;" onchange="totcalc(1);" /></td>
<td width="60"><input id="total_qty1" type="text" style="width:50px;" /></td>
</tr>
</table>
You have used i for two different things in the code. Firstly as a suffix to input element id values, and secondly as a loop counter for boxes. After i is no longer equal to 1 after various loops complete, the HTML element lookup by suffixed id fails:
document.getElementById('Size_XS'+i).value = Size_XS;
occurs after
for(var i=1;i<=Box_count;i++){ // ...
Feel free to delete the question if this is the problem :D
So, I've been recently tasked to do a few calculations and to build a custom JS statistics library. The only 3 things I have left are to create functions for the range, variance, and standard deviation. What I'm doing here is passing my array (x) into the js functions, but they keep coming up blank. Am I doing something wrong?
function findSum(x)
{
var sum = 0;
for(i = 0; i < x.length; i++)
{
sum = sum + x[i];
}
return sum;
};
function findMean(x)
{
return findSum(x) / x.length;
};
function findMedian(x)
{
x.sort( function(a,b) {return a - b;} );
var half = Math.floor(x.length/2);
if(x.length % 2)
return x[half];
else
return (x[half-1] + x[half]) / 2.0;
}
// Ascending functions for sort
function ascNum(a, b) { return a - b; }
function clip(arg, min, max) {
return Math.max(min, Math.min(arg, max));
};
function findMode(x)
{
var arrLen = x.length;
var _arr = x.slice().sort(ascNum);
var count = 1;
var maxCount = 0;
var numMaxCount = 0;
var mode_arr = [];
var i;
for (i = 0; i < arrLen; i++) {
if (_arr[i] === _arr[i + 1]) {
count++;
} else {
if (count > maxCount) {
mode_arr = [_arr[i]];
maxCount = count;
numMaxCount = 0;
}
// are there multiple max counts
else if (count === maxCount) {
mode_arr.push(_arr[i]);
numMaxCount++;
}
// resetting count for new value in array
count = 1;
}
}
return numMaxCount === 0 ? mode_arr[0] : mode_arr;
};
function findRange(x)
{
x.sort( function (a, b) {return a-b;} );
}
function findVariance(x) {
var mean = findMean(x);
return findMean(array.map(findSum(sum)) {
return Math.pow(sum - mean, 2);
}));
},
function findStandardDeviation(x)
{
return Math.sqrt(findVariance(x));
};
The HTML code:
<html>
<head>
<h1>Statistical Calculations</h1>
<title>Calculating Stats</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src='Stats.js'></script>
<script language="JavaScript">
function addNumber()
{
var input = document.getElementById('input').value;
var list = document.getElementById('list');
var option = document.createElement('OPTION');
list.options.add(option);
option.text = input;
}
function getStatistics()
{
var list = new Array();
var select = document.getElementById('list');
for(i = 0; i < select.options.length; i++)
{
list[i] = parseInt(select.options[i].text);
}
document.getElementById('summation').value =findSum(list);
document.getElementById('mean').value = findMean(list);
document.getElementById('median').value = findMedian(list);
document.getElementById('mode').value = findMode(list);
document.getElementById('variance').value = findVariance(list);
document.getElementById('standardDev').value = findStandardDeviation(list);
document.getElementById('range').value = findRange(list);
document.getElementById('max').value = findMax(list);
document.getElementById('min').value = findMin(list);
}
</script>
</head>
<body>
<table>
<tr>
<td>Input Number:</td><td><input type='text' id='input'></td>
</tr>
<tr>
<td colpsan='2'><input type='button' value='Add Number' onClick='addNumber()'></td>
</tr>
<tr>
<td colspan='2'>
<select id='list' size='5'>
</select>
</td>
</tr>
<tr>
<td colpsan='2'><input type='button' value='Calculate!' onClick='getStatistics()'></td>
</tr>
<tr>
<td>Summation:</td><td><input type='text' id='summation' readonly></td>
</tr>
<tr>
<td>Mean:</td><td><input type='text' id='mean' readonly></td>
</tr>
<tr>
<td>Median:</td><td><input type='text' id='median' readonly> </td>
</tr>
<tr>
<td>Mode:</td><td><input type='text' id='mode' readonly></td>
</tr>
<tr>
<td>Max:</td><td><input type='text' id='max' readonly></td>
</tr>
<tr>
<td>Min:</td><td><input type='text' id='min' readonly></td>
</tr>
<tr>
<td>Range:</td><td><input type='text' id='range' readonly></td>
</tr>
<tr>
<td>Variance:</td><td><input type='text' id='variance' readonly></td>
</tr>
<tr>
<td>Standard Deviation:</td><td><input type='text' id='standardDev' readonly></td>
</tr>
</table>
</body>
</html>
The last 3 seem to do absolutely nothing, and I've been bashing my head in for the last few days trying to figure it out. If anyone could help sort my functions out into working order, it'd be greatly appreciated! I'm sure that the array has been passing into the functions correctly, seeing as the first 4 functions obviously worked.
I'm sorry to post this question but I'm kinda newbie when it comes to js. I have created a simple page that will compute charging transactions, so what it will do is to simply multiply the Quantity and Price to .25%. But here is the trick, if the total product is less than 50 the Charge field should default to 50 and that's where I'm kinda lost,
here is my code:
<tr>
<td width="144">Quantity:</td>
<td width="63"><input type="text" name="quantity" id="quantity" size="8"/></td>
</tr>
<tr>
<td>Price:</td>
<td><input type="text" name="price" id="price" size="8"/></td>
</tr>
<tr>
<td colspan="4"><strong>Charges:</strong></td>
</tr>
<tr>
<td>Charge:</td>
<td><input style="color:#F00" type="text" name="charge" id="charge" size="8" readonly="readonly" /></td>
<td colspan="2">Quantity x Price x .25% OR 20 whichever is higher</td>
</tr>
here is the js that i managed to have,
$(function () {
$("#quantity, #price").keyup(function () {
var q = parseFloat($("#quantity").val()); // Quantity
var p = parseFloat($("#price").val()); // Price
if (isNaN(q) || isNaN(p) || q<=0 || p <= 0) {
$("#charge").val('');
return false;
}
$("#charge").val((q * p * 0.0025).toFixed(3)); // Charge
});
});
Put the total in a variable and test it before putting it into the DOM:
$(function () {
$("#quantity, #price").keyup(function () {
var q = parseFloat($("#quantity").val()); // Quantity
var p = parseFloat($("#price").val()); // Price
if (isNaN(q) || isNaN(p) || q<=0 || p <= 0) {
$("#charge").val('');
return false;
}
var total = q * p * 0.0025;
if (total < 50) {
total = 50;
}
$("#charge").val(total.toFixed(3)); // Charge
});
});
Another way is to use Math.max():
$("#charge").val(Math.max(50, q * p * 0.0025).toFixed(3)); // Charge
If I have more than 1 rows where each rows have 3 column with the inputbox , maybe look like this:
<table id="mytable">
<tr>
<td><input value = "1" /></td>
<td><input value = "2" onBlur="goCount(this)" /></td>
<td><input value = "2+1" /></td>
</tr>
<tr>
<td><input value = "3" /></td>
<td><input value = "4" onBlur="goCount(this)" /></td>
<td><input value = "3+4" /></td>
</tr>
counting must be between cell 1 + cell 2 and the result will show in third cell, maybe the function must be like this :
function goCount(btn) {
var x = btn.value;
var y = ??? ;
var z = x + y;
}
but I do not know how to do that, First get the cell 1 as value and put the result on cell 3 but still in each same rows
is there someone who would help me to resolve this, thanks ^^
Here is your solution
Demo
Your code should be like this
<table id="mytable">
<tr>
<td><input value = "1" onBlur="goCount(this)"/></td>
<td><input value = "2" onBlur="goCount(this)" /></td>
<td><input value = "" id="result"/></td>
</tr>
<tr>
<td><input value = "3" /></td>
<td><input value = "4" onBlur="goCount(this)" /></td>
<td><input value = "" /></td>
</tr>
<script type="text/javascript">
function goCount(btn) {
var x = btn.value;
//var y = ??? ;
var res= document.getElementById("result") ;
//alert( res.value);
if(res.value == "") {
res.value = 0 ;
}
res.value = parseInt(res.value) + parseInt(x) ;
}
</script>
Note: Here is one thing you should note, I have used particular ID to return value in that, if you are using this for many rows you should use jQuery to navigate to that element in respective row and print result in it.