Compare month in nested object array - javascript

The following problem is causing me some headache. I'm building an application to compare transaction data with a list of tenants and what they're supposed to pay for rent.
I've got it running nicely except it compares EACH transaction with the monthly rent. What I want to do is first add all (relevant) transaction amounts per month and then compare them.
Should I just build another nested for-loop to compare all the transaction months before I run this loop? I could potentially drop in years of transaction data making it quite inefficient...
Any tips are greatly appreciated.
var table = "<table><thead><tr><th>Rek</th><th>Name</th><th>Date</th><th>Amount</th><th>Rent</th><th>Diff</th></tr></thead><tbody>";
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < tenant.length; j++) {
if (tenant[j].reks.indexOf(data[i].rek) == -1)
continue;
else {
var diff = tenant[j].rent - data[i].amount; //TODO monthly!!!
var style = " style='background-color: ";
if (diff > 0)
style += "red;'";
else
style += "green;'";
table += "<tr><td>" + data[i].rek
+ "</td><td>" + data[i].name
+ "</td><td>" + (data[i].date.getMonth() + 1) + "-" + data[i].date.getFullYear()
+ "</td><td>€ " + data[i].amount
+ "</td><td>€ " + tenant[j].rent
+ "</td><td" + style
+ ">" + diff
+ "</td></tr>";
}
}
}
table += "</tbody></table>";
$('#top').html(table);

Related

Change innerHTML depending on input

I am iterating through a JSON-File and get a different amount of features for given locations. This can be 10 or there are only 2, depending on the location. I am able to retrieve the data from the JSON for each location and iterate through all of them at this spot.
GOAL: Depending on the number of features at the location I would like to create a table with max. 3 columns and number/3 rows. If there are e.g. 10 Features just make 3-3-3-1 (2 empty boxes).
var overlay = new ol.Overlay({
element: document.getElementById('overlay'),
positioning: 'bottom-left'
});
var displayImage = function(pixel) {
var features = [];
map.forEachFeatureAtPixel(pixel, function(feature,layer){
features.push(feature);
},{hitTolerance: 10});
if (features.length >0) {
var rows = Math.ceil(features.length / 3);
var imag = [];
var years = [];
console.log(features);
for (var i = 0, ii = features.length; i < ii; ++i) {
imag.push(features[i].values_.pointAttributes.Image);
years.push(features[i].values_.pointAttributes.Year);
overlay.setPosition(features[i].values_.geometry.flatCoordinates);
var element = overlay.getElement();
console.log(imag);
element.innerHTML =
"<img ID=\"theImage\" src= \"\">\n\
<table class=\"fototable\"> \n\
<tr><td> <button class=\"btn\" data-img=" + imag[0] + " onclick=\"myFunction(this)\"> " + years[0] + " </button></td>\n\
<td> <button class=\"btn\" data-img=" + imag[1] + " onclick=\"myFunction(this)\"> " + years[1] + " </button> </td>\n\
<td> <button class=\"btn\" data-img=" + imag[2] + " onclick=\"myFunction(this)\"> " + years[2] + " </button> </td></tr> \n\
<tr><td> <button class=\"btn\" data-img=" + imag[3] + " onclick=\"myFunction(this)\"> " + years[3] + " </button></td> \n\
<td><button class=\"btn\" data-img=" + imag[4] + " onclick=\"myFunction(this)\"> " + years[4] + " </button></td>\n\
<td><button class=\"btn\" data-img=" + imag[5] + " onclick=\"myFunction(this)\"> " + years[5] + " </button> </td></tr></table>";
As you might see I hard-coded it so far but this is not the best solution. I tried to do something like adding the ...etc. to a string but I did not manage to get the 3-columns max then.
Any help/link will be appreciated!
Have fun :)
let test = [1,2,3,4,5,6,7,8,9,10,11];
let innerHTMLStart = "<table>";
let innerHTMLEnd = "</table>"
let innerHTML = innerHTMLStart;
let lastIndex = test.length - 1;
//loop over our items
for(var i = 0; i < test.length; i++) {
//first iteration
if(i % 3 == 0 && i == 0) {
innerHTML = innerHTML + "<tr>"
//modulo 3 but not first iteration
} else if(i % 3 == 0 && i > 0) {
innerHTML = innerHTML + "</tr><tr>"
}
//add cells to the table
innerHTML = innerHTML + "<td>" + test[i] + "</td>";
if(i == lastIndex) {
//last iteration? how many <td>?
//always finish with 3 cells
if((i+1) % 3 == 0) {
innerHTML = innerHTML + "</tr>"
} else if((i+1) % 2 == 0) {
innerHTML = innerHTML + "<td></td><td></td></tr>"
} else {
console.log("else")
innerHTML = innerHTML + "<td></td></tr>"
}
}
}
innerHTML = innerHTML + innerHTMLEnd;
console.log(innerHTML)
I didn't test that code and probably contains errors but as i understand your question the code below should be suits your needs.
var content ="<table class=\"fototable\"><tr>";
for(var t=0; t<imag.length; t++){
content+="<td><button class=\"btn\" data-img=\" + imag[t] + \" onclick=\"myFunction(this)\"> " + years[t] + " </button></td>\n\";
if((t+1)%3==0 && t!=(imag.length-1)){
content+="</tr><tr>";
}
}
for(var i = 0; i<3-imag.length%3; i++){
content+="<td></td>";
}
content+="</tr></table>";
element.innerHtml = content;

Array issue when the length is below 5

Listing last five items in an array by using this code below worked so far, but when the array length was only 1 it started causing issues. Can I some how condition it so it doesn't cycle though when there is only one item in the array?
$(function() {
$.getJSON("#myURL", function(getStressTestErrorInfo2) {
if (getStressTestErrorInfo2.length >= 1) {
var len = getStressTestErrorInfo2.length - 5;
var data = getStressTestErrorInfo2;
var txt = "";
if (data.length - 1 !== undefined) {
for (var i = len; i < len + 5; i++) {
// dynamically generating a table-row for appending in the table.
txt += "<tr><td>" + data[i].AlarmNo + "</td><td>" + data[i].AlarmCnt + "</td><td>" + data[i].StresstestId + "</td><td>" + data[i].StresstestRunId + "</td><td>" + data[i].Name + "</td><td>" + data[i].StackTrace + "</td><td>" + data[i].Timestamp + "</td></tr>";
}
if (txt != "") {
// #table is the selector for the table element in the html
$("#listErrorsTest2").append(txt);
}
}
};
});
});
Change this line:
if (getStressTestErrorInfo2.length >= 1) {
to:
if (getStressTestErrorInfo2.length >= 5) {
This way, it wont start the function, if the length is lower then 5.
The issues you have is that no matter the size of the array, you take the size and substract 5 to it. Allowing you to take the last 5 cells of an array ... long enough. If the length is below 5, the index will be negative.
Now, you can't simply update the condition if you want to get the values of smaller arrays.
You can simply set the index to 0 if it is negative :
var len = getStressTestErrorInfo2.length - 5;
if (len < 0) len = 0; //Array with less than 5 values.
And loop until you reach the end
while(len < getStressTestErrorInfo2.length){ ... }
My approach at the begging had some (stupid) flaws. Instead of showing the last 5 items I reversed the array and listed first five and added the condition
if (len > 5) len = 5;
so it did the trick.
$(function() {
$.getJSON("#myURL", function(getStressTestErrorInfo0) {
if (getStressTestErrorInfo0.length >= 1) {
var data = getStressTestErrorInfo0;
/*Function to reverse the array*/
function reverseArr(input) {
var ret = new Array;
for (var i = input.length - 1; i >= 0; i--) {
ret.push(input[i]);
}
return ret;
}
var reverseData = reverseArr(data);
var len = getStressTestErrorInfo0.length;
var data = getStressTestErrorInfo0;
var txt = "";
if (len > 0) {
if (len > 5) len = 5;
for (var i = 0; i < len; i++) {
// dynamically generating a table-row for appending in the table.
txt += "<tr><td>" + reverseData[i].AlarmNo + "</td><td>" + reverseData[i].AlarmCnt + "</td><td>" + reverseData[i].StresstestId + "</td><td>" + reverseData[i].StresstestRunId + "</td><td>" + reverseData[i].Name + "</td><td>" + reverseData[i].StackTrace + "</td><td>" + reverseData[i].Timestamp + "</td></tr>";
}
if (txt != "") {
//selector for the table element in the html
$("#listErrors").append(txt);
}
}
};
});
});

While loop and outputting math operators

I'm trying to create a while loop that outputs a list of values, adds them together, and outputs a total with an "=" sign at the end
I.e., if the User enters the numbers 5 and 12, the output would show up like this:
5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 = total
This is how my 'while' loop looks right now:
while(enteredNum1 <= enteredNum2){
total += enteredNum1;
document.write(enteredNum1 + " + ");
enteredNum1++;
}
document.write("= " + total);
I know it will always append the " + ", but can anyone point me in the right direction for having the last value show "=" instead of the "+" again?
Alternative;
var numbers = [];
while(enteredNum1 <= enteredNum2){
total += enteredNum1;
numbers.push(enteredNum1++);
}
document.write(numbers.join(" + ") + " = " + total);
Proper way:
list = [];
total = 0;
enteredNum1 = parseInt(enteredNum1); // parseInt only if enteredNum1 can be a string
while(enteredNum1 <= enteredNum2) {
total += enteredNum1;
list.push(enteredNum1);
enteredNum1++;
}
document.write(list.join(" + ") + " = " + total);
Any easy way would be an if statement checking if the loop will continue:
while(enteredNum1 <= enteredNum2) {
total += enteredNum1;
if (enteredNum1 + 1 <= enteredNum2) {
document.write(enteredNum1 + " + ");
} else {
document.write(enteredNum1);
}
enteredNum1++;
}
document.write(" = " + total);
Alternatively, saving the output as a string and taking the "+" off using substring would work as well
This should work:
total += enteredNum1;
document.write(enteredNum1);
enteredNum1++;
while(enteredNum1 <= enteredNum2){
total += enteredNum1;
document.write(" + " + enteredNum1);
enteredNum1++;
}
document.write("= " + total);

Javascript function - works in IE, not in chrome

To preface this, we are a small organization and this system was built by someone long ago. I am a total novice at javascript so I have trouble doing complicated things, but I will do my best to understand your answers. But unfortunately redoing everything from scratch is not really an option at this point.
We have a system of collecting data where clients use a login to verify a member ID, which the system then uses to pull records from an MS Access database to .ASP/html forms so clients can update their data. One of these pages has the following function that runs on form submit to check that data in fields a/b/c sum to the same total as d/e/f/g/h/i. It does this separately for each column displayed (each column is a record in the database, each a/b/c/d/e/f is a field in the record.)
The problem is with this section of the function:
for (var j=0; j<recCnt; j++) {
sumByType = milesSurf[j] + milesElev[j] + milesUnder[j];
sumByTrack = milesSingle[j] + milesDouble[j] + milesTriple[j] + milesQuad[j] + milesPent[j] + milesSex[j];
etc.
It should use javascript FOR to loop through each record and test to see if they sum to the same thing.
In Firefox and IE this is working properly; the fields sum properly into "sumByType" and "sumByTrack". You can see below I added a little alert to figure out what was going wrong:
alert(sumByType + " " + j + " " + recCnt + " " + milesSurf[j] + " " + milesElev[j] + " " + milesUnder[j]);
In Chrome, that alert tells me that the components of "sumByType" and "sumByTrack" (the various "milesXXXXX" variables) are undefined.
My question is: Why in Chrome is this not working properly, when in IE and FFox it is? Any ideas?
Full function code below:
function submitCheck(formy, recCnt) {
//2/10/03: added milesQuad
//---------------checks Q#4 that Line Mileage by type is the same as by track
var milesElev = new Array();
var milesSurf = new Array();
var milesUnder = new Array();
var milesSingle = new Array();
var milesDouble = new Array();
var milesTriple = new Array();
var milesQuad = new Array();
var milesPent = new Array();
var milesSex = new Array();
var sumByType = 0;
var milesLineTrack = new Array(); //this is for Q5 to compare it to mileage by trackage
var j = 0; var sumByTrack = 0; var liney; var yrOp;
//var str = "document.frm.milesElev" + j;
//alert(str.value);
for (var i in document.frm) {
if (i.substring(0, i.length - 1) == "milesElev") {
milesElev[parseInt(i.substring(i.length-1, i.length))] = parseFloat(document.frm[i].value); }
if (i.substring(0, i.length - 1) == "milesSurf") {
milesSurf[parseInt(i.substring(i.length-1, i.length))] = parseFloat(document.frm[i].value); }
if (i.substring(0, i.length - 1) == "milesUnder") {
milesUnder[parseInt(i.substring(i.length-1, i.length))] = parseFloat(document.frm[i].value); }
if (i.substring(0, i.length - 1) == "milesSingle") {
milesSingle[parseInt(i.substring(i.length-1, i.length))] = parseFloat(document.frm[i].value); }
if (i.substring(0, i.length - 1) == "milesDouble") {
milesDouble[parseInt(i.substring(i.length-1, i.length))] = parseFloat(document.frm[i].value); }
if (i.substring(0, i.length - 1) == "milesTriple") {
milesTriple[parseInt(i.substring(i.length-1, i.length))] = parseFloat(document.frm[i].value); }
if (i.substring(0, i.length - 1) == "milesQuad") {
milesQuad[parseInt(i.substring(i.length-1, i.length))] = parseFloat(document.frm[i].value); }
if (i.substring(0, i.length - 1) == "milesPent") {
milesPent[parseInt(i.substring(i.length-1, i.length))] = parseFloat(document.frm[i].value); }
if (i.substring(0, i.length - 1) == "milesSex") {
milesSex[parseInt(i.substring(i.length-1, i.length))] = parseFloat(document.frm[i].value); }
if (i.substring(0, i.length -1) == "milesLineTrack") {
milesLineTrack[parseInt(i.substring(i.length-1, i.length))] = document.frm[i].value; } //12/13/02 used to be parseFloat(document.frm[i].value)
if (i.substring(0,5)=="Lines") {
liney = document.frm[i].value;
if (parseInt(liney)<1 || isNaN(liney)) {
alert("Each mode must have at least 1 line. Please correct the value in question #2.");
document.frm[i].select(); return false; }}
if (i.substring(0,8)=="yearOpen") {
yrOp = document.frm[i].value;
if (parseInt(yrOp)<1825 || isNaN(yrOp)) {
alert("Please enter a year after 1825 for question #3");
document.frm[i].select(); return false; }
}
}
for (var j=0; j<recCnt; j++) {
sumByType = milesSurf[j] + milesElev[j] + milesUnder[j];
sumByTrack = milesSingle[j] + milesDouble[j] + milesTriple[j] + milesQuad[j] + milesPent[j] + milesSex[j];
//---------------to round sumByTrack and sumByType from a long decimal to a single decimal place, like frm 7.89999998 to 7.9.
sumByTrack = sumByTrack * 10;
if (sumByTrack != parseInt(sumByTrack)) {
if (sumByTrack - parseInt(sumByTrack) >= .5) {
//round up
sumByTrack = parseInt(sumByTrack) + 1; }
else { //truncate
sumByTrack = parseInt(sumByTrack); }}
sumByTrack = sumByTrack / 10;
sumByType = sumByType * 10;
if (sumByType != parseInt(sumByType)) {
if (sumByType - parseInt(sumByType) >= .5) {
//round up
sumByType = parseInt(sumByType) + 1; }
else { //truncate
sumByType = parseInt(sumByType); }}
sumByType = sumByType / 10;
//-------------end of rounding ---------------------------
if (sumByType != sumByTrack) {
if (isNaN(sumByType)) {
sumByType = "(sum of 4.a., b., and c.) "; }
else {
sumByType = "of " + sumByType; }
if (isNaN(sumByTrack)) {
sumByTrack = "(sum of 4.d., e., f., g., h., and i.) "; }
else {
sumByTrack = "of " + sumByTrack; }
alert("For #4, the 'End-to-End Mileage By Type' " + sumByType + " must equal the 'End-to-end Mileage By Trackage' " + sumByTrack + ".");
alert(sumByType + " " + j + " " + recCnt + " " + milesSurf[j] + " " + milesElev[j] + " " + milesUnder[j]);
return false;
}
//alert (milesLineTrack[j] + " " + milesSingle[j] + " " + 2*milesDouble[j] + " " + 3*milesTriple[j] + " " + 4*milesQuad[j] + " " + 5*milesPent[j] + " " + 6*milesSex[j]);
var singDoubTrip = (milesSingle[j] + 2*milesDouble[j] + 3*milesTriple[j] + 4*milesQuad[j] + 5*milesPent[j] + 6*milesSex[j])
//----------round singDoubTrip to one digit after the decimal point (like from 6.000000001 to 6.0)
singDoubTrip = singDoubTrip * 10;
if (singDoubTrip != parseInt(singDoubTrip)) {
if (singDoubTrip - parseInt(singDoubTrip) >= .5) {
//round up
singDoubTrip = parseInt(singDoubTrip) + 1; }
else { //truncate
singDoubTrip = parseInt(singDoubTrip); }}
singDoubTrip = singDoubTrip / 10;
//----------end round singDoubTrip-----------------------------------------
if (parseFloat(milesLineTrack[j]) != singDoubTrip) {
//var mlt = milesLineTrack[j];
//if isNaN(milesLineTrack[j]) { mlt =
alert("For column #" + (j+1) + ", the mainline passenger track mileage of " + milesLineTrack[j] + " must equal the single track plus 2 times the double track plus 3 times the triple track plus 4 times the quadruple track plus 5 times the quintuple track plus 6 times the sextuple track, which is " + singDoubTrip + ".");
return false;
}
}
//---------------------end of checking Q#4----------------
//return false;
}
I think for (var i in document.frm) is the problem. You should not enumerate a form element, there will be plenty of unexpected properties - see Why is using "for...in" with array iteration a bad idea?, which is especially true for array-like objects. I can't believe this works properly in FF :-)
Use this:
var ele = document.frm.elements; // or even better document.getElementById("frm")
for (var i=0; i<ele.length; i++) {
// use ele[i] to access the element,
// and ele[i].name instead of i where you need the name
}
Also, you should favour a loop over those gazillion of if-statements.

need to refresh to show local storage values in javascript

I'm trying to get the values stored in the local storage variables in order to display them !!
but the problem here is that the display of the values is immediate, in other words :
the first time of loading the page nothing is displayed then every time i refresh the page the next value is displayed.
function ChoixDeQuestion (){
var ide=window.sessionStorage.getItem('idenq');
GetQuest(10);//--> this function store some values in the 'questions' var
var storedQuest=JSON.parse(window.localStorage['questions']);
var i;
for ( i = 0; i < storedQuest.length; i++)
{
var newdiv = document.createElement('div');
switch(storedQuest[i].type) {
case 'text':
newdiv.innerHTML += "<br> Question " + (i + 1) + " : "+storedQuest[i].text+" ? <br><br><textarea name='quest"+(i + 1)+"' rows=4 cols=40 >type here...</textarea>" ;
break;
case 'simple':
var questId=storedQuest[i].id;
GetChoix(questId);
var storedChoix=JSON.parse(window.localStorage['choices'+questId]);
newdiv.innerHTML += "<br> Question " + (i + 1) + " : "+storedQuest[i].text+" ? <br><br>";
for (var j = 0; j < storedChoix.length; j++) {
newdiv.innerHTML += " " + (j + 1) +"- "+storedChoix[j].text+ " <input type='radio' name='choix"+(j + 1)+"'>";
}
break;
case 'multiple':
var questId=storedQuest[i].id;
GetChoix(questId);
var storedChoix=JSON.parse(window.localStorage['choices'+questId]);
newdiv.innerHTML += "<br> Question " + (i + 1) + " : "+storedQuest[i].text+" ? <br><br>";
for (var j = 0; j < storedChoix.length; j++) {
newdiv.innerHTML += " " + (j + 1) +"- "+storedChoix[j].text+ " <input type='checkbox' name='choix"+(j + 1)+"'>";
}
break;
document.getElementById('results').appendChild(newdiv);
}
}
thie method is called in the
$(document).ready(function() { ChoixDeQuestion();});
So how can I get all the values shown in the same time when the page is loaded ??

Categories