JavaScript project not writing to document - javascript

I'm new to JavaScript at school, and this project isn't doing what I want it to do. (which is the reason for these posts in the first place, right?)
The goal is to have the user enter words one at a time with prompt in a function called startMeUp(), which then stops prompting when the user enters an empty string. (that part works)
It's then supposed to refer to a function "processString" that turns the inputted strings into an array, checks the length of each word in the array, and turns it uppercase if < 4 letters or lowercase if >= 4.
Finally, it's supposed to "return the converted string to a variable in the calling function startMeUp, and display the value using document.write"
I thought i was doing it correctly, but nothing is writing to the page, so i'm not sure where i've gone wrong. I've included the code below:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Exercise 2</title>
<script language="JavaScript" type="text/JavaScript">
//************************
// Main start-up function
// Invoked from the onload event
var someInput;
var someArray;
var someFinalString;
function startMeUp() {
do{
someInput = prompt("Enter a word");
}
while(someInput.length > 0);
processString(someInput);
document.write(someFinalString);
}
function processString(someInput){
//split the input string into a JavaScript array
someArray = someInput.split(" ");
//use a for loop to examine every word
for(i = 0; someArray[x]; i++)
{
if(someArray[i].length < 4)
{
someArray[i].toUpperCase();
}
if(someArray[i].length >= 4)
{
someArray[i].toLowerCase();
}
someFinalString = someArray.join(" ");
}
}
</script>
</head>
<body onload="startMeUp();">
</body>
</html>

Here is a working example of desire behavior.
function start() {
var input = "";
var str = "";
do {
input = prompt("Enter a word");
str += input + " ";
} while (input);
document.write(proccessStr(str));
}
function proccessStr (str) {
var arr = str.split(" ");
for (var i = 0; i < arr.length; i++) {
if (arr[i].length < 4)
arr[i] = arr[i].toUpperCase();
else
arr[i] = arr[i].toLowerCase();
}
return arr.join(" ");
}
start();
Codepen: https://codepen.io/anon/pen/qXByby (jsfiddle does'nt support docuent.write).
Few problems with your code.
You are using global variables without no need, not good practice
You don't save the all input from the user, so always the last string is saved, and that the empty string, so actually you send an empty string to your other function.
When you use string methods on string, it does'nt change the value inside the variable, it just creates new one, you need to assign it to the variable that holds the value in order to change it.
If look at my example, I used return to return the value of the transformed string to the first function, no need of global.
though I used document.write , it's not good practice , consider write to an element innerHTML/Text

Related

Unusual browser error and advice on a Calculate Sum program for javaScript

So I have a problem for class:
Calculate Sums
Create a function called calculateSums that will accept an array of numbers, and return true if the sum of all the positive numbers is greater than or equal to the sum of the absolute value of all the negative numbers.
Method of completion
You should use a while loop in your solution.
It does not matter if you consider 0 a positive or negative number
because it will not change the sum of either side.
After your loop finishes, you should simply return whether the sum of
positive numbers is greater than or equal to the sum of negative
numbers.
It should be possible to call the function as follows:
calculateSums([-1,2]) returns true
calculateSums([-1,2,-3]) returns false
In your code, call your function several times and display the arrays used and the result on your HTML page.
I am having trouble figuring out how to use a while loop to do this. I have one, but it's not right. I am also trying to display the result using "document.getElementByID("message").innerHTML..." and I am getting an error I don't understand.
Here is my code:
/**
* This function calculates the absolute sum of an array of numbers
* #inputs a - an array of numbers
* #returns compare - a boolean
*/
function calculateSum(a) {
//declare variables and set them equal to 0.
var result = 0;
var possum = 0;
var negsum = 0;
var compare;
while (possum >= negsum) {
for (var i = 0; i < a.length; i++) {
var num = a[i];
result = result + Math.abs(num);
if (num%2 == 0) {
possum += result;
} else {
negsum += result;
}
result = 0;
}
if (negsum > possum) {
compare = false;
break;
} else {
compare = true;
break;
}
}
if (compare == true) {
document.getElementById("message").innerHTML = compare;
} else {
document.getElementById("message").innerHTML = compare;
}
return compare;
}
Here is my HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Calculate Sums</title>
<script src = "assignment3.js"></script>
</head>
<body>
<script>
calculateSum([-1,2,3,-2]);
calculateSum([-3,1,-5,2]);
</script>
<p id = "message"></p>
</body>
</html>
I would love someone to help understand the error and offer suggestions of a better way to do this.
Here is the error in the browser:
Uncaught TypeError: Cannot set property 'innerHTML' of null
at calculateSum (assignment3.js:34)
at calculateSums.html:12
I am still very new to coding, so I am often times finding myself frustrated. I really appreciate the help I've found on this site.
Update: I figured out how to fix the while statement.
while (possum >= negsum || negsum > possum)
I'm not sure this is exactly how my teacher imagined it being done because we also have these acceptance criteria:
Calculate Sums
Your code must include a function called calculateSums that accepts
an array of numbers and includes a return statement
Your function must include a while loop.
Your code must use Math.abs() to get the absoluate value of any
negative numbers.
Your code must NOT include an infinite loop.
Your code must conditionally return true or false.
Your code must include multiple variations of tests to show your
function works.
The primary problem in your code is as follows:
When the browser receives the HTML markup in your code, it is processed from top to bottom.
So based on the coed you have shared the code executes in the following order:
The head section loads first as it is on the top. And consequently, your external script assignment3.js also gets loaded. (now the function in the script is available on the global namespace)
<head>
<meta charset="UTF-8" />
<title>Calculate Sums</title>
<script src = "assignment3.js"></script>
</head>
The browser then moves on to the body
<body>
<script>
calculateSum([-1,2,3,-2]);
calculateSum([-3,1,-5,2]);
</script>
<p id = "message"></p>
</body>
First, your script tag executes
<script>
calculateSum([-1,2,3,-2]);
calculateSum([-3,1,-5,2]);
</script>
This works well until this line in the calculateSum function
document.getElementById("message").innerHTML = compare;
Because, at this point, your browser has not gotten around to rendering the <p> tag (the script comes before and executes before this can happen). So document.getElementById("message") can't find the p tag and ends up returning nothing (null). And when you try to access a property on null, you get this error Cannot set property 'innerHTML' of null.
So to fix that, (and as a best practice in general) it's best to put your scripts at the end of the body tag like this (and not in the head):
<body>
<p id = "message"></p>
<script src = "assignment3.js"></script>
<script>
calculateSum([-1,2,3,-2]);
calculateSum([-3,1,-5,2]);
</script>
</body>
This ensures that your page load is not blocked by scripts and also has the side effect that the DOM will have been rendered and ready when your code executes.
Coming to your assignment problem specifically, you can use a while loop to iterate over the array and solve it in a simple manner.
Some change notes:
Move DOM manipulation out of the calculateSum method. This method now has a single clear purpose of calculating the sum and return either true or false.
Write a new function runTestCases which basically creates an array of arrays for the different tests we want to run and runs the calculateSum method for each. It also updates the DOM to reflect the result as stated in your problem statement.
Used while loop to iterate over the array in calculateSum
/**
* This function calculates the absolute sum of an array of numbers
* #inputs a - an array of numbers
* #returns compare - a boolean
*/
function calculateSum(a) {
//declare variables and set them equal to 0.
var result = 0;
var possum = 0;
var negsum = 0;
var currentIndex = 0;
while (currentIndex < a.length) {
var e = a[currentIndex++];
if (e < 0) {
// Negative number
negsum += Math.abs(e);
} else {
// Positive number
possum += e;
}
}
return possum >= negsum;
}
function runTestCases() {
// Array of test cases. (You can add or remove tests as needed)
var tests = [
[-1, 2],
[-1, 2, -3]
];
// Get reference of the list element to show the results
var ul = document.getElementById("result");
// Iterate over the tests aray and update dom to show each result
for (var i = 0; i < tests.length; i++) {
var test = tests[i]; // Get the current test case
var result = calculateSum(test); // Get the result
// Create a new DOM element to display the result
var li = document.createElement('li');
li.innerHTML = JSON.stringify(test) + " <b> " + result + "</b>";
//Appenf newly created element to the list
ul.append(li);
}
}
runTestCases();
<div>
<ul id="result"></ul>
</div>
Here is an answer that I think covers all the requirements:
function calculateSums(nums) {
var posSum = 0,
negSum = 0,
i = 0,
num;
while (i < nums.length) {
num = nums[i];
if (num < 0) {
negSum += Math.abs(num);
} else {
posSum += num;
}
++i;
}
return posSum >= negSum;
}
Uncaught TypeError: Cannot set property 'innerHTML' of null
at calculateSum (assignment3.js:34)
at calculateSums.html:12
You have to call the calculateSum() function after the p tag. It is trying to assign value before it is declare. Put your script before the tag.

Apps Script JS adding items to array from range (if not already in array) fails

I am looping through various cells and want to add their string content do an array, if the content is not already in the array. It works perfectly fine when I do it manually like so, trying to add 'eJobs' to the array (see below "var item = 'eJobs') which already containts 'eJobs':
var divisionarray = ['eJobs']
for (var i = 0; i < cells_users.length-1; ++i) {
var row_users = cells_users[i];
if (row_users[0] == user_ldap) {
var podarray = row_users[1].split(', ')
for (j = 0; j < podarray.length; j++) {
for (var k = 0; k < cells_edit.length; ++k) {
var row_edit = cells_edit[k]
if (podarray[j] === row_edit[0]) {
var item = 'eJobs'
if (!(divisionarray.indexOf(item) >= 0)) {
divisionarray.push(item)
}
}
}
}
Logger.log(divisionarray)
As expected, the log file shows [17-10-08 19:11:04:111 BST] [eJobs], illustrating that the code works and 'eJobs' has not been added to the array as it is already in the array.
Now, when I change var item='eJobs' to values of a range
var item = sheet_pods_edit.getRange(startRow+k, startColumn+1).getValue();
the code does not work anylonger, as the log file shows:
[17-10-08 19:14:03:770 BST] [eJobs, eJobs, BestJobs, Vivre Deco, ...
Note I have a range of thousands of cells, so I get alot of duplicates added. What am I missing? Note the cells of the defined range are indeed just strings with a single word (e.g. 'eJobs').
The code is working and the log file is indicating what the problem is..
[eJobs, eJobs, BestJobs, Vivre Deco,
In the second eJobs there is a white space before eJobs, so the first value and the second value don't match.
Without seeing your data and going by the 'just strings with a single word' I would say that using a .replace(" ", "") on the text string should work, this will find the first " " in the string and remove it. I.e. " eJobs" would become "eJobs".
2.
Is this line of code just for testing? You should never use a method like this in a script. It will be extremely inefficient
var item = sheet_pods_edit.getRange(startRow+k, startColumn+1).getValue();
Instead get the full range using .getValues()and iterate over it then.
3.
Is there a reason you are using === in if (podarray[j] === row_edit[0]) unless you need to check for type always use ==

For loop and getElementById

Hopefully an easy one, but I am having trouble printing out a number series from a for loop, back to the HTML. See below for my code, when I hit the button, it only returns 10, but not the rest of the numbers - where am I going wrong?
<!DOCTYPE html>
<html>
<body>
<button onclick="myFunction()">Try It</button>
<p id="number"></p>
<script>
function myFunction() {
for (i=0; i<11; i++) {
document.getElementById("number").innerHTML=i+"</br>";
}
}
</script>
</body>
</html>
You're replacing the element's contents on each loop. If you want to add to the contents, use += rather than = (as a minimal change):
document.getElementById("number").innerHTML+=i+"</br>";
// here -----------------------------------^
That said, I wouldn't do that, because it's making the browser do a lot of unnecessary work under the covers. Every time you read the value of innerHTML, the browser has to spin through the element and build up a string representing its contents; and every time you write to innerHTML, it has to parse the HTML, wipe out previous elements, and build new ones.
Instead, consider building up a string and doing one assignment:
function myFunction() {
var i, s = "";
for (i=0; i<11; i++) {
s += i + "<br>";
}
document.getElementById("number").innerHTML = s;
}
Side note 1: Your code is falling prey to The Horror of Implicit Globals because you're not declaring i. I've fixed that above by declaring it.
Side note 2: </br> is an invalid tag. In HTML, it's <br> (or <br/>; the ending / is entirely optional). In XHTML, it's <br/>.
document.getElementById("number").innerHTML=i+"</br>";
will replace the HTML of number, change it to
document.getElementById("number").innerHTML+=i+"</br>";// see the `+`
Setting .innerHTML with = completely changes its content.
Use += to append content.
document.getElementById("number").innerHTML += i + "</br>";
Since most of the other answers have shown you the error, here's an edit of your code that shows how you can get the result you want but without hitting the DOM with each iteration of the loop:
function myFunction() {
// create an array
var arr = [];
for (var i = 0; i < 11; i++) {
// push the data to the array
arr.push(i + '<br/>');
}
// grab the element and then add the joined array to the html
document.getElementById("number").innerHTML = arr.join('');
}
DEMO

String control in loops

I have a big question.
I have many Strings in my Programm and want to check these Strings on there values.
I wrote a Loop for it, but insted of the Definition of an String he is creating a new value. It's basicly really difficult to discribe, also because i am basicly German.
But i can give you my current code, so maybee you will see what I mean:
{
var Loch1G = $('#m1-Rundenanalyse-Datum').val(); //In the strings just the number is changing
var Loch2G = $('#m1-Rundenanalyse-Turnier').val();
x=1
while (x <= 2) {
if ("Loch" + x + "G" == ""){ //Next String is genrated (x=x+1)
alert("Eingabe war leer");
}
x=x+1
}
}
How can I solve this?
I'd suggest using an array to store the values you want to check:
var lochs = [];
lochs.push($('#m1-Rundenanalyse-Datum').val());
lochs.push($('#m1-Rundenanalyse-Turnier').val());
for (var i = 0, len = lochs.length; i < len; i++){
if (lochs[i] == ''){
alert("Eingabe war leer");
}
}
JS Fiddle demos: passes (no alert), fails (alert)
This suggestion is based on my presumption that you're trying to create the names of the vars you want to check, which won't work, whereas this approach lets you store all values (however many) in the same array and then iterate over that array to find any values that are equal to an empty string.
If you really want to stick with your current approach, you could do the following:
{
window.Loch1G = $('#m1-Rundenanalyse-Datum').val(); //In the strings just the number is changing
window.Loch2G = $('#m1-Rundenanalyse-Turnier').val();
var x=1;
while (x <= 2) {
if (window["Loch" + x + "G"] == ""){ //Next String is genrated (x=x+1)
alert("Eingabe war leer");
}
x=x+1;
}
}
But I can't think why you'd want to; plus the use of global variables is poor practice as it explicitly makes those variables available to every closure within the document, which allows them to be easily, and accidentally, overwritten.
In a reasonably up-to-date browser, that implements Array.prototype.every, you could dispense with the explicit iteration:
var lochs = [];
lochs.push($('#m1-Rundenanalyse-Datum').val());
lochs.push($('#m1-Rundenanalyse-Turnier').val());
if (!lochs.every(function(a){ return a !== ''; })) {
alert("Eingabe war leer");
}
JS Fiddle demos: passes (no alert), fails (alerts).

How do I correctly use an iteration value in JavaScript?

I am creating a 'simple' javaScript function which basically displays new information on the page when a user clicks next or previous.
The information is taken from an array and I want to use either i++ or i-- to call an element of the array.
Heres my JavaScript:
var titles = ["Dundalk", "Navan", "Drogheda", "Dublin"];
var i = 0;
function next()
{
i++;
if (i == titles.length)
{
i = 0;
}
var object = document.getElementById('tname');
object.innerHTML = titles[i];
}
function prev()
{
if (i == 0)
{
i = titles.length;
}
i--;
var object = document.getElementById('tname');
object.innerHTML = titles[i];
}
The problem is, when I run this code in my HTML page, I get an 'UNDEFINED' result. The JavaScript is not recognizing that i has been initialized as 0 in the beginning.
If i change titles[i] to titles[2], for example, the correct text is displayed in HTML.
What am I forgetting or how can I overcome this?
Thanks
The fact that you're seeing undefined indicates that you're accessing an array index which hasn't been set. Your code looks fine at a glance, so I would guess that there's some more code you're not showing which also uses i as a loop variable and leaves it set to a value > titles.length after the code above has run.

Categories