jQuery addition function giving me NaN - dom

I am using the following function to add all of my line totals together. Each of the totals will be a decimal number such as 23.45 . When the user enters any qty into any of text input boxes it should fire the function, but all I'm getting at the moment in grandtotal is NaN, who's nan is it and why is she messing with my script?
By the way, each of the linetotals is a span, which is filled with the line total calculation once a quantity is entered into the qty text box.
So basically, user comes along, selects a price from the line one drop down, so lets say 20.00 , they then enter the quantity into the text box qty, let's say 2, jQuery then multiplies qty by priceeach and output into the span with the id linetotal1. What I want to do is add all of the linetotals together for a grand total, but lets say if they don't enter anything into line 2, linetotal2, 3, 4, 5 will them be empty.
<script>
$(document).ready(function () {
$('input').on('keyup', function () {
linetotal1 = $('#linetotal1').text(),
linetotal2 = $('#linetotal2').text(),
linetotal3 = $('#linetotal3').text(),
linetotal4 = $('#linetotal4').text(),
linetotal5 = $('#linetotal5').text(),
grandtotal = parseFloat(linetotal1) + parseFloat(linetotal2) + parseFloat(linetotal3) + parseFloat(linetotal4) + parseFloat(linetotal5);
$('#grandtotal').text(grandtotal);
}); });
</script>

You could just loop from 1-5, and have the value default to 0 if it's a blank string:
var rawValue, grandtotal = 0;
for(var i=1; i<6; i++)
{
rawValue = $.trim($('#linetotal' + i).text());
if(rawValue == '') rawValue = 0;
grandtotal += parseFloat(rawValue);
}
$('#grandtotal').text(grandtotal);
jsFiddle Demo
If you wanted to do something a bit fancier with jQuery you could select each of the spans based on the ID starting with linetotal. This would work if you added more spans, where as with the for loop, you'd have to update the count. It would be better if the spans all had a common class, which you could use to easily select them.
var rawValue, grandtotal = 0;
$('span[id^="linetotal"]').each(function(i, elem){
rawValue = $.trim($(this).text());
if(rawValue == '') rawValue = 0;
grandtotal += parseFloat(rawValue);
});
$('#grandtotal').text(grandtotal);
jsFiddle Demo

You should do this by loop, i have done this before for my client check if my code helps you
var disValue = new Array();
var this_size = document.getElementsByName("myVal").length;
sum = 0;
for (i=0; i<this_size; i++)
{
disValue[i] = document.getElementsByName("myVal")[i].value;
}
for (i=0; i<this_size; i++)
{
sum = parseFloat(sum)+ parseFloat(disValue[i]);
}
if (sum != 0) {
document.getElementById("disc_test").innerHTML="<?php echo $this->__('You are saving') ?> "+sum +" <?php echo $this->__('on this order') ?>!";
}
ignore php tags :)

Related

Is there a better way to calculate the moving sum of a list in flutter

Is there a better way to calculate a moving sum of a list?
List<double?> rollingSum({int window = 3, List data = const []}) {
List<double?> sum = [];
int i = 0;
int maxLength = data.length - window + 1;
while (i < maxLength) {
List tmpData = data.getRange(i, i + window).toList();
double tmpSum = tmpData.reduce((a, b) => a + b);
sum.add(tmpSum);
i++;
}
// filling the first n values with null
i = 0;
while (i < window - 1) {
sum.insert(0, null);
i++;
}
return sum;
}
Well, the code is already clean for what you need. Maybe just some improvements like:
Use a for loop
You can use the method sublist which creates a "view" of a list, which is more efficient
To insert some values in the left/right of a list, there is a specific Dart method called padLeft, where you specify the lenght of the list which you want it to become (first parameter), then the value you want to use to fill it (second parameter). For example, if you have an array of N elements, and you want to fill it with X "null"s to the left, use padLeft(N+X, null).
List<double?> rollingSum({int window = 3, List data = const []}) {
List<double?> sum = [];
for (int i = 0; i < data.length - window + 1; i++) {
List tmpData = data.sublist(i, i + window);
double tmpSum = tmpData.reduce((a, b) => a + b);
sum.add(tmpSum);
}
sum.padLeft(window - 1, null);
return sum;
}
if I understand your problem correctly you can just calculate the window one time and in one loop you can for each iteration you can add the current element to the sum and subtract i - (window - 1)
so for an input like this
data = [1,2,3,4,5,6]
window = 3
the below code will result in [6,9,12,15]
int sum = 0;
List<double> res = [];
for (int i = 0;i<data.length;i++) {
sum += data[i];
if (i < window - 1) {
continue;
}
res.add(sum);
sum -= data[i - (window - 1)]; // remove element that got out of the window size
}
this way you won't have to use getRange nor sublist nor reduce as all of those are expensive functions in terms of time and space complexity

How to exclude a column when using getAllColumns property in ag-grid

I have a function that counts and hides the number of columns that does not fit the screen. I want to exclude a column when resizing and hiding the columns. Here is what I have.
let ctrOfColumns = this.gridOptionsValue.columnApi.getAllColumns();
this returns the columns that i have. I want to exclude a specific column which has a colId of 'toBeExcludedId' so that It won't be included in the hiding of columns algo.
Here is my algo in hiding of the columns
let gridWidthOfMyTable = $('#idOfMyGrid').outerWidth();
let columnsToBeShown = [];
let columnsToBeHidden = [];
let totalWidthOfColumn = 0;
for(let x = 0 ; x < ctrOfColumns.length; x ++){
const singleColumn = ctrOfColumns[x];
totalWidthOfColumn += singleColumn.getMinWidth();
if (totalWidthOfColumn > gridWidthOfMyTable) {
columnsToBeHidden.push(singleColumn);
} else {
columnsToBeShown.push(singleColumn);
}
}
this.gridOptionsValue.columnApi.setColumnsVisible(columnsToBeShown, true);
this.gridOptionsValue.columnApi.setColumnsVisible(columnsToBeHidden, false);
There is no need to loop through all the values in your array. You can just use chaining and apply a filter directly to getAllColumns(), like this:
let ctrOfColumns = this.gridOptionsValue
.columnApi
.getAllColumns()
.filter((column) => column.colId !== 'toBeExcludedId');

PDF Text Field Won't Show As Empty

I have a surcharge text box that I want to perform calculations based on a subtotal field. There is a minimum 4.50 which is calculated when the subtotal is <112.5. When the subtotal is >=112.5 the calculation is subtotal *0.04. My problem is that I don't know how to program the field to show as empty when the subtotal is 0.
Here is my code.
{
var nSubtotal = this.getField("Subtotal").value;
if(nSubtotal = "0")event.value = "";
if( nSubtotal >= 112.5) event.value = nSubtotal * 0.04;
if( nSubtotal < 112.5) event.value = 4.50;
}
This can be simplified (and be made to work) with something like this:
if (this.getField("Subtotal").value > 0) {
event.value = util.printf("%.2f", Math.min(560, Math.max(4.50, this.getField("Subtotal").value * 0.04))) ;
} else {
event.value = "" ;
}
Note that in this case, the formatting of the result field is done in the calculation, and therefore, the result field does NOT need any format set; this also prevents the result field to show a value based on incomplete calculations.

How to make custom time and date?

I have looked at this code and they just seem to simply update theirs every day with the HTML, but I know there's a way to make a custom date by altering Monday to be Morndas, Sunday to be Sundas, January as Morning Star, etc. How would I go about coding this for my own website, as it's a cool little feature to have on an Elder Scrolls website, and I am not always available to update it every night at midnight.
Thanks
I think this is best done using server side scripting, like PHP. But below I've given a Javascript implementation which you can easily embed. Once you learn about server side scripting, it should be trivial to translate this code to another language.
window.addEventListener('DOMContentLoaded', function() {
// Function to determine the postfix of the month number
function numberPostFix(nr) {
nr = nr % 100;
if (nr >= 10 && nr < 20) return 'th';
nr = nr % 10;
if (nr == 1) return 'st';
if (nr == 2) return 'nd';
if (nr == 3) return 'rd';
return 'th';
}
// Arrays of custom month names.
var monthNames = [
"Morning Star",
"Sun's Dawn",
"First Seed",
"Rain's Hand",
"Second Seed",
"Mid Year",
"Sun's Height",
"Last Seed",
"Hearthfire",
"Frostfall",
"Sun's Dusk",
"Evening Star"
];
// Array of custom weekday names.
var dayNames = [
"Sundas",
"Morndas",
"Tirdas",
"Middas",
"Turdas",
"Fredas",
"Loredas"
];
// Get all relevant parts.
var date = new Date();
var month = date.getMonth();
var monthday = date.getDate();
var weekday = date.getDay();
// Construct the day text.
var dateHtml = "Today is " + dayNames[weekday] + ", " + monthday + "<sup>" + numberPostFix(monthday) + "</sup> of " + monthNames[month];
// Write to document.
document.getElementById('date').innerHTML = dateHtml;
});
<header>
<h2>Welcome, this is your page header.</h2>
<span id="date"></span>
</header>

Change sheet cells color onEdit

I figured out how to compare dates in Google Sheets but when I try to enter more dates for some reason all the cells that were green and red become all red. Also how can I make two cells red if only one cell has a date?
Example: In cell D18 the Due date is 4-18-2014 and in cell E18 the cell is blank. I want to make both cells red so I would know that I should find out why is that cell red.
This is the code I have so far:
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Copy of Project Sheet 1');
var values1Rule1 = s.getRange('E2:E1000').getValues();
var values2Rule1 = s.getRange('D2:D1000').getValues();
var range3Rule1 = s.getRange('D2:E2');
var color1 = 'Red';
var color2 = 'Green';
for (var row in values1Rule1) {
for (var col in values1Rule1[row]) {
if (values1Rule1[row][col] > values2Rule1[row][col]) s.getRange(s.getRange('D2').offset(row, col, 1, 2).getA1Notation()).setBackgroundColor(color1);
else if (values1Rule1[row][col] < values2Rule1[row][col]) s.getRange(s.getRange('D2').offset(row, col, 1, 2).getA1Notation()).setBackgroundColor(color2);
else s.getRange(s.getRange('D2').offset(row, col, 1, 2).getA1Notation()).setBackgroundColor('white'); }}
};
All you need to do is add this condition as an OR clause in your red condition, e.g.
if (values1Rule1[row][col] > values2Rule1[row][col] || values1Rule1[row][col] === '')
But there's lots of "minor" problems with your code. First of all, you're doing way too many API calls unnecessarily. This is a big performance issue. For example, when you offset, you already have the new range, there's no need to getA1Notation then get the range again, you could do:
s.getRange('D2').offset(row, col, 1, 2).setBackgroundColor(color1);
But that's still two calls, getting D2, then offseting. You could get the desired range at once:
s.getRange(row+1, 4, 1, 2).setBackgroundColor(color1);
I'd go even further and build a matrix of colors and set it all at once after the loop:
s.getRange('D2:E1000').setBackgroundColors(colors);
But even better, inside an onEdit you should only work on what has just being edited, instead of triggering a full recalculation of your colors because the user edited something on another column or another sheet entirely.
I think your code should be something like this:
function onEdit(e) {
var ss = e.source;
var s = ss.getActiveSheet();
if( s.getName() !== 'Copy of Project Sheet 1' ) return; //only interested in one sheet
var r = s.getActiveRange();
var c = r.getColumn();
if( c !== 4 && c !== 5 ) return; //only interested in changes on columns D or E
r = r.offset(0, c === 4 ? 0 : -1, 1, 2);
var v = r.getValues()[0];
r.setBackgroundColor(v[1] === '' || v[1] > v[0] ? 'red' : v[1] < v[0] ? 'green' : 'white');
}
--edit
You can not run this function manually directly, because it needs a parameter that is passed only when it runs automatically. But you can emulate it with a test function, like this:
function testEdit() { onEdit({source:SpreadsheetApp.getActive()}); }