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

Zac Mackey
Zac Mackey
11,392 Points

My solution to the challenge, with comments.

Ok, so here's my solution to the challenge, complete with a list function to show all students, and a printed message if the student is not found.

If you have questions, feel free to ask. Or, if you have suggestions for improvements I'm all ears!

I tested it multiple ways to ensure information wasn't duplicated or displayed incorrectly and after about 2 hours on this thing I think it works great.

Setting the 'found' flag properly was my biggest issue. Placing the flag as false at the start of the while loop makes it so the flag will only change to true when a match is found.

/********
VARIABLES
********/

var html = '';
var search = '';
var quitSearch = 'Quit';
quitSearch = quitSearch.toLowerCase();
var found;


/*********
FUNCTIONS
*********/

// Function to print the HTML to the 'output' div ID.
function print(message) {
  var outputDiv = document.getElementById('output');
  outputDiv.innerHTML = message;
}

// Build HTML for all students list.
function createHTML(students) {
for (var i = 0; i < students.length; i += 1){
    student = students[i];
    html += '<h2>Student: ' + student.name + '</h2>';
    html += '<p>Track: ' + student.track + '</p>';
    html += '<p>Achievements: ' + student.achievements + '</p>';
    html += '<p>Points: ' + student.points + '</p>';
}
return html; // REMEMBER TO RETURN THE VALUE YOU JUST CREATED!
}

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


while (true) {
    found = false;
    search = prompt('Search for a student by name [Jody], use [List] for a full listing, or use [quit] to exit');
    if (search === null || search.toLowerCase() === quitSearch) break;
    else if (search.toLowerCase() === 'list' ){
        html = '';
        html = createHTML(students);
        print(html);
    } else {
        for (var i = 0; i < students.length; i += 1){
            student = students[i];
            if (student.name.toLowerCase() === search.toLowerCase() ) {
                html = getStudentReport( student );
                found = true;
            } 
            if (found === false) {
                html = 'Student not found!';
            }
        }
        print(html);        
    }
}

1 Answer

You should check for found outside of the for loop, otherwise if the student is found before reaching the end of the array of students, it will be later set to false again. So you only want to check if it is still false after going through the entire list of students.

Also, the createHTML and getStudentReport functions are almost exactly the same. You could get rid of the getStudentReport function and instead just pass createHTML an array with just one student in it if you only want to print the report for a single student.

Note that your code won't account for the scenario where there is more than one student with a matching name, since you're replacing the value of the html variable each time you find a matching student. If you just change it to add to the html variable, then it would contain the reports of multiple matching students at the end of the loop:

// shorthand for adding to the existing value of a variable
html += getStudentReport( student );
// OR the long way of writing it
html = html + getStudentReport( student );
// OR if using just the createHTML function with an array with a single value as I suggested above:
html += createHTML([student]);

Here was my solution:

var html = '';

function print(nodeID, message) {
  document.getElementById(nodeID).innerHTML = message;
}

function buildDefinitionList(obj) {
  var prop;
  var dListHTML = '<dl>';
  for (prop in obj) {
    dListHTML += '<dt>' + prop.charAt(0).toUpperCase() + prop.slice(1) + '</dt>';
    dListHTML += '<dd>' + obj[prop] + '</dd>';
  }
  dListHTML += '</dl>';
  return dListHTML;
}

function buildStudentList(list) {
  var i;
  var uListHTML = '<ul>';
  for (i = 0; i < list.length; i++) {
    uListHTML += '<li>' + buildDefinitionList(list[i]) + '</li>';
  }
  uListHTML += '</ul>';
  return uListHTML;
}

function getMatchingStudents(list) {
  var query;
  var i;
  var resultList;
  // keep looping until the user quits
  while(true) {
    // reset the result list
    resultList = [];
    // prompt and convert to lowercase
    query = prompt("Search student records: type a name [Iain] (or type 'quit' to end)");
    // check if they want to quit
    if (query === null || query.toLowerCase() === 'quit') {
      break;
    }
    // loop through students and check if the name contains the search query
    for (i = 0; i < list.length; i++) {
      if (list[i].name.toLowerCase().indexOf(query.toLowerCase()) > -1) {
        // if so, push to the result list
        resultList.push(list[i]);
      }
    }    
    // if there are results
    if (resultList.length > 0) {
      // build the list of matching students
      html = buildStudentList(resultList);
    } else {
      // otherwise print a friendly not found message
      html = '<p>Sorry, there are no students matching that name</p>';
    }    
    // print html to output div
    print('output', html);
  }
}

getMatchingStudents(students);