JavaScript JavaScript Loops, Arrays and Objects Tracking Data Using Objects The Student Record Search Challenge Solution

James Croxford
James Croxford
11,346 Points

My solutions to the extension problems (critique please!) and help on a function to check for empty strings on prompt()?

Working on extension 1:

Idea 1: counter

Declare a counter variable named 'counter' in the global scope of student-report.js along with the other global variables.

Currently, within the while-loop, the for-loop creates an i-th array (called student) for each object inside of the students array. It then checks the value of 'searchResponse' against the name element in each student array.

Presently if the submitted name is matched on the database, then a message is generated using the getStudentReport function, and printed to the screen. The for-loop runs through its code block whilst i is less than the length of the students array.

We could therefore piggyback off this by incrementing the counter variable by 1 if a match is found. This will obviously increment multiple times if multiple matches are found in the database.

We then create a separate if statement in the while-loop, but outside of the for-loop scope, which checks if the value of counter is equivalent to 0. If it is (meaning zero instances of the searched name were found) then an alert box is put to the screen to indicate so.

Working on extension two:

idea 1: message = '';

Similar bug to the message counter- needed to be reset on each passing of the while loop to clear the screen.

let message = ``;
let student;
let searchResponse;
let counter = 0;

//standard print function using getElementById
function print(message) {
  var outputDiv = document.getElementById('output');
  outputDiv.innerHTML = message;
}

//Seperates out the look and contents of the report/screen print out for modularity. Creates a variable (let) which does not exist outside of the function scope.
function getStudentReport(student) {
   let report = `<h2>Student: ${student['name']}</h2>
                  <p>Track: ${student['track']}</p>
                  <p>Points: ${student['points']}</p>
                  <p>Achievements: ${student['achievements']}'</p>`;
  return report;
}

/*Main logic block.
While (true) means that the loop continuously runs unless the break clause is triggered via typing quit or hitting cancel on the window.
if conditional has two clauses inside of it, to include the possibility that the user could exit the program by hitting cancel on the dialog box.
Hitting cancel returns a null value. It actually represents no value.Because it's not a string, we can't use the toLowerCase method on it. 
This checks to see if the value returned by the prompt method and stored in the search variable is null.*/
while (true) {
//reset both message and variable here to ensure alerts and screen prints function correctly.
  message = ``;
  counter = 0;
  searchResponse = prompt("To search the student records database, type a name into this box. If you want to exit the program, type 'quit'."); 
  if ( searchResponse === null || searchResponse.toLowerCase() === 'quit' ) {
    break; 
  }
  for (let i = 0; i < students.length; i += 1) {
    student = students[i];
    if (student.name.toLowerCase() === searchResponse.toLowerCase()) {
      //calls on the report function when assigning a value to the message variable.
      message += getStudentReport(student);
            //message is incremented with further callings of the function in case of multiple hits of the same name
      counter += 1;
            //value of counter incremented if one or more matches of the name are found.
            //If the value is zero, this indicates name isn't in the array, so the user is informed using the conditional statment below.
    }
  }
  if (counter === 0 ) {
    alert(`The name '${searchResponse}' was not found within the database. Please try another name, or to exit the program, type 'quit'`);
  }
//note the location outside of the for-loop to ensure that this message appears the appropriate number of times
//i.e. once for the entire array if the name isn't found within individual objects, rather than multiple times (even if the name is found within one)
  print(message);
}

//extension 1: message should be provided if a student is not found in the records.
// string validation
//extension 2: if there is more than one student with the same first name, then only the records of the person furthest down the array will be printed.
//How can we find and print all instances of that person sharing the same name to the screen when a search is conducted?

There's the entire code base above.

I've also gone further to try and warn the user when they enter an empty string into the prompt given searchResponse. I've created a validation function as seen below, which is causing a serious of bugs. Here's a sample of the code:

function searchResponseValidation(response) {
 while (searchResponse === '')
 alert(`No name was entered into the search box. Please type a name into the box to check it against the student database, or alternatively type 'quit' to exit the program.`);
  searchResponse = prompt("To search the student records database, type a name into this box. If you want to exit the program, type 'quit'."); 
}

while (true) {
  message = ``;
  counter = 0;
  searchResponse = prompt("To search the student records database, type a name into this box. If you want to exit the program, type 'quit'."); 
  searchResponseValidation(searchResponse);
  if ( searchResponse === null || searchResponse.toLowerCase() === 'quit' ) {
    break; 
  }
  for (let i = 0; i < students.length; i += 1) {
    student = students[i];
    if (student.name.toLowerCase() === searchResponse.toLowerCase()) {
      message += getStudentReport(student);
            //message is incremented with further callings of the function in case of multiple hits of the same name
      counter += 1;
    }
  }
  if (counter === 0 ) {
    alert(`The name '${searchResponse}' was not found within the database. Please try another name, or to exit the program, type 'quit'`);
  }
  print(message);
}

BUG- when entering an empty string (i.e. pressing enter/okay on the prompt box), the alert message in searchResponseValidation appears, and does not disappear.

BUG- if a name not on the database is entered, no warning is presented to the user. Only the second consecutive entry of a falsy value brings up the warning (e.g. "The name 'jghjhghjg' was not found within the database. Please try another name, or to exit the program, type 'quit'").

BUG- typing in a name present in the database straight away prints nothing to the screen. Entering that name again (or another name present in the database) then prints the information about that pupil to the screen. This pattern carries on when entering correct names into the prompt box- it takes two entries of names for the information to be printed to the screen.

Finally a snapshot of the workspace. https://w.trhou.se/dh7emeiis6 Any ideas how to address this?

3 Answers

Steven Parker
Steven Parker
201,932 Points

All the bugs seem to be related to the "searchResponseValidation" function.

The body of the "while" loop on line 22 is just the "alert" call on line 23. Since it doesn't do anything to change the loop condition, the loop continues indefinitely.

The function always performs a "prompt" (line 24) identical to the one in the main loop, and then overwrites the answer from the main prompt with the new answer. So the question is always asked twice, and the first answer is discarded.

Suggested fix (unused parameter also removed):

function searchResponseValidation() {
  while (searchResponse === '')
    searchResponse = prompt(`No name was entered into the search box!
Please type a name into the box to check it against the student database,\
 or alternatively type 'quit' to exit the program.`);
}
James Croxford
James Croxford
11,346 Points

Thanks for the response & the fix!

So what I don't understand is from my original code:

function searchResponseValidation(response) {
 while (searchResponse === '')
 alert(`No name was entered into the search box. Please type a name into the box to check it against the student database, or alternatively type 'quit' to exit the program.`);
  searchResponse = prompt("To search the student records database, type a name into this box. If you want to exit the program, type 'quit'."); 
}

To yours:

function searchResponseValidation() {
  while (searchResponse === '')
    searchResponse = prompt(`No name was entered into the search box!
Please type a name into the box to check it against the student database,\
 or alternatively type 'quit' to exit the program.`);
}

Is that in mine, although the alert() method doesn't do anything to change the loop condition, after the alert() method runs and prints to the screen, then the prompt method comes up (like in yours). To my eyes, my solution is only adding an additional step (the alert() method, which is redundant as you've shown, as the message could be incorporated into the prompt below), but then follows the same path as yours?

Steven Parker
Steven Parker
201,932 Points

Combining the alert and prompt causes the prompt to be done in the loop. Previously the loop only included the alert.

James Croxford
James Croxford
11,346 Points

I'm with you now! It only just clicked that I never put curly braces after the while loop to create the while loop.

This meant that in the case where the user entered ANY text in the original searchResponse prompt (inside of the main logic block), the program would call searchResponseValidation, the while condition would be false, with the alert ignored, and prompt for a name again with the same message. This would set the value of searchResponse a second time (be it empty string or a valid value). The program would then drop out of the function searchResponseValidation regardless of the searchResponse value and continue through the main logic block of the program.

This is also why the entry of a valid name in the database (the same one twice or two different ones) would work, but only on the second attempt- the prompt searchResponseValidation would overwrite whatever was entered in the first place before exiting the function searchResponseValidation and heading back into the main logic block of the program.

Likewise if the user entered nothing when originally prompted, the program would get caught in a endless loop of alert messages with no way to escape the while loop, as the alert method can do nothing to change said conditional statement. Also by changing the prompt method text inside the function searchResponseValidation it's less involvement for the user, and would have made the debugging arguably easier to work out where the prompts where originating from.

Thanks for the help!