Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

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

My Xtra Credit Solution: Objects & Arrays

This does exactly what I want, but I'm open to feedback on better ways to accomplish the same results.

students.js

var students = [ 
  { 
    name: 'Dave',
    track: 'Front End Development',
    achievements: 158,
    points: 14730
  },
  {
    name: 'Jody',
    track: 'iOS Development with Swift',
    achievements: '175',
    points: '16375'
  },
  {
    name: 'Jody',
    track: 'HTML',
    achievements: '32',
    points: '3350'
  },
  {
    name: 'Jordan',
    track: 'PHP Development',
    achievements: '55',
    points: '2025'
  },
  {
    name: 'John',
    track: 'Learn WordPress',
    achievements: '40',
    points: '1950'
  },
  {
    name: 'Trish',
    track: 'Rails Development',
    achievements: '5',
    points: '350'
  }
];

student_report.js

var message = '';  // the message that will be printed to the page's HTML
var student; // a variable that contains the individual student record object while looping through the array "students"
var whichPrompt = "first"; // tracking which of three prompt phrasings should be used
var search; // a container for the results of the question prompt
var outputDiv = document.getElementById('output'); //The existing HTML in the output div

function print(message) {
    var previousMessage = outputDiv.innerHTML;
    outputDiv.innerHTML = previousMessage + " " + message;
}

//Formatting for each student report
function getStudentReport ( student ) {
    var report = '<h2>Student: ' + student.name + '</h2>';
    report += '<p>Track: ' + student.track + '</p>';
    report += '<p>Points: ' + student.points + '</p>';
    report += '<p>Achievements: ' + student.achievements + '</p>';
    return report;
}

/*
A search that loops through the data in the "students" array in student.js
At the beginning of a search, it clears the HTML in the output div
For each successful hit for a name, it adds the student info (via getStudentReport) to the HTML of the output div.
This search uses different prompts depending upon the result of the previous search
*/
while ( true ) {
  if (whichPrompt === "first") {
    var promptMessage = 'Search student records:\nType a name [Jody]\n(or type "quit" to end)';
  }
    else if (whichPrompt === "fail") {
    var promptMessage = 'There are no students with the name \"' + search + '\" in our records: \n \nType a name [Jody]\n(or type "quit" to end)';
    print('<h2>No matching records found for \"' + search + '\" </h2>');
    }
    else if (whichPrompt === "success"){
    var promptMessage = 'Search successfull. \nYou may search for another student, or type "quit" to end';
    }

  search = prompt(promptMessage);
  outputDiv.innerHTML = ""; //comment out this line to keep a running list of all returned search results

  if (search === null || search.toLowerCase() === 'quit') {
    whichPrompt = "first";
    break;
  }
  whichPrompt = "fail";
  for (var i = 0; i < students.length; i += 1) {
    student = students[i];
    if ( student.name.toLowerCase() === search.toLowerCase() ) {
      whichPrompt = "success";
      message = getStudentReport( student );
      print(message);
      }     
  }
}

Yes, this total works! good Job!

Just still can't get my head around the reason it outputs BOTH 'jody's correctly. Because, technically, wouldn't the for loop...

for (var i = 0; i < students.length; i += 1) {
    student = students[i];
    if ( student.name.toLowerCase() === search.toLowerCase() ) {
      whichPrompt = "success";
      message = getStudentReport( student );
      print(message);
      }     
  }

only spit out one name, then return to the beginning of the while loop, then go through the whichprompt if else statements, see its says success but then after that it hits...

whichPrompt = "fail";

At which point, wouldn't the for loop start over again? How does it know to continue the loop from where it left off? Is this just how loops work unless you explicitly tell it to restart? Or am I just totally mis-reading the code here and missing something...

EDIT: WAIT, I get it, its in your print function that allows the second output to be saved, so the for loop actually gets to save its previous content, loop the second item THEN it clears the outputDiv since the students array has finished meeting the conditions twice. So essentially, its this parts that allows it...

var outputDiv = document.getElementById('output'); //The existing HTML in the output div

function print(message) {
    var previousMessage = outputDiv.innerHTML;
    outputDiv.innerHTML = previousMessage + " " + message;
}

Very cool!

So basically, in the old version, where...

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

The outputDiv content keeps getting deleted on the loop, because message isn't saved.

Is that right? Either way, this has helped a ton! Thanks!

Alexandre Babeanu
Alexandre Babeanu
10,947 Points

What if three students have the same name? Seems like your code won't work... I'd use an array to store all the students with matching names. Then modify student report to loop through the array.

3 Answers

Hamilton Steele Yep - You got it!

For those still struggling: The way things were setup in the video's example has the print statement called after every instance a name is found. So if there are two names with the same spelling (e.g. two people named "Jody") then the print statement outputs to the same div each time, overwriting any earlier output, so you only ever see the last one.

I'm really glad some part of my solution was helpful to you.

Alexandre Babeanu This exercise was setup with the original data structure formatted as objects, so I kept it in that format (I think the point of this exercise was to learn how to loop through objects, but the tricky part was realizing that the output got borked by over-writing each print statement with the next). If you look at the records, you'll see that they DO INDEED have two students with the same (Jody) - and it works!

It loops through the objects, and if it finds the same name, it appends each successive name onto the printed information, rather than over-writing it.

Alexandre Babeanu
Alexandre Babeanu
10,947 Points

Yeah my bad... It totally works!

Here is my answer, I think it's better practice to leave the print function alone. Just added a reset, a plus and a test at the end.

var message;
var student;
var search;

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

function getStudentReport( student ) {
  var report = '<h2>Student: ' + student.name + '</h2>';
  report += '<p>Track: ' + student.track + '</p>';
  report += '<p>Points: ' + student.points + '</p>';
  report += '<p>Achievements: ' + student.achievements + '</p>';
  return report;
}

while (true) {
  message = ''; //set the message variable to '' so that everytime there is a search the output be cleared
  search = prompt('Search student records: type a name [Jody] (or type "quit" to end)');
  if (search === null || search.toLowerCase() === 'quit') {
    print('Good bye!'); 
    break;
  }
  for (var i = 0; i < students.length; i += 1) {
    student = students[i];
    if ( student.name.toLowerCase() === search.toLowerCase() ) {
      message += getStudentReport( student );  // rather than overwriting the message just add to it,
    }
  }
  if(!message){ message = '<p> no matching record</p>';} // test if message is still empty ( no matches )

print(message);
}