Passing variable to getElementById results in NaN error - javascript

function upgrade(cost, hps, htmlName, id)
{
/* calc new cost based on quantity currently has */
var currUpgradeCost = Math.floor(cost * Math.pow(1.1,upgradeCount[id]));
/* can they afford it? */
if(totalHacks >= currUpgradeCost)
{
/* tally up THIS UPGRADE */
upgradeCount[id]++;
/* total the upgrades as a whole */
totalUpgrades = totalUpgrades + hps;
/* subtract this cost fro the total hacks so far */
totalHacks = totalHacks - currUpgradeCost;
/* update the HTML */
document.getElementById('hpc').innerHTML = totalUpgrades.toFixed(1);
document.getElementById('totalHacks').innerHTML = totalHacks.toFixed(0);
};
/* calc/display cost for next upgrade */
var nextCost = Math.floor(cost * Math.pow(1.1,upgradeCount[id]));
document.getElementById(htmlName).innerHTML = nextCost;
};
<button onclick="upgrade(15, .1,'upgradePCCost', 0)">Upgrade System</button>
- Cost <span id="upgradePCCost">15</span><br/>
<button onclick="upgrade(100, .5,'scriptBotCost', 1)">Script Bot</button>
- Cost <span id="scriptBotCost">100</span><br/>
EDIT: FULL FUNCTION:(yes tinkering with a clicker game to learn JS. )And I'll take the negative votes if it will solve it. These are the two sections giving me issues.
/EDIT
OK, hope I made this simple and to the point. Main problem - it works, it just gives a NaN error for the targetId.
Now I've been reading everywhere, and a couple things I found.
I could not find anyone passing a var to the elementById in the manner I was.
Since I cannot find the answer that works - I am obviously doing it wrong.
This is all part a larget project, and to avoid redundant code, it is based on what button they are clicking, so I just add that to the function. The only line that does not work, is the one above: elementById. My debugger does not show any errors, the html just keeps spitting out a NaN instead of 444 (in this example)
Many of the sites / forums I checked, all say this should work. So there is something I am missing.
Couple of the things I've tried:
-.toString()
-elementsByName
Thanks. I am pretty sure I checked everywhere on S.O. to make sure this is not a dupe, as no one is doing the same thing with the same results (i.e. many I found were solved because of typos - obviously, that is not my issue)

if this code doesn't work for you, definitely related with other part of your code. document.getElementById function expects string as argument, and you pass one, so, i don't think it's the problem. Similarly, you assign string to innerHTML property takes also string, but passing number value doesn't hurt, because javascript converts it to string for you. So, the error you get NaN (not a number) has nothing to do with the line:
document.getElementById(htmlName).innerHTML = someVar;
I don't see the other part of your code as you trimmed out, but I suspect the function runs when you click on the button, is reading the value "444" in your example, and passing to your "myFunction". Probably you should look for error there.
Ask yourself the classical debugger question when you stuck, what justifies my expectation the things to be as the way I expected? And find the line in your code justifies your expectation and check if it runs the way it should?
Using your example, you pass a "number" to innerHTML property, any you get NaN error. So, the question is, what justifies that the number you pass is a number? And find that part of your code, if you pass a number.
UPDATE: After seeing other part of your code, it looks your nextCost variable is NaN, so you cannot assign it to innerHTML.
nextCost is using some math calculation, which involves cost, which is number, considering onClick calls, only thing remains is the upgradeCount[id] array/object, both can be, but probably array. So I think you should look still other part of your code, which forms upgradeCount array, and make sure that upgradeCount in index id has number value.
Hope it helps.

This works perfectly for me:
<button onclick="upgrade(15, .1,'upgradePCCost', 0)">Upgrade System</button>
- Cost <span id="upgradePCCost">15</span><br/>
<button onclick="upgrade(100, .5,'scriptBotCost', 1)">Script Bot</button>
- Cost <span id="scriptBotCost">100</span><br/>
<script type="text/javascript">
function upgrade(cost, hps, htmlName, id)
{
upgradeCount = [ 1, 2, 3, 4 ];
totalHacks = 0;
/* calc new cost based on quantity currently has */
var currUpgradeCost = Math.floor(cost * Math.pow(1.1,upgradeCount[id]));
/* can they afford it? */
if(totalHacks >= currUpgradeCost)
{
/* tally up THIS UPGRADE */
upgradeCount[id]++;
/* total the upgrades as a whole */
totalUpgrades = totalUpgrades + hps;
/* subtract this cost fro the total hacks so far */
totalHacks = totalHacks - currUpgradeCost;
/* update the HTML */
document.getElementById('hpc').innerHTML = totalUpgrades.toFixed(1);
document.getElementById('totalHacks').innerHTML = totalHacks.toFixed(0);
};
/* calc/display cost for next upgrade */
var nextCost = Math.floor(cost * Math.pow(1.1,upgradeCount[id]));
document.getElementById(htmlName).innerHTML = nextCost;
};
</script>
I've run your code, and as you can see. If all the values are correct this function should work. As you can see i added upgradeCount and totalHacks so i could make the code run. But remember, before you can do math on the array you must be sure that all the values in it, is numbers, else you will get NaN.

Related

Javascript, Quirks of using undefined variables

This is gonna be a bit of a weird one b/c I can't provide the actual input for the test case. On the codingGame website there is an exercise where I have to find the lowest difference between integers. I create a variable, but leave it undefined and later use it to hold the lowest difference
function shortest(horses){
let short;
horses.sort((a,b) => a - b).forEach((horse,i) => {
let dif = horse - horses[i-1];
if (dif < short || !short) short = dif;
});
return short;
};
This passes all the tests but one, and the only way to solve the failed one is to assign a value to short instead of leaving it undefined (like let short = 10000000000000);
The website, annoyingly, won't give out the input so I'm not sure why the code is behaving this way so does does anyone know why leaving it undefined instead of a value will cause problems?

Apps Script extremely slow or endlessly "Preparing for execution..."

I have written a very simple code on my Google Sheets file. This is the purpose:
Save some cells values from StaticSheet (all the Copyxxx) that need to be copied in DynamicSheet.
Get the value of one specific cell inserted by the user manually.
Enter a While loop useful only to increase an indicator and get the number of the row where I want to copy those values previously saved.
Copy those values on this row but different columns.
The problem is that it seems that most of the time it does not even run the script after I told it to do so.
What is funny is that sometimes it works, super slowly, but it works for like a couple of minutes. And after it stops working again.
Could you please tell me what am I missing here please?
function Copy_Static_on_Dynamic() {
var app = SpreadsheetApp;
var ss = app.openById("xxxxyy--------yyzzzz")
var StaticSheet = ss.getSheetByName("DEAT Price");
var DynamicSheet = ss.getSheetByName("DEAT Price + TEST");
var CopySKU = StaticSheet.getRange(5,1,40);
var CopyPrices = StaticSheet.getRange(5,3,40,4);
var CopyUsage = StaticSheet.getRange(5,8,40);
var Week_1 = StaticSheet.getRange(2,4).getValues();
var i = 1;
Logger.clear();
while(DynamicSheet.getRange(i,3).getValues() != Week_1)
{
Logger.log(i);
i+=1;
}
CopySKU.copyTo(DynamicSheet.getRange(i,4,40));
CopyPrices.copyTo(DynamicSheet.getRange(i,6,40,4));
CopyUsage.copyTo(DynamicSheet.getRange(i,11,40));
}
If you see the "Preparing for Execution" message in the Apps Script editor, you can reload the browser window and run the function again. The program will likely go away.
So I think I have solved it.
As Serge insas was saying I had my script running on the background, I found it out on the "Execution" section, where you can also interrupt them.
After I discover it I kept testing, and I saw that the while loop needed almost 2 seconds to check the condition every time, making the script incredibly long.
So instead of:
while(DynamicSheet.getRange(i,3).getValues() != Week_1)
... I have created a variable declared previously such as:
var WeekLOOP = DynamicSheet.getRange(i,3).getValues();
while(WeekLOOP != Week_1) { --- }
... and now the script needs few milliseconds to run the condition. I don't have enough technical knowledge to say if this was the only issue, but is what apparently solved my problem.
Thanks to all for the support! Will come back if I need any further help :)
As was mentioned by Amit Agarwal, to solve the error message mentioned on the question, refresh the web browser tab.
Regarding the code,
On
var Week_1 = StaticSheet.getRange(2,4).getValues();
and
DynamicSheet.getRange(i,3).getValues()
instead of getValues you should use getValue because your code are referring to single cell cells otherwise you will be getting 2D arrays instead of scalar values.
The use of while should be made very carefully to avoid functions running endlessly. You could add some "safeguard" like the following
var max_iterations = 100 // Edit this
while(DynamicSheet.getRange(i,3).getValue() != Week_1 && i <= max_iterations) {

Free Code Camp weather app, toggle won't work

Here is my Javascript code.
$("#changetemp").click(function () {
var temp = $("#temperature").html;
var final_letter = temp[temp.length-1];
$("#temperature").html(function ()
{if (final_letter == "F") {return celsius;}
else {return fahrenheit;}});});
});}});});
It is supposed to toggle the temperature between celsius and fahrenheit but does a big fat nothing. I've googled and changed a few things (e.g. gone between val, html and text, and tried charAt but I can't get it to do anything, let alone the right thing. Any suggestions would be very welcome.
Edit: "#changetemp" is the button you click to toggle between temperature (ideally).
"#temperature" is where the temperature displays (and it does, but then won't change).
Also tried:
console.log(final_letter); (which gave the correct letter in the console)
console.log(celsius); (which reports as 'undefined') as does console.log(fahrenheit);
These two are defined earlier via a JSON
$.getJSON( url, function(location){ var celsius =
$("#temperature").html(Math.round(location.main.temp - 273) + "°C");});
and I tried to make them be global variables by putting
var celsius;
var fahrenheit;
after the beginning of the first function (which surrounds everything else) but I'm guessing that didn't work.
More:
Googling suggests that variables cannot begin with a number. Is this what is stopping me here?
1. I've managed to show the temperature though, just not change it.
2. How do you get round that? I tried changing the code so that 'celsius' would give 'Temperature: 10C' rather than '10C' but that didn't solve it.
i assume the error is in the line var temp = $("#temperature").html;
Does it help if you change it to var temp = $("#temperature").html();?
html is a jQuery function, so you need to call it with the parantheses. Otherwise temp will not contain the content of the #temp element, but rather a reference to the html method. Therefore you don't get the last letter of the content.

Problems with onclick / calculating a sum

Let me start by saying, that while I have some programming experiencing (some basic C from a college class and I once wrote a FORTRAN programm in college for a professor), I am utterly new to JS and beginning to get a bit frustrated.
For some reason, even after reading tutorials and watching several YouTube videos on objects, I seem unable to wrap my head around it. I understand the fundamentals and have no problems doing very basic stuff, like writing a loop that prints out increments on a HTML site, but every time I try something practical, I am completely at a loss.
Here is my current problem: I have created this HTML site that generates a shopping list. Basically, when I click on one of the buttons next to an item name, it adds that item to the list in the middle of my screen. Thanks to Google I found a piece of JavaScript code which, through try and error, I managed to tweak for this purpose:
<!-- click this button to add the item-->
<button onclick="myFunction('ITEM1', 100)" class="sidebarbuttons" >ITEM1 </button>
/* Create a List one line at a time- */
<script>
function myFunction( x, y ) {
var node = document.createElement("LI" );
var textnode = document.createTextNode(x);
node.appendChild(textnode);
document.getElementById("myList").appendChild(node);
}
</script>
So far, so good. Now I want to get the net price for all the items. Which means, When I click the button, I want a function to add the price of that item to a variable and then display that variable in a field with
document.getElementById("result").innerHTML = total_sum;
Here's my question: how, oh my god, how do I do this? I thought I could add the following:
function myfunction(x,y){
var sum = 0;
var sum+=y;
}
document.getElementById("result").innerHTML = 'sum';
Obviously, this doesn't work at all. Can you please give me some hints what I have to do to make this work?
First of all,
please consider to study JavaScript better, because it's a falsy easy programming language and it's very dangerous to copy&paste without knowing the language. It's quite normal to read a lot, watch a lot and don't know where to start, and it's the main reason because people hates JavaScript: because we don't know well JavaScript. So consider to read the book series "You Don't Know" by Kyle Simpson.
About your question. You can add a variable to storage the sum of your items and when you click to an item, you can add to it:
var total_sum = 0;
function myFunction( x, y ) {
var node = document.createElement("LI" );
var textnode = document.createTextNode(x);
node.appendChild(textnode);
document.getElementById("myList").appendChild(node);
showResults(y);
}
function showResults(price){
total_sum += parseFloat(price)
document.getElementById("result").innerHTML = total_sum;
}
JSBIN
Let me know ;)
So you are on the right track. Picking up where you left off in your last code block, there are few things you will need to change.
//declare the variable outside of the function... otherwise it will only be available to you within that function.
var totalSum = 0;
// then within your function you will be able to successfully add to the global totalSum variable
function calculateSum(x){
totalSum += x;
// and lastly... set the innerHTML within the function... which should equal the variable totalSum
document.getElementById("result").innerHTML = totalSum;
}
Hope this helps.

Javascript document.getElementsByName() function is being weird at me

I've got the following variables in my simple javascript calculator:
var distance = parseInt(document.getElementsByName("distance"), 10);
var mins_running = parseInt(document.getElementsByName("mins_running").value, 10); // the running pace minutes
var secs_running = parseInt(document.getElementsByName("secs_running").value, 10); // the running pace seconds
var mins_walking = parseInt(document.getElementsByName("mins_walking").value, 10); // the walking pace minutes
var secs_walking = parseInt(document.getElementsByName("secs_walking").value, 10); // the walking pace seconds
The problem is, when I try to use these variables (entered as text from a form but meant to be used as numbers in the calculator). When I do a typeof() in the developer console.log I'm told the values are of type 'number', but the very next line is also a console.log('mins_running'), for example, and it explicitly states the value is "NaN". Is my value a number or not? What's going on? Stupid javascript--be more normal, darn it!
Any reasonable input/help will be appreciated.
Thanks for all the help, guys. Looks like I'm back to using the old Form.elementName.value thing instead. (if this is a really bad idea or just not good for production code at all, please feel free to say something.)
document.getElementsByName("mins_running")
returns a NodeList, which has no attribute value. Use
document.getElementsByName("mins_running")[0].value
instead.
Example:
HTML:
<input type="text" name="mins_running" value="10">
<br><button id="theButton">Click Me</button>
JavaScript:
document.getElementById("theButton").onclick = function() {
// Note we're getting the first match ----------------vvv
var field = document.getElementsByName("mins_running")[0];
display("The field's current value is: " +
parseInt(field.value, 10));
// And using its value-^^^^^
};
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
Live Copy | Source
Waleed shared how to fix it.
The technical reason why you got NaN there is...
You grab a reference to a NodeList with document.getElementsByName("distance"), and you attempt to access the property value on that. That property does not exist on NodeList, or anywhere on the prototype chain. In JavaScript, that means undefined is returned.
When you call parseInt() with undefined as the first argument, the function will toString() it and return "undefined". You explicitly set the base as 10, which obviously only covers digits 0 to 9, and the number can't be parsed. When this happens, parseInt() returns NaN. Since NaN is of the Number type (it's part of the IEEE-754 specification), the typeof operator tells you it's a "Number".
If you'd set the base as 31, it'd be able to parse "undefined", and it'd be 26231474015353 :)
Set ids for your tags and use getElementById instead.

Categories