Array.push causes program to have errors - javascript

I followed the advice from a previous question to get my promps to add values to an array, but it has caused my program to throw up True values when they are not.
HIGHEST_GRADE = 7;
LOWEST_GRADE = 0;
var course = new Array();
var grade = new Array();
while(confirm("Would you like to add a course?")){
course.push( prompt("Enter the course code. Example - ABC1234") );
};
var upperTest = course.slice(0,3);
var integerTest = course.slice(4,7);
if (course.length !== 7) {
alert ('Invalid Course Code');
}
if (upperTest !== upperTest.toUpperCase()) {
alert ('Invalid Course Code');
}
if (isNaN(integerTest)) {
alert('Invalid Course Code');
}
if (isNaN(grade)) {
alert('Invalid Grade');
}
if (LOWEST_GRADE > grade || HIGHEST_GRADE < grade) {
alert('Invalid Grade');
}
I have it set to make sure the entered text matches the conditions, but since the .push was added the whole thing stuffs up.
I get an Invalid Course Code error, something is playing up with that.

The Array is used to store multiple courses, which is fine. But, since it's an array, you need to access each position of it to validate each individual course, using a loop:
var courses = new Array(); // use the name courses instead, to indicate that it's a collection
for (var i = 0; i < courses.length; i++) {
var course = courses[i];
var upperTest = course.slice(0,3);
var integerTest = course.slice(4,7);
if (course.length !== 7) {
alert ('Invalid Course Code');
}
if (upperTest !== upperTest.toUpperCase()) {
alert ('Invalid Course Code');
}
if (isNaN(integerTest)) {
alert('Invalid Course Code');
}
}
This will validate every course that is in the Array. Otherwise, when you test courses.length, you'll be validating the number of elements in the array, not the number of characters of each course.
The same needs to be done for the grades array.

Do you want to validate entered course code? In such case you need to do it with the item not with the whole array:
while (confirm("...")) {
var courseCode = prompt("...");
var upperTest = course.slice(0,3);
var integerTest = course.slice(4,7);
if (courseCode.length !== 7) {
alert ('Invalid Course Code');
continue;
}
// place your other if's here
courses.push(courseCode);
}

Related

Can anyone please show me how to use the .push() method for an array?

Ask the user to input names of people they would like to invite to a dinner party.
Each name should be added to an array.
The user can only invite a maximum of ten people. If they try to add more than 10 names, the program should state, “You have already added 10 people to your guest list.”
The program should then output the list.
I am trying to solve this task, I am not sure if I am doing it properly. I am a beginner so I will appreciate any help or hints.
{
let list = [];
list.length = 10
while(true){
let input = prompt("Add a guest");
if(input <= 10 || input == null){
break; //arr.slice(0,10)
}
list.push(String(input));
console.log(list);
}
}
Loop through; if the user inputs nothing I assume they are "done" - not stated in the requirements how to manage this.
I put this in a function to call passing the max count but that was not specifically stated here in the requirements.
Just loop until the conditions are met.
function addGuests(maxGuests = 10) {
const tooMany = "You have already added 10 people to your guest list.";
const promptText = "Add a guest";
let list = [];
let hasGuest = true;
while (list.length < maxGuests && hasGuest) {
let guests = prompt(promptText);
if (guests != null && guests.trim().length > 0) {
list.push(String(guests));
console.log("L:", list);
} else {
hasGuest = false;
}
if (list.length >= maxGuests) {
alert(tooMany);
}
}
return list;
}
let guests = addGuests(10);
console.log(guests, guests.length);
Try something like:
const readLineSync = require('readline-sync');
const arr = [];
while (arr.length < 10) {
const guest = readLineSync.question('Add a guest: ');
if (guest) {
arr.push(guest);
}
}
console.log('You have added 10 people...');
console.log(arr);
This uses the readline-sync module to get input from the user, starts off with an empty array and keeps pushing non-empty input values to it until the length of that array is 10. It then prints out the items in the array to the console.

JS Outer scoped variable

I have been working on and off on a game app based on the game show Countdown. So far I have been able to get the user to choose vowels and consonants and input a word which checks to see if the word that was entered contains the same letters that were generated. I have created an anonymous function which uses jQuery to check a dictionary text file to see if it is listed. However I'm running into trouble, I keep getting a warning message "functions declared within loops referencing an outer scoped variable may lead to confusing semantics."
I'm not sure what I'm doing wrong, please see code below:
$(".submission").hide();
//assigning letter container class to variable
var letterContainer = document.querySelector(".letter-container");
function pickFrom(letters) {
// if the length of the letter container is less than 8
if (letterContainer.innerHTML.length < 8) {
//add letters to the letter container
letterContainer.innerHTML += rando(letters);
}
//once letter container length reaches 8
if (letterContainer.innerHTML.length === 8) {
//show submission input and button
$(".submission").show();
//remove letter buttons after 8 letters have been chosen by user
$(".letter-btn").hide();
//assign given letters from letter container to a variable
var givenLetters = letterContainer.innerHTML.split("");
var inputWord = document.querySelector(".enter-word").value;
document.querySelector(".submit-word").addEventListener("click", function() {
var inputWord = document.querySelector(".enter-word").value.split("");
if (inputWord.length <= 8) {
//
var isValid;
for (var i = 0; i < inputWord.length; i++) {
// console.log(inputWord[i]);
if (givenLetters.includes(inputWord[i])) {
var indexPosition = givenLetters.indexOf(inputWord[i]);
givenLetters.splice(indexPosition, 1);
var newWord = inputWord.join("").toLowerCase();
$.get("https://raw.githubusercontent.com/cpog19901/Countdown/master/text/english3.txt", function(contents) {
//contents variable now contains the contents of the textfile as string
//check if file contains the word entered by user
var hasString = contents.includes(newWord);
//outputs true if contained, else false
console.log(hasString);
});
isValid = true;
} else {
console.log(inputWord[i]);
console.log("no");
isValid = false;
}
}
if (isValid == true) {
console.log("This is a valid word");
}
else if (isValid == false) {
console.log("This is NOT a valid word");
}
}
});
}
}
I need all statements to be true including the anonymous function so it will let the user know it's a valid word.
The error message indicates to look out for for-loops. I found this one:
for (var i = 0; i < inputWord.length; i++) {
/* … */
$.get("https://raw.githubusercontent.com/cpog19901/Countdown/master/text/english3.txt", function(contents) {
/* … */
}
/* … */
}
This AJAX call is made every single iteration of the loop (assuming the surrounding if is true).
Instead, you could do it earlier and store the results in a variable.

using multiple nested if statement in javascript

Its my understanding that you can stack multiple nested if statements so that you can validate a users input on a form. I have tried to combine two nested if statements so that I can check a users input for multiple fields such as freight and mileage used when they submit but it only goes through the first nested if statement for mileage? Is there a better method to write a script to accomplish this kind of task? The code I have been working with is below. My goal is to have a message alert the user that they have not entered any mileage information for their out of town trip and/or have it alert them they included parts and ask if they ordered them to put the freight info in the freight field. if neither issue exists, I want it to drop out of the if statements and lock the form minus the customer's signature.
test = this.getField("City").value;
test1 = test.toUpperCase();
if (test1.indexOf("HOBBS") == -1) {
if (this.getField("MileageTotal").value === 0) {
app.alert("You have not listed any mileage for this trip.\n\n Please add mileage information for trips outside of the city.", 3, 0, "Trip Mileage Missing");
app.alert(this.getField("MileageTotal").value);
}
} else if (this.getField("TotalParts").value > 0 ){
if(this.getField("Freight").value === 0) {
result = app.alert("You have indicated that you have used parts on this job. \n Were any of these parts ordered?", 2, 2, "No Freight Entered");
}
} else {
for (var i = 0; i < this.numFields; i++){
var fname = this.getNthFieldName(i);
this.getField(fname).readonly = true;
} // makes all fields readonly
var f = this.getField("TechSigDate");
f.value = util.printd("mmm/d/yyyy", new Date());
this.getField("Customer Signature").readonly = false;
this.getField("LockCustomer").readonly = false;
this.getField("Lock Form").display = display.hidden;
}
I appreciate all of the advice you all are giving. I attempted to combine the statements and use an && instead. This works great for the mileage however it skips the freight validation and goes straight to locking the form. I attempted to set it to be true if TotalParts is grater than 0 and Freight is 0. Am I doing the && statements incorrectly?
test = this.getField("City").value;
test1 = test.toUpperCase();
if (test1.indexOf("HOBBS") == -1 && this.getField("MileageTotal").value === 0) {
app.alert("You have not listed any mileage for this trip.\n\n Please add mileage information for trips outside of the city.", 3, 0, "Trip Mileage Missing");
app.alert(this.getField("MileageTotal").value);
}
if (this.getField("TotalParts").value > 0 &&this.getField("Freight").value === 0){
result = app.alert("You have indicated that you have used parts on this job. \n Were any of these parts ordered?", 2, 2, "No Freight Entered");
} else {
for (var i = 0; i < this.numFields; i++){
var fname = this.getNthFieldName(i);
this.getField(fname).readonly = true;
} // makes all fields readonly
var f = this.getField("TechSigDate");
f.value = util.printd("mmm/d/yyyy", new Date());
this.getField("Customer Signature").readonly = false;
this.getField("LockCustomer").readonly = false;
this.getField("Lock Form").display = display.hidden;
}
I would always show all problems.
It's annoying to the user to have to fix them all one by one.
test = this.getField("City").value;
test1 = test.toUpperCase();
alerts = []
if (test1.indexOf("HOBBS") === -1 && this.getField("MileageTotal").value === 0) {
alerts.push("You have not listed any mileage for this trip.\n\n Please add mileage information for trips outside of the city.", 3, 0, "Trip Mileage Missing");
alerts.push(this.getField("MileageTotal").value);
}
}
if (this.getField("TotalParts").value > 0 && this.getField("Freight").value === 0) {
alerts.push("You have indicated that you have used parts on this job. \n Were any of these parts ordered?", 2, 2, "No Freight Entered");
}
}
if (alerts.length === 0) {
this.numFields.forEach((files, index) => {
var fname = this.getNthFieldName(index);
this.getField(fname).readonly = true;
}) // makes all fields readonly
var f = this.getField("TechSigDate");
f.value = util.printd("mmm/d/yyyy", new Date());
this.getField("Customer Signature").readonly = false;
this.getField("LockCustomer").readonly = false;
this.getField("Lock Form").display = display.hidden;
} else {
// Maybe you can also do alerts.forEach(app.alert)
alerts.forEach(alert => app.alert)
}
If you want to check both if statements, get rid of the 'else'. This does not appear to be an exclusionary situation, e.g. freight and mileage are possible, yes?

Javascript if value is in array else in next array

I have found a few posts on here with similar questions but not entirely the same as what I am trying. I am currently using a simple if statement that checks the data the user enters then checks to see if it starts with a number of different values. I am doing this with the following:
var value = string;
var value = value.toLowerCase();
country = "NONE";
county = "NONE";
if (value.indexOf('ba1 ') == 0 || value.indexOf('ba2 ') == 0 || value.indexOf('ba3 ') == 0) { //CHECK AVON (MAINLAND UK) UK.AVON
country = "UK";
county = "UK.AVON";
} else if(value.indexOf('lu') == 0){//CHECK BEDFORDSHIRE (MAINLAND UK) UK.BEDS
country = "UK";
county = "UK.BEDS";
}
I have about 20-30 different if, else statements that are basically checking the post code entered and finding the county associated. However some of these if statements are incredibly long so I would like to store the values inside an array and then in the if statement simply check value.indexOf() for each of the array values.
So in the above example I would have an array as follows for the statement:
var avon = new Array('ba1 ','ba 2','ba3 ');
then inside the indexOf() use each value
Would this be possible with minimal script or am I going to need to make a function for this to work? I am ideally wanting to keep the array inside the if statement instead of querying for each array value.
You can use the some Array method (though you might need to shim it for legacy environments):
var value = string.toLowerCase(),
country = "NONE",
county = "NONE";
if (['ba1 ','ba 2','ba3 '].some(function(str) {
return value.slice(0, str.length) === str;
})) {
country = "UK";
county = "UK.AVON";
}
(using a more performant How to check if a string "StartsWith" another string? implementation also)
For an even shorter condition, you might also resort to regex (anchor and alternation):
if (/^ba(1 | 2|3 )/i.test(string)) { … }
No, it doesn’t exist, but you can make a function to do just that:
function containsAny(string, substrings) {
for(var i = 0; i < substrings.length; i++) {
if(string.indexOf(substrings[i]) !== -1) {
return true;
}
}
return false;
}
Alternatively, there’s a regular expression:
/ba[123] /.test(value)
My recomendation is to rethink your approach and use regular expressions instead of indexOf.
But if you really need it, you can use the following method:
function checkStart(value, acceptableStarts){
for (var i=0; i<acceptableStarts.length; i++) {
if (value.indexOf(acceptableStarts[i]) == 0) {
return true;
}
}
return false;
}
Your previous usage turns into:
if (checkStart(value, ['ba1', ba2 ', 'ba3'])) {
country = 'UK';
}
Even better you can generalize stuff, like this:
var countryPrefixes = {
'UK' : ['ba1','ba2 ', 'ba3'],
'FR' : ['fa2','fa2']
}
for (var key in countryPrefixes) {
if (checkStart(value, countryPrefixes[key]) {
country = key;
}
}
I'd forget using hard-coded logic for this, and just use data:
var countyMapping = {
'BA1': 'UK.AVON',
'BA2': 'UK.AVON',
'BA3': 'UK.AVON',
'LU': 'UK.BEDS',
...
};
Take successive characters off the right hand side of the postcode and do a trivial lookup in the table until you get a match. Four or so lines of code ought to do it:
function getCounty(str) {
while (str.length) {
var res = countyMapping[str];
if (res !== undefined) return res;
str = str.slice(0, -1);
}
}
I'd suggest normalising your strings first to ensure that the space between the two halves of the postcode is present and in the right place.
For extra bonus points, get the table out of a database so you don't have to modify your code when Scotland gets thrown out of leaves the UK ;-)

How can i know its valid in JS?

I am developing an Adobe interactive form with LiveCycle LC designer with JavaScript.
// Identify required fields (it may be a free text field, drop-down, check box, i mean there 3 kinds possibilties) and make yellow colored them
var myArrayYellow = new Array();
var yellowFields;
yellowFields = my_required_fields_list_string.rawValue
myArrayYellow = yellowFields.split(" ");
for (var i = 0; i < myArrayYellow.length; i++) {
===> Here at this point, i want to check the existence of [i] field in the form that its a valid field/objetc or not? bcz, i have chances of getting non-existing fields in the my_required_fields_list_string, hence prior to assigning yellow color to them, i want to check their validity on the form or not? Pls. let me know the JS for this // if its true/found, then only assign yellow color as below
xfa.resolveNode("MY_ADOBE_FORM.." + myArrayYellow [i]).ui.oneOfChild.border.fill.color.value = "255,255,254"
};
For some other purpose, some expert gave me a JS as below, i tried to tune it as per my above requirement, but its not working
function findNodes(vNode){
if (vNode.className === "field"){
if (vNode.isPropertySpecified("name") === true){
var myStateName = new RegExp(vNode.name);
var returnValue = GFL.search(myStateName);
if (returnValue != -1) {
this.ui.oneOfChild.border.fill.color.value = "192,192,192";
this.access = "readOnly";
} else {
this.ui.oneOfChild.border.fill.color.value = "255,255,255"; //whatever colour is open access
this.access = "open";
}
}
}
for (var a=0;a<vNode.nodes.length;a++) {
findNodes(vNode.nodes.item(a));
}
}
findNodes(xfa.form);
if I understand your problem, you need to check if xfa.resolveNode returns something and handle it from there.
var node;
if ( (node=xfa.resolveNode("MY_ADOBE_FORM.." + myArrayYellow[i]) )!==null){
node.ui.oneOfChild.border.fill.color.value = "255,255,254"
}
If I understand correctly, you are trying to check if all of your values in the array are valid before preforming operations on them. Just check and make sure they are not null.
EDIT: You should probably check for empty string as well.
for (var i = 0; i < myArrayYellow.length; i++) {
if (!(myArrayYellow[i] == null || myArrayYellow[i] == "")){
//Do Stuff
}
}

Categories